support more types of expressions
R=sigmund@google.com
Review URL: https://codereview.chromium.org//951463004
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a7ccf90..69b7cc8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,11 @@
+## 0.5.1
+
+* Added support for more types of expressions in constructor annotations. More
+specifically, any const expressions that evaluate to a `String`, `int`,
+`double`, or `bool` are now allowed. The evaluated value is what will be inlined
+in the bootstrap file in this case.
+
+
## 0.5.0
* The `InitializePluginTransformer` is gone in favor of a new
diff --git a/lib/build/initializer_plugin.dart b/lib/build/initializer_plugin.dart
index 035161e..f70e885 100644
--- a/lib/build/initializer_plugin.dart
+++ b/lib/build/initializer_plugin.dart
@@ -92,8 +92,6 @@
var constructor = annotation.constructorName == null
? ''
: '.${annotation.constructorName}';
- // TODO(jakemac): Support more than raw values here
- // https://github.com/dart-lang/static_init/issues/5
var args = buildArgumentList(annotation.arguments, pluginData);
return 'const $metaPrefix.${clazz}$constructor$args';
}
@@ -202,14 +200,8 @@
var logger = pluginData.logger;
var libraryPrefixes = pluginData.libraryPrefixes;
var buffer = new StringBuffer();
- if (expression is StringLiteral) {
- var value = expression.stringValue;
- if (value == null) {
- logger.error('Only const strings are allowed in initializer '
- 'expressions, found $expression');
- }
- value = value.replaceAll(r'\', r'\\').replaceAll(r"'", r"\'");
- buffer.write("'$value'");
+ if (expression is StringLiteral && expression.stringValue != null) {
+ buffer.write(_stringValue(expression.stringValue));
} else if (expression is BooleanLiteral ||
expression is DoubleLiteral ||
expression is IntegerLiteral ||
@@ -239,7 +231,7 @@
var element = expression.bestElement;
if (element == null || !element.isPublic) {
logger.error('Private constants are not supported in intializer '
- 'constructors, found $element.');
+ 'constructors, found $element.');
}
libraryPrefixes.putIfAbsent(
element.library, () => 'i${libraryPrefixes.length}');
@@ -256,10 +248,38 @@
} else {
logger.error('Unsupported argument to initializer constructor.');
}
+ } else if (expression is PropertyAccess) {
+ buffer.write(buildExpression(expression.target, pluginData));
+ buffer.write('.${expression.propertyName}');
+ } else if (expression is InstanceCreationExpression) {
+ logger.error('Unsupported expression in initializer, found $expression. '
+ 'Instance creation expressions are not supported (yet). Instead, '
+ 'please assign it to a const variable and use that instead.');
} else {
- logger.error('Only literals and identifiers are allowed for initializer '
- 'expressions, found $expression.');
+ // Try to evaluate the constant and use that.
+ var result = pluginData.resolver.evaluateConstant(
+ pluginData.initializer.targetElement.library, expression);
+ if (!result.isValid) {
+ logger.error('Invalid expression in initializer, found $expression. '
+ 'And got the following errors: ${result.errors}.');
+ }
+ var value = result.value.value;
+ if (value == null) {
+ logger.error('Unsupported expression in initializer, found '
+ '$expression. Please file a bug at '
+ 'https://github.com/dart-lang/initialize/issues');
+ }
+
+ if (value is String) value = _stringValue(value);
+ buffer.write(value);
}
return buffer.toString();
}
+
+ // Returns an expression for a string value. Wraps it in single quotes and
+ // escapes existing single quotes and escapes.
+ _stringValue(String value) {
+ value = value.replaceAll(r'\', r'\\').replaceAll(r"'", r"\'");
+ return "'$value'";
+ }
}
diff --git a/pubspec.yaml b/pubspec.yaml
index dea7882..59ca83e 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
name: initialize
-version: 0.5.0
+version: 0.5.1
author: Polymer.dart Authors <web@dartlang.org>
description: Generic building blocks for doing static initialization.
homepage: https://github.com/dart-lang/initialize
diff --git a/test/transformer_test.dart b/test/transformer_test.dart
index 12e3259..e90eefc 100644
--- a/test/transformer_test.dart
+++ b/test/transformer_test.dart
@@ -117,6 +117,8 @@
'a|web/index.dart': '''
@DynamicInit(foo)
@DynamicInit(Foo.foo)
+ @DynamicInit(bar.Foo.bar)
+ @DynamicInit(bar.Foo.foo)
@DynamicInit(const [foo, Foo.foo, 'foo'])
@DynamicInit(const {'foo': foo, 'Foo.foo': Foo.foo, 'bar': 'bar'})
@DynamicInit('foo')
@@ -124,19 +126,36 @@
@DynamicInit(null)
@DynamicInit(1)
@DynamicInit(1.1)
+ @DynamicInit('foo-\$x\${y}')
+ @DynamicInit(1 + 2)
+ @DynamicInit(1.0 + 0.2)
+ @DynamicInit(1 == 1)
@NamedArgInit(1, name: 'Bill')
library web_foo;
import 'package:test_initializers/common.dart';
import 'foo.dart';
+ import 'foo.dart' as bar;
+
+ const x = 'x';
+ const y = 'y';
+
+ class MyConst {
+ const MyConst;
+ }
''',
'a|web/foo.dart': '''
library foo;
const String foo = 'foo';
+ class Bar {
+ const Bar();
+ }
+
class Foo {
static foo = 'Foo.foo';
+ static bar = const Bar();
}
''',
// Mock out the Initialize package plus some initializers.
@@ -154,6 +173,8 @@
initializers.addAll([
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(i2.Foo.bar), 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')),
@@ -161,6 +182,10 @@
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.DynamicInit('foo-xy'), const LibraryIdentifier(#web_foo, null, 'index.dart')),
+ new InitEntry(const i1.DynamicInit(3), const LibraryIdentifier(#web_foo, null, 'index.dart')),
+ new InitEntry(const i1.DynamicInit(1.2), const LibraryIdentifier(#web_foo, null, 'index.dart')),
+ new InitEntry(const i1.DynamicInit(true), const LibraryIdentifier(#web_foo, null, 'index.dart')),
new InitEntry(const i1.NamedArgInit(1, name: 'Bill'), const LibraryIdentifier(#web_foo, null, 'index.dart')),
]);