OLD | NEW |
1 library angular2.transformer; | 1 library angular2.src.transform; |
2 | 2 |
3 import 'package:analyzer/src/generated/ast.dart'; | 3 import 'package:analyzer/src/generated/ast.dart'; |
4 import 'package:analyzer/src/generated/element.dart'; | 4 import 'package:analyzer/src/generated/element.dart'; |
5 import 'package:analyzer/src/generated/java_core.dart'; | 5 import 'package:analyzer/src/generated/java_core.dart'; |
6 import 'package:barback/barback.dart' show AssetId, TransformLogger; | 6 import 'package:barback/barback.dart' show AssetId, TransformLogger; |
7 import 'package:dart_style/dart_style.dart'; | 7 import 'package:dart_style/dart_style.dart'; |
8 import 'package:path/path.dart' as path; | 8 import 'package:path/path.dart' as path; |
9 | 9 |
10 import 'annotation_processor.dart'; | 10 import 'annotation_processor.dart'; |
11 | 11 |
12 /// Base class that maintains codegen state. | 12 /// Base class that maintains codegen state. |
13 class Context { | 13 class Context { |
14 final TransformLogger _logger; | 14 final TransformLogger _logger; |
15 /// Maps libraries to the import prefixes we will use in the newly | 15 /// Maps libraries to the import prefixes we will use in the newly |
16 /// generated code. | 16 /// generated code. |
17 final Map<LibraryElement, String> _libraryPrefixes; | 17 final Map<LibraryElement, String> _libraryPrefixes; |
18 | 18 |
19 DirectiveRegistry _directiveRegistry; | 19 DirectiveRegistry _directiveRegistry; |
| 20 /// Generates [registerType] calls for all [register]ed [AnnotationMatch] |
| 21 /// objects. |
20 DirectiveRegistry get directiveRegistry => _directiveRegistry; | 22 DirectiveRegistry get directiveRegistry => _directiveRegistry; |
21 | 23 |
22 Context({TransformLogger logger}) | 24 Context({TransformLogger logger}) |
23 : _logger = logger, | 25 : _logger = logger, |
24 _libraryPrefixes = {} { | 26 _libraryPrefixes = {} { |
25 _directiveRegistry = new _DirectiveRegistryImpl(this); | 27 _directiveRegistry = new _DirectiveRegistryImpl(this); |
26 } | 28 } |
27 | 29 |
28 void error(String errorString) { | 30 void error(String errorString) { |
29 if (_logger != null) { | 31 if (_logger == null) throw new Error(errorString); |
30 _logger.error(errorString); | 32 _logger.error(errorString); |
31 } else { | |
32 throw new Error(errorString); | |
33 } | |
34 } | 33 } |
35 | 34 |
36 /// If elements in [lib] should be prefixed in our generated code, returns | 35 /// If elements in [lib] should be prefixed in our generated code, returns |
37 /// the appropriate prefix followed by a `.`. Future items from the same | 36 /// the appropriate prefix followed by a `.`. Future items from the same |
38 /// library will use the same prefix. | 37 /// library will use the same prefix. |
39 /// If [lib] does not need a prefix, returns the empty string. | 38 /// If [lib] does not need a prefix, returns the empty string. |
40 String _getPrefixDot(LibraryElement lib) { | 39 String _getPrefixDot(LibraryElement lib) { |
41 var prefix = lib != null && !lib.isInSdk | 40 if (lib == null || lib.isInSdk) return ''; |
42 ? _libraryPrefixes.putIfAbsent(lib, () => 'i${_libraryPrefixes.length}') | 41 var prefix = |
43 : null; | 42 _libraryPrefixes.putIfAbsent(lib, () => 'i${_libraryPrefixes.length}'); |
44 return prefix == null ? '' : '${prefix}.'; | 43 return '${prefix}.'; |
45 } | 44 } |
46 } | 45 } |
47 | 46 |
| 47 /// Object which [register]s [AnnotationMatch] objects for code generation. |
48 abstract class DirectiveRegistry { | 48 abstract class DirectiveRegistry { |
49 // Adds [entry] to the `registerType` calls which will be generated. | 49 // Adds [entry] to the `registerType` calls which will be generated. |
50 void register(AnnotationMatch entry); | 50 void register(AnnotationMatch entry); |
51 } | 51 } |
52 | 52 |
53 const _reflectorImport = | 53 const _reflectorImport = ''' |
54 'import \'package:angular2/src/reflection/reflection.dart\' ' | 54 import 'package:angular2/src/reflection/reflection.dart' show reflector; |
55 'show reflector;'; | 55 '''; |
56 | 56 |
57 /// Default implementation to map from [LibraryElement] to [AssetId]. This | 57 /// Default implementation to map from [LibraryElement] to [AssetId]. This |
58 /// assumes that [el.source] has a getter called [assetId]. | 58 /// assumes that [el.source] has a getter called [assetId]. |
59 AssetId _assetIdFromLibraryElement(LibraryElement el) { | 59 AssetId _assetIdFromLibraryElement(LibraryElement el) { |
60 return (el.source as dynamic).assetId; | 60 return (el.source as dynamic).assetId; |
61 } | 61 } |
62 | 62 |
63 String codegenEntryPoint(Context context, | 63 String codegenEntryPoint(Context context, |
64 {LibraryElement entryPoint, AssetId newEntryPoint}) { | 64 {LibraryElement entryPoint, AssetId newEntryPoint}) { |
65 // This must be called prior to [codegenImports] or the entry point | 65 // This must be called prior to [codegenImports] or the entry point |
(...skipping 29 matching lines...) Expand all Loading... |
95 } else if (path.url.split(libraryId.path)[0] == | 95 } else if (path.url.split(libraryId.path)[0] == |
96 path.url.split(entryPoint.path)[0]) { | 96 path.url.split(entryPoint.path)[0]) { |
97 var relativePath = | 97 var relativePath = |
98 path.relative(libraryId.path, from: path.dirname(entryPoint.path)); | 98 path.relative(libraryId.path, from: path.dirname(entryPoint.path)); |
99 return "import '${relativePath}'"; | 99 return "import '${relativePath}'"; |
100 } else { | 100 } else { |
101 context._error("Can't import `${libraryId}` from `${entryPoint}`"); | 101 context._error("Can't import `${libraryId}` from `${entryPoint}`"); |
102 } | 102 } |
103 } | 103 } |
104 | 104 |
| 105 // TODO(https://github.com/kegluneq/angular/issues/4): Remove calls to |
| 106 // Element#node. |
105 class _DirectiveRegistryImpl implements DirectiveRegistry { | 107 class _DirectiveRegistryImpl implements DirectiveRegistry { |
106 final Context _context; | 108 final Context _context; |
107 final StringBuffer _buffer = new StringBuffer(); | 109 final StringBuffer _buffer = new StringBuffer(); |
108 | 110 |
109 _DirectiveRegistryImpl(this._context); | 111 _DirectiveRegistryImpl(this._context); |
110 | 112 |
111 @override | 113 @override |
112 String toString() { | 114 String toString() { |
113 return _buffer.isEmpty ? '' : 'reflector${_buffer};'; | 115 return _buffer.isEmpty ? '' : 'reflector${_buffer};'; |
114 } | 116 } |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 | 192 |
191 /// Visitor providing common methods for concrete implementations. | 193 /// Visitor providing common methods for concrete implementations. |
192 abstract class _TransformVisitor extends ToSourceVisitor { | 194 abstract class _TransformVisitor extends ToSourceVisitor { |
193 final Context _context; | 195 final Context _context; |
194 final PrintWriter _writer; | 196 final PrintWriter _writer; |
195 | 197 |
196 _TransformVisitor(PrintWriter writer, this._context) | 198 _TransformVisitor(PrintWriter writer, this._context) |
197 : this._writer = writer, | 199 : this._writer = writer, |
198 super(writer); | 200 super(writer); |
199 | 201 |
200 /// Safely visit the given node. | 202 /// Safely visit [node]. |
201 /// @param node the node to be visited | |
202 void _visitNode(AstNode node) { | 203 void _visitNode(AstNode node) { |
203 if (node != null) { | 204 if (node != null) { |
204 node.accept(this); | 205 node.accept(this); |
205 } | 206 } |
206 } | 207 } |
207 | 208 |
208 /** | 209 /// If [node] is null does nothing. Otherwise, prints [prefix], then |
209 * Safely visit the given node, printing the prefix before the node if it is n
on-`null`. | 210 /// visits [node]. |
210 * | |
211 * @param prefix the prefix to be printed if there is a node to visit | |
212 * @param node the node to be visited | |
213 */ | |
214 void _visitNodeWithPrefix(String prefix, AstNode node) { | 211 void _visitNodeWithPrefix(String prefix, AstNode node) { |
215 if (node != null) { | 212 if (node != null) { |
216 _writer.print(prefix); | 213 _writer.print(prefix); |
217 node.accept(this); | 214 node.accept(this); |
218 } | 215 } |
219 } | 216 } |
220 | 217 |
221 /** | 218 /// If [node] is null does nothing. Otherwise, visits [node], then prints |
222 * Safely visit the given node, printing the suffix after the node if it is no
n-`null`. | 219 /// [suffix]. |
223 * | |
224 * @param suffix the suffix to be printed if there is a node to visit | |
225 * @param node the node to be visited | |
226 */ | |
227 void _visitNodeWithSuffix(AstNode node, String suffix) { | 220 void _visitNodeWithSuffix(AstNode node, String suffix) { |
228 if (node != null) { | 221 if (node != null) { |
229 node.accept(this); | 222 node.accept(this); |
230 _writer.print(suffix); | 223 _writer.print(suffix); |
231 } | 224 } |
232 } | 225 } |
233 | 226 |
234 @override | 227 @override |
235 Object visitSimpleIdentifier(SimpleIdentifier node) { | 228 Object visitSimpleIdentifier(SimpleIdentifier node) { |
236 // Make sure the identifier is prefixed if necessary. | 229 // Make sure the identifier is prefixed if necessary. |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
381 @override | 374 @override |
382 Object visitAnnotation(Annotation node) { | 375 Object visitAnnotation(Annotation node) { |
383 _writer.print('const '); | 376 _writer.print('const '); |
384 _visitNode(node.name); | 377 _visitNode(node.name); |
385 // TODO(tjblasi): Do we need to handle named constructors for annotations? | 378 // TODO(tjblasi): Do we need to handle named constructors for annotations? |
386 // _visitNodeWithPrefix(".", node.constructorName); | 379 // _visitNodeWithPrefix(".", node.constructorName); |
387 _visitNode(node.arguments); | 380 _visitNode(node.arguments); |
388 return null; | 381 return null; |
389 } | 382 } |
390 } | 383 } |
OLD | NEW |