OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 library dev_compiler.src.codegen.side_effect_analysis; | 5 library dev_compiler.src.codegen.side_effect_analysis; |
6 | 6 |
7 import 'package:analyzer/src/generated/ast.dart'; | 7 import 'package:analyzer/src/generated/ast.dart'; |
8 import 'package:analyzer/src/generated/constant.dart'; | 8 import 'package:analyzer/src/generated/constant.dart'; |
9 import 'package:analyzer/src/generated/element.dart'; | 9 import 'package:analyzer/src/generated/element.dart'; |
10 import 'package:analyzer/src/generated/error.dart' show ErrorReporter; | 10 import 'package:analyzer/src/generated/error.dart' show ErrorReporter; |
(...skipping 18 matching lines...) Expand all Loading... |
29 /// | 29 /// |
30 /// This method is conservative: it should never return `true` unless it is | 30 /// This method is conservative: it should never return `true` unless it is |
31 /// certain the [node] is stateless, because generated code may rely on the | 31 /// certain the [node] is stateless, because generated code may rely on the |
32 /// correctness of a `true` value. However it may return `false` for things | 32 /// correctness of a `true` value. However it may return `false` for things |
33 /// that are in fact, stateless. | 33 /// that are in fact, stateless. |
34 bool isStateless(Expression node, [AstNode context]) { | 34 bool isStateless(Expression node, [AstNode context]) { |
35 // `this` and `super` cannot be reassigned. | 35 // `this` and `super` cannot be reassigned. |
36 if (node is ThisExpression || node is SuperExpression) return true; | 36 if (node is ThisExpression || node is SuperExpression) return true; |
37 if (node is SimpleIdentifier) { | 37 if (node is SimpleIdentifier) { |
38 var e = node.staticElement; | 38 var e = node.staticElement; |
39 if (e is PropertyAccessorElement) e = | 39 if (e is PropertyAccessorElement) { |
40 (e as PropertyAccessorElement).variable; | 40 e = e.variable; |
| 41 } |
41 if (e is VariableElement && !e.isSynthetic) { | 42 if (e is VariableElement && !e.isSynthetic) { |
42 if (e.isFinal) return true; | 43 if (e.isFinal) return true; |
43 if (e is LocalVariableElement || e is ParameterElement) { | 44 if (e is LocalVariableElement || e is ParameterElement) { |
44 // make sure the local isn't mutated in the context. | 45 // make sure the local isn't mutated in the context. |
45 return !_isPotentiallyMutated(e, context); | 46 return !_isPotentiallyMutated(e, context); |
46 } | 47 } |
47 } | 48 } |
48 } | 49 } |
49 return false; | 50 return false; |
50 } | 51 } |
(...skipping 19 matching lines...) Expand all Loading... |
70 class _AssignmentFinder extends RecursiveAstVisitor { | 71 class _AssignmentFinder extends RecursiveAstVisitor { |
71 final VariableElement _variable; | 72 final VariableElement _variable; |
72 bool _potentiallyMutated = false; | 73 bool _potentiallyMutated = false; |
73 | 74 |
74 _AssignmentFinder(this._variable); | 75 _AssignmentFinder(this._variable); |
75 | 76 |
76 @override | 77 @override |
77 visitSimpleIdentifier(SimpleIdentifier node) { | 78 visitSimpleIdentifier(SimpleIdentifier node) { |
78 // Ignore if qualified. | 79 // Ignore if qualified. |
79 AstNode parent = node.parent; | 80 AstNode parent = node.parent; |
80 if (parent is PrefixedIdentifier && | 81 if (parent is PrefixedIdentifier && identical(parent.identifier, node)) { |
81 identical(parent.identifier, node)) return; | 82 return; |
82 if (parent is PropertyAccess && | 83 } |
83 identical(parent.propertyName, node)) return; | 84 if (parent is PropertyAccess && identical(parent.propertyName, node)) { |
84 if (parent is MethodInvocation && | 85 return; |
85 identical(parent.methodName, node)) return; | 86 } |
| 87 if (parent is MethodInvocation && identical(parent.methodName, node)) { |
| 88 return; |
| 89 } |
86 if (parent is ConstructorName) return; | 90 if (parent is ConstructorName) return; |
87 if (parent is Label) return; | 91 if (parent is Label) return; |
88 | 92 |
89 if (node.inSetterContext() && node.staticElement == _variable) { | 93 if (node.inSetterContext() && node.staticElement == _variable) { |
90 _potentiallyMutated = true; | 94 _potentiallyMutated = true; |
91 } | 95 } |
92 } | 96 } |
93 } | 97 } |
94 | 98 |
95 class ConstFieldVisitor { | 99 class ConstFieldVisitor { |
(...skipping 22 matching lines...) Expand all Loading... |
118 // ConstantEvaluator will not compute constants for non-const fields, | 122 // ConstantEvaluator will not compute constants for non-const fields, |
119 // so run ConstantVisitor for those to figure out if the initializer is | 123 // so run ConstantVisitor for those to figure out if the initializer is |
120 // actually a constant (and therefore side effect free to evaluate). | 124 // actually a constant (and therefore side effect free to evaluate). |
121 assert(!field.isConst); | 125 assert(!field.isConst); |
122 | 126 |
123 var initializer = field.initializer; | 127 var initializer = field.initializer; |
124 if (initializer == null) return null; | 128 if (initializer == null) return null; |
125 return initializer.accept(_constantVisitor); | 129 return initializer.accept(_constantVisitor); |
126 } | 130 } |
127 } | 131 } |
OLD | NEW |