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

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

Issue 1665353002: Use ElementAnnotation as the ConstantEvaluationTarget for annotations. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 analyzer.src.generated.constant; 5 library analyzer.src.generated.constant;
6 6
7 import 'dart:collection'; 7 import 'dart:collection';
8 8
9 import 'package:analyzer/dart/ast/ast.dart'; 9 import 'package:analyzer/dart/ast/ast.dart';
10 import 'package:analyzer/dart/ast/visitor.dart'; 10 import 'package:analyzer/dart/ast/visitor.dart';
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after
377 } else if (constant is ConstructorElement) { 377 } else if (constant is ConstructorElement) {
378 if (constant.isConst) { 378 if (constant.isConst) {
379 // No evaluation needs to be done; constructor declarations are only in 379 // No evaluation needs to be done; constructor declarations are only in
380 // the dependency graph to ensure that any constants referred to in 380 // the dependency graph to ensure that any constants referred to in
381 // initializer lists and parameter defaults are evaluated before 381 // initializer lists and parameter defaults are evaluated before
382 // invocations of the constructor. However we do need to annotate the 382 // invocations of the constructor. However we do need to annotate the
383 // element as being free of constant evaluation cycles so that later 383 // element as being free of constant evaluation cycles so that later
384 // code will know that it is safe to evaluate. 384 // code will know that it is safe to evaluate.
385 (constant as ConstructorElementImpl).isCycleFree = true; 385 (constant as ConstructorElementImpl).isCycleFree = true;
386 } 386 }
387 } else if (constant is ConstantEvaluationTarget_Annotation) { 387 } else if (constant is ElementAnnotationImpl) {
388 Annotation constNode = constant.annotation; 388 Annotation constNode = constant.annotationAst;
389 ElementAnnotationImpl elementAnnotation = constNode.elementAnnotation; 389 Element element = constant.element;
390 // elementAnnotation is null if the annotation couldn't be resolved, in 390 if (element is PropertyAccessorElement &&
391 // which case we skip it. 391 element.variable is VariableElementImpl) {
392 if (elementAnnotation != null) { 392 // The annotation is a reference to a compile-time constant variable.
393 Element element = elementAnnotation.element; 393 // Just copy the evaluation result.
394 if (element is PropertyAccessorElement && 394 VariableElementImpl variableElement =
395 element.variable is VariableElementImpl) { 395 element.variable as VariableElementImpl;
396 // The annotation is a reference to a compile-time constant variable. 396 if (variableElement.evaluationResult != null) {
397 // Just copy the evaluation result. 397 constant.evaluationResult = variableElement.evaluationResult;
398 VariableElementImpl variableElement =
399 element.variable as VariableElementImpl;
400 if (variableElement.evaluationResult != null) {
401 elementAnnotation.evaluationResult =
402 variableElement.evaluationResult;
403 } else {
404 // This could happen in the event that the annotation refers to a
405 // non-constant. The error is detected elsewhere, so just silently
406 // ignore it here.
407 elementAnnotation.evaluationResult = new EvaluationResultImpl(null);
408 }
409 } else if (element is ConstructorElementImpl &&
410 element.isConst &&
411 constNode.arguments != null) {
412 RecordingErrorListener errorListener = new RecordingErrorListener();
413 CompilationUnit sourceCompilationUnit =
414 constNode.getAncestor((node) => node is CompilationUnit);
415 ErrorReporter errorReporter = new ErrorReporter(
416 errorListener, sourceCompilationUnit.element.source);
417 ConstantVisitor constantVisitor =
418 new ConstantVisitor(this, errorReporter);
419 DartObjectImpl result = evaluateConstructorCall(
420 constNode,
421 constNode.arguments.arguments,
422 element,
423 constantVisitor,
424 errorReporter);
425 elementAnnotation.evaluationResult =
426 new EvaluationResultImpl(result, errorListener.errors);
427 } else { 398 } else {
428 // This may happen for invalid code (e.g. failing to pass arguments 399 // This could happen in the event that the annotation refers to a
429 // to an annotation which references a const constructor). The error 400 // non-constant. The error is detected elsewhere, so just silently
430 // is detected elsewhere, so just silently ignore it here. 401 // ignore it here.
431 elementAnnotation.evaluationResult = new EvaluationResultImpl(null); 402 constant.evaluationResult = new EvaluationResultImpl(null);
432 } 403 }
404 } else if (element is ConstructorElementImpl &&
405 element.isConst &&
406 constNode.arguments != null) {
407 RecordingErrorListener errorListener = new RecordingErrorListener();
408 ErrorReporter errorReporter =
409 new ErrorReporter(errorListener, constant.source);
410 ConstantVisitor constantVisitor =
411 new ConstantVisitor(this, errorReporter);
412 DartObjectImpl result = evaluateConstructorCall(
413 constNode,
414 constNode.arguments.arguments,
415 element,
416 constantVisitor,
417 errorReporter);
418 constant.evaluationResult =
419 new EvaluationResultImpl(result, errorListener.errors);
420 } else {
421 // This may happen for invalid code (e.g. failing to pass arguments
422 // to an annotation which references a const constructor). The error
423 // is detected elsewhere, so just silently ignore it here.
424 constant.evaluationResult = new EvaluationResultImpl(null);
433 } 425 }
434 } else if (constant is VariableElement) { 426 } else if (constant is VariableElement) {
435 // constant is a VariableElement but not a VariableElementImpl. This can 427 // constant is a VariableElement but not a VariableElementImpl. This can
436 // happen sometimes in the case of invalid user code (for example, a 428 // happen sometimes in the case of invalid user code (for example, a
437 // constant expression that refers to a nonstatic field inside a generic 429 // constant expression that refers to a nonstatic field inside a generic
438 // class will wind up referring to a FieldMember). The error is detected 430 // class will wind up referring to a FieldMember). The error is detected
439 // elsewhere, so just silently ignore it here. 431 // elsewhere, so just silently ignore it here.
440 } else { 432 } else {
441 // Should not happen. 433 // Should not happen.
442 assert(false); 434 assert(false);
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
515 if ((field.isFinal || field.isConst) && 507 if ((field.isFinal || field.isConst) &&
516 !field.isStatic && 508 !field.isStatic &&
517 field.initializer != null) { 509 field.initializer != null) {
518 callback(field); 510 callback(field);
519 } 511 }
520 } 512 }
521 for (ParameterElement parameterElement in constant.parameters) { 513 for (ParameterElement parameterElement in constant.parameters) {
522 callback(parameterElement); 514 callback(parameterElement);
523 } 515 }
524 } 516 }
525 } else if (constant is ConstantEvaluationTarget_Annotation) { 517 } else if (constant is ElementAnnotationImpl) {
526 Annotation constNode = constant.annotation; 518 Annotation constNode = constant.annotationAst;
527 ElementAnnotationImpl elementAnnotation = constNode.elementAnnotation; 519 Element element = constant.element;
528 // elementAnnotation is null if the annotation couldn't be resolved, in 520 if (element is PropertyAccessorElement &&
529 // which case we skip it. 521 element.variable is VariableElementImpl) {
530 if (elementAnnotation != null) { 522 // The annotation is a reference to a compile-time constant variable,
531 Element element = elementAnnotation.element; 523 // so it depends on the variable.
532 if (element is PropertyAccessorElement && 524 callback(element.variable);
533 element.variable is VariableElementImpl) { 525 } else if (element is ConstructorElementImpl) {
534 // The annotation is a reference to a compile-time constant variable, 526 // The annotation is a constructor invocation, so it depends on the
535 // so it depends on the variable. 527 // constructor.
536 callback(element.variable); 528 callback(element);
537 } else if (element is ConstructorElementImpl) { 529 } else {
538 // The annotation is a constructor invocation, so it depends on the 530 // This could happen in the event of invalid code. The error will be
539 // constructor. 531 // reported at constant evaluation time.
540 callback(element);
541 } else {
542 // This could happen in the event of invalid code. The error will be
543 // reported at constant evaluation time.
544 }
545 } 532 }
546 if (constNode.arguments != null) { 533 if (constNode.arguments != null) {
547 constNode.arguments.accept(referenceFinder); 534 constNode.arguments.accept(referenceFinder);
548 } 535 }
549 } else if (constant is VariableElement) { 536 } else if (constant is VariableElement) {
550 // constant is a VariableElement but not a VariableElementImpl. This can 537 // constant is a VariableElement but not a VariableElementImpl. This can
551 // happen sometimes in the case of invalid user code (for example, a 538 // happen sometimes in the case of invalid user code (for example, a
552 // constant expression that refers to a nonstatic field inside a generic 539 // constant expression that refers to a nonstatic field inside a generic
553 // class will wind up referring to a FieldMember). So just don't bother 540 // class will wind up referring to a FieldMember). So just don't bother
554 // computing any dependencies. 541 // computing any dependencies.
(...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after
1016 static ConstructorElementImpl _getConstructorBase( 1003 static ConstructorElementImpl _getConstructorBase(
1017 ConstructorElement constructor) { 1004 ConstructorElement constructor) {
1018 while (constructor is ConstructorMember) { 1005 while (constructor is ConstructorMember) {
1019 constructor = (constructor as ConstructorMember).baseElement; 1006 constructor = (constructor as ConstructorMember).baseElement;
1020 } 1007 }
1021 return constructor; 1008 return constructor;
1022 } 1009 }
1023 } 1010 }
1024 1011
1025 /** 1012 /**
1026 * Wrapper around an [Annotation] which can be used as a
1027 * [ConstantEvaluationTarget].
1028 */
1029 class ConstantEvaluationTarget_Annotation implements ConstantEvaluationTarget {
1030 final AnalysisContext context;
1031 final Source source;
1032 final Source librarySource;
1033 final Annotation annotation;
1034
1035 ConstantEvaluationTarget_Annotation(
1036 this.context, this.source, this.librarySource, this.annotation);
1037
1038 @override
1039 int get hashCode => JenkinsSmiHash.hash3(
1040 source.hashCode, librarySource.hashCode, annotation.hashCode);
1041
1042 @override
1043 bool operator ==(other) {
1044 if (other is ConstantEvaluationTarget_Annotation) {
1045 return this.context == other.context &&
1046 this.source == other.source &&
1047 this.librarySource == other.librarySource &&
1048 this.annotation == other.annotation;
1049 } else {
1050 return false;
1051 }
1052 }
1053
1054 @override
1055 String toString() => 'Constant: $annotation';
1056 }
1057
1058 /**
1059 * Interface used by unit tests to verify correct dependency analysis during 1013 * Interface used by unit tests to verify correct dependency analysis during
1060 * constant evaluation. 1014 * constant evaluation.
1061 */ 1015 */
1062 abstract class ConstantEvaluationValidator { 1016 abstract class ConstantEvaluationValidator {
1063 /** 1017 /**
1064 * This method is called just before computing the constant value associated 1018 * This method is called just before computing the constant value associated
1065 * with [constant]. Unit tests will override this method to introduce 1019 * with [constant]. Unit tests will override this method to introduce
1066 * additional error checking. 1020 * additional error checking.
1067 */ 1021 */
1068 void beforeComputeValue(ConstantEvaluationTarget constant); 1022 void beforeComputeValue(ConstantEvaluationTarget constant);
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after
1303 /** 1257 /**
1304 * True if instance variables marked as "final" should be treated as "const". 1258 * True if instance variables marked as "final" should be treated as "const".
1305 */ 1259 */
1306 bool treatFinalInstanceVarAsConst = false; 1260 bool treatFinalInstanceVarAsConst = false;
1307 1261
1308 ConstantFinder(this.context, this.source, this.librarySource); 1262 ConstantFinder(this.context, this.source, this.librarySource);
1309 1263
1310 @override 1264 @override
1311 Object visitAnnotation(Annotation node) { 1265 Object visitAnnotation(Annotation node) {
1312 super.visitAnnotation(node); 1266 super.visitAnnotation(node);
1313 AnalysisContext owningContext = _getOwningContext(); 1267 ElementAnnotation elementAnnotation = node.elementAnnotation;
1314 constantsToCompute.add(new ConstantEvaluationTarget_Annotation( 1268 if (elementAnnotation == null) {
1315 owningContext, source, librarySource, node)); 1269 // Analyzer ignores annotations on "part of" directives.
1270 assert(node.parent is PartOfDirective);
1271 } else {
1272 constantsToCompute.add(elementAnnotation);
1273 }
1316 return null; 1274 return null;
1317 } 1275 }
1318 1276
1319 @override 1277 @override
1320 Object visitClassDeclaration(ClassDeclaration node) { 1278 Object visitClassDeclaration(ClassDeclaration node) {
1321 bool prevTreatFinalInstanceVarAsConst = treatFinalInstanceVarAsConst; 1279 bool prevTreatFinalInstanceVarAsConst = treatFinalInstanceVarAsConst;
1322 if (node.element.constructors.any((ConstructorElement e) => e.isConst)) { 1280 if (node.element.constructors.any((ConstructorElement e) => e.isConst)) {
1323 // Instance vars marked "final" need to be included in the dependency 1281 // Instance vars marked "final" need to be included in the dependency
1324 // graph, since constant constructors implicitly use the values in their 1282 // graph, since constant constructors implicitly use the values in their
1325 // initializers. 1283 // initializers.
(...skipping 4142 matching lines...) Expand 10 before | Expand all | Expand 10 after
5468 return BoolState.from(_element == rightElement); 5426 return BoolState.from(_element == rightElement);
5469 } else if (rightOperand is DynamicState) { 5427 } else if (rightOperand is DynamicState) {
5470 return BoolState.UNKNOWN_VALUE; 5428 return BoolState.UNKNOWN_VALUE;
5471 } 5429 }
5472 return BoolState.FALSE_STATE; 5430 return BoolState.FALSE_STATE;
5473 } 5431 }
5474 5432
5475 @override 5433 @override
5476 String toString() => _element == null ? "-unknown-" : _element.name; 5434 String toString() => _element == null ? "-unknown-" : _element.name;
5477 } 5435 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/dart/element/element.dart ('k') | pkg/analyzer/lib/src/generated/resolver.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698