Report compile-time error on disallowed metadata values.

Closes #14548

R=karlklose@google.com

Review URL: https://codereview.chromium.org/1510863004.
This commit is contained in:
Johnni Winther 2015-12-09 15:48:38 +01:00
parent e03c395a8c
commit 7716ef5da1
5 changed files with 65 additions and 41 deletions

View file

@ -256,6 +256,8 @@ enum MessageKind {
INVALID_CONTINUE,
INVALID_FOR_IN,
INVALID_INITIALIZER,
INVALID_METADATA,
INVALID_METADATA_GENERIC,
INVALID_OVERRIDDEN_FIELD,
INVALID_OVERRIDDEN_GETTER,
INVALID_OVERRIDDEN_METHOD,
@ -2866,6 +2868,31 @@ main() => new C();
"The getter '#{name}' is implicitly declared by this field "
"in class '#{class}'."),
MessageKind.INVALID_METADATA:
const MessageTemplate(MessageKind.INVALID_METADATA,
"A metadata annotation must be either a reference to a compile-time "
"constant variable or a call to a constant constructor.",
howToFix:
"Try using a different constant value or referencing it through a "
"constant variable.",
examples: const [
'@Object main() {}',
'@print main() {}']),
MessageKind.INVALID_METADATA_GENERIC:
const MessageTemplate(MessageKind.INVALID_METADATA_GENERIC,
"A metadata annotation using a constant constructor cannot use type "
"arguments.",
howToFix:
"Try removing the type arguments or referencing the constant "
"through a constant variable.",
examples: const ['''
class C<T> {
const C();
}
@C<int>() main() {}
''']),
MessageKind.EQUAL_MAP_ENTRY_KEY:
const MessageTemplate(MessageKind.EQUAL_MAP_ENTRY_KEY,
"An entry with the same key already exists in the map.",

View file

@ -21,6 +21,11 @@ import '../compiler.dart' show
Compiler;
import '../compile_time_constants.dart' show
ConstantCompiler;
import '../constants/expressions.dart' show
ConstantExpression,
ConstantExpressionKind,
ConstructedConstantExpression,
ErroneousConstantExpression;
import '../constants/values.dart' show
ConstantValue;
import '../core_types.dart' show
@ -1061,8 +1066,29 @@ class ResolverTask extends CompilerTask {
node.accept(visitor);
// TODO(johnniwinther): Avoid passing the [TreeElements] to
// [compileMetadata].
annotation.constant =
constantCompiler.compileMetadata(annotation, node, registry.mapping);
ConstantExpression constant = constantCompiler.compileMetadata(
annotation, node, registry.mapping);
switch (constant.kind) {
case ConstantExpressionKind.CONSTRUCTED:
ConstructedConstantExpression constructedConstant = constant;
if (constructedConstant.type.isGeneric) {
// Const constructor calls cannot have type arguments.
// TODO(24312): Remove this.
reporter.reportErrorMessage(
node, MessageKind.INVALID_METADATA_GENERIC);
constant = new ErroneousConstantExpression();
}
break;
case ConstantExpressionKind.VARIABLE:
case ConstantExpressionKind.ERRONEOUS:
break;
default:
reporter.reportErrorMessage(node, MessageKind.INVALID_METADATA);
constant = new ErroneousConstantExpression();
break;
}
annotation.constant = constant;
constantCompiler.evaluate(annotation.constant);
// TODO(johnniwinther): Register the relation between the annotation
// and the annotated element instead. This will allow the backend to

View file

@ -15,10 +15,9 @@ main() {
}
/// Singleline doc comment.
@Metadata // This is intentionally the type literal.
@Metadata(null)
// Singleline comment 1.
// Singleline comment 2.
@Metadata(null)
@Metadata(true)
@Metadata(false)
@Metadata(0)

View file

@ -169,7 +169,7 @@ void testFoo(MirrorSystem system, LibraryMirror helperLibrary,
var metadataList = fooClass.metadata;
Expect.isNotNull(metadataList);
Expect.equals(16, metadataList.length);
Expect.equals(14, metadataList.length);
var metadataListIndex = 0;
var metadata;
@ -192,28 +192,17 @@ void testFoo(MirrorSystem system, LibraryMirror helperLibrary,
Expect.stringEquals(
"Singleline doc comment.", metadata.trimmedText);
// @Metadata
// @Metadata(null)
metadata = metadataList[metadataListIndex++];
var metadataType = metadata.type;
Expect.isTrue(metadata is InstanceMirror);
Expect.isFalse(metadata.hasReflectee);
Expect.throws(() => metadata.reflectee, (_) => true);
Expect.isTrue(metadata is TypeInstanceMirror);
var metadataType = metadata.representedType;
Expect.isNotNull(metadataType);
Expect.equals(#Metadata, metadataType.simpleName);
// // This is intentionally the type literal.
metadata = metadataList[metadataListIndex++];
Expect.isTrue(metadata is InstanceMirror);
Expect.isFalse(metadata.hasReflectee);
Expect.throws(() => metadata.reflectee, (_) => true);
Expect.isTrue(metadata is CommentInstanceMirror);
Expect.equals(commentType.originalDeclaration, metadata.type);
Expect.isFalse(metadata.isDocComment);
Expect.stringEquals(
"// This is intentionally the type literal.", metadata.text);
Expect.stringEquals(
"This is intentionally the type literal.", metadata.trimmedText);
Expect.isTrue(metadataType.isOriginalDeclaration);
InstanceMirror data = metadata.getField(#data);
Expect.isNotNull(data);
Expect.isTrue(data.hasReflectee);
Expect.isNull(data.reflectee);
// Singleline comment 1.
metadata = metadataList[metadataListIndex++];
@ -241,17 +230,6 @@ void testFoo(MirrorSystem system, LibraryMirror helperLibrary,
Expect.stringEquals(
"Singleline comment 2.", metadata.trimmedText);
// @Metadata(null)
metadata = metadataList[metadataListIndex++];
Expect.isTrue(metadata is InstanceMirror);
Expect.isFalse(metadata.hasReflectee);
Expect.throws(() => metadata.reflectee, (_) => true);
Expect.equals(metadataType.originalDeclaration, metadata.type);
InstanceMirror data = metadata.getField(#data);
Expect.isNotNull(data);
Expect.isTrue(data.hasReflectee);
Expect.isNull(data.reflectee);
// @Metadata(true)
metadata = metadataList[metadataListIndex++];
Expect.isTrue(metadata is InstanceMirror);
@ -398,7 +376,7 @@ void testFoo(MirrorSystem system, LibraryMirror helperLibrary,
// leading comment.
Expect.equals(376, fooClassLocation.offset, "Unexpected offset");
// Expect the location to end with the class body.
Expect.equals(351, fooClassLocation.length, "Unexpected length");
Expect.equals(298, fooClassLocation.length, "Unexpected length");
Expect.equals(18, fooClassLocation.line, "Unexpected line");
Expect.equals(1, fooClassLocation.column, "Unexpected column");

View file

@ -64,12 +64,6 @@ mirrors/library_uri_io_test: SkipByDesign # Uses dart:io.
mirrors/load_library_test: RuntimeError # Issue 6335
mirrors/local_function_is_static_test: RuntimeError # Issue 6335
mirrors/lru_test: Skip # dart2js_native/lru_test is used instead
mirrors/metadata_allowed_values_test/01: MissingCompileTimeError # Issue 14548
mirrors/metadata_allowed_values_test/05: MissingCompileTimeError # Issue 14548
mirrors/metadata_allowed_values_test/10: MissingCompileTimeError # Issue 14548
mirrors/metadata_allowed_values_test/11: MissingCompileTimeError # Issue 14548
mirrors/metadata_allowed_values_test/13: MissingCompileTimeError # Issue 14548
mirrors/metadata_allowed_values_test/14: MissingCompileTimeError # Issue 14548
mirrors/metadata_scope_test/none: CompileTimeError # Issue 10905
mirrors/method_mirror_name_test: RuntimeError # Issue 6335
mirrors/method_mirror_properties_test: RuntimeError # Issue 11861