diff --git a/modules/angular2/pubspec.yaml b/modules/angular2/pubspec.yaml index 83ed101777..135a6b5127 100644 --- a/modules/angular2/pubspec.yaml +++ b/modules/angular2/pubspec.yaml @@ -14,6 +14,7 @@ dependencies: code_transformers: '^0.2.5' dart_style: '^0.1.3' html: '^0.12.0' + source_span: '^1.0.0' stack_trace: '^1.1.1' transformers: - angular2 diff --git a/modules/angular2/src/dom/html_adapter.dart b/modules/angular2/src/dom/html_adapter.dart index 2576f58913..a881d35c50 100644 --- a/modules/angular2/src/dom/html_adapter.dart +++ b/modules/angular2/src/dom/html_adapter.dart @@ -16,6 +16,36 @@ class Html5LibDomAdapter implements DomAdapter { 'tabindex': 'tabIndex', }; + @override + getGlobalEventTarget(String target) { + throw 'not implemented'; + } + + @override + getTitle() { + throw 'not implemented'; + } + + @override + setTitle(String newTitle) { + throw 'not implemented'; + } + + @override + String getEventKey(event) { + throw 'not implemented'; + } + + @override + void replaceChild(el, newNode, oldNode) { + throw 'not implemented'; + } + + @override + dynamic getBoundingClientRect(el) { + throw 'not implemented'; + } + Element parse(String templateHtml) => parser.parse(templateHtml).firstChild; query(selector) { throw 'not implemented'; @@ -54,7 +84,7 @@ class Html5LibDomAdapter implements DomAdapter { String type(node) { throw 'not implemented'; } - content(TemplateElement node) { + content(node) { throw 'not implemented'; } diff --git a/modules/angular2/src/transform/common/logging.dart b/modules/angular2/src/transform/common/logging.dart index db8c53f70c..6eae36978a 100644 --- a/modules/angular2/src/transform/common/logging.dart +++ b/modules/angular2/src/transform/common/logging.dart @@ -1,7 +1,9 @@ library angular2.transform.common.logging; +import 'dart:async'; import 'package:barback/barback.dart'; import 'package:code_transformers/messages/build_logger.dart'; +import 'package:source_span/source_span.dart'; BuildLogger _logger; @@ -24,6 +26,11 @@ BuildLogger get logger { } class PrintLogger implements BuildLogger { + @override + final String detailsUri = ''; + @override + final bool convertErrorsToWarnings = false; + void _printWithPrefix(prefix, msg) => print('$prefix: $msg'); void info(msg, {AssetId asset, SourceSpan span}) => _printWithPrefix('INFO', msg); @@ -43,7 +50,7 @@ class PrintLoggerError extends Error { final AssetId asset; final SourceSpan span; - PrintLoggerError(message, asset, span); + PrintLoggerError(this.message, this.asset, this.span); @override String toString() { diff --git a/modules/angular2/src/transform/common/names.dart b/modules/angular2/src/transform/common/names.dart index 471d607e58..8900d10137 100644 --- a/modules/angular2/src/transform/common/names.dart +++ b/modules/angular2/src/transform/common/names.dart @@ -3,6 +3,7 @@ library angular2.transform.common.names; const SETUP_METHOD_NAME = 'initReflector'; const REFLECTOR_VAR_NAME = 'reflector'; const DEPS_EXTENSION = '.ng_deps.dart'; +const REFLECTION_CAPABILITIES_NAME = 'ReflectionCapabilities'; const REGISTER_TYPE_METHOD_NAME = 'registerType'; const REGISTER_GETTERS_METHOD_NAME = 'registerGetters'; const REGISTER_SETTERS_METHOD_NAME = 'registerSetters'; diff --git a/modules/angular2/src/transform/common/options_reader.dart b/modules/angular2/src/transform/common/options_reader.dart index 74c479b0d6..847ffccdca 100644 --- a/modules/angular2/src/transform/common/options_reader.dart +++ b/modules/angular2/src/transform/common/options_reader.dart @@ -1,4 +1,4 @@ -library angular2.transform.common.options; +library angular2.transform.common.options_reader; import 'package:barback/barback.dart'; import 'options.dart'; diff --git a/modules/angular2/src/transform/common/parser.dart b/modules/angular2/src/transform/common/parser.dart index 20c0aebd39..ecfd70547a 100644 --- a/modules/angular2/src/transform/common/parser.dart +++ b/modules/angular2/src/transform/common/parser.dart @@ -43,7 +43,7 @@ class Parser { Future> _recurse(AssetId id, [List allDeps, Set seen]) async { if (seen == null) seen = new Set(); - if (seen.contains(id)) return; + if (seen.contains(id)) return null; seen.add(id); if (allDeps == null) allDeps = []; @@ -75,7 +75,6 @@ class NgDeps { class _ParseNgDepsVisitor extends Object with RecursiveAstVisitor { NgDeps ngDeps = null; - _RegisteredTypeBuilder current = null; @override Object visitImportDirective(ImportDirective node) { diff --git a/modules/angular2/src/transform/common/visitor_mixin.dart b/modules/angular2/src/transform/common/visitor_mixin.dart deleted file mode 100644 index 8cfde3044e..0000000000 --- a/modules/angular2/src/transform/common/visitor_mixin.dart +++ /dev/null @@ -1,111 +0,0 @@ -library angular2.transform.common; - -import 'package:analyzer/analyzer.dart'; -import 'package:analyzer/src/generated/java_core.dart'; -import 'package:analyzer/src/generated/scanner.dart'; - -/// Visitor providing common methods for concrete implementations. -class VisitorMixin { - PrintWriter writer; - - /** - * Visit the given function body, printing the prefix before if given body is not empty. - * - * @param prefix the prefix to be printed if there is a node to visit - * @param body the function body to be visited - */ - void visitFunctionWithPrefix(String prefix, FunctionBody body) { - if (body is! EmptyFunctionBody) { - writer.print(prefix); - } - visitNode(body); - } - - /// Safely visit [node]. - void visitNode(AstNode node) { - if (node != null) { - node.accept(this); - } - } - - /// Print a list of [nodes] without any separation. - void visitNodeList(NodeList nodes) { - visitNodeListWithSeparator(nodes, ""); - } - - /// Print a list of [nodes], separated by the given [separator]. - void visitNodeListWithSeparator(NodeList nodes, String separator) { - if (nodes != null) { - int size = nodes.length; - for (int i = 0; i < size; i++) { - if (i > 0) { - writer.print(separator); - } - nodes[i].accept(this); - } - } - } - - /// Print a list of [nodes], separated by the given [separator] and - /// preceded by the given [prefix]. - void visitNodeListWithSeparatorAndPrefix( - String prefix, NodeList nodes, String separator) { - if (nodes != null) { - int size = nodes.length; - if (size > 0) { - writer.print(prefix); - for (int i = 0; i < size; i++) { - if (i > 0) { - writer.print(separator); - } - nodes[i].accept(this); - } - } - } - } - - /// Print a list of [nodes], separated by the given [separator] and - /// succeeded by the given [suffix]. - void visitNodeListWithSeparatorAndSuffix( - NodeList nodes, String separator, String suffix) { - if (nodes != null) { - int size = nodes.length; - if (size > 0) { - for (int i = 0; i < size; i++) { - if (i > 0) { - writer.print(separator); - } - nodes[i].accept(this); - } - writer.print(suffix); - } - } - } - - /// If [node] is null does nothing. Otherwise, prints [prefix], then - /// visits [node]. - void visitNodeWithPrefix(String prefix, AstNode node) { - if (node != null) { - writer.print(prefix); - node.accept(this); - } - } - - /// If [node] is null does nothing. Otherwise, visits [node], then prints - /// [suffix]. - void visitNodeWithSuffix(AstNode node, String suffix) { - if (node != null) { - node.accept(this); - writer.print(suffix); - } - } - - /// Safely visit [node], printing [suffix] after the node if it is - /// non-`null`. - void visitTokenWithSuffix(Token token, String suffix) { - if (token != null) { - writer.print(token.lexeme); - writer.print(suffix); - } - } -} diff --git a/modules/angular2/src/transform/di_transformer.dart b/modules/angular2/src/transform/di_transformer.dart index 7991136dcf..13d3bd1210 100644 --- a/modules/angular2/src/transform/di_transformer.dart +++ b/modules/angular2/src/transform/di_transformer.dart @@ -5,10 +5,8 @@ import 'package:dart_style/dart_style.dart'; import 'directive_linker/transformer.dart'; import 'directive_processor/transformer.dart'; -import 'bind_generator/transformer.dart'; import 'reflection_remover/transformer.dart'; import 'common/formatter.dart' as formatter; -import 'common/names.dart'; import 'common/options.dart'; import 'common/options_reader.dart'; diff --git a/modules/angular2/src/transform/directive_linker/linker.dart b/modules/angular2/src/transform/directive_linker/linker.dart index 2e458aab9c..cccfdbb47d 100644 --- a/modules/angular2/src/transform/directive_linker/linker.dart +++ b/modules/angular2/src/transform/directive_linker/linker.dart @@ -17,9 +17,10 @@ Future linkNgDeps(AssetReader reader, AssetId entryPoint) async { if (ngDeps == null) return null; if (ngDeps.imports.isEmpty) return ngDeps.code; - var allDeps = ngDeps.imports.toList()..addAll(ngDeps.exports); - var depList = await _processNgImports( - reader, entryPoint, allDeps.map((node) => node.uri.stringValue)); + var depUris = [] + ..addAll(ngDeps.imports.map((i) => i.uri.stringValue)) + ..addAll(ngDeps.exports.map((i) => i.uri.stringValue)); + var depList = await _processNgImports(reader, entryPoint, depUris); if (depList.isEmpty) return ngDeps.code; diff --git a/modules/angular2/src/transform/directive_linker/transformer.dart b/modules/angular2/src/transform/directive_linker/transformer.dart index 1df022ddba..c596aee31f 100644 --- a/modules/angular2/src/transform/directive_linker/transformer.dart +++ b/modules/angular2/src/transform/directive_linker/transformer.dart @@ -6,7 +6,6 @@ import 'package:angular2/src/transform/common/asset_reader.dart'; import 'package:angular2/src/transform/common/formatter.dart'; import 'package:angular2/src/transform/common/logging.dart' as log; import 'package:angular2/src/transform/common/names.dart'; -import 'package:angular2/src/transform/common/options.dart'; import 'package:barback/barback.dart'; import 'linker.dart'; diff --git a/modules/angular2/src/transform/directive_processor/rewriter.dart b/modules/angular2/src/transform/directive_processor/rewriter.dart index 0a4ab9de9c..50eae3c9bd 100644 --- a/modules/angular2/src/transform/directive_processor/rewriter.dart +++ b/modules/angular2/src/transform/directive_processor/rewriter.dart @@ -4,7 +4,6 @@ import 'package:analyzer/analyzer.dart'; import 'package:analyzer/src/generated/java_core.dart'; import 'package:angular2/src/transform/common/logging.dart'; import 'package:angular2/src/transform/common/names.dart'; -import 'package:angular2/src/transform/common/visitor_mixin.dart'; import 'package:path/path.dart' as path; import 'visitors.dart'; @@ -27,8 +26,7 @@ String createNgDeps(String code, String path) { /// Visitor responsible for processing [CompilationUnit] and creating an /// associated .ng_deps.dart file. -class CreateNgDepsVisitor extends Object - with SimpleAstVisitor, VisitorMixin { +class CreateNgDepsVisitor extends Object with SimpleAstVisitor { final PrintWriter writer; final _Tester _tester = const _Tester(); bool _foundNgDirectives = false; @@ -48,11 +46,21 @@ class CreateNgDepsVisitor extends Object _paramsVisitor = new ParameterTransformVisitor(writer), _metaVisitor = new AnnotationsTransformVisitor(writer); + void _visitNodeListWithSeparator(NodeList list, String separator) { + if (list == null) return; + for (var i = 0, iLen = list.length; i < iLen; ++i) { + if (i != 0) { + writer.print(separator); + } + list[i].accept(this); + } + } + @override - void visitCompilationUnit(CompilationUnit node) { - visitNodeListWithSeparator(node.directives, " "); + Object visitCompilationUnit(CompilationUnit node) { + _visitNodeListWithSeparator(node.directives, " "); _openFunctionWrapper(); - visitNodeListWithSeparator(node.declarations, " "); + _visitNodeListWithSeparator(node.declarations, " "); _closeFunctionWrapper(); return null; } @@ -139,7 +147,7 @@ class CreateNgDepsVisitor extends Object _foundNgDirectives = true; } writer.print('..registerType('); - visitNode(node.name); + node.name.accept(this); writer.print(''', {'factory': '''); if (ctor == null) { _generateEmptyFactory(node.name.toString()); @@ -155,9 +163,8 @@ class CreateNgDepsVisitor extends Object writer.print(''', 'annotations': '''); node.accept(_metaVisitor); writer.print('})'); - - return null; } + return null; } Object _nodeToSource(AstNode node) { diff --git a/modules/angular2/src/transform/directive_processor/visitors.dart b/modules/angular2/src/transform/directive_processor/visitors.dart index d4de36e853..808fdbe5b0 100644 --- a/modules/angular2/src/transform/directive_processor/visitors.dart +++ b/modules/angular2/src/transform/directive_processor/visitors.dart @@ -3,10 +3,9 @@ library angular2.transform.directive_processor; import 'package:analyzer/analyzer.dart'; import 'package:analyzer/src/generated/java_core.dart'; import 'package:angular2/src/transform/common/logging.dart'; -import 'package:angular2/src/transform/common/visitor_mixin.dart'; -/// SourceVisitor designed to accept [ConstructorDeclaration] nodes. -class _CtorTransformVisitor extends ToSourceVisitor with VisitorMixin { +/// `ToSourceVisitor` designed to accept [ConstructorDeclaration] nodes. +class _CtorTransformVisitor extends ToSourceVisitor { bool _withParameterAnnotations = true; bool _withParameterTypes = true; bool _withParameterNames = true; @@ -20,25 +19,50 @@ class _CtorTransformVisitor extends ToSourceVisitor with VisitorMixin { : this.writer = writer, super(writer); + void _visitNodeWithPrefix(String prefix, AstNode node) { + if (node != null) { + writer.print(prefix); + node.accept(this); + } + } + + void _visitNodeWithSuffix(AstNode node, String suffix) { + if (node != null) { + node.accept(this); + writer.print(suffix); + } + } + + void _visitNode(AstNode node) { + if (node != null) { + node.accept(this); + } + } + /// If [_withParameterTypes] is true, this method outputs [node]'s type. If /// [_withParameterNames] is true, this method outputs [node]'s identifier. Object _visitNormalFormalParameter( NodeList metadata, TypeName type, SimpleIdentifier name) { if (_withParameterAnnotations && metadata != null) { assert(_withParameterTypes); - var suffix = type != null ? ', ' : ''; - visitNodeListWithSeparatorAndSuffix(metadata, ', ', suffix); + for (var i = 0, iLen = metadata.length; i < iLen; ++i) { + if (i != 0) { + writer.print(', '); + } + metadata[i].accept(this); + } + writer.print(type != null && metadata.isNotEmpty ? ', ' : ''); } var needCompileTimeConstants = !_withParameterNames; if (_withParameterTypes && type != null) { - visitNodeWithSuffix(type.name, ' '); + _visitNodeWithSuffix(type.name, ' '); if (!needCompileTimeConstants) { // Types with arguments are not compile-time constants. - visitNodeWithSuffix(type.typeArguments, ' '); + _visitNodeWithSuffix(type.typeArguments, ' '); } } if (_withParameterNames) { - visitNode(name); + _visitNode(name); } return null; } @@ -87,7 +111,7 @@ class _CtorTransformVisitor extends ToSourceVisitor with VisitorMixin { @override Object visitDefaultFormalParameter(DefaultFormalParameter node) { - visitNode(node.parameter); + _visitNode(node.parameter); // Ignore the declared default value. return null; } @@ -112,9 +136,9 @@ class _CtorTransformVisitor extends ToSourceVisitor with VisitorMixin { Object visitAnnotation(Annotation node) { var prefix = node.arguments != null && node.arguments.length > 0 ? 'const ' : ''; - visitNodeWithPrefix(prefix, node.name); - visitNodeWithPrefix(".", node.constructorName); - visitNode(node.arguments); + _visitNodeWithPrefix(prefix, node.name); + _visitNodeWithPrefix(".", node.constructorName); + _visitNode(node.arguments); return null; } } @@ -132,7 +156,7 @@ class ParameterTransformVisitor extends _CtorTransformVisitor { Object visitConstructorDeclaration(ConstructorDeclaration node) { _buildFieldMap(node); writer.print('const ['); - visitNode(node.parameters); + _visitNode(node.parameters); writer.print(']'); return null; } @@ -140,8 +164,7 @@ class ParameterTransformVisitor extends _CtorTransformVisitor { @override Object visitFormalParameterList(FormalParameterList node) { NodeList parameters = node.parameters; - int size = parameters.length; - for (int i = 0; i < size; i++) { + for (int i = 0, iLen = parameters.length; i < iLen; i++) { if (i > 0) { writer.print(', '); } @@ -166,20 +189,20 @@ class FactoryTransformVisitor extends _CtorTransformVisitor { _buildFieldMap(node); _withParameterNames = true; _withParameterTypes = true; - visitNode(node.parameters); + _visitNode(node.parameters); writer.print(' => new '); - visitNode(node.returnType); - visitNodeWithPrefix(".", node.name); + _visitNode(node.returnType); + _visitNodeWithPrefix(".", node.name); _withParameterTypes = false; - visitNode(node.parameters); + _visitNode(node.parameters); return null; } } /// ToSourceVisitor designed to print a [ClassDeclaration] node as a /// 'annotations' value for Angular2's [registerType] calls. -class AnnotationsTransformVisitor extends ToSourceVisitor with VisitorMixin { +class AnnotationsTransformVisitor extends ToSourceVisitor { final PrintWriter writer; AnnotationsTransformVisitor(PrintWriter writer) : this.writer = writer, @@ -202,9 +225,16 @@ class AnnotationsTransformVisitor extends ToSourceVisitor with VisitorMixin { @override Object visitAnnotation(Annotation node) { writer.print('const '); - visitNode(node.name); - visitNodeWithPrefix(".", node.constructorName); - visitNode(node.arguments); + if (node.name != null) { + node.name.accept(this); + } + if (node.constructorName != null) { + writer.print('.'); + node.constructorName.accept(this); + } + if (node.arguments != null) { + node.arguments.accept(this); + } return null; } } diff --git a/modules/angular2/src/transform/in_progress/annotation_processor.dart b/modules/angular2/src/transform/in_progress/annotation_processor.dart deleted file mode 100644 index 618a2f4e07..0000000000 --- a/modules/angular2/src/transform/in_progress/annotation_processor.dart +++ /dev/null @@ -1,71 +0,0 @@ -library angular2.transform; - -import 'dart:collection' show Queue; -import 'package:analyzer/src/generated/ast.dart'; -import 'package:analyzer/src/generated/element.dart'; - -import 'resolvers.dart'; - -/// Provides a mechanism for checking an element for the provided -/// [_annotationClass] and reporting the resulting (element, annotation) pairs. -class AnnotationMatcher { - /// Queue for annotations. - final matchQueue = new Queue(); - /// All the annotations we have seen for each element - final _seenAnnotations = new Map>(); - - /// The classes we are searching for to populate [matchQueue]. - final Set _annotationClasses; - - AnnotationMatcher(this._annotationClasses); - - /// Records all [_annotationClass] annotations and the [element]s they apply to. - /// Returns - List processAnnotations(ClassElement element) { - // Finding the node corresponding to [element] can be very expensive. - ClassDeclaration cachedNode = null; - - var result = []; - element.metadata.where((ElementAnnotation meta) { - // TODO(tjblasi): Make this recognize non-ConstructorElement annotations. - return meta.element is ConstructorElement && - _isAnnotationMatch(meta.element.returnType); - }).where((ElementAnnotation meta) { - // Only process ([element], [meta]) combinations we haven't seen previously. - return !_seenAnnotations - .putIfAbsent(element, () => new Set()) - .contains(meta); - }).forEach((ElementAnnotation meta) { - if (cachedNode == null) { - cachedNode = element.node; - } - - var match = new AnnotationMatch(cachedNode, meta); - _seenAnnotations[element].add(meta); - matchQueue.addLast(match); - result.add(match); - }); - return result; - } - - /// Whether [type], its superclass, or one of its interfaces matches [_annotationClass]. - bool _isAnnotationMatch(InterfaceType type) { - return _annotationClasses.any((el) => isAnnotationMatch(type, el)); - } -} - -/// [ClassElement] / [ElementAnnotation] pair. -class AnnotationMatch { - /// The resolved element corresponding to [node]. - final ClassElement element; - - /// The Ast node corresponding to the class definition. - final ClassDeclaration node; - - /// The resolved element for the matched annotation. - final ElementAnnotation annotation; - - AnnotationMatch(ClassDeclaration node, this.annotation) - : node = node, - element = node.element; -} diff --git a/modules/angular2/src/transform/in_progress/codegen.dart b/modules/angular2/src/transform/in_progress/codegen.dart deleted file mode 100644 index 5decc6234f..0000000000 --- a/modules/angular2/src/transform/in_progress/codegen.dart +++ /dev/null @@ -1,518 +0,0 @@ -library angular2.transform; - -import 'package:analyzer/src/generated/ast.dart'; -import 'package:analyzer/src/generated/element.dart'; -import 'package:analyzer/src/generated/java_core.dart'; -import 'package:barback/barback.dart' show AssetId, TransformLogger; -import 'package:dart_style/dart_style.dart'; -import 'package:path/path.dart' as path; - -import 'annotation_processor.dart'; -import 'common/logging.dart'; - -/// Base class that maintains codegen state. -class Context { - /// Maps libraries to the import prefixes we will use in the newly - /// generated code. - final Map _libraryPrefixes = {}; - - /// Whether to generate constructor stubs for classes annotated - /// with [Component], [Decorator], [View], and [Inject] (and subtypes). - bool generateCtorStubs = true; - - /// Whether to generate setter stubs for classes annotated with - /// [Directive] subtypes. These setters depend on the value passed to the - /// annotation's `properties` value. - bool generateSetterStubs = true; - - DirectiveRegistry _directiveRegistry; - /// Generates [registerType] calls for all [register]ed [AnnotationMatch] - /// objects. - DirectiveRegistry get directiveRegistry => _directiveRegistry; - - Context() { - _directiveRegistry = new _DirectiveRegistryImpl(this); - } - - /// If elements in [lib] should be prefixed in our generated code, returns - /// the appropriate prefix followed by a `.`. Future items from the same - /// library will use the same prefix. - /// If [lib] does not need a prefix, returns the empty string. - String _getPrefixDot(LibraryElement lib) { - if (lib == null || lib.isInSdk) return ''; - var prefix = - _libraryPrefixes.putIfAbsent(lib, () => 'i${_libraryPrefixes.length}'); - return '${prefix}.'; - } -} - -/// Object which [register]s [AnnotationMatch] objects for code generation. -abstract class DirectiveRegistry { - // Adds [entry] to the `registerType` calls which will be generated. - void register(AnnotationMatch entry); -} - -const setupReflectionMethodName = 'setupReflection'; - -const _libraryDeclaration = ''' -library angular2.transform.generated; -'''; - -const _reflectorImport = ''' -import 'package:angular2/src/reflection/reflection.dart' show reflector; -'''; - -/// Default implementation to map from [LibraryElement] to [AssetId]. This -/// assumes that [el.source] has a getter called [assetId]. -AssetId _assetIdFromLibraryElement(LibraryElement el) { - return (el.source as dynamic).assetId; -} - -String codegenEntryPoint(Context context, {AssetId newEntryPoint}) { - if (newEntryPoint == null) { - throw new ArgumentError.notNull('newEntryPoint'); - } - // TODO(kegluneq): copyright declaration - var outBuffer = new StringBuffer() - ..write(_libraryDeclaration) - ..write(_reflectorImport); - _codegenImports(context, newEntryPoint, outBuffer); - outBuffer - .write('${setupReflectionMethodName}() {${context.directiveRegistry}}'); - - return new DartFormatter().format(outBuffer.toString()); -} - -void _codegenImports( - Context context, AssetId newEntryPoint, StringBuffer buffer) { - context._libraryPrefixes.forEach((lib, prefix) { - buffer - ..write(_codegenImport( - context, _assetIdFromLibraryElement(lib), newEntryPoint)) - ..writeln('as ${prefix};'); - }); -} - -String _codegenImport(Context context, AssetId libraryId, AssetId entryPoint) { - if (libraryId.path.startsWith('lib/')) { - var packagePath = libraryId.path.replaceFirst('lib/', ''); - return "import 'package:${libraryId.package}/${packagePath}'"; - } else if (libraryId.package != entryPoint.package) { - logger.error("Can't import `${libraryId}` from `${entryPoint}`"); - } else if (path.url.split(libraryId.path)[0] == - path.url.split(entryPoint.path)[0]) { - var relativePath = - path.relative(libraryId.path, from: path.dirname(entryPoint.path)); - return "import '${relativePath}'"; - } else { - logger.error("Can't import `${libraryId}` from `${entryPoint}`"); - } -} - -// TODO(https://github.com/kegluneq/angular/issues/4): Remove calls to -// Element#node. -class _DirectiveRegistryImpl implements DirectiveRegistry { - final Context _context; - final PrintWriter _writer; - final Set _seen = new Set(); - final _AnnotationsTransformVisitor _annotationsVisitor; - final _BindTransformVisitor _bindVisitor; - final _FactoryTransformVisitor _factoryVisitor; - final _ParameterTransformVisitor _parametersVisitor; - - _DirectiveRegistryImpl._internal(Context context, PrintWriter writer) - : _writer = writer, - _context = context, - _annotationsVisitor = new _AnnotationsTransformVisitor(writer, context), - _bindVisitor = new _BindTransformVisitor(writer, context), - _factoryVisitor = new _FactoryTransformVisitor(writer, context), - _parametersVisitor = new _ParameterTransformVisitor(writer, context); - - factory _DirectiveRegistryImpl(Context context) { - return new _DirectiveRegistryImpl._internal( - context, new PrintStringWriter()); - } - - @override - String toString() { - return _seen.isEmpty ? '' : 'reflector${_writer};'; - } - - // Adds [entry] to the `registerType` calls which will be generated. - void register(AnnotationMatch entry) { - if (_seen.contains(entry.node)) return; - _seen.add(entry.node); - - if (_context.generateCtorStubs) { - _generateCtorStubs(entry); - } - if (_context.generateSetterStubs) { - _generateSetterStubs(entry); - } - } - - void _generateSetterStubs(AnnotationMatch entry) { - // TODO(kegluneq): Remove these requirements for setter stub generation. - if (entry.element is! ClassElement) { - logger.error('Directives can only be applied to classes.'); - return; - } - if (entry.node is! ClassDeclaration) { - logger.error('Unsupported annotation type for ctor stub generation. ' - 'Only class declarations are supported as Directives.'); - return; - } - - entry.node.accept(_bindVisitor); - } - - void _generateCtorStubs(AnnotationMatch entry) { - var element = entry.element; - var annotation = entry.annotation; - - // TODO(kegluneq): Remove these requirements for ctor stub generation. - if (annotation.element is! ConstructorElement) { - logger.error('Unsupported annotation type for ctor stub generation. ' - 'Only constructors are supported as Directives.'); - return; - } - if (element is! ClassElement) { - logger.error('Directives can only be applied to classes.'); - return; - } - if (entry.node is! ClassDeclaration) { - logger.error('Unsupported annotation type for ctor stub generation. ' - 'Only class declarations are supported as Directives.'); - return; - } - var ctor = element.unnamedConstructor; - if (ctor == null) { - logger.error('No unnamed constructor found for ${element.name}'); - return; - } - var ctorNode = ctor.node; - - _writer.print('..registerType('); - _codegenClassTypeString(element); - _writer.print(', {"factory": '); - _codegenClassTypeString(element); - _writer.print('.ngFactory'); - _writer.print(', "parameters": '); - _codegenClassTypeString(element); - _writer.print('.ngParameters'); - _writer.print(', "annotations": '); - _codegenClassTypeString(element); - _writer.print('.ngAnnotations'); - _writer.print('})'); - } - - void _codegenClassTypeString(ClassElement el) { - _writer.print('${_context._getPrefixDot(el.library)}${el.name}'); - } - - /// Creates the 'annotations' property for the Angular2 [registerType] call - /// for [node]. - void _codegenAnnotationsProp(ClassDeclaration node) { - node.accept(_annotationsVisitor); - } - - /// Creates the 'factory' property for the Angular2 [registerType] call - /// for [node]. [element] is necessary if [node] is null. - void _codegenFactoryProp(ConstructorDeclaration node, ClassElement element) { - if (node == null) { - // This occurs when the class does not declare a constructor. - var prefix = _context._getPrefixDot(element.library); - _writer.print('() => new ${prefix}${element.displayName}()'); - } else { - node.accept(_factoryVisitor); - } - } - - /// Creates the 'parameters' property for the Angular2 [registerType] call - /// for [node]. - void _codegenParametersProp(ConstructorDeclaration node) { - if (node == null) { - // This occurs when the class does not declare a constructor. - _writer.print('const [const []]'); - } else { - node.accept(_parametersVisitor); - } - } -} - -/// Visitor providing common methods for concrete implementations. -class _TransformVisitorMixin { - final Context context; - final PrintWriter writer; - - /// Safely visit [node]. - void _visitNode(AstNode node) { - if (node != null) { - node.accept(this); - } - } - - /// If [node] is null does nothing. Otherwise, prints [prefix], then - /// visits [node]. - void _visitNodeWithPrefix(String prefix, AstNode node) { - if (node != null) { - writer.print(prefix); - node.accept(this); - } - } - - /// If [node] is null does nothing. Otherwise, visits [node], then prints - /// [suffix]. - void _visitNodeWithSuffix(AstNode node, String suffix) { - if (node != null) { - node.accept(this); - writer.print(suffix); - } - } - - String prefixedSimpleIdentifier(SimpleIdentifier node) { - // Make sure the identifier is prefixed if necessary. - if (node.bestElement is ClassElementImpl || - node.bestElement is PropertyAccessorElement) { - return context._getPrefixDot(node.bestElement.library) + - node.token.lexeme; - } else { - return node.token.lexeme; - } - } -} - -class _TransformVisitor extends ToSourceVisitor with _TransformVisitorMixin { - final Context context; - final PrintWriter writer; - - _TransformVisitor(PrintWriter writer, this.context) - : this.writer = writer, - super(writer); - - @override - Object visitPrefixedIdentifier(PrefixedIdentifier node) { - // We add our own prefixes in [visitSimpleIdentifier], discard any used in - // the original source. - writer.print(super.prefixedSimpleIdentifier(node.identifier)); - return null; - } - - @override - Object visitSimpleIdentifier(SimpleIdentifier node) { - writer.print(super.prefixedSimpleIdentifier(node)); - return null; - } -} - -/// SourceVisitor designed to accept [ConstructorDeclaration] nodes. -class _CtorTransformVisitor extends _TransformVisitor { - bool _withParameterTypes = true; - bool _withParameterNames = true; - - _CtorTransformVisitor(PrintWriter writer, Context _context) - : super(writer, _context); - - /// If [_withParameterTypes] is true, this method outputs [node]'s type - /// (appropriately prefixed based on [_libraryPrefixes]. If - /// [_withParameterNames] is true, this method outputs [node]'s identifier. - Object _visitNormalFormalParameter(NormalFormalParameter node) { - if (_withParameterTypes) { - var paramType = node.element.type; - var prefix = context._getPrefixDot(paramType.element.library); - writer.print('${prefix}${paramType.displayName}'); - if (_withParameterNames) { - _visitNodeWithPrefix(' ', node.identifier); - } - } else if (_withParameterNames) { - _visitNode(node.identifier); - } - return null; - } - - @override - Object visitSimpleFormalParameter(SimpleFormalParameter node) { - return _visitNormalFormalParameter(node); - } - - @override - Object visitFieldFormalParameter(FieldFormalParameter node) { - if (node.parameters != null) { - logger.error('Parameters in ctor not supported ' - '(${super.visitFormalParameterList(node)}'); - } - return _visitNormalFormalParameter(node); - } - - @override - Object visitDefaultFormalParameter(DefaultFormalParameter node) { - _visitNode(node.parameter); - // Ignore the declared default value. - return null; - } - - @override - /// Overridden to avoid outputting grouping operators for default parameters. - Object visitFormalParameterList(FormalParameterList node) { - writer.print('('); - NodeList parameters = node.parameters; - int size = parameters.length; - for (int i = 0; i < size; i++) { - if (i > 0) { - writer.print(', '); - } - parameters[i].accept(this); - } - writer.print(')'); - return null; - } -} - -/// ToSourceVisitor designed to print 'parameters' values for Angular2's -/// [registerType] calls. -class _ParameterTransformVisitor extends _CtorTransformVisitor { - _ParameterTransformVisitor(PrintWriter writer, Context _context) - : super(writer, _context); - - @override - Object visitConstructorDeclaration(ConstructorDeclaration node) { - _withParameterNames = false; - _withParameterTypes = true; - writer.print('const [const ['); - _visitNode(node.parameters); - writer.print(']]'); - return null; - } - - @override - Object visitFormalParameterList(FormalParameterList node) { - NodeList parameters = node.parameters; - int size = parameters.length; - for (int i = 0; i < size; i++) { - if (i > 0) { - writer.print(', '); - } - parameters[i].accept(this); - } - return null; - } -} - -/// ToSourceVisitor designed to print 'factory' values for Angular2's -/// [registerType] calls. -class _FactoryTransformVisitor extends _CtorTransformVisitor { - _FactoryTransformVisitor(PrintWriter writer, Context _context) - : super(writer, _context); - - @override - Object visitConstructorDeclaration(ConstructorDeclaration node) { - _withParameterNames = true; - _withParameterTypes = true; - _visitNode(node.parameters); - writer.print(' => new '); - _visitNode(node.returnType); - _visitNodeWithPrefix(".", node.name); - _withParameterTypes = false; - _visitNode(node.parameters); - return null; - } -} - -/// ToSourceVisitor designed to print a [ClassDeclaration] node as a -/// 'annotations' value for Angular2's [registerType] calls. -class _AnnotationsTransformVisitor extends _TransformVisitor { - _AnnotationsTransformVisitor(PrintWriter writer, Context _context) - : super(writer, _context); - - @override - Object visitClassDeclaration(ClassDeclaration node) { - writer.print('const ['); - var size = node.metadata.length; - for (var i = 0; i < size; ++i) { - if (i > 0) { - writer.print(', '); - } - node.metadata[i].accept(this); - } - writer.print(']'); - return null; - } - - @override - Object visitAnnotation(Annotation node) { - writer.print('const '); - _visitNode(node.name); -// TODO(tjblasi): Do we need to handle named constructors for annotations? -// _visitNodeWithPrefix(".", node.constructorName); - _visitNode(node.arguments); - return null; - } -} - -/// Visitor designed to print a [ClassDeclaration] node as a -/// `registerSetters` call for Angular2. -class _BindTransformVisitor extends Object - with SimpleAstVisitor, _TransformVisitorMixin { - final Context context; - final PrintWriter writer; - final List _bindPieces = []; - SimpleIdentifier _currentName = null; - - _BindTransformVisitor(this.writer, this.context); - - @override - Object visitClassDeclaration(ClassDeclaration node) { - _currentName = node.name; - node.metadata.forEach((meta) => _visitNode(meta)); - if (_bindPieces.isNotEmpty) { - writer.print('..registerSetters({${_bindPieces.join(', ')}})'); - } - return null; - } - - @override - Object visitAnnotation(Annotation node) { - // TODO(kegluneq): Remove this restriction. - if (node.element is ConstructorElement) { - if (node.element.returnType.element is ClassElement) { - // TODO(kegluneq): Check if this is actually a `directive`. - node.arguments.arguments.forEach((arg) => _visitNode(arg)); - } - } - return null; - } - - @override - Object visitNamedExpression(NamedExpression node) { - if (node.name.label.toString() == 'bind') { - // TODO(kegluneq): Remove this restriction. - if (node.expression is MapLiteral) { - node.expression.accept(this); - } - } - return null; - } - - @override - Object visitMapLiteral(MapLiteral node) { - node.entries.forEach((entry) { - if (entry.key is SimpleStringLiteral) { - _visitNode(entry.key); - } else { - logger.error('`properties` currently only supports string literals'); - } - }); - return null; - } - - @override - Object visitSimpleStringLiteral(SimpleStringLiteral node) { - if (_currentName == null) { - logger.error('Unexpected code path: `currentName` should never be null'); - } - _bindPieces.add('"${node.value}": (' - '${super.prefixedSimpleIdentifier(_currentName)} o, String value) => ' - 'o.${node.value} = value'); - return null; - } -} diff --git a/modules/angular2/src/transform/in_progress/find_bootstrap.dart b/modules/angular2/src/transform/in_progress/find_bootstrap.dart deleted file mode 100644 index 414312010e..0000000000 --- a/modules/angular2/src/transform/in_progress/find_bootstrap.dart +++ /dev/null @@ -1,93 +0,0 @@ -library angular2.transform; - -import 'package:analyzer/src/generated/ast.dart'; -import 'package:analyzer/src/generated/element.dart'; -import 'package:code_transformers/resolver.dart'; - -import 'resolvers.dart'; - -/// Finds all calls to the Angular2 [bootstrap] method defined in [library]. -/// This only searches the code defined in the file -// represented by [library], not `part`s, `import`s, `export`s, etc. -Set findBootstrapCalls( - Resolver resolver, LibraryElement library) { - var types = new Angular2Types(resolver); - if (types.bootstrapMethod == null) { - throw new ArgumentError( - 'Could not find symbol for ${bootstrapMethodName}.'); - } - var visitor = new _FindFunctionVisitor(types.bootstrapMethod); - - // TODO(kegluneq): Determine how to get nodes without querying Element#node. - // Root of file defining that library (main part). - library.definingCompilationUnit.node.accept(visitor); - - return new Set.from(visitor.functionCalls.map((MethodInvocation mi) { - var visitor = new _ParseBootstrapTypeVisitor(types); - if (mi.argumentList.arguments.isEmpty) { - throw new ArgumentError('No arguments provided to `bootstrap`.'); - } - mi.argumentList.arguments[0].accept(visitor); - if (visitor.bootstrapType == null) { - throw new UnsupportedError( - 'Failed to parse `bootstrap` call: ${mi.toSource()}'); - } - return new BootstrapCallInfo(mi, visitor.bootstrapType); - })); -} - -/// Information about a single call to Angular2's [bootstrap] method. -class BootstrapCallInfo { - /// The [AstNode] representing the call to [bootstrap]. - final MethodInvocation call; - - /// The type, which should be annotated as a [Component], which is the root - /// of the Angular2 app. - final ClassElement bootstrapType; - - BootstrapCallInfo(this.call, this.bootstrapType); -} - -/// Visitor that finds the Angular2 bootstrap component given [bootstrap]'s -/// first argument. -/// -/// This visitor does not recursively visit nodes in the Ast. -class _ParseBootstrapTypeVisitor extends SimpleAstVisitor { - ClassElement bootstrapType = null; - - final Angular2Types _types; - - _ParseBootstrapTypeVisitor(this._types); - - // TODO(kegluneq): Allow non-SimpleIdentifier expressions. - - @override - Object visitSimpleIdentifier(SimpleIdentifier node) { - bootstrapType = (node.bestElement as ClassElement); - if (!_types.isComponent(bootstrapType)) { - throw new ArgumentError('Class passed to `${bootstrapMethodName}` must ' - 'be a @${_types.componentAnnotation.name}'); - } - } -} - -/// Recursively visits all nodes in an Ast structure, recording all encountered -/// calls to the provided [FunctionElement]. -class _FindFunctionVisitor extends RecursiveAstVisitor { - final FunctionElement _target; - _FindFunctionVisitor(this._target); - - final Set functionCalls = new Set(); - - bool _isDesiredMethod(MethodInvocation node) { - return node.methodName.bestElement == _target; - } - - @override - Object visitMethodInvocation(MethodInvocation node) { - if (_isDesiredMethod(node)) { - functionCalls.add(node); - } - return super.visitMethodInvocation(node); - } -} diff --git a/modules/angular2/src/transform/in_progress/find_reflection_capabilities.dart b/modules/angular2/src/transform/in_progress/find_reflection_capabilities.dart deleted file mode 100644 index 86bf4175f9..0000000000 --- a/modules/angular2/src/transform/in_progress/find_reflection_capabilities.dart +++ /dev/null @@ -1,152 +0,0 @@ -library angular2.transform; - -import 'package:analyzer/src/generated/ast.dart'; -import 'package:analyzer/src/generated/element.dart'; -import 'package:analyzer/src/generated/java_core.dart'; -import 'package:barback/barback.dart'; -import 'package:code_transformers/resolver.dart'; -import 'package:dart_style/dart_style.dart'; -import 'package:path/path.dart' as path; - -import 'codegen.dart'; -import 'common/logging.dart'; -import 'resolvers.dart'; - -/// Finds all calls to the Angular2 [ReflectionCapabilities] constructor -/// defined in [library]. -/// This only searches the code defined in the file -// represented by [library], not `part`s, `import`s, `export`s, etc. -String findReflectionCapabilities( - Resolver resolver, AssetId reflectionEntryPoint, AssetId newEntryPoint) { - var types = new Angular2Types(resolver); - if (types.reflectionCapabilities == null) { - throw new ArgumentError( - 'Could not find class for ${reflectionCapabilitiesTypeName}.'); - } - - var codegen = new _SetupReflectionCodegen( - resolver, reflectionEntryPoint, newEntryPoint); - - var writer = new PrintStringWriter(); - var visitor = new _RewriteReflectionEntryPointVisitor( - writer, types.reflectionCapabilities, codegen); - - // TODO(kegluneq): Determine how to get nodes without querying Element#node. - // Root of file defining that library (main part). - resolver.getLibrary(reflectionEntryPoint).definingCompilationUnit.node - .accept(visitor); - - return new DartFormatter().format(writer.toString()); -} - -class _SetupReflectionCodegen { - static const _prefixBase = 'ngStaticInit'; - - final String prefix; - final String importUri; - - _SetupReflectionCodegen._internal(this.prefix, this.importUri); - - factory _SetupReflectionCodegen( - Resolver resolver, AssetId reflectionEntryPoint, AssetId newEntryPoint) { - var lib = resolver.getLibrary(reflectionEntryPoint); - var prefix = _prefixBase; - var idx = 0; - while (lib.imports.any((import) { - return import.prefix != null && import.prefix == prefix; - })) { - prefix = '${_prefixBase}${idx++}'; - } - - var importPath = path.relative(newEntryPoint.path, - from: path.dirname(reflectionEntryPoint.path)); - return new _SetupReflectionCodegen._internal(prefix, importPath); - } - - /// Generates code to import the library containing the method which sets up - /// Angular2 reflection statically. - /// - /// The code generated here should follow the example of code generated for - /// an [ImportDirective] node. - String codegenImport() { - return 'import \'${importUri}\' as ${prefix};'; - } - - /// Generates code to call the method which sets up Angular2 reflection - /// statically. - /// - /// The code generated here should follow the example of code generated for - /// a [MethodInvocation] node, that is, it should be prefixed as necessary - /// and not be followed by a ';'. - String codegenSetupReflectionCall() { - return '${prefix}.${setupReflectionMethodName}()'; - } -} - -class _RewriteReflectionEntryPointVisitor extends ToSourceVisitor { - final PrintWriter _writer; - final ClassElement _forbiddenClass; - final _SetupReflectionCodegen _codegen; - - _RewriteReflectionEntryPointVisitor( - PrintWriter writer, this._forbiddenClass, this._codegen) - : _writer = writer, - super(writer); - - bool _isNewReflectionCapabilities(InstanceCreationExpression node) { - var typeElement = node.constructorName.type.name.bestElement; - return typeElement != null && typeElement == _forbiddenClass; - } - - bool _isReflectionCapabilitiesImport(ImportDirective node) { - return node.uriElement == _forbiddenClass.library; - } - - @override - Object visitImportDirective(ImportDirective node) { - if (_isReflectionCapabilitiesImport(node)) { - // TODO(kegluneq): Remove newlines once dart_style bug is fixed. - // https://github.com/dart-lang/dart_style/issues/178 - // _writer.print('\n/* ReflectionCapabilities import removed */\n'); - _writer.print(_codegen.codegenImport()); - // TODO(kegluneq): Remove once we generate all needed code. - { - super.visitImportDirective(node); - } - return null; - } - return super.visitImportDirective(node); - } - - @override - Object visitAssignmentExpression(AssignmentExpression node) { - if (node.rightHandSide is InstanceCreationExpression && - _isNewReflectionCapabilities(node.rightHandSide)) { - // TODO(kegluneq): Remove newlines once dart_style bug is fixed. - // https://github.com/dart-lang/dart_style/issues/178 - // _writer.print('/* Creation of ReflectionCapabilities removed */\n'); - _writer.print(_codegen.codegenSetupReflectionCall()); - - // TODO(kegluneq): Remove once we generate all needed code. - { - _writer.print(';'); - node.leftHandSide.accept(this); - _writer.print(' ${node.operator.lexeme} '); - super.visitInstanceCreationExpression(node.rightHandSide); - } - return null; - } - return super.visitAssignmentExpression(node); - } - - @override - Object visitInstanceCreationExpression(InstanceCreationExpression node) { - if (_isNewReflectionCapabilities(node)) { - logger.error('Unexpected format in creation of ' - '${reflectionCapabilitiesTypeName}'); - } else { - return super.visitInstanceCreationExpression(node); - } - return null; - } -} diff --git a/modules/angular2/src/transform/in_progress/resolvers.dart b/modules/angular2/src/transform/in_progress/resolvers.dart deleted file mode 100644 index 7cf0760a3a..0000000000 --- a/modules/angular2/src/transform/in_progress/resolvers.dart +++ /dev/null @@ -1,140 +0,0 @@ -library angular2.transform; - -import 'package:barback/barback.dart'; -import 'package:analyzer/src/generated/element.dart'; -import 'package:code_transformers/resolver.dart'; - -Resolvers createResolvers() { - return new Resolvers.fromMock({ - // The list of types below is derived from: - // * types that are used internally by the resolver (see - // _initializeFrom in resolver.dart). - // TODO(jakemac): Move this into code_transformers so it can be shared. - 'dart:core': ''' - library dart.core; - class Object {} - class Function {} - class StackTrace {} - class Symbol {} - class Type {} - - class String extends Object {} - class bool extends Object {} - class num extends Object {} - class int extends num {} - class double extends num {} - class DateTime extends Object {} - class Null extends Object {} - - class Deprecated extends Object { - final String expires; - const Deprecated(this.expires); - } - const Object deprecated = const Deprecated("next release"); - class _Override { const _Override(); } - const Object override = const _Override(); - class _Proxy { const _Proxy(); } - const Object proxy = const _Proxy(); - - class List extends Object {} - class Map extends Object {} - ''', - 'dart:html': ''' - library dart.html; - class HtmlElement {} - ''', - }); -} - -const bootstrapMethodName = 'bootstrap'; -const reflectionCapabilitiesTypeName = 'ReflectionCapabilities'; - -/// Provides resolved [Elements] for well-known Angular2 symbols. -class Angular2Types { - static Map _cache = {}; - static final _annotationsLibAssetId = - new AssetId('angular2', 'lib/src/core/annotations/annotations.dart'); - static final _applicationLibAssetId = - new AssetId('angular2', 'lib/src/core/application.dart'); - static final _templateLibAssetId = - new AssetId('angular2', 'lib/src/core/annotations/view.dart'); - static final _reflectionCapabilitiesLibAssetId = new AssetId( - 'angular2', 'lib/src/reflection/reflection_capabilities.dart'); - - final Resolver _resolver; - FunctionElement _bootstrapMethod; - - Angular2Types._internal(this._resolver); - - factory Angular2Types(Resolver resolver) { - return _cache.putIfAbsent( - resolver, () => new Angular2Types._internal(resolver)); - } - - LibraryElement get annotationsLib => - _resolver.getLibrary(_annotationsLibAssetId); - - ClassElement get directiveAnnotation => - _getTypeSafe(annotationsLib, 'Directive'); - - ClassElement get componentAnnotation => - _getTypeSafe(annotationsLib, 'Component'); - - ClassElement get decoratorAnnotation => - _getTypeSafe(annotationsLib, 'Decorator'); - - LibraryElement get templateLib => _resolver.getLibrary(_templateLibAssetId); - - ClassElement get templateAnnotation => _getTypeSafe(templateLib, 'View'); - - LibraryElement get reflectionCapabilitiesLib => - _resolver.getLibrary(_reflectionCapabilitiesLibAssetId); - - ClassElement get reflectionCapabilities => - _getTypeSafe(reflectionCapabilitiesLib, reflectionCapabilitiesTypeName); - - LibraryElement get applicationLib => - _resolver.getLibrary(_applicationLibAssetId); - - FunctionElement get bootstrapMethod { - if (_bootstrapMethod == null) { - _bootstrapMethod = applicationLib.definingCompilationUnit.functions - .firstWhere((FunctionElement el) => el.name == bootstrapMethodName, - orElse: () => null); - } - return _bootstrapMethod; - } - - /// Gets the type named [name] in library [lib]. Returns `null` if [lib] is - /// `null` or [name] cannot be found in [lib]. - ClassElement _getTypeSafe(LibraryElement lib, String name) { - if (lib == null) return null; - return lib.getType(name); - } - - /// Whether [clazz] is annotated as a [Component]. - bool isComponent(ClassElement clazz) => - hasAnnotation(clazz, componentAnnotation); -} - -/// Whether [type], its superclass, or one of its interfaces matches [target]. -bool isAnnotationMatch(InterfaceType type, ClassElement target) { - if (type == null || type.element == null) return false; - if (type.element.type == target.type) return true; - if (isAnnotationMatch(type.superclass, target)) return true; - for (var interface in type.interfaces) { - if (isAnnotationMatch(interface, target)) return true; - } - return false; -} - -/// Determines whether [clazz] has at least one annotation that `is` a -/// [metaClazz]. -bool hasAnnotation(ClassElement clazz, ClassElement metaClazz) { - if (clazz == null || metaClazz == null) return false; - return clazz.metadata.firstWhere((ElementAnnotation meta) { -// TODO(kegluneq): Make this recognize non-ConstructorElement annotations. - return meta.element is ConstructorElement && - isAnnotationMatch(meta.element.returnType, metaClazz); - }, orElse: () => null) != null; -} diff --git a/modules/angular2/src/transform/in_progress/traversal.dart b/modules/angular2/src/transform/in_progress/traversal.dart deleted file mode 100644 index 777f70f7b4..0000000000 --- a/modules/angular2/src/transform/in_progress/traversal.dart +++ /dev/null @@ -1,83 +0,0 @@ -library angular2.transform; - -import 'package:analyzer/src/generated/ast.dart'; -import 'package:analyzer/src/generated/element.dart'; - -import 'annotation_processor.dart'; -import 'common/logging.dart'; -import 'resolvers.dart'; - -/// Walks through an Angular2 application, finding all classes matching the -/// provided [annotationMatcher]. -class AngularVisibleTraversal { - final Angular2Types _types; - final _ComponentParsingAstVisitor _visitor; - - AngularVisibleTraversal(this._types, AnnotationMatcher annotationMatcher) - : _visitor = new _ComponentParsingAstVisitor(annotationMatcher); - - /// Walks an Angular2 application, starting with the class represented by - /// [entryPoint], which must be annotated as an Angular2 [Component]. - /// - /// We recursively check the entryPoint's annotations and constructor - /// arguments for types which match the provided [annotationMatcher]. - void traverse(ClassElement entryPoint) { - if (!_types.isComponent(entryPoint)) { - throw new ArgumentError.value(entryPoint, 'entryPoint', - 'Provided entryPoint must be annotated as a Component'); - } - entryPoint.node.accept(_visitor); - } -} - -class _ComponentParsingAstVisitor extends Object - with RecursiveAstVisitor { - final Set _seen = new Set(); - final AnnotationMatcher _matcher; - - _ComponentParsingAstVisitor(this._matcher); - - @override - Object visitClassDeclaration(ClassDeclaration node) { - if (node.element != null) { - if (_seen.contains(node.element)) return null; - _seen.add(node.element); - } - - // Process the class itself. - node.name.accept(this); - - // Process metadata information, ignoring [FieldDeclaration]s and - // [MethodDeclaration]s (see below). - node.metadata.forEach((Annotation meta) => meta.accept(this)); - - // Process constructor parameters, fields & methods are ignored below. - node.members.forEach((m) => m.accept(this)); - - return null; - } - - @override - Object visitFieldDeclaration(FieldDeclaration node) => null; - - @override - Object visitMethodDeclaration(MethodDeclaration node) => null; - - @override - Object visitAnnotation(Annotation node) { - // TODO(kegluneq): Visit only Angular2 annotations & subtypes. - return super.visitAnnotation(node); - } - - @override - Object visitSimpleIdentifier(SimpleIdentifier node) { - if (node.bestElement != null) { - if (node.bestElement is ClassElement) { - var matches = _matcher.processAnnotations(node.bestElement); - // If any of these types are matches, recurse on them. - matches.forEach((match) => match.node.accept(this)); - } - } - return super.visitSimpleIdentifier(node); - } -} diff --git a/modules/angular2/src/transform/reflection_remover/ast_tester.dart b/modules/angular2/src/transform/reflection_remover/ast_tester.dart index 4f2e9d75b3..a33d9d2c0e 100644 --- a/modules/angular2/src/transform/reflection_remover/ast_tester.dart +++ b/modules/angular2/src/transform/reflection_remover/ast_tester.dart @@ -2,12 +2,11 @@ library angular2.transform.reflection_remover.ast_tester; import 'package:analyzer/src/generated/ast.dart'; import 'package:analyzer/src/generated/element.dart'; +import 'package:angular2/src/transform/common/names.dart'; /// An object that checks for [ReflectionCapabilities] syntactically, that is, /// without resolution information. class AstTester { - static const REFLECTION_CAPABILITIES_NAME = 'ReflectionCapabilities'; - const AstTester(); bool isNewReflectionCapabilities(InstanceCreationExpression node) => diff --git a/modules/angular2/src/transform/reflection_remover/codegen.dart b/modules/angular2/src/transform/reflection_remover/codegen.dart index 903ee4fc80..acbee385fe 100644 --- a/modules/angular2/src/transform/reflection_remover/codegen.dart +++ b/modules/angular2/src/transform/reflection_remover/codegen.dart @@ -1,8 +1,6 @@ library angular2.transform.reflection_remover.codegen; import 'package:analyzer/src/generated/ast.dart'; -import 'package:barback/barback.dart'; -import 'package:code_transformers/resolver.dart'; import 'package:path/path.dart' as path; import 'package:angular2/src/transform/common/names.dart'; @@ -23,20 +21,6 @@ class Codegen { if (this.prefix.isEmpty) throw new ArgumentError.value('(empty)', 'prefix'); } - factory Codegen.fromResolver( - Resolver resolver, AssetId reflectionEntryPoint, AssetId newEntryPoint) { - var lib = resolver.getLibrary(reflectionEntryPoint); - var prefix = _PREFIX_BASE; - var idx = 0; - while (lib.imports.any((import) { - return import.prefix != null && import.prefix == prefix; - })) { - prefix = '${_PREFIX_BASE}${idx++}'; - } - - return new Codegen(reflectionEntryPoint, newEntryPoint, prefix: prefix); - } - /// Generates code to import the library containing the method which sets up /// Angular2 reflection statically. /// diff --git a/modules/angular2/src/transform/reflection_remover/rewriter.dart b/modules/angular2/src/transform/reflection_remover/rewriter.dart index 389fbd2799..ee46db9688 100644 --- a/modules/angular2/src/transform/reflection_remover/rewriter.dart +++ b/modules/angular2/src/transform/reflection_remover/rewriter.dart @@ -2,6 +2,7 @@ library angular2.transform.reflection_remover.rewriter; import 'package:analyzer/src/generated/ast.dart'; import 'package:angular2/src/transform/common/logging.dart'; +import 'package:angular2/src/transform/common/names.dart'; import 'ast_tester.dart'; import 'codegen.dart'; @@ -27,12 +28,11 @@ class Rewriter { var visitor = new _FindReflectionCapabilitiesVisitor(_tester); node.accept(visitor); if (visitor.reflectionCapabilityImports.isEmpty) { - logger.error( - 'Failed to find ${AstTester.REFLECTION_CAPABILITIES_NAME} import.'); + logger.error('Failed to find ${REFLECTION_CAPABILITIES_NAME} import.'); return _code; } if (visitor.reflectionCapabilityAssignments.isEmpty) { - logger.error('Failed to find ${AstTester.REFLECTION_CAPABILITIES_NAME} ' + logger.error('Failed to find ${REFLECTION_CAPABILITIES_NAME} ' 'instantiation.'); return _code; } @@ -120,7 +120,7 @@ class _FindReflectionCapabilitiesVisitor extends Object if (_tester.isNewReflectionCapabilities(node) && !reflectionCapabilityAssignments.contains(node.parent)) { logger.error('Unexpected format in creation of ' - '${reflectionCapabilitiesTypeName}'); + '${REFLECTION_CAPABILITIES_NAME}'); } return super.visitInstanceCreationExpression(node); } diff --git a/modules/angular2/src/transform/transformer.dart b/modules/angular2/src/transform/transformer.dart index f3c4f72b9e..ded793d04b 100644 --- a/modules/angular2/src/transform/transformer.dart +++ b/modules/angular2/src/transform/transformer.dart @@ -9,7 +9,6 @@ import 'bind_generator/transformer.dart'; import 'reflection_remover/transformer.dart'; import 'template_compiler/transformer.dart'; import 'common/formatter.dart' as formatter; -import 'common/names.dart'; import 'common/options.dart'; import 'common/options_reader.dart'; diff --git a/modules/angular2/test/transform/bind_generator/all_tests.dart b/modules/angular2/test/transform/bind_generator/all_tests.dart index a5f12101af..817e774584 100644 --- a/modules/angular2/test/transform/bind_generator/all_tests.dart +++ b/modules/angular2/test/transform/bind_generator/all_tests.dart @@ -1,14 +1,9 @@ library angular2.test.transform.bind_generator.all_tests; -import 'dart:io'; import 'package:barback/barback.dart'; import 'package:angular2/src/transform/bind_generator/generator.dart'; -import 'package:angular2/src/transform/common/formatter.dart'; -import 'package:code_transformers/tests.dart'; import 'package:dart_style/dart_style.dart'; -import 'package:path/path.dart' as path; import 'package:guinness/guinness.dart'; -import 'package:unittest/vm_config.dart'; import '../common/read_file.dart'; diff --git a/modules/angular2/test/transform/common/read_file.dart b/modules/angular2/test/transform/common/read_file.dart index dc81d937c6..53ae3ded61 100644 --- a/modules/angular2/test/transform/common/read_file.dart +++ b/modules/angular2/test/transform/common/read_file.dart @@ -1,6 +1,7 @@ library angular2.test.transform.common.read_file; import 'dart:async'; +import 'dart:convert'; import 'dart:io'; import 'package:angular2/src/transform/common/asset_reader.dart'; diff --git a/modules/angular2/test/transform/directive_linker/all_tests.dart b/modules/angular2/test/transform/directive_linker/all_tests.dart index a7068f5464..e8c3e60b1e 100644 --- a/modules/angular2/test/transform/directive_linker/all_tests.dart +++ b/modules/angular2/test/transform/directive_linker/all_tests.dart @@ -1,14 +1,9 @@ library angular2.test.transform.directive_linker.all_tests; import 'package:barback/barback.dart'; -import 'package:angular2/src/transform/common/logging.dart' hide init; -import 'package:angular2/src/transform/common/formatter.dart' hide init; import 'package:angular2/src/transform/directive_linker/linker.dart'; -import 'package:code_transformers/tests.dart'; import 'package:dart_style/dart_style.dart'; -import 'package:path/path.dart' as path; import 'package:guinness/guinness.dart'; -import 'package:unittest/vm_config.dart'; import '../common/read_file.dart'; diff --git a/modules/angular2/test/transform/directive_processor/all_tests.dart b/modules/angular2/test/transform/directive_processor/all_tests.dart index 26201fd3a2..dee04671b4 100644 --- a/modules/angular2/test/transform/directive_processor/all_tests.dart +++ b/modules/angular2/test/transform/directive_processor/all_tests.dart @@ -1,14 +1,8 @@ library angular2.test.transform.directive_processor.all_tests; -import 'dart:io'; -import 'package:barback/barback.dart'; import 'package:angular2/src/transform/directive_processor/rewriter.dart'; -import 'package:angular2/src/transform/common/formatter.dart'; -import 'package:code_transformers/tests.dart'; import 'package:dart_style/dart_style.dart'; -import 'package:path/path.dart' as path; import 'package:guinness/guinness.dart'; -import 'package:unittest/vm_config.dart'; import '../common/read_file.dart'; diff --git a/modules/angular2/test/transform/integration/all_tests.dart b/modules/angular2/test/transform/integration/all_tests.dart index ab770932ab..79a3821777 100644 --- a/modules/angular2/test/transform/integration/all_tests.dart +++ b/modules/angular2/test/transform/integration/all_tests.dart @@ -1,6 +1,5 @@ library angular2.test.transform.integration; -import 'dart:io'; import 'package:angular2/src/dom/html_adapter.dart'; import 'package:angular2/src/transform/common/names.dart'; import 'package:angular2/transformer.dart'; diff --git a/modules/angular2/test/transform/template_compiler/all_tests.dart b/modules/angular2/test/transform/template_compiler/all_tests.dart index e18fe5d5eb..d1332d5cbb 100644 --- a/modules/angular2/test/transform/template_compiler/all_tests.dart +++ b/modules/angular2/test/transform/template_compiler/all_tests.dart @@ -1,10 +1,8 @@ -library angular2.test.transform.directive_processor.all_tests; +library angular2.test.transform.template_compiler.all_tests; import 'package:barback/barback.dart'; import 'package:angular2/src/dom/html_adapter.dart'; import 'package:angular2/src/transform/common/asset_reader.dart'; -import 'package:angular2/src/transform/common/logging.dart'; -import 'package:angular2/src/transform/common/formatter.dart'; import 'package:angular2/src/transform/template_compiler/generator.dart'; import 'package:dart_style/dart_style.dart'; import 'package:guinness/guinness.dart';