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.
This commit is contained in:
Tim Blasi 2015-04-14 15:27:08 -07:00
parent e14543498c
commit fef1dee7aa
6 changed files with 53 additions and 39 deletions

View File

@ -2,6 +2,7 @@ library angular2.transform.directive_linker.linker;
import 'dart:async'; import 'dart:async';
import 'package:analyzer/analyzer.dart';
import 'package:angular2/src/transform/common/asset_reader.dart'; import 'package:angular2/src/transform/common/asset_reader.dart';
import 'package:angular2/src/transform/common/logging.dart'; import 'package:angular2/src/transform/common/logging.dart';
import 'package:angular2/src/transform/common/names.dart'; import 'package:angular2/src/transform/common/names.dart';
@ -13,32 +14,37 @@ import 'package:path/path.dart' as path;
Future<String> linkNgDeps(AssetReader reader, AssetId entryPoint) async { Future<String> linkNgDeps(AssetReader reader, AssetId entryPoint) async {
var parser = new Parser(reader); var parser = new Parser(reader);
NgDeps ngDeps = await parser.parse(entryPoint); NgDeps ngDeps = await parser.parse(entryPoint);
if (ngDeps == null) return null; if (ngDeps == null) return null;
if (ngDeps.imports.isEmpty) return ngDeps.code;
var depUris = <String>[] var allDeps = <UriBasedDirective>[]
..addAll(ngDeps.imports.map((i) => i.uri.stringValue)) ..addAll(ngDeps.imports)
..addAll(ngDeps.exports.map((i) => i.uri.stringValue)); ..addAll(ngDeps.exports)
var depList = await _processNgImports(reader, entryPoint, depUris); ..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 importBuf = new StringBuffer();
var declarationBuf = new StringBuffer(); var declarationBuf = new StringBuffer();
for (var i = 0; i < depList.length; ++i) { var code = ngDeps.code;
importBuf.write(''' var codeIdx = 0;
import '${depList[i]}' as i${i}; // Generate import statements for linked deps where necessary.
'''); for (var i = 0, it = allDeps.iterator; it.moveNext();) {
declarationBuf.write('i${i}.${SETUP_METHOD_NAME}(${REFLECTOR_VAR_NAME});'); 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; var declarationSeamIdx = ngDeps.setupMethod.end - 1;
return '${code.substring(0, importSeamIdx)}' return '$importBuf'
'$importBuf' '${code.substring(codeIdx, declarationSeamIdx)}'
'${code.substring(importSeamIdx, declarationSeamIdx)}'
'$declarationBuf' '$declarationBuf'
'${code.substring(declarationSeamIdx)}'; '${code.substring(declarationSeamIdx)}';
} }
@ -46,21 +52,30 @@ Future<String> linkNgDeps(AssetReader reader, AssetId entryPoint) async {
String _toDepsUri(String importUri) => String _toDepsUri(String importUri) =>
'${path.withoutExtension(importUri)}${DEPS_EXTENSION}'; '${path.withoutExtension(importUri)}${DEPS_EXTENSION}';
bool _isNotDartImport(String importUri) { bool _isNotDartDirective(UriBasedDirective directive) {
return !importUri.startsWith('dart:'); return !stringLiteralToString(directive.uri).startsWith('dart:');
} }
Future<List<String>> _processNgImports( /// Maps each input [UriBasedDirective] to its associated `.ng_deps.dart`
AssetReader reader, AssetId entryPoint, Iterable<String> imports) { /// file, if it exists.
Future<Map<UriBasedDirective, String>> _processNgImports(AssetReader reader,
AssetId entryPoint, Iterable<UriBasedDirective> directives) {
final nullFuture = new Future.value(null); final nullFuture = new Future.value(null);
var retVal = <String>[]; final retVal = <UriBasedDirective, String>{};
return Future return Future
.wait(imports.where(_isNotDartImport).map(_toDepsUri).map((ngDepsUri) { .wait(directives
var importAsset = .where(_isNotDartDirective)
uriToAssetId(entryPoint, ngDepsUri, logger, null /* span */); .map((UriBasedDirective directive) {
if (importAsset == entryPoint) return nullFuture; var ngDepsUri = _toDepsUri(stringLiteralToString(directive.uri));
return reader.hasInput(importAsset).then((hasInput) { var ngDepsAsset = uriToAssetId(entryPoint, ngDepsUri, logger,
if (hasInput) retVal.add(ngDepsUri); null /*
}); span */
);
if (ngDepsAsset == entryPoint) return nullFuture;
return reader.hasInput(ngDepsAsset).then((hasInput) {
if (hasInput) {
retVal[directive] = ngDepsUri;
}
}, onError: (_) => null);
})).then((_) => retVal); })).then((_) => retVal);
} }

View File

@ -2,9 +2,8 @@ library bar.ng_deps.dart;
import 'bar.dart'; import 'bar.dart';
import 'package:angular2/src/core/annotations/annotations.dart'; import 'package:angular2/src/core/annotations/annotations.dart';
import 'foo.ng_deps.dart' as i0;
export 'foo.dart'; export 'foo.dart';
import 'foo.ng_deps.dart' as i0;
bool _visited = false; bool _visited = false;
void initReflector(reflector) { void initReflector(reflector) {

View File

@ -2,9 +2,9 @@ library bar.ng_deps.dart;
import 'bar.dart'; import 'bar.dart';
import 'package:angular2/src/core/annotations/annotations.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.dart';
import 'foo.ng_deps.dart' as i0; import 'foo.ng_deps.dart' as i1;
import 'package:angular2/src/core/annotations/annotations.ng_deps.dart' as i1;
bool _visited = false; bool _visited = false;
void initReflector(reflector) { void initReflector(reflector) {

View File

@ -2,11 +2,11 @@ library web_foo.ng_deps.dart;
import 'index.dart'; import 'index.dart';
import 'package:angular2/src/core/application.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 'package:angular2/src/reflection/reflection.dart';
import 'index.ng_deps.dart' as ngStaticInit0; import 'index.ng_deps.dart' as ngStaticInit0;
import 'bar.dart'; import 'bar.dart';
import 'bar.ng_deps.dart' as i0; import 'bar.ng_deps.dart' as i1;
import 'package:angular2/src/core/application.ng_deps.dart' as i1;
bool _visited = false; bool _visited = false;
void initReflector(reflector) { void initReflector(reflector) {

View File

@ -2,9 +2,9 @@ library bar.ng_deps.dart;
import 'bar.dart'; import 'bar.dart';
import 'package:angular2/src/core/annotations/annotations.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.dart';
import 'package:angular2/src/core/annotations/view.ng_deps.dart' as i0; import 'package:angular2/src/core/annotations/view.ng_deps.dart' as i1;
import 'package:angular2/src/core/annotations/annotations.ng_deps.dart' as i1;
bool _visited = false; bool _visited = false;
void initReflector(reflector) { void initReflector(reflector) {

View File

@ -2,9 +2,9 @@ library bar.ng_deps.dart;
import 'bar.dart'; import 'bar.dart';
import 'package:angular2/src/core/annotations/annotations.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.dart' as prefix;
import 'foo.ng_deps.dart' as i0; import 'foo.ng_deps.dart' as i1;
import 'package:angular2/src/core/annotations/annotations.ng_deps.dart' as i1;
bool _visited = false; bool _visited = false;
void initReflector(reflector) { void initReflector(reflector) {