diff --git a/modules_dart/transform/lib/src/transform/common/code/import_export_code.dart b/modules_dart/transform/lib/src/transform/common/code/import_export_code.dart index aa76610254..30745b57dd 100644 --- a/modules_dart/transform/lib/src/transform/common/code/import_export_code.dart +++ b/modules_dart/transform/lib/src/transform/common/code/import_export_code.dart @@ -1,16 +1,27 @@ library angular2.transform.common.code.import_export_code; import 'package:analyzer/analyzer.dart'; +import 'package:angular2/src/transform/common/mirror_matcher.dart'; import 'package:angular2/src/transform/common/model/import_export_model.pb.dart'; +const _mirrorMatcher = const MirrorMatcher(); + /// Visitor responsible for parsing [ImportDirective]s into [ImportModel]s. class ImportVisitor extends SimpleAstVisitor { @override ImportModel visitImportDirective(ImportDirective node) { if (node.isSynthetic) return null; + /// We skip this, as it transitively imports 'dart:mirrors' + if (_mirrorMatcher.hasReflectionCapabilitiesUri(node)) return null; + String uri = stringLiteralToString(node.uri); + // The bootstrap code also transitively imports 'dart:mirrors' + if (_mirrorMatcher.hasBootstrapUri(node)) { + uri = BOOTSTRAP_STATIC_URI; + } + var model = new ImportModel() - ..uri = stringLiteralToString(node.uri) + ..uri = uri ..isDeferred = node.deferredKeyword != null; if (node.prefix != null) { model.prefix = node.prefix.name; @@ -26,7 +37,15 @@ class ExportVisitor extends SimpleAstVisitor { ExportModel visitExportDirective(ExportDirective node) { if (node.isSynthetic) return null; - var model = new ExportModel()..uri = stringLiteralToString(node.uri); + /// We skip this, as it transitively imports 'dart:mirrors' + if (_mirrorMatcher.hasReflectionCapabilitiesUri(node)) return null; + String uri = stringLiteralToString(node.uri); + // The bootstrap code also transitively imports 'dart:mirrors' + if (_mirrorMatcher.hasBootstrapUri(node)) { + uri = BOOTSTRAP_STATIC_URI; + } + + var model = new ExportModel()..uri = uri; _populateCombinators(node, model); return model; } diff --git a/modules_dart/transform/lib/src/transform/common/mirror_matcher.dart b/modules_dart/transform/lib/src/transform/common/mirror_matcher.dart new file mode 100644 index 0000000000..3eaf5a28c7 --- /dev/null +++ b/modules_dart/transform/lib/src/transform/common/mirror_matcher.dart @@ -0,0 +1,29 @@ +library angular2.transform.common.mirror_matcher; + +import 'package:analyzer/src/generated/ast.dart'; +import 'package:angular2/src/transform/common/names.dart'; + +const BOOTSTRAP_STATIC_URI = 'package:angular2/bootstrap_static.dart'; +const BOOTSTRAP_URI = 'package:angular2/bootstrap.dart'; +const REFLECTION_CAPABILITIES_URI = + 'package:angular2/src/core/reflection/reflection_capabilities.dart'; + +/// Syntactially checks for code related to the use of `dart:mirrors`. +/// +/// Checks various [AstNode]s to determine if they are +/// - Libraries that transitively import `dart:mirrors` +/// - Instantiations of [ReflectionCapabilities] +class MirrorMatcher { + const MirrorMatcher(); + + bool isNewReflectionCapabilities(InstanceCreationExpression node) => + '${node.constructorName.type.name}' == REFLECTION_CAPABILITIES_NAME; + + bool hasReflectionCapabilitiesUri(UriBasedDirective node) { + return node.uri.stringValue == REFLECTION_CAPABILITIES_URI; + } + + bool hasBootstrapUri(UriBasedDirective node) { + return node.uri.stringValue == BOOTSTRAP_URI; + } +} diff --git a/modules_dart/transform/lib/src/transform/reflection_remover/ast_tester.dart b/modules_dart/transform/lib/src/transform/reflection_remover/ast_tester.dart deleted file mode 100644 index f50dc5a77e..0000000000 --- a/modules_dart/transform/lib/src/transform/reflection_remover/ast_tester.dart +++ /dev/null @@ -1,44 +0,0 @@ -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 {@link ReflectionCapabilities} syntactically, that is, -/// without resolution information. -class AstTester { - const AstTester(); - - bool isNewReflectionCapabilities(InstanceCreationExpression node) => - '${node.constructorName.type.name}' == REFLECTION_CAPABILITIES_NAME; - - bool isReflectionCapabilitiesImport(ImportDirective node) { - return node.uri.stringValue == - "package:angular2/src/core/reflection/reflection_capabilities.dart"; - } - - bool isBootstrapImport(ImportDirective node) { - return node.uri.stringValue == "package:angular2/bootstrap.dart"; - } -} - -/// An object that checks for {@link ReflectionCapabilities} using a fully resolved -/// Ast. -class ResolvedTester implements AstTester { - final ClassElement _forbiddenClass; - - ResolvedTester(this._forbiddenClass); - - 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; - } - - bool isBootstrapImport(ImportDirective node) { - throw 'Not implemented'; - } -} diff --git a/modules_dart/transform/lib/src/transform/reflection_remover/rewriter.dart b/modules_dart/transform/lib/src/transform/reflection_remover/rewriter.dart index 2a01465d33..0e57d285c8 100644 --- a/modules_dart/transform/lib/src/transform/reflection_remover/rewriter.dart +++ b/modules_dart/transform/lib/src/transform/reflection_remover/rewriter.dart @@ -2,32 +2,33 @@ 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/mirror_matcher.dart'; import 'package:angular2/src/transform/common/mirror_mode.dart'; import 'package:angular2/src/transform/common/names.dart'; import 'package:path/path.dart' as path; -import 'ast_tester.dart'; import 'codegen.dart'; class Rewriter { final String _code; final Codegen _codegen; - final AstTester _tester; + final MirrorMatcher _mirrorMatcher; final MirrorMode _mirrorMode; final bool _writeStaticInit; Rewriter(this._code, this._codegen, - {AstTester tester, + {MirrorMatcher mirrorMatcher, MirrorMode mirrorMode: MirrorMode.none, bool writeStaticInit: true}) : _mirrorMode = mirrorMode, _writeStaticInit = writeStaticInit, - _tester = tester == null ? const AstTester() : tester; + _mirrorMatcher = + mirrorMatcher == null ? const MirrorMatcher() : mirrorMatcher; /// Rewrites the provided code removing imports of the /// {@link ReflectionCapabilities} library and instantiations of /// {@link ReflectionCapabilities}, as detected by the (potentially) provided - /// {@link AstTester}. + /// {@link MirrorMatcher}. /// /// To the extent possible, this method does not change line numbers or /// offsets in the provided code to facilitate debugging via source maps. @@ -62,9 +63,9 @@ class _RewriterVisitor extends Object with RecursiveAstVisitor { Object visitImportDirective(ImportDirective node) { buf.write(_rewriter._code.substring(_currentIndex, node.offset)); _currentIndex = node.offset; - if (_rewriter._tester.isReflectionCapabilitiesImport(node)) { + if (_rewriter._mirrorMatcher.hasReflectionCapabilitiesUri(node)) { _rewriteReflectionCapabilitiesImport(node); - } else if (_rewriter._tester.isBootstrapImport(node)) { + } else if (_rewriter._mirrorMatcher.hasBootstrapUri(node)) { _rewriteBootstrapImportToStatic(node); } if (!_importAdded && _rewriter._writeStaticInit) { @@ -78,7 +79,8 @@ class _RewriterVisitor extends Object with RecursiveAstVisitor { @override Object visitAssignmentExpression(AssignmentExpression node) { if (node.rightHandSide is InstanceCreationExpression && - _rewriter._tester.isNewReflectionCapabilities(node.rightHandSide)) { + _rewriter._mirrorMatcher + .isNewReflectionCapabilities(node.rightHandSide)) { reflectionCapabilityAssignments.add(node); _rewriteReflectionCapabilitiesAssignment(node); } @@ -87,7 +89,7 @@ class _RewriterVisitor extends Object with RecursiveAstVisitor { @override Object visitInstanceCreationExpression(InstanceCreationExpression node) { - if (_rewriter._tester.isNewReflectionCapabilities(node) && + if (_rewriter._mirrorMatcher.isNewReflectionCapabilities(node) && !reflectionCapabilityAssignments.contains(node.parent)) { logger.error('Unexpected format in creation of ' '${REFLECTION_CAPABILITIES_NAME}'); @@ -112,10 +114,10 @@ class _RewriterVisitor extends Object with RecursiveAstVisitor { _rewriteBootstrapImportToStatic(ImportDirective node) { if (_rewriter._writeStaticInit) { - // rewrite `bootstrap.dart` to `bootstrap_static.dart` + // rewrite bootstrap import to its static version. buf.write(_rewriter._code.substring(_currentIndex, node.offset)); // TODO(yjbanov): handle import "..." show/hide ... - buf.write("import 'package:angular2/bootstrap_static.dart';"); + buf.write("import '$BOOTSTRAP_STATIC_URI';"); } else { // leave it as is buf.write(_rewriter._code.substring(_currentIndex, node.end)); diff --git a/modules_dart/transform/lib/src/transform/transformer.dart b/modules_dart/transform/lib/src/transform/transformer.dart index 4aea0b03c3..a23d168677 100644 --- a/modules_dart/transform/lib/src/transform/transformer.dart +++ b/modules_dart/transform/lib/src/transform/transformer.dart @@ -32,9 +32,9 @@ class AngularTransformerGroup extends TransformerGroup { ]; } else { phases = [ - [new ReflectionRemover(options)], [new DirectiveProcessor(options)], [new DirectiveMetadataLinker()], + [new ReflectionRemover(options)], [ new DeferredRewriter(options), new StylesheetCompiler(), diff --git a/modules_dart/transform/test/transform/integration/simple_annotation_files/expected/index.ng_deps.dart b/modules_dart/transform/test/transform/integration/simple_annotation_files/expected/index.ng_deps.dart index 77b09d94d5..0db97e01a1 100644 --- a/modules_dart/transform/test/transform/integration/simple_annotation_files/expected/index.ng_deps.dart +++ b/modules_dart/transform/test/transform/integration/simple_annotation_files/expected/index.ng_deps.dart @@ -3,17 +3,14 @@ library web_foo.ng_deps.dart; import 'index.dart'; import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef; import 'package:angular2/bootstrap_static.dart'; -import 'index.ng_deps.dart' as ngStaticInit; -import 'index.ng_deps.dart' as i1; import 'package:angular2/src/core/reflection/reflection.dart'; import 'bar.dart'; -import 'bar.ng_deps.dart' as i3; +import 'bar.ng_deps.dart' as i2; export 'index.dart'; var _visited = false; void initReflector() { if (_visited) return; _visited = true; - i1.initReflector(); - i3.initReflector(); + i2.initReflector(); }