From fef1dee7aa9a8df94537bca3397ce3de02f72d84 Mon Sep 17 00:00:00 2001 From: Tim Blasi Date: Tue, 14 Apr 2015 15:27:08 -0700 Subject: [PATCH] fix(dart/transform): Ensure consistent ordering of generated imports - Linked imports are generated in a consistent order. - Linked imports are generated immediately after their associated files. --- .../transform/directive_linker/linker.dart | 73 +++++++++++-------- .../expected/bar.ng_deps.dart | 3 +- .../expected/bar.ng_deps.dart | 4 +- .../expected/index.ng_deps.dart | 4 +- .../expected/bar.ng_deps.dart | 4 +- .../two_deps_files/expected/bar.ng_deps.dart | 4 +- 6 files changed, 53 insertions(+), 39 deletions(-) diff --git a/modules/angular2/src/transform/directive_linker/linker.dart b/modules/angular2/src/transform/directive_linker/linker.dart index cccfdbb47d..d051eccc56 100644 --- a/modules/angular2/src/transform/directive_linker/linker.dart +++ b/modules/angular2/src/transform/directive_linker/linker.dart @@ -2,6 +2,7 @@ library angular2.transform.directive_linker.linker; import 'dart:async'; +import 'package:analyzer/analyzer.dart'; import 'package:angular2/src/transform/common/asset_reader.dart'; import 'package:angular2/src/transform/common/logging.dart'; import 'package:angular2/src/transform/common/names.dart'; @@ -13,32 +14,37 @@ import 'package:path/path.dart' as path; Future linkNgDeps(AssetReader reader, AssetId entryPoint) async { var parser = new Parser(reader); NgDeps ngDeps = await parser.parse(entryPoint); - if (ngDeps == null) return null; - if (ngDeps.imports.isEmpty) return ngDeps.code; - 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); + var allDeps = [] + ..addAll(ngDeps.imports) + ..addAll(ngDeps.exports) + ..sort((a, b) => a.end.compareTo(b.end)); + var linkedDepsMap = await _processNgImports(reader, entryPoint, allDeps); - if (depList.isEmpty) return ngDeps.code; + if (linkedDepsMap.isEmpty) return ngDeps.code; var importBuf = new StringBuffer(); var declarationBuf = new StringBuffer(); - for (var i = 0; i < depList.length; ++i) { - importBuf.write(''' - import '${depList[i]}' as i${i}; - '''); - declarationBuf.write('i${i}.${SETUP_METHOD_NAME}(${REFLECTOR_VAR_NAME});'); + var code = ngDeps.code; + var codeIdx = 0; + // Generate import statements for linked deps where necessary. + for (var i = 0, it = allDeps.iterator; it.moveNext();) { + if (linkedDepsMap.containsKey(it.current)) { + importBuf.write(code.substring(codeIdx, it.current.end)); + codeIdx = it.current.end; + importBuf.write(''' + import '${linkedDepsMap[it.current]}' as i${i}; + '''); + declarationBuf + .write('i${i}.${SETUP_METHOD_NAME}(${REFLECTOR_VAR_NAME});'); + ++i; + } } - var code = ngDeps.code; - var importSeamIdx = ngDeps.imports.last.end; var declarationSeamIdx = ngDeps.setupMethod.end - 1; - return '${code.substring(0, importSeamIdx)}' - '$importBuf' - '${code.substring(importSeamIdx, declarationSeamIdx)}' + return '$importBuf' + '${code.substring(codeIdx, declarationSeamIdx)}' '$declarationBuf' '${code.substring(declarationSeamIdx)}'; } @@ -46,21 +52,30 @@ Future linkNgDeps(AssetReader reader, AssetId entryPoint) async { String _toDepsUri(String importUri) => '${path.withoutExtension(importUri)}${DEPS_EXTENSION}'; -bool _isNotDartImport(String importUri) { - return !importUri.startsWith('dart:'); +bool _isNotDartDirective(UriBasedDirective directive) { + return !stringLiteralToString(directive.uri).startsWith('dart:'); } -Future> _processNgImports( - AssetReader reader, AssetId entryPoint, Iterable imports) { +/// Maps each input [UriBasedDirective] to its associated `.ng_deps.dart` +/// file, if it exists. +Future> _processNgImports(AssetReader reader, + AssetId entryPoint, Iterable directives) { final nullFuture = new Future.value(null); - var retVal = []; + final retVal = {}; return Future - .wait(imports.where(_isNotDartImport).map(_toDepsUri).map((ngDepsUri) { - var importAsset = - uriToAssetId(entryPoint, ngDepsUri, logger, null /* span */); - if (importAsset == entryPoint) return nullFuture; - return reader.hasInput(importAsset).then((hasInput) { - if (hasInput) retVal.add(ngDepsUri); - }); + .wait(directives + .where(_isNotDartDirective) + .map((UriBasedDirective directive) { + var ngDepsUri = _toDepsUri(stringLiteralToString(directive.uri)); + var ngDepsAsset = uriToAssetId(entryPoint, ngDepsUri, logger, + null /* + span */ + ); + if (ngDepsAsset == entryPoint) return nullFuture; + return reader.hasInput(ngDepsAsset).then((hasInput) { + if (hasInput) { + retVal[directive] = ngDepsUri; + } + }, onError: (_) => null); })).then((_) => retVal); } diff --git a/modules/angular2/test/transform/directive_linker/simple_export_files/expected/bar.ng_deps.dart b/modules/angular2/test/transform/directive_linker/simple_export_files/expected/bar.ng_deps.dart index e137315242..fce1f6129d 100644 --- a/modules/angular2/test/transform/directive_linker/simple_export_files/expected/bar.ng_deps.dart +++ b/modules/angular2/test/transform/directive_linker/simple_export_files/expected/bar.ng_deps.dart @@ -2,9 +2,8 @@ library bar.ng_deps.dart; import 'bar.dart'; import 'package:angular2/src/core/annotations/annotations.dart'; -import 'foo.ng_deps.dart' as i0; - export 'foo.dart'; +import 'foo.ng_deps.dart' as i0; bool _visited = false; void initReflector(reflector) { diff --git a/modules/angular2/test/transform/integration/list_of_types_files/expected/bar.ng_deps.dart b/modules/angular2/test/transform/integration/list_of_types_files/expected/bar.ng_deps.dart index 97ebf50aec..ffe4af32be 100644 --- a/modules/angular2/test/transform/integration/list_of_types_files/expected/bar.ng_deps.dart +++ b/modules/angular2/test/transform/integration/list_of_types_files/expected/bar.ng_deps.dart @@ -2,9 +2,9 @@ library bar.ng_deps.dart; import 'bar.dart'; import 'package:angular2/src/core/annotations/annotations.dart'; +import 'package:angular2/src/core/annotations/annotations.ng_deps.dart' as i0; import 'foo.dart'; -import 'foo.ng_deps.dart' as i0; -import 'package:angular2/src/core/annotations/annotations.ng_deps.dart' as i1; +import 'foo.ng_deps.dart' as i1; bool _visited = false; void initReflector(reflector) { diff --git a/modules/angular2/test/transform/integration/simple_annotation_files/expected/index.ng_deps.dart b/modules/angular2/test/transform/integration/simple_annotation_files/expected/index.ng_deps.dart index fa799430e0..80832316d1 100644 --- a/modules/angular2/test/transform/integration/simple_annotation_files/expected/index.ng_deps.dart +++ b/modules/angular2/test/transform/integration/simple_annotation_files/expected/index.ng_deps.dart @@ -2,11 +2,11 @@ library web_foo.ng_deps.dart; import 'index.dart'; import 'package:angular2/src/core/application.dart'; +import 'package:angular2/src/core/application.ng_deps.dart' as i0; import 'package:angular2/src/reflection/reflection.dart'; import 'index.ng_deps.dart' as ngStaticInit0; import 'bar.dart'; -import 'bar.ng_deps.dart' as i0; -import 'package:angular2/src/core/application.ng_deps.dart' as i1; +import 'bar.ng_deps.dart' as i1; bool _visited = false; void initReflector(reflector) { diff --git a/modules/angular2/test/transform/integration/two_annotations_files/expected/bar.ng_deps.dart b/modules/angular2/test/transform/integration/two_annotations_files/expected/bar.ng_deps.dart index 88804a9484..7934a9aa8e 100644 --- a/modules/angular2/test/transform/integration/two_annotations_files/expected/bar.ng_deps.dart +++ b/modules/angular2/test/transform/integration/two_annotations_files/expected/bar.ng_deps.dart @@ -2,9 +2,9 @@ library bar.ng_deps.dart; import 'bar.dart'; import 'package:angular2/src/core/annotations/annotations.dart'; +import 'package:angular2/src/core/annotations/annotations.ng_deps.dart' as i0; import 'package:angular2/src/core/annotations/view.dart'; -import 'package:angular2/src/core/annotations/view.ng_deps.dart' as i0; -import 'package:angular2/src/core/annotations/annotations.ng_deps.dart' as i1; +import 'package:angular2/src/core/annotations/view.ng_deps.dart' as i1; bool _visited = false; void initReflector(reflector) { diff --git a/modules/angular2/test/transform/integration/two_deps_files/expected/bar.ng_deps.dart b/modules/angular2/test/transform/integration/two_deps_files/expected/bar.ng_deps.dart index f4dbd5a7cb..4057de1c53 100644 --- a/modules/angular2/test/transform/integration/two_deps_files/expected/bar.ng_deps.dart +++ b/modules/angular2/test/transform/integration/two_deps_files/expected/bar.ng_deps.dart @@ -2,9 +2,9 @@ library bar.ng_deps.dart; import 'bar.dart'; import 'package:angular2/src/core/annotations/annotations.dart'; +import 'package:angular2/src/core/annotations/annotations.ng_deps.dart' as i0; import 'foo.dart' as prefix; -import 'foo.ng_deps.dart' as i0; -import 'package:angular2/src/core/annotations/annotations.ng_deps.dart' as i1; +import 'foo.ng_deps.dart' as i1; bool _visited = false; void initReflector(reflector) {