| 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 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |