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

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

Issue 1416873003: Rework handling of potentially-constant variables. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 2 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
« no previous file with comments | « no previous file | 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 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
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/generated/element.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698