Version 2.16.0-37.0.dev
Merge commit '7e6d8e085f959c3dfe92630e8e874366102b02ef' into 'dev'
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 9e0e011..40a1882 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -423,6 +423,7 @@
computeCoreTypes();
loader.buildClassHierarchy(myClasses, objectClassBuilder);
loader.computeHierarchy();
+ loader.computeMacroDeclarations(myClasses);
loader.computeShowHideElements();
loader.installTypedefTearOffs();
loader.performTopLevelInference(myClasses);
@@ -433,6 +434,7 @@
loader.checkMixins(myClasses);
loader.buildOutlineExpressions(
loader.coreTypes, synthesizedFunctionNodes);
+ loader.computeMacroApplications();
loader.checkTypes();
loader.checkRedirectingFactories(myClasses);
loader.checkMainMethods();
diff --git a/pkg/front_end/lib/src/fasta/kernel/macro.dart b/pkg/front_end/lib/src/fasta/kernel/macro.dart
new file mode 100644
index 0000000..63dff78
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/kernel/macro.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2021, 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.
+
+import 'package:kernel/ast.dart';
+
+bool enableMacros = false;
+
+final Uri macroLibraryUri = Uri.parse('package:macro_builder/src/macro.dart');
+const String macroClassName = 'Macro';
+
+class MacroDeclarationData {
+ Class? macroClass;
+ Map<Library, List<Class>> macroDeclarations = {};
+ Set<Class> macroClasses = {};
+}
+
+class MacroApplicationData {
+ Map<Library, LibraryMacroApplicationData> libraryData = {};
+}
+
+class MacroApplications {
+ final List<Class> macros;
+
+ MacroApplications(this.macros);
+}
+
+class LibraryMacroApplicationData {
+ MacroApplications? libraryApplications;
+ Map<Class, ClassMacroApplicationData> classData = {};
+ Map<Typedef, MacroApplications> typedefApplications = {};
+ Map<Member, MacroApplications> memberApplications = {};
+}
+
+class ClassMacroApplicationData {
+ MacroApplications? classApplications;
+ Map<Member, MacroApplications> memberApplications = {};
+}
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 29c7861..d9a23a6 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -64,6 +64,7 @@
import '../kernel/kernel_helper.dart'
show SynthesizedFunctionNode, TypeDependency;
import '../kernel/kernel_target.dart' show KernelTarget;
+import '../kernel/macro.dart';
import '../kernel/transform_collections.dart' show CollectionTransformer;
import '../kernel/transform_set_literals.dart' show SetLiteralTransformer;
import '../kernel/type_builder_computer.dart' show TypeBuilderComputer;
@@ -199,6 +200,8 @@
Uri? currentUriForCrashReporting;
+ Class? _macroClass;
+
SourceLoader(this.fileSystem, this.includeComments, this.target)
: dataForTesting =
retainDataForTesting ? new SourceLoaderDataForTesting() : null;
@@ -828,7 +831,7 @@
_typeInferenceEngine!.typeDependencies[member] = typeDependency;
}
- Future<Null> buildOutlines() async {
+ Future<void> buildOutlines() async {
_ensureCoreLibrary();
while (_unparsedLibraries.isNotEmpty) {
LibraryBuilder library = _unparsedLibraries.removeFirst();
@@ -1168,6 +1171,128 @@
ticker.logMs("Resolved $typeCount types");
}
+ void computeMacroDeclarations(List<SourceClassBuilder> classes) {
+ if (!enableMacros) return;
+ LibraryBuilder? macroLibraryBuilder = lookupLibraryBuilder(macroLibraryUri);
+ if (macroLibraryBuilder == null) return;
+ Builder? macroClassBuilder =
+ macroLibraryBuilder.lookupLocalMember(macroClassName);
+ if (macroClassBuilder is! ClassBuilder) {
+ // TODO(johnniwinther): Report this when the actual macro builder package
+ // exists. It should at least be a warning.
+ return;
+ }
+
+ Class macroClass = _macroClass = macroClassBuilder.cls;
+ if (retainDataForTesting) {
+ dataForTesting!.macroDeclarationData.macroClass = macroClass;
+ }
+ for (SourceClassBuilder classBuilder in classes) {
+ Class cls = classBuilder.cls;
+ if (hierarchy.isSubtypeOf(cls, macroClass)) {
+ if (retainDataForTesting) {
+ (dataForTesting!.macroDeclarationData
+ .macroDeclarations[cls.enclosingLibrary] ??= [])
+ .add(cls);
+ }
+ }
+ }
+ }
+
+ void computeMacroApplications() {
+ if (!enableMacros || _macroClass == null) return;
+ Class macroClass = _macroClass!;
+
+ Set<Class> macroClasses = {};
+ for (Library library in hierarchy.knownLibraries) {
+ for (Class cls in library.classes) {
+ // TODO(johnniwinther): Avoid calling `isSubtypeOf` for all classes. We
+ // should only check classes used in annotations to avoid marking too
+ // many classes as used.
+ if (hierarchy.isSubtypeOf(cls, macroClass)) {
+ macroClasses.add(cls);
+ if (retainDataForTesting) {
+ dataForTesting!.macroDeclarationData.macroClasses.add(cls);
+ }
+ }
+ }
+ }
+
+ Class? computeApplication(Expression expression) {
+ if (expression is ConstructorInvocation) {
+ Class cls = expression.target.enclosingClass;
+ if (macroClasses.contains(cls)) {
+ return cls;
+ }
+ }
+ return null;
+ }
+
+ MacroApplications? computeApplications(List<Expression> annotations) {
+ List<Class> macros = [];
+ for (Expression annotation in annotations) {
+ Class? cls = computeApplication(annotation);
+ if (cls != null) {
+ macros.add(cls);
+ }
+ }
+ return macros.isNotEmpty ? new MacroApplications(macros) : null;
+ }
+
+ for (LibraryBuilder libraryBuilder in libraryBuilders) {
+ if (libraryBuilder.loader != this) continue;
+ LibraryMacroApplicationData libraryMacroApplicationData =
+ new LibraryMacroApplicationData();
+ Library library = libraryBuilder.library;
+ libraryMacroApplicationData.libraryApplications =
+ computeApplications(library.annotations);
+ for (Class cls in library.classes) {
+ ClassMacroApplicationData classMacroApplicationData =
+ new ClassMacroApplicationData();
+ classMacroApplicationData.classApplications =
+ computeApplications(cls.annotations);
+ for (Member member in cls.members) {
+ MacroApplications? macroApplications =
+ computeApplications(member.annotations);
+ if (macroApplications != null) {
+ classMacroApplicationData.memberApplications[member] =
+ macroApplications;
+ }
+ }
+ if (classMacroApplicationData.classApplications != null ||
+ classMacroApplicationData.memberApplications.isNotEmpty) {
+ libraryMacroApplicationData.classData[cls] =
+ classMacroApplicationData;
+ }
+ }
+ for (Member member in library.members) {
+ MacroApplications? macroApplications =
+ computeApplications(member.annotations);
+ if (macroApplications != null) {
+ libraryMacroApplicationData.memberApplications[member] =
+ macroApplications;
+ }
+ }
+ for (Typedef typedef in library.typedefs) {
+ MacroApplications? macroApplications =
+ computeApplications(typedef.annotations);
+ if (macroApplications != null) {
+ libraryMacroApplicationData.typedefApplications[typedef] =
+ macroApplications;
+ }
+ }
+ if (libraryMacroApplicationData.libraryApplications != null ||
+ libraryMacroApplicationData.classData.isNotEmpty ||
+ libraryMacroApplicationData.typedefApplications.isNotEmpty ||
+ libraryMacroApplicationData.memberApplications.isNotEmpty) {
+ if (retainDataForTesting) {
+ dataForTesting!.macroApplicationData.libraryData[library] =
+ libraryMacroApplicationData;
+ }
+ }
+ }
+ }
+
void finishDeferredLoadTearoffs() {
int count = 0;
for (LibraryBuilder library in libraryBuilders) {
@@ -2269,4 +2394,8 @@
TreeNode toOriginal(TreeNode alias) {
return _aliasMap[alias] ?? alias;
}
+
+ final MacroDeclarationData macroDeclarationData = new MacroDeclarationData();
+
+ final MacroApplicationData macroApplicationData = new MacroApplicationData();
}
diff --git a/pkg/front_end/test/macros/macro_test.dart b/pkg/front_end/test/macros/macro_test.dart
index 98f0000..bcc7294 100644
--- a/pkg/front_end/test/macros/macro_test.dart
+++ b/pkg/front_end/test/macros/macro_test.dart
@@ -8,12 +8,13 @@
import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
import 'package:_fe_analyzer_shared/src/testing/features.dart';
+import 'package:front_end/src/fasta/kernel/macro.dart';
import 'package:front_end/src/testing/id_testing_helper.dart';
import 'package:kernel/ast.dart';
-import 'package:kernel/class_hierarchy.dart';
-import 'package:kernel/core_types.dart';
Future<void> main(List<String> args) async {
+ enableMacros = true;
+
Directory dataDir =
new Directory.fromUri(Platform.script.resolve('data/tests'));
await runTests<Features>(dataDir,
@@ -27,129 +28,6 @@
]));
}
-final Uri macroLibraryUri = Uri.parse('package:macro_builder/src/macro.dart');
-const String macroClassName = 'Macro';
-
-class MacroDeclarationData {
- Class? macroClass;
- Map<Library, List<Class>> macroDeclarations = {};
- Set<Class> macroClasses = {};
-}
-
-MacroDeclarationData computeMacroDeclarationData(
- Component component, ClassHierarchy classHierarchy) {
- MacroDeclarationData data = new MacroDeclarationData();
- Class? macroClass;
- outer:
- for (Library library in component.libraries) {
- if (library.importUri == macroLibraryUri) {
- for (Class cls in library.classes) {
- if (cls.name == macroClassName) {
- macroClass = cls;
- break outer;
- }
- }
- }
- }
- if (macroClass != null) {
- data.macroClass = macroClass;
- for (Library library in component.libraries) {
- for (Class cls in library.classes) {
- if (classHierarchy.isSubtypeOf(cls, macroClass)) {
- (data.macroDeclarations[library] ??= []).add(cls);
- data.macroClasses.add(cls);
- }
- }
- }
- }
- return data;
-}
-
-class MacroApplications {
- List<Class> macros = [];
-}
-
-class LibraryMacroApplicationData {
- MacroApplications? libraryApplications;
- Map<Class, ClassMacroApplicationData> classData = {};
- Map<Typedef, MacroApplications> typedefApplications = {};
- Map<Member, MacroApplications> memberApplications = {};
-}
-
-class ClassMacroApplicationData {
- MacroApplications? classApplications;
- Map<Member, MacroApplications> memberApplications = {};
-}
-
-MacroApplications? computeMacroApplications(
- List<Expression> annotations, MacroDeclarationData macroDeclarationData) {
- MacroApplications applications = new MacroApplications();
- bool hasApplications = false;
- for (Expression annotation in annotations) {
- if (annotation is ConstantExpression) {
- Constant constant = annotation.constant;
- if (constant is InstanceConstant) {
- if (macroDeclarationData.macroClasses.contains(constant.classNode)) {
- applications.macros.add(constant.classNode);
- hasApplications = true;
- }
- }
- }
- }
- return hasApplications ? applications : null;
-}
-
-ClassMacroApplicationData? computeClassMacroApplicationData(
- Class cls, MacroDeclarationData macroDeclarationData) {
- ClassMacroApplicationData data = new ClassMacroApplicationData();
- data.classApplications =
- computeMacroApplications(cls.annotations, macroDeclarationData);
- for (Member member in cls.members) {
- MacroApplications? macroApplications =
- computeMacroApplications(member.annotations, macroDeclarationData);
- if (macroApplications != null) {
- data.memberApplications[member] = macroApplications;
- }
- }
- return data.classApplications != null || data.memberApplications.isNotEmpty
- ? data
- : null;
-}
-
-LibraryMacroApplicationData? computeLibraryMacroApplicationData(
- Library library, MacroDeclarationData macroDeclarationData) {
- LibraryMacroApplicationData data = new LibraryMacroApplicationData();
- data.libraryApplications =
- computeMacroApplications(library.annotations, macroDeclarationData);
- for (Typedef typedef in library.typedefs) {
- MacroApplications? macroApplications =
- computeMacroApplications(typedef.annotations, macroDeclarationData);
- if (macroApplications != null) {
- data.typedefApplications[typedef] = macroApplications;
- }
- }
- for (Member member in library.members) {
- MacroApplications? macroApplications =
- computeMacroApplications(member.annotations, macroDeclarationData);
- if (macroApplications != null) {
- data.memberApplications[member] = macroApplications;
- }
- }
- for (Class cls in library.classes) {
- ClassMacroApplicationData? classMacroApplicationData =
- computeClassMacroApplicationData(cls, macroDeclarationData);
- if (classMacroApplicationData != null) {
- data.classData[cls] = classMacroApplicationData;
- }
- }
- return data.libraryApplications != null ||
- data.classData.isNotEmpty ||
- data.memberApplications.isNotEmpty ||
- data.typedefApplications.isNotEmpty
- ? data
- : null;
-}
-
class MacroDataComputer extends DataComputer<Features> {
const MacroDataComputer();
@@ -197,22 +75,20 @@
}
class MacroDataExtractor extends CfeDataExtractor<Features> {
- late final ClassHierarchy classHierarchy;
late final MacroDeclarationData macroDeclarationData;
+ late final MacroApplicationData macroApplicationData;
MacroDataExtractor(InternalCompilerResult compilerResult,
Map<Id, ActualData<Features>> actualMap)
: super(compilerResult, actualMap) {
- // TODO(johnniwinther): Why isn't `_UserTag` available in the
- // [ClassHierarchy] provided by the [compilerResult]?
- classHierarchy = new ClassHierarchy(
- compilerResult.component!, new CoreTypes(compilerResult.component!));
- macroDeclarationData =
- computeMacroDeclarationData(compilerResult.component!, classHierarchy);
+ macroDeclarationData = compilerResult
+ .kernelTargetForTesting!.loader.dataForTesting!.macroDeclarationData;
+ macroApplicationData = compilerResult
+ .kernelTargetForTesting!.loader.dataForTesting!.macroApplicationData;
}
LibraryMacroApplicationData? getLibraryMacroApplicationData(Library library) {
- return computeLibraryMacroApplicationData(library, macroDeclarationData);
+ return macroApplicationData.libraryData[library];
}
MacroApplications? getLibraryMacroApplications(Library library) {
@@ -221,8 +97,7 @@
ClassMacroApplicationData? getClassMacroApplicationData(Class cls) {
LibraryMacroApplicationData? applicationData =
- computeLibraryMacroApplicationData(
- cls.enclosingLibrary, macroDeclarationData);
+ getLibraryMacroApplicationData(cls.enclosingLibrary);
if (applicationData != null) {
return applicationData.classData[cls];
}
diff --git a/tools/VERSION b/tools/VERSION
index fdf498a..fb38f54 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 16
PATCH 0
-PRERELEASE 36
+PRERELEASE 37
PRERELEASE_PATCH 0
\ No newline at end of file