add LibraryIdentifier
R=sigmund@google.com
Review URL: https://codereview.chromium.org//880713002
diff --git a/CHANGELOG.md b/CHANGELOG.md
index de1d786..9937cb7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+## 0.3.0-dev
+
+* Library initializers now pass a `LibraryIdentifier` to `initialize` instead of
+just a `Symbol`. This provides the package, and path to the library in addition
+to the symbol so that paths can be normalized.
+
## 0.2.0
* `entryPoint` and `newEntryPoint` transformer options were renamed to
diff --git a/test/initialize_tracker.dart b/lib/src/initialize_tracker.dart
similarity index 100%
rename from test/initialize_tracker.dart
rename to lib/src/initialize_tracker.dart
diff --git a/lib/src/initializer.dart b/lib/src/initializer.dart
index 3ddf0cc..60a04d5 100644
--- a/lib/src/initializer.dart
+++ b/lib/src/initializer.dart
@@ -26,3 +26,23 @@
/// Typedef for a custom filter function.
typedef bool InitializerFilter(Initializer initializer);
+
+/// When annotating libraries, this is passed to the initializer.
+class LibraryIdentifier {
+ // The qualified name of the library.
+ final Symbol name;
+
+ // The package this library lives in. May be null if its the same as the root
+ // package.
+ final String package;
+
+ // The path to the library.
+ final String path;
+
+ const LibraryIdentifier(this.name, this.package, this.path);
+
+ bool operator ==(LibraryIdentifier other) =>
+ name == other.name && package == other.package && path == other.path;
+
+ String toString() => '$name: $package:$path';
+}
diff --git a/lib/src/mirror_loader.dart b/lib/src/mirror_loader.dart
index 1512ec9..f3e2689 100644
--- a/lib/src/mirror_loader.dart
+++ b/lib/src/mirror_loader.dart
@@ -145,7 +145,22 @@
annotatedValue = (declaration.owner as ObjectMirror)
.getField(declaration.simpleName).reflectee;
} else if (declaration is LibraryMirror) {
- annotatedValue = declaration.qualifiedName;
+ var package;
+ var filePath;
+ Uri uri = declaration.uri;
+ if (uri.scheme == 'file' || uri.scheme.startsWith('http')) {
+ filePath = path.url.relative(
+ uri.path, from: path.url.dirname(_root.uri.path));
+ } else if (uri.scheme == 'package') {
+ var segments = uri.pathSegments;
+ package = segments[0];
+ filePath = path.url.joinAll(segments.getRange(1, segments.length));
+ } else {
+ throw new UnsupportedError('Unsupported uri scheme ${uri.scheme} for '
+ 'library ${declaration}.');
+ }
+ annotatedValue =
+ new LibraryIdentifier(declaration.qualifiedName, package, filePath);
} else {
throw _UNSUPPORTED_DECLARATION;
}
diff --git a/lib/transformer.dart b/lib/transformer.dart
index 392d322..8036761 100644
--- a/lib/transformer.dart
+++ b/lib/transformer.dart
@@ -242,9 +242,10 @@
var initializersBuffer = new StringBuffer();
var libraryPrefixes = new Map<LibraryElement, String>();
- // Import the static_loader and original entry point.
+ // Import the static_loader, initializer, and original entry point.
importsBuffer
.writeln("import 'package:initialize/src/static_loader.dart';");
+ importsBuffer.writeln("import 'package:initialize/initialize.dart';");
libraryPrefixes[entryLib] = 'i0';
initializersBuffer.writeln(' initializers.addAll([');
@@ -300,7 +301,27 @@
final metaPrefix = libraryPrefixes[annotationElement.library];
var elementString;
if (element is LibraryElement) {
- elementString = '#${element.name}';
+ var segments = element.source.uri.pathSegments;
+ var package = segments[0];
+ var libraryPath;
+ var packageString;
+ if (_newEntryPoint.package == package &&
+ _newEntryPoint.path.startsWith('${segments[1]}/')) {
+ // reset `package` to null, we will do a relative path in this case.
+ packageString = 'null';
+ libraryPath = path.url.relative(
+ path.url.joinAll(segments.getRange(1, segments.length)),
+ from: path.url.dirname(path.url.join(_newEntryPoint.path)));
+ } else if (segments[1] == 'lib') {
+ packageString = "'$package'";
+ libraryPath = path.url.joinAll(segments.getRange(2, segments.length));
+ } else {
+ _logger.error('Unable to import `${element.source.uri.path}` from '
+ '${_newEntryPoint.path}.');
+ }
+
+ elementString = "const LibraryIdentifier("
+ "#${element.name}, $packageString, '$libraryPath')";
} else if (element is ClassElement || element is FunctionElement) {
elementString =
'${libraryPrefixes[data.element.library]}.${element.name}';
diff --git a/pubspec.yaml b/pubspec.yaml
index 25bc767..018cdef 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
name: initialize
-version: 0.2.0
+version: 0.3.0-dev
author: Polymer.dart Authors <web@dartlang.org>
description: Generic building blocks for doing static initialization.
homepage: https://github.com/dart-lang/initialize
@@ -9,6 +9,8 @@
html5lib: '>=0.12.0 <0.13.0'
path: '>=1.3.0 <2.0.0'
dev_dependencies:
+ test_package:
+ path: test_package
unittest: '>=0.10.0 <0.12.0'
environment:
sdk: '>=1.4.0 <2.0.0'
diff --git a/test/bar.dart b/test/bar.dart
index 664d4f7..dd83a8f 100644
--- a/test/bar.dart
+++ b/test/bar.dart
@@ -5,7 +5,7 @@
library initialize.test.bar;
import 'foo.dart';
-import 'initialize_tracker.dart';
+import 'package:initialize/src/initialize_tracker.dart';
// Foo should be initialized first.
@initializeTracker
diff --git a/test/cycle_a.dart b/test/cycle_a.dart
index b0d55da..6bc6d84 100644
--- a/test/cycle_a.dart
+++ b/test/cycle_a.dart
@@ -3,7 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
library initialize.test.cycle_a;
-import 'initialize_tracker.dart';
+import 'package:initialize/src/initialize_tracker.dart';
import 'cycle_b.dart';
@initializeTracker
diff --git a/test/cycle_b.dart b/test/cycle_b.dart
index 7dd9b5c..3af725d 100644
--- a/test/cycle_b.dart
+++ b/test/cycle_b.dart
@@ -3,7 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
library initialize.test.cycle_b;
-import 'initialize_tracker.dart';
+import 'package:initialize/src/initialize_tracker.dart';
import 'cycle_a.dart';
@initializeTracker
diff --git a/test/foo.dart b/test/foo.dart
index 6e5340c..a62e12f 100644
--- a/test/foo.dart
+++ b/test/foo.dart
@@ -4,7 +4,7 @@
@initializeTracker
library initialize.test.foo;
-import 'initialize_tracker.dart';
+import 'package:initialize/src/initialize_tracker.dart';
@initializeTracker
class Foo {}
diff --git a/test/initializer_custom_filter_test.dart b/test/initializer_custom_filter_test.dart
index ad54fee..f8f789d 100644
--- a/test/initializer_custom_filter_test.dart
+++ b/test/initializer_custom_filter_test.dart
@@ -7,7 +7,7 @@
import 'package:initialize/initialize.dart';
import 'package:unittest/unittest.dart';
import 'package:unittest/compact_vm_config.dart';
-import 'initialize_tracker.dart';
+import 'package:initialize/src/initialize_tracker.dart';
main() {
useCompactVMConfiguration();
diff --git a/test/initializer_test.dart b/test/initializer_test.dart
index 9426a9b..098628e 100644
--- a/test/initializer_test.dart
+++ b/test/initializer_test.dart
@@ -6,8 +6,9 @@
import 'foo.dart';
import 'bar.dart';
-import 'initialize_tracker.dart';
+import 'package:initialize/src/initialize_tracker.dart';
import 'package:initialize/initialize.dart';
+import 'package:test_package/foo.dart';
import 'package:unittest/unittest.dart';
import 'package:unittest/compact_vm_config.dart';
@@ -18,14 +19,17 @@
run().then((_) {
test('annotations are seen in post-order with superclasses first', () {
var expectedNames = [
- #initialize.test.foo,
+ 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,
- #initialize.test.bar,
+ const LibraryIdentifier(#initialize.test.bar, null, 'bar.dart'),
bar,
Bar,
- #initialize.initializer_test,
+ const LibraryIdentifier(
+ #initialize.initializer_test, null, 'initializer_test.dart'),
zap,
Zoop, // Zap extends Zoop, so Zoop comes first.
Zap
diff --git a/test/transformer_test.dart b/test/transformer_test.dart
index 62e2f65..a427e70 100644
--- a/test/transformer_test.dart
+++ b/test/transformer_test.dart
@@ -45,6 +45,7 @@
import 'package:initialize/initialize.dart';
import 'package:test_initializers/common.dart';
+ import 'baz.dart';
@DynamicInit('Bar')
@DynamicInit('Bar2')
@@ -54,6 +55,12 @@
@initMethod
bar() {}
''',
+ 'bar|lib/baz.dart': '''
+ @constInit
+ library baz;
+
+ import 'package:test_initializers/common.dart';
+ ''',
// Mock out the Initialize package plus some initializers.
'initialize|lib/initialize.dart': mockInitialize,
'test_initializers|lib/common.dart': commonInitializers,
@@ -65,29 +72,32 @@
</body></html>'''.replaceAll(' ', ''),
'a|web/index.bootstrap.dart': '''
import 'package:initialize/src/static_loader.dart';
+ import 'package:initialize/initialize.dart';
import 'index.dart' as i0;
- import 'package:bar/bar.dart' as i1;
+ import 'package:bar/baz.dart' as i1;
import 'package:test_initializers/common.dart' as i2;
- import 'package:initialize/initialize.dart' as i3;
- import 'foo.dart' as i4;
+ import 'package:bar/bar.dart' as i3;
+ import 'package:initialize/initialize.dart' as i4;
+ import 'foo.dart' as i5;
main() {
initializers.addAll([
- new InitEntry(const i2.DynamicInit('bar'), #bar),
- new InitEntry(const i2.DynamicInit('bar2'), #bar),
- new InitEntry(const i2.DynamicInit('bar()'), i1.bar),
- new InitEntry(i3.initMethod, i1.bar),
- new InitEntry(const i2.DynamicInit('Bar'), i1.Bar),
- new InitEntry(const i2.DynamicInit('Bar2'), i1.Bar),
- new InitEntry(i2.constInit, #foo),
- new InitEntry(i3.initMethod, i4.foo),
- new InitEntry(i2.constInit, i4.Foo),
+ new InitEntry(i2.constInit, const LibraryIdentifier(#baz, 'bar', 'baz.dart')),
+ new InitEntry(const i2.DynamicInit('bar'), const LibraryIdentifier(#bar, 'bar', 'bar.dart')),
+ new InitEntry(const i2.DynamicInit('bar2'), const LibraryIdentifier(#bar, 'bar', 'bar.dart')),
+ new InitEntry(const i2.DynamicInit('bar()'), i3.bar),
+ new InitEntry(i4.initMethod, i3.bar),
+ new InitEntry(const i2.DynamicInit('Bar'), i3.Bar),
+ new InitEntry(const i2.DynamicInit('Bar2'), i3.Bar),
+ new InitEntry(i2.constInit, const LibraryIdentifier(#foo, null, 'foo.dart')),
+ new InitEntry(i4.initMethod, i5.foo),
+ new InitEntry(i2.constInit, i5.Foo),
]);
i0.main();
}
'''.replaceAll(' ', '')
- });
+ }, []);
testPhases('constructor arguments', [[transformer]], {
'a|web/index.dart': '''
@@ -121,26 +131,27 @@
}, {
'a|web/index.bootstrap.dart': '''
import 'package:initialize/src/static_loader.dart';
+ import 'package:initialize/initialize.dart';
import 'index.dart' as i0;
import 'package:test_initializers/common.dart' as i1;
import 'foo.dart' as i2;
main() {
initializers.addAll([
- new InitEntry(const i1.DynamicInit(i2.foo), #web_foo),
- new InitEntry(const i1.DynamicInit(i2.Foo.foo), #web_foo),
- new InitEntry(const i1.DynamicInit(const [i2.foo, i2.Foo.foo, 'foo']), #web_foo),
- new InitEntry(const i1.DynamicInit(const {'foo': i2.foo, 'Foo.foo': i2.Foo.foo, 'bar': 'bar'}), #web_foo),
- new InitEntry(const i1.DynamicInit('foo'), #web_foo),
- new InitEntry(const i1.DynamicInit(true), #web_foo),
- new InitEntry(const i1.DynamicInit(null), #web_foo),
- new InitEntry(const i1.DynamicInit(1), #web_foo),
- new InitEntry(const i1.DynamicInit(1.1), #web_foo),
- new InitEntry(const i1.NamedArgInit(1, name: 'Bill'), #web_foo),
+ new InitEntry(const i1.DynamicInit(i2.foo), const LibraryIdentifier(#web_foo, null, 'index.dart')),
+ new InitEntry(const i1.DynamicInit(i2.Foo.foo), const LibraryIdentifier(#web_foo, null, 'index.dart')),
+ new InitEntry(const i1.DynamicInit(const [i2.foo, i2.Foo.foo, 'foo']), const LibraryIdentifier(#web_foo, null, 'index.dart')),
+ new InitEntry(const i1.DynamicInit(const {'foo': i2.foo, 'Foo.foo': i2.Foo.foo, 'bar': 'bar'}), const LibraryIdentifier(#web_foo, null, 'index.dart')),
+ new InitEntry(const i1.DynamicInit('foo'), const LibraryIdentifier(#web_foo, null, 'index.dart')),
+ new InitEntry(const i1.DynamicInit(true), const LibraryIdentifier(#web_foo, null, 'index.dart')),
+ new InitEntry(const i1.DynamicInit(null), const LibraryIdentifier(#web_foo, null, 'index.dart')),
+ new InitEntry(const i1.DynamicInit(1), const LibraryIdentifier(#web_foo, null, 'index.dart')),
+ new InitEntry(const i1.DynamicInit(1.1), const LibraryIdentifier(#web_foo, null, 'index.dart')),
+ new InitEntry(const i1.NamedArgInit(1, name: 'Bill'), const LibraryIdentifier(#web_foo, null, 'index.dart')),
]);
i0.main();
}
'''.replaceAll(' ', '')
- });
+ }, []);
}
diff --git a/test_package/README.md b/test_package/README.md
new file mode 100644
index 0000000..b5c2ddd
--- /dev/null
+++ b/test_package/README.md
@@ -0,0 +1,5 @@
+Initialize tests package
+========================
+
+Package used in the `initialize` packages tests. This is just a helper to make
+sure that it correctly normalizes urls in mirror mode.
diff --git a/test_package/lib/bar.dart b/test_package/lib/bar.dart
new file mode 100644
index 0000000..8cc6129
--- /dev/null
+++ b/test_package/lib/bar.dart
@@ -0,0 +1,7 @@
+// 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 test_package.bar;
+
+import 'package:initialize/src/initialize_tracker.dart';
diff --git a/test_package/lib/foo.dart b/test_package/lib/foo.dart
new file mode 100644
index 0000000..c1357f8
--- /dev/null
+++ b/test_package/lib/foo.dart
@@ -0,0 +1,8 @@
+// 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 test_package.foo;
+
+import 'bar.dart'; // Keep for the annotation
+import 'package:initialize/src/initialize_tracker.dart';
diff --git a/test_package/pubspec.yaml b/test_package/pubspec.yaml
new file mode 100644
index 0000000..438a6f9
--- /dev/null
+++ b/test_package/pubspec.yaml
@@ -0,0 +1,4 @@
+name: test_package
+dependencies:
+ initialize:
+ path: ../