Version 2.16.0-41.0.dev
Merge commit '02cd6a9a94cd10849cb44951afaae444ea4c3f13' into 'dev'
diff --git a/DEPS b/DEPS
index 9dab5da..a2c3532 100644
--- a/DEPS
+++ b/DEPS
@@ -44,9 +44,9 @@
# co19 is a cipd package. Use update.sh in tests/co19[_2] to update these
# hashes. It requires access to the dart-build-access group, which EngProd
# has.
- "co19_rev": "39c5bbc03bf5c5c0a3f9341abe811871eababfaf",
+ "co19_rev": "4ef349830b971c22d8ddb2970c4ba9002806fd85",
# This line prevents conflicts when both packages are rolled simultaneously.
- "co19_2_rev": "86f01ade433fbb4eec3a7f93f5e1e4fed9a84fb3",
+ "co19_2_rev": "995745937abffe9fc3a6441f9f0db27b2d706e4c",
# The internal benchmarks to use. See go/dart-benchmarks-internal
"benchmarks_internal_rev": "076df10d9b77af337f2d8029725787155eb1cd52",
diff --git a/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart b/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
index 0bfffd5..930f1b0 100644
--- a/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
@@ -400,7 +400,7 @@
// from ClassHierarchyBuilder.
TypeDeclarationBuilder? unaliasedDeclaration = this.declaration;
// The following code assumes that the declaration is a TypeAliasBuilder
- // that through a chain of other TypeAliasBuilders (possibly, the chian
+ // that through a chain of other TypeAliasBuilders (possibly, the chain
// length is 0) references a ClassBuilder of the Null class. Otherwise,
// it won't produce the NullType on the output.
while (unaliasedDeclaration is TypeAliasBuilder) {
@@ -421,7 +421,7 @@
// class from ClassHierarchyBuilder.
TypeDeclarationBuilder? unaliasedDeclaration = this.declaration;
// The following code assumes that the declaration is a TypeAliasBuilder
- // that through a chain of other TypeAliasBuilders (possibly, the chian
+ // that through a chain of other TypeAliasBuilders (possibly, the chain
// length is 0) references a ClassBuilder of the FutureOr class.
// Otherwise, it won't produce the FutureOrType on the output.
while (unaliasedDeclaration is TypeAliasBuilder) {
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index 61bdb2e..23f2625 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -9,18 +9,6 @@
import 'package:_fe_analyzer_shared/src/scanner/abstract_scanner.dart'
show ScannerConfiguration;
-import 'package:front_end/src/api_prototype/experimental_flags.dart';
-
-import 'package:front_end/src/api_prototype/lowering_predicates.dart'
- show isExtensionThisName;
-
-import 'package:front_end/src/base/nnbd_mode.dart';
-
-import 'package:front_end/src/fasta/builder/member_builder.dart'
- show MemberBuilder;
-
-import 'package:front_end/src/fasta/fasta_codes.dart';
-import 'package:front_end/src/fasta/source/source_loader.dart';
import 'package:kernel/binary/ast_from_binary.dart'
show
BinaryBuilderWithMetadata,
@@ -69,13 +57,19 @@
import 'package:package_config/package_config.dart' show Package, PackageConfig;
+import '../api_prototype/experimental_flags.dart';
+
import '../api_prototype/file_system.dart' show FileSystem, FileSystemEntity;
import '../api_prototype/incremental_kernel_generator.dart'
show IncrementalKernelGenerator, isLegalIdentifier;
+import '../api_prototype/lowering_predicates.dart' show isExtensionThisName;
+
import '../api_prototype/memory_file_system.dart' show MemoryFileSystem;
+import '../base/nnbd_mode.dart';
+
import 'builder/builder.dart' show Builder;
import 'builder/class_builder.dart' show ClassBuilder;
@@ -86,6 +80,8 @@
import 'builder/library_builder.dart' show LibraryBuilder;
+import 'builder/member_builder.dart' show MemberBuilder;
+
import 'builder/name_iterator.dart' show NameIterator;
import 'builder/type_builder.dart' show TypeBuilder;
@@ -107,6 +103,8 @@
import 'export.dart' show Export;
+import 'fasta_codes.dart';
+
import 'import.dart' show Import;
import 'incremental_serializer.dart' show IncrementalSerializer;
@@ -134,6 +132,8 @@
import 'source/source_library_builder.dart'
show ImplicitLanguageVersion, SourceLibraryBuilder;
+import 'source/source_loader.dart';
+
import 'ticker.dart' show Ticker;
import 'uri_translator.dart' show UriTranslator;
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 40a1882..2950121 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -402,7 +402,6 @@
if (loader.first == null) return null;
return withCrashReporting<Component?>(() async {
await loader.buildOutlines();
- loader.createTypeInferenceEngine();
loader.coreLibrary.becomeCoreLibrary();
loader.resolveParts();
loader.computeLibraryScopes();
@@ -411,32 +410,33 @@
loader.computeVariances();
loader.computeDefaultTypes(
dynamicType, nullType, bottomType, objectClassBuilder);
- List<SourceClassBuilder> myClasses =
+ List<SourceClassBuilder> sourceClassBuilders =
loader.checkSemantics(objectClassBuilder);
+ loader.computeMacroDeclarations(sourceClassBuilders);
loader.finishTypeVariables(objectClassBuilder, dynamicType);
+ loader.createTypeInferenceEngine();
loader.buildComponent();
installDefaultSupertypes();
- installSyntheticConstructors(myClasses);
+ installSyntheticConstructors(sourceClassBuilders);
loader.resolveConstructors();
component =
link(new List<Library>.from(loader.libraries), nameRoot: nameRoot);
computeCoreTypes();
- loader.buildClassHierarchy(myClasses, objectClassBuilder);
+ loader.buildClassHierarchy(sourceClassBuilders, objectClassBuilder);
loader.computeHierarchy();
- loader.computeMacroDeclarations(myClasses);
loader.computeShowHideElements();
loader.installTypedefTearOffs();
- loader.performTopLevelInference(myClasses);
- loader.checkSupertypes(myClasses);
- loader.checkOverrides(myClasses);
- loader.checkAbstractMembers(myClasses);
- loader.addNoSuchMethodForwarders(myClasses);
- loader.checkMixins(myClasses);
+ loader.performTopLevelInference(sourceClassBuilders);
+ loader.checkSupertypes(sourceClassBuilders);
+ loader.checkOverrides(sourceClassBuilders);
+ loader.checkAbstractMembers(sourceClassBuilders);
+ loader.addNoSuchMethodForwarders(sourceClassBuilders);
+ loader.checkMixins(sourceClassBuilders);
loader.buildOutlineExpressions(
loader.coreTypes, synthesizedFunctionNodes);
loader.computeMacroApplications();
loader.checkTypes();
- loader.checkRedirectingFactories(myClasses);
+ loader.checkRedirectingFactories(sourceClassBuilders);
loader.checkMainMethods();
installAllComponentProblems(loader.allComponentProblems);
loader.allComponentProblems.clear();
diff --git a/pkg/front_end/lib/src/fasta/kernel/macro.dart b/pkg/front_end/lib/src/fasta/kernel/macro.dart
index 63dff78..afa9dca 100644
--- a/pkg/front_end/lib/src/fasta/kernel/macro.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/macro.dart
@@ -10,9 +10,9 @@
const String macroClassName = 'Macro';
class MacroDeclarationData {
- Class? macroClass;
- Map<Library, List<Class>> macroDeclarations = {};
- Set<Class> macroClasses = {};
+ bool macrosAreAvailable = false;
+ Map<Uri, List<String>> macroDeclarations = {};
+ List<List<Uri>>? compilationSequence;
}
class MacroApplicationData {
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 d9a23a6..aa989c5 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -27,6 +27,7 @@
import 'package:kernel/core_types.dart' show CoreTypes;
import 'package:kernel/reference_from_index.dart' show ReferenceFromIndex;
import 'package:kernel/type_environment.dart';
+import 'package:kernel/util/graph.dart';
import 'package:package_config/package_config.dart' as package_config;
import '../../api_prototype/experimental_flags.dart';
@@ -34,7 +35,9 @@
import '../../base/common.dart';
import '../../base/instrumentation.dart' show Instrumentation;
import '../../base/nnbd_mode.dart';
+import '../dill/dill_class_builder.dart';
import '../dill/dill_library_builder.dart';
+import '../builder_graph.dart';
import '../builder/builder.dart';
import '../builder/class_builder.dart';
import '../builder/constructor_builder.dart';
@@ -200,7 +203,7 @@
Uri? currentUriForCrashReporting;
- Class? _macroClass;
+ ClassBuilder? _macroClassBuilder;
SourceLoader(this.fileSystem, this.includeComments, this.target)
: dataForTesting =
@@ -1171,10 +1174,12 @@
ticker.logMs("Resolved $typeCount types");
}
- void computeMacroDeclarations(List<SourceClassBuilder> classes) {
+ void computeMacroDeclarations(List<SourceClassBuilder> sourceClassBuilders) {
if (!enableMacros) return;
+
LibraryBuilder? macroLibraryBuilder = lookupLibraryBuilder(macroLibraryUri);
if (macroLibraryBuilder == null) return;
+
Builder? macroClassBuilder =
macroLibraryBuilder.lookupLocalMember(macroClassName);
if (macroClassBuilder is! ClassBuilder) {
@@ -1183,45 +1188,106 @@
return;
}
- Class macroClass = _macroClass = macroClassBuilder.cls;
+ _macroClassBuilder = macroClassBuilder;
if (retainDataForTesting) {
- dataForTesting!.macroDeclarationData.macroClass = macroClass;
+ dataForTesting!.macroDeclarationData.macrosAreAvailable = true;
}
- for (SourceClassBuilder classBuilder in classes) {
- Class cls = classBuilder.cls;
- if (hierarchy.isSubtypeOf(cls, macroClass)) {
- if (retainDataForTesting) {
- (dataForTesting!.macroDeclarationData
- .macroDeclarations[cls.enclosingLibrary] ??= [])
- .add(cls);
+
+ Set<ClassBuilder> macroClasses = {macroClassBuilder};
+ Set<Uri> macroLibraries = {macroLibraryBuilder.importUri};
+
+ bool isMacroClass(TypeDeclarationBuilder? typeDeclarationBuilder) {
+ if (typeDeclarationBuilder == null) return false;
+ while (typeDeclarationBuilder is TypeAliasBuilder) {
+ typeDeclarationBuilder =
+ typeDeclarationBuilder.unaliasDeclaration(null);
+ }
+ if (typeDeclarationBuilder is ClassBuilder) {
+ if (macroClasses.contains(typeDeclarationBuilder)) return true;
+ if (typeDeclarationBuilder is DillClassBuilder) {
+ // TODO(johnniwinther): Recognize macro classes from dill.
}
}
+ return false;
+ }
+
+ for (SourceClassBuilder sourceClassBuilder in sourceClassBuilders) {
+ bool isMacro =
+ isMacroClass(sourceClassBuilder.supertypeBuilder?.declaration);
+ if (!isMacro && sourceClassBuilder.interfaceBuilders != null) {
+ for (TypeBuilder interfaceBuilder
+ in sourceClassBuilder.interfaceBuilders!) {
+ if (isMacroClass(interfaceBuilder.declaration)) {
+ isMacro = true;
+ break;
+ }
+ }
+ }
+ isMacro = isMacro ||
+ isMacroClass(sourceClassBuilder.mixedInTypeBuilder?.declaration);
+ if (isMacro) {
+ macroClasses.add(sourceClassBuilder);
+ macroLibraries.add(sourceClassBuilder.library.importUri);
+ if (retainDataForTesting) {
+ (dataForTesting!.macroDeclarationData.macroDeclarations[
+ sourceClassBuilder.library.importUri] ??= [])
+ .add(sourceClassBuilder.name);
+ }
+ }
+ }
+
+ bool isDillLibrary(Uri uri) => _builders[uri]?.loader != this;
+
+ List<List<Uri>> computeCompilationSequence(Graph<Uri> libraryGraph,
+ {required bool Function(Uri) filter}) {
+ List<List<Uri>> stronglyConnectedComponents =
+ computeStrongComponents(libraryGraph);
+
+ Graph<List<Uri>> strongGraph =
+ new StrongComponentGraph(libraryGraph, stronglyConnectedComponents);
+ List<List<List<Uri>>> componentLayers = [];
+ topologicalSort(strongGraph, layers: componentLayers);
+ List<List<Uri>> layeredComponents = [];
+ List<Uri> currentLayer = [];
+ for (List<List<Uri>> layer in componentLayers) {
+ bool declaresMacro = false;
+ for (List<Uri> component in layer) {
+ for (Uri uri in component) {
+ if (filter(uri)) continue;
+ if (macroLibraries.contains(uri)) {
+ declaresMacro = true;
+ }
+ currentLayer.add(uri);
+ }
+ }
+ if (declaresMacro) {
+ layeredComponents.add(currentLayer);
+ currentLayer = [];
+ }
+ }
+ if (currentLayer.isNotEmpty) {
+ layeredComponents.add(currentLayer);
+ }
+ return layeredComponents;
+ }
+
+ List<List<Uri>> compilationSteps = computeCompilationSequence(
+ new BuilderGraph(_builders),
+ filter: isDillLibrary);
+ if (retainDataForTesting) {
+ dataForTesting!.macroDeclarationData.compilationSequence =
+ compilationSteps;
}
}
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);
- }
- }
- }
- }
+ if (!enableMacros || _macroClassBuilder == null) return;
+ Class macroClass = _macroClassBuilder!.cls;
Class? computeApplication(Expression expression) {
if (expression is ConstructorInvocation) {
Class cls = expression.target.enclosingClass;
- if (macroClasses.contains(cls)) {
+ if (hierarchy.isSubtypeOf(cls, macroClass)) {
return cls;
}
}
diff --git a/pkg/front_end/test/macros/data/tests/declare_macro.dart b/pkg/front_end/test/macros/data/tests/declare_macro.dart
index 58edc63..5d396f7 100644
--- a/pkg/front_end/test/macros/data/tests/declare_macro.dart
+++ b/pkg/front_end/test/macros/data/tests/declare_macro.dart
@@ -3,6 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
/*library:
+ compilationSequence=[
+ package:macro_builder/src/macro.dart,
+ main.dart|package:macro_builder/macro_builder.dart],
declaredMacros=[MyMacro],
macrosAreAvailable
*/
diff --git a/pkg/front_end/test/macros/data/tests/declare_vs_apply/apply_lib.dart b/pkg/front_end/test/macros/data/tests/declare_vs_apply/apply_lib.dart
new file mode 100644
index 0000000..f4e6484
--- /dev/null
+++ b/pkg/front_end/test/macros/data/tests/declare_vs_apply/apply_lib.dart
@@ -0,0 +1,18 @@
+// 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.
+
+/*library:
+ macrosAreApplied,
+ macrosAreAvailable
+*/
+
+import 'macro_lib.dart';
+import 'apply_lib_dep.dart';
+
+@Macro1()
+/*class: Class:
+ appliedMacros=[Macro1],
+ macrosAreApplied
+*/
+class Class extends Super {}
diff --git a/pkg/front_end/test/macros/data/tests/declare_vs_apply/apply_lib_dep.dart b/pkg/front_end/test/macros/data/tests/declare_vs_apply/apply_lib_dep.dart
new file mode 100644
index 0000000..018b909
--- /dev/null
+++ b/pkg/front_end/test/macros/data/tests/declare_vs_apply/apply_lib_dep.dart
@@ -0,0 +1,7 @@
+// 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.
+
+/*library: macrosAreAvailable*/
+
+class Super {}
diff --git a/pkg/front_end/test/macros/data/tests/declare_vs_apply/macro_lib.dart b/pkg/front_end/test/macros/data/tests/declare_vs_apply/macro_lib.dart
new file mode 100644
index 0000000..149d512
--- /dev/null
+++ b/pkg/front_end/test/macros/data/tests/declare_vs_apply/macro_lib.dart
@@ -0,0 +1,15 @@
+// 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.
+
+/*library:
+ declaredMacros=[Macro1],
+ macrosAreAvailable
+*/
+
+import 'package:macro_builder/macro_builder.dart';
+import 'macro_lib_dep.dart';
+
+class Macro1 extends MacroBase implements Macro {
+ const Macro1();
+}
diff --git a/pkg/front_end/test/macros/data/tests/declare_vs_apply/macro_lib_dep.dart b/pkg/front_end/test/macros/data/tests/declare_vs_apply/macro_lib_dep.dart
new file mode 100644
index 0000000..13c27f8
--- /dev/null
+++ b/pkg/front_end/test/macros/data/tests/declare_vs_apply/macro_lib_dep.dart
@@ -0,0 +1,9 @@
+// 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.
+
+/*library: macrosAreAvailable*/
+
+class MacroBase {
+ const MacroBase();
+}
diff --git a/pkg/front_end/test/macros/data/tests/declare_vs_apply/main.dart b/pkg/front_end/test/macros/data/tests/declare_vs_apply/main.dart
new file mode 100644
index 0000000..868f08d
--- /dev/null
+++ b/pkg/front_end/test/macros/data/tests/declare_vs_apply/main.dart
@@ -0,0 +1,19 @@
+// 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.
+
+/*library:
+ compilationSequence=[
+ apply_lib_dep.dart|macro_lib_dep.dart|main_lib_dep.dart|package:macro_builder/src/macro.dart,
+ macro_lib.dart|package:macro_builder/macro_builder.dart,
+ apply_lib.dart|main.dart],
+ macrosAreAvailable
+*/
+
+import 'apply_lib.dart';
+import 'main_lib_dep.dart';
+
+void main() {
+ new Class();
+ method();
+}
diff --git a/pkg/front_end/test/macros/data/tests/declare_vs_apply/main_lib_dep.dart b/pkg/front_end/test/macros/data/tests/declare_vs_apply/main_lib_dep.dart
new file mode 100644
index 0000000..684c9d7
--- /dev/null
+++ b/pkg/front_end/test/macros/data/tests/declare_vs_apply/main_lib_dep.dart
@@ -0,0 +1,7 @@
+// 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.
+
+/*library: macrosAreAvailable*/
+
+void method() {}
diff --git a/pkg/front_end/test/macros/data/tests/direct_import.dart b/pkg/front_end/test/macros/data/tests/direct_import.dart
index b2f6177..f3484cd 100644
--- a/pkg/front_end/test/macros/data/tests/direct_import.dart
+++ b/pkg/front_end/test/macros/data/tests/direct_import.dart
@@ -2,7 +2,12 @@
// 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.
-/*library: macrosAreAvailable*/
+/*library:
+ compilationSequence=[
+ package:macro_builder/src/macro.dart,
+ main.dart],
+ macrosAreAvailable
+*/
// ignore: unused_import
import 'package:macro_builder/src/macro.dart';
diff --git a/pkg/front_end/test/macros/data/tests/import_macro_builder.dart b/pkg/front_end/test/macros/data/tests/import_macro_builder.dart
index 14e5966c..dca3012 100644
--- a/pkg/front_end/test/macros/data/tests/import_macro_builder.dart
+++ b/pkg/front_end/test/macros/data/tests/import_macro_builder.dart
@@ -2,7 +2,12 @@
// 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.
-/*library: macrosAreAvailable*/
+/*library:
+ compilationSequence=[
+ package:macro_builder/src/macro.dart,
+ main.dart|package:macro_builder/macro_builder.dart],
+ macrosAreAvailable
+*/
// ignore: unused_import
import 'package:macro_builder/macro_builder.dart';
diff --git a/pkg/front_end/test/macros/data/tests/import_macro_package.dart b/pkg/front_end/test/macros/data/tests/import_macro_package.dart
index 5e69df3..1fabb48 100644
--- a/pkg/front_end/test/macros/data/tests/import_macro_package.dart
+++ b/pkg/front_end/test/macros/data/tests/import_macro_package.dart
@@ -2,7 +2,13 @@
// 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.
-/*library: macrosAreAvailable*/
+/*library:
+ compilationSequence=[
+ package:macro_builder/src/macro.dart,
+ package:macro/macro.dart|package:macro_builder/macro_builder.dart,
+ main.dart],
+ macrosAreAvailable
+*/
// ignore: unused_import
import 'package:macro/macro.dart';
diff --git a/pkg/front_end/test/macros/data/tests/import_macro_source/main.dart b/pkg/front_end/test/macros/data/tests/import_macro_source/main.dart
index 625315b..5b109f4 100644
--- a/pkg/front_end/test/macros/data/tests/import_macro_source/main.dart
+++ b/pkg/front_end/test/macros/data/tests/import_macro_source/main.dart
@@ -2,7 +2,13 @@
// 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.
-/*library: macrosAreAvailable*/
+/*library:
+ compilationSequence=[
+ package:macro_builder/src/macro.dart,
+ macro_lib.dart|package:macro_builder/macro_builder.dart,
+ main.dart],
+ macrosAreAvailable
+*/
// ignore: unused_import
import 'macro_lib.dart';
diff --git a/pkg/front_end/test/macros/data/tests/macro_declarations.dart b/pkg/front_end/test/macros/data/tests/macro_declarations.dart
new file mode 100644
index 0000000..872dad84
--- /dev/null
+++ b/pkg/front_end/test/macros/data/tests/macro_declarations.dart
@@ -0,0 +1,37 @@
+// 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.
+
+/*library:
+ compilationSequence=[
+ package:macro_builder/src/macro.dart,
+ main.dart|package:macro_builder/macro_builder.dart],
+ declaredMacros=[
+ Extends,
+ ExtendsAlias,
+ Implements,
+ ImplementsAlias,
+ Mixin,
+ MixinAlias,
+ _Mixin&Object&Macro,
+ _MixinAlias&Object&Alias],
+ macrosAreAvailable
+*/
+
+import 'package:macro_builder/macro_builder.dart';
+
+class Extends extends Macro {}
+
+class Implements implements Macro {}
+
+class Mixin with Macro {}
+
+typedef Alias = Macro;
+
+class ExtendsAlias extends Alias {}
+
+class ImplementsAlias implements Alias {}
+
+class MixinAlias with Alias {}
+
+void main() {}
diff --git a/pkg/front_end/test/macros/data/tests/multiple_macros/macro_lib1.dart b/pkg/front_end/test/macros/data/tests/multiple_macros/macro_lib1.dart
new file mode 100644
index 0000000..a05f387
--- /dev/null
+++ b/pkg/front_end/test/macros/data/tests/multiple_macros/macro_lib1.dart
@@ -0,0 +1,14 @@
+// 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.
+
+/*library:
+ declaredMacros=[Macro1],
+ macrosAreAvailable
+*/
+
+import 'package:macro_builder/macro_builder.dart';
+
+class Macro1 implements Macro {
+ const Macro1();
+}
diff --git a/pkg/front_end/test/macros/data/tests/multiple_macros/macro_lib2a.dart b/pkg/front_end/test/macros/data/tests/multiple_macros/macro_lib2a.dart
new file mode 100644
index 0000000..967801f
--- /dev/null
+++ b/pkg/front_end/test/macros/data/tests/multiple_macros/macro_lib2a.dart
@@ -0,0 +1,14 @@
+// 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.
+
+/*library:
+ declaredMacros=[Macro2a],
+ macrosAreAvailable
+*/
+
+import 'package:macro_builder/macro_builder.dart';
+
+class Macro2a implements Macro {
+ const Macro2a();
+}
diff --git a/pkg/front_end/test/macros/data/tests/multiple_macros/macro_lib2b.dart b/pkg/front_end/test/macros/data/tests/multiple_macros/macro_lib2b.dart
new file mode 100644
index 0000000..b9bc7d2
--- /dev/null
+++ b/pkg/front_end/test/macros/data/tests/multiple_macros/macro_lib2b.dart
@@ -0,0 +1,21 @@
+// 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.
+
+/*library:
+ declaredMacros=[Macro2b],
+ macrosAreApplied,
+ macrosAreAvailable
+*/
+
+import 'package:macro_builder/macro_builder.dart';
+import 'macro_lib2a.dart';
+
+@Macro2a()
+/*class: Macro2b:
+ appliedMacros=[Macro2a],
+ macrosAreApplied
+*/
+class Macro2b implements Macro {
+ const Macro2b();
+}
diff --git a/pkg/front_end/test/macros/data/tests/multiple_macros/main.dart b/pkg/front_end/test/macros/data/tests/multiple_macros/main.dart
new file mode 100644
index 0000000..9dee592
--- /dev/null
+++ b/pkg/front_end/test/macros/data/tests/multiple_macros/main.dart
@@ -0,0 +1,26 @@
+// 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.
+
+/*library:
+ compilationSequence=[
+ package:macro_builder/src/macro.dart,
+ macro_lib1.dart|macro_lib2a.dart|package:macro_builder/macro_builder.dart,
+ macro_lib2b.dart,
+ main.dart],
+ macrosAreApplied,
+ macrosAreAvailable
+*/
+
+import 'macro_lib1.dart';
+import 'macro_lib2a.dart';
+import 'macro_lib2b.dart';
+
+@Macro1()
+@Macro2a()
+@Macro2b()
+/*member: main:appliedMacros=[
+ Macro1,
+ Macro2a,
+ Macro2b]*/
+void main() {}
diff --git a/pkg/front_end/test/macros/data/tests/no_import.dart b/pkg/front_end/test/macros/data/tests/no_import.dart
index e5c2fad..80fd055 100644
--- a/pkg/front_end/test/macros/data/tests/no_import.dart
+++ b/pkg/front_end/test/macros/data/tests/no_import.dart
@@ -2,4 +2,6 @@
// 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.
+/*library: */
+
void main() {}
diff --git a/pkg/front_end/test/macros/data/tests/use_macro_package.dart b/pkg/front_end/test/macros/data/tests/use_macro_package.dart
index 09c2b3b..74f18ff 100644
--- a/pkg/front_end/test/macros/data/tests/use_macro_package.dart
+++ b/pkg/front_end/test/macros/data/tests/use_macro_package.dart
@@ -4,6 +4,10 @@
/*library:
appliedMacros=[Macro3],
+ compilationSequence=[
+ package:macro_builder/src/macro.dart,
+ package:macro/macro.dart|package:macro_builder/macro_builder.dart,
+ main.dart],
macrosAreApplied,
macrosAreAvailable
*/
diff --git a/pkg/front_end/test/macros/data/tests/use_macro_source/main.dart b/pkg/front_end/test/macros/data/tests/use_macro_source/main.dart
index f5a3e60..930eb5c 100644
--- a/pkg/front_end/test/macros/data/tests/use_macro_source/main.dart
+++ b/pkg/front_end/test/macros/data/tests/use_macro_source/main.dart
@@ -3,6 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
/*library:
+ compilationSequence=[
+ package:macro_builder/src/macro.dart,
+ macro_lib.dart|package:macro_builder/macro_builder.dart,
+ main.dart],
macrosAreApplied,
macrosAreAvailable
*/
diff --git a/pkg/front_end/test/macros/macro_test.dart b/pkg/front_end/test/macros/macro_test.dart
index bcc7294..82fe62d 100644
--- a/pkg/front_end/test/macros/macro_test.dart
+++ b/pkg/front_end/test/macros/macro_test.dart
@@ -70,10 +70,29 @@
class Tags {
static const String macrosAreAvailable = 'macrosAreAvailable';
static const String macrosAreApplied = 'macrosAreApplied';
+ static const String compilationSequence = 'compilationSequence';
static const String declaredMacros = 'declaredMacros';
static const String appliedMacros = 'appliedMacros';
}
+String importUriToString(Uri importUri) {
+ if (importUri.scheme == 'package') {
+ return importUri.toString();
+ } else if (importUri.scheme == 'dart') {
+ return importUri.toString();
+ } else {
+ return importUri.pathSegments.last;
+ }
+}
+
+String libraryToString(Library library) => importUriToString(library.importUri);
+
+String strongComponentToString(Iterable<Uri> uris) {
+ List<String> list = uris.map(importUriToString).toList();
+ list.sort();
+ return list.join('|');
+}
+
class MacroDataExtractor extends CfeDataExtractor<Features> {
late final MacroDeclarationData macroDeclarationData;
late final MacroApplicationData macroApplicationData;
@@ -129,25 +148,6 @@
}
@override
- Features computeLibraryValue(Id id, Library node) {
- Features features = new Features();
- if (macroDeclarationData.macroClass != null) {
- features.add(Tags.macrosAreAvailable);
- }
- List<Class>? macroClasses = macroDeclarationData.macroDeclarations[node];
- if (macroClasses != null) {
- for (Class cls in macroClasses) {
- features.addElement(Tags.declaredMacros, cls.name);
- }
- }
- if (getLibraryMacroApplicationData(node) != null) {
- features.add(Tags.macrosAreApplied);
- }
- registerMacroApplications(features, getLibraryMacroApplications(node));
- return features;
- }
-
- @override
Features computeClassValue(Id id, Class node) {
Features features = new Features();
if (getClassMacroApplicationData(node) != null) {
@@ -158,6 +158,35 @@
}
@override
+ Features computeLibraryValue(Id id, Library node) {
+ Features features = new Features();
+ if (macroDeclarationData.macrosAreAvailable) {
+ features.add(Tags.macrosAreAvailable);
+ }
+ if (node == compilerResult.component!.mainMethod!.enclosingLibrary) {
+ if (macroDeclarationData.compilationSequence != null) {
+ features.markAsUnsorted(Tags.compilationSequence);
+ for (List<Uri> component in macroDeclarationData.compilationSequence!) {
+ features.addElement(
+ Tags.compilationSequence, strongComponentToString(component));
+ }
+ }
+ }
+ List<String>? macroClasses =
+ macroDeclarationData.macroDeclarations[node.importUri];
+ if (macroClasses != null) {
+ for (String clsName in macroClasses) {
+ features.addElement(Tags.declaredMacros, clsName);
+ }
+ }
+ if (getLibraryMacroApplicationData(node) != null) {
+ features.add(Tags.macrosAreApplied);
+ }
+ registerMacroApplications(features, getLibraryMacroApplications(node));
+ return features;
+ }
+
+ @override
Features computeMemberValue(Id id, Member node) {
Features features = new Features();
registerMacroApplications(features, getMemberMacroApplications(node));
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index fcf3a64..0f0d0b8 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -679,6 +679,8 @@
launched
launcher
layer
+layered
+layers
layout
lc
ld
@@ -1215,6 +1217,7 @@
subexpression
subexpression's
subexpressions
+subgraph
subnode
subnodes
subscription
diff --git a/pkg/front_end/test/spell_checking_list_common.txt b/pkg/front_end/test/spell_checking_list_common.txt
index cad9efd..4a5faff 100644
--- a/pkg/front_end/test/spell_checking_list_common.txt
+++ b/pkg/front_end/test/spell_checking_list_common.txt
@@ -436,7 +436,6 @@
checking
checkpoints
checks
-chian
child
children
choice
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index 86bfe96..bb52fe8 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -598,10 +598,13 @@
la
launch
launching
+layered
layers
le
legs
lengths
+lib2a
+lib2b
lightly
likewise
lily
@@ -644,6 +647,8 @@
loopback
mac
macro
+macro2a
+macro2b
macros
maker
matters
diff --git a/pkg/kernel/lib/util/graph.dart b/pkg/kernel/lib/util/graph.dart
index 4119f1b..aedbf14 100644
--- a/pkg/kernel/lib/util/graph.dart
+++ b/pkg/kernel/lib/util/graph.dart
@@ -4,12 +4,42 @@
library fasta.graph;
+import 'dart:math';
+
+import '../ast.dart';
+
abstract class Graph<T> {
Iterable<T> get vertices;
Iterable<T> neighborsOf(T vertex);
}
+/// [Graph] implementation using a collection of [Library] nodes as the graph
+/// vertices and using library dependencies to compute neighbors.
+///
+/// If [coreLibrary] is provided, it will be included in the neighbor of all
+/// vertices. Otherwise, `dart:core` will only be neighboring libraries that
+/// explicitly dependent on it.
+class LibraryGraph implements Graph<Library> {
+ final Iterable<Library> libraries;
+ final Library? coreLibrary;
+
+ LibraryGraph(this.libraries, {this.coreLibrary});
+
+ @override
+ Iterable<Library> get vertices => libraries;
+
+ @override
+ Iterable<Library> neighborsOf(Library library) sync* {
+ if (coreLibrary != null && library != coreLibrary) {
+ yield coreLibrary!;
+ }
+ for (LibraryDependency dependency in library.dependencies) {
+ yield dependency.targetLibrary;
+ }
+ }
+}
+
/// Computes the strongly connected components of [graph].
///
/// This implementation is based on [Dijkstra's path-based strong component
@@ -77,3 +107,93 @@
return result;
}
+
+/// A [Graph] using strongly connected components, as computed by
+/// [computeStrongComponents], as vertices. Neighbors are computed using the
+/// neighbors of the provided [subgraph] which was used to compute the strongly
+/// connected components.
+class StrongComponentGraph<T> implements Graph<List<T>> {
+ final Graph<T> subgraph;
+ final List<List<T>> components;
+ final Map<T, List<T>> _elementToComponentMap = {};
+ final Map<List<T>, Set<List<T>>> _neighborsMap = {};
+
+ StrongComponentGraph(this.subgraph, this.components) {
+ for (List<T> component in components) {
+ for (T element in component) {
+ _elementToComponentMap[element] = component;
+ }
+ }
+ }
+
+ Set<List<T>> _computeNeighborsOf(List<T> component) {
+ Set<List<T>> neighbors = {};
+ for (T element in component) {
+ for (T neighborElement in subgraph.neighborsOf(element)) {
+ List<T> neighborComponent = _elementToComponentMap[neighborElement]!;
+ if (component != neighborComponent) {
+ neighbors.add(neighborComponent);
+ }
+ }
+ }
+ return neighbors;
+ }
+
+ @override
+ Iterable<List<T>> neighborsOf(List<T> vertex) {
+ return _neighborsMap[vertex] ??= _computeNeighborsOf(vertex);
+ }
+
+ @override
+ Iterable<List<T>> get vertices => components;
+}
+
+/// Returns the non-cyclic vertices of [graph] sorted in topological order.
+///
+/// If [indexMap] is provided, it is filled with "index" of each vertex.
+/// If [layers] is provided, it is filled with a list of the vertices for each
+/// "index".
+///
+/// Here, the "index" of a vertex is the length of the longest path through
+/// neighbors. For vertices with no neighbors, the index is 0. For any other
+/// vertex, it is 1 plus max of the index of its neighbors.
+List<T> topologicalSort<T>(Graph<T> graph,
+ {Map<T, int>? indexMap, List<List<T>>? layers}) {
+ List<T> workList = graph.vertices.toList();
+ indexMap ??= {};
+ List<T> topologicallySortedVertices = [];
+ List<T> previousWorkList;
+ do {
+ previousWorkList = workList;
+ workList = [];
+ for (int i = 0; i < previousWorkList.length; i++) {
+ T vertex = previousWorkList[i];
+ int index = 0;
+ bool allSupertypesProcessed = true;
+ for (T neighbor in graph.neighborsOf(vertex)) {
+ int? neighborIndex = indexMap[neighbor];
+ if (neighborIndex == null) {
+ allSupertypesProcessed = false;
+ break;
+ } else {
+ index = max(index, neighborIndex + 1);
+ }
+ }
+ if (allSupertypesProcessed) {
+ indexMap[vertex] = index;
+ topologicallySortedVertices.add(vertex);
+ if (layers != null) {
+ if (index >= layers.length) {
+ assert(index == layers.length);
+ layers.add([vertex]);
+ } else {
+ layers[index].add(vertex);
+ }
+ }
+ } else {
+ workList.add(vertex);
+ }
+ }
+ } while (previousWorkList.length != workList.length);
+ return topologicallySortedVertices;
+}
diff --git a/tools/VERSION b/tools/VERSION
index c982ee7..d12c805 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 16
PATCH 0
-PRERELEASE 40
+PRERELEASE 41
PRERELEASE_PATCH 0
\ No newline at end of file