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

Side by Side Diff: pkg/analyzer/lib/src/dart/constant/utilities.dart

Issue 1816923002: Move constant implementation out of generated (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 4 years, 9 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2014, the Dart 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 file.
4
5 library analyzer.src.dart.constant.utilities;
6
7 import 'dart:collection';
8
9 import 'package:analyzer/dart/ast/ast.dart';
10 import 'package:analyzer/dart/ast/visitor.dart';
11 import 'package:analyzer/dart/element/element.dart';
12 import 'package:analyzer/src/dart/ast/utilities.dart';
13 import 'package:analyzer/src/dart/element/element.dart';
14 import 'package:analyzer/src/dart/element/handle.dart'
15 show ConstructorElementHandle;
16 import 'package:analyzer/src/dart/element/member.dart';
17 import 'package:analyzer/src/generated/engine.dart';
18 import 'package:analyzer/src/generated/source.dart' show Source;
19 import 'package:analyzer/src/task/dart.dart';
20
21 ConstructorElementImpl getConstructorImpl(ConstructorElement constructor) {
22 while (constructor is ConstructorMember) {
23 constructor = (constructor as ConstructorMember).baseElement;
24 }
25 if (constructor is ConstructorElementHandle) {
26 constructor = (constructor as ConstructorElementHandle).actualElement;
27 }
28 return constructor;
29 }
30
31 /**
32 * Callback used by [ReferenceFinder] to report that a dependency was found.
33 */
34 typedef void ReferenceFinderCallback(ConstantEvaluationTarget dependency);
35
36 /**
37 * An [AstCloner] that copies the necessary information from the AST to allow
38 * constants to be evaluated.
39 */
40 class ConstantAstCloner extends AstCloner {
41 ConstantAstCloner() : super(true);
42
43 @override
44 ConstructorName visitConstructorName(ConstructorName node) {
45 ConstructorName name = super.visitConstructorName(node);
46 name.staticElement = node.staticElement;
47 return name;
48 }
49
50 @override
51 InstanceCreationExpression visitInstanceCreationExpression(
52 InstanceCreationExpression node) {
53 InstanceCreationExpression expression =
54 super.visitInstanceCreationExpression(node);
55 expression.staticElement = node.staticElement;
56 return expression;
57 }
58
59 @override
60 RedirectingConstructorInvocation visitRedirectingConstructorInvocation(
61 RedirectingConstructorInvocation node) {
62 RedirectingConstructorInvocation invocation =
63 super.visitRedirectingConstructorInvocation(node);
64 invocation.staticElement = node.staticElement;
65 return invocation;
66 }
67
68 @override
69 SimpleIdentifier visitSimpleIdentifier(SimpleIdentifier node) {
70 SimpleIdentifier identifier = super.visitSimpleIdentifier(node);
71 identifier.staticElement = node.staticElement;
72 return identifier;
73 }
74
75 @override
76 SuperConstructorInvocation visitSuperConstructorInvocation(
77 SuperConstructorInvocation node) {
78 SuperConstructorInvocation invocation =
79 super.visitSuperConstructorInvocation(node);
80 invocation.staticElement = node.staticElement;
81 return invocation;
82 }
83
84 @override
85 TypeName visitTypeName(TypeName node) {
86 TypeName typeName = super.visitTypeName(node);
87 typeName.type = node.type;
88 return typeName;
89 }
90 }
91
92 /**
93 * A visitor used to traverse the AST structures of all of the compilation units
94 * being resolved and build the full set of dependencies for all constant
95 * expressions.
96 */
97 class ConstantExpressionsDependenciesFinder extends RecursiveAstVisitor {
98 /**
99 * The constants whose values need to be computed.
100 */
101 HashSet<ConstantEvaluationTarget> dependencies =
102 new HashSet<ConstantEvaluationTarget>();
103
104 @override
105 void visitInstanceCreationExpression(InstanceCreationExpression node) {
106 if (node.isConst) {
107 _find(node);
108 } else {
109 super.visitInstanceCreationExpression(node);
110 }
111 }
112
113 @override
114 void visitListLiteral(ListLiteral node) {
115 if (node.constKeyword != null) {
116 _find(node);
117 } else {
118 super.visitListLiteral(node);
119 }
120 }
121
122 @override
123 void visitMapLiteral(MapLiteral node) {
124 if (node.constKeyword != null) {
125 _find(node);
126 } else {
127 super.visitMapLiteral(node);
128 }
129 }
130
131 @override
132 void visitSwitchCase(SwitchCase node) {
133 _find(node.expression);
134 node.statements.accept(this);
135 }
136
137 void _find(Expression node) {
138 if (node != null) {
139 ReferenceFinder referenceFinder = new ReferenceFinder(dependencies.add);
140 node.accept(referenceFinder);
141 }
142 }
143 }
144
145 /**
146 * A visitor used to traverse the AST structures of all of the compilation units
147 * being resolved and build tables of the constant variables, constant
148 * constructors, constant constructor invocations, and annotations found in
149 * those compilation units.
150 */
151 class ConstantFinder extends RecursiveAstVisitor<Object> {
152 final AnalysisContext context;
153 final Source source;
154 final Source librarySource;
155
156 /**
157 * The elements and AST nodes whose constant values need to be computed.
158 */
159 List<ConstantEvaluationTarget> constantsToCompute =
160 <ConstantEvaluationTarget>[];
161
162 /**
163 * A flag indicating whether instance variables marked as "final" should be
164 * treated as "const".
165 */
166 bool treatFinalInstanceVarAsConst = false;
167
168 ConstantFinder(this.context, this.source, this.librarySource);
169
170 @override
171 Object visitAnnotation(Annotation node) {
172 super.visitAnnotation(node);
173 ElementAnnotation elementAnnotation = node.elementAnnotation;
174 if (elementAnnotation == null) {
175 // Analyzer ignores annotations on "part of" directives.
176 assert(node.parent is PartOfDirective);
177 } else {
178 constantsToCompute.add(elementAnnotation);
179 }
180 return null;
181 }
182
183 @override
184 Object visitClassDeclaration(ClassDeclaration node) {
185 bool prevTreatFinalInstanceVarAsConst = treatFinalInstanceVarAsConst;
186 if (node.element.constructors.any((ConstructorElement e) => e.isConst)) {
187 // Instance vars marked "final" need to be included in the dependency
188 // graph, since constant constructors implicitly use the values in their
189 // initializers.
190 treatFinalInstanceVarAsConst = true;
191 }
192 try {
193 return super.visitClassDeclaration(node);
194 } finally {
195 treatFinalInstanceVarAsConst = prevTreatFinalInstanceVarAsConst;
196 }
197 }
198
199 @override
200 Object visitConstructorDeclaration(ConstructorDeclaration node) {
201 super.visitConstructorDeclaration(node);
202 if (node.constKeyword != null) {
203 ConstructorElement element = node.element;
204 if (element != null) {
205 constantsToCompute.add(element);
206 constantsToCompute.addAll(element.parameters);
207 }
208 }
209 return null;
210 }
211
212 @override
213 Object visitDefaultFormalParameter(DefaultFormalParameter node) {
214 super.visitDefaultFormalParameter(node);
215 Expression defaultValue = node.defaultValue;
216 if (defaultValue != null && node.element != null) {
217 constantsToCompute.add(node.element);
218 }
219 return null;
220 }
221
222 @override
223 Object visitVariableDeclaration(VariableDeclaration node) {
224 super.visitVariableDeclaration(node);
225 Expression initializer = node.initializer;
226 VariableElement element = node.element;
227 if (initializer != null &&
228 (node.isConst ||
229 treatFinalInstanceVarAsConst &&
230 element is FieldElement &&
231 node.isFinal &&
232 !element.isStatic)) {
233 if (element != null) {
234 constantsToCompute.add(element);
235 }
236 }
237 return null;
238 }
239 }
240
241 /**
242 * An object used to add reference information for a given variable to the
243 * bi-directional mapping used to order the evaluation of constants.
244 */
245 class ReferenceFinder extends RecursiveAstVisitor<Object> {
246 /**
247 * The callback which should be used to report any dependencies that were
248 * found.
249 */
250 final ReferenceFinderCallback _callback;
251
252 /**
253 * Initialize a newly created reference finder to find references from a given
254 * variable to other variables and to add those references to the given graph.
255 * The [_callback] will be invoked for every dependency found.
256 */
257 ReferenceFinder(this._callback);
258
259 @override
260 Object visitInstanceCreationExpression(InstanceCreationExpression node) {
261 if (node.isConst) {
262 ConstructorElement constructor = getConstructorImpl(node.staticElement);
263 if (constructor != null) {
264 _callback(constructor);
265 }
266 }
267 return super.visitInstanceCreationExpression(node);
268 }
269
270 @override
271 Object visitLabel(Label node) {
272 // We are visiting the "label" part of a named expression in a function
273 // call (presumably a constructor call), e.g. "const C(label: ...)". We
274 // don't want to visit the SimpleIdentifier for the label because that's a
275 // reference to a function parameter that needs to be filled in; it's not a
276 // constant whose value we depend on.
277 return null;
278 }
279
280 @override
281 Object visitRedirectingConstructorInvocation(
282 RedirectingConstructorInvocation node) {
283 super.visitRedirectingConstructorInvocation(node);
284 ConstructorElement target = getConstructorImpl(node.staticElement);
285 if (target != null) {
286 _callback(target);
287 }
288 return null;
289 }
290
291 @override
292 Object visitSimpleIdentifier(SimpleIdentifier node) {
293 Element element = node.staticElement;
294 if (element is PropertyAccessorElement) {
295 element = (element as PropertyAccessorElement).variable;
296 }
297 if (element is VariableElement && element.isConst) {
298 _callback(element);
299 }
300 return null;
301 }
302
303 @override
304 Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
305 super.visitSuperConstructorInvocation(node);
306 ConstructorElement constructor = getConstructorImpl(node.staticElement);
307 if (constructor != null) {
308 _callback(constructor);
309 }
310 return null;
311 }
312 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/dart/constant/evaluation.dart ('k') | pkg/analyzer/lib/src/dart/constant/value.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698