change to source-order crawling of directives instead of alphabetical
R=sigmund@google.com
Review URL: https://codereview.chromium.org//1018643002
diff --git a/.status b/.status
index 1aea97f..5fc034b 100644
--- a/.status
+++ b/.status
@@ -21,6 +21,7 @@
build/test/initializer_custom_filter_test: Skip
build/test/initializer_cycle_error_test: Skip
build/test/initializer_test: Skip
+build/test/initializer_parts_test: Skip
build/test/initializer_type_filter_test: Skip
build/test/init_method_test: Skip
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 583e378..0282c7c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,10 @@
+## 0.5.1+7
+
+* Change to source order-crawling of directives instead of alphabetical. The one
+exception is for `part` directives, those are still crawled in alphabetical
+order since we can't currently get the original source order from the mirror
+system.
+
## 0.5.1+6
* Fix some analyzer warnings.
diff --git a/lib/src/mirror_loader.dart b/lib/src/mirror_loader.dart
index ba49566..1caf144 100644
--- a/lib/src/mirror_loader.dart
+++ b/lib/src/mirror_loader.dart
@@ -98,7 +98,7 @@
librariesSeen.add(lib);
// First visit all our dependencies.
- for (var dependency in _sortedLibraryDependencies(lib)) {
+ for (var dependency in lib.libraryDependencies) {
// Skip dart: imports, they never use this package.
if (dependency.targetLibrary.uri.toString().startsWith('dart:')) continue;
if (librariesSeen.contains(dependency.targetLibrary)) continue;
@@ -110,7 +110,7 @@
_readAnnotations(lib, queue);
// Last, parse all class and method annotations.
- for (var declaration in _sortedLibraryDeclarations(lib)) {
+ for (var declaration in _sortedDeclarationsWithMetadata(lib)) {
_readAnnotations(declaration, queue);
// Check classes for static annotations which are not supported
if (declaration is ClassMirror) {
@@ -123,34 +123,37 @@
return queue;
}
- Iterable<LibraryDependencyMirror> _sortedLibraryDependencies(
- LibraryMirror lib) => new List.from(lib.libraryDependencies)
- ..sort((a, b) {
- var aScheme = a.targetLibrary.uri.scheme;
- var bScheme = b.targetLibrary.uri.scheme;
- if (aScheme != 'file' && bScheme == 'file') return -1;
- if (bScheme != 'file' && aScheme == 'file') return 1;
- return _relativeLibraryUri(a).compareTo(_relativeLibraryUri(b));
- });
-
- String _relativeLibraryUri(LibraryDependencyMirror lib) {
- if (lib.targetLibrary.uri.scheme == 'file' &&
- lib.sourceLibrary.uri.scheme == 'file') {
- return path.relative(lib.targetLibrary.uri.path,
- from: path.dirname(lib.sourceLibrary.uri.path));
- }
- return lib.targetLibrary.uri.toString();
+ Iterable<DeclarationMirror> _sortedDeclarationsWithMetadata(
+ LibraryMirror lib) {
+ return new List()
+ ..addAll(_sortDeclarations(
+ lib, lib.declarations.values.where(
+ (d) => d is MethodMirror && d.metadata.isNotEmpty)))
+ ..addAll(_sortDeclarations(
+ lib, lib.declarations.values.where(
+ (d) => d is ClassMirror && d.metadata.isNotEmpty)));
}
- Iterable<DeclarationMirror> _sortedLibraryDeclarations(LibraryMirror lib) =>
- lib.declarations.values
- .where((d) => d is ClassMirror || d is MethodMirror)
- .toList()
- ..sort((a, b) {
- if (a is MethodMirror && b is ClassMirror) return -1;
- if (a is ClassMirror && b is MethodMirror) return 1;
- return _declarationName(a).compareTo(_declarationName(b));
+ List<DeclarationMirror> _sortDeclarations(
+ LibraryMirror sourceLib, Iterable<DeclarationMirror> declarations) {
+ var declarationList = declarations.toList();
+ declarationList.sort((DeclarationMirror a, DeclarationMirror b) {
+ // If in the same file, compare by line.
+ var aSourceUri = a.location.sourceUri;
+ var bSourceUri = b.location.sourceUri;
+ if (aSourceUri == bSourceUri) {
+ return a.location.line.compareTo(b.location.line);
+ }
+
+ // Run parts first if one is from the original library.
+ if (aSourceUri == sourceLib.uri) return 1;
+ if (bSourceUri == sourceLib.uri) return -1;
+
+ // Sort parts alphabetically.
+ return aSourceUri.path.compareTo(bSourceUri.path);
});
+ return declarationList;
+ }
String _declarationName(DeclarationMirror declaration) =>
MirrorSystem.getName(declaration.qualifiedName);
diff --git a/lib/transformer.dart b/lib/transformer.dart
index 3d3a18c..8fec4b7 100644
--- a/lib/transformer.dart
+++ b/lib/transformer.dart
@@ -351,46 +351,53 @@
/// [lib]. This includes exported methods from other libraries too.
List<FunctionElement> _topLevelMethodsOfLibrary(
LibraryElement library, Set<LibraryElement> seen) {
- var result = [];
- result.addAll(library.units.expand((u) => u.functions));
- for (var export in library.exports) {
+ var methods = [];
+
+ var orderedExports = new List.from(library.exports)
+ ..sort((a, b) => a.uriOffset.compareTo(b.uriOffset));
+ for (var export in orderedExports) {
if (seen.contains(export.exportedLibrary)) continue;
- var exported = _topLevelMethodsOfLibrary(export.exportedLibrary, seen);
- _filter(exported, export.combinators);
- result.addAll(exported);
+ methods.addAll(_topLevelMethodsOfLibrary(export.exportedLibrary, seen));
}
- result.sort((a, b) => a.name.compareTo(b.name));
- return result;
+
+ for (CompilationUnitElement unit in _orderedUnits(library)) {
+ methods.addAll(new List.from(unit.functions)
+ ..sort((a, b) => a.nameOffset.compareTo(b.nameOffset)));
+ }
+
+ return methods;
}
/// Retrieves all classes that are visible if you were to import [lib]. This
/// includes exported classes from other libraries.
List<ClassElement> _classesOfLibrary(
LibraryElement library, Set<LibraryElement> seen) {
- var result = [];
- result.addAll(library.units.expand((u) => u.types));
- for (var export in library.exports) {
+ var classes = [];
+
+ var orderedExports = new List.from(library.exports)
+ ..sort((a, b) => a.uriOffset.compareTo(b.uriOffset));
+ for (var export in orderedExports) {
if (seen.contains(export.exportedLibrary)) continue;
- var exported = _classesOfLibrary(export.exportedLibrary, seen);
- _filter(exported, export.combinators);
- result.addAll(exported);
+ classes.addAll(_classesOfLibrary(export.exportedLibrary, seen));
}
- result.sort((a, b) => a.name.compareTo(b.name));
- return result;
+
+ for (var unit in _orderedUnits(library)) {
+ classes.addAll(new List.from(unit.types)
+ ..sort((a, b) => a.nameOffset.compareTo(b.nameOffset)));
+ }
+
+ return classes;
}
- /// Filters [elements] that come from an export, according to its show/hide
- /// combinators. This modifies [elements] in place.
- void _filter(List<Element> elements, List<NamespaceCombinator> combinators) {
- for (var c in combinators) {
- if (c is ShowElementCombinator) {
- var show = c.shownNames.toSet();
- elements.retainWhere((e) => show.contains(e.displayName));
- } else if (c is HideElementCombinator) {
- var hide = c.hiddenNames.toSet();
- elements.removeWhere((e) => hide.contains(e.displayName));
- }
- }
+ List<CompilationUnitElement> _orderedUnits(LibraryElement library) {
+ var definingUnit = library.definingCompilationUnit;
+ // The first item is the source library, remove it for now.
+ return new List.from(library.units)
+ ..sort((a, b) {
+ if (a == definingUnit) return 1;
+ if (b == definingUnit) return -1;
+ return a.uri.compareTo(b.uri);
+ });
}
Iterable<LibraryElement> _sortedLibraryDependencies(LibraryElement library) {
@@ -402,32 +409,7 @@
return (new List.from(library.imports)
..addAll(library.exports)
- ..sort((a, b) {
- // dart: imports don't have a uri
- if (a.uri == null && b.uri != null) return -1;
- if (b.uri == null && a.uri != null) return 1;
- if (a.uri == null && b.uri == null) {
- return getLibrary(a).name.compareTo(getLibrary(b).name);
- }
-
- // package: imports next
- var aIsPackage = a.uri.startsWith('package:');
- var bIsPackage = b.uri.startsWith('package:');
- if (aIsPackage && !bIsPackage) {
- return -1;
- } else if (bIsPackage && !aIsPackage) {
- return 1;
- } else if (bIsPackage && aIsPackage) {
- return a.uri.compareTo(b.uri);
- }
-
- // And finally compare based on the relative uri if both are file paths.
- var aUri = path.url.relative(a.source.uri.path,
- from: path.url.dirname(library.source.uri.path));
- var bUri = path.url.relative(b.source.uri.path,
- from: path.url.dirname(library.source.uri.path));
- return aUri.compareTo(bUri);
- })).map(getLibrary);
+ ..sort((a, b) => a.nameOffset.compareTo(b.nameOffset))).map(getLibrary);
}
}
diff --git a/pubspec.yaml b/pubspec.yaml
index b418049..c2dc506 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
name: initialize
-version: 0.5.1+6
+version: 0.5.1+7
author: Polymer.dart Authors <web@dartlang.org>
description: Generic building blocks for doing static initialization.
homepage: https://github.com/dart-lang/initialize
@@ -25,6 +25,7 @@
entry_points:
- test/deferred_library_test.dart
- test/initializer_test.dart
+ - test/initializer_parts_test.dart
- test/initializer_cycle_error_test.dart
- test/initializer_custom_filter_test.dart
- test/initializer_type_filter_test.dart
diff --git a/test/foo/bar.dart b/test/foo/bar.dart
index 3889e35..ae9d27b 100644
--- a/test/foo/bar.dart
+++ b/test/foo/bar.dart
@@ -4,6 +4,7 @@
@initializeTracker
library initialize.test.foo.bar;
+export '../foo.dart';
import '../foo.dart';
import 'package:initialize/src/initialize_tracker.dart';
diff --git a/test/initializer_parts_test.dart b/test/initializer_parts_test.dart
new file mode 100644
index 0000000..bfba5e8
--- /dev/null
+++ b/test/initializer_parts_test.dart
@@ -0,0 +1,41 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+@initializeTracker
+library initialize.initializer_parts_test;
+
+import 'package:initialize/src/initialize_tracker.dart';
+import 'package:initialize/initialize.dart';
+import 'package:unittest/unittest.dart';
+import 'package:unittest/compact_vm_config.dart';
+
+part 'parts/foo.dart';
+part 'parts/bar.dart';
+
+main() {
+ useCompactVMConfiguration();
+
+ // Run all initializers.
+ run().then((_) {
+ test('parts', () {
+ var expectedNames = [
+ const LibraryIdentifier(#initialize.initializer_parts_test, null, 'initializer_parts_test.dart'),
+ bar2,
+ bar,
+ foo,
+ baz,
+ Bar2,
+ Bar,
+ Foo,
+ Baz,
+ ];
+ expect(InitializeTracker.seen, expectedNames);
+ });
+ });
+}
+
+@initializeTracker
+class Baz {}
+
+@initializeTracker
+baz() {}
diff --git a/test/initializer_test.dart b/test/initializer_test.dart
index 9b87a87..1488b1d 100644
--- a/test/initializer_test.dart
+++ b/test/initializer_test.dart
@@ -4,7 +4,6 @@
@initializeTracker
library initialize.initializer_test;
-import 'foo.dart';
import 'foo/bar.dart';
import 'package:initialize/src/initialize_tracker.dart';
import 'package:initialize/initialize.dart';
@@ -19,20 +18,20 @@
run().then((_) {
test('annotations are seen in post-order with superclasses first', () {
var expectedNames = [
- const LibraryIdentifier(#test_package.bar, 'test_package', 'bar.dart'),
- const LibraryIdentifier(#test_package.foo, 'test_package', 'foo.dart'),
const LibraryIdentifier(#initialize.test.foo, null, 'foo.dart'),
- foo,
fooBar,
+ foo,
Foo,
const LibraryIdentifier(#initialize.test.foo.bar, null, 'foo/bar.dart'),
bar,
Bar,
+ const LibraryIdentifier(#test_package.bar, 'test_package', 'bar.dart'),
+ const LibraryIdentifier(#test_package.foo, 'test_package', 'foo.dart'),
const LibraryIdentifier(
#initialize.initializer_test, null, 'initializer_test.dart'),
zap,
Zoop, // Zap extends Zoop, so Zoop comes first.
- Zap
+ Zap,
];
expect(InitializeTracker.seen, expectedNames);
});
diff --git a/test/parts/bar.dart b/test/parts/bar.dart
new file mode 100644
index 0000000..4aa5f5c
--- /dev/null
+++ b/test/parts/bar.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+part of initialize.initializer_parts_test;
+
+@initializeTracker
+class Bar2 {}
+
+@initializeTracker
+class Bar {}
+
+@initializeTracker
+bar2() {}
+
+@initializeTracker
+bar() {}
diff --git a/test/parts/foo.dart b/test/parts/foo.dart
new file mode 100644
index 0000000..2c0528f
--- /dev/null
+++ b/test/parts/foo.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+part of initialize.initializer_parts_test;
+
+@initializeTracker
+class Foo {}
+
+@initializeTracker
+foo() {}
diff --git a/test/transformer_test.dart b/test/transformer_test.dart
index e6dda99..8b43d45 100644
--- a/test/transformer_test.dart
+++ b/test/transformer_test.dart
@@ -280,6 +280,79 @@
}
''')
}, []);
+
+ testPhases('library parts and exports', phases, {
+ 'a|web/index.dart': '''
+ @constInit
+ library index;
+
+ import 'package:test_initializers/common.dart';
+ export 'export.dart';
+
+ part 'foo.dart';
+ part 'bar.dart';
+
+ @constInit
+ index() {};
+
+ @constInit
+ class Index {};
+ ''',
+ 'a|web/foo.dart': '''
+ part of index;
+
+ @constInit
+ foo() {};
+
+ @constInit
+ class Foo {};
+ ''',
+ 'a|web/bar.dart': '''
+ part of index;
+
+ @constInit
+ bar() {};
+
+ @constInit
+ class Bar {};
+ ''',
+ 'a|web/export.dart': '''
+ @constInit
+ library export;
+
+ import 'package:test_initializers/common.dart';
+
+ @constInit
+ class Export {};
+ ''',
+ // Mock out the Initialize package plus some initializers.
+ 'initialize|lib/initialize.dart': mockInitialize,
+ 'test_initializers|lib/common.dart': commonInitializers,
+ }, {
+ 'a|web/index.initialize.dart': formatter.format('''
+ import 'package:initialize/src/static_loader.dart';
+ import 'package:initialize/initialize.dart';
+ import 'index.dart' as i0;
+ import 'export.dart' as i1;
+ import 'package:test_initializers/common.dart' as i2;
+
+ main() {
+ initializers.addAll([
+ new InitEntry(i2.constInit, const LibraryIdentifier(#export, null, 'export.dart')),
+ new InitEntry(i2.constInit, i1.Export),
+ new InitEntry(i2.constInit, const LibraryIdentifier(#index, null, 'index.dart')),
+ new InitEntry(i2.constInit, i0.bar),
+ new InitEntry(i2.constInit, i0.foo),
+ new InitEntry(i2.constInit, i0.index),
+ new InitEntry(i2.constInit, i0.Bar),
+ new InitEntry(i2.constInit, i0.Foo),
+ new InitEntry(i2.constInit, i0.Index),
+ ]);
+
+ i0.main();
+ }
+ ''')
+ }, []);
}
class SkipConstructorsPlugin extends InitializerPlugin {
diff --git a/tool/all_tests.sh b/tool/all_tests.sh
index 4c0bb39..13ed73c 100755
--- a/tool/all_tests.sh
+++ b/tool/all_tests.sh
@@ -7,12 +7,24 @@
# Fast fail the script on failures.
set -e
-# Run the command-line tests.
+# Run the un-transformed command-line tests.
# TODO(jakemac): Add back once http://dartbug.com/22592 is fixed.
# dart test/deferred_library_test.dart
dart test/init_method_test.dart
dart test/initializer_custom_filter_test.dart
dart test/initializer_cycle_error_test.dart
dart test/initializer_test.dart
+dart test/initializer_parts_test.dart
dart test/initializer_type_filter_test.dart
dart test/transformer_test.dart
+
+pub build test --mode=debug
+
+# Run the transformed command-line tests.
+# TODO(jakemac): Add back once initialize supports deferred libraries.
+# dart test/deferred_library_test.dart
+dart build/test/init_method_test.initialize.dart
+dart build/test/initializer_custom_filter_test.initialize.dart
+dart build/test/initializer_test.initialize.dart
+dart build/test/initializer_parts_test.initialize.dart
+dart build/test/initializer_type_filter_test.initialize.dart