Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(967)

Unified Diff: tests/compiler/dart2js/equivalence/id_equivalence.dart

Issue 3007903002: Support annotations on assignment and postfix operations (Closed)
Patch Set: Updated cf. comments Created 3 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: tests/compiler/dart2js/equivalence/id_equivalence.dart
diff --git a/tests/compiler/dart2js/equivalence/id_equivalence.dart b/tests/compiler/dart2js/equivalence/id_equivalence.dart
index ed2a9dccd4c01574744c13b9461e3731a9147262..a9bc295ce9879a91d4d9e95008bc6387eb3328ca 100644
--- a/tests/compiler/dart2js/equivalence/id_equivalence.dart
+++ b/tests/compiler/dart2js/equivalence/id_equivalence.dart
@@ -8,11 +8,14 @@ import 'package:compiler/src/resolution/access_semantics.dart';
import 'package:compiler/src/resolution/send_structure.dart';
import 'package:compiler/src/resolution/tree_elements.dart';
import 'package:compiler/src/tree/nodes.dart' as ast;
+import 'package:expect/expect.dart';
import 'package:kernel/ast.dart' as ir;
enum IdKind {
element,
node,
+ invoke,
+ update,
}
/// Id for a code point or element with type inference information.
@@ -20,6 +23,61 @@ abstract class Id {
IdKind get kind;
}
+class IdValue {
+ final Id id;
+ final String value;
+
+ const IdValue(this.id, this.value);
+
+ int get hashCode => id.hashCode * 13 + value.hashCode * 17;
+
+ bool operator ==(other) {
+ if (identical(this, other)) return true;
+ if (other is! IdValue) return false;
+ return id == other.id && value == other.value;
+ }
+
+ String toString() {
+ switch (id.kind) {
+ case IdKind.element:
+ ElementId elementId = id;
+ return '$elementPrefix${elementId.name}:$value';
+ case IdKind.node:
+ return value;
+ case IdKind.invoke:
+ return '$invokePrefix$value';
+ case IdKind.update:
+ return '$updatePrefix$value';
+ }
+ throw new UnsupportedError("Unexpected id kind: ${id.kind}");
+ }
+
+ static const String elementPrefix = "element: ";
+ static const String invokePrefix = "invoke: ";
+ static const String updatePrefix = "update: ";
+
+ static IdValue decode(int offset, String text) {
+ Id id;
+ String expected;
+ if (text.startsWith(elementPrefix)) {
+ text = text.substring(elementPrefix.length);
+ int colonPos = text.indexOf(':');
+ id = new ElementId(text.substring(0, colonPos));
+ expected = text.substring(colonPos + 1);
+ } else if (text.startsWith(invokePrefix)) {
+ id = new NodeId(offset, IdKind.invoke);
+ expected = text.substring(invokePrefix.length);
+ } else if (text.startsWith(updatePrefix)) {
+ id = new NodeId(offset, IdKind.update);
+ expected = text.substring(updatePrefix.length);
+ } else {
+ id = new NodeId(offset, IdKind.node);
+ expected = text;
+ }
+ return new IdValue(id, expected);
+ }
+}
+
/// Id for an element with type inference information.
// TODO(johnniwinther): Support local variables, functions and parameters.
class ElementId implements Id {
@@ -48,42 +106,65 @@ class ElementId implements Id {
IdKind get kind => IdKind.element;
- String toString() =>
- className != null ? '$className.$memberName' : memberName;
+ String get name => className != null ? '$className.$memberName' : memberName;
+
+ String toString() => name;
}
/// Id for a code point with type inference information.
// TODO(johnniwinther): Create an [NodeId]-based equivalence with the kernel IR.
class NodeId implements Id {
final int value;
+ final IdKind kind;
- const NodeId(this.value);
+ const NodeId(this.value, this.kind);
- int get hashCode => value.hashCode;
+ int get hashCode => value.hashCode * 13 + kind.hashCode * 17;
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! NodeId) return false;
- return value == other.value;
+ return value == other.value && kind == other.kind;
}
- IdKind get kind => IdKind.node;
-
String toString() => '$kind:$value';
}
class ActualData {
- final Id id;
- final String value;
+ final IdValue value;
final SourceSpan sourceSpan;
final Object object;
- ActualData(this.id, this.value, this.sourceSpan, this.object);
+ ActualData(this.value, this.sourceSpan, this.object);
+}
+
+abstract class DataRegistry {
+ DiagnosticReporter get reporter;
+ Map<Id, ActualData> get actualMap;
+
+ void registerValue(
+ SourceSpan sourceSpan, Id id, String value, Object object) {
+ if (actualMap.containsKey(id)) {
+ ActualData existingData = actualMap[id];
+ reportHere(reporter, sourceSpan,
+ "Duplicate id ${id}, value=$value, object=$object");
+ reportHere(
+ reporter,
+ sourceSpan,
+ "Duplicate id ${id}, value=${existingData.value}, "
+ "object=${existingData.object}");
+ Expect.fail("Duplicate id $id.");
+ }
+ if (value != null) {
+ actualMap[id] =
+ new ActualData(new IdValue(id, value), sourceSpan, object);
+ }
+ }
}
/// Abstract AST visitor for computing data corresponding to a node or element,
// and record it with a generic [Id].
-abstract class AstDataExtractor extends ast.Visitor {
+abstract class AstDataExtractor extends ast.Visitor with DataRegistry {
final DiagnosticReporter reporter;
final Map<Id, ActualData> actualMap;
final ResolvedAst resolvedAst;
@@ -93,23 +174,16 @@ abstract class AstDataExtractor extends ast.Visitor {
/// Implement this to compute the data corresponding to [element].
///
/// If `null` is returned, [element] has no associated data.
- String computeElementValue(AstElement element);
+ String computeElementValue(Id id, AstElement element);
/// Implement this to compute the data corresponding to [node]. If [node] has
/// a corresponding [AstElement] this is provided in [element].
///
/// If `null` is returned, [node] has no associated data.
- String computeNodeValue(ast.Node node, AstElement element);
+ String computeNodeValue(Id id, ast.Node node, AstElement element);
TreeElements get elements => resolvedAst.elements;
- void registerValue(
- SourceSpan sourceSpan, Id id, String value, Object object) {
- if (value != null) {
- actualMap[id] = new ActualData(id, value, sourceSpan, object);
- }
- }
-
ElementId computeElementId(AstElement element) {
String memberName = element.name;
if (element.isSetter) {
@@ -119,7 +193,7 @@ abstract class AstDataExtractor extends ast.Visitor {
return new ElementId.internal(memberName, className);
}
- NodeId computeAccessId(ast.Send node, AccessSemantics access) {
+ ast.Node computeAccessPosition(ast.Send node, AccessSemantics access) {
switch (access.kind) {
case AccessKind.DYNAMIC_PROPERTY:
case AccessKind.LOCAL_VARIABLE:
@@ -128,7 +202,18 @@ abstract class AstDataExtractor extends ast.Visitor {
case AccessKind.PARAMETER:
case AccessKind.FINAL_PARAMETER:
case AccessKind.EXPRESSION:
- return computeDefaultNodeId(node.selector);
+ return node.selector;
+ default:
+ return null;
+ }
+ }
+
+ ast.Node computeUpdatePosition(ast.Send node, AccessSemantics access) {
+ switch (access.kind) {
+ case AccessKind.DYNAMIC_PROPERTY:
+ case AccessKind.LOCAL_VARIABLE:
+ case AccessKind.PARAMETER:
+ return node.selector;
default:
return null;
}
@@ -137,13 +222,13 @@ abstract class AstDataExtractor extends ast.Visitor {
void computeForElement(AstElement element) {
ElementId id = computeElementId(element);
if (id == null) return;
- String value = computeElementValue(element);
+ String value = computeElementValue(id, element);
registerValue(element.sourcePosition, id, value, element);
}
void computeForNode(ast.Node node, NodeId id, [AstElement element]) {
if (id == null) return;
- String value = computeNodeValue(node, element);
+ String value = computeNodeValue(id, node, element);
SourceSpan sourceSpan = computeSourceSpan(node);
registerValue(sourceSpan, id, value, element ?? node);
}
@@ -154,17 +239,28 @@ abstract class AstDataExtractor extends ast.Visitor {
}
NodeId computeDefaultNodeId(ast.Node node) {
- return new NodeId(node.getBeginToken().charOffset);
+ return new NodeId(node.getBeginToken().charOffset, IdKind.node);
+ }
+
+ NodeId createAccessId(ast.Node node) {
+ return new NodeId(node.getBeginToken().charOffset, IdKind.node);
+ }
+
+ NodeId createInvokeId(ast.Node node) {
+ return new NodeId(node.getBeginToken().charOffset, IdKind.invoke);
}
- NodeId computeLoopNodeId(ast.Node node) => computeDefaultNodeId(node);
+ NodeId createUpdateId(ast.Node node) {
+ return new NodeId(node.getBeginToken().charOffset, IdKind.update);
+ }
+
+ NodeId createLoopId(ast.Node node) => computeDefaultNodeId(node);
- NodeId computeGotoNodeId(ast.Node node) => computeDefaultNodeId(node);
+ NodeId createGotoId(ast.Node node) => computeDefaultNodeId(node);
- NodeId computeSwitchNodeId(ast.SwitchStatement node) =>
- computeDefaultNodeId(node);
+ NodeId createSwitchId(ast.SwitchStatement node) => computeDefaultNodeId(node);
- NodeId computeSwitchCaseNodeId(ast.SwitchCase node) {
+ NodeId createSwitchCaseId(ast.SwitchCase node) {
ast.Node position;
for (ast.Node child in node.labelsAndCases) {
if (child.asCaseMatch() != null) {
@@ -213,11 +309,45 @@ abstract class AstDataExtractor extends ast.Visitor {
if (sendStructure != null) {
switch (sendStructure.kind) {
case SendStructureKind.GET:
+ ast.Node position =
+ computeAccessPosition(node, sendStructure.semantics);
+ if (position != null) {
+ computeForNode(node, computeDefaultNodeId(position));
+ }
+ break;
case SendStructureKind.INVOKE:
case SendStructureKind.BINARY:
case SendStructureKind.EQUALS:
case SendStructureKind.NOT_EQUALS:
- computeForNode(node, computeAccessId(node, sendStructure.semantics));
+ ast.Node position =
+ computeAccessPosition(node, sendStructure.semantics);
+ if (position != null) {
+ computeForNode(node, createInvokeId(position));
+ }
+ break;
+ case SendStructureKind.SET:
+ break;
+ default:
+ }
+ }
+ visitNode(node);
+ }
+
+ visitSendSet(ast.SendSet node) {
+ dynamic sendStructure = elements.getSendStructure(node);
+ if (sendStructure != null) {
+ switch (sendStructure.kind) {
+ case SendStructureKind.SET:
+ ast.Node position =
+ computeUpdatePosition(node, sendStructure.semantics);
+ if (position != null) {
+ computeForNode(node, createUpdateId(position));
+ }
+ break;
+ case SendStructureKind.POSTFIX:
+ computeForNode(node, createAccessId(node.selector));
+ computeForNode(node, createInvokeId(node.assignmentOperator));
+ computeForNode(node, createUpdateId(node.selector));
break;
default:
}
@@ -226,49 +356,43 @@ abstract class AstDataExtractor extends ast.Visitor {
}
visitLoop(ast.Loop node) {
- computeForNode(node, computeLoopNodeId(node));
+ computeForNode(node, createLoopId(node));
visitNode(node);
}
visitGotoStatement(ast.GotoStatement node) {
- computeForNode(node, computeGotoNodeId(node));
+ computeForNode(node, createGotoId(node));
visitNode(node);
}
visitSwitchStatement(ast.SwitchStatement node) {
- computeForNode(node, computeSwitchNodeId(node));
+ computeForNode(node, createSwitchId(node));
visitNode(node);
}
visitSwitchCase(ast.SwitchCase node) {
- computeForNode(node, computeSwitchCaseNodeId(node));
+ computeForNode(node, createSwitchCaseId(node));
visitNode(node);
}
}
/// Abstract IR visitor for computing data corresponding to a node or element,
/// and record it with a generic [Id]
-abstract class IrDataExtractor extends ir.Visitor {
+abstract class IrDataExtractor extends ir.Visitor with DataRegistry {
+ final DiagnosticReporter reporter;
final Map<Id, ActualData> actualMap;
- void registerValue(
- SourceSpan sourceSpan, Id id, String value, Object object) {
- if (value != null) {
- actualMap[id] = new ActualData(id, value, sourceSpan, object);
- }
- }
-
/// Implement this to compute the data corresponding to [member].
///
/// If `null` is returned, [member] has no associated data.
- String computeMemberValue(ir.Member member);
+ String computeMemberValue(Id id, ir.Member member);
/// Implement this to compute the data corresponding to [node].
///
/// If `null` is returned, [node] has no associated data.
- String computeNodeValue(ir.TreeNode node);
+ String computeNodeValue(Id id, ir.TreeNode node);
- IrDataExtractor(this.actualMap);
+ IrDataExtractor(this.reporter, this.actualMap);
Id computeElementId(ir.Member node) {
String className;
if (node.enclosingClass != null) {
@@ -284,13 +408,13 @@ abstract class IrDataExtractor extends ir.Visitor {
void computeForMember(ir.Member member) {
ElementId id = computeElementId(member);
if (id == null) return;
- String value = computeMemberValue(member);
+ String value = computeMemberValue(id, member);
registerValue(computeSourceSpan(member), id, value, member);
}
void computeForNode(ir.TreeNode node, NodeId id) {
if (id == null) return;
- String value = computeNodeValue(node);
+ String value = computeNodeValue(id, node);
registerValue(computeSourceSpan(node), id, value, node);
}
@@ -301,15 +425,24 @@ abstract class IrDataExtractor extends ir.Visitor {
NodeId computeDefaultNodeId(ir.TreeNode node) {
assert(node.fileOffset != ir.TreeNode.noOffset);
- return new NodeId(node.fileOffset);
+ return new NodeId(node.fileOffset, IdKind.node);
+ }
+
+ NodeId createInvokeId(ir.TreeNode node) {
+ assert(node.fileOffset != ir.TreeNode.noOffset);
+ return new NodeId(node.fileOffset, IdKind.invoke);
}
- NodeId computeLoopNodeId(ir.TreeNode node) => computeDefaultNodeId(node);
- NodeId computeGotoNodeId(ir.TreeNode node) => computeDefaultNodeId(node);
- NodeId computeSwitchNodeId(ir.SwitchStatement node) =>
- computeDefaultNodeId(node);
- NodeId computeSwitchCaseNodeId(ir.SwitchCase node) =>
- new NodeId(node.expressionOffsets.first);
+ NodeId createUpdateId(ir.TreeNode node) {
+ assert(node.fileOffset != ir.TreeNode.noOffset);
+ return new NodeId(node.fileOffset, IdKind.update);
+ }
+
+ NodeId createLoopId(ir.TreeNode node) => computeDefaultNodeId(node);
+ NodeId createGotoId(ir.TreeNode node) => computeDefaultNodeId(node);
+ NodeId createSwitchId(ir.SwitchStatement node) => computeDefaultNodeId(node);
+ NodeId createSwitchCaseId(ir.SwitchCase node) =>
+ new NodeId(node.expressionOffsets.first, IdKind.node);
void run(ir.Node root) {
root.accept(this);
@@ -325,7 +458,7 @@ abstract class IrDataExtractor extends ir.Visitor {
}
visitMethodInvocation(ir.MethodInvocation node) {
- computeForNode(node, computeDefaultNodeId(node));
+ computeForNode(node, createInvokeId(node));
super.visitMethodInvocation(node);
}
@@ -335,7 +468,9 @@ abstract class IrDataExtractor extends ir.Visitor {
}
visitVariableDeclaration(ir.VariableDeclaration node) {
- computeForNode(node, computeDefaultNodeId(node));
+ if (node.parent is! ir.FunctionDeclaration) {
+ computeForNode(node, computeDefaultNodeId(node));
+ }
super.visitVariableDeclaration(node);
}
@@ -354,43 +489,53 @@ abstract class IrDataExtractor extends ir.Visitor {
super.visitVariableGet(node);
}
+ visitPropertySet(ir.PropertySet node) {
+ computeForNode(node, createUpdateId(node));
+ super.visitPropertySet(node);
+ }
+
+ visitVariableSet(ir.VariableSet node) {
+ computeForNode(node, createUpdateId(node));
+ super.visitVariableSet(node);
+ }
+
visitDoStatement(ir.DoStatement node) {
- computeForNode(node, computeLoopNodeId(node));
+ computeForNode(node, createLoopId(node));
super.visitDoStatement(node);
}
visitForStatement(ir.ForStatement node) {
- computeForNode(node, computeLoopNodeId(node));
+ computeForNode(node, createLoopId(node));
super.visitForStatement(node);
}
visitForInStatement(ir.ForInStatement node) {
- computeForNode(node, computeLoopNodeId(node));
+ computeForNode(node, createLoopId(node));
super.visitForInStatement(node);
}
visitWhileStatement(ir.WhileStatement node) {
- computeForNode(node, computeLoopNodeId(node));
+ computeForNode(node, createLoopId(node));
super.visitWhileStatement(node);
}
visitBreakStatement(ir.BreakStatement node) {
- computeForNode(node, computeGotoNodeId(node));
+ computeForNode(node, createGotoId(node));
super.visitBreakStatement(node);
}
visitSwitchStatement(ir.SwitchStatement node) {
- computeForNode(node, computeSwitchNodeId(node));
+ computeForNode(node, createSwitchId(node));
super.visitSwitchStatement(node);
}
visitSwitchCase(ir.SwitchCase node) {
- computeForNode(node, computeSwitchCaseNodeId(node));
+ computeForNode(node, createSwitchCaseId(node));
super.visitSwitchCase(node);
}
visitContinueSwitchStatement(ir.ContinueSwitchStatement node) {
- computeForNode(node, computeGotoNodeId(node));
+ computeForNode(node, createGotoId(node));
super.visitContinueSwitchStatement(node);
}
}

Powered by Google App Engine
This is Rietveld 408576698