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 cc0421de795a4c97c0e6178190eabe0f1a3618b6..6e04b7d9ea8438cdacfe7166f97c82fa527a7b29 100644 |
--- a/tests/compiler/dart2js/equivalence/id_equivalence.dart |
+++ b/tests/compiler/dart2js/equivalence/id_equivalence.dart |
@@ -2,6 +2,7 @@ |
// for details. All rights reserved. Use of this source code is governed by a |
// BSD-style license that can be found in the LICENSE file. |
+import 'package:compiler/src/common.dart'; |
import 'package:compiler/src/elements/elements.dart'; |
import 'package:compiler/src/resolution/access_semantics.dart'; |
import 'package:compiler/src/resolution/send_structure.dart'; |
@@ -71,8 +72,37 @@ class NodeId implements Id { |
String toString() => '$kind:$value'; |
} |
-abstract class AstEnumeratorMixin { |
- TreeElements get elements; |
+class ActualData { |
+ final Id id; |
+ final String value; |
+ final SourceSpan sourceSpan; |
+ final Object object; |
+ |
+ ActualData(this.id, this.value, this.sourceSpan, this.object); |
+} |
+ |
+/// Mixin used for computing [Id] data. |
+abstract class ComputerMixin { |
Siggi Cherem (dart-lang)
2017/08/18 21:20:21
nit: rename to describe what it does and not what
Johnni Winther
2017/08/19 09:30:52
Mixin removed
|
+ Map<Id, ActualData> get actualMap; |
+ |
+ void registerValue( |
+ SourceSpan sourceSpan, Id id, String value, Object object) { |
+ if (id != null && value != null) { |
Siggi Cherem (dart-lang)
2017/08/18 21:20:21
note that you already guard agaisnt null id's on a
Johnni Winther
2017/08/19 09:30:52
Done.
|
+ actualMap[id] = new ActualData(id, value, sourceSpan, object); |
+ } |
+ } |
+} |
+ |
+/// Abstract AST visitor for computing [Id] data. |
Siggi Cherem (dart-lang)
2017/08/18 21:20:21
nit: reword to: visitor for computing data corresp
Johnni Winther
2017/08/19 09:30:52
Done.
|
+abstract class AbstractResolvedAstComputer extends ast.Visitor |
Siggi Cherem (dart-lang)
2017/08/18 21:20:21
other naming ideas:
- AbstractAstDataBuilder and
Johnni Winther
2017/08/19 09:30:52
Extractor it is.
|
+ with ComputerMixin { |
+ final DiagnosticReporter reporter; |
+ final Map<Id, ActualData> actualMap; |
+ final ResolvedAst resolvedAst; |
+ |
+ AbstractResolvedAstComputer(this.reporter, this.actualMap, this.resolvedAst); |
+ |
+ TreeElements get elements => resolvedAst.elements; |
ElementId computeElementId(AstElement element) { |
String memberName = element.name; |
@@ -86,111 +116,118 @@ abstract class AstEnumeratorMixin { |
NodeId computeAccessId(ast.Send node, AccessSemantics access) { |
switch (access.kind) { |
case AccessKind.DYNAMIC_PROPERTY: |
- return new NodeId(node.selector.getBeginToken().charOffset); |
+ case AccessKind.LOCAL_VARIABLE: |
+ case AccessKind.FINAL_LOCAL_VARIABLE: |
+ case AccessKind.LOCAL_FUNCTION: |
+ case AccessKind.PARAMETER: |
+ case AccessKind.FINAL_PARAMETER: |
+ case AccessKind.EXPRESSION: |
+ return computeDefaultNodeId(node.selector); |
default: |
return null; |
} |
} |
- NodeId computeNodeId(ast.Node node, AstElement element) { |
- if (element != null && element.isLocal) { |
- return new NodeId(node.getBeginToken().charOffset); |
- } else if (node is ast.Send) { |
- dynamic sendStructure = elements.getSendStructure(node); |
- if (sendStructure == null) return null; |
- switch (sendStructure.kind) { |
- case SendStructureKind.GET: |
- case SendStructureKind.INVOKE: |
- return computeAccessId(node, sendStructure.semantics); |
- default: |
- } |
- } |
- return null; |
+ void computeForElement(AstElement element) { |
+ ElementId id = computeElementId(element); |
+ if (id == null) return; |
+ String value = computeElementValue(element); |
+ registerValue(element.sourcePosition, id, value, element); |
} |
-} |
-/// Visitor that finds the AST node or element corresponding to an [Id]. |
-class AstIdFinder extends ast.Visitor with AstEnumeratorMixin { |
- Id soughtId; |
- var /*AstElement|ast.Node*/ found; |
- final TreeElements elements; |
+ void computeForNode(ast.Node node, NodeId id, [AstElement element]) { |
+ if (id == null) return; |
+ String value = computeNodeValue(node, element); |
+ SourceSpan sourceSpan = computeSourceSpan(node); |
+ registerValue(sourceSpan, id, value, element ?? node); |
+ } |
- AstIdFinder(this.elements); |
+ SourceSpan computeSourceSpan(ast.Node node) { |
+ return new SourceSpan(resolvedAst.sourceUri, |
+ node.getBeginToken().charOffset, node.getEndToken().charEnd); |
+ } |
- /// Visits the subtree of [root] returns the [ast.Node] or [AstElement] |
- /// corresponding to [id]. |
- /*AstElement|ast.Node*/ find(ast.Node root, Id id) { |
- soughtId = id; |
- root.accept(this); |
- var result = found; |
- found = null; |
- return result; |
+ String computeElementValue(AstElement element); |
Siggi Cherem (dart-lang)
2017/08/18 21:20:21
let's move these two up and add dart doc on them.
Johnni Winther
2017/08/19 09:30:52
Done.
|
+ |
+ String computeNodeValue(ast.Node node, AstElement element); |
+ |
+ NodeId computeDefaultNodeId(ast.Node node) { |
+ return new NodeId(node.getBeginToken().charOffset); |
} |
- visit(ast.Node node) { |
- if (found == null) { |
- node?.accept(this); |
- } |
+ NodeId computeLoopNodeId(ast.Node node) { |
+ return new NodeId(node.getBeginToken().charOffset); |
} |
- visitNode(ast.Node node) { |
- if (found == null) { |
- node.visitChildren(this); |
- } |
+ NodeId computeGotoNodeId(ast.Node node) { |
+ return new NodeId(node.getBeginToken().charOffset); |
} |
- visitSend(ast.Send node) { |
- if (found == null) { |
- visitNode(node); |
- Id id = computeNodeId(node, null); |
- if (id == soughtId) { |
- found = node; |
- } |
- } |
+ void run() { |
+ resolvedAst.node.accept(this); |
+ } |
+ |
+ visitNode(ast.Node node) { |
+ node.visitChildren(this); |
} |
visitVariableDefinitions(ast.VariableDefinitions node) { |
- if (found == null) { |
- for (ast.Node child in node.definitions) { |
- AstElement element = elements[child]; |
- if (element != null) { |
- Id id; |
- if (element is FieldElement) { |
- id = computeElementId(element); |
- } else { |
- id = computeNodeId(child, element); |
- } |
- if (id == soughtId) { |
- found = element; |
- return; |
- } |
- } |
+ for (ast.Node child in node.definitions) { |
+ AstElement element = elements[child]; |
+ if (element == null) { |
+ reportHere(reporter, child, 'No element for variable.'); |
+ } else if (!element.isLocal) { |
+ computeForElement(element); |
+ } else { |
+ computeForNode(child, computeDefaultNodeId(child), element); |
} |
- visitNode(node); |
} |
+ visitNode(node); |
} |
visitFunctionExpression(ast.FunctionExpression node) { |
- if (found == null) { |
- AstElement element = elements.getFunctionDefinition(node); |
- if (element != null) { |
- Id id; |
- if (element is LocalFunctionElement) { |
- id = computeNodeId(node, element); |
- } else { |
- id = computeElementId(element); |
- } |
- if (id == soughtId) { |
- found = element; |
- return; |
- } |
+ AstElement element = elements.getFunctionDefinition(node); |
+ if (!element.isLocal) { |
+ computeForElement(element); |
+ } else { |
+ computeForNode(node, computeDefaultNodeId(node), element); |
+ } |
+ visitNode(node); |
+ } |
+ |
+ visitSend(ast.Send node) { |
+ dynamic sendStructure = elements.getSendStructure(node); |
+ if (sendStructure != null) { |
+ switch (sendStructure.kind) { |
+ case SendStructureKind.GET: |
+ case SendStructureKind.INVOKE: |
+ case SendStructureKind.BINARY: |
+ case SendStructureKind.EQUALS: |
+ case SendStructureKind.NOT_EQUALS: |
+ computeForNode(node, computeAccessId(node, sendStructure.semantics)); |
+ break; |
+ default: |
} |
- visitNode(node); |
} |
+ visitNode(node); |
+ } |
+ |
+ visitLoop(ast.Loop node) { |
+ computeForNode(node, computeLoopNodeId(node)); |
+ visitNode(node); |
+ } |
+ |
+ visitGotoStatement(ast.GotoStatement node) { |
+ computeForNode(node, computeGotoNodeId(node)); |
+ visitNode(node); |
} |
} |
-abstract class IrEnumeratorMixin { |
+/// Abstract IR visitor for computing [Id] data. |
+abstract class AbstractIrComputer extends ir.Visitor with ComputerMixin { |
+ final Map<Id, ActualData> actualMap; |
+ |
+ AbstractIrComputer(this.actualMap); |
Id computeElementId(ir.Member node) { |
String className; |
if (node.enclosingClass != null) { |
@@ -203,60 +240,101 @@ abstract class IrEnumeratorMixin { |
return new ElementId.internal(memberName, className); |
} |
- Id computeNodeId(ir.TreeNode node) { |
- if (node is ir.MethodInvocation) { |
- assert(node.fileOffset != ir.TreeNode.noOffset); |
- return new NodeId(node.fileOffset); |
- } else if (node is ir.PropertyGet) { |
- assert(node.fileOffset != ir.TreeNode.noOffset); |
- return new NodeId(node.fileOffset); |
- } else if (node is ir.VariableDeclaration) { |
- assert(node.fileOffset != ir.TreeNode.noOffset); |
- return new NodeId(node.fileOffset); |
- } else if (node is ir.FunctionExpression) { |
- assert(node.fileOffset != ir.TreeNode.noOffset); |
- return new NodeId(node.fileOffset); |
- } else if (node is ir.FunctionDeclaration) { |
- assert(node.fileOffset != ir.TreeNode.noOffset); |
- return new NodeId(node.fileOffset); |
- } |
- return null; |
+ void computeForMember(ir.Member member) { |
+ ElementId id = computeElementId(member); |
+ if (id == null) return; |
+ String value = computeMemberValue(member); |
+ registerValue(computeSourceSpan(member), id, value, member); |
+ } |
+ |
+ void computeForNode(ir.TreeNode node, NodeId id) { |
+ if (id == null) return; |
+ String value = computeNodeValue(node); |
+ registerValue(computeSourceSpan(node), id, value, node); |
+ } |
+ |
+ SourceSpan computeSourceSpan(ir.TreeNode node) { |
+ return new SourceSpan( |
+ Uri.parse(node.location.file), node.fileOffset, node.fileOffset + 1); |
} |
-} |
-/// Visitor that finds the IR node corresponding to an [Id]. |
-class IrIdFinder extends ir.Visitor with IrEnumeratorMixin { |
- Id soughtId; |
- ir.Node found; |
+ String computeMemberValue(ir.Member member); |
- /// Visits the subtree of [root] returns the [ir.Node] corresponding to [id]. |
- ir.Node find(ir.Node root, Id id) { |
- soughtId = id; |
+ String computeNodeValue(ir.TreeNode node); |
+ |
+ NodeId computeDefaultNodeId(ir.TreeNode node) { |
+ assert(node.fileOffset != ir.TreeNode.noOffset); |
+ return new NodeId(node.fileOffset); |
+ } |
+ |
+ NodeId computeLoopNodeId(ir.TreeNode node) => computeDefaultNodeId(node); |
+ NodeId computeGotoNodeId(ir.TreeNode node) => computeDefaultNodeId(node); |
+ |
+ void run(ir.Node root) { |
root.accept(this); |
- var result = found; |
- found = null; |
- return result; |
} |
- defaultTreeNode(ir.TreeNode node) { |
- if (found == null) { |
- Id id = computeNodeId(node); |
- if (id == soughtId) { |
- found = node; |
- return; |
- } |
- node.visitChildren(this); |
- } |
+ defaultNode(ir.Node node) { |
+ node.visitChildren(this); |
} |
defaultMember(ir.Member node) { |
- if (found == null) { |
- Id id = computeElementId(node); |
- if (id == soughtId) { |
- found = node; |
- return; |
- } |
- defaultTreeNode(node); |
- } |
+ computeForMember(node); |
+ super.defaultMember(node); |
+ } |
+ |
+ visitMethodInvocation(ir.MethodInvocation node) { |
+ computeForNode(node, computeDefaultNodeId(node)); |
+ super.visitMethodInvocation(node); |
+ } |
+ |
+ visitPropertyGet(ir.PropertyGet node) { |
+ computeForNode(node, computeDefaultNodeId(node)); |
+ super.visitPropertyGet(node); |
+ } |
+ |
+ visitVariableDeclaration(ir.VariableDeclaration node) { |
+ computeForNode(node, computeDefaultNodeId(node)); |
+ super.visitVariableDeclaration(node); |
+ } |
+ |
+ visitFunctionDeclaration(ir.FunctionDeclaration node) { |
+ computeForNode(node, computeDefaultNodeId(node)); |
+ super.visitFunctionDeclaration(node); |
+ } |
+ |
+ visitFunctionExpression(ir.FunctionExpression node) { |
+ computeForNode(node, computeDefaultNodeId(node)); |
+ super.visitFunctionExpression(node); |
+ } |
+ |
+ visitVariableGet(ir.VariableGet node) { |
+ computeForNode(node, computeDefaultNodeId(node)); |
+ super.visitVariableGet(node); |
+ } |
+ |
+ visitDoStatement(ir.DoStatement node) { |
+ computeForNode(node, computeLoopNodeId(node)); |
+ super.visitDoStatement(node); |
+ } |
+ |
+ visitForStatement(ir.ForStatement node) { |
+ computeForNode(node, computeLoopNodeId(node)); |
+ super.visitForStatement(node); |
+ } |
+ |
+ visitForInStatement(ir.ForInStatement node) { |
+ computeForNode(node, computeLoopNodeId(node)); |
+ super.visitForInStatement(node); |
+ } |
+ |
+ visitWhileStatement(ir.WhileStatement node) { |
+ computeForNode(node, computeLoopNodeId(node)); |
+ super.visitWhileStatement(node); |
+ } |
+ |
+ visitBreakStatement(ir.BreakStatement node) { |
+ computeForNode(node, computeGotoNodeId(node)); |
+ super.visitBreakStatement(node); |
} |
} |