Version 2.17.0-65.0.dev
Merge commit 'f6ebe80d26883d41498d978198ab75649ee97a0d' into 'dev'
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index ea924c5..560c08b 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -109,7 +109,7 @@
<body>
<h1>Analysis Server API Specification</h1>
<h1 style="color:#999999">Version
- 1.32.8
+ 1.32.9
</h1>
<p>
This document contains a specification of the API provided by the
@@ -4392,7 +4392,7 @@
<dl><dt class="value">ANNOTATION</dt><dt class="value">BUILT_IN</dt><dt class="value">CLASS</dt><dt class="value">COMMENT_BLOCK</dt><dt class="value">COMMENT_DOCUMENTATION</dt><dt class="value">COMMENT_END_OF_LINE</dt><dt class="value">CONSTRUCTOR</dt><dt class="value">CONSTRUCTOR_TEAR_OFF</dt><dt class="value">DIRECTIVE</dt><dt class="value">DYNAMIC_TYPE</dt><dd>
<p>Deprecated - no longer sent.</p>
- </dd><dt class="value">DYNAMIC_LOCAL_VARIABLE_DECLARATION</dt><dt class="value">DYNAMIC_LOCAL_VARIABLE_REFERENCE</dt><dt class="value">DYNAMIC_PARAMETER_DECLARATION</dt><dt class="value">DYNAMIC_PARAMETER_REFERENCE</dt><dt class="value">ENUM</dt><dt class="value">ENUM_CONSTANT</dt><dt class="value">FIELD</dt><dd>
+ </dd><dt class="value">DYNAMIC_LOCAL_VARIABLE_DECLARATION</dt><dt class="value">DYNAMIC_LOCAL_VARIABLE_REFERENCE</dt><dt class="value">DYNAMIC_PARAMETER_DECLARATION</dt><dt class="value">DYNAMIC_PARAMETER_REFERENCE</dt><dt class="value">ENUM</dt><dt class="value">ENUM_CONSTANT</dt><dt class="value">EXTENSION</dt><dt class="value">FIELD</dt><dd>
<p>Deprecated - no longer sent.</p>
</dd><dt class="value">FIELD_STATIC</dt><dd>
diff --git a/pkg/analysis_server/lib/protocol/protocol_constants.dart b/pkg/analysis_server/lib/protocol/protocol_constants.dart
index ade68e1..3baa946 100644
--- a/pkg/analysis_server/lib/protocol/protocol_constants.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_constants.dart
@@ -6,7 +6,7 @@
// To regenerate the file, use the script
// "pkg/analysis_server/tool/spec/generate_files".
-const String PROTOCOL_VERSION = '1.32.8';
+const String PROTOCOL_VERSION = '1.32.9';
const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
diff --git a/pkg/analysis_server/lib/src/computer/computer_highlights.dart b/pkg/analysis_server/lib/src/computer/computer_highlights.dart
index 8881116..df18a65 100644
--- a/pkg/analysis_server/lib/src/computer/computer_highlights.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_highlights.dart
@@ -242,20 +242,9 @@
return false;
}
- // TODO(dantup): Right now there is no highlight type for extension, so
- // bail out and do the default thing (which will be to return
- // IDENTIFIER_DEFAULT). Adding EXTENSION requires coordination with
- // IntelliJ + bumping protocol version.
- if (!_computeSemanticTokens) {
- return false;
- }
-
return _addRegion_node(
node,
- // TODO(dantup): Change this to EXTENSION and add to LSP mapping when
- // we have it, but for now use CLASS (which is probably what we'll map it
- // to for LSP semantic tokens anyway).
- HighlightRegionType.CLASS,
+ HighlightRegionType.EXTENSION,
);
}
diff --git a/pkg/analysis_server/lib/src/lsp/semantic_tokens/mapping.dart b/pkg/analysis_server/lib/src/lsp/semantic_tokens/mapping.dart
index 7143991..68e43fd 100644
--- a/pkg/analysis_server/lib/src/lsp/semantic_tokens/mapping.dart
+++ b/pkg/analysis_server/lib/src/lsp/semantic_tokens/mapping.dart
@@ -123,6 +123,7 @@
HighlightRegionType.DYNAMIC_PARAMETER_REFERENCE: SemanticTokenTypes.parameter,
HighlightRegionType.ENUM: SemanticTokenTypes.enum_,
HighlightRegionType.ENUM_CONSTANT: SemanticTokenTypes.enumMember,
+ HighlightRegionType.EXTENSION: SemanticTokenTypes.class_,
HighlightRegionType.FUNCTION_TYPE_ALIAS: SemanticTokenTypes.type,
HighlightRegionType.IDENTIFIER_DEFAULT: CustomSemanticTokenTypes.source,
HighlightRegionType.IMPORT_PREFIX: SemanticTokenTypes.variable,
diff --git a/pkg/analysis_server/test/analysis/notification_highlights2_test.dart b/pkg/analysis_server/test/analysis/notification_highlights2_test.dart
index c97ddd3..ed4a472 100644
--- a/pkg/analysis_server/test/analysis/notification_highlights2_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_highlights2_test.dart
@@ -681,6 +681,20 @@
assertHasRegion(HighlightRegionType.ENUM_CONSTANT, 'BBB);');
}
+ Future<void> test_EXTENSION() async {
+ addTestFile('''
+extension E on int {
+ void foo() {}
+}
+void f() {
+ E(0).foo();
+}
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.EXTENSION, 'E on int');
+ assertHasRegion(HighlightRegionType.EXTENSION, 'E(0)');
+ }
+
Future<void> test_FUNCTION_TYPE_ALIAS() async {
addTestFile('''
typedef A();
diff --git a/pkg/analysis_server/test/integration/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
index 4b5a4ce..1e7cde4 100644
--- a/pkg/analysis_server/test/integration/support/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
@@ -794,6 +794,7 @@
/// DYNAMIC_PARAMETER_REFERENCE
/// ENUM
/// ENUM_CONSTANT
+/// EXTENSION
/// FIELD
/// FIELD_STATIC
/// FUNCTION
@@ -875,6 +876,7 @@
'DYNAMIC_PARAMETER_REFERENCE',
'ENUM',
'ENUM_CONSTANT',
+ 'EXTENSION',
'FIELD',
'FIELD_STATIC',
'FUNCTION',
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/HighlightRegionType.java b/pkg/analysis_server/tool/spec/generated/java/types/HighlightRegionType.java
index fe567c5..4c4e17f 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/HighlightRegionType.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/HighlightRegionType.java
@@ -50,6 +50,8 @@
public static final String ENUM_CONSTANT = "ENUM_CONSTANT";
+ public static final String EXTENSION = "EXTENSION";
+
/**
* Deprecated - no longer sent.
*/
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index 3c5c0ad..51f35a4 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -7,7 +7,7 @@
<body>
<h1>Analysis Server API Specification</h1>
<h1 style="color:#999999">Version
- <version>1.32.8</version>
+ <version>1.32.9</version>
</h1>
<p>
This document contains a specification of the API provided by the
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart
index 2223244..c1a528b 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart
@@ -1882,6 +1882,7 @@
/// DYNAMIC_PARAMETER_REFERENCE
/// ENUM
/// ENUM_CONSTANT
+/// EXTENSION
/// FIELD
/// FIELD_STATIC
/// FUNCTION
@@ -1995,6 +1996,9 @@
static const HighlightRegionType ENUM_CONSTANT =
HighlightRegionType._('ENUM_CONSTANT');
+ static const HighlightRegionType EXTENSION =
+ HighlightRegionType._('EXTENSION');
+
/// Deprecated - no longer sent.
static const HighlightRegionType FIELD = HighlightRegionType._('FIELD');
@@ -2210,6 +2214,7 @@
DYNAMIC_PARAMETER_REFERENCE,
ENUM,
ENUM_CONSTANT,
+ EXTENSION,
FIELD,
FIELD_STATIC,
FUNCTION,
@@ -2314,6 +2319,8 @@
return ENUM;
case 'ENUM_CONSTANT':
return ENUM_CONSTANT;
+ case 'EXTENSION':
+ return EXTENSION;
case 'FIELD':
return FIELD;
case 'FIELD_STATIC':
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
index ade68e1..3baa946 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
@@ -6,7 +6,7 @@
// To regenerate the file, use the script
// "pkg/analysis_server/tool/spec/generate_files".
-const String PROTOCOL_VERSION = '1.32.8';
+const String PROTOCOL_VERSION = '1.32.9';
const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
diff --git a/pkg/analyzer_plugin/doc/api.html b/pkg/analyzer_plugin/doc/api.html
index cba223d..a1c3097 100644
--- a/pkg/analyzer_plugin/doc/api.html
+++ b/pkg/analyzer_plugin/doc/api.html
@@ -1388,7 +1388,7 @@
<dl><dt class="value">ANNOTATION</dt><dt class="value">BUILT_IN</dt><dt class="value">CLASS</dt><dt class="value">COMMENT_BLOCK</dt><dt class="value">COMMENT_DOCUMENTATION</dt><dt class="value">COMMENT_END_OF_LINE</dt><dt class="value">CONSTRUCTOR</dt><dt class="value">CONSTRUCTOR_TEAR_OFF</dt><dt class="value">DIRECTIVE</dt><dt class="value">DYNAMIC_TYPE</dt><dd>
<p>Deprecated - no longer sent.</p>
- </dd><dt class="value">DYNAMIC_LOCAL_VARIABLE_DECLARATION</dt><dt class="value">DYNAMIC_LOCAL_VARIABLE_REFERENCE</dt><dt class="value">DYNAMIC_PARAMETER_DECLARATION</dt><dt class="value">DYNAMIC_PARAMETER_REFERENCE</dt><dt class="value">ENUM</dt><dt class="value">ENUM_CONSTANT</dt><dt class="value">FIELD</dt><dd>
+ </dd><dt class="value">DYNAMIC_LOCAL_VARIABLE_DECLARATION</dt><dt class="value">DYNAMIC_LOCAL_VARIABLE_REFERENCE</dt><dt class="value">DYNAMIC_PARAMETER_DECLARATION</dt><dt class="value">DYNAMIC_PARAMETER_REFERENCE</dt><dt class="value">ENUM</dt><dt class="value">ENUM_CONSTANT</dt><dt class="value">EXTENSION</dt><dt class="value">FIELD</dt><dd>
<p>Deprecated - no longer sent.</p>
</dd><dt class="value">FIELD_STATIC</dt><dd>
diff --git a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
index dd7d2a2..61b9776 100644
--- a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
+++ b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
@@ -1882,6 +1882,7 @@
/// DYNAMIC_PARAMETER_REFERENCE
/// ENUM
/// ENUM_CONSTANT
+/// EXTENSION
/// FIELD
/// FIELD_STATIC
/// FUNCTION
@@ -1995,6 +1996,9 @@
static const HighlightRegionType ENUM_CONSTANT =
HighlightRegionType._('ENUM_CONSTANT');
+ static const HighlightRegionType EXTENSION =
+ HighlightRegionType._('EXTENSION');
+
/// Deprecated - no longer sent.
static const HighlightRegionType FIELD = HighlightRegionType._('FIELD');
@@ -2210,6 +2214,7 @@
DYNAMIC_PARAMETER_REFERENCE,
ENUM,
ENUM_CONSTANT,
+ EXTENSION,
FIELD,
FIELD_STATIC,
FUNCTION,
@@ -2314,6 +2319,8 @@
return ENUM;
case 'ENUM_CONSTANT':
return ENUM_CONSTANT;
+ case 'EXTENSION':
+ return EXTENSION;
case 'FIELD':
return FIELD;
case 'FIELD_STATIC':
diff --git a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
index 164ea38..cdb3f12 100644
--- a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
+++ b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
@@ -379,6 +379,7 @@
/// DYNAMIC_PARAMETER_REFERENCE
/// ENUM
/// ENUM_CONSTANT
+/// EXTENSION
/// FIELD
/// FIELD_STATIC
/// FUNCTION
@@ -460,6 +461,7 @@
'DYNAMIC_PARAMETER_REFERENCE',
'ENUM',
'ENUM_CONSTANT',
+ 'EXTENSION',
'FIELD',
'FIELD_STATIC',
'FUNCTION',
diff --git a/pkg/analyzer_plugin/tool/spec/common_types_spec.html b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
index ce3a5e9..969a0ee 100644
--- a/pkg/analyzer_plugin/tool/spec/common_types_spec.html
+++ b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
@@ -719,6 +719,7 @@
</value>
<value><code>ENUM</code></value>
<value><code>ENUM_CONSTANT</code></value>
+ <value><code>EXTENSION</code></value>
<value>
<code>FIELD</code>
<p>Deprecated - no longer sent.</p>
diff --git a/pkg/compiler/lib/src/deferred_load/program_split_constraints/builder.dart b/pkg/compiler/lib/src/deferred_load/program_split_constraints/builder.dart
index 2520547..2428f3e 100644
--- a/pkg/compiler/lib/src/deferred_load/program_split_constraints/builder.dart
+++ b/pkg/compiler/lib/src/deferred_load/program_split_constraints/builder.dart
@@ -28,12 +28,10 @@
/// Imports which load before [import].
final Set<Constraint> predecessors = {};
- /// Whether or not this [ConstraintNode] should always apply transitions as
+ /// Whether or not this [Constraint] should always apply transitions as
/// opposed to conditionally applying transitions.
bool get alwaysApplyTransitions {
- return combinerType == null ||
- combinerType == CombinerType.and ||
- combinerType == CombinerType.fuse;
+ return combinerType == null || combinerType == CombinerType.and;
}
Constraint(this.name, this.imports, this.combinerType) {
@@ -122,19 +120,36 @@
// 3) Build a graph of [Constraint]s by processing user constraints and
// intializing each [Constraint]'s predecessor / successor members.
- for (var constraint in nodes.ordered) {
- var successor = nodeToConstraintMap[constraint.successor];
- var predecessor = nodeToConstraintMap[constraint.predecessor];
+ void createEdge(NamedNode successorNode, NamedNode predecessorNode) {
+ var successor = nodeToConstraintMap[successorNode];
+ var predecessor = nodeToConstraintMap[predecessorNode];
successor.predecessors.add(predecessor);
predecessor.successors.add(successor);
}
+ for (var constraint in nodes.ordered) {
+ if (constraint is RelativeOrderNode) {
+ createEdge(constraint.successor, constraint.predecessor);
+ } else if (constraint is FuseNode) {
+ // Fuse nodes are just syntactic sugar for generating cycles in the
+ // ordering graph.
+ for (var node1 in constraint.nodes) {
+ for (var node2 in constraint.nodes) {
+ if (node1 != node2) {
+ createEdge(node1, node2);
+ }
+ }
+ }
+ }
+ }
+
// 4) Compute the transitive closure of constraints. This gives us a map of
// transitiveTransitions, where each key is a parent [ImportEntity] and each
// value represents the transitive set of child [ImportEntity]s which are
// always loaded after the parent.
Map<ImportEntity, Set<ImportEntity>> singletonTransitions = {};
Map<Constraint, SetTransition> setTransitions = {};
+ Map<Constraint, Set<ImportEntity>> processed = {};
Queue<_WorkItem> queue = Queue.from(nodeToConstraintMap.values
.where((node) => node.successors.isEmpty)
.map((node) => _WorkItem(node)));
@@ -154,14 +169,6 @@
for (var import in imports) {
// We insert an implicit 'self' transition for every import.
var transitions = singletonTransitions[import] ??= {import};
-
- // In the case of [CombinerType.fuse], the nodes in the
- // [Constraint] form a strongly connected component,
- // i.e. [ImportEntity]s that are always part of a
- // single [ImportSet].
- if (constraint.combinerType == CombinerType.fuse) {
- transitions.addAll(imports);
- }
transitions.addAll(transitiveChildren);
}
} else {
@@ -177,6 +184,14 @@
...transitiveChildren,
};
for (var predecessor in constraint.predecessors) {
+ // We allow cycles in the constraint graph, so we need to support
+ // reprocessing constraints when we need to consider new transitive
+ // children.
+ if (processed.containsKey(predecessor) &&
+ processed[predecessor].containsAll(predecessorTransitiveChildren)) {
+ continue;
+ }
+ (processed[predecessor] ??= {}).addAll(predecessorTransitiveChildren);
queue.add(_WorkItem(predecessor,
transitiveChildren: predecessorTransitiveChildren));
}
diff --git a/pkg/compiler/lib/src/deferred_load/program_split_constraints/nodes.dart b/pkg/compiler/lib/src/deferred_load/program_split_constraints/nodes.dart
index 92068f6..17a6904 100644
--- a/pkg/compiler/lib/src/deferred_load/program_split_constraints/nodes.dart
+++ b/pkg/compiler/lib/src/deferred_load/program_split_constraints/nodes.dart
@@ -71,13 +71,11 @@
/// A [CombinerType] defines how to combine multiple [ReferenceNode]s in a
/// single step.
-enum CombinerType { fuse, and, or }
+enum CombinerType { and, or }
CombinerType parseCombinerType(Map<String, dynamic> nodeJson) {
String type = nodeJson['type'];
switch (type) {
- case 'fuse':
- return CombinerType.fuse;
case 'and':
return CombinerType.and;
case 'or':
@@ -89,8 +87,6 @@
String combinerTypeToString(CombinerType type) {
switch (type) {
- case CombinerType.fuse:
- return 'fuse';
case CombinerType.and:
return 'and';
case CombinerType.or:
@@ -151,9 +147,13 @@
}
}
+/// An [OrderNode] is a [Node] without a name that indicates a temporal
+/// constraint.
+abstract class OrderNode extends Node {}
+
/// A [RelativeOrderNode] is an unnamed [Node] which defines a relative
/// load order between two [NamedNode]s.
-class RelativeOrderNode extends Node {
+class RelativeOrderNode extends OrderNode {
final NamedNode predecessor;
final NamedNode successor;
@@ -165,7 +165,7 @@
@override
Map<String, dynamic> toJson() {
return {
- 'type': 'order',
+ 'type': 'relative_order',
'predecessor': predecessor.name,
'successor': successor.name
};
@@ -185,6 +185,35 @@
}
}
+/// A [FuseNode] is an [OrderNode] with a list of [NamedNode] children.
+/// A [FuseNode] joins its children into a strongly connected component.
+class FuseNode extends OrderNode {
+ final Set<NamedNode> nodes;
+
+ FuseNode(this.nodes);
+
+ @override
+ Map<String, dynamic> toJson() {
+ return {'type': 'fuse', 'nodes': nodes.map((node) => node.name).toList()};
+ }
+
+ static FuseNode fromJson(
+ Map<String, dynamic> nodeJson, Map<String, NamedNode> nameMap) {
+ List<dynamic> referencesJson = _jsonLookup(nodeJson, 'nodes');
+ Set<NamedNode> nodes = {};
+ for (String reference in referencesJson) {
+ nodes.add(nameMap[reference]);
+ }
+ return FuseNode(nodes);
+ }
+
+ @override
+ String toString() {
+ var nodeNames = nodes.map((node) => node.name).join(', ');
+ return 'FuseNode(nodes=$nodeNames)';
+ }
+}
+
/// A builder class for constructing constraint nodes.
typedef ReferenceNodeNamer = String Function(UriAndPrefix);
@@ -221,6 +250,14 @@
return namedNodes[nodeName];
}
+ ReferenceNode _lookupReferenceNode(String nodeName) {
+ var node = _lookupNamedNode(nodeName);
+ if (node is! ReferenceNode) {
+ throw 'node $nodeName is not a ReferenceNode.';
+ }
+ return node as ReferenceNode;
+ }
+
/// Returns a [ReferenceNode] referencing [importUriAndPrefix].
/// [ReferenceNode]s are typically created in bulk, by mapping over a list of
/// strings of imports in the form 'uri#prefix'. In further builder calls,
@@ -242,16 +279,8 @@
/// Creates a [CombinerNode] which can be referenced by [name] in further
/// calls to the builder.
CombinerNode combinerNode(String name, Set<String> nodes, CombinerType type) {
- ReferenceNode _lookup(String nodeName) {
- var node = _lookupNamedNode(nodeName);
- if (node is! ReferenceNode) {
- // TODO(joshualitt): Implement nested combiners.
- throw '$name references node $nodeName which is not a ReferenceNode.';
- }
- return node as ReferenceNode;
- }
-
- return _addNamedNode(CombinerNode(name, type, nodes.map(_lookup).toSet()));
+ return _addNamedNode(
+ CombinerNode(name, type, nodes.map(_lookupReferenceNode).toSet()));
}
/// Creates an 'and' [CombinerNode] which can be referenced by [name] in
@@ -260,10 +289,10 @@
return combinerNode(name, nodes, CombinerType.and);
}
- /// Creates a 'fuse' [CombinerNode] which can be referenced by [name] in
- /// further calls to the builder.
- CombinerNode fuseNode(String name, Set<String> nodes) {
- return combinerNode(name, nodes, CombinerType.fuse);
+ /// Creates a [FuseNode], which is a type of [OrderNode] indicating a
+ /// [Set<String>] nodes can always be loaded together.
+ FuseNode fuseNode(Set<String> nodes) {
+ return FuseNode(nodes.map(_lookupNamedNode).toSet());
}
/// Creates an 'or' [CombinerNode] which can be referenced by [name] in
@@ -277,7 +306,7 @@
/// program split constraints.
class ConstraintData {
final List<NamedNode> named;
- final List<RelativeOrderNode> ordered;
+ final List<OrderNode> ordered;
ConstraintData(this.named, this.ordered);
}
diff --git a/pkg/compiler/lib/src/deferred_load/program_split_constraints/parser.dart b/pkg/compiler/lib/src/deferred_load/program_split_constraints/parser.dart
index 968b07b..e60c182 100644
--- a/pkg/compiler/lib/src/deferred_load/program_split_constraints/parser.dart
+++ b/pkg/compiler/lib/src/deferred_load/program_split_constraints/parser.dart
@@ -10,7 +10,7 @@
/// [ConstraintData] object.
class Parser {
final Map<String, NamedNode> nameMap = {};
- final List<RelativeOrderNode> orderedNodes = [];
+ final List<OrderNode> orderedNodes = [];
void parseReference(Map<String, dynamic> nodeJson) {
var reference = ReferenceNode.fromJson(nodeJson);
@@ -22,29 +22,36 @@
nameMap[combinerNode.name] = combinerNode;
}
- void parseOrder(Map<String, dynamic> nodeJson) {
+ void parseRelativeOrder(Map<String, dynamic> nodeJson) {
orderedNodes.add(RelativeOrderNode.fromJson(nodeJson, nameMap));
}
+ void parseFuse(Map<String, dynamic> nodeJson) {
+ orderedNodes.add(FuseNode.fromJson(nodeJson, nameMap));
+ }
+
/// Reads a program split constraints json file string and returns a [Nodes]
/// object reflecting the parsed constraints.
ConstraintData read(String programSplitJson) {
List<dynamic> doc = json.decode(programSplitJson);
List<Map<String, dynamic>> referenceConstraints = [];
List<Map<String, dynamic>> combinerConstraints = [];
- List<Map<String, dynamic>> orderConstraints = [];
+ List<Map<String, dynamic>> fuseConstraints = [];
+ List<Map<String, dynamic>> relativeOrderConstraints = [];
for (Map<String, dynamic> constraint in doc) {
switch (constraint['type']) {
case 'reference':
referenceConstraints.add(constraint);
break;
case 'and':
- case 'fuse':
case 'or':
combinerConstraints.add(constraint);
break;
- case 'order':
- orderConstraints.add(constraint);
+ case 'fuse':
+ fuseConstraints.add(constraint);
+ break;
+ case 'relative_order':
+ relativeOrderConstraints.add(constraint);
break;
default:
throw 'Unrecognized constraint type in $constraint';
@@ -54,7 +61,8 @@
// Parse references, than combiners, than finally sequences.
referenceConstraints.forEach(parseReference);
combinerConstraints.forEach(parseCombiner);
- orderConstraints.forEach(parseOrder);
+ fuseConstraints.forEach(parseFuse);
+ relativeOrderConstraints.forEach(parseRelativeOrder);
return ConstraintData(nameMap.values.toList(), orderedNodes);
}
}
diff --git a/pkg/compiler/test/custom_split/custom_split_test.dart b/pkg/compiler/test/custom_split/custom_split_test.dart
index f1e4fd4..7f4c4dc 100644
--- a/pkg/compiler/test/custom_split/custom_split_test.dart
+++ b/pkg/compiler/test/custom_split/custom_split_test.dart
@@ -24,6 +24,8 @@
'diamond_and',
'diamond_fuse',
'diamond_or',
+ 'fuse_with_and',
+ 'fuse_with_or',
'two_step',
'two_branch',
];
diff --git a/pkg/compiler/test/custom_split/data/diamond/constraints.json b/pkg/compiler/test/custom_split/data/diamond/constraints.json
index 21b8afa..537cf0b 100644
--- a/pkg/compiler/test/custom_split/data/diamond/constraints.json
+++ b/pkg/compiler/test/custom_split/data/diamond/constraints.json
@@ -20,22 +20,22 @@
"import": "memory:sdk/tests/web/native/main.dart#step3"
},
{
- "type": "order",
+ "type": "relative_order",
"predecessor": "memory:sdk/tests/web/native/main.dart#step1",
"successor": "memory:sdk/tests/web/native/main.dart#step2a"
},
{
- "type": "order",
+ "type": "relative_order",
"predecessor": "memory:sdk/tests/web/native/main.dart#step1",
"successor": "memory:sdk/tests/web/native/main.dart#step2b"
},
{
- "type": "order",
+ "type": "relative_order",
"predecessor": "memory:sdk/tests/web/native/main.dart#step2a",
"successor": "memory:sdk/tests/web/native/main.dart#step3"
},
{
- "type": "order",
+ "type": "relative_order",
"predecessor": "memory:sdk/tests/web/native/main.dart#step2b",
"successor": "memory:sdk/tests/web/native/main.dart#step3"
}
diff --git a/pkg/compiler/test/custom_split/data/diamond_and/constraints.json b/pkg/compiler/test/custom_split/data/diamond_and/constraints.json
index 85344e7..bf91a12 100644
--- a/pkg/compiler/test/custom_split/data/diamond_and/constraints.json
+++ b/pkg/compiler/test/custom_split/data/diamond_and/constraints.json
@@ -28,12 +28,12 @@
]
},
{
- "type": "order",
+ "type": "relative_order",
"predecessor": "memory:sdk/tests/web/native/main.dart#step1",
"successor": "step2"
},
{
- "type": "order",
+ "type": "relative_order",
"predecessor": "step2",
"successor": "memory:sdk/tests/web/native/main.dart#step3"
}
diff --git a/pkg/compiler/test/custom_split/data/diamond_fuse/constraints.dart b/pkg/compiler/test/custom_split/data/diamond_fuse/constraints.dart
index 145cbd1..a0fe64f 100644
--- a/pkg/compiler/test/custom_split/data/diamond_fuse/constraints.dart
+++ b/pkg/compiler/test/custom_split/data/diamond_fuse/constraints.dart
@@ -19,8 +19,8 @@
var builder = ProgramSplitBuilder();
return [
...imports.map(builder.referenceNode),
- builder.fuseNode('step2', {step2a, step2b}),
- builder.orderNode(step1, 'step2'),
- builder.orderNode('step2', step3),
+ builder.fuseNode({step2a, step2b}),
+ builder.orderNode(step1, step2a),
+ builder.orderNode(step2b, step3),
];
}
diff --git a/pkg/compiler/test/custom_split/data/diamond_fuse/constraints.json b/pkg/compiler/test/custom_split/data/diamond_fuse/constraints.json
index dccfe20..835bebe 100644
--- a/pkg/compiler/test/custom_split/data/diamond_fuse/constraints.json
+++ b/pkg/compiler/test/custom_split/data/diamond_fuse/constraints.json
@@ -21,20 +21,19 @@
},
{
"type": "fuse",
- "name": "step2",
"nodes": [
"memory:sdk/tests/web/native/main.dart#step2a",
"memory:sdk/tests/web/native/main.dart#step2b"
]
},
{
- "type": "order",
+ "type": "relative_order",
"predecessor": "memory:sdk/tests/web/native/main.dart#step1",
- "successor": "step2"
+ "successor": "memory:sdk/tests/web/native/main.dart#step2a"
},
{
- "type": "order",
- "predecessor": "step2",
+ "type": "relative_order",
+ "predecessor": "memory:sdk/tests/web/native/main.dart#step2b",
"successor": "memory:sdk/tests/web/native/main.dart#step3"
}
]
\ No newline at end of file
diff --git a/pkg/compiler/test/custom_split/data/diamond_or/constraints.json b/pkg/compiler/test/custom_split/data/diamond_or/constraints.json
index c4091f4..f4ea01b 100644
--- a/pkg/compiler/test/custom_split/data/diamond_or/constraints.json
+++ b/pkg/compiler/test/custom_split/data/diamond_or/constraints.json
@@ -28,12 +28,12 @@
]
},
{
- "type": "order",
+ "type": "relative_order",
"predecessor": "memory:sdk/tests/web/native/main.dart#step1",
"successor": "step2"
},
{
- "type": "order",
+ "type": "relative_order",
"predecessor": "step2",
"successor": "memory:sdk/tests/web/native/main.dart#step3"
}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_and/constraints.dart b/pkg/compiler/test/custom_split/data/fuse_with_and/constraints.dart
new file mode 100644
index 0000000..12a80ee
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_and/constraints.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2022, 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 'dart:isolate';
+
+import 'package:compiler/src/deferred_load/program_split_constraints/nodes.dart';
+import '../../constraint_harness.dart';
+
+void main(List<String> args, SendPort sendPort) {
+ waitForImportsAndInvoke(sendPort, processDeferredImports);
+}
+
+List<Node> processDeferredImports(List<String> imports) {
+ var lib1 = 'memory:sdk/tests/web/native/lib1.dart#b1';
+ var lib2 = 'memory:sdk/tests/web/native/lib2.dart#b2';
+ var lib3 = 'memory:sdk/tests/web/native/lib3.dart#b3';
+ var lib4 = 'memory:sdk/tests/web/native/lib4.dart#b4';
+ var builder = ProgramSplitBuilder();
+ return [
+ ...imports.map(builder.referenceNode),
+ builder.andNode('lib1_and_lib2', {lib1, lib2}),
+ builder.fuseNode({'lib1_and_lib2', lib3}),
+ builder.orderNode(lib3, lib4),
+ ];
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_and/constraints.json b/pkg/compiler/test/custom_split/data/fuse_with_and/constraints.json
new file mode 100644
index 0000000..d95cc50
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_and/constraints.json
@@ -0,0 +1,42 @@
+[
+ {
+ "type": "reference",
+ "name": "memory:sdk/tests/web/native/lib1.dart#b1",
+ "import": "memory:sdk/tests/web/native/lib1.dart#b1"
+ },
+ {
+ "type": "reference",
+ "name": "memory:sdk/tests/web/native/lib2.dart#b2",
+ "import": "memory:sdk/tests/web/native/lib2.dart#b2"
+ },
+ {
+ "type": "reference",
+ "name": "memory:sdk/tests/web/native/lib3.dart#b3",
+ "import": "memory:sdk/tests/web/native/lib3.dart#b3"
+ },
+ {
+ "type": "reference",
+ "name": "memory:sdk/tests/web/native/lib4.dart#b4",
+ "import": "memory:sdk/tests/web/native/lib4.dart#b4"
+ },
+ {
+ "type": "and",
+ "name": "lib1_and_lib2",
+ "nodes": [
+ "memory:sdk/tests/web/native/lib1.dart#b1",
+ "memory:sdk/tests/web/native/lib2.dart#b2"
+ ]
+ },
+ {
+ "type": "fuse",
+ "nodes": [
+ "lib1_and_lib2",
+ "memory:sdk/tests/web/native/lib3.dart#b3"
+ ]
+ },
+ {
+ "type": "relative_order",
+ "predecessor": "memory:sdk/tests/web/native/lib3.dart#b3",
+ "successor": "memory:sdk/tests/web/native/lib4.dart#b4"
+ }
+]
\ No newline at end of file
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_and/lib1.dart b/pkg/compiler/test/custom_split/data/fuse_with_and/lib1.dart
new file mode 100644
index 0000000..33e2c05
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_and/lib1.dart
@@ -0,0 +1,12 @@
+// 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.
+
+// This file was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import 'lib_100_0.dart' deferred as b1;
+
+/*member: entryLib1:member_unit=main{}*/
+entryLib1() async {
+ await b1.loadLibrary();
+ b1.g_100_0();
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_and/lib2.dart b/pkg/compiler/test/custom_split/data/fuse_with_and/lib2.dart
new file mode 100644
index 0000000..1ad0cd3
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_and/lib2.dart
@@ -0,0 +1,12 @@
+// 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.
+
+// This file was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import 'lib_010_0.dart' deferred as b2;
+
+/*member: entryLib2:member_unit=main{}*/
+entryLib2() async {
+ await b2.loadLibrary();
+ b2.g_010_0();
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_and/lib3.dart b/pkg/compiler/test/custom_split/data/fuse_with_and/lib3.dart
new file mode 100644
index 0000000..1d2b9d5
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_and/lib3.dart
@@ -0,0 +1,12 @@
+// 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.
+
+// This file was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import 'lib_001_0.dart' deferred as b3;
+
+/*member: entryLib3:member_unit=main{}*/
+entryLib3() async {
+ await b3.loadLibrary();
+ b3.g_001_0();
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_and/lib4.dart b/pkg/compiler/test/custom_split/data/fuse_with_and/lib4.dart
new file mode 100644
index 0000000..1eedd87
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_and/lib4.dart
@@ -0,0 +1,12 @@
+// 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.
+
+// This file was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import 'lib_000_1.dart' deferred as b4;
+
+/*member: entryLib4:member_unit=main{}*/
+entryLib4() async {
+ await b4.loadLibrary();
+ b4.g_000_1();
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_and/libImport.dart b/pkg/compiler/test/custom_split/data/fuse_with_and/libImport.dart
new file mode 100644
index 0000000..d55f632
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_and/libImport.dart
@@ -0,0 +1,58 @@
+// 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.
+
+// This file was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import "package:expect/expect.dart";
+
+/*member: v:member_unit=1{b1, b2, b3, b4}*/
+void v(Set<String> u, String name, int bit) {
+ Expect.isTrue(u.add(name));
+ Expect.equals(name[bit], '1');
+}
+
+@pragma('dart2js:noInline')
+/*member: f_100_0:member_unit=1{b1, b2, b3, b4}*/
+f_100_0(Set<String> u, int b) => v(u, '1000', b);
+@pragma('dart2js:noInline')
+/*member: f_100_1:member_unit=1{b1, b2, b3, b4}*/
+f_100_1(Set<String> u, int b) => v(u, '1001', b);
+@pragma('dart2js:noInline')
+/*member: f_101_0:member_unit=1{b1, b2, b3, b4}*/
+f_101_0(Set<String> u, int b) => v(u, '1010', b);
+@pragma('dart2js:noInline')
+/*member: f_101_1:member_unit=1{b1, b2, b3, b4}*/
+f_101_1(Set<String> u, int b) => v(u, '1011', b);
+@pragma('dart2js:noInline')
+/*member: f_110_0:member_unit=1{b1, b2, b3, b4}*/
+f_110_0(Set<String> u, int b) => v(u, '1100', b);
+@pragma('dart2js:noInline')
+/*member: f_110_1:member_unit=1{b1, b2, b3, b4}*/
+f_110_1(Set<String> u, int b) => v(u, '1101', b);
+@pragma('dart2js:noInline')
+/*member: f_111_0:member_unit=1{b1, b2, b3, b4}*/
+f_111_0(Set<String> u, int b) => v(u, '1110', b);
+@pragma('dart2js:noInline')
+/*member: f_111_1:member_unit=1{b1, b2, b3, b4}*/
+f_111_1(Set<String> u, int b) => v(u, '1111', b);
+@pragma('dart2js:noInline')
+/*member: f_010_0:member_unit=1{b1, b2, b3, b4}*/
+f_010_0(Set<String> u, int b) => v(u, '0100', b);
+@pragma('dart2js:noInline')
+/*member: f_010_1:member_unit=1{b1, b2, b3, b4}*/
+f_010_1(Set<String> u, int b) => v(u, '0101', b);
+@pragma('dart2js:noInline')
+/*member: f_011_0:member_unit=1{b1, b2, b3, b4}*/
+f_011_0(Set<String> u, int b) => v(u, '0110', b);
+@pragma('dart2js:noInline')
+/*member: f_011_1:member_unit=1{b1, b2, b3, b4}*/
+f_011_1(Set<String> u, int b) => v(u, '0111', b);
+@pragma('dart2js:noInline')
+/*member: f_001_0:member_unit=1{b1, b2, b3, b4}*/
+f_001_0(Set<String> u, int b) => v(u, '0010', b);
+@pragma('dart2js:noInline')
+/*member: f_001_1:member_unit=1{b1, b2, b3, b4}*/
+f_001_1(Set<String> u, int b) => v(u, '0011', b);
+@pragma('dart2js:noInline')
+/*member: f_000_1:member_unit=2{b4}*/
+f_000_1(Set<String> u, int b) => v(u, '0001', b);
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_and/lib_000_1.dart b/pkg/compiler/test/custom_split/data/fuse_with_and/lib_000_1.dart
new file mode 100644
index 0000000..091a013
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_and/lib_000_1.dart
@@ -0,0 +1,25 @@
+// 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.
+
+// This file was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import "package:expect/expect.dart";
+
+import 'libImport.dart';
+
+@pragma('dart2js:noInline')
+/*member: g_000_1:member_unit=2{b4}*/
+g_000_1() {
+ Set<String> uniques = {};
+
+ // f_***_1;
+ f_000_1(uniques, 3);
+ f_001_1(uniques, 3);
+ f_010_1(uniques, 3);
+ f_011_1(uniques, 3);
+ f_100_1(uniques, 3);
+ f_101_1(uniques, 3);
+ f_110_1(uniques, 3);
+ f_111_1(uniques, 3);
+ Expect.equals(8, uniques.length);
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_and/lib_001_0.dart b/pkg/compiler/test/custom_split/data/fuse_with_and/lib_001_0.dart
new file mode 100644
index 0000000..19906dd
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_and/lib_001_0.dart
@@ -0,0 +1,25 @@
+// 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.
+
+// This file was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import "package:expect/expect.dart";
+
+import 'libImport.dart';
+
+@pragma('dart2js:noInline')
+/*member: g_001_0:member_unit=1{b1, b2, b3, b4}*/
+g_001_0() {
+ Set<String> uniques = {};
+
+ // f_**1_*;
+ f_001_0(uniques, 2);
+ f_001_1(uniques, 2);
+ f_011_0(uniques, 2);
+ f_011_1(uniques, 2);
+ f_101_0(uniques, 2);
+ f_101_1(uniques, 2);
+ f_111_0(uniques, 2);
+ f_111_1(uniques, 2);
+ Expect.equals(8, uniques.length);
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_and/lib_010_0.dart b/pkg/compiler/test/custom_split/data/fuse_with_and/lib_010_0.dart
new file mode 100644
index 0000000..22b05ac
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_and/lib_010_0.dart
@@ -0,0 +1,25 @@
+// 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.
+
+// This file was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import "package:expect/expect.dart";
+
+import 'libImport.dart';
+
+@pragma('dart2js:noInline')
+/*member: g_010_0:member_unit=1{b1, b2, b3, b4}*/
+g_010_0() {
+ Set<String> uniques = {};
+
+ // f_*1*_*;
+ f_010_0(uniques, 1);
+ f_010_1(uniques, 1);
+ f_011_0(uniques, 1);
+ f_011_1(uniques, 1);
+ f_110_0(uniques, 1);
+ f_110_1(uniques, 1);
+ f_111_0(uniques, 1);
+ f_111_1(uniques, 1);
+ Expect.equals(8, uniques.length);
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_and/lib_100_0.dart b/pkg/compiler/test/custom_split/data/fuse_with_and/lib_100_0.dart
new file mode 100644
index 0000000..d39141b
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_and/lib_100_0.dart
@@ -0,0 +1,25 @@
+// 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.
+
+// This file was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import "package:expect/expect.dart";
+
+import 'libImport.dart';
+
+@pragma('dart2js:noInline')
+/*member: g_100_0:member_unit=1{b1, b2, b3, b4}*/
+g_100_0() {
+ Set<String> uniques = {};
+
+ // f_1**_*;
+ f_100_0(uniques, 0);
+ f_100_1(uniques, 0);
+ f_101_0(uniques, 0);
+ f_101_1(uniques, 0);
+ f_110_0(uniques, 0);
+ f_110_1(uniques, 0);
+ f_111_0(uniques, 0);
+ f_111_1(uniques, 0);
+ Expect.equals(8, uniques.length);
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_and/main.dart b/pkg/compiler/test/custom_split/data/fuse_with_and/main.dart
new file mode 100644
index 0000000..f07ccf9
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_and/main.dart
@@ -0,0 +1,31 @@
+// 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:
+ a_pre_fragments=[
+ p1: {units: [2{b4}], usedBy: [], needs: []},
+ p2: {units: [1{b1, b2, b3, b4}], usedBy: [], needs: []}],
+ b_finalized_fragments=[
+ f1: [2{b4}],
+ f2: [1{b1, b2, b3, b4}]],
+ c_steps=[
+ b1=(f2),
+ b2=(f2),
+ b3=(f2),
+ b4=(f2, f1)]
+*/
+
+// This file was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import 'lib1.dart';
+import 'lib2.dart';
+import 'lib3.dart';
+import 'lib4.dart';
+
+/*member: main:member_unit=main{}*/
+main() {
+ entryLib1();
+ entryLib2();
+ entryLib3();
+ entryLib4();
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_or/constraints.dart b/pkg/compiler/test/custom_split/data/fuse_with_or/constraints.dart
new file mode 100644
index 0000000..370ca10
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_or/constraints.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2022, 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 'dart:isolate';
+
+import 'package:compiler/src/deferred_load/program_split_constraints/nodes.dart';
+import '../../constraint_harness.dart';
+
+void main(List<String> args, SendPort sendPort) {
+ waitForImportsAndInvoke(sendPort, processDeferredImports);
+}
+
+List<Node> processDeferredImports(List<String> imports) {
+ var lib1 = 'memory:sdk/tests/web/native/lib1.dart#b1';
+ var lib2 = 'memory:sdk/tests/web/native/lib2.dart#b2';
+ var lib3 = 'memory:sdk/tests/web/native/lib3.dart#b3';
+ var lib4 = 'memory:sdk/tests/web/native/lib4.dart#b4';
+ var builder = ProgramSplitBuilder();
+ return [
+ ...imports.map(builder.referenceNode),
+ builder.orNode('lib1_or_lib2', {lib1, lib2}),
+ builder.fuseNode({'lib1_or_lib2', lib3}),
+ builder.orderNode(lib3, lib4),
+ ];
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_or/constraints.json b/pkg/compiler/test/custom_split/data/fuse_with_or/constraints.json
new file mode 100644
index 0000000..6d44688
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_or/constraints.json
@@ -0,0 +1,42 @@
+[
+ {
+ "type": "reference",
+ "name": "memory:sdk/tests/web/native/lib1.dart#b1",
+ "import": "memory:sdk/tests/web/native/lib1.dart#b1"
+ },
+ {
+ "type": "reference",
+ "name": "memory:sdk/tests/web/native/lib2.dart#b2",
+ "import": "memory:sdk/tests/web/native/lib2.dart#b2"
+ },
+ {
+ "type": "reference",
+ "name": "memory:sdk/tests/web/native/lib3.dart#b3",
+ "import": "memory:sdk/tests/web/native/lib3.dart#b3"
+ },
+ {
+ "type": "reference",
+ "name": "memory:sdk/tests/web/native/lib4.dart#b4",
+ "import": "memory:sdk/tests/web/native/lib4.dart#b4"
+ },
+ {
+ "type": "or",
+ "name": "lib1_or_lib2",
+ "nodes": [
+ "memory:sdk/tests/web/native/lib1.dart#b1",
+ "memory:sdk/tests/web/native/lib2.dart#b2"
+ ]
+ },
+ {
+ "type": "fuse",
+ "nodes": [
+ "lib1_or_lib2",
+ "memory:sdk/tests/web/native/lib3.dart#b3"
+ ]
+ },
+ {
+ "type": "relative_order",
+ "predecessor": "memory:sdk/tests/web/native/lib3.dart#b3",
+ "successor": "memory:sdk/tests/web/native/lib4.dart#b4"
+ }
+]
\ No newline at end of file
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_or/lib1.dart b/pkg/compiler/test/custom_split/data/fuse_with_or/lib1.dart
new file mode 100644
index 0000000..33e2c05
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_or/lib1.dart
@@ -0,0 +1,12 @@
+// 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.
+
+// This file was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import 'lib_100_0.dart' deferred as b1;
+
+/*member: entryLib1:member_unit=main{}*/
+entryLib1() async {
+ await b1.loadLibrary();
+ b1.g_100_0();
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_or/lib2.dart b/pkg/compiler/test/custom_split/data/fuse_with_or/lib2.dart
new file mode 100644
index 0000000..1ad0cd3
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_or/lib2.dart
@@ -0,0 +1,12 @@
+// 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.
+
+// This file was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import 'lib_010_0.dart' deferred as b2;
+
+/*member: entryLib2:member_unit=main{}*/
+entryLib2() async {
+ await b2.loadLibrary();
+ b2.g_010_0();
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_or/lib3.dart b/pkg/compiler/test/custom_split/data/fuse_with_or/lib3.dart
new file mode 100644
index 0000000..1d2b9d5
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_or/lib3.dart
@@ -0,0 +1,12 @@
+// 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.
+
+// This file was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import 'lib_001_0.dart' deferred as b3;
+
+/*member: entryLib3:member_unit=main{}*/
+entryLib3() async {
+ await b3.loadLibrary();
+ b3.g_001_0();
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_or/lib4.dart b/pkg/compiler/test/custom_split/data/fuse_with_or/lib4.dart
new file mode 100644
index 0000000..1eedd87
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_or/lib4.dart
@@ -0,0 +1,12 @@
+// 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.
+
+// This file was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import 'lib_000_1.dart' deferred as b4;
+
+/*member: entryLib4:member_unit=main{}*/
+entryLib4() async {
+ await b4.loadLibrary();
+ b4.g_000_1();
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_or/libImport.dart b/pkg/compiler/test/custom_split/data/fuse_with_or/libImport.dart
new file mode 100644
index 0000000..dd4364a
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_or/libImport.dart
@@ -0,0 +1,58 @@
+// 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.
+
+// This file was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import "package:expect/expect.dart";
+
+/*member: v:member_unit=2{b1, b2, b3, b4}*/
+void v(Set<String> u, String name, int bit) {
+ Expect.isTrue(u.add(name));
+ Expect.equals(name[bit], '1');
+}
+
+@pragma('dart2js:noInline')
+/*member: f_100_0:member_unit=1{b1}*/
+f_100_0(Set<String> u, int b) => v(u, '1000', b);
+@pragma('dart2js:noInline')
+/*member: f_100_1:member_unit=3{b1, b4}*/
+f_100_1(Set<String> u, int b) => v(u, '1001', b);
+@pragma('dart2js:noInline')
+/*member: f_101_0:member_unit=2{b1, b2, b3, b4}*/
+f_101_0(Set<String> u, int b) => v(u, '1010', b);
+@pragma('dart2js:noInline')
+/*member: f_101_1:member_unit=2{b1, b2, b3, b4}*/
+f_101_1(Set<String> u, int b) => v(u, '1011', b);
+@pragma('dart2js:noInline')
+/*member: f_110_0:member_unit=2{b1, b2, b3, b4}*/
+f_110_0(Set<String> u, int b) => v(u, '1100', b);
+@pragma('dart2js:noInline')
+/*member: f_110_1:member_unit=2{b1, b2, b3, b4}*/
+f_110_1(Set<String> u, int b) => v(u, '1101', b);
+@pragma('dart2js:noInline')
+/*member: f_111_0:member_unit=2{b1, b2, b3, b4}*/
+f_111_0(Set<String> u, int b) => v(u, '1110', b);
+@pragma('dart2js:noInline')
+/*member: f_111_1:member_unit=2{b1, b2, b3, b4}*/
+f_111_1(Set<String> u, int b) => v(u, '1111', b);
+@pragma('dart2js:noInline')
+/*member: f_010_0:member_unit=4{b2}*/
+f_010_0(Set<String> u, int b) => v(u, '0100', b);
+@pragma('dart2js:noInline')
+/*member: f_010_1:member_unit=5{b2, b4}*/
+f_010_1(Set<String> u, int b) => v(u, '0101', b);
+@pragma('dart2js:noInline')
+/*member: f_011_0:member_unit=2{b1, b2, b3, b4}*/
+f_011_0(Set<String> u, int b) => v(u, '0110', b);
+@pragma('dart2js:noInline')
+/*member: f_011_1:member_unit=2{b1, b2, b3, b4}*/
+f_011_1(Set<String> u, int b) => v(u, '0111', b);
+@pragma('dart2js:noInline')
+/*member: f_001_0:member_unit=2{b1, b2, b3, b4}*/
+f_001_0(Set<String> u, int b) => v(u, '0010', b);
+@pragma('dart2js:noInline')
+/*member: f_001_1:member_unit=2{b1, b2, b3, b4}*/
+f_001_1(Set<String> u, int b) => v(u, '0011', b);
+@pragma('dart2js:noInline')
+/*member: f_000_1:member_unit=6{b4}*/
+f_000_1(Set<String> u, int b) => v(u, '0001', b);
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_or/lib_000_1.dart b/pkg/compiler/test/custom_split/data/fuse_with_or/lib_000_1.dart
new file mode 100644
index 0000000..5407d70
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_or/lib_000_1.dart
@@ -0,0 +1,25 @@
+// 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.
+
+// This file was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import "package:expect/expect.dart";
+
+import 'libImport.dart';
+
+@pragma('dart2js:noInline')
+/*member: g_000_1:member_unit=6{b4}*/
+g_000_1() {
+ Set<String> uniques = {};
+
+ // f_***_1;
+ f_000_1(uniques, 3);
+ f_001_1(uniques, 3);
+ f_010_1(uniques, 3);
+ f_011_1(uniques, 3);
+ f_100_1(uniques, 3);
+ f_101_1(uniques, 3);
+ f_110_1(uniques, 3);
+ f_111_1(uniques, 3);
+ Expect.equals(8, uniques.length);
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_or/lib_001_0.dart b/pkg/compiler/test/custom_split/data/fuse_with_or/lib_001_0.dart
new file mode 100644
index 0000000..1614e60
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_or/lib_001_0.dart
@@ -0,0 +1,25 @@
+// 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.
+
+// This file was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import "package:expect/expect.dart";
+
+import 'libImport.dart';
+
+@pragma('dart2js:noInline')
+/*member: g_001_0:member_unit=2{b1, b2, b3, b4}*/
+g_001_0() {
+ Set<String> uniques = {};
+
+ // f_**1_*;
+ f_001_0(uniques, 2);
+ f_001_1(uniques, 2);
+ f_011_0(uniques, 2);
+ f_011_1(uniques, 2);
+ f_101_0(uniques, 2);
+ f_101_1(uniques, 2);
+ f_111_0(uniques, 2);
+ f_111_1(uniques, 2);
+ Expect.equals(8, uniques.length);
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_or/lib_010_0.dart b/pkg/compiler/test/custom_split/data/fuse_with_or/lib_010_0.dart
new file mode 100644
index 0000000..4cf27c5
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_or/lib_010_0.dart
@@ -0,0 +1,25 @@
+// 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.
+
+// This file was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import "package:expect/expect.dart";
+
+import 'libImport.dart';
+
+@pragma('dart2js:noInline')
+/*member: g_010_0:member_unit=4{b2}*/
+g_010_0() {
+ Set<String> uniques = {};
+
+ // f_*1*_*;
+ f_010_0(uniques, 1);
+ f_010_1(uniques, 1);
+ f_011_0(uniques, 1);
+ f_011_1(uniques, 1);
+ f_110_0(uniques, 1);
+ f_110_1(uniques, 1);
+ f_111_0(uniques, 1);
+ f_111_1(uniques, 1);
+ Expect.equals(8, uniques.length);
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_or/lib_100_0.dart b/pkg/compiler/test/custom_split/data/fuse_with_or/lib_100_0.dart
new file mode 100644
index 0000000..0fe7274
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_or/lib_100_0.dart
@@ -0,0 +1,25 @@
+// 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.
+
+// This file was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import "package:expect/expect.dart";
+
+import 'libImport.dart';
+
+@pragma('dart2js:noInline')
+/*member: g_100_0:member_unit=1{b1}*/
+g_100_0() {
+ Set<String> uniques = {};
+
+ // f_1**_*;
+ f_100_0(uniques, 0);
+ f_100_1(uniques, 0);
+ f_101_0(uniques, 0);
+ f_101_1(uniques, 0);
+ f_110_0(uniques, 0);
+ f_110_1(uniques, 0);
+ f_111_0(uniques, 0);
+ f_111_1(uniques, 0);
+ Expect.equals(8, uniques.length);
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_or/main.dart b/pkg/compiler/test/custom_split/data/fuse_with_or/main.dart
new file mode 100644
index 0000000..a2531cb
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_or/main.dart
@@ -0,0 +1,39 @@
+// 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:
+ a_pre_fragments=[
+ p1: {units: [6{b4}], usedBy: [], needs: []},
+ p2: {units: [4{b2}], usedBy: [], needs: []},
+ p3: {units: [1{b1}], usedBy: [], needs: []},
+ p4: {units: [5{b2, b4}], usedBy: [], needs: []},
+ p5: {units: [3{b1, b4}], usedBy: [], needs: []},
+ p6: {units: [2{b1, b2, b3, b4}], usedBy: [], needs: []}],
+ b_finalized_fragments=[
+ f1: [6{b4}],
+ f2: [4{b2}],
+ f3: [1{b1}],
+ f4: [5{b2, b4}],
+ f5: [3{b1, b4}],
+ f6: [2{b1, b2, b3, b4}]],
+ c_steps=[
+ b1=(f6, f5, f3),
+ b2=(f6, f4, f2),
+ b3=(f6),
+ b4=(f6, f5, f4, f1)]
+*/
+
+// This file was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import 'lib1.dart';
+import 'lib2.dart';
+import 'lib3.dart';
+import 'lib4.dart';
+
+/*member: main:member_unit=main{}*/
+main() {
+ entryLib1();
+ entryLib2();
+ entryLib3();
+ entryLib4();
+}
diff --git a/pkg/compiler/test/custom_split/data/two_branch/constraints.json b/pkg/compiler/test/custom_split/data/two_branch/constraints.json
index 1a29d7b..9ab73ee 100644
--- a/pkg/compiler/test/custom_split/data/two_branch/constraints.json
+++ b/pkg/compiler/test/custom_split/data/two_branch/constraints.json
@@ -15,12 +15,12 @@
"import": "memory:sdk/tests/web/native/main.dart#step2b"
},
{
- "type": "order",
+ "type": "relative_order",
"predecessor": "memory:sdk/tests/web/native/main.dart#step1",
"successor": "memory:sdk/tests/web/native/main.dart#step2a"
},
{
- "type": "order",
+ "type": "relative_order",
"predecessor": "memory:sdk/tests/web/native/main.dart#step1",
"successor": "memory:sdk/tests/web/native/main.dart#step2b"
}
diff --git a/pkg/compiler/test/custom_split/data/two_step/constraints.json b/pkg/compiler/test/custom_split/data/two_step/constraints.json
index 77a02de..a0e82d6 100644
--- a/pkg/compiler/test/custom_split/data/two_step/constraints.json
+++ b/pkg/compiler/test/custom_split/data/two_step/constraints.json
@@ -15,12 +15,12 @@
"import": "memory:sdk/tests/web/native/main.dart#step3"
},
{
- "type": "order",
+ "type": "relative_order",
"predecessor": "memory:sdk/tests/web/native/main.dart#step1",
"successor": "memory:sdk/tests/web/native/main.dart#step2"
},
{
- "type": "order",
+ "type": "relative_order",
"predecessor": "memory:sdk/tests/web/native/main.dart#step2",
"successor": "memory:sdk/tests/web/native/main.dart#step3"
}
diff --git a/pkg/compiler/tool/graph_isomorphizer.dart b/pkg/compiler/tool/graph_isomorphizer.dart
index 49894bd..74489b8 100644
--- a/pkg/compiler/tool/graph_isomorphizer.dart
+++ b/pkg/compiler/tool/graph_isomorphizer.dart
@@ -142,8 +142,11 @@
/// A bool to omit the comment block.
final bool skipCopyright;
+ // A bool to generate simple code within test files.
+ final bool simple;
+
GraphIsomorphizer(this.names, this.maxBit,
- {this.outDirectory: '.', this.skipCopyright: false});
+ {this.outDirectory: '.', this.skipCopyright: false, this.simple: false});
void noInlineDecorator(StringBuffer out) {
out.write("@pragma('dart2js:noInline')\n");
@@ -188,90 +191,92 @@
var nameKeys = names.keys.toList();
nameKeys.sort();
- // Generate the 'base' classes, mixins, and types which will be combined to
- // generate hierarchies. Also generate a const instance per class and a closure
- // to invoke.
Set<String> uniques = {};
- for (var bitPosition in nameKeys) {
- var bitsList = names[bitPosition];
- for (var bits in bitsList) {
- var name = generateBitString(bits);
- if (!uniques.add(name)) continue;
- String className = 'C$name';
- String mixinName = 'M$name';
- String typeName = 'T$name';
- (classNames[bitPosition] ??= []).add(className);
- (mixinNames[bitPosition] ??= []).add(mixinName);
- (typeNames[bitPosition] ??= []).add(typeName);
- (mixerClassNames[bitPosition] ??= []).add(className);
- (mixerTypeNames[bitPosition] ??= []).add(typeName);
- out.write('class $className { const $className(); }\n');
- out.write('class $mixinName {}\n');
- out.write('class $typeName {}\n');
- out.write('const $className i$className = const $className();\n');
- out.write('closure$className(foo) => ($className unused) ');
- out.write('=> i$className.toString() == foo.toString();\n');
+ if (!simple) {
+ // Generate the 'base' classes, mixins, and types which will be combined to
+ // generate hierarchies. Also generate a const instance per class and a closure
+ // to invoke.
+ for (var bitPosition in nameKeys) {
+ var bitsList = names[bitPosition];
+ for (var bits in bitsList) {
+ var name = generateBitString(bits);
+ if (!uniques.add(name)) continue;
+ String className = 'C$name';
+ String mixinName = 'M$name';
+ String typeName = 'T$name';
+ (classNames[bitPosition] ??= []).add(className);
+ (mixinNames[bitPosition] ??= []).add(mixinName);
+ (typeNames[bitPosition] ??= []).add(typeName);
+ (mixerClassNames[bitPosition] ??= []).add(className);
+ (mixerTypeNames[bitPosition] ??= []).add(typeName);
+ out.write('class $className { const $className(); }\n');
+ out.write('class $mixinName {}\n');
+ out.write('class $typeName {}\n');
+ out.write('const $className i$className = const $className();\n');
+ out.write('closure$className(foo) => ($className unused) ');
+ out.write('=> i$className.toString() == foo.toString();\n');
+ }
}
- }
- // Generate combined classes and types, as well as const instances and
- // closures.
- newline(out);
- uniques = {};
- for (var bitPosition in nameKeys) {
- var bitsList = names[bitPosition];
- for (var bits in bitsList) {
- var name = generateBitString(bits);
- var bitCount = bits.reduce((a, b) => a + b);
- var baseName = 'C$name';
- if (!uniques.add(baseName)) continue;
- if (bitCount > 1) {
- List<String> classes = [];
- List<String> mixins = [];
- List<String> types = [];
- for (int i = 0; i < bits.length; i++) {
- if (bits[i] == 1) {
- classes.addAll(classNames[i]);
- mixins.addAll(mixinNames[i]);
- types.addAll(typeNames[i]);
- }
- }
- String mixinString = mixins.join(', ');
- int count = 1;
- assert(classes.length == types.length);
- for (int i = 0; i < classes.length; i++) {
- var cls = classes[i];
- var type = types[i];
- List<String> classImpls = [];
- List<String> typeImpls = [];
- if (i > 0) {
- classImpls.addAll(classes.sublist(0, i));
- typeImpls.addAll(types.sublist(0, i));
- }
- if (i < classes.length - 1) {
- classImpls.addAll(classes.sublist(i + 1));
- typeImpls.addAll(types.sublist(i + 1));
- }
- var classImplementsString = classImpls.join(', ');
- String className = '${baseName}_class_${count}';
- out.write('class $className extends $cls with $mixinString ');
- out.write(
- 'implements $classImplementsString { const $className(); }\n');
- out.write('const $className i$className = const $className();\n');
- out.write('closure$className(foo) => ($className unused) ');
- out.write('=> i$className.toString() == foo.toString();\n');
-
- var typeImplementsString = typeImpls.join(', ');
- String typeName = 'T${name}_type__${count}';
- out.write('class $typeName extends $type with $mixinString ');
- out.write('implements $typeImplementsString {}\n');
+ // Generate combined classes and types, as well as const instances and
+ // closures.
+ newline(out);
+ uniques = {};
+ for (var bitPosition in nameKeys) {
+ var bitsList = names[bitPosition];
+ for (var bits in bitsList) {
+ var name = generateBitString(bits);
+ var bitCount = bits.reduce((a, b) => a + b);
+ var baseName = 'C$name';
+ if (!uniques.add(baseName)) continue;
+ if (bitCount > 1) {
+ List<String> classes = [];
+ List<String> mixins = [];
+ List<String> types = [];
for (int i = 0; i < bits.length; i++) {
if (bits[i] == 1) {
- mixerClassNames[i].add(className);
- mixerTypeNames[i].add(typeName);
+ classes.addAll(classNames[i]);
+ mixins.addAll(mixinNames[i]);
+ types.addAll(typeNames[i]);
}
}
- count++;
+ String mixinString = mixins.join(', ');
+ int count = 1;
+ assert(classes.length == types.length);
+ for (int i = 0; i < classes.length; i++) {
+ var cls = classes[i];
+ var type = types[i];
+ List<String> classImpls = [];
+ List<String> typeImpls = [];
+ if (i > 0) {
+ classImpls.addAll(classes.sublist(0, i));
+ typeImpls.addAll(types.sublist(0, i));
+ }
+ if (i < classes.length - 1) {
+ classImpls.addAll(classes.sublist(i + 1));
+ typeImpls.addAll(types.sublist(i + 1));
+ }
+ var classImplementsString = classImpls.join(', ');
+ String className = '${baseName}_class_${count}';
+ out.write('class $className extends $cls with $mixinString ');
+ out.write(
+ 'implements $classImplementsString { const $className(); }\n');
+ out.write('const $className i$className = const $className();\n');
+ out.write('closure$className(foo) => ($className unused) ');
+ out.write('=> i$className.toString() == foo.toString();\n');
+
+ var typeImplementsString = typeImpls.join(', ');
+ String typeName = 'T${name}_type__${count}';
+ out.write('class $typeName extends $type with $mixinString ');
+ out.write('implements $typeImplementsString {}\n');
+ for (int i = 0; i < bits.length; i++) {
+ if (bits[i] == 1) {
+ mixerClassNames[i].add(className);
+ mixerTypeNames[i].add(typeName);
+ }
+ }
+ count++;
+ }
}
}
}
@@ -301,35 +306,41 @@
importExpect(out);
out.write("import '$import';\n\n");
- // create type test.
- noInlineDecorator(out);
- out.write('typeTest(dynamic t) {\n');
- for (var type in mixerTypeNames[bit]) {
- out.write(' if (t is $type) { return true; }\n');
+ if (!simple) {
+ // create type test.
+ noInlineDecorator(out);
+ out.write('typeTest(dynamic t) {\n');
+ for (var type in mixerTypeNames[bit]) {
+ out.write(' if (t is $type) { return true; }\n');
+ }
+ out.write(' return false;\n');
+ out.write('}\n\n');
}
- out.write(' return false;\n');
- out.write('}\n\n');
noInlineDecorator(out);
out.write('g$name() {\n');
- out.write(' // C${generateCommentName(bits, bit)};\n');
- // Construct new instances of each class and pass them to the typeTest
- for (var cls in mixerClassNames[bit]) {
- out.write(' Expect.isFalse(typeTest($cls()));\n');
- }
- newline(out);
+ if (!simple) {
+ out.write(' // C${generateCommentName(bits, bit)};\n');
- // Invoke the test closure for each class.
- for (var cls in mixerClassNames[bit]) {
- out.write(' Expect.isTrue(closure$cls($cls())($cls()));\n');
- }
- newline(out);
+ // Construct new instances of each class and pass them to the typeTest
+ for (var cls in mixerClassNames[bit]) {
+ out.write(' Expect.isFalse(typeTest($cls()));\n');
+ }
+ newline(out);
- // Verify the runtimeTypes of the closures haven't been mangled.
- for (var cls in mixerClassNames[bit]) {
- out.write(' Expect.equals(closure$cls($cls()).runtimeType.toString(), ');
- out.write("'($cls) => bool');\n");
+ // Invoke the test closure for each class.
+ for (var cls in mixerClassNames[bit]) {
+ out.write(' Expect.isTrue(closure$cls($cls())($cls()));\n');
+ }
+ newline(out);
+
+ // Verify the runtimeTypes of the closures haven't been mangled.
+ for (var cls in mixerClassNames[bit]) {
+ out.write(
+ ' Expect.equals(closure$cls($cls()).runtimeType.toString(), ');
+ out.write("'($cls) => bool');\n");
+ }
}
newline(out);
@@ -466,6 +477,7 @@
/// Creates a GraphIsomorphizer based on the provided args.
GraphIsomorphizer createGraphIsomorphizer(List<String> args) {
+ bool simple = true;
int maxBit = 0;
String graphFile = '';
String outDirectory = '.';
@@ -480,6 +492,9 @@
if (arg.startsWith('--out-dir')) {
outDirectory = arg.substring('--out-dir='.length);
}
+ if (arg == '--simple') {
+ simple = true;
+ }
}
// If we don't have a graphFile, then we generate all permutations of bits up
@@ -491,7 +506,8 @@
} else {
maxBit = namesFromGraphFile(graphFile, names);
}
- return GraphIsomorphizer(names, maxBit, outDirectory: outDirectory);
+ return GraphIsomorphizer(names, maxBit,
+ outDirectory: outDirectory, simple: simple);
}
void main(List<String> args) {
diff --git a/pkg/dart_internal/CHANGELOG.md b/pkg/dart_internal/CHANGELOG.md
index 8894fed..868e075 100644
--- a/pkg/dart_internal/CHANGELOG.md
+++ b/pkg/dart_internal/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.2.4
+
+- Support the latest Dart SDK.
+
## 0.2.3
- Support the latest Dart SDK.
diff --git a/pkg/front_end/lib/src/fasta/kernel/macro.dart b/pkg/front_end/lib/src/fasta/kernel/macro.dart
index 3c8f11a..7a54280 100644
--- a/pkg/front_end/lib/src/fasta/kernel/macro.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/macro.dart
@@ -32,6 +32,7 @@
bool macrosAreAvailable = false;
Map<Uri, List<String>> macroDeclarations = {};
List<List<Uri>>? compilationSequence;
+ List<Map<Uri, Map<String, List<String>>>> neededPrecompilations = [];
}
class MacroClass {
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 3e21692..08c9e9b 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -1345,18 +1345,24 @@
ticker.logMs("Resolved $typeCount types");
}
- void computeMacroDeclarations() {
- if (!enableMacros) return;
+ /// Computes which macro declarations that needs to be precompiled in order
+ /// to support macro application during compilation.
+ ///
+ /// If no macros need precompilation, `null` is returned. Otherwise a map
+ /// from library uris to macro class names and the names of constructor their
+ /// constructors is returned.
+ Map<Uri, Map<String, List<String>>>? computeMacroDeclarations() {
+ if (!enableMacros) return null;
LibraryBuilder? macroLibraryBuilder = lookupLibraryBuilder(macroLibraryUri);
- if (macroLibraryBuilder == null) return;
+ if (macroLibraryBuilder == null) return null;
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;
+ return null;
}
_macroClassBuilder = macroClassBuilder;
@@ -1364,10 +1370,9 @@
dataForTesting!.macroDeclarationData.macrosAreAvailable = true;
}
- Set<ClassBuilder> macroClasses = {};
-
- /// Libraries containing macros that need compilation.
- Set<Uri> macroLibraries = {};
+ /// Libraries containing macros that need compilation mapped to the
+ /// [ClassBuilder]s for the macro classes.
+ Map<Uri, List<ClassBuilder>> macroLibraries = {};
/// Libraries containing precompiled macro classes.
Set<Uri> precompiledMacroLibraries = {};
@@ -1383,8 +1388,7 @@
Uri libraryUri = builder.library.importUri;
MacroClass macroClass = new MacroClass(libraryUri, builder.name);
if (!precompiledMacroUris.containsKey(macroClass)) {
- macroClasses.add(builder);
- macroLibraries.add(libraryUri);
+ (macroLibraries[libraryUri] ??= []).add(builder);
if (retainDataForTesting) {
(dataForTesting!.macroDeclarationData
.macroDeclarations[libraryUri] ??= [])
@@ -1397,8 +1401,8 @@
}
}
- if (macroClasses.isEmpty) {
- return;
+ if (macroLibraries.isEmpty) {
+ return null;
}
List<List<Uri>> computeCompilationSequence(Graph<Uri> libraryGraph,
@@ -1417,7 +1421,7 @@
for (List<Uri> component in layer) {
for (Uri uri in component) {
if (filter(uri)) continue;
- if (macroLibraries.contains(uri)) {
+ if (macroLibraries.containsKey(uri)) {
declaresMacro = true;
}
currentLayer.add(uri);
@@ -1456,7 +1460,7 @@
addPrecompiledLibrary(builder.importUri);
} else if (precompiledMacroLibraries.contains(builder.importUri)) {
assert(
- !macroLibraries.contains(builder.importUri),
+ !macroLibraries.containsKey(builder.importUri),
"Macro library ${builder.importUri} is only partially "
"precompiled.");
addPrecompiledLibrary(builder.importUri);
@@ -1471,6 +1475,52 @@
dataForTesting!.macroDeclarationData.compilationSequence =
compilationSteps;
}
+
+ if (compilationSteps.length > 1) {
+ // We have at least 1 layer of macros that need to be precompiled before
+ // we can compile the program itself.
+ Map<Uri, Map<String, List<String>>> neededPrecompilations = {};
+ for (int i = 0; i < compilationSteps.length - 1; i++) {
+ List<Uri> compilationStep = compilationSteps[i];
+ for (Uri uri in compilationStep) {
+ List<ClassBuilder>? macroClasses = macroLibraries[uri];
+ // [uri] might not itself declare any macros but instead a part of the
+ // libraries that macros depend upon.
+ if (macroClasses != null) {
+ Map<String, List<String>>? constructorMap;
+ for (ClassBuilder macroClass in macroClasses) {
+ List<String> constructors =
+ macroClass.constructors.local.keys.toList();
+ if (constructors.isNotEmpty) {
+ // TODO(johnniwinther): If there is no constructor here, it
+ // means the macro had no _explicit_ constructors. Since macro
+ // constructor are required to be const, this would be an error
+ // case. We need to handle that precompilation could result in
+ // errors like this. For this case we should probably add 'new'
+ // in case of [constructors] being empty in expectation of
+ // triggering the error during precompilation.
+ (constructorMap ??= {})[macroClass.name] = constructors;
+ }
+ }
+ if (constructorMap != null) {
+ neededPrecompilations[uri] = constructorMap;
+ }
+ }
+ }
+ if (neededPrecompilations.isNotEmpty) {
+ if (retainDataForTesting) {
+ dataForTesting!.macroDeclarationData.neededPrecompilations
+ .add(neededPrecompilations);
+ }
+ // We have found the first needed layer of precompilation. There might
+ // be more layers but we'll compute these at the next attempt at
+ // compilation, when this layer has been precompiled.
+ // TODO(johnniwinther): Use this to trigger a precompile step.
+ return neededPrecompilations;
+ }
+ }
+ }
+ return null;
}
Future<MacroApplications?> computeMacroApplications() async {
diff --git a/pkg/front_end/test/macros/data/tests/applications.dart b/pkg/front_end/test/macros/data/tests/applications.dart
index 06bf716..6adb8dc 100644
--- a/pkg/front_end/test/macros/data/tests/applications.dart
+++ b/pkg/front_end/test/macros/data/tests/applications.dart
@@ -24,7 +24,8 @@
package:macro/macro.dart/Macro3/named(),
package:macro/macro.dart/Macro3/named()],
macrosAreApplied,
- macrosAreAvailable
+ macrosAreAvailable,
+ neededPrecompilations=[package:macro/macro.dart=Macro1(named/new)|Macro2(named/new)|Macro3(named/new)]
*/
import 'package:macro/macro.dart';
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
index 69ea910..09e50a9 100644
--- 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
@@ -8,7 +8,8 @@
apply_lib.dart|main.dart],
macroClassIds=[macro_lib.dart/Macro1],
macroInstanceIds=[macro_lib.dart/Macro1/()],
- macrosAreAvailable
+ macrosAreAvailable,
+ neededPrecompilations=[macro_lib.dart=Macro1(new)]
*/
import 'apply_lib.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 9619bb1..64d7efc 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
@@ -6,7 +6,8 @@
compilationSequence=[
package:_fe_analyzer_shared/src/macros/api.dart|package:macro/macro.dart,
main.dart],
- macrosAreAvailable
+ macrosAreAvailable,
+ neededPrecompilations=[package:macro/macro.dart=Macro1(named/new)|Macro2(named/new)|Macro3(named/new)]
*/
// ignore: unused_import
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 15c660c..d94aeaa 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
@@ -6,7 +6,8 @@
compilationSequence=[
macro_lib.dart|package:_fe_analyzer_shared/src/macros/api.dart,
main.dart],
- macrosAreAvailable
+ macrosAreAvailable,
+ neededPrecompilations=[macro_lib.dart=Macro1(new)]
*/
// ignore: unused_import
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
index 873d202..103c1ed 100644
--- a/pkg/front_end/test/macros/data/tests/multiple_macros/main.dart
+++ b/pkg/front_end/test/macros/data/tests/multiple_macros/main.dart
@@ -17,7 +17,8 @@
macro_lib2a.dart/Macro2a/(),
macro_lib2b.dart/Macro2b/()],
macrosAreApplied,
- macrosAreAvailable
+ macrosAreAvailable,
+ neededPrecompilations=[macro_lib1.dart=Macro1(new)macro_lib2a.dart=Macro2a(new)]
*/
import 'macro_lib1.dart';
diff --git a/pkg/front_end/test/macros/data/tests/precompiled.dart b/pkg/front_end/test/macros/data/tests/precompiled.dart
index 5b29de2..16171a8 100644
--- a/pkg/front_end/test/macros/data/tests/precompiled.dart
+++ b/pkg/front_end/test/macros/data/tests/precompiled.dart
@@ -13,7 +13,8 @@
package:macro/macro.dart/Macro1/(),
package:precompiled_macro/precompiled_macro.dart/PrecompiledMacro/()],
macrosAreApplied,
- macrosAreAvailable
+ macrosAreAvailable,
+ neededPrecompilations=[package:macro/macro.dart=Macro1(named/new)|Macro2(named/new)|Macro3(named/new)]
*/
import 'package:precompiled_macro/precompiled_macro.dart';
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 c3b123e..9fea835 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
@@ -19,7 +19,8 @@
package:macro/macro.dart/Macro3/(),
package:macro/macro.dart/Macro3/()],
macrosAreApplied,
- macrosAreAvailable
+ macrosAreAvailable,
+ neededPrecompilations=[package:macro/macro.dart=Macro1(named/new)|Macro2(named/new)|Macro3(named/new)]
*/
library use_macro_package;
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 eff50a1..475694d 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
@@ -16,7 +16,8 @@
macro_lib.dart/Macro2/(),
macro_lib.dart/Macro2/()],
macrosAreApplied,
- macrosAreAvailable
+ macrosAreAvailable,
+ neededPrecompilations=[macro_lib.dart=Macro1(new)|Macro2(new)]
*/
import 'macro_lib.dart';
diff --git a/pkg/front_end/test/macros/macro_test.dart b/pkg/front_end/test/macros/macro_test.dart
index 26aef58..e6ff78d 100644
--- a/pkg/front_end/test/macros/macro_test.dart
+++ b/pkg/front_end/test/macros/macro_test.dart
@@ -86,12 +86,17 @@
static const String macrosAreAvailable = 'macrosAreAvailable';
static const String macrosAreApplied = 'macrosAreApplied';
static const String compilationSequence = 'compilationSequence';
+ static const String neededPrecompilations = 'neededPrecompilations';
static const String declaredMacros = 'declaredMacros';
static const String appliedMacros = 'appliedMacros';
static const String macroClassIds = 'macroClassIds';
static const String macroInstanceIds = 'macroInstanceIds';
}
+String constructorNameToString(String constructorName) {
+ return constructorName == '' ? 'new' : constructorName;
+}
+
String importUriToString(Uri importUri) {
if (importUri.scheme == 'package') {
return importUri.toString();
@@ -183,9 +188,8 @@
if (macroApplications != null) {
for (MacroApplication application in macroApplications) {
String className = application.classBuilder.name;
- String constructorName = application.constructorName == ''
- ? 'new'
- : application.constructorName;
+ String constructorName =
+ constructorNameToString(application.constructorName);
features.addElement(
Tags.appliedMacros, '${className}.${constructorName}');
}
@@ -216,6 +220,32 @@
Tags.compilationSequence, strongComponentToString(component));
}
}
+ for (Map<Uri, Map<String, List<String>>> precompilation
+ in macroDeclarationData.neededPrecompilations) {
+ Map<String, Map<String, List<String>>> converted =
+ new Map.fromIterables(precompilation.keys.map(importUriToString),
+ precompilation.values);
+ List<String> uris = converted.keys.toList()..sort();
+ StringBuffer sb = new StringBuffer();
+ for (String uri in uris) {
+ sb.write(uri);
+ sb.write('=');
+ Map<String, List<String>> macros = converted[uri]!;
+ List<String> classes = macros.keys.toList()..sort();
+ String delimiter = '';
+ for (String cls in classes) {
+ List<String> constructorNames =
+ macros[cls]!.map(constructorNameToString).toList()..sort();
+ sb.write(delimiter);
+ sb.write(cls);
+ sb.write('(');
+ sb.write(constructorNames.join('/'));
+ sb.write(')');
+ delimiter = '|';
+ }
+ }
+ features.addElement(Tags.neededPrecompilations, sb.toString());
+ }
for (_MacroClassIdentifier id in macroExecutor.macroClasses) {
features.addElement(Tags.macroClassIds, id.toText());
}
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index 7ec217f..22b6b5a 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -980,6 +980,9 @@
pre
prebuild
prebuilt
+precompilation
+precompilations
+precompile
precompiled
preexisted
preexisting
@@ -1391,6 +1394,7 @@
traverse
trees
tricky
+triggering
trips
trivially
ts
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index 4e51302..1da0854 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -774,6 +774,8 @@
population
portions
pp
+precompilation
+precompilations
preliminary
prematurely
press
diff --git a/sdk/lib/_internal/vm/lib/hash_factories.dart b/sdk/lib/_internal/vm/lib/hash_factories.dart
new file mode 100644
index 0000000..9e45e8d
--- /dev/null
+++ b/sdk/lib/_internal/vm/lib/hash_factories.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2022, 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.
+
+// This is a placeholder file which will shortly contain the LinkedhashMap and
+// LinkedHashSet patches from collection_patch.dart. The change is done in two
+// steps to ease rolling it into Flutter.
diff --git a/sdk/lib/libraries.json b/sdk/lib/libraries.json
index b62cc71..8573ca4 100644
--- a/sdk/lib/libraries.json
+++ b/sdk/lib/libraries.json
@@ -32,7 +32,8 @@
"uri": "collection/collection.dart",
"patches": [
"_internal/vm/lib/collection_patch.dart",
- "_internal/vm/lib/compact_hash.dart"
+ "_internal/vm/lib/compact_hash.dart",
+ "_internal/vm/lib/hash_factories.dart"
]
},
"convert": {
diff --git a/sdk/lib/libraries.yaml b/sdk/lib/libraries.yaml
index 4aab70c..dcf81c0 100644
--- a/sdk/lib/libraries.yaml
+++ b/sdk/lib/libraries.yaml
@@ -41,6 +41,7 @@
patches:
- "_internal/vm/lib/collection_patch.dart"
- "_internal/vm/lib/compact_hash.dart"
+ - "_internal/vm/lib/hash_factories.dart"
convert:
uri: "convert/convert.dart"
diff --git a/tools/VERSION b/tools/VERSION
index 9d9cc54..633bc51 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 17
PATCH 0
-PRERELEASE 64
+PRERELEASE 65
PRERELEASE_PATCH 0
\ No newline at end of file