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

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

Issue 1888223003: Move scopes into a separate library (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 4 years, 8 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.resolver; 5 library analyzer.src.generated.resolver;
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/token.dart'; 10 import 'package:analyzer/dart/ast/token.dart';
11 import 'package:analyzer/dart/ast/visitor.dart'; 11 import 'package:analyzer/dart/ast/visitor.dart';
12 import 'package:analyzer/dart/element/element.dart'; 12 import 'package:analyzer/dart/element/element.dart';
13 import 'package:analyzer/dart/element/type.dart'; 13 import 'package:analyzer/dart/element/type.dart';
14 import 'package:analyzer/dart/element/visitor.dart'; 14 import 'package:analyzer/dart/element/visitor.dart';
15 import 'package:analyzer/src/dart/ast/ast.dart'; 15 import 'package:analyzer/src/dart/ast/ast.dart';
16 import 'package:analyzer/src/dart/ast/token.dart'; 16 import 'package:analyzer/src/dart/ast/token.dart';
17 import 'package:analyzer/src/dart/ast/utilities.dart'; 17 import 'package:analyzer/src/dart/ast/utilities.dart';
18 import 'package:analyzer/src/dart/element/element.dart'; 18 import 'package:analyzer/src/dart/element/element.dart';
19 import 'package:analyzer/src/dart/element/member.dart'; 19 import 'package:analyzer/src/dart/element/member.dart';
20 import 'package:analyzer/src/dart/element/type.dart'; 20 import 'package:analyzer/src/dart/element/type.dart';
21 import 'package:analyzer/src/dart/element/utilities.dart'; 21 import 'package:analyzer/src/dart/element/utilities.dart';
22 import 'package:analyzer/src/dart/resolver/scope.dart';
22 import 'package:analyzer/src/generated/constant.dart'; 23 import 'package:analyzer/src/generated/constant.dart';
23 import 'package:analyzer/src/generated/element_resolver.dart'; 24 import 'package:analyzer/src/generated/element_resolver.dart';
24 import 'package:analyzer/src/generated/engine.dart'; 25 import 'package:analyzer/src/generated/engine.dart';
25 import 'package:analyzer/src/generated/error.dart'; 26 import 'package:analyzer/src/generated/error.dart';
26 import 'package:analyzer/src/generated/error_verifier.dart'; 27 import 'package:analyzer/src/generated/error_verifier.dart';
27 import 'package:analyzer/src/generated/java_core.dart'; 28 import 'package:analyzer/src/generated/java_core.dart';
28 import 'package:analyzer/src/generated/java_engine.dart'; 29 import 'package:analyzer/src/generated/java_engine.dart';
29 import 'package:analyzer/src/generated/source.dart'; 30 import 'package:analyzer/src/generated/source.dart';
30 import 'package:analyzer/src/generated/static_type_analyzer.dart'; 31 import 'package:analyzer/src/generated/static_type_analyzer.dart';
31 import 'package:analyzer/src/generated/type_system.dart'; 32 import 'package:analyzer/src/generated/type_system.dart';
32 import 'package:analyzer/src/generated/utilities_dart.dart'; 33 import 'package:analyzer/src/generated/utilities_dart.dart';
33 import 'package:analyzer/src/task/strong/info.dart' 34 import 'package:analyzer/src/task/strong/info.dart'
34 show InferredType, StaticInfo; 35 show InferredType, StaticInfo;
35 36
37 export 'package:analyzer/src/dart/resolver/scope.dart';
36 export 'package:analyzer/src/generated/type_system.dart'; 38 export 'package:analyzer/src/generated/type_system.dart';
37 39
38 /** 40 /**
39 * Instances of the class `BestPracticesVerifier` traverse an AST structure look ing for 41 * Instances of the class `BestPracticesVerifier` traverse an AST structure look ing for
40 * violations of Dart best practices. 42 * violations of Dart best practices.
41 */ 43 */
42 class BestPracticesVerifier extends RecursiveAstVisitor<Object> { 44 class BestPracticesVerifier extends RecursiveAstVisitor<Object> {
43 // static String _HASHCODE_GETTER_NAME = "hashCode"; 45 // static String _HASHCODE_GETTER_NAME = "hashCode";
44 46
45 static String _NULL_TYPE_NAME = "Null"; 47 static String _NULL_TYPE_NAME = "Null";
(...skipping 1040 matching lines...) Expand 10 before | Expand all | Expand 10 after
1086 } else { 1088 } else {
1087 if (!accessor.isSynthetic && accessor.correspondingGetter == null) { 1089 if (!accessor.isSynthetic && accessor.correspondingGetter == null) {
1088 setters.add(accessor); 1090 setters.add(accessor);
1089 } 1091 }
1090 } 1092 }
1091 } 1093 }
1092 } 1094 }
1093 } 1095 }
1094 1096
1095 /** 1097 /**
1096 * Instances of the class `ClassScope` implement the scope defined by a class.
1097 */
1098 class ClassScope extends EnclosedScope {
1099 /**
1100 * Initialize a newly created scope enclosed within another scope.
1101 *
1102 * @param enclosingScope the scope in which this scope is lexically enclosed
1103 * @param typeElement the element representing the type represented by this sc ope
1104 */
1105 ClassScope(Scope enclosingScope, ClassElement typeElement)
1106 : super(enclosingScope) {
1107 if (typeElement == null) {
1108 throw new IllegalArgumentException("class element cannot be null");
1109 }
1110 _defineMembers(typeElement);
1111 }
1112
1113 @override
1114 AnalysisError getErrorForDuplicate(Element existing, Element duplicate) {
1115 if (existing is PropertyAccessorElement && duplicate is MethodElement) {
1116 if (existing.nameOffset < duplicate.nameOffset) {
1117 return new AnalysisError(
1118 duplicate.source,
1119 duplicate.nameOffset,
1120 duplicate.nameLength,
1121 CompileTimeErrorCode.METHOD_AND_GETTER_WITH_SAME_NAME,
1122 [existing.displayName]);
1123 } else {
1124 return new AnalysisError(
1125 existing.source,
1126 existing.nameOffset,
1127 existing.nameLength,
1128 CompileTimeErrorCode.GETTER_AND_METHOD_WITH_SAME_NAME,
1129 [existing.displayName]);
1130 }
1131 }
1132 return super.getErrorForDuplicate(existing, duplicate);
1133 }
1134
1135 /**
1136 * Define the instance members defined by the class.
1137 *
1138 * @param typeElement the element representing the type represented by this sc ope
1139 */
1140 void _defineMembers(ClassElement typeElement) {
1141 for (PropertyAccessorElement accessor in typeElement.accessors) {
1142 define(accessor);
1143 }
1144 for (MethodElement method in typeElement.methods) {
1145 define(method);
1146 }
1147 }
1148 }
1149
1150 /**
1151 * Instances of the class `ConstantVerifier` traverse an AST structure looking f or additional 1098 * Instances of the class `ConstantVerifier` traverse an AST structure looking f or additional
1152 * errors and warnings not covered by the parser and resolver. In particular, it looks for errors 1099 * errors and warnings not covered by the parser and resolver. In particular, it looks for errors
1153 * and warnings related to constant expressions. 1100 * and warnings related to constant expressions.
1154 */ 1101 */
1155 class ConstantVerifier extends RecursiveAstVisitor<Object> { 1102 class ConstantVerifier extends RecursiveAstVisitor<Object> {
1156 /** 1103 /**
1157 * The error reporter by which errors will be reported. 1104 * The error reporter by which errors will be reported.
1158 */ 1105 */
1159 final ErrorReporter _errorReporter; 1106 final ErrorReporter _errorReporter;
1160 1107
(...skipping 2123 matching lines...) Expand 10 before | Expand all | Expand 10 after
3284 class ElementMismatchException extends AnalysisException { 3231 class ElementMismatchException extends AnalysisException {
3285 /** 3232 /**
3286 * Initialize a newly created exception to have the given [message] and 3233 * Initialize a newly created exception to have the given [message] and
3287 * [cause]. 3234 * [cause].
3288 */ 3235 */
3289 ElementMismatchException(String message, [CaughtException cause = null]) 3236 ElementMismatchException(String message, [CaughtException cause = null])
3290 : super(message, cause); 3237 : super(message, cause);
3291 } 3238 }
3292 3239
3293 /** 3240 /**
3294 * Instances of the class `EnclosedScope` implement a scope that is lexically en closed in
3295 * another scope.
3296 */
3297 class EnclosedScope extends Scope {
3298 /**
3299 * The scope in which this scope is lexically enclosed.
3300 */
3301 @override
3302 final Scope enclosingScope;
3303
3304 /**
3305 * A table mapping names that will be defined in this scope, but right now are not initialized.
3306 * According to the scoping rules these names are hidden, even if they were de fined in an outer
3307 * scope.
3308 */
3309 HashMap<String, Element> _hiddenElements = new HashMap<String, Element>();
3310
3311 /**
3312 * A flag indicating whether there are any names defined in this scope.
3313 */
3314 bool _hasHiddenName = false;
3315
3316 /**
3317 * Initialize a newly created scope enclosed within another scope.
3318 *
3319 * @param enclosingScope the scope in which this scope is lexically enclosed
3320 */
3321 EnclosedScope(this.enclosingScope);
3322
3323 @override
3324 AnalysisErrorListener get errorListener => enclosingScope.errorListener;
3325
3326 /**
3327 * Record that given element is declared in this scope, but hasn't been initia lized yet, so it is
3328 * error to use. If there is already an element with the given name defined in an outer scope,
3329 * then it will become unavailable.
3330 *
3331 * @param element the element declared, but not initialized in this scope
3332 */
3333 void hide(Element element) {
3334 if (element != null) {
3335 String name = element.name;
3336 if (name != null && !name.isEmpty) {
3337 _hiddenElements[name] = element;
3338 _hasHiddenName = true;
3339 }
3340 }
3341 }
3342
3343 @override
3344 Element internalLookup(
3345 Identifier identifier, String name, LibraryElement referencingLibrary) {
3346 Element element = localLookup(name, referencingLibrary);
3347 if (element != null) {
3348 return element;
3349 }
3350 // May be there is a hidden Element.
3351 if (_hasHiddenName) {
3352 Element hiddenElement = _hiddenElements[name];
3353 if (hiddenElement != null) {
3354 errorListener.onError(new AnalysisError(
3355 getSource(identifier),
3356 identifier.offset,
3357 identifier.length,
3358 CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION, []));
3359 return hiddenElement;
3360 }
3361 }
3362 // Check enclosing scope.
3363 return enclosingScope.internalLookup(identifier, name, referencingLibrary);
3364 }
3365 }
3366
3367 /**
3368 * Instances of the class `EnumMemberBuilder` build the members in enum declarat ions. 3241 * Instances of the class `EnumMemberBuilder` build the members in enum declarat ions.
3369 */ 3242 */
3370 class EnumMemberBuilder extends RecursiveAstVisitor<Object> { 3243 class EnumMemberBuilder extends RecursiveAstVisitor<Object> {
3371 /** 3244 /**
3372 * The type provider used to access the types needed to build an element model for enum 3245 * The type provider used to access the types needed to build an element model for enum
3373 * declarations. 3246 * declarations.
3374 */ 3247 */
3375 final TypeProvider _typeProvider; 3248 final TypeProvider _typeProvider;
3376 3249
3377 /** 3250 /**
(...skipping 598 matching lines...) Expand 10 before | Expand all | Expand 10 after
3976 3849
3977 /** 3850 /**
3978 * Return `true` if the given [node] exits. 3851 * Return `true` if the given [node] exits.
3979 */ 3852 */
3980 static bool exits(AstNode node) { 3853 static bool exits(AstNode node) {
3981 return new ExitDetector()._nodeExits(node); 3854 return new ExitDetector()._nodeExits(node);
3982 } 3855 }
3983 } 3856 }
3984 3857
3985 /** 3858 /**
3986 * The scope defined by a function.
3987 */
3988 class FunctionScope extends EnclosedScope {
3989 /**
3990 * The element representing the function that defines this scope.
3991 */
3992 final ExecutableElement _functionElement;
3993
3994 /**
3995 * A flag indicating whether the parameters have already been defined, used to
3996 * prevent the parameters from being defined multiple times.
3997 */
3998 bool _parametersDefined = false;
3999
4000 /**
4001 * Initialize a newly created scope enclosed within the [enclosingScope] that
4002 * represents the given [_functionElement].
4003 */
4004 FunctionScope(Scope enclosingScope, this._functionElement)
4005 : super(new EnclosedScope(new EnclosedScope(enclosingScope))) {
4006 if (_functionElement == null) {
4007 throw new IllegalArgumentException("function element cannot be null");
4008 }
4009 _defineTypeParameters();
4010 }
4011
4012 /**
4013 * Define the parameters for the given function in the scope that encloses
4014 * this function.
4015 */
4016 void defineParameters() {
4017 if (_parametersDefined) {
4018 return;
4019 }
4020 _parametersDefined = true;
4021 Scope parameterScope = enclosingScope;
4022 for (ParameterElement parameter in _functionElement.parameters) {
4023 if (!parameter.isInitializingFormal) {
4024 parameterScope.define(parameter);
4025 }
4026 }
4027 }
4028
4029 /**
4030 * Define the type parameters for the function.
4031 */
4032 void _defineTypeParameters() {
4033 Scope typeParameterScope = enclosingScope.enclosingScope;
4034 for (TypeParameterElement typeParameter
4035 in _functionElement.typeParameters) {
4036 typeParameterScope.define(typeParameter);
4037 }
4038 }
4039 }
4040
4041 /**
4042 * The scope defined by a function type alias.
4043 */
4044 class FunctionTypeScope extends EnclosedScope {
4045 final FunctionTypeAliasElement _typeElement;
4046
4047 bool _parametersDefined = false;
4048
4049 /**
4050 * Initialize a newly created scope enclosed within the [enclosingScope] that
4051 * represents the given [_typeElement].
4052 */
4053 FunctionTypeScope(Scope enclosingScope, this._typeElement)
4054 : super(new EnclosedScope(enclosingScope)) {
4055 _defineTypeParameters();
4056 }
4057
4058 /**
4059 * Define the parameters for the function type alias.
4060 */
4061 void defineParameters() {
4062 if (_parametersDefined) {
4063 return;
4064 }
4065 _parametersDefined = true;
4066 for (ParameterElement parameter in _typeElement.parameters) {
4067 define(parameter);
4068 }
4069 }
4070
4071 /**
4072 * Define the type parameters for the function type alias.
4073 */
4074 void _defineTypeParameters() {
4075 Scope typeParameterScope = enclosingScope;
4076 for (TypeParameterElement typeParameter in _typeElement.typeParameters) {
4077 typeParameterScope.define(typeParameter);
4078 }
4079 }
4080 }
4081
4082 /**
4083 * A visitor that visits ASTs and fills [UsedImportedElements]. 3859 * A visitor that visits ASTs and fills [UsedImportedElements].
4084 */ 3860 */
4085 class GatherUsedImportedElementsVisitor extends RecursiveAstVisitor { 3861 class GatherUsedImportedElementsVisitor extends RecursiveAstVisitor {
4086 final LibraryElement library; 3862 final LibraryElement library;
4087 final UsedImportedElements usedElements = new UsedImportedElements(); 3863 final UsedImportedElements usedElements = new UsedImportedElements();
4088 3864
4089 GatherUsedImportedElementsVisitor(this.library); 3865 GatherUsedImportedElementsVisitor(this.library);
4090 3866
4091 @override 3867 @override
4092 void visitExportDirective(ExportDirective node) { 3868 void visitExportDirective(ExportDirective node) {
4093 _visitDirective(node); 3869 _visitDirective(node);
4094 } 3870 }
4095 3871
4096 @override 3872 @override
4097 void visitImportDirective(ImportDirective node) { 3873 void visitImportDirective(ImportDirective node) {
4098 _visitDirective(node); 3874 _visitDirective(node);
4099 } 3875 }
4100 3876
4101 @override 3877 @override
4102 void visitLibraryDirective(LibraryDirective node) { 3878 void visitLibraryDirective(LibraryDirective node) {
4103 _visitDirective(node); 3879 _visitDirective(node);
4104 } 3880 }
4105 3881
4106 @override 3882 @override
4107 void visitSimpleIdentifier(SimpleIdentifier node) { 3883 void visitSimpleIdentifier(SimpleIdentifier node) {
4108 _visitIdentifier(node, node.staticElement); 3884 _visitIdentifier(node, node.staticElement);
4109 } 3885 }
4110 3886
4111 /** 3887 /**
3888 * If the given [identifier] is prefixed with a [PrefixElement], fill the
3889 * corresponding `UsedImportedElements.prefixMap` entry and return `true`.
3890 */
3891 bool _recordPrefixMap(SimpleIdentifier identifier, Element element) {
3892 bool recordIfTargetIsPrefixElement(Expression target) {
3893 if (target is SimpleIdentifier && target.staticElement is PrefixElement) {
3894 List<Element> prefixedElements = usedElements.prefixMap
3895 .putIfAbsent(target.staticElement, () => <Element>[]);
3896 prefixedElements.add(element);
3897 return true;
3898 }
3899 return false;
3900 }
3901 AstNode parent = identifier.parent;
3902 if (parent is MethodInvocation && parent.methodName == identifier) {
3903 return recordIfTargetIsPrefixElement(parent.target);
3904 }
3905 if (parent is PrefixedIdentifier && parent.identifier == identifier) {
3906 return recordIfTargetIsPrefixElement(parent.prefix);
3907 }
3908 return false;
3909 }
3910
3911 /**
4112 * Visit identifiers used by the given [directive]. 3912 * Visit identifiers used by the given [directive].
4113 */ 3913 */
4114 void _visitDirective(Directive directive) { 3914 void _visitDirective(Directive directive) {
4115 directive.documentationComment?.accept(this); 3915 directive.documentationComment?.accept(this);
4116 directive.metadata.accept(this); 3916 directive.metadata.accept(this);
4117 } 3917 }
4118 3918
4119 void _visitIdentifier(SimpleIdentifier identifier, Element element) { 3919 void _visitIdentifier(SimpleIdentifier identifier, Element element) {
4120 if (element == null) { 3920 if (element == null) {
4121 return; 3921 return;
(...skipping 28 matching lines...) Expand all
4150 if (containingLibrary == null) { 3950 if (containingLibrary == null) {
4151 return; 3951 return;
4152 } 3952 }
4153 // Ignore if a local element. 3953 // Ignore if a local element.
4154 if (library == containingLibrary) { 3954 if (library == containingLibrary) {
4155 return; 3955 return;
4156 } 3956 }
4157 // Remember the element. 3957 // Remember the element.
4158 usedElements.elements.add(element); 3958 usedElements.elements.add(element);
4159 } 3959 }
4160
4161 /**
4162 * If the given [identifier] is prefixed with a [PrefixElement], fill the
4163 * corresponding `UsedImportedElements.prefixMap` entry and return `true`.
4164 */
4165 bool _recordPrefixMap(SimpleIdentifier identifier, Element element) {
4166 bool recordIfTargetIsPrefixElement(Expression target) {
4167 if (target is SimpleIdentifier && target.staticElement is PrefixElement) {
4168 List<Element> prefixedElements = usedElements.prefixMap
4169 .putIfAbsent(target.staticElement, () => <Element>[]);
4170 prefixedElements.add(element);
4171 return true;
4172 }
4173 return false;
4174 }
4175 AstNode parent = identifier.parent;
4176 if (parent is MethodInvocation && parent.methodName == identifier) {
4177 return recordIfTargetIsPrefixElement(parent.target);
4178 }
4179 if (parent is PrefixedIdentifier && parent.identifier == identifier) {
4180 return recordIfTargetIsPrefixElement(parent.prefix);
4181 }
4182 return false;
4183 }
4184 } 3960 }
4185 3961
4186 /** 3962 /**
4187 * An [AstVisitor] that fills [UsedLocalElements]. 3963 * An [AstVisitor] that fills [UsedLocalElements].
4188 */ 3964 */
4189 class GatherUsedLocalElementsVisitor extends RecursiveAstVisitor { 3965 class GatherUsedLocalElementsVisitor extends RecursiveAstVisitor {
4190 final UsedLocalElements usedElements = new UsedLocalElements(); 3966 final UsedLocalElements usedElements = new UsedLocalElements();
4191 3967
4192 final LibraryElement _enclosingLibrary; 3968 final LibraryElement _enclosingLibrary;
4193 ClassElement _enclosingClass; 3969 ClassElement _enclosingClass;
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
4415 // Find to-do comments 4191 // Find to-do comments
4416 new ToDoFinder(errorReporter).findIn(unit); 4192 new ToDoFinder(errorReporter).findIn(unit);
4417 // pub analysis 4193 // pub analysis
4418 // TODO(danrubel/jwren) Commented out until bugs in the pub verifier are 4194 // TODO(danrubel/jwren) Commented out until bugs in the pub verifier are
4419 // fixed 4195 // fixed
4420 // unit.accept(new PubVerifier(context, errorReporter)); 4196 // unit.accept(new PubVerifier(context, errorReporter));
4421 } 4197 }
4422 } 4198 }
4423 4199
4424 /** 4200 /**
4425 * Instances of the class `ImplicitLabelScope` represent the scope statements
4426 * that can be the target of unlabeled break and continue statements.
4427 */
4428 class ImplicitLabelScope {
4429 /**
4430 * The implicit label scope associated with the top level of a function.
4431 */
4432 static const ImplicitLabelScope ROOT = const ImplicitLabelScope._(null, null);
4433
4434 /**
4435 * The implicit label scope enclosing this implicit label scope.
4436 */
4437 final ImplicitLabelScope outerScope;
4438
4439 /**
4440 * The statement that acts as a target for break and/or continue statements
4441 * at this scoping level.
4442 */
4443 final Statement statement;
4444
4445 /**
4446 * Private constructor.
4447 */
4448 const ImplicitLabelScope._(this.outerScope, this.statement);
4449
4450 /**
4451 * Get the statement which should be the target of an unlabeled `break` or
4452 * `continue` statement, or `null` if there is no appropriate target.
4453 */
4454 Statement getTarget(bool isContinue) {
4455 if (outerScope == null) {
4456 // This scope represents the toplevel of a function body, so it doesn't
4457 // match either break or continue.
4458 return null;
4459 }
4460 if (isContinue && statement is SwitchStatement) {
4461 return outerScope.getTarget(isContinue);
4462 }
4463 return statement;
4464 }
4465
4466 /**
4467 * Initialize a newly created scope to represent a switch statement or loop
4468 * nested within the current scope. [statement] is the statement associated
4469 * with the newly created scope.
4470 */
4471 ImplicitLabelScope nest(Statement statement) =>
4472 new ImplicitLabelScope._(this, statement);
4473 }
4474
4475 /**
4476 * Instances of the class `ImportsVerifier` visit all of the referenced librarie s in the source code 4201 * Instances of the class `ImportsVerifier` visit all of the referenced librarie s in the source code
4477 * verifying that all of the imports are used, otherwise a [HintCode.UNUSED_IMPO RT] hint is 4202 * verifying that all of the imports are used, otherwise a [HintCode.UNUSED_IMPO RT] hint is
4478 * generated with [generateUnusedImportHints]. 4203 * generated with [generateUnusedImportHints].
4479 * 4204 *
4480 * Additionally, [generateDuplicateImportHints] generates [HintCode.DUPLICATE_IM PORT] hints and 4205 * Additionally, [generateDuplicateImportHints] generates [HintCode.DUPLICATE_IM PORT] hints and
4481 * [HintCode.UNUSED_SHOWN_NAME] hints. 4206 * [HintCode.UNUSED_SHOWN_NAME] hints.
4482 * 4207 *
4483 * While this class does not yet have support for an "Organize Imports" action, this logic built up 4208 * While this class does not yet have support for an "Organize Imports" action, this logic built up
4484 * in this class could be used for such an action in the future. 4209 * in this class could be used for such an action in the future.
4485 */ 4210 */
(...skipping 1674 matching lines...) Expand 10 before | Expand all | Expand 10 after
6160 NOT_INIT, 5885 NOT_INIT,
6161 INIT_IN_DECLARATION, 5886 INIT_IN_DECLARATION,
6162 INIT_IN_FIELD_FORMAL, 5887 INIT_IN_FIELD_FORMAL,
6163 INIT_IN_INITIALIZERS 5888 INIT_IN_INITIALIZERS
6164 ]; 5889 ];
6165 5890
6166 const INIT_STATE(String name, int ordinal) : super(name, ordinal); 5891 const INIT_STATE(String name, int ordinal) : super(name, ordinal);
6167 } 5892 }
6168 5893
6169 /** 5894 /**
6170 * Instances of the class `LabelScope` represent a scope in which a single label is defined.
6171 */
6172 class LabelScope {
6173 /**
6174 * The label scope enclosing this label scope.
6175 */
6176 final LabelScope _outerScope;
6177
6178 /**
6179 * The label defined in this scope.
6180 */
6181 final String _label;
6182
6183 /**
6184 * The element to which the label resolves.
6185 */
6186 final LabelElement element;
6187
6188 /**
6189 * The AST node to which the label resolves.
6190 */
6191 final AstNode node;
6192
6193 /**
6194 * Initialize a newly created scope to represent the label [_label].
6195 * [_outerScope] is the scope enclosing the new label scope. [node] is the
6196 * AST node the label resolves to. [element] is the element the label
6197 * resolves to.
6198 */
6199 LabelScope(this._outerScope, this._label, this.node, this.element);
6200
6201 /**
6202 * Return the LabelScope which defines [targetLabel], or `null` if it is not
6203 * defined in this scope.
6204 */
6205 LabelScope lookup(String targetLabel) {
6206 if (_label == targetLabel) {
6207 return this;
6208 } else if (_outerScope != null) {
6209 return _outerScope.lookup(targetLabel);
6210 } else {
6211 return null;
6212 }
6213 }
6214 }
6215
6216 /**
6217 * Instances of the class `LibraryImportScope` represent the scope containing al l of the names
6218 * available from imported libraries.
6219 */
6220 class LibraryImportScope extends Scope {
6221 /**
6222 * The element representing the library in which this scope is enclosed.
6223 */
6224 final LibraryElement _definingLibrary;
6225
6226 /**
6227 * The listener that is to be informed when an error is encountered.
6228 */
6229 @override
6230 final AnalysisErrorListener errorListener;
6231
6232 /**
6233 * A list of the namespaces representing the names that are available in this scope from imported
6234 * libraries.
6235 */
6236 List<Namespace> _importedNamespaces;
6237
6238 /**
6239 * Initialize a newly created scope representing the names imported into the g iven library.
6240 *
6241 * @param definingLibrary the element representing the library that imports th e names defined in
6242 * this scope
6243 * @param errorListener the listener that is to be informed when an error is e ncountered
6244 */
6245 LibraryImportScope(this._definingLibrary, this.errorListener) {
6246 _createImportedNamespaces();
6247 }
6248
6249 @override
6250 void define(Element element) {
6251 if (!Scope.isPrivateName(element.displayName)) {
6252 super.define(element);
6253 }
6254 }
6255
6256 @override
6257 Source getSource(AstNode node) {
6258 Source source = super.getSource(node);
6259 if (source == null) {
6260 source = _definingLibrary.definingCompilationUnit.source;
6261 }
6262 return source;
6263 }
6264
6265 @override
6266 Element internalLookup(
6267 Identifier identifier, String name, LibraryElement referencingLibrary) {
6268 Element foundElement = localLookup(name, referencingLibrary);
6269 if (foundElement != null) {
6270 return foundElement;
6271 }
6272 for (int i = 0; i < _importedNamespaces.length; i++) {
6273 Namespace nameSpace = _importedNamespaces[i];
6274 Element element = nameSpace.get(name);
6275 if (element != null) {
6276 if (foundElement == null) {
6277 foundElement = element;
6278 } else if (!identical(foundElement, element)) {
6279 foundElement = MultiplyDefinedElementImpl.fromElements(
6280 _definingLibrary.context, foundElement, element);
6281 }
6282 }
6283 }
6284 if (foundElement is MultiplyDefinedElementImpl) {
6285 foundElement = _removeSdkElements(
6286 identifier, name, foundElement as MultiplyDefinedElementImpl);
6287 }
6288 if (foundElement is MultiplyDefinedElementImpl) {
6289 String foundEltName = foundElement.displayName;
6290 List<Element> conflictingMembers = foundElement.conflictingElements;
6291 int count = conflictingMembers.length;
6292 List<String> libraryNames = new List<String>(count);
6293 for (int i = 0; i < count; i++) {
6294 libraryNames[i] = _getLibraryName(conflictingMembers[i]);
6295 }
6296 libraryNames.sort();
6297 errorListener.onError(new AnalysisError(
6298 getSource(identifier),
6299 identifier.offset,
6300 identifier.length,
6301 StaticWarningCode.AMBIGUOUS_IMPORT, [
6302 foundEltName,
6303 StringUtilities.printListOfQuotedNames(libraryNames)
6304 ]));
6305 return foundElement;
6306 }
6307 if (foundElement != null) {
6308 defineNameWithoutChecking(name, foundElement);
6309 }
6310 return foundElement;
6311 }
6312
6313 /**
6314 * Create all of the namespaces associated with the libraries imported into th is library. The
6315 * names are not added to this scope, but are stored for later reference.
6316 *
6317 * @param definingLibrary the element representing the library that imports th e libraries for
6318 * which namespaces will be created
6319 */
6320 void _createImportedNamespaces() {
6321 NamespaceBuilder builder = new NamespaceBuilder();
6322 List<ImportElement> imports = _definingLibrary.imports;
6323 int count = imports.length;
6324 _importedNamespaces = new List<Namespace>(count);
6325 for (int i = 0; i < count; i++) {
6326 _importedNamespaces[i] =
6327 builder.createImportNamespaceForDirective(imports[i]);
6328 }
6329 }
6330
6331 /**
6332 * Returns the name of the library that defines given element.
6333 *
6334 * @param element the element to get library name
6335 * @return the name of the library that defines given element
6336 */
6337 String _getLibraryName(Element element) {
6338 if (element == null) {
6339 return StringUtilities.EMPTY;
6340 }
6341 LibraryElement library = element.library;
6342 if (library == null) {
6343 return StringUtilities.EMPTY;
6344 }
6345 List<ImportElement> imports = _definingLibrary.imports;
6346 int count = imports.length;
6347 for (int i = 0; i < count; i++) {
6348 if (identical(imports[i].importedLibrary, library)) {
6349 return library.definingCompilationUnit.displayName;
6350 }
6351 }
6352 List<String> indirectSources = new List<String>();
6353 for (int i = 0; i < count; i++) {
6354 LibraryElement importedLibrary = imports[i].importedLibrary;
6355 if (importedLibrary != null) {
6356 for (LibraryElement exportedLibrary
6357 in importedLibrary.exportedLibraries) {
6358 if (identical(exportedLibrary, library)) {
6359 indirectSources
6360 .add(importedLibrary.definingCompilationUnit.displayName);
6361 }
6362 }
6363 }
6364 }
6365 int indirectCount = indirectSources.length;
6366 StringBuffer buffer = new StringBuffer();
6367 buffer.write(library.definingCompilationUnit.displayName);
6368 if (indirectCount > 0) {
6369 buffer.write(" (via ");
6370 if (indirectCount > 1) {
6371 indirectSources.sort();
6372 buffer.write(StringUtilities.printListOfQuotedNames(indirectSources));
6373 } else {
6374 buffer.write(indirectSources[0]);
6375 }
6376 buffer.write(")");
6377 }
6378 return buffer.toString();
6379 }
6380
6381 /**
6382 * Given a collection of elements (captured by the [foundElement]) that the
6383 * [identifier] (with the given [name]) resolved to, remove from the list all
6384 * of the names defined in the SDK and return the element(s) that remain.
6385 */
6386 Element _removeSdkElements(Identifier identifier, String name,
6387 MultiplyDefinedElementImpl foundElement) {
6388 List<Element> conflictingElements = foundElement.conflictingElements;
6389 List<Element> nonSdkElements = new List<Element>();
6390 Element sdkElement = null;
6391 for (Element member in conflictingElements) {
6392 if (member.library.isInSdk) {
6393 sdkElement = member;
6394 } else {
6395 nonSdkElements.add(member);
6396 }
6397 }
6398 if (sdkElement != null && nonSdkElements.length > 0) {
6399 String sdkLibName = _getLibraryName(sdkElement);
6400 String otherLibName = _getLibraryName(nonSdkElements[0]);
6401 errorListener.onError(new AnalysisError(
6402 getSource(identifier),
6403 identifier.offset,
6404 identifier.length,
6405 StaticWarningCode.CONFLICTING_DART_IMPORT,
6406 [name, sdkLibName, otherLibName]));
6407 }
6408 if (nonSdkElements.length == conflictingElements.length) {
6409 // None of the members were removed
6410 return foundElement;
6411 } else if (nonSdkElements.length == 1) {
6412 // All but one member was removed
6413 return nonSdkElements[0];
6414 } else if (nonSdkElements.length == 0) {
6415 // All members were removed
6416 AnalysisEngine.instance.logger
6417 .logInformation("Multiply defined SDK element: $foundElement");
6418 return foundElement;
6419 }
6420 return new MultiplyDefinedElementImpl(
6421 _definingLibrary.context, nonSdkElements);
6422 }
6423 }
6424
6425 /**
6426 * Instances of the class `LibraryScope` implement a scope containing all of the names defined
6427 * in a given library.
6428 */
6429 class LibraryScope extends EnclosedScope {
6430 /**
6431 * Initialize a newly created scope representing the names defined in the give n library.
6432 *
6433 * @param definingLibrary the element representing the library represented by this scope
6434 * @param errorListener the listener that is to be informed when an error is e ncountered
6435 */
6436 LibraryScope(
6437 LibraryElement definingLibrary, AnalysisErrorListener errorListener)
6438 : super(new LibraryImportScope(definingLibrary, errorListener)) {
6439 _defineTopLevelNames(definingLibrary);
6440 }
6441
6442 @override
6443 AnalysisError getErrorForDuplicate(Element existing, Element duplicate) {
6444 if (existing is PrefixElement) {
6445 // TODO(scheglov) consider providing actual 'nameOffset' from the
6446 // synthetic accessor
6447 int offset = duplicate.nameOffset;
6448 if (duplicate is PropertyAccessorElement) {
6449 PropertyAccessorElement accessor = duplicate;
6450 if (accessor.isSynthetic) {
6451 offset = accessor.variable.nameOffset;
6452 }
6453 }
6454 return new AnalysisError(
6455 duplicate.source,
6456 offset,
6457 duplicate.nameLength,
6458 CompileTimeErrorCode.PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER,
6459 [existing.displayName]);
6460 }
6461 return super.getErrorForDuplicate(existing, duplicate);
6462 }
6463
6464 /**
6465 * Add to this scope all of the public top-level names that are defined in the given compilation
6466 * unit.
6467 *
6468 * @param compilationUnit the compilation unit defining the top-level names to be added to this
6469 * scope
6470 */
6471 void _defineLocalNames(CompilationUnitElement compilationUnit) {
6472 for (PropertyAccessorElement element in compilationUnit.accessors) {
6473 define(element);
6474 }
6475 for (ClassElement element in compilationUnit.enums) {
6476 define(element);
6477 }
6478 for (FunctionElement element in compilationUnit.functions) {
6479 define(element);
6480 }
6481 for (FunctionTypeAliasElement element
6482 in compilationUnit.functionTypeAliases) {
6483 define(element);
6484 }
6485 for (ClassElement element in compilationUnit.types) {
6486 define(element);
6487 }
6488 }
6489
6490 /**
6491 * Add to this scope all of the names that are explicitly defined in the given library.
6492 *
6493 * @param definingLibrary the element representing the library that defines th e names in this
6494 * scope
6495 */
6496 void _defineTopLevelNames(LibraryElement definingLibrary) {
6497 for (PrefixElement prefix in definingLibrary.prefixes) {
6498 define(prefix);
6499 }
6500 _defineLocalNames(definingLibrary.definingCompilationUnit);
6501 for (CompilationUnitElement compilationUnit in definingLibrary.parts) {
6502 _defineLocalNames(compilationUnit);
6503 }
6504 }
6505 }
6506
6507 /**
6508 * This class is used to replace uses of `HashMap<String, ExecutableElement>` 5895 * This class is used to replace uses of `HashMap<String, ExecutableElement>`
6509 * which are not as performant as this class. 5896 * which are not as performant as this class.
6510 */ 5897 */
6511 class MemberMap { 5898 class MemberMap {
6512 /** 5899 /**
6513 * The current size of this map. 5900 * The current size of this map.
6514 */ 5901 */
6515 int _size = 0; 5902 int _size = 0;
6516 5903
6517 /** 5904 /**
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
6658 /** 6045 /**
6659 * Initializes [keys] and [values]. 6046 * Initializes [keys] and [values].
6660 */ 6047 */
6661 void _initArrays(int initialCapacity) { 6048 void _initArrays(int initialCapacity) {
6662 _keys = new List<String>(initialCapacity); 6049 _keys = new List<String>(initialCapacity);
6663 _values = new List<ExecutableElement>(initialCapacity); 6050 _values = new List<ExecutableElement>(initialCapacity);
6664 } 6051 }
6665 } 6052 }
6666 6053
6667 /** 6054 /**
6668 * Instances of the class `Namespace` implement a mapping of identifiers to the elements
6669 * represented by those identifiers. Namespaces are the building blocks for scop es.
6670 */
6671 class Namespace {
6672 /**
6673 * An empty namespace.
6674 */
6675 static Namespace EMPTY = new Namespace(new HashMap<String, Element>());
6676
6677 /**
6678 * A table mapping names that are defined in this namespace to the element rep resenting the thing
6679 * declared with that name.
6680 */
6681 final HashMap<String, Element> _definedNames;
6682
6683 /**
6684 * Initialize a newly created namespace to have the given defined names.
6685 *
6686 * @param definedNames the mapping from names that are defined in this namespa ce to the
6687 * corresponding elements
6688 */
6689 Namespace(this._definedNames);
6690
6691 /**
6692 * Return a table containing the same mappings as those defined by this namesp ace.
6693 *
6694 * @return a table containing the same mappings as those defined by this names pace
6695 */
6696 Map<String, Element> get definedNames => _definedNames;
6697
6698 /**
6699 * Return the element in this namespace that is available to the containing sc ope using the given
6700 * name.
6701 *
6702 * @param name the name used to reference the
6703 * @return the element represented by the given identifier
6704 */
6705 Element get(String name) => _definedNames[name];
6706 }
6707
6708 /**
6709 * Instances of the class `NamespaceBuilder` are used to build a `Namespace`. Na mespace
6710 * builders are thread-safe and re-usable.
6711 */
6712 class NamespaceBuilder {
6713 /**
6714 * Create a namespace representing the export namespace of the given [ExportEl ement].
6715 *
6716 * @param element the export element whose export namespace is to be created
6717 * @return the export namespace that was created
6718 */
6719 Namespace createExportNamespaceForDirective(ExportElement element) {
6720 LibraryElement exportedLibrary = element.exportedLibrary;
6721 if (exportedLibrary == null) {
6722 //
6723 // The exported library will be null if the URI does not reference a valid
6724 // library.
6725 //
6726 return Namespace.EMPTY;
6727 }
6728 HashMap<String, Element> exportedNames = _getExportMapping(exportedLibrary);
6729 exportedNames = _applyCombinators(exportedNames, element.combinators);
6730 return new Namespace(exportedNames);
6731 }
6732
6733 /**
6734 * Create a namespace representing the export namespace of the given library.
6735 *
6736 * @param library the library whose export namespace is to be created
6737 * @return the export namespace that was created
6738 */
6739 Namespace createExportNamespaceForLibrary(LibraryElement library) {
6740 HashMap<String, Element> exportedNames = _getExportMapping(library);
6741 return new Namespace(exportedNames);
6742 }
6743
6744 /**
6745 * Create a namespace representing the import namespace of the given library.
6746 *
6747 * @param library the library whose import namespace is to be created
6748 * @return the import namespace that was created
6749 */
6750 Namespace createImportNamespaceForDirective(ImportElement element) {
6751 LibraryElement importedLibrary = element.importedLibrary;
6752 if (importedLibrary == null) {
6753 //
6754 // The imported library will be null if the URI does not reference a valid
6755 // library.
6756 //
6757 return Namespace.EMPTY;
6758 }
6759 HashMap<String, Element> exportedNames = _getExportMapping(importedLibrary);
6760 exportedNames = _applyCombinators(exportedNames, element.combinators);
6761 exportedNames = _applyPrefix(exportedNames, element.prefix);
6762 return new Namespace(exportedNames);
6763 }
6764
6765 /**
6766 * Create a namespace representing the public namespace of the given library.
6767 *
6768 * @param library the library whose public namespace is to be created
6769 * @return the public namespace that was created
6770 */
6771 Namespace createPublicNamespaceForLibrary(LibraryElement library) {
6772 HashMap<String, Element> definedNames = new HashMap<String, Element>();
6773 _addPublicNames(definedNames, library.definingCompilationUnit);
6774 for (CompilationUnitElement compilationUnit in library.parts) {
6775 _addPublicNames(definedNames, compilationUnit);
6776 }
6777 return new Namespace(definedNames);
6778 }
6779
6780 /**
6781 * Add all of the names in the given namespace to the given mapping table.
6782 *
6783 * @param definedNames the mapping table to which the names in the given names pace are to be added
6784 * @param namespace the namespace containing the names to be added to this nam espace
6785 */
6786 void _addAllFromNamespace(
6787 Map<String, Element> definedNames, Namespace namespace) {
6788 if (namespace != null) {
6789 definedNames.addAll(namespace.definedNames);
6790 }
6791 }
6792
6793 /**
6794 * Add the given element to the given mapping table if it has a publicly visib le name.
6795 *
6796 * @param definedNames the mapping table to which the public name is to be add ed
6797 * @param element the element to be added
6798 */
6799 void _addIfPublic(Map<String, Element> definedNames, Element element) {
6800 String name = element.name;
6801 if (name != null && !Scope.isPrivateName(name)) {
6802 definedNames[name] = element;
6803 }
6804 }
6805
6806 /**
6807 * Add to the given mapping table all of the public top-level names that are d efined in the given
6808 * compilation unit.
6809 *
6810 * @param definedNames the mapping table to which the public names are to be a dded
6811 * @param compilationUnit the compilation unit defining the top-level names to be added to this
6812 * namespace
6813 */
6814 void _addPublicNames(Map<String, Element> definedNames,
6815 CompilationUnitElement compilationUnit) {
6816 for (PropertyAccessorElement element in compilationUnit.accessors) {
6817 _addIfPublic(definedNames, element);
6818 }
6819 for (ClassElement element in compilationUnit.enums) {
6820 _addIfPublic(definedNames, element);
6821 }
6822 for (FunctionElement element in compilationUnit.functions) {
6823 _addIfPublic(definedNames, element);
6824 }
6825 for (FunctionTypeAliasElement element
6826 in compilationUnit.functionTypeAliases) {
6827 _addIfPublic(definedNames, element);
6828 }
6829 for (ClassElement element in compilationUnit.types) {
6830 _addIfPublic(definedNames, element);
6831 }
6832 }
6833
6834 /**
6835 * Apply the given combinators to all of the names in the given mapping table.
6836 *
6837 * @param definedNames the mapping table to which the namespace operations are to be applied
6838 * @param combinators the combinators to be applied
6839 */
6840 HashMap<String, Element> _applyCombinators(
6841 HashMap<String, Element> definedNames,
6842 List<NamespaceCombinator> combinators) {
6843 for (NamespaceCombinator combinator in combinators) {
6844 if (combinator is HideElementCombinator) {
6845 definedNames = _hide(definedNames, combinator.hiddenNames);
6846 } else if (combinator is ShowElementCombinator) {
6847 definedNames = _show(definedNames, combinator.shownNames);
6848 } else {
6849 // Internal error.
6850 AnalysisEngine.instance.logger
6851 .logError("Unknown type of combinator: ${combinator.runtimeType}");
6852 }
6853 }
6854 return definedNames;
6855 }
6856
6857 /**
6858 * Apply the given prefix to all of the names in the table of defined names.
6859 *
6860 * @param definedNames the names that were defined before this operation
6861 * @param prefixElement the element defining the prefix to be added to the nam es
6862 */
6863 HashMap<String, Element> _applyPrefix(
6864 HashMap<String, Element> definedNames, PrefixElement prefixElement) {
6865 if (prefixElement != null) {
6866 String prefix = prefixElement.name;
6867 HashMap<String, Element> newNames = new HashMap<String, Element>();
6868 definedNames.forEach((String name, Element element) {
6869 newNames["$prefix.$name"] = element;
6870 });
6871 return newNames;
6872 } else {
6873 return definedNames;
6874 }
6875 }
6876
6877 /**
6878 * Create a mapping table representing the export namespace of the given libra ry.
6879 *
6880 * @param library the library whose public namespace is to be created
6881 * @param visitedElements a set of libraries that do not need to be visited wh en processing the
6882 * export directives of the given library because all of the names de fined by them will
6883 * be added by another library
6884 * @return the mapping table that was created
6885 */
6886 HashMap<String, Element> _computeExportMapping(
6887 LibraryElement library, HashSet<LibraryElement> visitedElements) {
6888 visitedElements.add(library);
6889 try {
6890 HashMap<String, Element> definedNames = new HashMap<String, Element>();
6891 for (ExportElement element in library.exports) {
6892 LibraryElement exportedLibrary = element.exportedLibrary;
6893 if (exportedLibrary != null &&
6894 !visitedElements.contains(exportedLibrary)) {
6895 //
6896 // The exported library will be null if the URI does not reference a
6897 // valid library.
6898 //
6899 HashMap<String, Element> exportedNames =
6900 _computeExportMapping(exportedLibrary, visitedElements);
6901 exportedNames = _applyCombinators(exportedNames, element.combinators);
6902 definedNames.addAll(exportedNames);
6903 }
6904 }
6905 _addAllFromNamespace(
6906 definedNames,
6907 (library.context as InternalAnalysisContext)
6908 .getPublicNamespace(library));
6909 return definedNames;
6910 } finally {
6911 visitedElements.remove(library);
6912 }
6913 }
6914
6915 HashMap<String, Element> _getExportMapping(LibraryElement library) {
6916 if (library is LibraryElementImpl) {
6917 if (library.exportNamespace != null) {
6918 return library.exportNamespace.definedNames;
6919 } else {
6920 HashMap<String, Element> exportMapping =
6921 _computeExportMapping(library, new HashSet<LibraryElement>());
6922 library.exportNamespace = new Namespace(exportMapping);
6923 return exportMapping;
6924 }
6925 }
6926 return _computeExportMapping(library, new HashSet<LibraryElement>());
6927 }
6928
6929 /**
6930 * Return a new map of names which has all the names from [definedNames]
6931 * with exception of [hiddenNames].
6932 */
6933 Map<String, Element> _hide(
6934 HashMap<String, Element> definedNames, List<String> hiddenNames) {
6935 HashMap<String, Element> newNames =
6936 new HashMap<String, Element>.from(definedNames);
6937 for (String name in hiddenNames) {
6938 newNames.remove(name);
6939 newNames.remove("$name=");
6940 }
6941 return newNames;
6942 }
6943
6944 /**
6945 * Return a new map of names which has only [shownNames] from [definedNames].
6946 */
6947 HashMap<String, Element> _show(
6948 HashMap<String, Element> definedNames, List<String> shownNames) {
6949 HashMap<String, Element> newNames = new HashMap<String, Element>();
6950 for (String name in shownNames) {
6951 Element element = definedNames[name];
6952 if (element != null) {
6953 newNames[name] = element;
6954 }
6955 String setterName = "$name=";
6956 element = definedNames[setterName];
6957 if (element != null) {
6958 newNames[setterName] = element;
6959 }
6960 }
6961 return newNames;
6962 }
6963 }
6964
6965 /**
6966 * Instances of the class `OverrideVerifier` visit all of the declarations in a compilation 6055 * Instances of the class `OverrideVerifier` visit all of the declarations in a compilation
6967 * unit to verify that if they have an override annotation it is being used corr ectly. 6056 * unit to verify that if they have an override annotation it is being used corr ectly.
6968 */ 6057 */
6969 class OverrideVerifier extends RecursiveAstVisitor<Object> { 6058 class OverrideVerifier extends RecursiveAstVisitor<Object> {
6970 /** 6059 /**
6971 * The error reporter used to report errors. 6060 * The error reporter used to report errors.
6972 */ 6061 */
6973 final ErrorReporter _errorReporter; 6062 final ErrorReporter _errorReporter;
6974 6063
6975 /** 6064 /**
(...skipping 2494 matching lines...) Expand 10 before | Expand all | Expand 10 after
9470 if (onError != null) { 8559 if (onError != null) {
9471 onError(errorCode, argumentList, 8560 onError(errorCode, argumentList,
9472 [unnamedParameterCount, positionalArgumentCount]); 8561 [unnamedParameterCount, positionalArgumentCount]);
9473 } 8562 }
9474 } 8563 }
9475 return resolvedParameters; 8564 return resolvedParameters;
9476 } 8565 }
9477 } 8566 }
9478 8567
9479 /** 8568 /**
9480 * The abstract class `Scope` defines the behavior common to name scopes used by the resolver
9481 * to determine which names are visible at any given point in the code.
9482 */
9483 abstract class Scope {
9484 /**
9485 * The prefix used to mark an identifier as being private to its library.
9486 */
9487 static int PRIVATE_NAME_PREFIX = 0x5F;
9488
9489 /**
9490 * The suffix added to the declared name of a setter when looking up the sette r. Used to
9491 * disambiguate between a getter and a setter that have the same name.
9492 */
9493 static String SETTER_SUFFIX = "=";
9494
9495 /**
9496 * The name used to look up the method used to implement the unary minus opera tor. Used to
9497 * disambiguate between the unary and binary operators.
9498 */
9499 static String UNARY_MINUS = "unary-";
9500
9501 /**
9502 * A table mapping names that are defined in this scope to the element represe nting the thing
9503 * declared with that name.
9504 */
9505 HashMap<String, Element> _definedNames = new HashMap<String, Element>();
9506
9507 /**
9508 * A flag indicating whether there are any names defined in this scope.
9509 */
9510 bool _hasName = false;
9511
9512 /**
9513 * Return the scope in which this scope is lexically enclosed.
9514 *
9515 * @return the scope in which this scope is lexically enclosed
9516 */
9517 Scope get enclosingScope => null;
9518
9519 /**
9520 * Return the listener that is to be informed when an error is encountered.
9521 *
9522 * @return the listener that is to be informed when an error is encountered
9523 */
9524 AnalysisErrorListener get errorListener;
9525
9526 /**
9527 * Add the given element to this scope. If there is already an element with th e given name defined
9528 * in this scope, then an error will be generated and the original element wil l continue to be
9529 * mapped to the name. If there is an element with the given name in an enclos ing scope, then a
9530 * warning will be generated but the given element will hide the inherited ele ment.
9531 *
9532 * @param element the element to be added to this scope
9533 */
9534 void define(Element element) {
9535 String name = _getName(element);
9536 if (name != null && !name.isEmpty) {
9537 if (_definedNames.containsKey(name)) {
9538 errorListener
9539 .onError(getErrorForDuplicate(_definedNames[name], element));
9540 } else {
9541 _definedNames[name] = element;
9542 _hasName = true;
9543 }
9544 }
9545 }
9546
9547 /**
9548 * Add the given element to this scope without checking for duplication or hid ing.
9549 *
9550 * @param name the name of the element to be added
9551 * @param element the element to be added to this scope
9552 */
9553 void defineNameWithoutChecking(String name, Element element) {
9554 _definedNames[name] = element;
9555 _hasName = true;
9556 }
9557
9558 /**
9559 * Add the given element to this scope without checking for duplication or hid ing.
9560 *
9561 * @param element the element to be added to this scope
9562 */
9563 void defineWithoutChecking(Element element) {
9564 _definedNames[_getName(element)] = element;
9565 _hasName = true;
9566 }
9567
9568 /**
9569 * Return the error code to be used when reporting that a name being defined l ocally conflicts
9570 * with another element of the same name in the local scope.
9571 *
9572 * @param existing the first element to be declared with the conflicting name
9573 * @param duplicate another element declared with the conflicting name
9574 * @return the error code used to report duplicate names within a scope
9575 */
9576 AnalysisError getErrorForDuplicate(Element existing, Element duplicate) {
9577 // TODO(brianwilkerson) Customize the error message based on the types of
9578 // elements that share the same name.
9579 // TODO(jwren) There are 4 error codes for duplicate, but only 1 is being
9580 // generated.
9581 Source source = duplicate.source;
9582 return new AnalysisError(source, duplicate.nameOffset, duplicate.nameLength,
9583 CompileTimeErrorCode.DUPLICATE_DEFINITION, [existing.displayName]);
9584 }
9585
9586 /**
9587 * Return the source that contains the given identifier, or the source associa ted with this scope
9588 * if the source containing the identifier could not be determined.
9589 *
9590 * @param identifier the identifier whose source is to be returned
9591 * @return the source that contains the given identifier
9592 */
9593 Source getSource(AstNode node) {
9594 CompilationUnit unit = node.getAncestor((node) => node is CompilationUnit);
9595 if (unit != null) {
9596 CompilationUnitElement unitElement = unit.element;
9597 if (unitElement != null) {
9598 return unitElement.source;
9599 }
9600 }
9601 return null;
9602 }
9603
9604 /**
9605 * Return the element with which the given name is associated, or `null` if th e name is not
9606 * defined within this scope.
9607 *
9608 * @param identifier the identifier node to lookup element for, used to report correct kind of a
9609 * problem and associate problem with
9610 * @param name the name associated with the element to be returned
9611 * @param referencingLibrary the library that contains the reference to the na me, used to
9612 * implement library-level privacy
9613 * @return the element with which the given name is associated
9614 */
9615 Element internalLookup(
9616 Identifier identifier, String name, LibraryElement referencingLibrary);
9617
9618 /**
9619 * Return the element with which the given name is associated, or `null` if th e name is not
9620 * defined within this scope. This method only returns elements that are direc tly defined within
9621 * this scope, not elements that are defined in an enclosing scope.
9622 *
9623 * @param name the name associated with the element to be returned
9624 * @param referencingLibrary the library that contains the reference to the na me, used to
9625 * implement library-level privacy
9626 * @return the element with which the given name is associated
9627 */
9628 Element localLookup(String name, LibraryElement referencingLibrary) {
9629 if (_hasName) {
9630 return _definedNames[name];
9631 }
9632 return null;
9633 }
9634
9635 /**
9636 * Return the element with which the given identifier is associated, or `null` if the name
9637 * is not defined within this scope.
9638 *
9639 * @param identifier the identifier associated with the element to be returned
9640 * @param referencingLibrary the library that contains the reference to the na me, used to
9641 * implement library-level privacy
9642 * @return the element with which the given identifier is associated
9643 */
9644 Element lookup(Identifier identifier, LibraryElement referencingLibrary) =>
9645 internalLookup(identifier, identifier.name, referencingLibrary);
9646
9647 /**
9648 * Return the name that will be used to look up the given element.
9649 *
9650 * @param element the element whose look-up name is to be returned
9651 * @return the name that will be used to look up the given element
9652 */
9653 String _getName(Element element) {
9654 if (element is MethodElement) {
9655 MethodElement method = element;
9656 if (method.name == "-" && method.parameters.length == 0) {
9657 return UNARY_MINUS;
9658 }
9659 }
9660 return element.name;
9661 }
9662
9663 /**
9664 * Return `true` if the given name is a library-private name.
9665 *
9666 * @param name the name being tested
9667 * @return `true` if the given name is a library-private name
9668 */
9669 static bool isPrivateName(String name) =>
9670 name != null && StringUtilities.startsWithChar(name, PRIVATE_NAME_PREFIX);
9671 }
9672
9673 /**
9674 * The abstract class `ScopedVisitor` maintains name and label scopes as an AST structure is 8569 * The abstract class `ScopedVisitor` maintains name and label scopes as an AST structure is
9675 * being visited. 8570 * being visited.
9676 */ 8571 */
9677 abstract class ScopedVisitor extends UnifyingAstVisitor<Object> { 8572 abstract class ScopedVisitor extends UnifyingAstVisitor<Object> {
9678 /** 8573 /**
9679 * The element for the library containing the compilation unit being visited. 8574 * The element for the library containing the compilation unit being visited.
9680 */ 8575 */
9681 final LibraryElement definingLibrary; 8576 final LibraryElement definingLibrary;
9682 8577
9683 /** 8578 /**
(...skipping 1126 matching lines...) Expand 10 before | Expand all | Expand 10 after
10810 * 9705 *
10811 * @param element the element whose type might have been overridden 9706 * @param element the element whose type might have been overridden
10812 * @param type the overridden type of the given element 9707 * @param type the overridden type of the given element
10813 */ 9708 */
10814 void setType(VariableElement element, DartType type) { 9709 void setType(VariableElement element, DartType type) {
10815 _overridenTypes[element] = type; 9710 _overridenTypes[element] = type;
10816 } 9711 }
10817 } 9712 }
10818 9713
10819 /** 9714 /**
10820 * Instances of the class `TypeParameterScope` implement the scope defined by th e type
10821 * parameters in a class.
10822 */
10823 class TypeParameterScope extends EnclosedScope {
10824 /**
10825 * Initialize a newly created scope enclosed within another scope.
10826 *
10827 * @param enclosingScope the scope in which this scope is lexically enclosed
10828 * @param typeElement the element representing the type represented by this sc ope
10829 */
10830 TypeParameterScope(Scope enclosingScope, ClassElement typeElement)
10831 : super(enclosingScope) {
10832 if (typeElement == null) {
10833 throw new IllegalArgumentException("class element cannot be null");
10834 }
10835 _defineTypeParameters(typeElement);
10836 }
10837
10838 /**
10839 * Define the type parameters for the class.
10840 *
10841 * @param typeElement the element representing the type represented by this sc ope
10842 */
10843 void _defineTypeParameters(ClassElement typeElement) {
10844 for (TypeParameterElement typeParameter in typeElement.typeParameters) {
10845 define(typeParameter);
10846 }
10847 }
10848 }
10849
10850 /**
10851 * Instances of the class `TypePromotionManager` manage the ability to promote t ypes of local 9715 * Instances of the class `TypePromotionManager` manage the ability to promote t ypes of local
10852 * variables and formal parameters from their declared types based on control fl ow. 9716 * variables and formal parameters from their declared types based on control fl ow.
10853 */ 9717 */
10854 class TypePromotionManager { 9718 class TypePromotionManager {
10855 /** 9719 /**
10856 * The current promotion scope, or `null` if no scope has been entered. 9720 * The current promotion scope, or `null` if no scope has been entered.
10857 */ 9721 */
10858 TypePromotionManager_TypePromoteScope currentScope; 9722 TypePromotionManager_TypePromoteScope currentScope;
10859 9723
10860 /** 9724 /**
(...skipping 2231 matching lines...) Expand 10 before | Expand all | Expand 10 after
13092 nonFields.add(node); 11956 nonFields.add(node);
13093 return null; 11957 return null;
13094 } 11958 }
13095 11959
13096 @override 11960 @override
13097 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this); 11961 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this);
13098 11962
13099 @override 11963 @override
13100 Object visitWithClause(WithClause node) => null; 11964 Object visitWithClause(WithClause node) => null;
13101 } 11965 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/dart/resolver/scope.dart ('k') | pkg/analyzer/test/src/task/dart_work_manager_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698