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

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

Issue 285423002: New analyzer snapshot (with CaughtException). (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Replace AnalysisException with CaughtException Created 6 years, 7 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 | Annotate | Revision Log
« no previous file with comments | « pkg/analyzer/lib/src/generated/ast.dart ('k') | pkg/analyzer/lib/src/generated/element.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 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 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 // This code was auto-generated, is not intended to be edited, and is subject to 5 // This code was auto-generated, is not intended to be edited, and is subject to
6 // significant change. Please see the README file for more information. 6 // significant change. Please see the README file for more information.
7 7
8 library engine.constant; 8 library engine.constant;
9 9
10 import 'java_core.dart'; 10 import 'java_core.dart';
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 * 105 *
106 * @return `true` if this object represents a boolean value 106 * @return `true` if this object represents a boolean value
107 */ 107 */
108 @override 108 @override
109 bool get isBool => true; 109 bool get isBool => true;
110 110
111 @override 111 @override
112 bool get isBoolNumStringOrNull => true; 112 bool get isBoolNumStringOrNull => true;
113 113
114 @override 114 @override
115 bool get isUnknown => value == null;
116
117 @override
115 BoolState logicalAnd(InstanceState rightOperand) { 118 BoolState logicalAnd(InstanceState rightOperand) {
116 assertBool(rightOperand); 119 assertBool(rightOperand);
117 if (value == null) { 120 if (value == null) {
118 return UNKNOWN_VALUE; 121 return UNKNOWN_VALUE;
119 } 122 }
120 return value ? rightOperand.convertToBool() : FALSE_STATE; 123 return value ? rightOperand.convertToBool() : FALSE_STATE;
121 } 124 }
122 125
123 @override 126 @override
124 BoolState logicalNot() { 127 BoolState logicalNot() {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
197 200
198 /** 201 /**
199 * Initialize a newly created evaluator to evaluate expressions in the given s ource. 202 * Initialize a newly created evaluator to evaluate expressions in the given s ource.
200 * 203 *
201 * @param source the source containing the expression(s) that will be evaluate d 204 * @param source the source containing the expression(s) that will be evaluate d
202 * @param typeProvider the type provider used to access known types 205 * @param typeProvider the type provider used to access known types
203 */ 206 */
204 ConstantEvaluator(this._source, this._typeProvider); 207 ConstantEvaluator(this._source, this._typeProvider);
205 208
206 EvaluationResult evaluate(Expression expression) { 209 EvaluationResult evaluate(Expression expression) {
207 EvaluationResultImpl result = expression.accept(new ConstantVisitor(_typePro vider)); 210 EvaluationResultImpl result = expression.accept(new ConstantVisitor.con1(_ty peProvider));
208 if (result is ValidResult) { 211 if (result is ValidResult) {
209 return EvaluationResult.forValue(result.value); 212 return EvaluationResult.forValue(result.value);
210 } 213 }
211 List<AnalysisError> errors = new List<AnalysisError>(); 214 List<AnalysisError> errors = new List<AnalysisError>();
212 for (ErrorResult_ErrorData data in (result as ErrorResult).errorData) { 215 for (ErrorResult_ErrorData data in (result as ErrorResult).errorData) {
213 AstNode node = data.node; 216 AstNode node = data.node;
214 errors.add(new AnalysisError.con2(_source, node.offset, node.length, data. errorCode, [])); 217 errors.add(new AnalysisError.con2(_source, node.offset, node.length, data. errorCode, []));
215 } 218 }
216 return EvaluationResult.forErrors(new List.from(errors)); 219 return EvaluationResult.forErrors(new List.from(errors));
217 } 220 }
218 } 221 }
219 222
220 /** 223 /**
221 * Instances of the class `ConstantFinder` are used to traverse the AST structur es of all of 224 * Instances of the class `ConstantFinder` are used to traverse the AST structur es of all of
222 * the compilation units being resolved and build a table mapping constant varia ble elements to the 225 * the compilation units being resolved and build a table mapping constant varia ble elements to the
223 * declarations of those variables. 226 * declarations of those variables.
224 */ 227 */
225 class ConstantFinder extends RecursiveAstVisitor<Object> { 228 class ConstantFinder extends RecursiveAstVisitor<Object> {
226 /** 229 /**
227 * A table mapping constant variable elements to the declarations of those var iables. 230 * A table mapping constant variable elements to the declarations of those var iables.
228 */ 231 */
229 final Map<VariableElement, VariableDeclaration> variableMap = new Map<Variable Element, VariableDeclaration>(); 232 final Map<VariableElement, VariableDeclaration> variableMap = new Map<Variable Element, VariableDeclaration>();
230 233
234 /**
235 * A table mapping constant constructors to the declarations of those construc tors.
236 */
237 final Map<ConstructorElement, ConstructorDeclaration> constructorMap = new Map <ConstructorElement, ConstructorDeclaration>();
238
239 /**
240 * A collection of constant constructor invocations.
241 */
242 final List<InstanceCreationExpression> constructorInvocations = new List<Insta nceCreationExpression>();
243
244 @override
245 Object visitConstructorDeclaration(ConstructorDeclaration node) {
246 super.visitConstructorDeclaration(node);
247 if (node.constKeyword != null) {
248 ConstructorElement element = node.element;
249 if (element != null) {
250 constructorMap[element] = node;
251 }
252 }
253 return null;
254 }
255
256 @override
257 Object visitInstanceCreationExpression(InstanceCreationExpression node) {
258 super.visitInstanceCreationExpression(node);
259 if (node.isConst) {
260 constructorInvocations.add(node);
261 }
262 return null;
263 }
264
231 @override 265 @override
232 Object visitVariableDeclaration(VariableDeclaration node) { 266 Object visitVariableDeclaration(VariableDeclaration node) {
233 super.visitVariableDeclaration(node); 267 super.visitVariableDeclaration(node);
234 Expression initializer = node.initializer; 268 Expression initializer = node.initializer;
235 if (initializer != null && node.isConst) { 269 if (initializer != null && node.isConst) {
236 VariableElement element = node.element; 270 VariableElement element = node.element;
237 if (element != null) { 271 if (element != null) {
238 variableMap[element] = node; 272 variableMap[element] = node;
239 } 273 }
240 } 274 }
241 return null; 275 return null;
242 } 276 }
243 } 277 }
244 278
245 /** 279 /**
246 * Instances of the class `ConstantValueComputer` compute the values of constant variables in 280 * Instances of the class `ConstantValueComputer` compute the values of constant variables and
247 * one or more compilation units. The expected usage pattern is for the compilat ion units to be 281 * constant constructor invocations in one or more compilation units. The expect ed usage pattern is
248 * added to this computer using the method [add] and then for the method 282 * for the compilation units to be added to this computer using the method
249 * [computeValues] to be invoked exactly once. Any use of an instance after invo king the 283 * [add] and then for the method [computeValues] to be invoked
250 * method [computeValues] will result in unpredictable behavior. 284 * exactly once. Any use of an instance after invoking the method [computeValues ] will
285 * result in unpredictable behavior.
251 */ 286 */
252 class ConstantValueComputer { 287 class ConstantValueComputer {
253 /** 288 /**
254 * The type provider used to access the known types. 289 * The type provider used to access the known types.
255 */ 290 */
256 final TypeProvider _typeProvider; 291 TypeProvider typeProvider;
257 292
258 /** 293 /**
259 * The object used to find constant variables in the compilation units that we re added. 294 * The object used to find constant variables and constant constructor invocat ions in the
295 * compilation units that were added.
260 */ 296 */
261 ConstantFinder _constantFinder = new ConstantFinder(); 297 ConstantFinder _constantFinder = new ConstantFinder();
262 298
263 /** 299 /**
264 * A graph in which the nodes are the constant variables and the edges are fro m each variable to 300 * A graph in which the nodes are the constants, and the edges are from each c onstant to the other
265 * the other constant variables that are referenced in the head's initializer. 301 * constants that are referenced by it.
266 */ 302 */
267 DirectedGraph<VariableElement> _referenceGraph = new DirectedGraph<VariableEle ment>(); 303 DirectedGraph<AstNode> referenceGraph = new DirectedGraph<AstNode>();
268 304
269 /** 305 /**
270 * A table mapping constant variables to the declarations of those variables. 306 * A table mapping constant variables to the declarations of those variables.
271 */ 307 */
272 Map<VariableElement, VariableDeclaration> _declarationMap; 308 Map<VariableElement, VariableDeclaration> _variableDeclarationMap;
309
310 /**
311 * A table mapping constant constructors to the declarations of those construc tors.
312 */
313 Map<ConstructorElement, ConstructorDeclaration> constructorDeclarationMap;
314
315 /**
316 * A collection of constant constructor invocations.
317 */
318 List<InstanceCreationExpression> _constructorInvocations;
273 319
274 /** 320 /**
275 * Initialize a newly created constant value computer. 321 * Initialize a newly created constant value computer.
276 * 322 *
277 * @param typeProvider the type provider used to access known types 323 * @param typeProvider the type provider used to access known types
278 */ 324 */
279 ConstantValueComputer(this._typeProvider); 325 ConstantValueComputer(TypeProvider typeProvider) {
280 326 this.typeProvider = typeProvider;
281 /** 327 }
282 * Add the constant variables in the given compilation unit to the list of con stant variables 328
283 * whose value needs to be computed. 329 /**
330 * Add the constants in the given compilation unit to the list of constants wh ose value needs to
331 * be computed.
284 * 332 *
285 * @param unit the compilation unit defining the constant variables to be adde d 333 * @param unit the compilation unit defining the constants to be added
286 */ 334 */
287 void add(CompilationUnit unit) { 335 void add(CompilationUnit unit) {
288 unit.accept(_constantFinder); 336 unit.accept(_constantFinder);
289 } 337 }
290 338
291 /** 339 /**
292 * Compute values for all of the constant variables in the compilation units t hat were added. 340 * Compute values for all of the constants in the compilation units that were added.
293 */ 341 */
294 void computeValues() { 342 void computeValues() {
295 _declarationMap = _constantFinder.variableMap; 343 _variableDeclarationMap = _constantFinder.variableMap;
296 for (MapEntry<VariableElement, VariableDeclaration> entry in getMapEntrySet( _declarationMap)) { 344 constructorDeclarationMap = _constantFinder.constructorMap;
297 VariableElement element = entry.getKey(); 345 _constructorInvocations = _constantFinder.constructorInvocations;
298 ReferenceFinder referenceFinder = new ReferenceFinder(element, _referenceG raph); 346 for (MapEntry<VariableElement, VariableDeclaration> entry in getMapEntrySet( _variableDeclarationMap)) {
299 _referenceGraph.addNode(element); 347 VariableDeclaration declaration = entry.getValue();
300 entry.getValue().initializer.accept(referenceFinder); 348 ReferenceFinder referenceFinder = new ReferenceFinder(declaration, referen ceGraph, _variableDeclarationMap, constructorDeclarationMap);
301 } 349 referenceGraph.addNode(declaration);
302 while (!_referenceGraph.isEmpty) { 350 declaration.initializer.accept(referenceFinder);
303 VariableElement element = _referenceGraph.removeSink(); 351 }
304 while (element != null) { 352 for (MapEntry<ConstructorElement, ConstructorDeclaration> entry in getMapEnt rySet(constructorDeclarationMap)) {
305 _computeValueFor(element); 353 ConstructorDeclaration declaration = entry.getValue();
306 element = _referenceGraph.removeSink(); 354 ReferenceFinder referenceFinder = new ReferenceFinder(declaration, referen ceGraph, _variableDeclarationMap, constructorDeclarationMap);
307 } 355 referenceGraph.addNode(declaration);
308 if (!_referenceGraph.isEmpty) { 356 bool superInvocationFound = false;
309 List<VariableElement> variablesInCycle = _referenceGraph.findCycle(); 357 NodeList<ConstructorInitializer> initializers = declaration.initializers;
310 if (variablesInCycle == null) { 358 for (ConstructorInitializer initializer in initializers) {
311 // 359 if (initializer is SuperConstructorInvocation) {
312 // This should not happen. Either the graph should be empty, or there should be at least 360 superInvocationFound = true;
313 // one sink, or there should be a cycle. If this does happen we exit t o prevent an 361 }
314 // infinite loop. 362 initializer.accept(referenceFinder);
315 // 363 }
316 AnalysisEngine.instance.logger.logError("Exiting constant value comput er with ${_referenceGraph.nodeCount} variables that are neither sinks nor in a c ycle"); 364 if (!superInvocationFound) {
317 return; 365 // No explicit superconstructor invocation found, so we need to manually insert
318 } 366 // a reference to the implicit superconstructor.
319 for (VariableElement variable in variablesInCycle) { 367 InterfaceType superclass = (entry.getKey().returnType as InterfaceType). superclass;
320 _generateCycleError(variablesInCycle, variable); 368 if (superclass != null && !superclass.isObject) {
321 } 369 ConstructorElement unnamedConstructor = superclass.element.unnamedCons tructor;
322 _referenceGraph.removeAllNodes(variablesInCycle); 370 ConstructorDeclaration superConstructorDeclaration = findConstructorDe claration(unnamedConstructor);
323 } 371 if (superConstructorDeclaration != null) {
324 } 372 referenceGraph.addEdge(declaration, superConstructorDeclaration);
325 } 373 }
326 374 }
327 /** 375 }
328 * Compute a value for the given variable. 376 for (FormalParameter parameter in declaration.parameters.parameters) {
377 referenceGraph.addNode(parameter);
378 referenceGraph.addEdge(declaration, parameter);
379 if (parameter is DefaultFormalParameter) {
380 Expression defaultValue = parameter.defaultValue;
381 if (defaultValue != null) {
382 ReferenceFinder parameterReferenceFinder = new ReferenceFinder(param eter, referenceGraph, _variableDeclarationMap, constructorDeclarationMap);
383 defaultValue.accept(parameterReferenceFinder);
384 }
385 }
386 }
387 }
388 for (InstanceCreationExpression expression in _constructorInvocations) {
389 referenceGraph.addNode(expression);
390 ConstructorElement constructor = expression.staticElement;
391 if (constructor == null) {
392 break;
393 }
394 constructor = _followConstantRedirectionChain(constructor);
395 ConstructorDeclaration declaration = findConstructorDeclaration(constructo r);
396 // An instance creation expression depends both on the constructor and the arguments passed
397 // to it.
398 ReferenceFinder referenceFinder = new ReferenceFinder(expression, referenc eGraph, _variableDeclarationMap, constructorDeclarationMap);
399 if (declaration != null) {
400 referenceGraph.addEdge(expression, declaration);
401 }
402 expression.argumentList.accept(referenceFinder);
403 }
404 List<List<AstNode>> topologicalSort = referenceGraph.computeTopologicalSort( );
405 for (List<AstNode> constantsInCycle in topologicalSort) {
406 if (constantsInCycle.length == 1) {
407 _computeValueFor(constantsInCycle[0]);
408 } else {
409 for (AstNode constant in constantsInCycle) {
410 _generateCycleError(constantsInCycle, constant);
411 }
412 }
413 }
414 }
415
416 /**
417 * This method is called just before computing the constant value associated w ith an AST node.
418 * Unit tests will override this method to introduce additional error checking .
419 */
420 void beforeComputeValue(AstNode constNode) {
421 }
422
423 /**
424 * This method is called just before getting the constant initializers associa ted with a
425 * constructor AST node. Unit tests will override this method to introduce add itional error
426 * checking.
427 */
428 void beforeGetConstantInitializers(ConstructorElement constructor) {
429 }
430
431 /**
432 * This method is called just before getting a parameter's default value. Unit tests will override
433 * this method to introduce additional error checking.
434 */
435 void beforeGetParameterDefault(ParameterElement parameter) {
436 }
437
438 /**
439 * Create the ConstantVisitor used to evaluate constants. Unit tests will over ride this method to
440 * introduce additional error checking.
441 */
442 ConstantVisitor createConstantVisitor() => new ConstantVisitor.con1(typeProvid er);
443
444 ConstructorDeclaration findConstructorDeclaration(ConstructorElement construct or) => constructorDeclarationMap[_getConstructorBase(constructor)];
445
446 /**
447 * Compute a value for the given constant.
329 * 448 *
330 * @param variable the variable for which a value is to be computed 449 * @param constNode the constant for which a value is to be computed
331 */ 450 */
332 void _computeValueFor(VariableElement variable) { 451 void _computeValueFor(AstNode constNode) {
333 VariableDeclaration declaration = _declarationMap[variable]; 452 beforeComputeValue(constNode);
334 if (declaration == null) { 453 if (constNode is VariableDeclaration) {
335 // 454 VariableDeclaration declaration = constNode;
336 // The declaration will be null when the variable was added to the graph a s a result of being 455 Element element = declaration.element;
337 // referenced by another variable but is not defined in the compilation un its that were added 456 EvaluationResultImpl result = declaration.initializer.accept(createConstan tVisitor());
338 // to this computer. In such cases, the variable should already have a val ue associated with 457 (element as VariableElementImpl).evaluationResult = result;
339 // it, but we don't bother to check because there's nothing we can do abou t it at this point. 458 } else if (constNode is InstanceCreationExpression) {
340 // 459 InstanceCreationExpression expression = constNode;
460 ConstructorElement constructor = expression.staticElement;
461 if (constructor == null) {
462 // Couldn't resolve the constructor so we can't compute a value. No pro blem--the error
463 // has already been reported.
464 return;
465 }
466 ConstantVisitor constantVisitor = createConstantVisitor();
467 ValidResult result = _evaluateConstructorCall(expression.argumentList.argu ments, constructor, constantVisitor);
468 expression.evaluationResult = result;
469 } else if (constNode is ConstructorDeclaration) {
470 ConstructorDeclaration declaration = constNode;
471 NodeList<ConstructorInitializer> initializers = declaration.initializers;
472 ConstructorElementImpl constructor = declaration.element as ConstructorEle mentImpl;
473 constructor.constantInitializers = new ConstantValueComputer_InitializerCl oner().cloneNodeList(initializers);
474 } else if (constNode is FormalParameter) {
475 if (constNode is DefaultFormalParameter) {
476 DefaultFormalParameter parameter = constNode;
477 ParameterElement element = parameter.element;
478 Expression defaultValue = parameter.defaultValue;
479 if (defaultValue != null) {
480 EvaluationResultImpl result = defaultValue.accept(createConstantVisito r());
481 (element as ParameterElementImpl).evaluationResult = result;
482 }
483 }
484 } else {
485 // Should not happen.
486 AnalysisEngine.instance.logger.logError("Constant value computer trying to compute the value of a node which is not a VariableDeclaration, InstanceCreatio nExpression, FormalParameter, or ConstructorDeclaration");
341 return; 487 return;
342 } 488 }
343 EvaluationResultImpl result = declaration.initializer.accept(new ConstantVis itor(_typeProvider)); 489 }
344 (variable as VariableElementImpl).evaluationResult = result; 490
345 if (result is ErrorResult) { 491 ValidResult _evaluateConstructorCall(NodeList<Expression> arguments, Construct orElement constructor, ConstantVisitor constantVisitor) {
346 List<AnalysisError> errors = new List<AnalysisError>(); 492 int argumentCount = arguments.length;
347 for (ErrorResult_ErrorData data in result.errorData) { 493 List<DartObjectImpl> argumentValues = new List<DartObjectImpl>(argumentCount );
348 AstNode node = data.node; 494 Map<String, DartObjectImpl> namedArgumentValues = new Map<String, DartObject Impl>();
349 Source source = variable.getAncestor((element) => element is Compilation UnitElement).source; 495 for (int i = 0; i < argumentCount; i++) {
350 errors.add(new AnalysisError.con2(source, node.offset, node.length, data .errorCode, [])); 496 Expression argument = arguments[i];
351 } 497 if (argument is NamedExpression) {
352 } 498 NamedExpression namedExpression = argument;
353 } 499 String name = namedExpression.name.label.name;
354 500 namedArgumentValues[name] = constantVisitor._valueOf(namedExpression.exp ression);
355 /** 501 argumentValues[i] = constantVisitor.null2;
356 * Generate an error indicating that the given variable is not a valid compile -time constant 502 } else {
357 * because it references at least one of the variables in the given cycle, eac h of which directly 503 argumentValues[i] = constantVisitor._valueOf(argument);
358 * or indirectly references the variable. 504 }
505 }
506 constructor = _followConstantRedirectionChain(constructor);
507 InterfaceType definingClass = constructor.returnType as InterfaceType;
508 if (constructor.isFactory) {
509 // We couldn't find a non-factory constructor. See if it's because we rea ched an external
510 // const factory constructor that we can emulate.
511 // TODO(paulberry): if the constructor is one of {bool,int,String}.fromEnv ironment(),
512 // we may be able to infer the value based on -D flags provided to the ana lyzer (see
513 // dartbug.com/17234).
514 if (identical(definingClass, typeProvider.symbolType) && argumentCount == 1) {
515 String argumentValue = argumentValues[0].stringValue;
516 if (argumentValue != null) {
517 return constantVisitor._valid(definingClass, new SymbolState(argumentV alue));
518 }
519 }
520 // Either it's an external const factory constructor that we can't emulate , or an error
521 // occurred (a cycle, or a const constructor trying to delegate to a non-c onst constructor).
522 // In the former case, the best we can do is consider it an unknown value. In the latter
523 // case, the error has already been reported, so considering it an unknown value will
524 // suppress further errors.
525 return constantVisitor._validWithUnknownValue(definingClass);
526 }
527 beforeGetConstantInitializers(constructor);
528 ConstructorElementImpl constructorBase = _getConstructorBase(constructor) as ConstructorElementImpl;
529 List<ConstructorInitializer> initializers = constructorBase.constantInitiali zers;
530 if (initializers == null) {
531 // This can happen in some cases where there are compile errors in the cod e being analyzed
532 // (for example if the code is trying to create a const instance using a n on-const
533 // constructor, or the node we're visiting is involved in a cycle). The e rror has already
534 // been reported, so consider it an unknown value to suppress further erro rs.
535 return constantVisitor._validWithUnknownValue(definingClass);
536 }
537 Map<String, DartObjectImpl> fieldMap = new Map<String, DartObjectImpl>();
538 Map<String, DartObjectImpl> parameterMap = new Map<String, DartObjectImpl>() ;
539 List<ParameterElement> parameters = constructorBase.parameters;
540 int parameterCount = parameters.length;
541 for (int i = 0; i < parameterCount; i++) {
542 ParameterElement parameter = parameters[i];
543 while (parameter is ParameterMember) {
544 parameter = (parameter as ParameterMember).baseElement;
545 }
546 DartObjectImpl argumentValue = null;
547 if (parameter.parameterKind == ParameterKind.NAMED) {
548 argumentValue = namedArgumentValues[parameter.name];
549 } else if (i < argumentCount) {
550 argumentValue = argumentValues[i];
551 }
552 if (argumentValue == null && parameter is ParameterElementImpl) {
553 // The parameter is an optional positional parameter for which no value was provided, so
554 // use the default value.
555 beforeGetParameterDefault(parameter);
556 EvaluationResultImpl evaluationResult = (parameter as ParameterElementIm pl).evaluationResult;
557 if (evaluationResult is ValidResult) {
558 argumentValue = evaluationResult.value;
559 } else if (evaluationResult == null) {
560 // No default was provided, so the default value is null.
561 argumentValue = constantVisitor.null2;
562 }
563 }
564 if (argumentValue != null) {
565 if (parameter.isInitializingFormal) {
566 FieldElement field = (parameter as FieldFormalParameterElement).field;
567 if (field != null) {
568 String fieldName = field.name;
569 fieldMap[fieldName] = argumentValue;
570 }
571 } else {
572 String name = parameter.name;
573 parameterMap[name] = argumentValue;
574 }
575 }
576 }
577 ConstantVisitor initializerVisitor = new ConstantVisitor.con2(typeProvider, parameterMap);
578 String superName = null;
579 NodeList<Expression> superArguments = null;
580 for (ConstructorInitializer initializer in initializers) {
581 if (initializer is ConstructorFieldInitializer) {
582 ConstructorFieldInitializer constructorFieldInitializer = initializer;
583 Expression initializerExpression = constructorFieldInitializer.expressio n;
584 EvaluationResultImpl evaluationResult = initializerExpression.accept(ini tializerVisitor);
585 if (evaluationResult is ValidResult) {
586 DartObjectImpl value = evaluationResult.value;
587 String fieldName = constructorFieldInitializer.fieldName.name;
588 fieldMap[fieldName] = value;
589 }
590 } else if (initializer is SuperConstructorInvocation) {
591 SuperConstructorInvocation superConstructorInvocation = initializer;
592 SimpleIdentifier name = superConstructorInvocation.constructorName;
593 if (name != null) {
594 superName = name.name;
595 }
596 superArguments = superConstructorInvocation.argumentList.arguments;
597 }
598 }
599 // Evaluate explicit or implicit call to super().
600 InterfaceType superclass = definingClass.superclass;
601 if (superclass != null && !superclass.isObject) {
602 ConstructorElement superConstructor = superclass.lookUpConstructor(superNa me, constructor.library);
603 if (superConstructor != null) {
604 if (superArguments == null) {
605 superArguments = new NodeList<Expression>(null);
606 }
607 _evaluateSuperConstructorCall(fieldMap, superConstructor, superArguments , initializerVisitor);
608 }
609 }
610 return constantVisitor._valid(definingClass, new GenericState(fieldMap));
611 }
612
613 void _evaluateSuperConstructorCall(Map<String, DartObjectImpl> fieldMap, Const ructorElement superConstructor, NodeList<Expression> superArguments, ConstantVis itor initializerVisitor) {
614 if (superConstructor != null && superConstructor.isConst) {
615 ValidResult evaluationResult = _evaluateConstructorCall(superArguments, su perConstructor, initializerVisitor);
616 fieldMap[GenericState.SUPERCLASS_FIELD] = evaluationResult.value;
617 }
618 }
619
620 /**
621 * Attempt to follow the chain of factory redirections until a constructor is reached which is not
622 * a const factory constructor.
359 * 623 *
360 * @param variablesInCycle the variables in the cycle that includes the given variable 624 * @return the constant constructor which terminates the chain of factory redi rections, if the
361 * @param variable the variable that is not a valid compile-time constant 625 * chain terminates. If there is a problem (e.g. a redirection can't b e found, or a cycle
362 */ 626 * is encountered), the chain will be followed as far as possible and then a const factory
363 void _generateCycleError(List<VariableElement> variablesInCycle, VariableEleme nt variable) { 627 * constructor will be returned.
628 */
629 ConstructorElement _followConstantRedirectionChain(ConstructorElement construc tor) {
630 Set<ConstructorElement> constructorsVisited = new Set<ConstructorElement>();
631 while (constructor.isFactory) {
632 if (identical(constructor.enclosingElement.type, typeProvider.symbolType)) {
633 // The dart:core.Symbol has a const factory constructor that redirects t o
634 // dart:_internal.Symbol. That in turn redirects to an external const c onstructor, which
635 // we won't be able to evaluate. So stop following the chain of redirec tions at
636 // dart:core.Symbol, and let [evaluateInstanceCreationExpression] handle it specially.
637 break;
638 }
639 constructorsVisited.add(constructor);
640 ConstructorElement redirectedConstructor = constructor.redirectedConstruct or;
641 if (redirectedConstructor == null) {
642 // This can happen if constructor is an external factory constructor.
643 break;
644 }
645 if (!redirectedConstructor.isConst) {
646 // Delegating to a non-const constructor--this is not allowed (and
647 // is checked elsewhere--see [ErrorVerifier.checkForRedirectToNonConstCo nstructor()]).
648 break;
649 }
650 if (constructorsVisited.contains(redirectedConstructor)) {
651 // Cycle in redirecting factory constructors--this is not allowed
652 // and is checked elsewhere--see [ErrorVerifier.checkForRecursiveFactory Redirect()]).
653 break;
654 }
655 constructor = redirectedConstructor;
656 }
657 return constructor;
658 }
659
660 /**
661 * Generate an error indicating that the given constant is not a valid compile -time constant
662 * because it references at least one of the constants in the given cycle, eac h of which directly
663 * or indirectly references the constant.
664 *
665 * @param constantsInCycle the constants in the cycle that includes the given constant
666 * @param constant the constant that is not a valid compile-time constant
667 */
668 void _generateCycleError(List<AstNode> constantsInCycle, AstNode constant) {
669 }
670
671 ConstructorElement _getConstructorBase(ConstructorElement constructor) {
672 while (constructor is ConstructorMember) {
673 constructor = (constructor as ConstructorMember).baseElement;
674 }
675 return constructor;
364 } 676 }
365 } 677 }
366 678
679 /**
680 * [AstCloner] that copies the necessary information from the AST to allow const constructor
681 * initializers to be evaluated.
682 */
683 class ConstantValueComputer_InitializerCloner extends AstCloner {
684 @override
685 InstanceCreationExpression visitInstanceCreationExpression(InstanceCreationExp ression node) {
686 // All we need is the evaluation result, and the keyword so that we know whe ther it's const.
687 InstanceCreationExpression expression = new InstanceCreationExpression(node. keyword, null, null);
688 expression.evaluationResult = node.evaluationResult;
689 return expression;
690 }
691
692 @override
693 SimpleIdentifier visitSimpleIdentifier(SimpleIdentifier node) {
694 SimpleIdentifier identifier = super.visitSimpleIdentifier(node);
695 identifier.staticElement = node.staticElement;
696 return identifier;
697 }
698
699 @override
700 SuperConstructorInvocation visitSuperConstructorInvocation(SuperConstructorInv ocation node) {
701 SuperConstructorInvocation invocation = super.visitSuperConstructorInvocatio n(node);
702 invocation.staticElement = node.staticElement;
703 return invocation;
704 }
705 }
706
367 /** 707 /**
368 * Instances of the class `ConstantVisitor` evaluate constant expressions to pro duce their 708 * Instances of the class `ConstantVisitor` evaluate constant expressions to pro duce their
369 * compile-time value. According to the Dart Language Specification: <blockquote > A constant 709 * compile-time value. According to the Dart Language Specification: <blockquote > A constant
370 * expression is one of the following: 710 * expression is one of the following:
371 * * A literal number. 711 * * A literal number.
372 * * A literal boolean. 712 * * A literal boolean.
373 * * A literal string where any interpolated expression is a compile-time consta nt that evaluates 713 * * A literal string where any interpolated expression is a compile-time consta nt that evaluates
374 * to a numeric, string or boolean value or to <b>null</b>. 714 * to a numeric, string or boolean value or to <b>null</b>.
375 * * A literal symbol. 715 * * A literal symbol.
376 * * <b>null</b>. 716 * * <b>null</b>.
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
411 /** 751 /**
412 * The type provider used to access the known types. 752 * The type provider used to access the known types.
413 */ 753 */
414 final TypeProvider _typeProvider; 754 final TypeProvider _typeProvider;
415 755
416 /** 756 /**
417 * An shared object representing the value 'null'. 757 * An shared object representing the value 'null'.
418 */ 758 */
419 DartObjectImpl _nullObject; 759 DartObjectImpl _nullObject;
420 760
761 Map<String, DartObjectImpl> _lexicalEnvironment;
762
421 /** 763 /**
422 * Initialize a newly created constant visitor. 764 * Initialize a newly created constant visitor.
423 * 765 *
424 * @param typeProvider the type provider used to access known types 766 * @param typeProvider the type provider used to access known types
767 * @param lexicalEnvironment values which should override simpleIdentifiers, o r null if no
768 * overriding is necessary.
425 */ 769 */
426 ConstantVisitor(this._typeProvider); 770 ConstantVisitor.con1(this._typeProvider) {
771 this._lexicalEnvironment = null;
772 }
773
774 /**
775 * Initialize a newly created constant visitor.
776 *
777 * @param typeProvider the type provider used to access known types
778 * @param lexicalEnvironment values which should override simpleIdentifiers, o r null if no
779 * overriding is necessary.
780 */
781 ConstantVisitor.con2(this._typeProvider, Map<String, DartObjectImpl> lexicalEn vironment) {
782 this._lexicalEnvironment = lexicalEnvironment;
783 }
427 784
428 @override 785 @override
429 EvaluationResultImpl visitAdjacentStrings(AdjacentStrings node) { 786 EvaluationResultImpl visitAdjacentStrings(AdjacentStrings node) {
430 EvaluationResultImpl result = null; 787 EvaluationResultImpl result = null;
431 for (StringLiteral string in node.strings) { 788 for (StringLiteral string in node.strings) {
432 if (result == null) { 789 if (result == null) {
433 result = string.accept(this); 790 result = string.accept(this);
434 } else { 791 } else {
435 result = result.concatenate(_typeProvider, node, string.accept(this)); 792 result = result.concatenate(_typeProvider, node, string.accept(this));
436 } 793 }
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
532 889
533 @override 890 @override
534 EvaluationResultImpl visitDoubleLiteral(DoubleLiteral node) => _valid(_typePro vider.doubleType, new DoubleState(node.value)); 891 EvaluationResultImpl visitDoubleLiteral(DoubleLiteral node) => _valid(_typePro vider.doubleType, new DoubleState(node.value));
535 892
536 @override 893 @override
537 EvaluationResultImpl visitInstanceCreationExpression(InstanceCreationExpressio n node) { 894 EvaluationResultImpl visitInstanceCreationExpression(InstanceCreationExpressio n node) {
538 if (!node.isConst) { 895 if (!node.isConst) {
539 // TODO(brianwilkerson) Figure out which error to report. 896 // TODO(brianwilkerson) Figure out which error to report.
540 return _error(node, null); 897 return _error(node, null);
541 } 898 }
542 ConstructorElement constructor = node.staticElement; 899 beforeGetEvaluationResult(node);
543 if (constructor != null && constructor.isConst) { 900 EvaluationResultImpl result = node.evaluationResult;
544 NodeList<Expression> arguments = node.argumentList.arguments; 901 if (result != null) {
545 int argumentCount = arguments.length; 902 return result;
546 List<DartObjectImpl> argumentValues = new List<DartObjectImpl>(argumentCou nt);
547 Map<String, DartObjectImpl> namedArgumentValues = new Map<String, DartObje ctImpl>();
548 for (int i = 0; i < argumentCount; i++) {
549 Expression argument = arguments[i];
550 if (argument is NamedExpression) {
551 NamedExpression namedExpression = argument;
552 String name = namedExpression.name.label.name;
553 namedArgumentValues[name] = _valueOf(namedExpression.expression);
554 argumentValues[i] = null2;
555 } else {
556 argumentValues[i] = _valueOf(argument);
557 }
558 }
559 Set<ConstructorElement> constructorsVisited = new Set<ConstructorElement>( );
560 InterfaceType definingClass = constructor.returnType as InterfaceType;
561 while (constructor.isFactory) {
562 if (definingClass.element.library.isDartCore) {
563 String className = definingClass.name;
564 if (className == "Symbol" && argumentCount == 1) {
565 String argumentValue = argumentValues[0].stringValue;
566 if (argumentValue != null) {
567 return _valid(definingClass, new SymbolState(argumentValue));
568 }
569 }
570 }
571 constructorsVisited.add(constructor);
572 ConstructorElement redirectedConstructor = constructor.redirectedConstru ctor;
573 if (redirectedConstructor == null) {
574 // This can happen if constructor is an external factory constructor. Since there is no
575 // constructor to delegate to, we currently can't evaluate the constan t.
576 // TODO(paulberry): if the constructor is one of {bool,int,String}.fro mEnvironment(),
577 // we may be able to infer the value based on -D flags provided to the analyzer (see
578 // dartbug.com/17234).
579 return _error(node, null);
580 }
581 if (!redirectedConstructor.isConst) {
582 // Delegating to a non-const constructor--this is not allowed (and
583 // is checked elsewhere--see [ErrorVerifier.checkForRedirectToNonConst Constructor()]).
584 // So if we encounter it just error out.
585 return _error(node, null);
586 }
587 if (constructorsVisited.contains(redirectedConstructor)) {
588 // Cycle in redirecting factory constructors--this is not allowed
589 // and is checked elsewhere--see [ErrorVerifier.checkForRecursiveFacto ryRedirect()]).
590 // So if we encounter it just error out.
591 return _error(node, null);
592 }
593 constructor = redirectedConstructor;
594 definingClass = constructor.returnType as InterfaceType;
595 }
596 Map<String, DartObjectImpl> fieldMap = new Map<String, DartObjectImpl>();
597 List<ParameterElement> parameters = constructor.parameters;
598 int parameterCount = parameters.length;
599 for (int i = 0; i < parameterCount; i++) {
600 ParameterElement parameter = parameters[i];
601 if (parameter.isInitializingFormal) {
602 FieldElement field = (parameter as FieldFormalParameterElement).field;
603 if (field != null) {
604 String fieldName = field.name;
605 if (parameter.parameterKind == ParameterKind.NAMED) {
606 DartObjectImpl argumentValue = namedArgumentValues[parameter.name] ;
607 if (argumentValue != null) {
608 fieldMap[fieldName] = argumentValue;
609 }
610 } else if (i < argumentCount) {
611 fieldMap[fieldName] = argumentValues[i];
612 }
613 }
614 }
615 }
616 // TODO(brianwilkerson) This doesn't handle fields initialized in an initi alizer. We should be
617 // able to handle fields initialized by the superclass' constructor fairly easily, but other
618 // initializers will be harder.
619 return _valid(definingClass, new GenericState(fieldMap));
620 } 903 }
621 // TODO(brianwilkerson) Figure out which error to report. 904 // TODO(brianwilkerson) Figure out which error to report.
622 return _error(node, null); 905 return _error(node, null);
623 } 906 }
624 907
625 @override 908 @override
626 EvaluationResultImpl visitIntegerLiteral(IntegerLiteral node) => _valid(_typeP rovider.intType, new IntState(node.value)); 909 EvaluationResultImpl visitIntegerLiteral(IntegerLiteral node) => _valid(_typeP rovider.intType, new IntState(node.value));
627 910
628 @override 911 @override
629 EvaluationResultImpl visitInterpolationExpression(InterpolationExpression node ) { 912 EvaluationResultImpl visitInterpolationExpression(InterpolationExpression node ) {
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
748 return _error(node, null); 1031 return _error(node, null);
749 } 1032 }
750 break; 1033 break;
751 } 1034 }
752 } 1035 }
753 1036
754 @override 1037 @override
755 EvaluationResultImpl visitPropertyAccess(PropertyAccess node) => _getConstantV alue(node, node.propertyName.staticElement); 1038 EvaluationResultImpl visitPropertyAccess(PropertyAccess node) => _getConstantV alue(node, node.propertyName.staticElement);
756 1039
757 @override 1040 @override
758 EvaluationResultImpl visitSimpleIdentifier(SimpleIdentifier node) => _getConst antValue(node, node.staticElement); 1041 EvaluationResultImpl visitSimpleIdentifier(SimpleIdentifier node) {
1042 if (_lexicalEnvironment != null && _lexicalEnvironment.containsKey(node.name )) {
1043 return new ValidResult(_lexicalEnvironment[node.name]);
1044 }
1045 return _getConstantValue(node, node.staticElement);
1046 }
759 1047
760 @override 1048 @override
761 EvaluationResultImpl visitSimpleStringLiteral(SimpleStringLiteral node) => _va lid(_typeProvider.stringType, new StringState(node.value)); 1049 EvaluationResultImpl visitSimpleStringLiteral(SimpleStringLiteral node) => _va lid(_typeProvider.stringType, new StringState(node.value));
762 1050
763 @override 1051 @override
764 EvaluationResultImpl visitStringInterpolation(StringInterpolation node) { 1052 EvaluationResultImpl visitStringInterpolation(StringInterpolation node) {
765 EvaluationResultImpl result = null; 1053 EvaluationResultImpl result = null;
766 for (InterpolationElement element in node.elements) { 1054 for (InterpolationElement element in node.elements) {
767 if (result == null) { 1055 if (result == null) {
768 result = element.accept(this); 1056 result = element.accept(this);
(...skipping 11 matching lines...) Expand all
780 for (int i = 0; i < components.length; i++) { 1068 for (int i = 0; i < components.length; i++) {
781 if (i > 0) { 1069 if (i > 0) {
782 builder.appendChar(0x2E); 1070 builder.appendChar(0x2E);
783 } 1071 }
784 builder.append(components[i].lexeme); 1072 builder.append(components[i].lexeme);
785 } 1073 }
786 return _valid(_typeProvider.symbolType, new SymbolState(builder.toString())) ; 1074 return _valid(_typeProvider.symbolType, new SymbolState(builder.toString())) ;
787 } 1075 }
788 1076
789 /** 1077 /**
1078 * This method is called just before retrieving an evaluation result from an A ST node. Unit tests
1079 * will override it to introduce additional error checking.
1080 */
1081 void beforeGetEvaluationResult(AstNode node) {
1082 }
1083
1084 /**
1085 * Return an object representing the value 'null'.
1086 *
1087 * @return an object representing the value 'null'
1088 */
1089 DartObjectImpl get null2 {
1090 if (_nullObject == null) {
1091 _nullObject = new DartObjectImpl(_typeProvider.nullType, NullState.NULL_ST ATE);
1092 }
1093 return _nullObject;
1094 }
1095
1096 ValidResult _valid(InterfaceType type, InstanceState state) => new ValidResult (new DartObjectImpl(type, state));
1097
1098 ValidResult _validWithUnknownValue(InterfaceType type) {
1099 if (type.element.library.isDartCore) {
1100 String typeName = type.name;
1101 if (typeName == "bool") {
1102 return _valid(type, BoolState.UNKNOWN_VALUE);
1103 } else if (typeName == "double") {
1104 return _valid(type, DoubleState.UNKNOWN_VALUE);
1105 } else if (typeName == "int") {
1106 return _valid(type, IntState.UNKNOWN_VALUE);
1107 } else if (typeName == "String") {
1108 return _valid(type, StringState.UNKNOWN_VALUE);
1109 }
1110 }
1111 return _valid(type, GenericState.UNKNOWN_VALUE);
1112 }
1113
1114 /**
1115 * Return the value of the given expression, or a representation of 'null' if the expression
1116 * cannot be evaluated.
1117 *
1118 * @param expression the expression whose value is to be returned
1119 * @return the value of the given expression
1120 */
1121 DartObjectImpl _valueOf(Expression expression) {
1122 EvaluationResultImpl expressionValue = expression.accept(this);
1123 if (expressionValue is ValidResult) {
1124 return expressionValue.value;
1125 }
1126 return null2;
1127 }
1128
1129 /**
790 * Return a result object representing an error associated with the given node . 1130 * Return a result object representing an error associated with the given node .
791 * 1131 *
792 * @param node the AST node associated with the error 1132 * @param node the AST node associated with the error
793 * @param code the error code indicating the nature of the error 1133 * @param code the error code indicating the nature of the error
794 * @return a result object representing an error associated with the given nod e 1134 * @return a result object representing an error associated with the given nod e
795 */ 1135 */
796 ErrorResult _error(AstNode node, ErrorCode code) => new ErrorResult.con1(node, code == null ? CompileTimeErrorCode.INVALID_CONSTANT : code); 1136 ErrorResult _error(AstNode node, ErrorCode code) => new ErrorResult.con1(node, code == null ? CompileTimeErrorCode.INVALID_CONSTANT : code);
797 1137
798 /** 1138 /**
799 * Return the constant value of the static constant represented by the given e lement. 1139 * Return the constant value of the static constant represented by the given e lement.
800 * 1140 *
801 * @param node the node to be used if an error needs to be reported 1141 * @param node the node to be used if an error needs to be reported
802 * @param element the element whose value is to be returned 1142 * @param element the element whose value is to be returned
803 * @return the constant value of the static constant 1143 * @return the constant value of the static constant
804 */ 1144 */
805 EvaluationResultImpl _getConstantValue(AstNode node, Element element) { 1145 EvaluationResultImpl _getConstantValue(AstNode node, Element element) {
806 if (element is PropertyAccessorElement) { 1146 if (element is PropertyAccessorElement) {
807 element = (element as PropertyAccessorElement).variable; 1147 element = (element as PropertyAccessorElement).variable;
808 } 1148 }
809 if (element is VariableElementImpl) { 1149 if (element is VariableElementImpl) {
810 VariableElementImpl variableElementImpl = element; 1150 VariableElementImpl variableElementImpl = element;
1151 beforeGetEvaluationResult(node);
811 EvaluationResultImpl value = variableElementImpl.evaluationResult; 1152 EvaluationResultImpl value = variableElementImpl.evaluationResult;
812 if (variableElementImpl.isConst && value != null) { 1153 if (variableElementImpl.isConst && value != null) {
813 return value; 1154 return value;
814 } 1155 }
815 } else if (element is ExecutableElement) { 1156 } else if (element is ExecutableElement) {
816 ExecutableElement function = element; 1157 ExecutableElement function = element;
817 if (function.isStatic) { 1158 if (function.isStatic) {
818 return _valid(_typeProvider.functionType, new FunctionState(function)); 1159 return _valid(_typeProvider.functionType, new FunctionState(function));
819 } 1160 }
820 } else if (element is ClassElement || element is FunctionTypeAliasElement) { 1161 } else if (element is ClassElement || element is FunctionTypeAliasElement) {
821 return _valid(_typeProvider.typeType, new TypeState(element)); 1162 return _valid(_typeProvider.typeType, new TypeState(element));
822 } 1163 }
823 // TODO(brianwilkerson) Figure out which error to report. 1164 // TODO(brianwilkerson) Figure out which error to report.
824 return _error(node, null); 1165 return _error(node, null);
825 } 1166 }
826 1167
827 /** 1168 /**
828 * Return an object representing the value 'null'.
829 *
830 * @return an object representing the value 'null'
831 */
832 DartObjectImpl get null2 {
833 if (_nullObject == null) {
834 _nullObject = new DartObjectImpl(_typeProvider.nullType, NullState.NULL_ST ATE);
835 }
836 return _nullObject;
837 }
838
839 /**
840 * Return the union of the errors encoded in the given results. 1169 * Return the union of the errors encoded in the given results.
841 * 1170 *
842 * @param leftResult the first set of errors, or `null` if there was no previo us collection 1171 * @param leftResult the first set of errors, or `null` if there was no previo us collection
843 * of errors 1172 * of errors
844 * @param rightResult the errors to be added to the collection, or a valid res ult if there are no 1173 * @param rightResult the errors to be added to the collection, or a valid res ult if there are no
845 * errors to be added 1174 * errors to be added
846 * @return the union of the errors encoded in the given results 1175 * @return the union of the errors encoded in the given results
847 */ 1176 */
848 ErrorResult _union(ErrorResult leftResult, EvaluationResultImpl rightResult) { 1177 ErrorResult _union(ErrorResult leftResult, EvaluationResultImpl rightResult) {
849 if (rightResult is ErrorResult) { 1178 if (rightResult is ErrorResult) {
850 if (leftResult != null) { 1179 if (leftResult != null) {
851 return new ErrorResult.con2(leftResult, rightResult); 1180 return new ErrorResult.con2(leftResult, rightResult);
852 } else { 1181 } else {
853 return rightResult; 1182 return rightResult;
854 } 1183 }
855 } 1184 }
856 return leftResult; 1185 return leftResult;
857 } 1186 }
858
859 ValidResult _valid(InterfaceType type, InstanceState state) => new ValidResult (new DartObjectImpl(type, state));
860
861 ValidResult _validWithUnknownValue(InterfaceType type) {
862 if (type.element.library.isDartCore) {
863 String typeName = type.name;
864 if (typeName == "bool") {
865 return _valid(type, BoolState.UNKNOWN_VALUE);
866 } else if (typeName == "double") {
867 return _valid(type, DoubleState.UNKNOWN_VALUE);
868 } else if (typeName == "int") {
869 return _valid(type, IntState.UNKNOWN_VALUE);
870 } else if (typeName == "String") {
871 return _valid(type, StringState.UNKNOWN_VALUE);
872 }
873 }
874 return _valid(type, GenericState.UNKNOWN_VALUE);
875 }
876
877 /**
878 * Return the value of the given expression, or a representation of 'null' if the expression
879 * cannot be evaluated.
880 *
881 * @param expression the expression whose value is to be returned
882 * @return the value of the given expression
883 */
884 DartObjectImpl _valueOf(Expression expression) {
885 EvaluationResultImpl expressionValue = expression.accept(this);
886 if (expressionValue is ValidResult) {
887 return expressionValue.value;
888 }
889 return null2;
890 }
891 } 1187 }
892 1188
893 /** 1189 /**
894 * The interface `DartObject` defines the behavior of objects that represent the state of a 1190 * The interface `DartObject` defines the behavior of objects that represent the state of a
895 * Dart object. 1191 * Dart object.
896 */ 1192 */
897 abstract class DartObject { 1193 abstract class DartObject {
898 /** 1194 /**
899 * Return the boolean value of this object, or `null` if either the value of t his object is 1195 * Return the boolean value of this object, or `null` if either the value of t his object is
900 * not known or this object is not of type 'bool'. 1196 * not known or this object is not of type 'bool'.
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
1136 } 1432 }
1137 1433
1138 @override 1434 @override
1139 double get doubleValue { 1435 double get doubleValue {
1140 if (_state is DoubleState) { 1436 if (_state is DoubleState) {
1141 return (_state as DoubleState).value; 1437 return (_state as DoubleState).value;
1142 } 1438 }
1143 return null; 1439 return null;
1144 } 1440 }
1145 1441
1442 Map<String, DartObjectImpl> get fields => _state.fields;
1443
1146 @override 1444 @override
1147 int get intValue { 1445 int get intValue {
1148 if (_state is IntState) { 1446 if (_state is IntState) {
1149 return (_state as IntState).value; 1447 return (_state as IntState).value;
1150 } 1448 }
1151 return null; 1449 return null;
1152 } 1450 }
1153 1451
1154 @override 1452 @override
1155 String get stringValue { 1453 String get stringValue {
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1216 @override 1514 @override
1217 bool get isFalse => _state is BoolState && identical((_state as BoolState).val ue, false); 1515 bool get isFalse => _state is BoolState && identical((_state as BoolState).val ue, false);
1218 1516
1219 @override 1517 @override
1220 bool get isNull => _state is NullState; 1518 bool get isNull => _state is NullState;
1221 1519
1222 @override 1520 @override
1223 bool get isTrue => _state is BoolState && identical((_state as BoolState).valu e, true); 1521 bool get isTrue => _state is BoolState && identical((_state as BoolState).valu e, true);
1224 1522
1225 /** 1523 /**
1524 * Return true if this object represents an unknown value.
1525 */
1526 bool get isUnknown => _state.isUnknown;
1527
1528 /**
1226 * Return `true` if this object represents an instance of a user-defined class . 1529 * Return `true` if this object represents an instance of a user-defined class .
1227 * 1530 *
1228 * @return `true` if this object represents an instance of a user-defined clas s 1531 * @return `true` if this object represents an instance of a user-defined clas s
1229 */ 1532 */
1230 bool get isUserDefinedObject => _state is GenericState; 1533 bool get isUserDefinedObject => _state is GenericState;
1231 1534
1232 /** 1535 /**
1233 * Return the result of invoking the '&lt;' operator on this object with the g iven argument. 1536 * Return the result of invoking the '&lt;' operator on this object with the g iven argument.
1234 * 1537 *
1235 * @param typeProvider the type provider used to find known types 1538 * @param typeProvider the type provider used to find known types
(...skipping 1206 matching lines...) Expand 10 before | Expand all | Expand 10 after
2442 * Instances of the class `GenericState` represent the state of an object repres enting a Dart 2745 * Instances of the class `GenericState` represent the state of an object repres enting a Dart
2443 * object for which there is no more specific state. 2746 * object for which there is no more specific state.
2444 */ 2747 */
2445 class GenericState extends InstanceState { 2748 class GenericState extends InstanceState {
2446 /** 2749 /**
2447 * The values of the fields of this instance. 2750 * The values of the fields of this instance.
2448 */ 2751 */
2449 final Map<String, DartObjectImpl> _fieldMap; 2752 final Map<String, DartObjectImpl> _fieldMap;
2450 2753
2451 /** 2754 /**
2755 * Pseudo-field that we use to represent fields in the superclass.
2756 */
2757 static String SUPERCLASS_FIELD = "(super)";
2758
2759 /**
2452 * A state that can be used to represent an object whose state is not known. 2760 * A state that can be used to represent an object whose state is not known.
2453 */ 2761 */
2454 static GenericState UNKNOWN_VALUE = new GenericState(new Map<String, DartObjec tImpl>()); 2762 static GenericState UNKNOWN_VALUE = new GenericState(new Map<String, DartObjec tImpl>());
2455 2763
2456 /** 2764 /**
2457 * Initialize a newly created state to represent a newly created object. 2765 * Initialize a newly created state to represent a newly created object.
2458 * 2766 *
2459 * @param fieldMap the values of the fields of this instance 2767 * @param fieldMap the values of the fields of this instance
2460 */ 2768 */
2461 GenericState(this._fieldMap); 2769 GenericState(this._fieldMap);
2462 2770
2463 @override 2771 @override
2464 StringState convertToString() => StringState.UNKNOWN_VALUE; 2772 StringState convertToString() => StringState.UNKNOWN_VALUE;
2465 2773
2466 @override 2774 @override
2775 BoolState equalEqual(InstanceState rightOperand) {
2776 assertBoolNumStringOrNull(rightOperand);
2777 if (rightOperand is DynamicState) {
2778 return BoolState.UNKNOWN_VALUE;
2779 }
2780 return BoolState.from(this == rightOperand);
2781 }
2782
2783 @override
2467 bool operator ==(Object object) { 2784 bool operator ==(Object object) {
2468 if (object is! GenericState) { 2785 if (object is! GenericState) {
2469 return false; 2786 return false;
2470 } 2787 }
2471 GenericState state = object as GenericState; 2788 GenericState state = object as GenericState;
2472 Set<String> otherFields = new Set<String>.from(state._fieldMap.keys.toSet()) ; 2789 Set<String> otherFields = new Set<String>.from(state._fieldMap.keys.toSet()) ;
2473 for (String fieldName in _fieldMap.keys.toSet()) { 2790 for (String fieldName in _fieldMap.keys.toSet()) {
2474 if (_fieldMap[fieldName] != state._fieldMap[fieldName]) { 2791 if (_fieldMap[fieldName] != state._fieldMap[fieldName]) {
2475 return false; 2792 return false;
2476 } 2793 }
2477 otherFields.remove(fieldName); 2794 otherFields.remove(fieldName);
2478 } 2795 }
2479 for (String fieldName in otherFields) { 2796 for (String fieldName in otherFields) {
2480 if (state._fieldMap[fieldName] != _fieldMap[fieldName]) { 2797 if (state._fieldMap[fieldName] != _fieldMap[fieldName]) {
2481 return false; 2798 return false;
2482 } 2799 }
2483 } 2800 }
2484 return true; 2801 return true;
2485 } 2802 }
2486 2803
2487 @override 2804 @override
2488 BoolState equalEqual(InstanceState rightOperand) { 2805 Map<String, DartObjectImpl> get fields => _fieldMap;
2489 assertBoolNumStringOrNull(rightOperand);
2490 if (rightOperand is DynamicState) {
2491 return BoolState.UNKNOWN_VALUE;
2492 }
2493 return BoolState.from(this == rightOperand);
2494 }
2495 2806
2496 @override 2807 @override
2497 String get typeName => "user defined type"; 2808 String get typeName => "user defined type";
2498 2809
2499 @override 2810 @override
2500 int get hashCode { 2811 int get hashCode {
2501 int hashCode = 0; 2812 int hashCode = 0;
2502 for (DartObjectImpl value in _fieldMap.values) { 2813 for (DartObjectImpl value in _fieldMap.values) {
2503 hashCode += value.hashCode; 2814 hashCode += value.hashCode;
2504 } 2815 }
2505 return hashCode; 2816 return hashCode;
2506 } 2817 }
2818
2819 @override
2820 bool get isUnknown => identical(this, UNKNOWN_VALUE);
2507 } 2821 }
2508 2822
2509 /** 2823 /**
2510 * The class `InstanceState` defines the behavior of objects representing the st ate of a Dart 2824 * The class `InstanceState` defines the behavior of objects representing the st ate of a Dart
2511 * object. 2825 * object.
2512 */ 2826 */
2513 abstract class InstanceState { 2827 abstract class InstanceState {
2514 /** 2828 /**
2515 * Return the result of invoking the '+' operator on this object with the give n argument. 2829 * Return the result of invoking the '+' operator on this object with the give n argument.
2516 * 2830 *
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
2618 /** 2932 /**
2619 * Return the result of invoking the '==' operator on this object with the giv en argument. 2933 * Return the result of invoking the '==' operator on this object with the giv en argument.
2620 * 2934 *
2621 * @param rightOperand the right-hand operand of the operation 2935 * @param rightOperand the right-hand operand of the operation
2622 * @return the result of invoking the '==' operator on this object with the gi ven argument 2936 * @return the result of invoking the '==' operator on this object with the gi ven argument
2623 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind 2937 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
2624 */ 2938 */
2625 BoolState equalEqual(InstanceState rightOperand); 2939 BoolState equalEqual(InstanceState rightOperand);
2626 2940
2627 /** 2941 /**
2942 * If this represents a generic dart object, return a map from its fieldnames to their values.
2943 * Otherwise return null.
2944 */
2945 Map<String, DartObjectImpl> get fields => null;
2946
2947 /**
2628 * Return the name of the type of this value. 2948 * Return the name of the type of this value.
2629 * 2949 *
2630 * @return the name of the type of this value 2950 * @return the name of the type of this value
2631 */ 2951 */
2632 String get typeName; 2952 String get typeName;
2633 2953
2634 /** 2954 /**
2635 * Return this object's value if it can be represented exactly, or `null` if e ither the 2955 * Return this object's value if it can be represented exactly, or `null` if e ither the
2636 * value cannot be represented exactly or if the value is `null`. Clients shou ld use 2956 * value cannot be represented exactly or if the value is `null`. Clients shou ld use
2637 * [hasExactValue] to distinguish between these two cases. 2957 * [hasExactValue] to distinguish between these two cases.
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
2695 3015
2696 /** 3016 /**
2697 * Return `true` if this object represents an object whose type is either 'boo l', 'num', 3017 * Return `true` if this object represents an object whose type is either 'boo l', 'num',
2698 * 'String', or 'Null'. 3018 * 'String', or 'Null'.
2699 * 3019 *
2700 * @return `true` if this object represents either a boolean, numeric, string or null value 3020 * @return `true` if this object represents either a boolean, numeric, string or null value
2701 */ 3021 */
2702 bool get isBoolNumStringOrNull => false; 3022 bool get isBoolNumStringOrNull => false;
2703 3023
2704 /** 3024 /**
3025 * Return true if this object represents an unknown value.
3026 */
3027 bool get isUnknown => false;
3028
3029 /**
2705 * Return the result of invoking the '&lt;' operator on this object with the g iven argument. 3030 * Return the result of invoking the '&lt;' operator on this object with the g iven argument.
2706 * 3031 *
2707 * @param rightOperand the right-hand operand of the operation 3032 * @param rightOperand the right-hand operand of the operation
2708 * @return the result of invoking the '&lt;' operator on this object with the given argument 3033 * @return the result of invoking the '&lt;' operator on this object with the given argument
2709 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind 3034 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
2710 */ 3035 */
2711 BoolState lessThan(InstanceState rightOperand) { 3036 BoolState lessThan(InstanceState rightOperand) {
2712 assertNumOrNull(this); 3037 assertNumOrNull(this);
2713 assertNumOrNull(rightOperand); 3038 assertNumOrNull(rightOperand);
2714 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT); 3039 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
(...skipping 880 matching lines...) Expand 10 before | Expand all | Expand 10 after
3595 @override 3920 @override
3596 StringState convertToString() => StringState.UNKNOWN_VALUE; 3921 StringState convertToString() => StringState.UNKNOWN_VALUE;
3597 3922
3598 @override 3923 @override
3599 NumState divide(InstanceState rightOperand) { 3924 NumState divide(InstanceState rightOperand) {
3600 assertNumOrNull(rightOperand); 3925 assertNumOrNull(rightOperand);
3601 return UNKNOWN_VALUE; 3926 return UNKNOWN_VALUE;
3602 } 3927 }
3603 3928
3604 @override 3929 @override
3605 bool operator ==(Object object) => object is NumState;
3606
3607 @override
3608 BoolState equalEqual(InstanceState rightOperand) { 3930 BoolState equalEqual(InstanceState rightOperand) {
3609 assertBoolNumStringOrNull(rightOperand); 3931 assertBoolNumStringOrNull(rightOperand);
3610 return BoolState.UNKNOWN_VALUE; 3932 return BoolState.UNKNOWN_VALUE;
3611 } 3933 }
3612 3934
3613 @override 3935 @override
3936 bool operator ==(Object object) => object is NumState;
3937
3938 @override
3614 String get typeName => "num"; 3939 String get typeName => "num";
3615 3940
3616 @override 3941 @override
3617 BoolState greaterThan(InstanceState rightOperand) { 3942 BoolState greaterThan(InstanceState rightOperand) {
3618 assertNumOrNull(rightOperand); 3943 assertNumOrNull(rightOperand);
3619 return BoolState.UNKNOWN_VALUE; 3944 return BoolState.UNKNOWN_VALUE;
3620 } 3945 }
3621 3946
3622 @override 3947 @override
3623 BoolState greaterThanOrEqual(InstanceState rightOperand) { 3948 BoolState greaterThanOrEqual(InstanceState rightOperand) {
(...skipping 17 matching lines...) Expand all
3641 } else if (rightOperand is DynamicState) { 3966 } else if (rightOperand is DynamicState) {
3642 return IntState.UNKNOWN_VALUE; 3967 return IntState.UNKNOWN_VALUE;
3643 } 3968 }
3644 return IntState.UNKNOWN_VALUE; 3969 return IntState.UNKNOWN_VALUE;
3645 } 3970 }
3646 3971
3647 @override 3972 @override
3648 bool get isBoolNumStringOrNull => true; 3973 bool get isBoolNumStringOrNull => true;
3649 3974
3650 @override 3975 @override
3976 bool get isUnknown => identical(this, UNKNOWN_VALUE);
3977
3978 @override
3651 BoolState lessThan(InstanceState rightOperand) { 3979 BoolState lessThan(InstanceState rightOperand) {
3652 assertNumOrNull(rightOperand); 3980 assertNumOrNull(rightOperand);
3653 return BoolState.UNKNOWN_VALUE; 3981 return BoolState.UNKNOWN_VALUE;
3654 } 3982 }
3655 3983
3656 @override 3984 @override
3657 BoolState lessThanOrEqual(InstanceState rightOperand) { 3985 BoolState lessThanOrEqual(InstanceState rightOperand) {
3658 assertNumOrNull(rightOperand); 3986 assertNumOrNull(rightOperand);
3659 return BoolState.UNKNOWN_VALUE; 3987 return BoolState.UNKNOWN_VALUE;
3660 } 3988 }
(...skipping 22 matching lines...) Expand all
3683 @override 4011 @override
3684 String toString() => "-unknown-"; 4012 String toString() => "-unknown-";
3685 } 4013 }
3686 4014
3687 /** 4015 /**
3688 * Instances of the class `ReferenceFinder` add reference information for a give n variable to 4016 * Instances of the class `ReferenceFinder` add reference information for a give n variable to
3689 * the bi-directional mapping used to order the evaluation of constants. 4017 * the bi-directional mapping used to order the evaluation of constants.
3690 */ 4018 */
3691 class ReferenceFinder extends RecursiveAstVisitor<Object> { 4019 class ReferenceFinder extends RecursiveAstVisitor<Object> {
3692 /** 4020 /**
3693 * The element representing the variable whose initializer will be visited. 4021 * The element representing the construct that will be visited.
3694 */ 4022 */
3695 final VariableElement _source; 4023 final AstNode _source;
3696 4024
3697 /** 4025 /**
3698 * A graph in which the nodes are the constant variables and the edges are fro m each variable to 4026 * A graph in which the nodes are the constant variables and the edges are fro m each variable to
3699 * the other constant variables that are referenced in the head's initializer. 4027 * the other constant variables that are referenced in the head's initializer.
3700 */ 4028 */
3701 final DirectedGraph<VariableElement> _referenceGraph; 4029 final DirectedGraph<AstNode> _referenceGraph;
4030
4031 /**
4032 * A table mapping constant variables to the declarations of those variables.
4033 */
4034 final Map<VariableElement, VariableDeclaration> _variableDeclarationMap;
4035
4036 /**
4037 * A table mapping constant constructors to the declarations of those construc tors.
4038 */
4039 final Map<ConstructorElement, ConstructorDeclaration> _constructorDeclarationM ap;
3702 4040
3703 /** 4041 /**
3704 * Initialize a newly created reference finder to find references from the giv en variable to other 4042 * Initialize a newly created reference finder to find references from the giv en variable to other
3705 * variables and to add those references to the given graph. 4043 * variables and to add those references to the given graph.
3706 * 4044 *
3707 * @param source the element representing the variable whose initializer will be visited 4045 * @param source the element representing the variable whose initializer will be visited
3708 * @param referenceGraph a graph recording which variables (heads) reference w hich other variables 4046 * @param referenceGraph a graph recording which variables (heads) reference w hich other variables
3709 * (tails) in their initializers 4047 * (tails) in their initializers
4048 * @param variableDeclarationMap A table mapping constant variables to the dec larations of those
4049 * variables.
4050 * @param constructorDeclarationMap A table mapping constant constructors to t he declarations of
4051 * those constructors.
3710 */ 4052 */
3711 ReferenceFinder(this._source, this._referenceGraph); 4053 ReferenceFinder(this._source, this._referenceGraph, this._variableDeclarationM ap, this._constructorDeclarationMap);
4054
4055 @override
4056 Object visitInstanceCreationExpression(InstanceCreationExpression node) {
4057 if (node.isConst) {
4058 _referenceGraph.addEdge(_source, node);
4059 }
4060 return null;
4061 }
3712 4062
3713 @override 4063 @override
3714 Object visitSimpleIdentifier(SimpleIdentifier node) { 4064 Object visitSimpleIdentifier(SimpleIdentifier node) {
3715 Element element = node.staticElement; 4065 Element element = node.staticElement;
3716 if (element is PropertyAccessorElement) { 4066 if (element is PropertyAccessorElement) {
3717 element = (element as PropertyAccessorElement).variable; 4067 element = (element as PropertyAccessorElement).variable;
3718 } 4068 }
3719 if (element is VariableElement) { 4069 if (element is VariableElement) {
3720 VariableElement variable = element as VariableElement; 4070 VariableElement variable = element as VariableElement;
3721 if (variable.isConst) { 4071 if (variable.isConst) {
3722 _referenceGraph.addEdge(_source, variable); 4072 VariableDeclaration variableDeclaration = _variableDeclarationMap[variab le];
4073 // The declaration will be null when the variable is not defined in the compilation units
4074 // that were used to produce the variableDeclarationMap. In such cases, the variable should
4075 // already have a value associated with it, but we don't bother to check because there's
4076 // nothing we can do about it at this point.
4077 if (variableDeclaration != null) {
4078 _referenceGraph.addEdge(_source, variableDeclaration);
4079 }
3723 } 4080 }
3724 } 4081 }
3725 return null; 4082 return null;
4083 }
4084
4085 @override
4086 Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
4087 super.visitSuperConstructorInvocation(node);
4088 ConstructorElement constructor = node.staticElement;
4089 if (constructor != null && constructor.isConst) {
4090 ConstructorDeclaration constructorDeclaration = _constructorDeclarationMap [constructor];
4091 // The declaration will be null when the constructor is not defined in the compilation
4092 // units that were used to produce the constructorDeclarationMap. In such cases, the
4093 // constructor should already have its initializer AST's stored in it, but we don't bother
4094 // to check because there's nothing we can do about it at this point.
4095 if (constructorDeclaration != null) {
4096 _referenceGraph.addEdge(_source, constructorDeclaration);
4097 }
4098 }
4099 return null;
3726 } 4100 }
3727 } 4101 }
3728 4102
3729 /** 4103 /**
3730 * Instances of the class `StringState` represent the state of an object represe nting a 4104 * Instances of the class `StringState` represent the state of an object represe nting a
3731 * string. 4105 * string.
3732 */ 4106 */
3733 class StringState extends InstanceState { 4107 class StringState extends InstanceState {
3734 /** 4108 /**
3735 * The value of this instance. 4109 * The value of this instance.
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
3795 @override 4169 @override
3796 bool get hasExactValue => true; 4170 bool get hasExactValue => true;
3797 4171
3798 @override 4172 @override
3799 int get hashCode => value == null ? 0 : value.hashCode; 4173 int get hashCode => value == null ? 0 : value.hashCode;
3800 4174
3801 @override 4175 @override
3802 bool get isBoolNumStringOrNull => true; 4176 bool get isBoolNumStringOrNull => true;
3803 4177
3804 @override 4178 @override
4179 bool get isUnknown => value == null;
4180
4181 @override
3805 String toString() => value == null ? "-unknown-" : "'${value}'"; 4182 String toString() => value == null ? "-unknown-" : "'${value}'";
3806 } 4183 }
3807 4184
3808 /** 4185 /**
3809 * Instances of the class `StringState` represent the state of an object represe nting a 4186 * Instances of the class `StringState` represent the state of an object represe nting a
3810 * symbol. 4187 * symbol.
3811 */ 4188 */
3812 class SymbolState extends InstanceState { 4189 class SymbolState extends InstanceState {
3813 /** 4190 /**
3814 * The value of this instance. 4191 * The value of this instance.
(...skipping 541 matching lines...) Expand 10 before | Expand all | Expand 10 after
4356 ErrorResult _error(AstNode node, ErrorCode code) => new ErrorResult.con1(node, code); 4733 ErrorResult _error(AstNode node, ErrorCode code) => new ErrorResult.con1(node, code);
4357 4734
4358 /** 4735 /**
4359 * Return a result object representing the given value. 4736 * Return a result object representing the given value.
4360 * 4737 *
4361 * @param value the value to be represented as a result object 4738 * @param value the value to be represented as a result object
4362 * @return a result object representing the given value 4739 * @return a result object representing the given value
4363 */ 4740 */
4364 ValidResult _valueOf(DartObjectImpl value) => new ValidResult(value); 4741 ValidResult _valueOf(DartObjectImpl value) => new ValidResult(value);
4365 } 4742 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/generated/ast.dart ('k') | pkg/analyzer/lib/src/generated/element.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698