| OLD | NEW |
| 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 library engine.constant; | 5 library engine.constant; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 | 8 |
| 9 import 'package:analyzer/src/generated/engine.dart'; | 9 import 'package:analyzer/src/generated/engine.dart'; |
| 10 import 'package:analyzer/src/generated/utilities_general.dart'; | 10 import 'package:analyzer/src/generated/utilities_general.dart'; |
| (...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 } | 313 } |
| 314 String name = argumentValues[0].toStringValue(); | 314 String name = argumentValues[0].toStringValue(); |
| 315 return isValidPublicSymbol(name); | 315 return isValidPublicSymbol(name); |
| 316 } | 316 } |
| 317 | 317 |
| 318 /** | 318 /** |
| 319 * Compute the constant value associated with the given [constant]. | 319 * Compute the constant value associated with the given [constant]. |
| 320 */ | 320 */ |
| 321 void computeConstantValue(ConstantEvaluationTarget constant) { | 321 void computeConstantValue(ConstantEvaluationTarget constant) { |
| 322 validator.beforeComputeValue(constant); | 322 validator.beforeComputeValue(constant); |
| 323 if (constant is ParameterElement) { | 323 if (constant is ParameterElementImpl) { |
| 324 if (constant.initializer != null) { | 324 if (constant.initializer != null) { |
| 325 Expression defaultValue = | 325 Expression defaultValue = constant.constantInitializer; |
| 326 (constant as PotentiallyConstVariableElement).constantInitializer; | |
| 327 if (defaultValue != null) { | 326 if (defaultValue != null) { |
| 328 RecordingErrorListener errorListener = new RecordingErrorListener(); | 327 RecordingErrorListener errorListener = new RecordingErrorListener(); |
| 329 ErrorReporter errorReporter = | 328 ErrorReporter errorReporter = |
| 330 new ErrorReporter(errorListener, constant.source); | 329 new ErrorReporter(errorListener, constant.source); |
| 331 DartObjectImpl dartObject = | 330 DartObjectImpl dartObject = |
| 332 defaultValue.accept(new ConstantVisitor(this, errorReporter)); | 331 defaultValue.accept(new ConstantVisitor(this, errorReporter)); |
| 333 (constant as ParameterElementImpl).evaluationResult = | 332 constant.evaluationResult = |
| 334 new EvaluationResultImpl(dartObject, errorListener.errors); | 333 new EvaluationResultImpl(dartObject, errorListener.errors); |
| 335 } | 334 } |
| 336 } | 335 } |
| 337 } else if (constant is VariableElement) { | 336 } else if (constant is VariableElementImpl) { |
| 338 Expression constantInitializer = | 337 Expression constantInitializer = constant.constantInitializer; |
| 339 (constant as PotentiallyConstVariableElement).constantInitializer; | |
| 340 if (constantInitializer != null) { | 338 if (constantInitializer != null) { |
| 341 RecordingErrorListener errorListener = new RecordingErrorListener(); | 339 RecordingErrorListener errorListener = new RecordingErrorListener(); |
| 342 ErrorReporter errorReporter = | 340 ErrorReporter errorReporter = |
| 343 new ErrorReporter(errorListener, constant.source); | 341 new ErrorReporter(errorListener, constant.source); |
| 344 DartObjectImpl dartObject = constantInitializer | 342 DartObjectImpl dartObject = constantInitializer |
| 345 .accept(new ConstantVisitor(this, errorReporter)); | 343 .accept(new ConstantVisitor(this, errorReporter)); |
| 346 // Only check the type for truly const declarations (don't check final | 344 // Only check the type for truly const declarations (don't check final |
| 347 // fields with initializers, since their types may be generic. The type | 345 // fields with initializers, since their types may be generic. The type |
| 348 // of the final field will be checked later, when the constructor is | 346 // of the final field will be checked later, when the constructor is |
| 349 // invoked). | 347 // invoked). |
| 350 if (dartObject != null && constant.isConst) { | 348 if (dartObject != null && constant.isConst) { |
| 351 if (!runtimeTypeMatch(dartObject, constant.type)) { | 349 if (!runtimeTypeMatch(dartObject, constant.type)) { |
| 352 errorReporter.reportErrorForElement( | 350 errorReporter.reportErrorForElement( |
| 353 CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH, | 351 CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH, |
| 354 constant, | 352 constant, |
| 355 [dartObject.type, constant.type]); | 353 [dartObject.type, constant.type]); |
| 356 } | 354 } |
| 357 } | 355 } |
| 358 (constant as VariableElementImpl).evaluationResult = | 356 constant.evaluationResult = |
| 359 new EvaluationResultImpl(dartObject, errorListener.errors); | 357 new EvaluationResultImpl(dartObject, errorListener.errors); |
| 360 } | 358 } |
| 361 } else if (constant is ConstructorElement) { | 359 } else if (constant is ConstructorElement) { |
| 362 if (constant.isConst) { | 360 if (constant.isConst) { |
| 363 // No evaluation needs to be done; constructor declarations are only in | 361 // No evaluation needs to be done; constructor declarations are only in |
| 364 // the dependency graph to ensure that any constants referred to in | 362 // the dependency graph to ensure that any constants referred to in |
| 365 // initializer lists and parameter defaults are evaluated before | 363 // initializer lists and parameter defaults are evaluated before |
| 366 // invocations of the constructor. However we do need to annotate the | 364 // invocations of the constructor. However we do need to annotate the |
| 367 // element as being free of constant evaluation cycles so that later | 365 // element as being free of constant evaluation cycles so that later |
| 368 // code will know that it is safe to evaluate. | 366 // code will know that it is safe to evaluate. |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 408 errorReporter); | 406 errorReporter); |
| 409 elementAnnotation.evaluationResult = | 407 elementAnnotation.evaluationResult = |
| 410 new EvaluationResultImpl(result, errorListener.errors); | 408 new EvaluationResultImpl(result, errorListener.errors); |
| 411 } else { | 409 } else { |
| 412 // This may happen for invalid code (e.g. failing to pass arguments | 410 // This may happen for invalid code (e.g. failing to pass arguments |
| 413 // to an annotation which references a const constructor). The error | 411 // to an annotation which references a const constructor). The error |
| 414 // is detected elsewhere, so just silently ignore it here. | 412 // is detected elsewhere, so just silently ignore it here. |
| 415 elementAnnotation.evaluationResult = new EvaluationResultImpl(null); | 413 elementAnnotation.evaluationResult = new EvaluationResultImpl(null); |
| 416 } | 414 } |
| 417 } | 415 } |
| 416 } else if (constant is VariableElement) { |
| 417 // constant is a VariableElement but not a VariableElementImpl. This can |
| 418 // happen sometimes in the case of invalid user code (for example, a |
| 419 // constant expression that refers to a nonstatic field inside a generic |
| 420 // class will wind up referring to a FieldMember). The error is detected |
| 421 // elsewhere, so just silently ignore it here. |
| 418 } else { | 422 } else { |
| 419 // Should not happen. | 423 // Should not happen. |
| 420 assert(false); | 424 assert(false); |
| 421 AnalysisEngine.instance.logger.logError( | 425 AnalysisEngine.instance.logger.logError( |
| 422 "Constant value computer trying to compute the value of a node of type
${constant.runtimeType}"); | 426 "Constant value computer trying to compute the value of a node of type
${constant.runtimeType}"); |
| 423 return; | 427 return; |
| 424 } | 428 } |
| 425 } | 429 } |
| 426 | 430 |
| 427 /** | 431 /** |
| 428 * Determine which constant elements need to have their values computed | 432 * Determine which constant elements need to have their values computed |
| 429 * prior to computing the value of [constant], and report them using | 433 * prior to computing the value of [constant], and report them using |
| 430 * [callback]. | 434 * [callback]. |
| 431 * | 435 * |
| 432 * Note that it's possible (in erroneous code) for a constant to depend on a | 436 * Note that it's possible (in erroneous code) for a constant to depend on a |
| 433 * non-constant. When this happens, we report the dependency anyhow so that | 437 * non-constant. When this happens, we report the dependency anyhow so that |
| 434 * if the non-constant changes to a constant, we will know to recompute the | 438 * if the non-constant changes to a constant, we will know to recompute the |
| 435 * thing that depends on it. [computeDependencies] and | 439 * thing that depends on it. [computeDependencies] and |
| 436 * [computeConstantValue] are responsible for ignoring the request if they | 440 * [computeConstantValue] are responsible for ignoring the request if they |
| 437 * are asked to act on a non-constant target. | 441 * are asked to act on a non-constant target. |
| 438 */ | 442 */ |
| 439 void computeDependencies( | 443 void computeDependencies( |
| 440 ConstantEvaluationTarget constant, ReferenceFinderCallback callback) { | 444 ConstantEvaluationTarget constant, ReferenceFinderCallback callback) { |
| 441 ReferenceFinder referenceFinder = new ReferenceFinder(callback); | 445 ReferenceFinder referenceFinder = new ReferenceFinder(callback); |
| 442 if (constant is ParameterElement) { | 446 if (constant is ParameterElementImpl) { |
| 443 if (constant.initializer != null) { | 447 if (constant.initializer != null) { |
| 444 Expression defaultValue = | 448 Expression defaultValue = constant.constantInitializer; |
| 445 (constant as ConstVariableElement).constantInitializer; | |
| 446 if (defaultValue != null) { | 449 if (defaultValue != null) { |
| 447 defaultValue.accept(referenceFinder); | 450 defaultValue.accept(referenceFinder); |
| 448 } | 451 } |
| 449 } | 452 } |
| 450 } else if (constant is PotentiallyConstVariableElement) { | 453 } else if (constant is VariableElementImpl) { |
| 451 Expression initializer = constant.constantInitializer; | 454 Expression initializer = constant.constantInitializer; |
| 452 if (initializer != null) { | 455 if (initializer != null) { |
| 453 initializer.accept(referenceFinder); | 456 initializer.accept(referenceFinder); |
| 454 } | 457 } |
| 455 } else if (constant is ConstructorElementImpl) { | 458 } else if (constant is ConstructorElementImpl) { |
| 456 if (constant.isConst) { | 459 if (constant.isConst) { |
| 457 constant.isCycleFree = false; | 460 constant.isCycleFree = false; |
| 458 ConstructorElement redirectedConstructor = | 461 ConstructorElement redirectedConstructor = |
| 459 getConstRedirectedConstructor(constant); | 462 getConstRedirectedConstructor(constant); |
| 460 if (redirectedConstructor != null) { | 463 if (redirectedConstructor != null) { |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 525 // constructor. | 528 // constructor. |
| 526 callback(element); | 529 callback(element); |
| 527 } else { | 530 } else { |
| 528 // This could happen in the event of invalid code. The error will be | 531 // This could happen in the event of invalid code. The error will be |
| 529 // reported at constant evaluation time. | 532 // reported at constant evaluation time. |
| 530 } | 533 } |
| 531 } | 534 } |
| 532 if (constNode.arguments != null) { | 535 if (constNode.arguments != null) { |
| 533 constNode.arguments.accept(referenceFinder); | 536 constNode.arguments.accept(referenceFinder); |
| 534 } | 537 } |
| 538 } else if (constant is VariableElement) { |
| 539 // constant is a VariableElement but not a VariableElementImpl. This can |
| 540 // happen sometimes in the case of invalid user code (for example, a |
| 541 // constant expression that refers to a nonstatic field inside a generic |
| 542 // class will wind up referring to a FieldMember). So just don't bother |
| 543 // computing any dependencies. |
| 535 } else { | 544 } else { |
| 536 // Should not happen. | 545 // Should not happen. |
| 537 assert(false); | 546 assert(false); |
| 538 AnalysisEngine.instance.logger.logError( | 547 AnalysisEngine.instance.logger.logError( |
| 539 "Constant value computer trying to compute the value of a node of type
${constant.runtimeType}"); | 548 "Constant value computer trying to compute the value of a node of type
${constant.runtimeType}"); |
| 540 } | 549 } |
| 541 } | 550 } |
| 542 | 551 |
| 543 /** | 552 /** |
| 544 * Evaluate a call to fromEnvironment() on the bool, int, or String class. The | 553 * Evaluate a call to fromEnvironment() on the bool, int, or String class. The |
| (...skipping 4996 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5541 return BoolState.from(_element == rightElement); | 5550 return BoolState.from(_element == rightElement); |
| 5542 } else if (rightOperand is DynamicState) { | 5551 } else if (rightOperand is DynamicState) { |
| 5543 return BoolState.UNKNOWN_VALUE; | 5552 return BoolState.UNKNOWN_VALUE; |
| 5544 } | 5553 } |
| 5545 return BoolState.FALSE_STATE; | 5554 return BoolState.FALSE_STATE; |
| 5546 } | 5555 } |
| 5547 | 5556 |
| 5548 @override | 5557 @override |
| 5549 String toString() => _element == null ? "-unknown-" : _element.name; | 5558 String toString() => _element == null ? "-unknown-" : _element.name; |
| 5550 } | 5559 } |
| OLD | NEW |