Reland "[cfe] Build some annotations during outlining"
Reland the change to build some annotations during outlining, with a
bug fix. Annotations from patch classes and procedures were not
applied to the actual class or procedure, which is fixed.
The original commit was reviewed at
https://dart-review.googlesource.com/c/sdk/+/103806
The revert was reviewed at
https://dart-review.googlesource.com/c/sdk/+/104220
The original commit message was:
During the outline phase, after top-level type inference, compile
annotations for libraries, classes, fields, procedures, and
constructors.
Change-Id: I836160ddad4114ded72701e8a3938f703228931c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/104560
Commit-Queue: Kevin Millikin <kmillikin@google.com>
Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 3754d84..2d4fad3 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -2008,8 +2008,7 @@
}
}
- void finishFunction(
- List annotations, formals, AsyncMarker asyncModifier, FunctionBody body) {
+ void finishFunction(formals, AsyncMarker asyncModifier, FunctionBody body) {
debugEvent("finishFunction");
Statement bodyStatement;
diff --git a/pkg/front_end/lib/src/fasta/builder/class_builder.dart b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
index 05441e7..0ef4745 100644
--- a/pkg/front_end/lib/src/fasta/builder/class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
@@ -77,6 +77,8 @@
return library.partOfLibrary ?? library;
}
+ void buildAnnotations(LibraryBuilder library) {}
+
/// Registers a constructor redirection for this class and returns true if
/// this redirection gives rise to a cycle that has not been reported before.
bool checkConstructorCyclic(String source, String target) {
@@ -124,7 +126,7 @@
return constructors.lookup(name, charOffset, uri);
}
- void forEach(void f(String name, MemberBuilder builder)) {
+ void forEach(void f(String name, Declaration builder)) {
scope.forEach(f);
}
diff --git a/pkg/front_end/lib/src/fasta/builder/library_builder.dart b/pkg/front_end/lib/src/fasta/builder/library_builder.dart
index 9dbca65..ed544d6 100644
--- a/pkg/front_end/lib/src/fasta/builder/library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/library_builder.dart
@@ -235,6 +235,8 @@
}
void recordAccess(int charOffset, int length, Uri fileUri) {}
+
+ void buildAnnotations() {}
}
class LibraryLocalDeclarationIterator implements Iterator<Declaration> {
diff --git a/pkg/front_end/lib/src/fasta/builder/member_builder.dart b/pkg/front_end/lib/src/fasta/builder/member_builder.dart
index 827fe5f..2dd5099 100644
--- a/pkg/front_end/lib/src/fasta/builder/member_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/member_builder.dart
@@ -37,6 +37,8 @@
}
}
+ void buildAnnotations(LibraryBuilder library) {}
+
@override
String get fullNameForErrors => name;
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 6abe0c6..393be7d 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -601,25 +601,7 @@
// `invalid-type`.
buildDartType(pop()); // Type.
}
- List<Expression> annotations = pop();
- // Fields with duplicate names are sorted out in the else branch of the
- // `declaration.next == null` above.
- if (annotations != null && fields.isNotEmpty) {
- inferAnnotations(annotations);
- Field field = fields.first.target;
- // The first (and often only field) will not get a clone.
- for (int i = 0; i < annotations.length; i++) {
- field.addAnnotation(annotations[i]);
- }
- for (int i = 1; i < fields.length; i++) {
- // We have to clone the annotations on the remaining fields.
- field = fields[i].target;
- cloner ??= new CloneVisitor();
- for (Expression annotation in annotations) {
- field.addAnnotation(cloner.clone(annotation));
- }
- }
- }
+ pop(); // Annotations.
resolveRedirectingFactoryTargets();
finishVariableMetadata();
@@ -751,8 +733,8 @@
}
@override
- void finishFunction(List<Expression> annotations, FormalParameters formals,
- AsyncMarker asyncModifier, Statement body) {
+ void finishFunction(
+ FormalParameters formals, AsyncMarker asyncModifier, Statement body) {
debugEvent("finishFunction");
typePromoter?.finished();
@@ -903,11 +885,6 @@
..fileOffset = body.fileOffset;
}
}
- Member target = builder.target;
- inferAnnotations(annotations);
- for (Expression annotation in annotations ?? const []) {
- target.addAnnotation(annotation);
- }
if (builder is KernelConstructorBuilder) {
finishConstructor(builder, asyncModifier);
} else if (builder is KernelProcedureBuilder) {
@@ -1155,6 +1132,14 @@
return expression;
}
+ Expression parseAnnotation(Token token) {
+ Parser parser = new Parser(this);
+ token = parser.parseMetadata(parser.syntheticPreviousToken(token));
+ Expression annotation = pop();
+ checkEmpty(token.charOffset);
+ return annotation;
+ }
+
void finishConstructor(
KernelConstructorBuilder builder, AsyncMarker asyncModifier) {
/// Quotes below are from [Dart Programming Language Specification, 4th
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_body_builder.dart
index 1886808..c37724b 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_body_builder.dart
@@ -42,6 +42,27 @@
: forest = const Fangorn(),
super.forField(member, typeInferrer);
+ KernelBodyBuilder.forAnnotation(
+ KernelLibraryBuilder library,
+ KernelClassBuilder classBuilder,
+ ModifierBuilder member,
+ Scope scope,
+ Scope parameterScope,
+ Uri fileUri)
+ : forest = const Fangorn(),
+ super(
+ library,
+ member,
+ scope,
+ parameterScope,
+ library.loader.hierarchy,
+ library.loader.coreTypes,
+ classBuilder,
+ member?.isInstanceMember ?? false,
+ fileUri,
+ library.loader.typeInferenceEngine
+ ?.createLocalTypeInferrer(fileUri, null, library));
+
@override
void enterThenForTypePromotion(Expression condition) {
typePromoter?.enterThen(condition);
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
index 6ad083c..31214d6 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
@@ -105,6 +105,7 @@
Declaration,
KernelFunctionBuilder,
KernelLibraryBuilder,
+ KernelMetadataBuilder,
KernelNamedTypeBuilder,
KernelProcedureBuilder,
KernelRedirectingFactoryBuilder,
@@ -224,6 +225,19 @@
}
}
+ @override
+ void buildAnnotations(LibraryBuilder library) {
+ void build(String ignore, Declaration declaration) {
+ MemberBuilder member = declaration;
+ member.buildAnnotations(library);
+ }
+
+ KernelMetadataBuilder.buildAnnotations(
+ isPatch ? origin.target : cls, metadata, library, this, null, null);
+ constructors.forEach(build);
+ scope.forEach(build);
+ }
+
void checkSupertypes(CoreTypes coreTypes) {
// This method determines whether the class (that's being built) its super
// class appears both in 'extends' and 'implements' clauses and whether any
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart
index 904f47d..39c70c9 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart
@@ -23,7 +23,9 @@
FieldBuilder,
ImplicitFieldType,
KernelLibraryBuilder,
+ KernelMetadataBuilder,
KernelTypeBuilder,
+ LibraryBuilder,
MetadataBuilder;
import 'kernel_shadow_ast.dart' show ShadowField;
@@ -91,6 +93,13 @@
return field;
}
+ @override
+ void buildAnnotations(LibraryBuilder library) {
+ ClassBuilder classBuilder = isClassMember ? parent : null;
+ KernelMetadataBuilder.buildAnnotations(
+ field, metadata, library, classBuilder, this, null);
+ }
+
Field get target => field;
void prepareTopLevelInference() {
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
index 80db2c8..983b7c7 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
@@ -135,6 +135,7 @@
KernelTypeAliasBuilder,
KernelFunctionTypeBuilder,
KernelInvalidTypeBuilder,
+ KernelMetadataBuilder,
KernelMixinApplicationBuilder,
KernelNamedTypeBuilder,
KernelProcedureBuilder,
@@ -902,6 +903,12 @@
}
@override
+ void buildAnnotations() {
+ KernelMetadataBuilder.buildAnnotations(
+ library, metadata, this, null, null, null);
+ }
+
+ @override
void buildBuilder(Declaration declaration, LibraryBuilder coreLibrary) {
Class cls;
Member member;
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_metadata_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_metadata_builder.dart
index 7cfa901..7bc39e6 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_metadata_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_metadata_builder.dart
@@ -4,12 +4,48 @@
library fasta.kernel_metadata_builder;
-import 'kernel_builder.dart' show MetadataBuilder;
+import 'package:kernel/ast.dart' show Annotatable, Class, Library;
+
+import 'kernel_body_builder.dart' show KernelBodyBuilder;
+
+import 'kernel_builder.dart'
+ show
+ KernelClassBuilder,
+ KernelLibraryBuilder,
+ MetadataBuilder,
+ MemberBuilder;
import '../scanner.dart' show Token;
-class KernelMetadataBuilder extends MetadataBuilder {
- final int charOffset;
+import '../scope.dart' show Scope;
- KernelMetadataBuilder(Token beginToken) : charOffset = beginToken.charOffset;
+class KernelMetadataBuilder extends MetadataBuilder {
+ final Token beginToken;
+
+ int get charOffset => beginToken.charOffset;
+
+ KernelMetadataBuilder(this.beginToken);
+
+ static void buildAnnotations(
+ Annotatable parent,
+ List<MetadataBuilder> metadata,
+ KernelLibraryBuilder library,
+ KernelClassBuilder classBuilder,
+ MemberBuilder member,
+ Scope parameterScope) {
+ if (metadata == null) return;
+ Uri fileUri = member?.fileUri ?? classBuilder?.fileUri ?? library.fileUri;
+ Scope scope = parent is Library || parent is Class || classBuilder == null
+ ? library.scope
+ : classBuilder.scope;
+ KernelBodyBuilder bodyBuilder = new KernelBodyBuilder.forAnnotation(
+ library, classBuilder, member, scope, parameterScope, fileUri);
+ for (int i = 0; i < metadata.length; ++i) {
+ KernelMetadataBuilder annotationBuilder = metadata[i];
+ parent.addAnnotation(
+ bodyBuilder.parseAnnotation(annotationBuilder.beginToken));
+ }
+ bodyBuilder.inferAnnotations(parent.annotations);
+ bodyBuilder.resolveRedirectingFactoryTargets();
+ }
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart
index 2434d09..c8d217b 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart
@@ -65,6 +65,7 @@
FormalParameterBuilder,
KernelFormalParameterBuilder,
KernelLibraryBuilder,
+ KernelMetadataBuilder,
KernelTypeBuilder,
KernelTypeVariableBuilder,
LibraryBuilder,
@@ -361,6 +362,18 @@
return procedure;
}
+ @override
+ void buildAnnotations(LibraryBuilder library) {
+ ClassBuilder classBuilder = isClassMember ? parent : null;
+ KernelMetadataBuilder.buildAnnotations(
+ target,
+ metadata,
+ library,
+ classBuilder,
+ this,
+ computeFormalParameterScope(classBuilder?.scope ?? library.scope));
+ }
+
Procedure get target => origin.procedure;
@override
@@ -483,6 +496,18 @@
return constructor;
}
+ @override
+ void buildAnnotations(LibraryBuilder library) {
+ ClassBuilder classBuilder = isClassMember ? parent : null;
+ KernelMetadataBuilder.buildAnnotations(
+ target,
+ metadata,
+ library,
+ classBuilder,
+ this,
+ computeFormalParameterScope(classBuilder?.scope ?? library.scope));
+ }
+
FunctionNode buildFunction(LibraryBuilder library) {
// According to the specification §9.3 the return type of a constructor
// function is its enclosing class.
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
index 49d0344..83e30e9 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -279,6 +279,7 @@
loader.checkRedirectingFactories(myClasses);
loader.addNoSuchMethodForwarders(myClasses);
loader.checkMixins(myClasses);
+ loader.buildAnnotations();
installAllComponentProblems(loader.allComponentProblems);
loader.allComponentProblems.clear();
return component;
diff --git a/pkg/front_end/lib/src/fasta/source/diet_listener.dart b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
index 1125c14..cf3c27f 100644
--- a/pkg/front_end/lib/src/fasta/source/diet_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
@@ -363,10 +363,8 @@
@override
void endLibraryName(Token libraryKeyword, Token semicolon) {
debugEvent("endLibraryName");
- pop(); // name
-
- Token metadata = pop();
- parseMetadata(library, metadata, library.target);
+ pop(); // Name.
+ pop(); // Annotations.
}
@override
@@ -537,7 +535,6 @@
ProcedureBuilder builder = lookupConstructor(beginToken, name);
if (bodyToken == null || optional("=", bodyToken.endGroup.next)) {
- parseMetadata(builder, metadata, builder.target);
buildRedirectingFactoryMethod(
bodyToken, builder, MemberKind.Factory, metadata);
} else {
@@ -709,18 +706,14 @@
debugEvent("beginClassOrMixinBody");
Token beginToken = pop();
Object name = pop();
- Token metadata = pop();
+ pop(); // Annotation begin token.
assert(currentClass == null);
assert(memberScope == library.scope);
if (name is ParserRecovery) {
currentClassIsParserRecovery = true;
return;
}
-
- Declaration classBuilder = lookupBuilder(beginToken, null, name);
- parseMetadata(classBuilder, metadata, classBuilder.target);
-
- currentClass = classBuilder;
+ currentClass = lookupBuilder(beginToken, null, name);
memberScope = currentClass.scope;
}
@@ -747,26 +740,9 @@
@override
void endEnum(Token enumKeyword, Token leftBrace, int count) {
debugEvent("Enum");
- List<Object> metadataAndValues =
- const FixedNullableList<Object>().pop(stack, count * 2);
- Object name = pop();
- Token metadata = pop();
- checkEmpty(enumKeyword.charOffset);
- if (name is ParserRecovery) return;
-
- ClassBuilder enumBuilder = lookupBuilder(enumKeyword, null, name);
- parseMetadata(enumBuilder, metadata, enumBuilder.target);
- if (metadataAndValues != null) {
- for (int i = 0; i < metadataAndValues.length; i += 2) {
- Token metadata = metadataAndValues[i];
- String valueName = metadataAndValues[i + 1];
- Declaration declaration = enumBuilder.scope.local[valueName];
- if (metadata != null) {
- parseMetadata(declaration, metadata, declaration.target);
- }
- }
- }
-
+ const FixedNullableList<Object>().pop(stack, count * 2);
+ pop(); // Name.
+ pop(); // Annotations begin token.
checkEmpty(enumKeyword.charOffset);
}
@@ -775,20 +751,9 @@
Token equals, Token implementsKeyword, Token endToken) {
debugEvent("NamedMixinApplication");
- Object name = pop();
- Token metadata = pop();
+ pop(); // Name.
+ pop(); // Annotations begin token.
checkEmpty(beginToken.charOffset);
- if (name is ParserRecovery) return;
-
- Declaration classBuilder = library.scopeBuilder[name];
- if (classBuilder != null) {
- // TODO(ahe): We shouldn't have to check for null here. The problem is
- // that we don't create a named mixin application if the mixins or
- // supertype are missing. Could we create a class instead? The nested
- // declarations wouldn't match up.
- parseMetadata(classBuilder, metadata, classBuilder.target);
- checkEmpty(beginToken.charOffset);
- }
}
AsyncMarker getAsyncMarker(StackListener listener) => listener.pop();
@@ -800,13 +765,11 @@
void listenerFinishFunction(
StackListener listener,
Token token,
- Token metadata,
MemberKind kind,
- List metadataConstants,
dynamic formals,
AsyncMarker asyncModifier,
dynamic body) {
- listener.finishFunction(metadataConstants, formals, asyncModifier, body);
+ listener.finishFunction(formals, asyncModifier, body);
}
/// Invokes the listener's [finishFields] method.
@@ -823,10 +786,9 @@
Token token = startToken;
try {
Parser parser = new Parser(listener);
- List metadataConstants;
if (metadata != null) {
parser.parseMetadataStar(parser.syntheticPreviousToken(metadata));
- metadataConstants = listener.pop();
+ listener.pop(); // Annotations.
}
token = parser.parseFormalParametersOpt(
parser.syntheticPreviousToken(token), kind);
@@ -840,8 +802,8 @@
parser.parseFunctionBody(token, isExpression, allowAbstract);
var body = listener.pop();
listener.checkEmpty(token.charOffset);
- listenerFinishFunction(listener, startToken, metadata, kind,
- metadataConstants, formals, asyncModifier, body);
+ listenerFinishFunction(
+ listener, startToken, kind, formals, asyncModifier, body);
} on DebugAbort {
rethrow;
} catch (e, s) {
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index 88e4621..adffcbd 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -82,6 +82,7 @@
KernelProcedureBuilder,
KernelTypeBuilder,
LibraryBuilder,
+ MemberBuilder,
NamedTypeBuilder,
TypeBuilder;
@@ -947,6 +948,23 @@
ticker.logMs("Checked mixin declaration applications");
}
+ void buildAnnotations() {
+ builders.forEach((Uri uri, LibraryBuilder library) {
+ if (library.loader == this) {
+ library.buildAnnotations();
+ Iterator<Declaration> iterator = library.iterator;
+ while (iterator.moveNext()) {
+ Declaration declaration = iterator.current;
+ if (declaration is ClassBuilder) {
+ declaration.buildAnnotations(library);
+ } else if (declaration is MemberBuilder) {
+ declaration.buildAnnotations(library);
+ }
+ }
+ }
+ });
+ }
+
ClassHierarchyBuilder buildClassHierarchy(
List<SourceClassBuilder> sourceClasses, ClassBuilder objectClass) {
ClassHierarchyBuilder hierarchy = ClassHierarchyBuilder.build(
diff --git a/pkg/front_end/lib/src/fasta/source/stack_listener.dart b/pkg/front_end/lib/src/fasta/source/stack_listener.dart
index db6a7cd..443b623 100644
--- a/pkg/front_end/lib/src/fasta/source/stack_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/stack_listener.dart
@@ -86,8 +86,8 @@
// TODO(ahe): This doesn't belong here. Only implemented by body_builder.dart
// and ast_builder.dart.
- void finishFunction(covariant List<Object> annotations, covariant formals,
- AsyncMarker asyncModifier, covariant body) {
+ void finishFunction(
+ covariant formals, AsyncMarker asyncModifier, covariant body) {
return unsupported("finishFunction", -1, uri);
}
diff --git a/pkg/front_end/testcases/annotation_on_enum_values.dart.outline.expect b/pkg/front_end/testcases/annotation_on_enum_values.dart.outline.expect
index 319403e..a04857a 100644
--- a/pkg/front_end/testcases/annotation_on_enum_values.dart.outline.expect
+++ b/pkg/front_end/testcases/annotation_on_enum_values.dart.outline.expect
@@ -11,7 +11,9 @@
final field core::int index;
final field core::String _name;
static const field core::List<self::Foo> values = const <self::Foo>[self::Foo::bar, self::Foo::baz, self::Foo::cafebabe];
+ @self::hest
static const field self::Foo bar = const self::Foo::•(0, "Foo.bar");
+ @self::Fisk::fisk<dynamic>(self::hest)
static const field self::Foo baz = const self::Foo::•(1, "Foo.baz");
static const field self::Foo cafebabe = const self::Foo::•(2, "Foo.cafebabe");
const constructor •(core::int index, core::String _name) → self::Foo
diff --git a/pkg/front_end/testcases/annotation_top.dart.outline.expect b/pkg/front_end/testcases/annotation_top.dart.outline.expect
index 6839b80..579ecba 100644
--- a/pkg/front_end/testcases/annotation_top.dart.outline.expect
+++ b/pkg/front_end/testcases/annotation_top.dart.outline.expect
@@ -1,3 +1,5 @@
+@test::a
+@test::A::•(1)
library test;
import self as self;
import "dart:core" as core;
@@ -8,12 +10,20 @@
const constructor •(core::int value) → self::A
;
}
+@self::a
+@self::A::•(2)
class C extends core::Object {
synthetic constructor •() → self::C
;
}
static const field core::Object a;
+@self::a
+@self::A::•(3)
static field core::int f1;
+@self::a
+@self::A::•(3)
static field core::int f2;
+@self::a
+@self::A::•(4)
static method main() → void
;
diff --git a/pkg/front_end/testcases/bug33099.dart.outline.expect b/pkg/front_end/testcases/bug33099.dart.outline.expect
index 42a5b20..24e4823 100644
--- a/pkg/front_end/testcases/bug33099.dart.outline.expect
+++ b/pkg/front_end/testcases/bug33099.dart.outline.expect
@@ -12,6 +12,7 @@
class MyTest extends core::Object {
synthetic constructor •() → self::MyTest
;
+ @self::failingTest
method foo() → void
;
}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.outline.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.outline.expect
index 459d870..6ddb363 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.outline.expect
@@ -8,10 +8,12 @@
const constructor named(core::List<core::String> l) → self::Foo
;
}
+@self::Foo::•(const <dynamic>[])
class Bar extends core::Object {
synthetic constructor •() → self::Bar
;
}
+@self::Foo::named(const <dynamic>[])
class Baz extends core::Object {
synthetic constructor •() → self::Baz
;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.outline.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.outline.expect
index b4da95f..62d5559 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.outline.expect
@@ -7,9 +7,12 @@
;
}
abstract class Bar extends core::Object {
+ @self::Foo::•(const <dynamic>[])
field dynamic x;
+ @self::Foo::•(const <dynamic>[])
constructor •() → self::Bar
;
+ @self::Foo::•(const <dynamic>[])
abstract method f() → void;
}
static method main() → dynamic
diff --git a/pkg/front_end/testcases/inference/override_equals.dart.outline.expect b/pkg/front_end/testcases/inference/override_equals.dart.outline.expect
index bf42edb..41bfd6e 100644
--- a/pkg/front_end/testcases/inference/override_equals.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/override_equals.dart.outline.expect
@@ -5,6 +5,7 @@
class NullEquality extends core::Object {
synthetic constructor •() → self::NullEquality
;
+ @core::override
operator ==(core::Object other) → core::Null
;
}
diff --git a/pkg/front_end/testcases/metadata_enum.dart.outline.expect b/pkg/front_end/testcases/metadata_enum.dart.outline.expect
index 6fd993b..1ecf0f8 100644
--- a/pkg/front_end/testcases/metadata_enum.dart.outline.expect
+++ b/pkg/front_end/testcases/metadata_enum.dart.outline.expect
@@ -2,6 +2,7 @@
import self as self;
import "dart:core" as core;
+@self::a
class E extends core::Object {
final field core::int index;
final field core::String _name;
diff --git a/pkg/front_end/testcases/metadata_named_mixin_application.dart.outline.expect b/pkg/front_end/testcases/metadata_named_mixin_application.dart.outline.expect
index cec02ba..ec64387 100644
--- a/pkg/front_end/testcases/metadata_named_mixin_application.dart.outline.expect
+++ b/pkg/front_end/testcases/metadata_named_mixin_application.dart.outline.expect
@@ -2,6 +2,7 @@
import self as self;
import "dart:core" as core;
+@self::a
class C = self::D with self::E {
synthetic constructor •() → self::C
: super self::D::•()
diff --git a/pkg/front_end/testcases/native_as_name.dart.outline.expect b/pkg/front_end/testcases/native_as_name.dart.outline.expect
index 6c2884c..b78f8ae 100644
--- a/pkg/front_end/testcases/native_as_name.dart.outline.expect
+++ b/pkg/front_end/testcases/native_as_name.dart.outline.expect
@@ -21,6 +21,7 @@
class Y2 extends self::Y1 {
synthetic constructor •() → self::Y2
;
+ @core::override
get native() → core::String
;
}
diff --git a/pkg/front_end/testcases/override_check_generic_method_f_bounded.dart.outline.expect b/pkg/front_end/testcases/override_check_generic_method_f_bounded.dart.outline.expect
index 9051099..cc16f53 100644
--- a/pkg/front_end/testcases/override_check_generic_method_f_bounded.dart.outline.expect
+++ b/pkg/front_end/testcases/override_check_generic_method_f_bounded.dart.outline.expect
@@ -14,6 +14,7 @@
class Hest extends core::Object implements self::Bar {
synthetic constructor •() → self::Hest
;
+ @core::override
method fisk<U extends self::Foo<self::Hest::fisk::U> = dynamic>() → void
;
}
diff --git a/pkg/front_end/testcases/rasta/issue_000033.dart.outline.expect b/pkg/front_end/testcases/rasta/issue_000033.dart.outline.expect
index 6a28c0d..44fbbbc 100644
--- a/pkg/front_end/testcases/rasta/issue_000033.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/issue_000033.dart.outline.expect
@@ -1,5 +1,15 @@
library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/rasta/issue_000033.dart:5:2: Warning: Method not found: 'JS'.
+// @JS()
+// ^^
+//
import self as self;
+@invalid-expression "pkg/front_end/testcases/rasta/issue_000033.dart:5:2: Error: Method not found: 'JS'.
+@JS()
+ ^^"
static method main() → dynamic
;
diff --git a/pkg/front_end/testcases/redirecting_factory_metadata.dart.outline.expect b/pkg/front_end/testcases/redirecting_factory_metadata.dart.outline.expect
index 5b95c2b..dc87a52 100644
--- a/pkg/front_end/testcases/redirecting_factory_metadata.dart.outline.expect
+++ b/pkg/front_end/testcases/redirecting_factory_metadata.dart.outline.expect
@@ -6,6 +6,7 @@
static field dynamic _redirecting# = <dynamic>[self::Foo::•];
constructor named(dynamic p) → self::Foo
;
+ @self::forFactoryItself
static factory •(dynamic p) → self::Foo
let dynamic #redirecting_factory = self::Foo::named in invalid-expression;
}
diff --git a/pkg/front_end/testcases/regress/issue_36793.dart.legacy.expect b/pkg/front_end/testcases/regress/issue_36793.dart.legacy.expect
index 4735cfe..69ebf3f 100644
--- a/pkg/front_end/testcases/regress/issue_36793.dart.legacy.expect
+++ b/pkg/front_end/testcases/regress/issue_36793.dart.legacy.expect
@@ -13,6 +13,7 @@
import "dart:core" as core;
static const field core::int y = 42;
+@self::y
static field core::int x;
static method main() → dynamic {
core::print(self::y);
diff --git a/pkg/front_end/testcases/regress/issue_36793.dart.legacy.transformed.expect b/pkg/front_end/testcases/regress/issue_36793.dart.legacy.transformed.expect
index 4735cfe..69ebf3f 100644
--- a/pkg/front_end/testcases/regress/issue_36793.dart.legacy.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_36793.dart.legacy.transformed.expect
@@ -13,6 +13,7 @@
import "dart:core" as core;
static const field core::int y = 42;
+@self::y
static field core::int x;
static method main() → dynamic {
core::print(self::y);
diff --git a/pkg/front_end/testcases/regress/issue_36793.dart.outline.expect b/pkg/front_end/testcases/regress/issue_36793.dart.outline.expect
index 659526a..b13488b 100644
--- a/pkg/front_end/testcases/regress/issue_36793.dart.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_36793.dart.outline.expect
@@ -13,6 +13,7 @@
import "dart:core" as core;
static const field core::int y;
+@self::y
static field core::int x;
static method main() → dynamic
;
diff --git a/pkg/front_end/testcases/regress/issue_36793.dart.strong.expect b/pkg/front_end/testcases/regress/issue_36793.dart.strong.expect
index 4735cfe..69ebf3f 100644
--- a/pkg/front_end/testcases/regress/issue_36793.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_36793.dart.strong.expect
@@ -13,6 +13,7 @@
import "dart:core" as core;
static const field core::int y = 42;
+@self::y
static field core::int x;
static method main() → dynamic {
core::print(self::y);
diff --git a/pkg/front_end/testcases/regress/issue_36793.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_36793.dart.strong.transformed.expect
index 4735cfe..69ebf3f 100644
--- a/pkg/front_end/testcases/regress/issue_36793.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_36793.dart.strong.transformed.expect
@@ -13,6 +13,7 @@
import "dart:core" as core;
static const field core::int y = 42;
+@self::y
static field core::int x;
static method main() → dynamic {
core::print(self::y);
diff --git a/pkg/front_end/tool/fasta_perf.dart b/pkg/front_end/tool/fasta_perf.dart
index bd1ed2c..0ba6da6 100644
--- a/pkg/front_end/tool/fasta_perf.dart
+++ b/pkg/front_end/tool/fasta_perf.dart
@@ -217,7 +217,7 @@
// Note: this method converts the body to kernel, so we skip that here.
@override
- finishFunction(annotations, formals, asyncModifier, body) {}
+ finishFunction(formals, asyncModifier, body) {}
}
// Invoke the fasta kernel generator for the program starting in [entryUri]
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 30a5f5c..0a9e01b 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -192,6 +192,11 @@
Uri get fileUri;
}
+abstract class Annotatable {
+ List<Expression> get annotations;
+ void addAnnotation(Expression node);
+}
+
/// Indirection between a reference and its definition.
///
/// There is only one reference object per [NamedNode].
@@ -267,7 +272,8 @@
// ------------------------------------------------------------------------
@coq
-class Library extends NamedNode implements Comparable<Library>, FileUriNode {
+class Library extends NamedNode
+ implements Annotatable, Comparable<Library>, FileUriNode {
/// An import path to this library.
///
/// The [Uri] should have the `dart`, `package`, `app`, or `file` scheme.
@@ -721,7 +727,7 @@
/// rule directly, as doing so can obstruct transformations. It is possible to
/// transform a mixin application to become a regular class, and vice versa.
@coq
-class Class extends NamedNode implements FileUriNode {
+class Class extends NamedNode implements Annotatable, FileUriNode {
/// Start offset of the class in the source file it comes from.
///
/// Note that this includes annotations if any.
@@ -1086,7 +1092,7 @@
// ------------------------------------------------------------------------
@coq
-abstract class Member extends NamedNode implements FileUriNode {
+abstract class Member extends NamedNode implements Annotatable, FileUriNode {
/// End offset in the source file it comes from.
///
/// Valid values are from 0 and up, or -1 ([TreeNode.noOffset]) if the file