OLD | NEW |
---|---|
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 import 'package:compiler/src/common.dart'; | 5 import 'package:compiler/src/common.dart'; |
6 import 'package:compiler/src/elements/elements.dart'; | 6 import 'package:compiler/src/elements/elements.dart'; |
7 import 'package:compiler/src/resolution/access_semantics.dart'; | 7 import 'package:compiler/src/resolution/access_semantics.dart'; |
8 import 'package:compiler/src/resolution/send_structure.dart'; | 8 import 'package:compiler/src/resolution/send_structure.dart'; |
9 import 'package:compiler/src/resolution/tree_elements.dart'; | 9 import 'package:compiler/src/resolution/tree_elements.dart'; |
10 import 'package:compiler/src/tree/nodes.dart' as ast; | 10 import 'package:compiler/src/tree/nodes.dart' as ast; |
11 import 'package:expect/expect.dart'; | |
11 import 'package:kernel/ast.dart' as ir; | 12 import 'package:kernel/ast.dart' as ir; |
12 | 13 |
13 enum IdKind { | 14 enum IdKind { |
14 element, | 15 element, |
15 node, | 16 node, |
17 invoke, | |
18 update, | |
16 } | 19 } |
17 | 20 |
18 /// Id for a code point or element with type inference information. | 21 /// Id for a code point or element with type inference information. |
19 abstract class Id { | 22 abstract class Id { |
20 IdKind get kind; | 23 IdKind get kind; |
21 } | 24 } |
22 | 25 |
26 class IdValue { | |
27 final Id id; | |
28 final String value; | |
29 | |
30 const IdValue(this.id, this.value); | |
31 | |
32 int get hashCode => id.hashCode * 13 + value.hashCode * 17; | |
33 | |
34 bool operator ==(other) { | |
35 if (identical(this, other)) return true; | |
36 if (other is! IdValue) return false; | |
37 return id == other.id && value == other.value; | |
38 } | |
39 | |
40 String toString() { | |
41 switch (id.kind) { | |
42 case IdKind.element: | |
43 ElementId elementId = id; | |
44 return '${elementId.name}:$value'; | |
Siggi Cherem (dart-lang)
2017/08/31 23:04:03
to make it easier to understand the ID when readin
Johnni Winther
2017/09/01 14:00:03
Good idea. Encoding changed to
'element: Sub.meth
| |
45 case IdKind.node: | |
46 return value; | |
47 case IdKind.invoke: | |
48 return '()$value'; | |
49 case IdKind.update: | |
50 return '=$value'; | |
51 } | |
52 throw new UnsupportedError("Unexpected id kind: ${id.kind}"); | |
53 } | |
54 | |
55 static IdValue decode(int offset, String text) { | |
56 int colonPos = text.indexOf(':'); | |
57 Id id; | |
58 String expected; | |
59 if (colonPos == -1) { | |
60 if (text.startsWith('=')) { | |
61 id = new NodeId(offset, IdKind.update); | |
62 expected = text.substring(1); | |
63 } else if (text.startsWith('()')) { | |
64 id = new NodeId(offset, IdKind.invoke); | |
65 expected = text.substring(2); | |
66 } else { | |
67 id = new NodeId(offset, IdKind.node); | |
68 expected = text; | |
69 } | |
70 } else { | |
71 id = new ElementId(text.substring(0, colonPos)); | |
72 expected = text.substring(colonPos + 1); | |
73 } | |
74 return new IdValue(id, expected); | |
75 } | |
76 } | |
77 | |
23 /// Id for an element with type inference information. | 78 /// Id for an element with type inference information. |
24 // TODO(johnniwinther): Support local variables, functions and parameters. | 79 // TODO(johnniwinther): Support local variables, functions and parameters. |
25 class ElementId implements Id { | 80 class ElementId implements Id { |
26 final String className; | 81 final String className; |
27 final String memberName; | 82 final String memberName; |
28 | 83 |
29 factory ElementId(String text) { | 84 factory ElementId(String text) { |
30 int dotPos = text.indexOf('.'); | 85 int dotPos = text.indexOf('.'); |
31 if (dotPos != -1) { | 86 if (dotPos != -1) { |
32 return new ElementId.internal( | 87 return new ElementId.internal( |
33 text.substring(dotPos + 1), text.substring(0, dotPos)); | 88 text.substring(dotPos + 1), text.substring(0, dotPos)); |
34 } else { | 89 } else { |
35 return new ElementId.internal(text); | 90 return new ElementId.internal(text); |
36 } | 91 } |
37 } | 92 } |
38 | 93 |
39 ElementId.internal(this.memberName, [this.className]); | 94 ElementId.internal(this.memberName, [this.className]); |
40 | 95 |
41 int get hashCode => className.hashCode * 13 + memberName.hashCode * 17; | 96 int get hashCode => className.hashCode * 13 + memberName.hashCode * 17; |
42 | 97 |
43 bool operator ==(other) { | 98 bool operator ==(other) { |
44 if (identical(this, other)) return true; | 99 if (identical(this, other)) return true; |
45 if (other is! ElementId) return false; | 100 if (other is! ElementId) return false; |
46 return className == other.className && memberName == other.memberName; | 101 return className == other.className && memberName == other.memberName; |
47 } | 102 } |
48 | 103 |
49 IdKind get kind => IdKind.element; | 104 IdKind get kind => IdKind.element; |
50 | 105 |
51 String toString() => | 106 String get name => className != null ? '$className.$memberName' : memberName; |
52 className != null ? '$className.$memberName' : memberName; | 107 |
108 String toString() => name; | |
53 } | 109 } |
54 | 110 |
55 /// Id for a code point with type inference information. | 111 /// Id for a code point with type inference information. |
56 // TODO(johnniwinther): Create an [NodeId]-based equivalence with the kernel IR. | 112 // TODO(johnniwinther): Create an [NodeId]-based equivalence with the kernel IR. |
57 class NodeId implements Id { | 113 class NodeId implements Id { |
58 final int value; | 114 final int value; |
115 final IdKind kind; | |
59 | 116 |
60 const NodeId(this.value); | 117 const NodeId(this.value, this.kind); |
61 | 118 |
62 int get hashCode => value.hashCode; | 119 int get hashCode => value.hashCode * 13 + kind.hashCode * 17; |
63 | 120 |
64 bool operator ==(other) { | 121 bool operator ==(other) { |
65 if (identical(this, other)) return true; | 122 if (identical(this, other)) return true; |
66 if (other is! NodeId) return false; | 123 if (other is! NodeId) return false; |
67 return value == other.value; | 124 return value == other.value && kind == other.kind; |
68 } | 125 } |
69 | 126 |
70 IdKind get kind => IdKind.node; | |
71 | |
72 String toString() => '$kind:$value'; | 127 String toString() => '$kind:$value'; |
73 } | 128 } |
74 | 129 |
75 class ActualData { | 130 class ActualData { |
76 final Id id; | 131 final IdValue value; |
77 final String value; | |
78 final SourceSpan sourceSpan; | 132 final SourceSpan sourceSpan; |
79 final Object object; | 133 final Object object; |
80 | 134 |
81 ActualData(this.id, this.value, this.sourceSpan, this.object); | 135 ActualData(this.value, this.sourceSpan, this.object); |
136 } | |
137 | |
138 abstract class DataRegistry { | |
139 DiagnosticReporter get reporter; | |
140 Map<Id, ActualData> get actualMap; | |
141 | |
142 void registerValue( | |
143 SourceSpan sourceSpan, Id id, String value, Object object) { | |
144 if (actualMap.containsKey(id)) { | |
145 ActualData existingData = actualMap[id]; | |
146 reportHere(reporter, sourceSpan, | |
147 "Duplicate id ${id}, value=$value, object=$object"); | |
148 reportHere( | |
149 reporter, | |
150 sourceSpan, | |
151 "Duplicate id ${id}, value=${existingData.value}, " | |
152 "object=${existingData.object}"); | |
153 Expect.fail("Duplicate id $id."); | |
154 } | |
155 if (value != null) { | |
156 actualMap[id] = | |
157 new ActualData(new IdValue(id, value), sourceSpan, object); | |
158 } | |
159 } | |
82 } | 160 } |
83 | 161 |
84 /// Abstract AST visitor for computing data corresponding to a node or element, | 162 /// Abstract AST visitor for computing data corresponding to a node or element, |
85 // and record it with a generic [Id]. | 163 // and record it with a generic [Id]. |
86 abstract class AstDataExtractor extends ast.Visitor { | 164 abstract class AstDataExtractor extends ast.Visitor with DataRegistry { |
87 final DiagnosticReporter reporter; | 165 final DiagnosticReporter reporter; |
88 final Map<Id, ActualData> actualMap; | 166 final Map<Id, ActualData> actualMap; |
89 final ResolvedAst resolvedAst; | 167 final ResolvedAst resolvedAst; |
90 | 168 |
91 AstDataExtractor(this.reporter, this.actualMap, this.resolvedAst); | 169 AstDataExtractor(this.reporter, this.actualMap, this.resolvedAst); |
92 | 170 |
93 /// Implement this to compute the data corresponding to [element]. | 171 /// Implement this to compute the data corresponding to [element]. |
94 /// | 172 /// |
95 /// If `null` is returned, [element] has no associated data. | 173 /// If `null` is returned, [element] has no associated data. |
96 String computeElementValue(AstElement element); | 174 String computeElementValue(Id id, AstElement element); |
97 | 175 |
98 /// Implement this to compute the data corresponding to [node]. If [node] has | 176 /// Implement this to compute the data corresponding to [node]. If [node] has |
99 /// a corresponding [AstElement] this is provided in [element]. | 177 /// a corresponding [AstElement] this is provided in [element]. |
100 /// | 178 /// |
101 /// If `null` is returned, [node] has no associated data. | 179 /// If `null` is returned, [node] has no associated data. |
102 String computeNodeValue(ast.Node node, AstElement element); | 180 String computeNodeValue(Id id, ast.Node node, AstElement element); |
103 | 181 |
104 TreeElements get elements => resolvedAst.elements; | 182 TreeElements get elements => resolvedAst.elements; |
105 | 183 |
106 void registerValue( | |
107 SourceSpan sourceSpan, Id id, String value, Object object) { | |
108 if (value != null) { | |
109 actualMap[id] = new ActualData(id, value, sourceSpan, object); | |
110 } | |
111 } | |
112 | |
113 ElementId computeElementId(AstElement element) { | 184 ElementId computeElementId(AstElement element) { |
114 String memberName = element.name; | 185 String memberName = element.name; |
115 if (element.isSetter) { | 186 if (element.isSetter) { |
116 memberName += '='; | 187 memberName += '='; |
117 } | 188 } |
118 String className = element.enclosingClass?.name; | 189 String className = element.enclosingClass?.name; |
119 return new ElementId.internal(memberName, className); | 190 return new ElementId.internal(memberName, className); |
120 } | 191 } |
121 | 192 |
122 NodeId computeAccessId(ast.Send node, AccessSemantics access) { | 193 ast.Node computeAccessPosition(ast.Send node, AccessSemantics access) { |
123 switch (access.kind) { | 194 switch (access.kind) { |
124 case AccessKind.DYNAMIC_PROPERTY: | 195 case AccessKind.DYNAMIC_PROPERTY: |
125 case AccessKind.LOCAL_VARIABLE: | 196 case AccessKind.LOCAL_VARIABLE: |
126 case AccessKind.FINAL_LOCAL_VARIABLE: | 197 case AccessKind.FINAL_LOCAL_VARIABLE: |
127 case AccessKind.LOCAL_FUNCTION: | 198 case AccessKind.LOCAL_FUNCTION: |
128 case AccessKind.PARAMETER: | 199 case AccessKind.PARAMETER: |
129 case AccessKind.FINAL_PARAMETER: | 200 case AccessKind.FINAL_PARAMETER: |
130 case AccessKind.EXPRESSION: | 201 case AccessKind.EXPRESSION: |
131 return computeDefaultNodeId(node.selector); | 202 return node.selector; |
132 default: | 203 default: |
133 return null; | 204 return null; |
134 } | 205 } |
206 } | |
207 | |
208 ast.Node computeUpdatePosition(ast.Send node, AccessSemantics access) { | |
209 switch (access.kind) { | |
210 case AccessKind.DYNAMIC_PROPERTY: | |
211 case AccessKind.LOCAL_VARIABLE: | |
212 case AccessKind.PARAMETER: | |
213 return node.selector; | |
214 default: | |
215 return null; | |
216 } | |
135 } | 217 } |
136 | 218 |
137 void computeForElement(AstElement element) { | 219 void computeForElement(AstElement element) { |
138 ElementId id = computeElementId(element); | 220 ElementId id = computeElementId(element); |
139 if (id == null) return; | 221 if (id == null) return; |
140 String value = computeElementValue(element); | 222 String value = computeElementValue(id, element); |
141 registerValue(element.sourcePosition, id, value, element); | 223 registerValue(element.sourcePosition, id, value, element); |
142 } | 224 } |
143 | 225 |
144 void computeForNode(ast.Node node, NodeId id, [AstElement element]) { | 226 void computeForNode(ast.Node node, NodeId id, [AstElement element]) { |
145 if (id == null) return; | 227 if (id == null) return; |
146 String value = computeNodeValue(node, element); | 228 String value = computeNodeValue(id, node, element); |
147 SourceSpan sourceSpan = computeSourceSpan(node); | 229 SourceSpan sourceSpan = computeSourceSpan(node); |
148 registerValue(sourceSpan, id, value, element ?? node); | 230 registerValue(sourceSpan, id, value, element ?? node); |
149 } | 231 } |
150 | 232 |
151 SourceSpan computeSourceSpan(ast.Node node) { | 233 SourceSpan computeSourceSpan(ast.Node node) { |
152 return new SourceSpan(resolvedAst.sourceUri, | 234 return new SourceSpan(resolvedAst.sourceUri, |
153 node.getBeginToken().charOffset, node.getEndToken().charEnd); | 235 node.getBeginToken().charOffset, node.getEndToken().charEnd); |
154 } | 236 } |
155 | 237 |
156 NodeId computeDefaultNodeId(ast.Node node) { | 238 NodeId computeDefaultNodeId(ast.Node node) { |
157 return new NodeId(node.getBeginToken().charOffset); | 239 return new NodeId(node.getBeginToken().charOffset, IdKind.node); |
158 } | 240 } |
159 | 241 |
160 NodeId computeLoopNodeId(ast.Node node) => computeDefaultNodeId(node); | 242 NodeId createAccessId(ast.Node node) { |
243 return new NodeId(node.getBeginToken().charOffset, IdKind.node); | |
244 } | |
161 | 245 |
162 NodeId computeGotoNodeId(ast.Node node) => computeDefaultNodeId(node); | 246 NodeId createInvokeId(ast.Node node) { |
247 return new NodeId(node.getBeginToken().charOffset, IdKind.invoke); | |
248 } | |
163 | 249 |
164 NodeId computeSwitchNodeId(ast.SwitchStatement node) => | 250 NodeId createUpdateId(ast.Node node) { |
165 computeDefaultNodeId(node); | 251 return new NodeId(node.getBeginToken().charOffset, IdKind.update); |
252 } | |
166 | 253 |
167 NodeId computeSwitchCaseNodeId(ast.SwitchCase node) { | 254 NodeId createLoopId(ast.Node node) => computeDefaultNodeId(node); |
255 | |
256 NodeId createGotoId(ast.Node node) => computeDefaultNodeId(node); | |
257 | |
258 NodeId createSwitchId(ast.SwitchStatement node) => computeDefaultNodeId(node); | |
259 | |
260 NodeId createSwitchCaseId(ast.SwitchCase node) { | |
168 ast.Node position; | 261 ast.Node position; |
169 for (ast.Node child in node.labelsAndCases) { | 262 for (ast.Node child in node.labelsAndCases) { |
170 if (child.asCaseMatch() != null) { | 263 if (child.asCaseMatch() != null) { |
171 ast.CaseMatch caseMatch = child; | 264 ast.CaseMatch caseMatch = child; |
172 position = caseMatch.expression; | 265 position = caseMatch.expression; |
173 break; | 266 break; |
174 } | 267 } |
175 } | 268 } |
176 return computeDefaultNodeId(position); | 269 return computeDefaultNodeId(position); |
177 } | 270 } |
(...skipping 28 matching lines...) Expand all Loading... | |
206 computeForNode(node, computeDefaultNodeId(node), element); | 299 computeForNode(node, computeDefaultNodeId(node), element); |
207 } | 300 } |
208 visitNode(node); | 301 visitNode(node); |
209 } | 302 } |
210 | 303 |
211 visitSend(ast.Send node) { | 304 visitSend(ast.Send node) { |
212 dynamic sendStructure = elements.getSendStructure(node); | 305 dynamic sendStructure = elements.getSendStructure(node); |
213 if (sendStructure != null) { | 306 if (sendStructure != null) { |
214 switch (sendStructure.kind) { | 307 switch (sendStructure.kind) { |
215 case SendStructureKind.GET: | 308 case SendStructureKind.GET: |
309 ast.Node position = | |
310 computeAccessPosition(node, sendStructure.semantics); | |
311 if (position != null) { | |
312 computeForNode(node, computeDefaultNodeId(position)); | |
313 } | |
314 break; | |
216 case SendStructureKind.INVOKE: | 315 case SendStructureKind.INVOKE: |
217 case SendStructureKind.BINARY: | 316 case SendStructureKind.BINARY: |
218 case SendStructureKind.EQUALS: | 317 case SendStructureKind.EQUALS: |
219 case SendStructureKind.NOT_EQUALS: | 318 case SendStructureKind.NOT_EQUALS: |
220 computeForNode(node, computeAccessId(node, sendStructure.semantics)); | 319 ast.Node position = |
320 computeAccessPosition(node, sendStructure.semantics); | |
321 if (position != null) { | |
322 computeForNode(node, createInvokeId(position)); | |
323 } | |
324 break; | |
325 case SendStructureKind.SET: | |
221 break; | 326 break; |
222 default: | 327 default: |
223 } | 328 } |
329 } | |
330 visitNode(node); | |
331 } | |
332 | |
333 visitSendSet(ast.SendSet node) { | |
334 dynamic sendStructure = elements.getSendStructure(node); | |
335 if (sendStructure != null) { | |
336 switch (sendStructure.kind) { | |
337 case SendStructureKind.SET: | |
338 ast.Node position = | |
339 computeUpdatePosition(node, sendStructure.semantics); | |
340 if (position != null) { | |
341 computeForNode(node, createUpdateId(position)); | |
342 } | |
343 break; | |
344 case SendStructureKind.POSTFIX: | |
345 computeForNode(node, createAccessId(node.selector)); | |
346 computeForNode(node, createInvokeId(node.assignmentOperator)); | |
347 computeForNode(node, createUpdateId(node.selector)); | |
348 break; | |
349 default: | |
350 } | |
224 } | 351 } |
225 visitNode(node); | 352 visitNode(node); |
226 } | 353 } |
227 | 354 |
228 visitLoop(ast.Loop node) { | 355 visitLoop(ast.Loop node) { |
229 computeForNode(node, computeLoopNodeId(node)); | 356 computeForNode(node, createLoopId(node)); |
230 visitNode(node); | 357 visitNode(node); |
231 } | 358 } |
232 | 359 |
233 visitGotoStatement(ast.GotoStatement node) { | 360 visitGotoStatement(ast.GotoStatement node) { |
234 computeForNode(node, computeGotoNodeId(node)); | 361 computeForNode(node, createGotoId(node)); |
235 visitNode(node); | 362 visitNode(node); |
236 } | 363 } |
237 | 364 |
238 visitSwitchStatement(ast.SwitchStatement node) { | 365 visitSwitchStatement(ast.SwitchStatement node) { |
239 computeForNode(node, computeSwitchNodeId(node)); | 366 computeForNode(node, createSwitchId(node)); |
240 visitNode(node); | 367 visitNode(node); |
241 } | 368 } |
242 | 369 |
243 visitSwitchCase(ast.SwitchCase node) { | 370 visitSwitchCase(ast.SwitchCase node) { |
244 computeForNode(node, computeSwitchCaseNodeId(node)); | 371 computeForNode(node, createSwitchCaseId(node)); |
245 visitNode(node); | 372 visitNode(node); |
246 } | 373 } |
247 } | 374 } |
248 | 375 |
249 /// Abstract IR visitor for computing data corresponding to a node or element, | 376 /// Abstract IR visitor for computing data corresponding to a node or element, |
250 /// and record it with a generic [Id] | 377 /// and record it with a generic [Id] |
251 abstract class IrDataExtractor extends ir.Visitor { | 378 abstract class IrDataExtractor extends ir.Visitor with DataRegistry { |
379 final DiagnosticReporter reporter; | |
252 final Map<Id, ActualData> actualMap; | 380 final Map<Id, ActualData> actualMap; |
253 | 381 |
254 void registerValue( | |
255 SourceSpan sourceSpan, Id id, String value, Object object) { | |
256 if (value != null) { | |
257 actualMap[id] = new ActualData(id, value, sourceSpan, object); | |
258 } | |
259 } | |
260 | |
261 /// Implement this to compute the data corresponding to [member]. | 382 /// Implement this to compute the data corresponding to [member]. |
262 /// | 383 /// |
263 /// If `null` is returned, [member] has no associated data. | 384 /// If `null` is returned, [member] has no associated data. |
264 String computeMemberValue(ir.Member member); | 385 String computeMemberValue(Id id, ir.Member member); |
265 | 386 |
266 /// Implement this to compute the data corresponding to [node]. | 387 /// Implement this to compute the data corresponding to [node]. |
267 /// | 388 /// |
268 /// If `null` is returned, [node] has no associated data. | 389 /// If `null` is returned, [node] has no associated data. |
269 String computeNodeValue(ir.TreeNode node); | 390 String computeNodeValue(Id id, ir.TreeNode node); |
270 | 391 |
271 IrDataExtractor(this.actualMap); | 392 IrDataExtractor(this.reporter, this.actualMap); |
272 Id computeElementId(ir.Member node) { | 393 Id computeElementId(ir.Member node) { |
273 String className; | 394 String className; |
274 if (node.enclosingClass != null) { | 395 if (node.enclosingClass != null) { |
275 className = node.enclosingClass.name; | 396 className = node.enclosingClass.name; |
276 } | 397 } |
277 String memberName = node.name.name; | 398 String memberName = node.name.name; |
278 if (node is ir.Procedure && node.kind == ir.ProcedureKind.Setter) { | 399 if (node is ir.Procedure && node.kind == ir.ProcedureKind.Setter) { |
279 memberName += '='; | 400 memberName += '='; |
280 } | 401 } |
281 return new ElementId.internal(memberName, className); | 402 return new ElementId.internal(memberName, className); |
282 } | 403 } |
283 | 404 |
284 void computeForMember(ir.Member member) { | 405 void computeForMember(ir.Member member) { |
285 ElementId id = computeElementId(member); | 406 ElementId id = computeElementId(member); |
286 if (id == null) return; | 407 if (id == null) return; |
287 String value = computeMemberValue(member); | 408 String value = computeMemberValue(id, member); |
288 registerValue(computeSourceSpan(member), id, value, member); | 409 registerValue(computeSourceSpan(member), id, value, member); |
289 } | 410 } |
290 | 411 |
291 void computeForNode(ir.TreeNode node, NodeId id) { | 412 void computeForNode(ir.TreeNode node, NodeId id) { |
292 if (id == null) return; | 413 if (id == null) return; |
293 String value = computeNodeValue(node); | 414 String value = computeNodeValue(id, node); |
294 registerValue(computeSourceSpan(node), id, value, node); | 415 registerValue(computeSourceSpan(node), id, value, node); |
295 } | 416 } |
296 | 417 |
297 SourceSpan computeSourceSpan(ir.TreeNode node) { | 418 SourceSpan computeSourceSpan(ir.TreeNode node) { |
298 return new SourceSpan( | 419 return new SourceSpan( |
299 Uri.parse(node.location.file), node.fileOffset, node.fileOffset + 1); | 420 Uri.parse(node.location.file), node.fileOffset, node.fileOffset + 1); |
300 } | 421 } |
301 | 422 |
302 NodeId computeDefaultNodeId(ir.TreeNode node) { | 423 NodeId computeDefaultNodeId(ir.TreeNode node) { |
303 assert(node.fileOffset != ir.TreeNode.noOffset); | 424 assert(node.fileOffset != ir.TreeNode.noOffset); |
304 return new NodeId(node.fileOffset); | 425 return new NodeId(node.fileOffset, IdKind.node); |
305 } | 426 } |
306 | 427 |
307 NodeId computeLoopNodeId(ir.TreeNode node) => computeDefaultNodeId(node); | 428 NodeId createInvokeId(ir.TreeNode node) { |
308 NodeId computeGotoNodeId(ir.TreeNode node) => computeDefaultNodeId(node); | 429 assert(node.fileOffset != ir.TreeNode.noOffset); |
309 NodeId computeSwitchNodeId(ir.SwitchStatement node) => | 430 return new NodeId(node.fileOffset, IdKind.invoke); |
310 computeDefaultNodeId(node); | 431 } |
311 NodeId computeSwitchCaseNodeId(ir.SwitchCase node) => | 432 |
312 new NodeId(node.expressionOffsets.first); | 433 NodeId createUpdateId(ir.TreeNode node) { |
434 assert(node.fileOffset != ir.TreeNode.noOffset); | |
435 return new NodeId(node.fileOffset, IdKind.update); | |
436 } | |
437 | |
438 NodeId createLoopId(ir.TreeNode node) => computeDefaultNodeId(node); | |
439 NodeId createGotoId(ir.TreeNode node) => computeDefaultNodeId(node); | |
440 NodeId createSwitchId(ir.SwitchStatement node) => computeDefaultNodeId(node); | |
441 NodeId createSwitchCaseId(ir.SwitchCase node) => | |
442 new NodeId(node.expressionOffsets.first, IdKind.node); | |
313 | 443 |
314 void run(ir.Node root) { | 444 void run(ir.Node root) { |
315 root.accept(this); | 445 root.accept(this); |
316 } | 446 } |
317 | 447 |
318 defaultNode(ir.Node node) { | 448 defaultNode(ir.Node node) { |
319 node.visitChildren(this); | 449 node.visitChildren(this); |
320 } | 450 } |
321 | 451 |
322 defaultMember(ir.Member node) { | 452 defaultMember(ir.Member node) { |
323 computeForMember(node); | 453 computeForMember(node); |
324 super.defaultMember(node); | 454 super.defaultMember(node); |
325 } | 455 } |
326 | 456 |
327 visitMethodInvocation(ir.MethodInvocation node) { | 457 visitMethodInvocation(ir.MethodInvocation node) { |
328 computeForNode(node, computeDefaultNodeId(node)); | 458 computeForNode(node, createInvokeId(node)); |
329 super.visitMethodInvocation(node); | 459 super.visitMethodInvocation(node); |
330 } | 460 } |
331 | 461 |
332 visitPropertyGet(ir.PropertyGet node) { | 462 visitPropertyGet(ir.PropertyGet node) { |
333 computeForNode(node, computeDefaultNodeId(node)); | 463 computeForNode(node, computeDefaultNodeId(node)); |
334 super.visitPropertyGet(node); | 464 super.visitPropertyGet(node); |
335 } | 465 } |
336 | 466 |
337 visitVariableDeclaration(ir.VariableDeclaration node) { | 467 visitVariableDeclaration(ir.VariableDeclaration node) { |
338 computeForNode(node, computeDefaultNodeId(node)); | 468 if (node.parent is! ir.FunctionDeclaration) { |
469 computeForNode(node, computeDefaultNodeId(node)); | |
470 } | |
339 super.visitVariableDeclaration(node); | 471 super.visitVariableDeclaration(node); |
340 } | 472 } |
341 | 473 |
342 visitFunctionDeclaration(ir.FunctionDeclaration node) { | 474 visitFunctionDeclaration(ir.FunctionDeclaration node) { |
343 computeForNode(node, computeDefaultNodeId(node)); | 475 computeForNode(node, computeDefaultNodeId(node)); |
344 super.visitFunctionDeclaration(node); | 476 super.visitFunctionDeclaration(node); |
345 } | 477 } |
346 | 478 |
347 visitFunctionExpression(ir.FunctionExpression node) { | 479 visitFunctionExpression(ir.FunctionExpression node) { |
348 computeForNode(node, computeDefaultNodeId(node)); | 480 computeForNode(node, computeDefaultNodeId(node)); |
349 super.visitFunctionExpression(node); | 481 super.visitFunctionExpression(node); |
350 } | 482 } |
351 | 483 |
352 visitVariableGet(ir.VariableGet node) { | 484 visitVariableGet(ir.VariableGet node) { |
353 computeForNode(node, computeDefaultNodeId(node)); | 485 computeForNode(node, computeDefaultNodeId(node)); |
354 super.visitVariableGet(node); | 486 super.visitVariableGet(node); |
355 } | 487 } |
356 | 488 |
489 visitPropertySet(ir.PropertySet node) { | |
490 computeForNode(node, createUpdateId(node)); | |
491 super.visitPropertySet(node); | |
492 } | |
493 | |
494 visitVariableSet(ir.VariableSet node) { | |
495 computeForNode(node, createUpdateId(node)); | |
496 super.visitVariableSet(node); | |
497 } | |
498 | |
357 visitDoStatement(ir.DoStatement node) { | 499 visitDoStatement(ir.DoStatement node) { |
358 computeForNode(node, computeLoopNodeId(node)); | 500 computeForNode(node, createLoopId(node)); |
359 super.visitDoStatement(node); | 501 super.visitDoStatement(node); |
360 } | 502 } |
361 | 503 |
362 visitForStatement(ir.ForStatement node) { | 504 visitForStatement(ir.ForStatement node) { |
363 computeForNode(node, computeLoopNodeId(node)); | 505 computeForNode(node, createLoopId(node)); |
364 super.visitForStatement(node); | 506 super.visitForStatement(node); |
365 } | 507 } |
366 | 508 |
367 visitForInStatement(ir.ForInStatement node) { | 509 visitForInStatement(ir.ForInStatement node) { |
368 computeForNode(node, computeLoopNodeId(node)); | 510 computeForNode(node, createLoopId(node)); |
369 super.visitForInStatement(node); | 511 super.visitForInStatement(node); |
370 } | 512 } |
371 | 513 |
372 visitWhileStatement(ir.WhileStatement node) { | 514 visitWhileStatement(ir.WhileStatement node) { |
373 computeForNode(node, computeLoopNodeId(node)); | 515 computeForNode(node, createLoopId(node)); |
374 super.visitWhileStatement(node); | 516 super.visitWhileStatement(node); |
375 } | 517 } |
376 | 518 |
377 visitBreakStatement(ir.BreakStatement node) { | 519 visitBreakStatement(ir.BreakStatement node) { |
378 computeForNode(node, computeGotoNodeId(node)); | 520 computeForNode(node, createGotoId(node)); |
379 super.visitBreakStatement(node); | 521 super.visitBreakStatement(node); |
380 } | 522 } |
381 | 523 |
382 visitSwitchStatement(ir.SwitchStatement node) { | 524 visitSwitchStatement(ir.SwitchStatement node) { |
383 computeForNode(node, computeSwitchNodeId(node)); | 525 computeForNode(node, createSwitchId(node)); |
384 super.visitSwitchStatement(node); | 526 super.visitSwitchStatement(node); |
385 } | 527 } |
386 | 528 |
387 visitSwitchCase(ir.SwitchCase node) { | 529 visitSwitchCase(ir.SwitchCase node) { |
388 computeForNode(node, computeSwitchCaseNodeId(node)); | 530 computeForNode(node, createSwitchCaseId(node)); |
389 super.visitSwitchCase(node); | 531 super.visitSwitchCase(node); |
390 } | 532 } |
391 | 533 |
392 visitContinueSwitchStatement(ir.ContinueSwitchStatement node) { | 534 visitContinueSwitchStatement(ir.ContinueSwitchStatement node) { |
393 computeForNode(node, computeGotoNodeId(node)); | 535 computeForNode(node, createGotoId(node)); |
394 super.visitContinueSwitchStatement(node); | 536 super.visitContinueSwitchStatement(node); |
395 } | 537 } |
396 } | 538 } |
OLD | NEW |