-
Notifications
You must be signed in to change notification settings - Fork 0
/
allocator.dart
96 lines (79 loc) · 2.91 KB
/
allocator.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'specs/directive.dart';
import 'specs/reference.dart';
/// Collects references and automatically allocates prefixes and imports.
///
/// `Allocator` takes out the manual work of deciding whether a symbol will
/// clash with other imports in your generated code, or what imports are needed
/// to resolve all symbols in your generated code.
abstract class Allocator {
/// An allocator that does not prefix symbols nor collects imports.
static const Allocator none = _NullAllocator();
/// Creates a new default allocator that applies no prefixing.
factory Allocator() = _Allocator;
/// Creates a new allocator that applies naive prefixing to avoid conflicts.
///
/// This implementation is not optimized for any particular code generation
/// style and instead takes a conservative approach of prefixing _every_
/// import except references to `dart:core` (which are considered always
/// imported).
///
/// The prefixes are not guaranteed to be stable and cannot be expected to
/// have any particular value.
factory Allocator.simplePrefixing() = _PrefixedAllocator;
/// Returns a reference string given a [reference] object.
///
/// For example, a no-op implementation:
/// ```dart
/// allocate(const Reference('List', 'dart:core')); // Returns 'List'.
/// ```
///
/// Where-as an implementation that prefixes imports might output:
/// ```dart
/// allocate(const Reference('Foo', 'package:foo')); // Returns '_i1.Foo'.
/// ```
String allocate(Reference reference);
/// All imports that have so far been added implicitly via [allocate].
Iterable<Directive> get imports;
}
class _Allocator implements Allocator {
final _imports = <String>{};
@override
String allocate(Reference reference) {
final url = reference.url;
if (url != null) {
_imports.add(url);
}
return reference.symbol!;
}
@override
Iterable<Directive> get imports => _imports.map(Directive.import);
}
class _NullAllocator implements Allocator {
const _NullAllocator();
@override
String allocate(Reference reference) => reference.symbol!;
@override
Iterable<Directive> get imports => const [];
}
class _PrefixedAllocator implements Allocator {
static const _doNotPrefix = ['dart:core'];
final _imports = <String, int>{};
var _keys = 1;
@override
String allocate(Reference reference) {
final symbol = reference.symbol;
final url = reference.url;
if (url == null || _doNotPrefix.contains(url)) {
return symbol!;
}
return '_i${_imports.putIfAbsent(url, _nextKey)}.$symbol';
}
int _nextKey() => _keys++;
@override
Iterable<Directive> get imports => _imports.keys.map(
(u) => Directive.import(u, as: '_i${_imports[u]}'),
);
}