OLD | NEW |
| (Empty) |
1 // Copyright (c) 2015, the Dartino project authors. Please see the AUTHORS file | |
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.md file. | |
4 | |
5 library fletchc.closure_environment; | |
6 | |
7 import 'package:compiler/src/resolution/semantic_visitor.dart'; | |
8 | |
9 import 'package:compiler/src/resolution/operators.dart' show | |
10 AssignmentOperator, | |
11 BinaryOperator, | |
12 IncDecOperator, | |
13 UnaryOperator; | |
14 | |
15 import 'package:compiler/src/elements/elements.dart'; | |
16 import 'package:compiler/src/resolution/tree_elements.dart'; | |
17 import 'package:compiler/src/resolution/send_resolver.dart'; | |
18 import 'package:compiler/src/tree/tree.dart'; | |
19 import 'package:compiler/src/universe/selector.dart'; | |
20 import 'package:compiler/src/universe/call_structure.dart'; | |
21 import 'package:compiler/src/diagnostics/spannable.dart' show | |
22 Spannable, | |
23 SpannableAssertionFailure; | |
24 import 'package:compiler/src/dart_types.dart'; | |
25 | |
26 enum CaptureMode { | |
27 /** | |
28 * If a local is marked [ByValue], the local is read in closures. | |
29 */ | |
30 ByValue, | |
31 | |
32 /** | |
33 * If a local is marked [ByReference], a write to the local can be observed | |
34 * from a closure. | |
35 * | |
36 * In this case, the local must be boxed. | |
37 */ | |
38 ByReference, | |
39 } | |
40 | |
41 /** | |
42 * The computed infomation about a closures usage of locals and 'this'. | |
43 */ | |
44 class ClosureInfo { | |
45 bool isThisFree = false; | |
46 Set<LocalElement> free = new Set<LocalElement>(); | |
47 | |
48 void markUsed(LocalElement element) { | |
49 free.add(element); | |
50 } | |
51 } | |
52 | |
53 class ClosureEnvironment { | |
54 /** | |
55 * A map of locals that are captured, and how. | |
56 */ | |
57 final Map<LocalElement, CaptureMode> captured = <LocalElement, CaptureMode>{}; | |
58 | |
59 /** | |
60 * A map of all nested closures of [function], and what locals they capture. | |
61 */ | |
62 final Map<FunctionElement, ClosureInfo> closures = | |
63 <FunctionElement, ClosureInfo>{}; | |
64 | |
65 bool shouldBeBoxed(element) => captured[element] == CaptureMode.ByReference; | |
66 } | |
67 | |
68 class ClosureVisitor | |
69 extends SemanticVisitor | |
70 with TraversalSendMixin, | |
71 SemanticSendResolvedMixin, | |
72 BaseImplementationOfLocalsMixin, | |
73 VariableBulkMixin, | |
74 ParameterBulkMixin, | |
75 FunctionBulkMixin, | |
76 ConstructorBulkMixin, | |
77 InitializerBulkMixin | |
78 implements SemanticSendVisitor, SemanticDeclarationVisitor { | |
79 final ClosureEnvironment closureEnvironment = new ClosureEnvironment(); | |
80 | |
81 /** | |
82 * A set of all locals that are assigned in [function] excluding nested | |
83 * closures. This is the inverse of implicit final locals. | |
84 */ | |
85 final Set<LocalElement> locallyAssigned = new Set<LocalElement>(); | |
86 | |
87 final MemberElement element; | |
88 | |
89 ExecutableElement currentElement; | |
90 | |
91 bool inInitializers = false; | |
92 | |
93 ClosureVisitor(this.element, TreeElements elements) | |
94 : super(elements); | |
95 | |
96 SemanticSendVisitor get sendVisitor => this; | |
97 SemanticDeclarationVisitor get declVisitor => this; | |
98 | |
99 ClosureEnvironment compute() { | |
100 assert(element.memberContext == element); | |
101 assert(currentElement == null); | |
102 currentElement = element; | |
103 if (element.node != null) element.resolvedAst.node.accept(this); | |
104 assert(currentElement == element); | |
105 return closureEnvironment; | |
106 } | |
107 | |
108 void visitNode(Node node) { | |
109 node.visitChildren(this); | |
110 } | |
111 | |
112 void visitVariableDefinitions(VariableDefinitions node) { | |
113 for (Node definition in node.definitions) { | |
114 VariableElement element = elements[definition]; | |
115 Expression initializer = element.initializer; | |
116 if (initializer != null) initializer.accept(this); | |
117 } | |
118 } | |
119 | |
120 void visitFunctionExpression(FunctionExpression node) { | |
121 ExecutableElement oldElement = currentElement; | |
122 currentElement = elements.getFunctionDefinition(node); | |
123 if (currentElement != element) { | |
124 ClosureInfo info = new ClosureInfo(); | |
125 closureEnvironment.closures[currentElement] = info; | |
126 } | |
127 if (currentElement.isConstructor) { | |
128 inInitializers = true; | |
129 visitInitializers(node, null); | |
130 inInitializers = false; | |
131 } | |
132 node.body.accept(this); | |
133 currentElement = oldElement; | |
134 } | |
135 | |
136 void visitFieldInitializer( | |
137 SendSet node, | |
138 FieldElement field, | |
139 Node initializer, | |
140 _) { | |
141 initializer.accept(this); | |
142 } | |
143 | |
144 void visitSuperConstructorInvoke( | |
145 Send node, | |
146 ConstructorElement superConstructor, | |
147 InterfaceType type, | |
148 NodeList arguments, | |
149 CallStructure callStructure, | |
150 _) { | |
151 arguments.accept(this); | |
152 } | |
153 | |
154 void visitThisConstructorInvoke( | |
155 Send node, | |
156 ConstructorElement thisConstructor, | |
157 NodeList arguments, | |
158 CallStructure callStructure, | |
159 _) { | |
160 arguments.accept(this); | |
161 } | |
162 | |
163 void markUsed(LocalElement element, CaptureMode use) { | |
164 if (currentElement == element.executableContext) { | |
165 // If a local is assigned in the declaring context, and it is captured | |
166 // at this point, mark it as used by reference (we assign to the value | |
167 // after it's captured). | |
168 if (use == CaptureMode.ByReference) { | |
169 if (closureEnvironment.captured.containsKey(element)) { | |
170 closureEnvironment.captured[element] = use; | |
171 } else { | |
172 locallyAssigned.add(element); | |
173 } | |
174 } | |
175 } else { | |
176 if (locallyAssigned.contains(element)) use = CaptureMode.ByReference; | |
177 // If the element is used by reference, upgrade it unconditionally. | |
178 if (use == CaptureMode.ByReference) { | |
179 closureEnvironment.captured[element] = use; | |
180 } else { | |
181 // If it's used by value, only add it to `captured` if it's not | |
182 // there already - if it's in there it can be by reference. | |
183 closureEnvironment.captured.putIfAbsent(element, () => use); | |
184 } | |
185 ExecutableElement current = currentElement; | |
186 // Mark all closures from the current to the one where `element` is | |
187 // defined, as used in that closure. That makes sure we capture it in | |
188 // all intermidiate closures, thus making it available in the current. | |
189 while (current != element.executableContext) { | |
190 ClosureInfo info = closureEnvironment.closures[current]; | |
191 info.markUsed(element); | |
192 current = (current as Local).executableContext; | |
193 } | |
194 } | |
195 } | |
196 | |
197 void markThisUsed() { | |
198 assert(!inInitializers); | |
199 ExecutableElement current = currentElement; | |
200 while (current != element) { | |
201 ClosureInfo info = closureEnvironment.closures[current]; | |
202 info.isThisFree = true; | |
203 current = (current as Local).executableContext; | |
204 } | |
205 } | |
206 | |
207 void handleLocalGet(Send node, LocalElement element, _) { | |
208 markUsed(element, CaptureMode.ByValue); | |
209 } | |
210 | |
211 void handleLocalSet( | |
212 SendSet node, | |
213 LocalElement element, | |
214 Node rhs, | |
215 _) { | |
216 markUsed(element, CaptureMode.ByReference); | |
217 rhs.accept(this); | |
218 } | |
219 | |
220 void handleLocalInvoke( | |
221 Send node, | |
222 LocalElement element, | |
223 NodeList arguments, | |
224 CallStructure callStructure, | |
225 _) { | |
226 markUsed(element, CaptureMode.ByValue); | |
227 arguments.accept(this); | |
228 } | |
229 | |
230 void visitThisPropertySet(Send node, Name name, Node rhs, _) { | |
231 markThisUsed(); | |
232 super.visitThisPropertySet(node, name, rhs, null); | |
233 } | |
234 | |
235 void visitLocalVariablePrefix( | |
236 SendSet node, | |
237 LocalVariableElement element, | |
238 IncDecOperator operator, | |
239 _) { | |
240 markUsed(element, CaptureMode.ByReference); | |
241 } | |
242 | |
243 void visitLocalVariablePostfix( | |
244 SendSet node, | |
245 LocalVariableElement element, | |
246 IncDecOperator operator, | |
247 _) { | |
248 markUsed(element, CaptureMode.ByReference); | |
249 } | |
250 | |
251 void visitThisPropertyInvoke( | |
252 Send node, | |
253 NodeList arguments, | |
254 Selector selector, | |
255 _) { | |
256 markThisUsed(); | |
257 arguments.accept(this); | |
258 } | |
259 | |
260 void visitThisPropertyGet( | |
261 Send node, | |
262 Name name, | |
263 _) { | |
264 markThisUsed(); | |
265 } | |
266 | |
267 void visitThisGet(Node node, _) { | |
268 markThisUsed(); | |
269 } | |
270 | |
271 void visitIs(Send node, Node expression, DartType type, _) { | |
272 // TODO(ajohnsen): Type is used ByValue. | |
273 expression.accept(this); | |
274 } | |
275 | |
276 void visitIsNot(Send node, Node expression, DartType type, _) { | |
277 // TODO(ajohnsen): Type is used ByValue. | |
278 expression.accept(this); | |
279 } | |
280 | |
281 void visitAs(Send node, Node expression, DartType type, _) { | |
282 // TODO(ajohnsen): Type is used ByValue. | |
283 expression.accept(this); | |
284 } | |
285 | |
286 void visitAssert(Assert node) { | |
287 // TODO(ajohnsen): Only visit in checked mode. | |
288 node.condition.accept(this); | |
289 node.message?.accept(this); | |
290 } | |
291 | |
292 void visitLocalVariableCompound( | |
293 Send node, | |
294 LocalVariableElement variable, | |
295 AssignmentOperator operator, | |
296 Node rhs, | |
297 _) { | |
298 markUsed(variable, CaptureMode.ByReference); | |
299 super.visitLocalVariableCompound(node, variable, operator, rhs, null); | |
300 } | |
301 | |
302 void internalError(Spannable spannable, String message) { | |
303 throw new SpannableAssertionFailure(spannable, message); | |
304 } | |
305 | |
306 void apply(Node node, [_]) { | |
307 node.accept(this); | |
308 } | |
309 | |
310 void visitThisInvoke( | |
311 Send node, | |
312 NodeList arguments, | |
313 CallStructure callStructure, | |
314 _) { | |
315 markThisUsed(); | |
316 super.visitThisInvoke(node, arguments, callStructure, null); | |
317 } | |
318 | |
319 void visitSuperFieldGet( | |
320 Send node, | |
321 FieldElement field, | |
322 _) { | |
323 markThisUsed(); | |
324 super.visitSuperFieldGet(node, field, null); | |
325 } | |
326 | |
327 void visitSuperFieldSet( | |
328 SendSet node, | |
329 FieldElement field, | |
330 Node rhs, | |
331 _) { | |
332 markThisUsed(); | |
333 super.visitSuperFieldSet(node, field, rhs, null); | |
334 } | |
335 | |
336 void visitSuperFieldInvoke( | |
337 Send node, | |
338 FieldElement field, | |
339 NodeList arguments, | |
340 CallStructure callStructure, | |
341 _) { | |
342 markThisUsed(); | |
343 super.visitSuperFieldInvoke(node, field, arguments, callStructure, null); | |
344 } | |
345 | |
346 void visitSuperMethodGet( | |
347 Send node, | |
348 MethodElement method, | |
349 _) { | |
350 markThisUsed(); | |
351 super.visitSuperMethodGet(node, method, null); | |
352 } | |
353 | |
354 void visitSuperGetterGet( | |
355 Send node, | |
356 FunctionElement getter, | |
357 _) { | |
358 markThisUsed(); | |
359 super.visitSuperGetterGet(node, getter, null); | |
360 } | |
361 | |
362 void visitSuperSetterSet( | |
363 SendSet node, | |
364 FunctionElement setter, | |
365 Node rhs, | |
366 _) { | |
367 markThisUsed(); | |
368 super.visitSuperSetterSet(node, setter, rhs, null); | |
369 } | |
370 | |
371 void visitSuperGetterInvoke( | |
372 Send node, | |
373 FunctionElement getter, | |
374 NodeList arguments, | |
375 CallStructure callStructure, | |
376 _) { | |
377 markThisUsed(); | |
378 super.visitSuperGetterInvoke(node, getter, arguments, callStructure, null); | |
379 } | |
380 | |
381 void visitTypeVariableTypeLiteralGet( | |
382 Send node, | |
383 TypeVariableElement element, | |
384 _) { | |
385 // TODO(ajohnsen): Visit 'this' for type literal support, except for | |
386 // closures in initializers. | |
387 super.visitTypeVariableTypeLiteralGet(node, element, null); | |
388 } | |
389 | |
390 void visitTypeVariableTypeLiteralInvoke( | |
391 Send node, | |
392 TypeVariableElement element, | |
393 NodeList arguments, | |
394 CallStructure callStructure, | |
395 _) { | |
396 // TODO(ajohnsen): Visit 'this' for type literal support, except for | |
397 // closures in initializers. | |
398 super.visitTypeVariableTypeLiteralInvoke( | |
399 node, element, arguments, callStructure, null); | |
400 } | |
401 | |
402 void visitSuperBinary( | |
403 Send node, | |
404 FunctionElement function, | |
405 BinaryOperator operator, | |
406 Node argument, | |
407 _) { | |
408 markThisUsed(); | |
409 super.visitSuperBinary(node, function, operator, argument, null); | |
410 } | |
411 | |
412 void visitSuperIndex( | |
413 Send node, | |
414 FunctionElement function, | |
415 Node index, | |
416 _) { | |
417 markThisUsed(); | |
418 super.visitSuperIndex(node, function, index, null); | |
419 } | |
420 | |
421 void visitSuperIndexPostfix( | |
422 SendSet node, | |
423 FunctionElement getter, | |
424 FunctionElement setter, | |
425 Node index, | |
426 IncDecOperator operator, | |
427 _) { | |
428 markThisUsed(); | |
429 super.visitSuperIndexPostfix(node, getter, setter, index, operator, null); | |
430 } | |
431 | |
432 void visitSuperNotEquals( | |
433 Send node, | |
434 FunctionElement function, | |
435 Node argument, | |
436 _) { | |
437 markThisUsed(); | |
438 super.visitSuperNotEquals(node, function, argument, null); | |
439 } | |
440 | |
441 void visitSuperEquals( | |
442 Send node, | |
443 FunctionElement function, | |
444 Node argument, | |
445 _) { | |
446 markThisUsed(); | |
447 super.visitSuperEquals(node, function, argument, null); | |
448 } | |
449 | |
450 void visitSuperUnary( | |
451 Send node, | |
452 UnaryOperator operator, | |
453 FunctionElement function, | |
454 _) { | |
455 markThisUsed(); | |
456 super.visitSuperUnary(node, operator, function, null); | |
457 } | |
458 | |
459 void visitSuperIndexSet( | |
460 Send node, | |
461 FunctionElement function, | |
462 Node index, | |
463 Node rhs, | |
464 _) { | |
465 markThisUsed(); | |
466 super.visitSuperIndexSet(node, function, index, rhs, null); | |
467 } | |
468 | |
469 void visitThisPropertyCompound( | |
470 Send node, | |
471 Name name, | |
472 AssignmentOperator operator, | |
473 Node rhs, | |
474 _) { | |
475 markThisUsed(); | |
476 super.visitThisPropertyCompound( | |
477 node, name, operator, rhs, null); | |
478 } | |
479 | |
480 void visitParameterCompound( | |
481 Send node, | |
482 ParameterElement parameter, | |
483 AssignmentOperator operator, | |
484 Node rhs, | |
485 _) { | |
486 markUsed(parameter, CaptureMode.ByReference); | |
487 super.visitParameterCompound(node, parameter, operator, rhs, null); | |
488 } | |
489 | |
490 void visitSuperFieldCompound( | |
491 Send node, | |
492 FieldElement field, | |
493 AssignmentOperator operator, | |
494 Node rhs, | |
495 _) { | |
496 markThisUsed(); | |
497 super.visitSuperFieldCompound(node, field, operator, rhs, null); | |
498 } | |
499 | |
500 void visitSuperGetterSetterCompound( | |
501 Send node, | |
502 FunctionElement getter, | |
503 FunctionElement setter, | |
504 AssignmentOperator operator, | |
505 Node rhs, | |
506 _) { | |
507 markThisUsed(); | |
508 super.visitSuperGetterSetterCompound( | |
509 node, getter, setter, operator, rhs, null); | |
510 } | |
511 | |
512 void visitSuperMethodSetterCompound( | |
513 Send node, | |
514 FunctionElement method, | |
515 FunctionElement setter, | |
516 AssignmentOperator operator, | |
517 Node rhs, | |
518 _) { | |
519 markThisUsed(); | |
520 super.visitSuperMethodSetterCompound( | |
521 node, method, setter, operator, rhs, null); | |
522 } | |
523 | |
524 void visitSuperFieldSetterCompound( | |
525 Send node, | |
526 FieldElement field, | |
527 FunctionElement setter, | |
528 AssignmentOperator operator, | |
529 Node rhs, | |
530 _) { | |
531 markThisUsed(); | |
532 super.visitSuperFieldSetterCompound( | |
533 node, field, setter, operator, rhs, null); | |
534 } | |
535 | |
536 void visitSuperGetterFieldCompound( | |
537 Send node, | |
538 FunctionElement getter, | |
539 FieldElement field, | |
540 AssignmentOperator operator, | |
541 Node rhs, | |
542 _) { | |
543 markThisUsed(); | |
544 super.visitSuperGetterFieldCompound( | |
545 node, getter, field, operator, rhs, null); | |
546 } | |
547 | |
548 void visitSuperCompoundIndexSet( | |
549 Send node, | |
550 FunctionElement getter, | |
551 FunctionElement setter, | |
552 Node index, | |
553 AssignmentOperator operator, | |
554 Node rhs, | |
555 _) { | |
556 markThisUsed(); | |
557 super.visitSuperCompoundIndexSet( | |
558 node, getter, setter, index, operator, rhs, null); | |
559 } | |
560 | |
561 void visitParameterPrefix( | |
562 Send node, | |
563 ParameterElement parameter, | |
564 IncDecOperator operator, | |
565 _) { | |
566 markUsed(parameter, CaptureMode.ByReference); | |
567 super.visitParameterPrefix(node, parameter, operator, null); | |
568 } | |
569 | |
570 void visitThisPropertyPrefix( | |
571 Send node, | |
572 Name name, | |
573 IncDecOperator operator, | |
574 _) { | |
575 markThisUsed(); | |
576 super.visitThisPropertyPrefix( | |
577 node, name, operator, null); | |
578 } | |
579 | |
580 void visitSuperFieldPrefix( | |
581 Send node, | |
582 FieldElement field, | |
583 IncDecOperator operator, | |
584 _) { | |
585 markThisUsed(); | |
586 super.visitSuperFieldPrefix(node, field, operator, null); | |
587 } | |
588 | |
589 void visitSuperFieldFieldPrefix( | |
590 Send node, | |
591 FieldElement readField, | |
592 FieldElement writtenField, | |
593 IncDecOperator operator, | |
594 _) { | |
595 markThisUsed(); | |
596 super.visitSuperFieldFieldPrefix( | |
597 node, readField, writtenField, operator, null); | |
598 } | |
599 | |
600 void visitSuperFieldSetterPrefix( | |
601 Send node, | |
602 FieldElement field, | |
603 FunctionElement setter, | |
604 IncDecOperator operator, | |
605 _) { | |
606 markThisUsed(); | |
607 super.visitSuperFieldSetterPrefix(node, field, setter, operator, null); | |
608 } | |
609 | |
610 void visitSuperGetterSetterPrefix( | |
611 Send node, | |
612 FunctionElement getter, | |
613 FunctionElement setter, | |
614 IncDecOperator operator, | |
615 _) { | |
616 markThisUsed(); | |
617 super.visitSuperGetterSetterPrefix(node, getter, setter, operator, null); | |
618 } | |
619 | |
620 void visitSuperGetterFieldPrefix( | |
621 Send node, | |
622 FunctionElement getter, | |
623 FieldElement field, | |
624 IncDecOperator operator, | |
625 _) { | |
626 markThisUsed(); | |
627 super.visitSuperGetterFieldPrefix(node, getter, field, operator, null); | |
628 } | |
629 | |
630 void visitSuperMethodSetterPrefix( | |
631 Send node, | |
632 FunctionElement method, | |
633 FunctionElement setter, | |
634 IncDecOperator operator, | |
635 _) { | |
636 markThisUsed(); | |
637 super.visitSuperMethodSetterPrefix(node, method, setter, operator, null); | |
638 } | |
639 | |
640 void visitTypeVariableTypeLiteralPrefix( | |
641 Send node, | |
642 TypeVariableElement element, | |
643 IncDecOperator operator, | |
644 _) { | |
645 markThisUsed(); | |
646 super.visitTypeVariableTypeLiteralPrefix(node, element, operator, null); | |
647 } | |
648 | |
649 void visitParameterPostfix( | |
650 Send node, | |
651 ParameterElement parameter, | |
652 IncDecOperator operator, | |
653 _) { | |
654 markUsed(parameter, CaptureMode.ByReference); | |
655 super.visitParameterPostfix(node, parameter, operator, null); | |
656 } | |
657 | |
658 void visitThisPropertyPostfix( | |
659 Send node, | |
660 Name name, | |
661 IncDecOperator operator, | |
662 _) { | |
663 markThisUsed(); | |
664 super.visitThisPropertyPostfix( | |
665 node, name, operator, null); | |
666 } | |
667 | |
668 void visitSuperFieldPostfix( | |
669 Send node, | |
670 FieldElement field, | |
671 IncDecOperator operator, | |
672 _) { | |
673 markThisUsed(); | |
674 super.visitSuperFieldPostfix(node, field, operator, null); | |
675 } | |
676 | |
677 void visitSuperFieldFieldPostfix( | |
678 Send node, | |
679 FieldElement readField, | |
680 FieldElement writtenField, | |
681 IncDecOperator operator, | |
682 _) { | |
683 markThisUsed(); | |
684 super.visitSuperFieldFieldPostfix( | |
685 node, readField, writtenField, operator, null); | |
686 } | |
687 | |
688 void visitSuperFieldSetterPostfix( | |
689 Send node, | |
690 FieldElement field, | |
691 FunctionElement setter, | |
692 IncDecOperator operator, | |
693 _) { | |
694 markThisUsed(); | |
695 super.visitSuperFieldSetterPostfix(node, field, setter, operator, null); | |
696 } | |
697 | |
698 void visitSuperGetterSetterPostfix( | |
699 Send node, | |
700 FunctionElement getter, | |
701 FunctionElement setter, | |
702 IncDecOperator operator, | |
703 _) { | |
704 markThisUsed(); | |
705 super.visitSuperGetterSetterPostfix(node, getter, setter, operator, null); | |
706 } | |
707 | |
708 void visitSuperGetterFieldPostfix( | |
709 Send node, | |
710 FunctionElement getter, | |
711 FieldElement field, | |
712 IncDecOperator operator, | |
713 _) { | |
714 markThisUsed(); | |
715 super.visitSuperGetterFieldPostfix(node, getter, field, operator, null); | |
716 } | |
717 | |
718 void visitSuperMethodSetterPostfix( | |
719 Send node, | |
720 FunctionElement method, | |
721 FunctionElement setter, | |
722 IncDecOperator operator, | |
723 _) { | |
724 markThisUsed(); | |
725 super.visitSuperMethodSetterPostfix(node, method, setter, operator, null); | |
726 } | |
727 | |
728 void visitTypeVariableTypeLiteralPostfix( | |
729 Send node, | |
730 TypeVariableElement element, | |
731 IncDecOperator operator, | |
732 _) { | |
733 markThisUsed(); | |
734 super.visitTypeVariableTypeLiteralPostfix(node, element, operator, null); | |
735 } | |
736 | |
737 void visitSuperIndexPrefix( | |
738 Send node, | |
739 FunctionElement indexFunction, | |
740 FunctionElement indexSetFunction, | |
741 Node index, | |
742 IncDecOperator operator, | |
743 _) { | |
744 markThisUsed(); | |
745 super.visitSuperIndexPrefix( | |
746 node, indexFunction, indexSetFunction, index, operator, null); | |
747 } | |
748 | |
749 @override | |
750 void visitTypeAnnotation(TypeAnnotation node) { | |
751 // This is to avoid the inherited implementation that visits children and | |
752 // throws when encountering anything unresolved. | |
753 } | |
754 | |
755 void handleImmutableLocalSet( | |
756 SendSet node, | |
757 LocalElement element, | |
758 Node rhs, | |
759 _) { | |
760 apply(rhs); | |
761 } | |
762 | |
763 void bulkHandleNode(Node node, String message, _) { | |
764 } | |
765 | |
766 void applyInitializers(FunctionExpression initializers, _) { | |
767 } | |
768 | |
769 void applyParameters(NodeList parameters, _) { | |
770 } | |
771 } | |
OLD | NEW |