| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library engine.resolver.element_resolver; | 5 library analyzer.src.generated.element_resolver; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 | 8 |
| 9 import 'ast.dart'; | 9 import 'package:analyzer/dart/ast/ast.dart'; |
| 10 import 'element.dart'; | 10 import 'package:analyzer/dart/ast/syntactic_entity.dart'; |
| 11 import 'engine.dart'; | 11 import 'package:analyzer/dart/ast/token.dart'; |
| 12 import 'error.dart'; | 12 import 'package:analyzer/dart/ast/visitor.dart'; |
| 13 import 'resolver.dart'; | 13 import 'package:analyzer/dart/element/element.dart'; |
| 14 import 'scanner.dart' as sc; | 14 import 'package:analyzer/dart/element/type.dart'; |
| 15 import 'utilities_dart.dart'; | 15 import 'package:analyzer/error/error.dart'; |
| 16 import 'package:analyzer/src/dart/ast/ast.dart' |
| 17 show |
| 18 ChildEntities, |
| 19 IdentifierImpl, |
| 20 PrefixedIdentifierImpl, |
| 21 SimpleIdentifierImpl; |
| 22 import 'package:analyzer/src/dart/ast/token.dart'; |
| 23 import 'package:analyzer/src/dart/element/element.dart'; |
| 24 import 'package:analyzer/src/dart/element/type.dart'; |
| 25 import 'package:analyzer/src/error/codes.dart'; |
| 26 import 'package:analyzer/src/generated/engine.dart'; |
| 27 import 'package:analyzer/src/generated/resolver.dart'; |
| 16 | 28 |
| 17 /** | 29 /** |
| 18 * An object used by instances of [ResolverVisitor] to resolve references within | 30 * An object used by instances of [ResolverVisitor] to resolve references within |
| 19 * the AST structure to the elements being referenced. The requirements for the | 31 * the AST structure to the elements being referenced. The requirements for the |
| 20 * element resolver are: | 32 * element resolver are: |
| 21 * | 33 * |
| 22 * 1. Every [SimpleIdentifier] should be resolved to the element to which it | 34 * 1. Every [SimpleIdentifier] should be resolved to the element to which it |
| 23 * refers. Specifically: | 35 * refers. Specifically: |
| 24 * * An identifier within the declaration of that name should resolve to the | 36 * * An identifier within the declaration of that name should resolve to the |
| 25 * element being declared. | 37 * element being declared. |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 bool _enableStrictCallChecks = false; | 107 bool _enableStrictCallChecks = false; |
| 96 | 108 |
| 97 /** | 109 /** |
| 98 * The type representing the type 'dynamic'. | 110 * The type representing the type 'dynamic'. |
| 99 */ | 111 */ |
| 100 DartType _dynamicType; | 112 DartType _dynamicType; |
| 101 | 113 |
| 102 /** | 114 /** |
| 103 * The type representing the type 'type'. | 115 * The type representing the type 'type'. |
| 104 */ | 116 */ |
| 105 DartType _typeType; | 117 InterfaceType _typeType; |
| 106 | 118 |
| 107 /** | 119 /** |
| 108 * A utility class for the resolver to answer the question of "what are my | 120 * A utility class for the resolver to answer the question of "what are my |
| 109 * subtypes?". | 121 * subtypes?". |
| 110 */ | 122 */ |
| 111 SubtypeManager _subtypeManager; | 123 SubtypeManager _subtypeManager; |
| 112 | 124 |
| 113 /** | 125 /** |
| 114 * The object keeping track of which elements have had their types promoted. | 126 * The object keeping track of which elements have had their types promoted. |
| 115 */ | 127 */ |
| (...skipping 21 matching lines...) Expand all Loading... |
| 137 bool get isInConstConstructor { | 149 bool get isInConstConstructor { |
| 138 ExecutableElement function = _resolver.enclosingFunction; | 150 ExecutableElement function = _resolver.enclosingFunction; |
| 139 if (function is ConstructorElement) { | 151 if (function is ConstructorElement) { |
| 140 return function.isConst; | 152 return function.isConst; |
| 141 } | 153 } |
| 142 return false; | 154 return false; |
| 143 } | 155 } |
| 144 | 156 |
| 145 @override | 157 @override |
| 146 Object visitAssignmentExpression(AssignmentExpression node) { | 158 Object visitAssignmentExpression(AssignmentExpression node) { |
| 147 sc.Token operator = node.operator; | 159 Token operator = node.operator; |
| 148 sc.TokenType operatorType = operator.type; | 160 TokenType operatorType = operator.type; |
| 149 if (operatorType != sc.TokenType.EQ && | 161 if (operatorType != TokenType.AMPERSAND_AMPERSAND_EQ && |
| 150 operatorType != sc.TokenType.QUESTION_QUESTION_EQ) { | 162 operatorType != TokenType.BAR_BAR_EQ && |
| 163 operatorType != TokenType.EQ && |
| 164 operatorType != TokenType.QUESTION_QUESTION_EQ) { |
| 151 operatorType = _operatorFromCompoundAssignment(operatorType); | 165 operatorType = _operatorFromCompoundAssignment(operatorType); |
| 152 Expression leftHandSide = node.leftHandSide; | 166 Expression leftHandSide = node.leftHandSide; |
| 153 if (leftHandSide != null) { | 167 if (leftHandSide != null) { |
| 154 String methodName = operatorType.lexeme; | 168 String methodName = operatorType.lexeme; |
| 155 DartType staticType = _getStaticType(leftHandSide); | 169 DartType staticType = _getStaticType(leftHandSide); |
| 156 MethodElement staticMethod = | 170 MethodElement staticMethod = |
| 157 _lookUpMethod(leftHandSide, staticType, methodName); | 171 _lookUpMethod(leftHandSide, staticType, methodName); |
| 158 node.staticElement = staticMethod; | 172 node.staticElement = staticMethod; |
| 159 DartType propagatedType = _getPropagatedType(leftHandSide); | 173 DartType propagatedType = _getPropagatedType(leftHandSide); |
| 160 MethodElement propagatedMethod = | 174 MethodElement propagatedMethod = |
| (...skipping 15 matching lines...) Expand all Loading... |
| 176 operator, | 190 operator, |
| 177 [methodName, propagatedType.displayName]); | 191 [methodName, propagatedType.displayName]); |
| 178 } | 192 } |
| 179 } | 193 } |
| 180 } | 194 } |
| 181 return null; | 195 return null; |
| 182 } | 196 } |
| 183 | 197 |
| 184 @override | 198 @override |
| 185 Object visitBinaryExpression(BinaryExpression node) { | 199 Object visitBinaryExpression(BinaryExpression node) { |
| 186 sc.Token operator = node.operator; | 200 Token operator = node.operator; |
| 187 if (operator.isUserDefinableOperator) { | 201 if (operator.isUserDefinableOperator) { |
| 188 _resolveBinaryExpression(node, operator.lexeme); | 202 _resolveBinaryExpression(node, operator.lexeme); |
| 189 } else if (operator.type == sc.TokenType.BANG_EQ) { | 203 } else if (operator.type == TokenType.BANG_EQ) { |
| 190 _resolveBinaryExpression(node, sc.TokenType.EQ_EQ.lexeme); | 204 _resolveBinaryExpression(node, TokenType.EQ_EQ.lexeme); |
| 191 } | 205 } |
| 192 return null; | 206 return null; |
| 193 } | 207 } |
| 194 | 208 |
| 195 @override | 209 @override |
| 196 Object visitBreakStatement(BreakStatement node) { | 210 Object visitBreakStatement(BreakStatement node) { |
| 197 node.target = _lookupBreakOrContinueTarget(node, node.label, false); | 211 node.target = _lookupBreakOrContinueTarget(node, node.label, false); |
| 198 return null; | 212 return null; |
| 199 } | 213 } |
| 200 | 214 |
| 201 @override | 215 @override |
| 202 Object visitClassDeclaration(ClassDeclaration node) { | 216 Object visitClassDeclaration(ClassDeclaration node) { |
| 203 setMetadata(node.element, node); | 217 resolveMetadata(node); |
| 204 return null; | 218 return null; |
| 205 } | 219 } |
| 206 | 220 |
| 207 @override | 221 @override |
| 208 Object visitClassTypeAlias(ClassTypeAlias node) { | 222 Object visitClassTypeAlias(ClassTypeAlias node) { |
| 209 setMetadata(node.element, node); | 223 resolveMetadata(node); |
| 210 return null; | 224 return null; |
| 211 } | 225 } |
| 212 | 226 |
| 213 @override | 227 @override |
| 214 Object visitCommentReference(CommentReference node) { | 228 Object visitCommentReference(CommentReference node) { |
| 215 Identifier identifier = node.identifier; | 229 Identifier identifier = node.identifier; |
| 216 if (identifier is SimpleIdentifier) { | 230 if (identifier is SimpleIdentifier) { |
| 217 SimpleIdentifier simpleIdentifier = identifier; | 231 Element element = _resolveSimpleIdentifier(identifier); |
| 218 Element element = _resolveSimpleIdentifier(simpleIdentifier); | |
| 219 if (element == null) { | 232 if (element == null) { |
| 220 // | 233 // |
| 221 // This might be a reference to an imported name that is missing the | 234 // This might be a reference to an imported name that is missing the |
| 222 // prefix. | 235 // prefix. |
| 223 // | 236 // |
| 224 element = _findImportWithoutPrefix(simpleIdentifier); | 237 element = _findImportWithoutPrefix(identifier); |
| 225 if (element is MultiplyDefinedElement) { | 238 if (element is MultiplyDefinedElement) { |
| 226 // TODO(brianwilkerson) Report this error? | 239 // TODO(brianwilkerson) Report this error? |
| 227 element = null; | 240 element = null; |
| 228 } | 241 } |
| 229 } | 242 } |
| 230 if (element == null) { | 243 if (element == null) { |
| 231 // TODO(brianwilkerson) Report this error? | 244 // TODO(brianwilkerson) Report this error? |
| 232 // resolver.reportError( | 245 // resolver.reportError( |
| 233 // StaticWarningCode.UNDEFINED_IDENTIFIER, | 246 // StaticWarningCode.UNDEFINED_IDENTIFIER, |
| 234 // simpleIdentifier, | 247 // simpleIdentifier, |
| 235 // simpleIdentifier.getName()); | 248 // simpleIdentifier.getName()); |
| 236 } else { | 249 } else { |
| 237 if (element.library == null || element.library != _definingLibrary) { | 250 if (element.library == null || element.library != _definingLibrary) { |
| 238 // TODO(brianwilkerson) Report this error? | 251 // TODO(brianwilkerson) Report this error? |
| 239 } | 252 } |
| 240 simpleIdentifier.staticElement = element; | 253 identifier.staticElement = element; |
| 241 if (node.newKeyword != null) { | 254 if (node.newKeyword != null) { |
| 242 if (element is ClassElement) { | 255 if (element is ClassElement) { |
| 243 ConstructorElement constructor = element.unnamedConstructor; | 256 ConstructorElement constructor = element.unnamedConstructor; |
| 244 if (constructor == null) { | 257 if (constructor == null) { |
| 245 // TODO(brianwilkerson) Report this error. | 258 // TODO(brianwilkerson) Report this error. |
| 246 } else { | 259 } else { |
| 247 simpleIdentifier.staticElement = constructor; | 260 identifier.staticElement = constructor; |
| 248 } | 261 } |
| 249 } else { | 262 } else { |
| 250 // TODO(brianwilkerson) Report this error. | 263 // TODO(brianwilkerson) Report this error. |
| 251 } | 264 } |
| 252 } | 265 } |
| 253 } | 266 } |
| 254 } else if (identifier is PrefixedIdentifier) { | 267 } else if (identifier is PrefixedIdentifier) { |
| 255 PrefixedIdentifier prefixedIdentifier = identifier; | 268 SimpleIdentifier prefix = identifier.prefix; |
| 256 SimpleIdentifier prefix = prefixedIdentifier.prefix; | 269 SimpleIdentifier name = identifier.identifier; |
| 257 SimpleIdentifier name = prefixedIdentifier.identifier; | |
| 258 Element element = _resolveSimpleIdentifier(prefix); | 270 Element element = _resolveSimpleIdentifier(prefix); |
| 259 if (element == null) { | 271 if (element == null) { |
| 260 // resolver.reportError(StaticWarningCode.UNDEFINED_IDENTIFIER, prefix, p
refix.getName()); | 272 // resolver.reportError(StaticWarningCode.UNDEFINED_IDENTIFIER, prefix, p
refix.getName()); |
| 261 } else { | 273 } else { |
| 274 prefix.staticElement = element; |
| 262 if (element is PrefixElement) { | 275 if (element is PrefixElement) { |
| 263 prefix.staticElement = element; | |
| 264 // TODO(brianwilkerson) Report this error? | 276 // TODO(brianwilkerson) Report this error? |
| 265 element = _resolver.nameScope.lookup(identifier, _definingLibrary); | 277 element = _resolver.nameScope.lookup(identifier, _definingLibrary); |
| 266 name.staticElement = element; | 278 name.staticElement = element; |
| 267 return null; | 279 return null; |
| 268 } | 280 } |
| 269 LibraryElement library = element.library; | 281 LibraryElement library = element.library; |
| 270 if (library == null) { | 282 if (library == null) { |
| 271 // TODO(brianwilkerson) We need to understand how the library could | 283 // TODO(brianwilkerson) We need to understand how the library could |
| 272 // ever be null. | 284 // ever be null. |
| 273 AnalysisEngine.instance.logger | 285 AnalysisEngine.instance.logger |
| 274 .logError("Found element with null library: ${element.name}"); | 286 .logError("Found element with null library: ${element.name}"); |
| 275 } else if (library != _definingLibrary) { | 287 } else if (library != _definingLibrary) { |
| 276 // TODO(brianwilkerson) Report this error. | 288 // TODO(brianwilkerson) Report this error. |
| 277 } | 289 } |
| 278 name.staticElement = element; | |
| 279 if (node.newKeyword == null) { | 290 if (node.newKeyword == null) { |
| 280 if (element is ClassElement) { | 291 if (element is ClassElement) { |
| 281 Element memberElement = | 292 Element memberElement = |
| 282 _lookupGetterOrMethod(element.type, name.name); | 293 _lookupGetterOrMethod(element.type, name.name); |
| 283 if (memberElement == null) { | 294 if (memberElement == null) { |
| 284 memberElement = element.getNamedConstructor(name.name); | 295 memberElement = element.getNamedConstructor(name.name); |
| 285 if (memberElement == null) { | 296 if (memberElement == null) { |
| 286 memberElement = _lookUpSetter(prefix, element.type, name.name); | 297 memberElement = _lookUpSetter(prefix, element.type, name.name); |
| 287 } | 298 } |
| 288 } | 299 } |
| 289 if (memberElement == null) { | 300 if (memberElement == null) { |
| 290 // reportGetterOrSetterNotFound(prefixedIdentifier, name, element.g
etDisplayName()); | 301 // reportGetterOrSetterNotFound(identifier, name, element.getDispla
yName()); |
| 291 } else { | 302 } else { |
| 292 name.staticElement = memberElement; | 303 name.staticElement = memberElement; |
| 293 } | 304 } |
| 294 } else { | 305 } else { |
| 295 // TODO(brianwilkerson) Report this error. | 306 // TODO(brianwilkerson) Report this error. |
| 296 } | 307 } |
| 297 } else { | 308 } else { |
| 298 if (element is ClassElement) { | 309 if (element is ClassElement) { |
| 299 ConstructorElement constructor = | 310 ConstructorElement constructor = |
| 300 element.getNamedConstructor(name.name); | 311 element.getNamedConstructor(name.name); |
| 301 if (constructor == null) { | 312 if (constructor == null) { |
| 302 // TODO(brianwilkerson) Report this error. | 313 // TODO(brianwilkerson) Report this error. |
| 303 } else { | 314 } else { |
| 304 name.staticElement = constructor; | 315 name.staticElement = constructor; |
| 305 } | 316 } |
| 306 } else { | 317 } else { |
| 307 // TODO(brianwilkerson) Report this error. | 318 // TODO(brianwilkerson) Report this error. |
| 308 } | 319 } |
| 309 } | 320 } |
| 310 } | 321 } |
| 311 } | 322 } |
| 312 return null; | 323 return null; |
| 313 } | 324 } |
| 314 | 325 |
| 315 @override | 326 @override |
| 316 Object visitConstructorDeclaration(ConstructorDeclaration node) { | 327 Object visitConstructorDeclaration(ConstructorDeclaration node) { |
| 317 super.visitConstructorDeclaration(node); | 328 super.visitConstructorDeclaration(node); |
| 318 ConstructorElement element = node.element; | 329 ConstructorElement element = node.element; |
| 319 if (element is ConstructorElementImpl) { | 330 if (element is ConstructorElementImpl) { |
| 320 ConstructorElementImpl constructorElement = element; | |
| 321 ConstructorName redirectedNode = node.redirectedConstructor; | 331 ConstructorName redirectedNode = node.redirectedConstructor; |
| 322 if (redirectedNode != null) { | 332 if (redirectedNode != null) { |
| 323 // set redirected factory constructor | 333 // set redirected factory constructor |
| 324 ConstructorElement redirectedElement = redirectedNode.staticElement; | 334 ConstructorElement redirectedElement = redirectedNode.staticElement; |
| 325 constructorElement.redirectedConstructor = redirectedElement; | 335 element.redirectedConstructor = redirectedElement; |
| 326 } else { | 336 } else { |
| 327 // set redirected generative constructor | 337 // set redirected generative constructor |
| 328 for (ConstructorInitializer initializer in node.initializers) { | 338 for (ConstructorInitializer initializer in node.initializers) { |
| 329 if (initializer is RedirectingConstructorInvocation) { | 339 if (initializer is RedirectingConstructorInvocation) { |
| 330 ConstructorElement redirectedElement = initializer.staticElement; | 340 ConstructorElement redirectedElement = initializer.staticElement; |
| 331 constructorElement.redirectedConstructor = redirectedElement; | 341 element.redirectedConstructor = redirectedElement; |
| 332 } | 342 } |
| 333 } | 343 } |
| 334 } | 344 } |
| 335 setMetadata(constructorElement, node); | 345 resolveMetadata(node); |
| 336 } | 346 } |
| 337 return null; | 347 return null; |
| 338 } | 348 } |
| 339 | 349 |
| 340 @override | 350 @override |
| 341 Object visitConstructorFieldInitializer(ConstructorFieldInitializer node) { | 351 Object visitConstructorFieldInitializer(ConstructorFieldInitializer node) { |
| 342 SimpleIdentifier fieldName = node.fieldName; | 352 SimpleIdentifier fieldName = node.fieldName; |
| 343 ClassElement enclosingClass = _resolver.enclosingClass; | 353 ClassElement enclosingClass = _resolver.enclosingClass; |
| 344 FieldElement fieldElement = enclosingClass.getField(fieldName.name); | 354 FieldElement fieldElement = enclosingClass.getField(fieldName.name); |
| 345 fieldName.staticElement = fieldElement; | 355 fieldName.staticElement = fieldElement; |
| 346 return null; | 356 return null; |
| 347 } | 357 } |
| 348 | 358 |
| 349 @override | 359 @override |
| 350 Object visitConstructorName(ConstructorName node) { | 360 Object visitConstructorName(ConstructorName node) { |
| 351 DartType type = node.type.type; | 361 DartType type = node.type.type; |
| 352 if (type != null && type.isDynamic) { | 362 if (type != null && type.isDynamic) { |
| 353 return null; | 363 // Nothing to do. |
| 354 } else if (type is! InterfaceType) { | 364 } else if (type is InterfaceType) { |
| 365 // look up ConstructorElement |
| 366 ConstructorElement constructor; |
| 367 SimpleIdentifier name = node.name; |
| 368 if (name == null) { |
| 369 constructor = type.lookUpConstructor(null, _definingLibrary); |
| 370 } else { |
| 371 constructor = type.lookUpConstructor(name.name, _definingLibrary); |
| 372 name.staticElement = constructor; |
| 373 } |
| 374 node.staticElement = constructor; |
| 375 } else { |
| 355 // TODO(brianwilkerson) Report these errors. | 376 // TODO(brianwilkerson) Report these errors. |
| 356 // ASTNode parent = node.getParent(); | 377 // ASTNode parent = node.getParent(); |
| 357 // if (parent instanceof InstanceCreationExpression) { | 378 // if (parent instanceof InstanceCreationExpression) { |
| 358 // if (((InstanceCreationExpression) parent).isConst()) { | 379 // if (((InstanceCreationExpression) parent).isConst()) { |
| 359 // // CompileTimeErrorCode.CONST_WITH_NON_TYPE | 380 // // CompileTimeErrorCode.CONST_WITH_NON_TYPE |
| 360 // } else { | 381 // } else { |
| 361 // // StaticWarningCode.NEW_WITH_NON_TYPE | 382 // // StaticWarningCode.NEW_WITH_NON_TYPE |
| 362 // } | 383 // } |
| 363 // } else { | 384 // } else { |
| 364 // // This is part of a redirecting factory constructor; not sure which e
rror code to use | 385 // // This is part of a redirecting factory constructor; not sure which e
rror code to use |
| 365 // } | 386 // } |
| 366 return null; | |
| 367 } | 387 } |
| 368 // look up ConstructorElement | |
| 369 ConstructorElement constructor; | |
| 370 SimpleIdentifier name = node.name; | |
| 371 InterfaceType interfaceType = type as InterfaceType; | |
| 372 if (name == null) { | |
| 373 constructor = interfaceType.lookUpConstructor(null, _definingLibrary); | |
| 374 } else { | |
| 375 constructor = | |
| 376 interfaceType.lookUpConstructor(name.name, _definingLibrary); | |
| 377 name.staticElement = constructor; | |
| 378 } | |
| 379 node.staticElement = constructor; | |
| 380 return null; | 388 return null; |
| 381 } | 389 } |
| 382 | 390 |
| 383 @override | 391 @override |
| 384 Object visitContinueStatement(ContinueStatement node) { | 392 Object visitContinueStatement(ContinueStatement node) { |
| 385 node.target = _lookupBreakOrContinueTarget(node, node.label, true); | 393 node.target = _lookupBreakOrContinueTarget(node, node.label, true); |
| 386 return null; | 394 return null; |
| 387 } | 395 } |
| 388 | 396 |
| 389 @override | 397 @override |
| 390 Object visitDeclaredIdentifier(DeclaredIdentifier node) { | 398 Object visitDeclaredIdentifier(DeclaredIdentifier node) { |
| 391 setMetadata(node.element, node); | 399 resolveMetadata(node); |
| 392 return null; | 400 return null; |
| 393 } | 401 } |
| 394 | 402 |
| 395 @override | 403 @override |
| 396 Object visitEnumDeclaration(EnumDeclaration node) { | 404 Object visitEnumDeclaration(EnumDeclaration node) { |
| 397 setMetadata(node.element, node); | 405 resolveMetadata(node); |
| 398 return null; | 406 return null; |
| 399 } | 407 } |
| 400 | 408 |
| 401 @override | 409 @override |
| 402 Object visitExportDirective(ExportDirective node) { | 410 Object visitExportDirective(ExportDirective node) { |
| 403 ExportElement exportElement = node.element; | 411 ExportElement exportElement = node.element; |
| 404 if (exportElement != null) { | 412 if (exportElement != null) { |
| 405 // The element is null when the URI is invalid | 413 // The element is null when the URI is invalid |
| 406 // TODO(brianwilkerson) Figure out whether the element can ever be | 414 // TODO(brianwilkerson) Figure out whether the element can ever be |
| 407 // something other than an ExportElement | 415 // something other than an ExportElement |
| 408 _resolveCombinators(exportElement.exportedLibrary, node.combinators); | 416 _resolveCombinators(exportElement.exportedLibrary, node.combinators); |
| 409 setMetadata(exportElement, node); | 417 resolveMetadata(node); |
| 410 } | 418 } |
| 411 return null; | 419 return null; |
| 412 } | 420 } |
| 413 | 421 |
| 414 @override | 422 @override |
| 415 Object visitFieldFormalParameter(FieldFormalParameter node) { | 423 Object visitFieldFormalParameter(FieldFormalParameter node) { |
| 416 _setMetadataForParameter(node.element, node); | 424 _resolveMetadataForParameter(node); |
| 417 return super.visitFieldFormalParameter(node); | 425 return super.visitFieldFormalParameter(node); |
| 418 } | 426 } |
| 419 | 427 |
| 420 @override | 428 @override |
| 421 Object visitFunctionDeclaration(FunctionDeclaration node) { | 429 Object visitFunctionDeclaration(FunctionDeclaration node) { |
| 422 setMetadata(node.element, node); | 430 resolveMetadata(node); |
| 423 return null; | 431 return null; |
| 424 } | 432 } |
| 425 | 433 |
| 426 @override | 434 @override |
| 427 Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { | 435 Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { |
| 428 // TODO(brianwilkerson) Can we ever resolve the function being invoked? | 436 Expression function = node.function; |
| 429 Expression expression = node.function; | 437 DartType staticInvokeType = _instantiateGenericMethod( |
| 430 if (expression is FunctionExpression) { | 438 function.staticType, node.typeArguments, node); |
| 431 FunctionExpression functionExpression = expression; | 439 DartType propagatedInvokeType = _instantiateGenericMethod( |
| 432 ExecutableElement functionElement = functionExpression.element; | 440 function.propagatedType, node.typeArguments, node); |
| 433 ArgumentList argumentList = node.argumentList; | 441 |
| 434 List<ParameterElement> parameters = | 442 node.staticInvokeType = staticInvokeType; |
| 435 _resolveArgumentsToFunction(false, argumentList, functionElement); | 443 node.propagatedInvokeType = |
| 436 if (parameters != null) { | 444 _propagatedInvokeTypeIfBetter(propagatedInvokeType, staticInvokeType); |
| 437 argumentList.correspondingStaticParameters = parameters; | 445 |
| 438 } | 446 List<ParameterElement> parameters = |
| 447 _computeCorrespondingParameters(node.argumentList, staticInvokeType); |
| 448 if (parameters != null) { |
| 449 node.argumentList.correspondingStaticParameters = parameters; |
| 450 } |
| 451 |
| 452 parameters = _computeCorrespondingParameters( |
| 453 node.argumentList, propagatedInvokeType); |
| 454 if (parameters != null) { |
| 455 node.argumentList.correspondingPropagatedParameters = parameters; |
| 439 } | 456 } |
| 440 return null; | 457 return null; |
| 441 } | 458 } |
| 442 | 459 |
| 443 @override | 460 @override |
| 444 Object visitFunctionTypeAlias(FunctionTypeAlias node) { | 461 Object visitFunctionTypeAlias(FunctionTypeAlias node) { |
| 445 setMetadata(node.element, node); | 462 resolveMetadata(node); |
| 446 return null; | 463 return null; |
| 447 } | 464 } |
| 448 | 465 |
| 449 @override | 466 @override |
| 450 Object visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) { | 467 Object visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) { |
| 451 _setMetadataForParameter(node.element, node); | 468 _resolveMetadataForParameter(node); |
| 452 return null; | 469 return null; |
| 453 } | 470 } |
| 454 | 471 |
| 455 @override | 472 @override |
| 456 Object visitImportDirective(ImportDirective node) { | 473 Object visitImportDirective(ImportDirective node) { |
| 457 SimpleIdentifier prefixNode = node.prefix; | 474 SimpleIdentifier prefixNode = node.prefix; |
| 458 if (prefixNode != null) { | 475 if (prefixNode != null) { |
| 459 String prefixName = prefixNode.name; | 476 String prefixName = prefixNode.name; |
| 460 for (PrefixElement prefixElement in _definingLibrary.prefixes) { | 477 List<PrefixElement> prefixes = _definingLibrary.prefixes; |
| 478 int count = prefixes.length; |
| 479 for (int i = 0; i < count; i++) { |
| 480 PrefixElement prefixElement = prefixes[i]; |
| 461 if (prefixElement.displayName == prefixName) { | 481 if (prefixElement.displayName == prefixName) { |
| 462 prefixNode.staticElement = prefixElement; | 482 prefixNode.staticElement = prefixElement; |
| 463 break; | 483 break; |
| 464 } | 484 } |
| 465 } | 485 } |
| 466 } | 486 } |
| 467 ImportElement importElement = node.element; | 487 ImportElement importElement = node.element; |
| 468 if (importElement != null) { | 488 if (importElement != null) { |
| 469 // The element is null when the URI is invalid | 489 // The element is null when the URI is invalid |
| 470 LibraryElement library = importElement.importedLibrary; | 490 LibraryElement library = importElement.importedLibrary; |
| 471 if (library != null) { | 491 if (library != null) { |
| 472 _resolveCombinators(library, node.combinators); | 492 _resolveCombinators(library, node.combinators); |
| 473 } | 493 } |
| 474 setMetadata(importElement, node); | 494 resolveMetadata(node); |
| 475 } | 495 } |
| 476 return null; | 496 return null; |
| 477 } | 497 } |
| 478 | 498 |
| 479 @override | 499 @override |
| 480 Object visitIndexExpression(IndexExpression node) { | 500 Object visitIndexExpression(IndexExpression node) { |
| 481 Expression target = node.realTarget; | 501 Expression target = node.realTarget; |
| 482 DartType staticType = _getStaticType(target); | 502 DartType staticType = _getStaticType(target); |
| 483 DartType propagatedType = _getPropagatedType(target); | 503 DartType propagatedType = _getPropagatedType(target); |
| 484 String getterMethodName = sc.TokenType.INDEX.lexeme; | 504 String getterMethodName = TokenType.INDEX.lexeme; |
| 485 String setterMethodName = sc.TokenType.INDEX_EQ.lexeme; | 505 String setterMethodName = TokenType.INDEX_EQ.lexeme; |
| 486 bool isInGetterContext = node.inGetterContext(); | 506 bool isInGetterContext = node.inGetterContext(); |
| 487 bool isInSetterContext = node.inSetterContext(); | 507 bool isInSetterContext = node.inSetterContext(); |
| 488 if (isInGetterContext && isInSetterContext) { | 508 if (isInGetterContext && isInSetterContext) { |
| 489 // lookup setter | 509 // lookup setter |
| 490 MethodElement setterStaticMethod = | 510 MethodElement setterStaticMethod = |
| 491 _lookUpMethod(target, staticType, setterMethodName); | 511 _lookUpMethod(target, staticType, setterMethodName); |
| 492 MethodElement setterPropagatedMethod = | 512 MethodElement setterPropagatedMethod = |
| 493 _lookUpMethod(target, propagatedType, setterMethodName); | 513 _lookUpMethod(target, propagatedType, setterMethodName); |
| 494 // set setter element | 514 // set setter element |
| 495 node.staticElement = setterStaticMethod; | 515 node.staticElement = setterStaticMethod; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 557 List<ParameterElement> parameters = _resolveArgumentsToFunction( | 577 List<ParameterElement> parameters = _resolveArgumentsToFunction( |
| 558 node.isConst, argumentList, invokedConstructor); | 578 node.isConst, argumentList, invokedConstructor); |
| 559 if (parameters != null) { | 579 if (parameters != null) { |
| 560 argumentList.correspondingStaticParameters = parameters; | 580 argumentList.correspondingStaticParameters = parameters; |
| 561 } | 581 } |
| 562 return null; | 582 return null; |
| 563 } | 583 } |
| 564 | 584 |
| 565 @override | 585 @override |
| 566 Object visitLibraryDirective(LibraryDirective node) { | 586 Object visitLibraryDirective(LibraryDirective node) { |
| 567 setMetadata(node.element, node); | 587 resolveMetadata(node); |
| 568 return null; | 588 return null; |
| 569 } | 589 } |
| 570 | 590 |
| 571 @override | 591 @override |
| 572 Object visitMethodDeclaration(MethodDeclaration node) { | 592 Object visitMethodDeclaration(MethodDeclaration node) { |
| 573 setMetadata(node.element, node); | 593 resolveMetadata(node); |
| 574 return null; | 594 return null; |
| 575 } | 595 } |
| 576 | 596 |
| 577 @override | 597 @override |
| 578 Object visitMethodInvocation(MethodInvocation node) { | 598 Object visitMethodInvocation(MethodInvocation node) { |
| 579 SimpleIdentifier methodName = node.methodName; | 599 SimpleIdentifier methodName = node.methodName; |
| 580 // | 600 // |
| 581 // Synthetic identifiers have been already reported during parsing. | 601 // Synthetic identifiers have been already reported during parsing. |
| 582 // | 602 // |
| 583 if (methodName.isSynthetic) { | 603 if (methodName.isSynthetic) { |
| 584 return null; | 604 return null; |
| 585 } | 605 } |
| 586 // | 606 // |
| 587 // We have a method invocation of one of two forms: 'e.m(a1, ..., an)' or | 607 // We have a method invocation of one of two forms: 'e.m(a1, ..., an)' or |
| 588 // 'm(a1, ..., an)'. The first step is to figure out which executable is | 608 // 'm(a1, ..., an)'. The first step is to figure out which executable is |
| 589 // being invoked, using both the static and the propagated type information. | 609 // being invoked, using both the static and the propagated type information. |
| 590 // | 610 // |
| 591 Expression target = node.realTarget; | 611 Expression target = node.realTarget; |
| 592 if (target is SuperExpression && !_isSuperInValidContext(target)) { | 612 if (target is SuperExpression && !_isSuperInValidContext(target)) { |
| 593 return null; | 613 return null; |
| 594 } | 614 } |
| 595 Element staticElement; | 615 Element staticElement; |
| 596 Element propagatedElement; | 616 Element propagatedElement; |
| 597 DartType staticType = null; | |
| 598 DartType propagatedType = null; | |
| 599 if (target == null) { | 617 if (target == null) { |
| 600 staticElement = _resolveInvokedElement(methodName); | 618 staticElement = _resolveInvokedElement(methodName); |
| 601 propagatedElement = null; | 619 propagatedElement = null; |
| 602 } else if (methodName.name == FunctionElement.LOAD_LIBRARY_NAME && | 620 } else if (methodName.name == FunctionElement.LOAD_LIBRARY_NAME && |
| 603 _isDeferredPrefix(target)) { | 621 _isDeferredPrefix(target)) { |
| 604 if (node.operator.type == sc.TokenType.QUESTION_PERIOD) { | 622 if (node.operator.type == TokenType.QUESTION_PERIOD) { |
| 605 _resolver.reportErrorForNode( | 623 _resolver.errorReporter.reportErrorForNode( |
| 606 CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, | 624 CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, |
| 607 target, | 625 target, |
| 608 [(target as SimpleIdentifier).name]); | 626 [(target as SimpleIdentifier).name]); |
| 609 } | 627 } |
| 610 LibraryElement importedLibrary = _getImportedLibrary(target); | 628 LibraryElement importedLibrary = _getImportedLibrary(target); |
| 611 methodName.staticElement = importedLibrary.loadLibraryFunction; | 629 FunctionElement loadLibraryFunction = importedLibrary.loadLibraryFunction; |
| 630 methodName.staticElement = loadLibraryFunction; |
| 631 node.staticInvokeType = loadLibraryFunction.type; |
| 612 return null; | 632 return null; |
| 613 } else { | 633 } else { |
| 614 staticType = _getStaticType(target); | |
| 615 propagatedType = _getPropagatedType(target); | |
| 616 // | 634 // |
| 617 // If this method invocation is of the form 'C.m' where 'C' is a class, | 635 // If this method invocation is of the form 'C.m' where 'C' is a class, |
| 618 // then we don't call resolveInvokedElement(...) which walks up the class | 636 // then we don't call resolveInvokedElement(...) which walks up the class |
| 619 // hierarchy, instead we just look for the member in the type only. This | 637 // hierarchy, instead we just look for the member in the type only. This |
| 620 // does not apply to conditional method invocation (i.e. 'C?.m(...)'). | 638 // does not apply to conditional method invocation (i.e. 'C?.m(...)'). |
| 621 // | 639 // |
| 622 bool isConditional = node.operator.type == sc.TokenType.QUESTION_PERIOD; | 640 bool isConditional = node.operator.type == TokenType.QUESTION_PERIOD; |
| 623 ClassElementImpl typeReference = getTypeReference(target); | 641 ClassElement typeReference = getTypeReference(target); |
| 624 if (typeReference != null) { | 642 if (typeReference != null) { |
| 625 staticElement = | 643 if (node.isCascaded) { |
| 626 propagatedElement = _resolveElement(typeReference, methodName); | 644 typeReference = _typeType.element; |
| 645 } |
| 646 staticElement = _resolveElement(typeReference, methodName); |
| 627 } else { | 647 } else { |
| 648 DartType staticType = _resolver.strongMode |
| 649 ? _getStaticTypeOrFunctionType(target) |
| 650 : _getStaticType(target); |
| 651 DartType propagatedType = _getPropagatedType(target); |
| 628 staticElement = _resolveInvokedElementWithTarget( | 652 staticElement = _resolveInvokedElementWithTarget( |
| 629 target, staticType, methodName, isConditional); | 653 target, staticType, methodName, isConditional); |
| 630 propagatedElement = _resolveInvokedElementWithTarget( | 654 // If we have propagated type information use it (since it should |
| 631 target, propagatedType, methodName, isConditional); | 655 // not be redundant with the staticType). Otherwise, don't produce |
| 656 // a propagatedElement which duplicates the staticElement. |
| 657 if (propagatedType is InterfaceType) { |
| 658 propagatedElement = _resolveInvokedElementWithTarget( |
| 659 target, propagatedType, methodName, isConditional); |
| 660 } |
| 632 } | 661 } |
| 633 } | 662 } |
| 663 |
| 634 staticElement = _convertSetterToGetter(staticElement); | 664 staticElement = _convertSetterToGetter(staticElement); |
| 635 propagatedElement = _convertSetterToGetter(propagatedElement); | 665 propagatedElement = _convertSetterToGetter(propagatedElement); |
| 666 |
| 667 // |
| 668 // Given the elements, determine the type of the function we are invoking |
| 669 // |
| 670 DartType staticInvokeType = _getInvokeType(staticElement); |
| 671 methodName.staticType = staticInvokeType; |
| 672 |
| 673 DartType propagatedInvokeType = _getInvokeType(propagatedElement); |
| 674 methodName.propagatedType = |
| 675 _propagatedInvokeTypeIfBetter(propagatedInvokeType, staticInvokeType); |
| 676 |
| 677 // |
| 678 // Instantiate generic function or method if needed. |
| 679 // |
| 680 staticInvokeType = _instantiateGenericMethod( |
| 681 staticInvokeType, node.typeArguments, node.methodName); |
| 682 propagatedInvokeType = _instantiateGenericMethod( |
| 683 propagatedInvokeType, node.typeArguments, node.methodName); |
| 684 |
| 636 // | 685 // |
| 637 // Record the results. | 686 // Record the results. |
| 638 // | 687 // |
| 639 methodName.staticElement = staticElement; | 688 methodName.staticElement = staticElement; |
| 640 methodName.propagatedElement = propagatedElement; | 689 methodName.propagatedElement = propagatedElement; |
| 690 |
| 691 node.staticInvokeType = staticInvokeType; |
| 692 // |
| 693 // Store the propagated invoke type if it's more specific than the static |
| 694 // type. |
| 695 // |
| 696 // We still need to record the propagated parameter elements however, |
| 697 // as they are used in propagatedType downwards inference of lambda |
| 698 // parameters. So we don't want to clear the propagatedInvokeType variable. |
| 699 // |
| 700 node.propagatedInvokeType = |
| 701 _propagatedInvokeTypeIfBetter(propagatedInvokeType, staticInvokeType); |
| 702 |
| 641 ArgumentList argumentList = node.argumentList; | 703 ArgumentList argumentList = node.argumentList; |
| 642 if (staticElement != null) { | 704 if (staticInvokeType != null) { |
| 643 List<ParameterElement> parameters = | 705 List<ParameterElement> parameters = |
| 644 _computeCorrespondingParameters(argumentList, staticElement); | 706 _computeCorrespondingParameters(argumentList, staticInvokeType); |
| 645 if (parameters != null) { | 707 argumentList.correspondingStaticParameters = parameters; |
| 646 argumentList.correspondingStaticParameters = parameters; | |
| 647 } | |
| 648 } | 708 } |
| 649 if (propagatedElement != null) { | 709 if (propagatedInvokeType != null) { |
| 650 List<ParameterElement> parameters = | 710 List<ParameterElement> parameters = |
| 651 _computeCorrespondingParameters(argumentList, propagatedElement); | 711 _computeCorrespondingParameters(argumentList, propagatedInvokeType); |
| 652 if (parameters != null) { | 712 argumentList.correspondingPropagatedParameters = parameters; |
| 653 argumentList.correspondingPropagatedParameters = parameters; | |
| 654 } | |
| 655 } | 713 } |
| 656 // | 714 // |
| 657 // Then check for error conditions. | 715 // Then check for error conditions. |
| 658 // | 716 // |
| 659 ErrorCode errorCode = _checkForInvocationError(target, true, staticElement); | 717 ErrorCode errorCode = _checkForInvocationError(target, true, staticElement); |
| 718 if (errorCode != null && |
| 719 target is SimpleIdentifier && |
| 720 target.staticElement is PrefixElement) { |
| 721 Identifier functionName = |
| 722 new PrefixedIdentifierImpl.temp(target, methodName); |
| 723 if (_resolver.nameScope.shouldIgnoreUndefined(functionName)) { |
| 724 return null; |
| 725 } |
| 726 } |
| 660 bool generatedWithTypePropagation = false; | 727 bool generatedWithTypePropagation = false; |
| 661 if (_enableHints && errorCode == null && staticElement == null) { | 728 if (_enableHints && errorCode == null && staticElement == null) { |
| 662 // The method lookup may have failed because there were multiple | 729 // The method lookup may have failed because there were multiple |
| 663 // incompatible choices. In this case we don't want to generate a hint. | 730 // incompatible choices. In this case we don't want to generate a hint. |
| 664 errorCode = _checkForInvocationError(target, false, propagatedElement); | 731 errorCode = _checkForInvocationError(target, false, propagatedElement); |
| 665 if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_METHOD)) { | 732 if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_METHOD)) { |
| 666 ClassElement classElementContext = null; | 733 ClassElement classElementContext = null; |
| 667 if (target == null) { | 734 if (target == null) { |
| 668 classElementContext = _resolver.enclosingClass; | 735 classElementContext = _resolver.enclosingClass; |
| 669 } else { | 736 } else { |
| 670 DartType type = _getBestType(target); | 737 DartType type = _getBestType(target); |
| 671 if (type != null) { | 738 if (type != null) { |
| 672 if (type.element is ClassElement) { | 739 Element element = type.element; |
| 673 classElementContext = type.element as ClassElement; | 740 if (element is ClassElement) { |
| 741 classElementContext = element; |
| 674 } | 742 } |
| 675 } | 743 } |
| 676 } | 744 } |
| 677 if (classElementContext != null) { | 745 if (classElementContext != null) { |
| 678 _subtypeManager.ensureLibraryVisited(_definingLibrary); | 746 _subtypeManager.ensureLibraryVisited(_definingLibrary); |
| 679 HashSet<ClassElement> subtypeElements = | 747 HashSet<ClassElement> subtypeElements = |
| 680 _subtypeManager.computeAllSubtypes(classElementContext); | 748 _subtypeManager.computeAllSubtypes(classElementContext); |
| 681 for (ClassElement subtypeElement in subtypeElements) { | 749 for (ClassElement subtypeElement in subtypeElements) { |
| 682 if (subtypeElement.getMethod(methodName.name) != null) { | 750 if (subtypeElement.getMethod(methodName.name) != null) { |
| 683 errorCode = null; | 751 errorCode = null; |
| 684 } | 752 } |
| 685 } | 753 } |
| 686 } | 754 } |
| 687 } | 755 } |
| 688 generatedWithTypePropagation = true; | 756 generatedWithTypePropagation = true; |
| 689 } | 757 } |
| 690 if (errorCode == null) { | 758 if (errorCode == null) { |
| 691 return null; | 759 return null; |
| 692 } | 760 } |
| 693 if (identical( | 761 if (identical( |
| 694 errorCode, StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION) || | 762 errorCode, StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION) || |
| 695 identical(errorCode, | 763 identical(errorCode, |
| 696 CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT) || | 764 CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT) || |
| 697 identical(errorCode, StaticTypeWarningCode.UNDEFINED_FUNCTION)) { | 765 identical(errorCode, StaticTypeWarningCode.UNDEFINED_FUNCTION)) { |
| 698 _resolver.reportErrorForNode(errorCode, methodName, [methodName.name]); | 766 if (!_resolver.nameScope.shouldIgnoreUndefined(methodName)) { |
| 767 _resolver.errorReporter |
| 768 .reportErrorForNode(errorCode, methodName, [methodName.name]); |
| 769 } |
| 699 } else if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_METHOD)) { | 770 } else if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_METHOD)) { |
| 700 String targetTypeName; | 771 String targetTypeName; |
| 701 if (target == null) { | 772 if (target == null) { |
| 702 ClassElement enclosingClass = _resolver.enclosingClass; | 773 ClassElement enclosingClass = _resolver.enclosingClass; |
| 703 targetTypeName = enclosingClass.displayName; | 774 targetTypeName = enclosingClass.displayName; |
| 704 ErrorCode proxyErrorCode = (generatedWithTypePropagation | 775 ErrorCode proxyErrorCode = (generatedWithTypePropagation |
| 705 ? HintCode.UNDEFINED_METHOD | 776 ? HintCode.UNDEFINED_METHOD |
| 706 : StaticTypeWarningCode.UNDEFINED_METHOD); | 777 : StaticTypeWarningCode.UNDEFINED_METHOD); |
| 707 _recordUndefinedNode(_resolver.enclosingClass, proxyErrorCode, | 778 _recordUndefinedNode(_resolver.enclosingClass, proxyErrorCode, |
| 708 methodName, [methodName.name, targetTypeName]); | 779 methodName, [methodName.name, targetTypeName]); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 722 } | 793 } |
| 723 if (!_enableStrictCallChecks && | 794 if (!_enableStrictCallChecks && |
| 724 targetType != null && | 795 targetType != null && |
| 725 targetType.isDartCoreFunction && | 796 targetType.isDartCoreFunction && |
| 726 methodName.name == FunctionElement.CALL_METHOD_NAME) { | 797 methodName.name == FunctionElement.CALL_METHOD_NAME) { |
| 727 // TODO(brianwilkerson) Can we ever resolve the function being | 798 // TODO(brianwilkerson) Can we ever resolve the function being |
| 728 // invoked? | 799 // invoked? |
| 729 // resolveArgumentsToParameters(node.getArgumentList(), invokedFunction
); | 800 // resolveArgumentsToParameters(node.getArgumentList(), invokedFunction
); |
| 730 return null; | 801 return null; |
| 731 } | 802 } |
| 732 targetTypeName = targetType == null ? null : targetType.displayName; | 803 if (!node.isCascaded) { |
| 804 ClassElement typeReference = getTypeReference(target); |
| 805 if (typeReference != null) { |
| 806 ConstructorElement constructor = |
| 807 typeReference.getNamedConstructor(methodName.name); |
| 808 if (constructor != null) { |
| 809 _recordUndefinedNode( |
| 810 typeReference, |
| 811 StaticTypeWarningCode.UNDEFINED_METHOD_WITH_CONSTRUCTOR, |
| 812 methodName, |
| 813 [methodName.name, typeReference.name]); |
| 814 return null; |
| 815 } |
| 816 } |
| 817 } |
| 818 targetTypeName = targetType?.displayName; |
| 733 ErrorCode proxyErrorCode = (generatedWithTypePropagation | 819 ErrorCode proxyErrorCode = (generatedWithTypePropagation |
| 734 ? HintCode.UNDEFINED_METHOD | 820 ? HintCode.UNDEFINED_METHOD |
| 735 : StaticTypeWarningCode.UNDEFINED_METHOD); | 821 : StaticTypeWarningCode.UNDEFINED_METHOD); |
| 736 _recordUndefinedNode(targetType.element, proxyErrorCode, methodName, | 822 _recordUndefinedNode(targetType.element, proxyErrorCode, methodName, |
| 737 [methodName.name, targetTypeName]); | 823 [methodName.name, targetTypeName]); |
| 738 } | 824 } |
| 739 } else if (identical( | 825 } else if (identical( |
| 740 errorCode, StaticTypeWarningCode.UNDEFINED_SUPER_METHOD)) { | 826 errorCode, StaticTypeWarningCode.UNDEFINED_SUPER_METHOD)) { |
| 741 // Generate the type name. | 827 // Generate the type name. |
| 742 // The error code will never be generated via type propagation | 828 // The error code will never be generated via type propagation |
| 743 DartType targetType = _getStaticType(target); | 829 DartType getSuperType(DartType type) { |
| 744 if (targetType is InterfaceType && !targetType.isObject) { | 830 if (type is InterfaceType && !type.isObject) { |
| 745 targetType = (targetType as InterfaceType).superclass; | 831 return type.superclass; |
| 832 } |
| 833 return type; |
| 746 } | 834 } |
| 747 String targetTypeName = targetType == null ? null : targetType.name; | 835 |
| 748 _resolver.reportErrorForNode(StaticTypeWarningCode.UNDEFINED_SUPER_METHOD, | 836 DartType targetType = getSuperType(_getStaticType(target)); |
| 749 methodName, [methodName.name, targetTypeName]); | 837 String targetTypeName = targetType?.name; |
| 838 _resolver.errorReporter.reportErrorForNode( |
| 839 StaticTypeWarningCode.UNDEFINED_SUPER_METHOD, |
| 840 methodName, |
| 841 [methodName.name, targetTypeName]); |
| 750 } | 842 } |
| 751 return null; | 843 return null; |
| 752 } | 844 } |
| 753 | 845 |
| 754 @override | 846 @override |
| 755 Object visitPartDirective(PartDirective node) { | 847 Object visitPartDirective(PartDirective node) { |
| 756 setMetadata(node.element, node); | 848 resolveMetadata(node); |
| 757 return null; | 849 return null; |
| 758 } | 850 } |
| 759 | 851 |
| 760 @override | |
| 761 Object visitPartOfDirective(PartOfDirective node) { | |
| 762 setMetadata(node.element, node); | |
| 763 return null; | |
| 764 } | |
| 765 | |
| 766 @override | 852 @override |
| 767 Object visitPostfixExpression(PostfixExpression node) { | 853 Object visitPostfixExpression(PostfixExpression node) { |
| 768 Expression operand = node.operand; | 854 Expression operand = node.operand; |
| 769 String methodName = _getPostfixOperator(node); | 855 String methodName = _getPostfixOperator(node); |
| 770 DartType staticType = _getStaticType(operand); | 856 DartType staticType = _getStaticType(operand); |
| 771 MethodElement staticMethod = _lookUpMethod(operand, staticType, methodName); | 857 MethodElement staticMethod = _lookUpMethod(operand, staticType, methodName); |
| 772 node.staticElement = staticMethod; | 858 node.staticElement = staticMethod; |
| 773 DartType propagatedType = _getPropagatedType(operand); | 859 DartType propagatedType = _getPropagatedType(operand); |
| 774 MethodElement propagatedMethod = | 860 MethodElement propagatedMethod = |
| 775 _lookUpMethod(operand, propagatedType, methodName); | 861 _lookUpMethod(operand, propagatedType, methodName); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 811 identifier.staticElement = importedLibrary.loadLibraryFunction; | 897 identifier.staticElement = importedLibrary.loadLibraryFunction; |
| 812 return null; | 898 return null; |
| 813 } | 899 } |
| 814 // | 900 // |
| 815 // Check to see whether the prefix is really a prefix. | 901 // Check to see whether the prefix is really a prefix. |
| 816 // | 902 // |
| 817 Element prefixElement = prefix.staticElement; | 903 Element prefixElement = prefix.staticElement; |
| 818 if (prefixElement is PrefixElement) { | 904 if (prefixElement is PrefixElement) { |
| 819 Element element = _resolver.nameScope.lookup(node, _definingLibrary); | 905 Element element = _resolver.nameScope.lookup(node, _definingLibrary); |
| 820 if (element == null && identifier.inSetterContext()) { | 906 if (element == null && identifier.inSetterContext()) { |
| 821 element = _resolver.nameScope.lookup( | 907 Identifier setterName = new PrefixedIdentifierImpl.temp( |
| 822 new SyntheticIdentifier("${node.name}=", node), _definingLibrary); | 908 node.prefix, |
| 909 new SimpleIdentifierImpl(new StringToken(TokenType.STRING, |
| 910 "${node.identifier.name}=", node.identifier.offset - 1))); |
| 911 element = _resolver.nameScope.lookup(setterName, _definingLibrary); |
| 912 } |
| 913 if (element == null && _resolver.nameScope.shouldIgnoreUndefined(node)) { |
| 914 return null; |
| 823 } | 915 } |
| 824 if (element == null) { | 916 if (element == null) { |
| 825 if (identifier.inSetterContext()) { | 917 if (identifier.inSetterContext()) { |
| 826 _resolver.reportErrorForNode(StaticWarningCode.UNDEFINED_SETTER, | 918 _resolver.errorReporter.reportErrorForNode( |
| 827 identifier, [identifier.name, prefixElement.name]); | 919 StaticWarningCode.UNDEFINED_SETTER, |
| 828 } else if (node.parent is Annotation) { | 920 identifier, |
| 829 Annotation annotation = node.parent as Annotation; | 921 [identifier.name, prefixElement.name]); |
| 830 _resolver.reportErrorForNode( | |
| 831 CompileTimeErrorCode.INVALID_ANNOTATION, annotation); | |
| 832 return null; | 922 return null; |
| 923 } |
| 924 AstNode parent = node.parent; |
| 925 if (parent is Annotation) { |
| 926 _resolver.errorReporter.reportErrorForNode( |
| 927 CompileTimeErrorCode.INVALID_ANNOTATION, parent); |
| 833 } else { | 928 } else { |
| 834 _resolver.reportErrorForNode(StaticWarningCode.UNDEFINED_GETTER, | 929 _resolver.errorReporter.reportErrorForNode( |
| 835 identifier, [identifier.name, prefixElement.name]); | 930 StaticWarningCode.UNDEFINED_GETTER, |
| 931 identifier, |
| 932 [identifier.name, prefixElement.name]); |
| 836 } | 933 } |
| 837 return null; | 934 return null; |
| 838 } | 935 } |
| 839 if (element is PropertyAccessorElement && identifier.inSetterContext()) { | 936 Element accessor = element; |
| 840 PropertyInducingElement variable = | 937 if (accessor is PropertyAccessorElement && identifier.inSetterContext()) { |
| 841 (element as PropertyAccessorElement).variable; | 938 PropertyInducingElement variable = accessor.variable; |
| 842 if (variable != null) { | 939 if (variable != null) { |
| 843 PropertyAccessorElement setter = variable.setter; | 940 PropertyAccessorElement setter = variable.setter; |
| 844 if (setter != null) { | 941 if (setter != null) { |
| 845 element = setter; | 942 element = setter; |
| 846 } | 943 } |
| 847 } | 944 } |
| 848 } | 945 } |
| 849 // TODO(brianwilkerson) The prefix needs to be resolved to the element for | 946 // TODO(brianwilkerson) The prefix needs to be resolved to the element for |
| 850 // the import that defines the prefix, not the prefix's element. | 947 // the import that defines the prefix, not the prefix's element. |
| 851 identifier.staticElement = element; | 948 identifier.staticElement = element; |
| 852 // Validate annotation element. | 949 // Validate annotation element. |
| 853 if (node.parent is Annotation) { | 950 AstNode parent = node.parent; |
| 854 Annotation annotation = node.parent as Annotation; | 951 if (parent is Annotation) { |
| 855 _resolveAnnotationElement(annotation); | 952 _resolveAnnotationElement(parent); |
| 856 return null; | |
| 857 } | 953 } |
| 858 return null; | 954 return null; |
| 859 } | 955 } |
| 860 // May be annotation, resolve invocation of "const" constructor. | 956 // May be annotation, resolve invocation of "const" constructor. |
| 861 if (node.parent is Annotation) { | 957 AstNode parent = node.parent; |
| 862 Annotation annotation = node.parent as Annotation; | 958 if (parent is Annotation) { |
| 863 _resolveAnnotationElement(annotation); | 959 _resolveAnnotationElement(parent); |
| 864 } | 960 } |
| 865 // | 961 // |
| 866 // Otherwise, the prefix is really an expression that happens to be a simple | 962 // Otherwise, the prefix is really an expression that happens to be a simple |
| 867 // identifier and this is really equivalent to a property access node. | 963 // identifier and this is really equivalent to a property access node. |
| 868 // | 964 // |
| 869 _resolvePropertyAccess(prefix, identifier); | 965 _resolvePropertyAccess(prefix, identifier, false); |
| 870 return null; | 966 return null; |
| 871 } | 967 } |
| 872 | 968 |
| 873 @override | 969 @override |
| 874 Object visitPrefixExpression(PrefixExpression node) { | 970 Object visitPrefixExpression(PrefixExpression node) { |
| 875 sc.Token operator = node.operator; | 971 Token operator = node.operator; |
| 876 sc.TokenType operatorType = operator.type; | 972 TokenType operatorType = operator.type; |
| 877 if (operatorType.isUserDefinableOperator || | 973 if (operatorType.isUserDefinableOperator || |
| 878 operatorType == sc.TokenType.PLUS_PLUS || | 974 operatorType == TokenType.PLUS_PLUS || |
| 879 operatorType == sc.TokenType.MINUS_MINUS) { | 975 operatorType == TokenType.MINUS_MINUS) { |
| 880 Expression operand = node.operand; | 976 Expression operand = node.operand; |
| 881 String methodName = _getPrefixOperator(node); | 977 String methodName = _getPrefixOperator(node); |
| 882 DartType staticType = _getStaticType(operand); | 978 DartType staticType = _getStaticType(operand); |
| 883 MethodElement staticMethod = | 979 MethodElement staticMethod = |
| 884 _lookUpMethod(operand, staticType, methodName); | 980 _lookUpMethod(operand, staticType, methodName); |
| 885 node.staticElement = staticMethod; | 981 node.staticElement = staticMethod; |
| 886 DartType propagatedType = _getPropagatedType(operand); | 982 DartType propagatedType = _getPropagatedType(operand); |
| 887 MethodElement propagatedMethod = | 983 MethodElement propagatedMethod = |
| 888 _lookUpMethod(operand, propagatedType, methodName); | 984 _lookUpMethod(operand, propagatedType, methodName); |
| 889 node.propagatedElement = propagatedMethod; | 985 node.propagatedElement = propagatedMethod; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 915 return null; | 1011 return null; |
| 916 } | 1012 } |
| 917 | 1013 |
| 918 @override | 1014 @override |
| 919 Object visitPropertyAccess(PropertyAccess node) { | 1015 Object visitPropertyAccess(PropertyAccess node) { |
| 920 Expression target = node.realTarget; | 1016 Expression target = node.realTarget; |
| 921 if (target is SuperExpression && !_isSuperInValidContext(target)) { | 1017 if (target is SuperExpression && !_isSuperInValidContext(target)) { |
| 922 return null; | 1018 return null; |
| 923 } | 1019 } |
| 924 SimpleIdentifier propertyName = node.propertyName; | 1020 SimpleIdentifier propertyName = node.propertyName; |
| 925 _resolvePropertyAccess(target, propertyName); | 1021 _resolvePropertyAccess(target, propertyName, node.isCascaded); |
| 926 return null; | 1022 return null; |
| 927 } | 1023 } |
| 928 | 1024 |
| 929 @override | 1025 @override |
| 930 Object visitRedirectingConstructorInvocation( | 1026 Object visitRedirectingConstructorInvocation( |
| 931 RedirectingConstructorInvocation node) { | 1027 RedirectingConstructorInvocation node) { |
| 932 ClassElement enclosingClass = _resolver.enclosingClass; | 1028 ClassElement enclosingClass = _resolver.enclosingClass; |
| 933 if (enclosingClass == null) { | 1029 if (enclosingClass == null) { |
| 934 // TODO(brianwilkerson) Report this error. | 1030 // TODO(brianwilkerson) Report this error. |
| 935 return null; | 1031 return null; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 954 List<ParameterElement> parameters = | 1050 List<ParameterElement> parameters = |
| 955 _resolveArgumentsToFunction(false, argumentList, element); | 1051 _resolveArgumentsToFunction(false, argumentList, element); |
| 956 if (parameters != null) { | 1052 if (parameters != null) { |
| 957 argumentList.correspondingStaticParameters = parameters; | 1053 argumentList.correspondingStaticParameters = parameters; |
| 958 } | 1054 } |
| 959 return null; | 1055 return null; |
| 960 } | 1056 } |
| 961 | 1057 |
| 962 @override | 1058 @override |
| 963 Object visitSimpleFormalParameter(SimpleFormalParameter node) { | 1059 Object visitSimpleFormalParameter(SimpleFormalParameter node) { |
| 964 _setMetadataForParameter(node.element, node); | 1060 _resolveMetadataForParameter(node); |
| 965 return null; | 1061 return null; |
| 966 } | 1062 } |
| 967 | 1063 |
| 968 @override | 1064 @override |
| 969 Object visitSimpleIdentifier(SimpleIdentifier node) { | 1065 Object visitSimpleIdentifier(SimpleIdentifier node) { |
| 970 // | 1066 // |
| 971 // Synthetic identifiers have been already reported during parsing. | 1067 // Synthetic identifiers have been already reported during parsing. |
| 972 // | 1068 // |
| 973 if (node.isSynthetic) { | 1069 if (node.isSynthetic) { |
| 974 return null; | 1070 return null; |
| 975 } | 1071 } |
| 976 // | 1072 // |
| 977 // Ignore nodes that should have been resolved before getting here. | 1073 // Ignore nodes that should have been resolved before getting here. |
| 978 // | 1074 // |
| 979 if (node.inDeclarationContext()) { | 1075 if (node.inDeclarationContext()) { |
| 980 return null; | 1076 return null; |
| 981 } | 1077 } |
| 1078 if (node.staticElement is LocalVariableElement || |
| 1079 node.staticElement is ParameterElement) { |
| 1080 return null; |
| 1081 } |
| 982 AstNode parent = node.parent; | 1082 AstNode parent = node.parent; |
| 983 if (parent is FieldFormalParameter) { | 1083 if (parent is FieldFormalParameter) { |
| 984 return null; | 1084 return null; |
| 985 } else if (parent is ConstructorFieldInitializer && | 1085 } else if (parent is ConstructorFieldInitializer && |
| 986 parent.fieldName == node) { | 1086 parent.fieldName == node) { |
| 987 return null; | 1087 return null; |
| 988 } else if (parent is Annotation && parent.constructorName == node) { | 1088 } else if (parent is Annotation && parent.constructorName == node) { |
| 989 return null; | 1089 return null; |
| 990 } | 1090 } |
| 991 // | 1091 // |
| 992 // The name dynamic denotes a Type object even though dynamic is not a | 1092 // The name dynamic denotes a Type object even though dynamic is not a |
| 993 // class. | 1093 // class. |
| 994 // | 1094 // |
| 995 if (node.name == _dynamicType.name) { | 1095 if (node.name == _dynamicType.name) { |
| 996 node.staticElement = _dynamicType.element; | 1096 node.staticElement = _dynamicType.element; |
| 997 node.staticType = _typeType; | 1097 node.staticType = _typeType; |
| 998 return null; | 1098 return null; |
| 999 } | 1099 } |
| 1000 // | 1100 // |
| 1001 // Otherwise, the node should be resolved. | 1101 // Otherwise, the node should be resolved. |
| 1002 // | 1102 // |
| 1003 Element element = _resolveSimpleIdentifier(node); | 1103 Element element = _resolveSimpleIdentifier(node); |
| 1004 ClassElement enclosingClass = _resolver.enclosingClass; | 1104 ClassElement enclosingClass = _resolver.enclosingClass; |
| 1005 if (_isFactoryConstructorReturnType(node) && | 1105 if (_isFactoryConstructorReturnType(node) && |
| 1006 !identical(element, enclosingClass)) { | 1106 !identical(element, enclosingClass)) { |
| 1007 _resolver.reportErrorForNode( | 1107 _resolver.errorReporter.reportErrorForNode( |
| 1008 CompileTimeErrorCode.INVALID_FACTORY_NAME_NOT_A_CLASS, node); | 1108 CompileTimeErrorCode.INVALID_FACTORY_NAME_NOT_A_CLASS, node); |
| 1009 } else if (_isConstructorReturnType(node) && | 1109 } else if (_isConstructorReturnType(node) && |
| 1010 !identical(element, enclosingClass)) { | 1110 !identical(element, enclosingClass)) { |
| 1011 _resolver.reportErrorForNode( | 1111 _resolver.errorReporter.reportErrorForNode( |
| 1012 CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME, node); | 1112 CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME, node); |
| 1013 element = null; | 1113 element = null; |
| 1014 } else if (element == null || | 1114 } else if (element == null || |
| 1015 (element is PrefixElement && !_isValidAsPrefix(node))) { | 1115 (element is PrefixElement && !_isValidAsPrefix(node))) { |
| 1016 // TODO(brianwilkerson) Recover from this error. | 1116 // TODO(brianwilkerson) Recover from this error. |
| 1017 if (_isConstructorReturnType(node)) { | 1117 if (_isConstructorReturnType(node)) { |
| 1018 _resolver.reportErrorForNode( | 1118 _resolver.errorReporter.reportErrorForNode( |
| 1019 CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME, node); | 1119 CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME, node); |
| 1020 } else if (node.parent is Annotation) { | 1120 } else if (parent is Annotation) { |
| 1021 Annotation annotation = node.parent as Annotation; | 1121 _resolver.errorReporter.reportErrorForNode( |
| 1022 _resolver.reportErrorForNode( | 1122 CompileTimeErrorCode.INVALID_ANNOTATION, parent); |
| 1023 CompileTimeErrorCode.INVALID_ANNOTATION, annotation); | 1123 } else if (element != null) { |
| 1024 } else if (element is PrefixElement) { | 1124 _resolver.errorReporter.reportErrorForNode( |
| 1025 _resolver.reportErrorForNode( | |
| 1026 CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, | 1125 CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, |
| 1027 node, | 1126 node, |
| 1028 [element.name]); | 1127 [element.name]); |
| 1029 } else { | 1128 } else if (node.name == "await" && _resolver.enclosingFunction != null) { |
| 1129 _recordUndefinedNode( |
| 1130 _resolver.enclosingClass, |
| 1131 StaticWarningCode.UNDEFINED_IDENTIFIER_AWAIT, |
| 1132 node, |
| 1133 [_resolver.enclosingFunction.displayName]); |
| 1134 } else if (!_resolver.nameScope.shouldIgnoreUndefined(node)) { |
| 1030 _recordUndefinedNode(_resolver.enclosingClass, | 1135 _recordUndefinedNode(_resolver.enclosingClass, |
| 1031 StaticWarningCode.UNDEFINED_IDENTIFIER, node, [node.name]); | 1136 StaticWarningCode.UNDEFINED_IDENTIFIER, node, [node.name]); |
| 1032 } | 1137 } |
| 1033 } | 1138 } |
| 1034 node.staticElement = element; | 1139 node.staticElement = element; |
| 1035 if (node.inSetterContext() && | 1140 if (node.inSetterContext() && |
| 1036 node.inGetterContext() && | 1141 node.inGetterContext() && |
| 1037 enclosingClass != null) { | 1142 enclosingClass != null) { |
| 1038 InterfaceType enclosingType = enclosingClass.type; | 1143 InterfaceType enclosingType = enclosingClass.type; |
| 1039 AuxiliaryElements auxiliaryElements = new AuxiliaryElements( | 1144 AuxiliaryElements auxiliaryElements = new AuxiliaryElements( |
| 1040 _lookUpGetter(null, enclosingType, node.name), null); | 1145 _lookUpGetter(null, enclosingType, node.name), null); |
| 1041 node.auxiliaryElements = auxiliaryElements; | 1146 node.auxiliaryElements = auxiliaryElements; |
| 1042 } | 1147 } |
| 1043 // | 1148 // |
| 1044 // Validate annotation element. | 1149 // Validate annotation element. |
| 1045 // | 1150 // |
| 1046 if (node.parent is Annotation) { | 1151 if (parent is Annotation) { |
| 1047 Annotation annotation = node.parent as Annotation; | 1152 _resolveAnnotationElement(parent); |
| 1048 _resolveAnnotationElement(annotation); | |
| 1049 } | 1153 } |
| 1050 return null; | 1154 return null; |
| 1051 } | 1155 } |
| 1052 | 1156 |
| 1053 @override | 1157 @override |
| 1054 Object visitSuperConstructorInvocation(SuperConstructorInvocation node) { | 1158 Object visitSuperConstructorInvocation(SuperConstructorInvocation node) { |
| 1055 ClassElementImpl enclosingClass = _resolver.enclosingClass; | 1159 ClassElementImpl enclosingClass = |
| 1160 AbstractClassElementImpl.getImpl(_resolver.enclosingClass); |
| 1056 if (enclosingClass == null) { | 1161 if (enclosingClass == null) { |
| 1057 // TODO(brianwilkerson) Report this error. | 1162 // TODO(brianwilkerson) Report this error. |
| 1058 return null; | 1163 return null; |
| 1059 } | 1164 } |
| 1060 InterfaceType superType = enclosingClass.supertype; | 1165 InterfaceType superType = enclosingClass.supertype; |
| 1061 if (superType == null) { | 1166 if (superType == null) { |
| 1062 // TODO(brianwilkerson) Report this error. | 1167 // TODO(brianwilkerson) Report this error. |
| 1063 return null; | 1168 return null; |
| 1064 } | 1169 } |
| 1065 SimpleIdentifier name = node.constructorName; | 1170 SimpleIdentifier name = node.constructorName; |
| 1066 String superName = name != null ? name.name : null; | 1171 String superName = name?.name; |
| 1067 ConstructorElement element = | 1172 ConstructorElement element = |
| 1068 superType.lookUpConstructor(superName, _definingLibrary); | 1173 superType.lookUpConstructor(superName, _definingLibrary); |
| 1069 if (element == null || | 1174 if (element == null || |
| 1070 (!enclosingClass.doesMixinLackConstructors && | 1175 (!enclosingClass.doesMixinLackConstructors && |
| 1071 !enclosingClass.isSuperConstructorAccessible(element))) { | 1176 !enclosingClass.isSuperConstructorAccessible(element))) { |
| 1072 if (name != null) { | 1177 if (name != null) { |
| 1073 _resolver.reportErrorForNode( | 1178 _resolver.errorReporter.reportErrorForNode( |
| 1074 CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER, | 1179 CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER, |
| 1075 node, | 1180 node, |
| 1076 [superType.displayName, name]); | 1181 [superType.displayName, name]); |
| 1077 } else { | 1182 } else { |
| 1078 _resolver.reportErrorForNode( | 1183 _resolver.errorReporter.reportErrorForNode( |
| 1079 CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT, | 1184 CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT, |
| 1080 node, | 1185 node, |
| 1081 [superType.displayName]); | 1186 [superType.displayName]); |
| 1082 } | 1187 } |
| 1083 return null; | 1188 return null; |
| 1084 } else { | 1189 } else { |
| 1085 if (element.isFactory) { | 1190 if (element.isFactory) { |
| 1086 _resolver.reportErrorForNode( | 1191 _resolver.errorReporter.reportErrorForNode( |
| 1087 CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR, node, [element]); | 1192 CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR, node, [element]); |
| 1088 } | 1193 } |
| 1089 } | 1194 } |
| 1090 if (name != null) { | 1195 if (name != null) { |
| 1091 name.staticElement = element; | 1196 name.staticElement = element; |
| 1092 } | 1197 } |
| 1093 node.staticElement = element; | 1198 node.staticElement = element; |
| 1199 // TODO(brianwilkerson) Defer this check until we know there's an error (by |
| 1200 // in-lining _resolveArgumentsToFunction below). |
| 1201 ClassDeclaration declaration = |
| 1202 node.getAncestor((AstNode node) => node is ClassDeclaration); |
| 1203 Identifier superclassName = declaration.extendsClause?.superclass?.name; |
| 1204 if (superclassName != null && |
| 1205 _resolver.nameScope.shouldIgnoreUndefined(superclassName)) { |
| 1206 return null; |
| 1207 } |
| 1094 ArgumentList argumentList = node.argumentList; | 1208 ArgumentList argumentList = node.argumentList; |
| 1095 List<ParameterElement> parameters = _resolveArgumentsToFunction( | 1209 List<ParameterElement> parameters = _resolveArgumentsToFunction( |
| 1096 isInConstConstructor, argumentList, element); | 1210 isInConstConstructor, argumentList, element); |
| 1097 if (parameters != null) { | 1211 if (parameters != null) { |
| 1098 argumentList.correspondingStaticParameters = parameters; | 1212 argumentList.correspondingStaticParameters = parameters; |
| 1099 } | 1213 } |
| 1100 return null; | 1214 return null; |
| 1101 } | 1215 } |
| 1102 | 1216 |
| 1103 @override | 1217 @override |
| 1104 Object visitSuperExpression(SuperExpression node) { | 1218 Object visitSuperExpression(SuperExpression node) { |
| 1105 if (!_isSuperInValidContext(node)) { | 1219 if (!_isSuperInValidContext(node)) { |
| 1106 _resolver.reportErrorForNode( | 1220 _resolver.errorReporter.reportErrorForNode( |
| 1107 CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT, node); | 1221 CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT, node); |
| 1108 } | 1222 } |
| 1109 return super.visitSuperExpression(node); | 1223 return super.visitSuperExpression(node); |
| 1110 } | 1224 } |
| 1111 | 1225 |
| 1112 @override | 1226 @override |
| 1113 Object visitTypeParameter(TypeParameter node) { | 1227 Object visitTypeParameter(TypeParameter node) { |
| 1114 setMetadata(node.element, node); | 1228 resolveMetadata(node); |
| 1115 return null; | 1229 return null; |
| 1116 } | 1230 } |
| 1117 | 1231 |
| 1118 @override | 1232 @override |
| 1119 Object visitVariableDeclaration(VariableDeclaration node) { | 1233 Object visitVariableDeclaration(VariableDeclaration node) { |
| 1120 setMetadata(node.element, node); | 1234 resolveMetadata(node); |
| 1121 return null; | 1235 return null; |
| 1122 } | 1236 } |
| 1123 | 1237 |
| 1124 /** | 1238 /** |
| 1125 * Given that we have found code to invoke the given [element], return the | 1239 * Given that we have found code to invoke the given [element], return the |
| 1126 * error code that should be reported, or `null` if no error should be | 1240 * error code that should be reported, or `null` if no error should be |
| 1127 * reported. The [target] is the target of the invocation, or `null` if there | 1241 * reported. The [target] is the target of the invocation, or `null` if there |
| 1128 * was no target. The flag [useStaticContext] should be `true` if the | 1242 * was no target. The flag [useStaticContext] should be `true` if the |
| 1129 * invocation is in a static constant (does not have access to instance state. | 1243 * invocation is in a static constant (does not have access to instance state)
. |
| 1130 */ | 1244 */ |
| 1131 ErrorCode _checkForInvocationError( | 1245 ErrorCode _checkForInvocationError( |
| 1132 Expression target, bool useStaticContext, Element element) { | 1246 Expression target, bool useStaticContext, Element element) { |
| 1133 // Prefix is not declared, instead "prefix.id" are declared. | 1247 // Prefix is not declared, instead "prefix.id" are declared. |
| 1134 if (element is PrefixElement) { | 1248 if (element is PrefixElement) { |
| 1135 return CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT; | 1249 return CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT; |
| 1136 } | 1250 } else if (element is PropertyAccessorElement) { |
| 1137 if (element is PropertyAccessorElement) { | |
| 1138 // | 1251 // |
| 1139 // This is really a function expression invocation. | 1252 // This is really a function expression invocation. |
| 1140 // | 1253 // |
| 1141 // TODO(brianwilkerson) Consider the possibility of re-writing the AST. | 1254 // TODO(brianwilkerson) Consider the possibility of re-writing the AST. |
| 1142 FunctionType getterType = element.type; | 1255 FunctionType getterType = element.type; |
| 1143 if (getterType != null) { | 1256 if (getterType != null) { |
| 1144 DartType returnType = getterType.returnType; | 1257 DartType returnType = getterType.returnType; |
| 1145 if (!_isExecutableType(returnType)) { | 1258 if (!_isExecutableType(returnType)) { |
| 1146 return StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION; | 1259 return StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION; |
| 1147 } | 1260 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1191 DartType targetType; | 1304 DartType targetType; |
| 1192 if (useStaticContext) { | 1305 if (useStaticContext) { |
| 1193 targetType = _getStaticType(target); | 1306 targetType = _getStaticType(target); |
| 1194 } else { | 1307 } else { |
| 1195 // Compute and use the propagated type, if it is null, then it may | 1308 // Compute and use the propagated type, if it is null, then it may |
| 1196 // be the case that static type is some type, in which the static | 1309 // be the case that static type is some type, in which the static |
| 1197 // type should be used. | 1310 // type should be used. |
| 1198 targetType = _getBestType(target); | 1311 targetType = _getBestType(target); |
| 1199 } | 1312 } |
| 1200 if (targetType == null) { | 1313 if (targetType == null) { |
| 1314 if (target is Identifier && |
| 1315 _resolver.nameScope.shouldIgnoreUndefined(target)) { |
| 1316 return null; |
| 1317 } |
| 1201 return StaticTypeWarningCode.UNDEFINED_FUNCTION; | 1318 return StaticTypeWarningCode.UNDEFINED_FUNCTION; |
| 1202 } else if (!targetType.isDynamic && !targetType.isBottom) { | 1319 } else if (!targetType.isDynamic && !targetType.isBottom) { |
| 1203 // Proxy-conditional warning, based on state of | 1320 // Proxy-conditional warning, based on state of |
| 1204 // targetType.getElement() | 1321 // targetType.getElement() |
| 1205 return StaticTypeWarningCode.UNDEFINED_METHOD; | 1322 return StaticTypeWarningCode.UNDEFINED_METHOD; |
| 1206 } | 1323 } |
| 1207 } | 1324 } |
| 1208 } | 1325 } |
| 1209 } | 1326 } |
| 1210 return null; | 1327 return null; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1227 bool shouldReportMissingMember_static = | 1344 bool shouldReportMissingMember_static = |
| 1228 _shouldReportMissingMember(staticType, staticMethod); | 1345 _shouldReportMissingMember(staticType, staticMethod); |
| 1229 bool shouldReportMissingMember_propagated = | 1346 bool shouldReportMissingMember_propagated = |
| 1230 !shouldReportMissingMember_static && | 1347 !shouldReportMissingMember_static && |
| 1231 _enableHints && | 1348 _enableHints && |
| 1232 _shouldReportMissingMember(propagatedType, propagatedMethod) && | 1349 _shouldReportMissingMember(propagatedType, propagatedMethod) && |
| 1233 !_memberFoundInSubclass( | 1350 !_memberFoundInSubclass( |
| 1234 propagatedType.element, methodName, true, false); | 1351 propagatedType.element, methodName, true, false); |
| 1235 if (shouldReportMissingMember_static || | 1352 if (shouldReportMissingMember_static || |
| 1236 shouldReportMissingMember_propagated) { | 1353 shouldReportMissingMember_propagated) { |
| 1237 sc.Token leftBracket = expression.leftBracket; | 1354 Token leftBracket = expression.leftBracket; |
| 1238 sc.Token rightBracket = expression.rightBracket; | 1355 Token rightBracket = expression.rightBracket; |
| 1239 ErrorCode errorCode; | 1356 ErrorCode errorCode; |
| 1240 if (shouldReportMissingMember_static) { | 1357 if (shouldReportMissingMember_static) { |
| 1241 if (target is SuperExpression) { | 1358 if (target is SuperExpression) { |
| 1242 errorCode = StaticTypeWarningCode.UNDEFINED_SUPER_OPERATOR; | 1359 errorCode = StaticTypeWarningCode.UNDEFINED_SUPER_OPERATOR; |
| 1243 } else { | 1360 } else { |
| 1244 errorCode = StaticTypeWarningCode.UNDEFINED_OPERATOR; | 1361 errorCode = StaticTypeWarningCode.UNDEFINED_OPERATOR; |
| 1245 } | 1362 } |
| 1246 } else { | 1363 } else { |
| 1247 errorCode = HintCode.UNDEFINED_OPERATOR; | 1364 errorCode = HintCode.UNDEFINED_OPERATOR; |
| 1248 } | 1365 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1262 return false; | 1379 return false; |
| 1263 } | 1380 } |
| 1264 | 1381 |
| 1265 /** | 1382 /** |
| 1266 * Given an [argumentList] and the executable [element] that will be invoked | 1383 * Given an [argumentList] and the executable [element] that will be invoked |
| 1267 * using those arguments, compute the list of parameters that correspond to | 1384 * using those arguments, compute the list of parameters that correspond to |
| 1268 * the list of arguments. Return the parameters that correspond to the | 1385 * the list of arguments. Return the parameters that correspond to the |
| 1269 * arguments, or `null` if no correspondence could be computed. | 1386 * arguments, or `null` if no correspondence could be computed. |
| 1270 */ | 1387 */ |
| 1271 List<ParameterElement> _computeCorrespondingParameters( | 1388 List<ParameterElement> _computeCorrespondingParameters( |
| 1272 ArgumentList argumentList, Element element) { | 1389 ArgumentList argumentList, DartType type) { |
| 1273 if (element is PropertyAccessorElement) { | 1390 if (type is InterfaceType) { |
| 1274 // | 1391 MethodElement callMethod = |
| 1275 // This is an invocation of the call method defined on the value returned | 1392 type.lookUpMethod(FunctionElement.CALL_METHOD_NAME, _definingLibrary); |
| 1276 // by the getter. | 1393 if (callMethod != null) { |
| 1277 // | 1394 return _resolveArgumentsToFunction(false, argumentList, callMethod); |
| 1278 FunctionType getterType = element.type; | |
| 1279 if (getterType != null) { | |
| 1280 DartType getterReturnType = getterType.returnType; | |
| 1281 if (getterReturnType is InterfaceType) { | |
| 1282 MethodElement callMethod = getterReturnType.lookUpMethod( | |
| 1283 FunctionElement.CALL_METHOD_NAME, _definingLibrary); | |
| 1284 if (callMethod != null) { | |
| 1285 return _resolveArgumentsToFunction(false, argumentList, callMethod); | |
| 1286 } | |
| 1287 } else if (getterReturnType is FunctionType) { | |
| 1288 List<ParameterElement> parameters = getterReturnType.parameters; | |
| 1289 return _resolveArgumentsToParameters(false, argumentList, parameters); | |
| 1290 } | |
| 1291 } | 1395 } |
| 1292 } else if (element is ExecutableElement) { | 1396 } else if (type is FunctionType) { |
| 1293 return _resolveArgumentsToFunction(false, argumentList, element); | 1397 return _resolveArgumentsToParameters( |
| 1294 } else if (element is VariableElement) { | 1398 false, argumentList, type.parameters); |
| 1295 VariableElement variable = element; | |
| 1296 DartType type = _promoteManager.getStaticType(variable); | |
| 1297 if (type is FunctionType) { | |
| 1298 FunctionType functionType = type; | |
| 1299 List<ParameterElement> parameters = functionType.parameters; | |
| 1300 return _resolveArgumentsToParameters(false, argumentList, parameters); | |
| 1301 } else if (type is InterfaceType) { | |
| 1302 // "call" invocation | |
| 1303 MethodElement callMethod = type.lookUpMethod( | |
| 1304 FunctionElement.CALL_METHOD_NAME, _definingLibrary); | |
| 1305 if (callMethod != null) { | |
| 1306 List<ParameterElement> parameters = callMethod.parameters; | |
| 1307 return _resolveArgumentsToParameters(false, argumentList, parameters); | |
| 1308 } | |
| 1309 } | |
| 1310 } | 1399 } |
| 1311 return null; | 1400 return null; |
| 1312 } | 1401 } |
| 1313 | 1402 |
| 1314 /** | 1403 /** |
| 1315 * If the given [element] is a setter, return the getter associated with it. | 1404 * If the given [element] is a setter, return the getter associated with it. |
| 1316 * Otherwise, return the element unchanged. | 1405 * Otherwise, return the element unchanged. |
| 1317 */ | 1406 */ |
| 1318 Element _convertSetterToGetter(Element element) { | 1407 Element _convertSetterToGetter(Element element) { |
| 1319 // TODO(brianwilkerson) Determine whether and why the element could ever be | 1408 // TODO(brianwilkerson) Determine whether and why the element could ever be |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1332 !(element is ClassElement && element.isOrInheritsProxy); | 1421 !(element is ClassElement && element.isOrInheritsProxy); |
| 1333 | 1422 |
| 1334 /** | 1423 /** |
| 1335 * Look for any declarations of the given [identifier] that are imported using | 1424 * Look for any declarations of the given [identifier] that are imported using |
| 1336 * a prefix. Return the element that was found, or `null` if the name is not | 1425 * a prefix. Return the element that was found, or `null` if the name is not |
| 1337 * imported using a prefix. | 1426 * imported using a prefix. |
| 1338 */ | 1427 */ |
| 1339 Element _findImportWithoutPrefix(SimpleIdentifier identifier) { | 1428 Element _findImportWithoutPrefix(SimpleIdentifier identifier) { |
| 1340 Element element = null; | 1429 Element element = null; |
| 1341 Scope nameScope = _resolver.nameScope; | 1430 Scope nameScope = _resolver.nameScope; |
| 1342 for (ImportElement importElement in _definingLibrary.imports) { | 1431 List<ImportElement> imports = _definingLibrary.imports; |
| 1432 int length = imports.length; |
| 1433 for (int i = 0; i < length; i++) { |
| 1434 ImportElement importElement = imports[i]; |
| 1343 PrefixElement prefixElement = importElement.prefix; | 1435 PrefixElement prefixElement = importElement.prefix; |
| 1344 if (prefixElement != null) { | 1436 if (prefixElement != null) { |
| 1345 Identifier prefixedIdentifier = new SyntheticIdentifier( | 1437 Identifier prefixedIdentifier = new PrefixedIdentifierImpl.temp( |
| 1346 "${prefixElement.name}.${identifier.name}", identifier); | 1438 new SimpleIdentifierImpl(new StringToken(TokenType.STRING, |
| 1439 prefixElement.name, prefixElement.nameOffset)), |
| 1440 identifier); |
| 1347 Element importedElement = | 1441 Element importedElement = |
| 1348 nameScope.lookup(prefixedIdentifier, _definingLibrary); | 1442 nameScope.lookup(prefixedIdentifier, _definingLibrary); |
| 1349 if (importedElement != null) { | 1443 if (importedElement != null) { |
| 1350 if (element == null) { | 1444 if (element == null) { |
| 1351 element = importedElement; | 1445 element = importedElement; |
| 1352 } else { | 1446 } else { |
| 1353 element = MultiplyDefinedElementImpl.fromElements( | 1447 element = MultiplyDefinedElementImpl.fromElements( |
| 1354 _definingLibrary.context, element, importedElement); | 1448 _definingLibrary.context, element, importedElement); |
| 1355 } | 1449 } |
| 1356 } | 1450 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1369 // | 1463 // |
| 1370 // All function types are subtypes of 'Function', which is itself a | 1464 // All function types are subtypes of 'Function', which is itself a |
| 1371 // subclass of 'Object'. | 1465 // subclass of 'Object'. |
| 1372 // | 1466 // |
| 1373 bestType = _resolver.typeProvider.functionType; | 1467 bestType = _resolver.typeProvider.functionType; |
| 1374 } | 1468 } |
| 1375 return bestType; | 1469 return bestType; |
| 1376 } | 1470 } |
| 1377 | 1471 |
| 1378 /** | 1472 /** |
| 1379 * Assuming that the given [expression] is a prefix for a deferred import, | 1473 * Assuming that the given [identifier] is a prefix for a deferred import, |
| 1380 * return the library that is being imported. | 1474 * return the library that is being imported. |
| 1381 */ | 1475 */ |
| 1382 LibraryElement _getImportedLibrary(Expression expression) { | 1476 LibraryElement _getImportedLibrary(SimpleIdentifier identifier) { |
| 1383 PrefixElement prefixElement = | 1477 PrefixElement prefixElement = identifier.staticElement as PrefixElement; |
| 1384 (expression as SimpleIdentifier).staticElement as PrefixElement; | |
| 1385 List<ImportElement> imports = | 1478 List<ImportElement> imports = |
| 1386 prefixElement.enclosingElement.getImportsWithPrefix(prefixElement); | 1479 prefixElement.enclosingElement.getImportsWithPrefix(prefixElement); |
| 1387 return imports[0].importedLibrary; | 1480 return imports[0].importedLibrary; |
| 1388 } | 1481 } |
| 1389 | 1482 |
| 1390 /** | 1483 /** |
| 1484 * Given an element, computes the type of the invocation. |
| 1485 * |
| 1486 * For executable elements (like methods, functions) this is just their type. |
| 1487 * |
| 1488 * For variables it is their type taking into account any type promotion. |
| 1489 * |
| 1490 * For calls to getters in Dart, we invoke the function that is returned by |
| 1491 * the getter, so the invoke type is the getter's returnType. |
| 1492 */ |
| 1493 DartType _getInvokeType(Element element) { |
| 1494 DartType invokeType; |
| 1495 if (element is PropertyAccessorElement) { |
| 1496 invokeType = element.returnType; |
| 1497 } else if (element is ExecutableElement) { |
| 1498 invokeType = element.type; |
| 1499 } else if (element is VariableElement) { |
| 1500 invokeType = _promoteManager.getStaticType(element); |
| 1501 } |
| 1502 return invokeType ?? DynamicTypeImpl.instance; |
| 1503 } |
| 1504 |
| 1505 /** |
| 1391 * Return the name of the method invoked by the given postfix [expression]. | 1506 * Return the name of the method invoked by the given postfix [expression]. |
| 1392 */ | 1507 */ |
| 1393 String _getPostfixOperator(PostfixExpression expression) => | 1508 String _getPostfixOperator(PostfixExpression expression) => |
| 1394 (expression.operator.type == sc.TokenType.PLUS_PLUS) | 1509 (expression.operator.type == TokenType.PLUS_PLUS) |
| 1395 ? sc.TokenType.PLUS.lexeme | 1510 ? TokenType.PLUS.lexeme |
| 1396 : sc.TokenType.MINUS.lexeme; | 1511 : TokenType.MINUS.lexeme; |
| 1397 | 1512 |
| 1398 /** | 1513 /** |
| 1399 * Return the name of the method invoked by the given postfix [expression]. | 1514 * Return the name of the method invoked by the given postfix [expression]. |
| 1400 */ | 1515 */ |
| 1401 String _getPrefixOperator(PrefixExpression expression) { | 1516 String _getPrefixOperator(PrefixExpression expression) { |
| 1402 sc.Token operator = expression.operator; | 1517 Token operator = expression.operator; |
| 1403 sc.TokenType operatorType = operator.type; | 1518 TokenType operatorType = operator.type; |
| 1404 if (operatorType == sc.TokenType.PLUS_PLUS) { | 1519 if (operatorType == TokenType.PLUS_PLUS) { |
| 1405 return sc.TokenType.PLUS.lexeme; | 1520 return TokenType.PLUS.lexeme; |
| 1406 } else if (operatorType == sc.TokenType.MINUS_MINUS) { | 1521 } else if (operatorType == TokenType.MINUS_MINUS) { |
| 1407 return sc.TokenType.MINUS.lexeme; | 1522 return TokenType.MINUS.lexeme; |
| 1408 } else if (operatorType == sc.TokenType.MINUS) { | 1523 } else if (operatorType == TokenType.MINUS) { |
| 1409 return "unary-"; | 1524 return "unary-"; |
| 1410 } else { | 1525 } else { |
| 1411 return operator.lexeme; | 1526 return operator.lexeme; |
| 1412 } | 1527 } |
| 1413 } | 1528 } |
| 1414 | 1529 |
| 1415 /** | 1530 /** |
| 1416 * Return the propagated type of the given [expression] that is to be used for | 1531 * Return the propagated type of the given [expression] that is to be used for |
| 1417 * type analysis. | 1532 * type analysis. |
| 1418 */ | 1533 */ |
| 1419 DartType _getPropagatedType(Expression expression) { | 1534 DartType _getPropagatedType(Expression expression) { |
| 1420 DartType propagatedType = _resolveTypeParameter(expression.propagatedType); | 1535 DartType propagatedType = _resolveTypeParameter(expression.propagatedType); |
| 1421 if (propagatedType is FunctionType) { | 1536 if (propagatedType is FunctionType) { |
| 1422 // | 1537 // |
| 1423 // All function types are subtypes of 'Function', which is itself a | 1538 // All function types are subtypes of 'Function', which is itself a |
| 1424 // subclass of 'Object'. | 1539 // subclass of 'Object'. |
| 1425 // | 1540 // |
| 1426 propagatedType = _resolver.typeProvider.functionType; | 1541 propagatedType = _resolver.typeProvider.functionType; |
| 1427 } | 1542 } |
| 1428 return propagatedType; | 1543 return propagatedType; |
| 1429 } | 1544 } |
| 1430 | 1545 |
| 1431 /** | 1546 /** |
| 1432 * Return the static type of the given [expression] that is to be used for | 1547 * Return the static type of the given [expression] that is to be used for |
| 1433 * type analysis. | 1548 * type analysis. |
| 1434 */ | 1549 */ |
| 1435 DartType _getStaticType(Expression expression) { | 1550 DartType _getStaticType(Expression expression) { |
| 1436 if (expression is NullLiteral) { | 1551 DartType staticType = _getStaticTypeOrFunctionType(expression); |
| 1437 return _resolver.typeProvider.bottomType; | |
| 1438 } | |
| 1439 DartType staticType = _resolveTypeParameter(expression.staticType); | |
| 1440 if (staticType is FunctionType) { | 1552 if (staticType is FunctionType) { |
| 1441 // | 1553 // |
| 1442 // All function types are subtypes of 'Function', which is itself a | 1554 // All function types are subtypes of 'Function', which is itself a |
| 1443 // subclass of 'Object'. | 1555 // subclass of 'Object'. |
| 1444 // | 1556 // |
| 1445 staticType = _resolver.typeProvider.functionType; | 1557 staticType = _resolver.typeProvider.functionType; |
| 1446 } | 1558 } |
| 1447 return staticType; | 1559 return staticType; |
| 1448 } | 1560 } |
| 1449 | 1561 |
| 1562 DartType _getStaticTypeOrFunctionType(Expression expression) { |
| 1563 if (expression is NullLiteral) { |
| 1564 return _resolver.typeProvider.bottomType; |
| 1565 } |
| 1566 return _resolveTypeParameter(expression.staticType); |
| 1567 } |
| 1568 |
| 1569 /** |
| 1570 * Check for a generic method & apply type arguments if any were passed. |
| 1571 */ |
| 1572 DartType _instantiateGenericMethod( |
| 1573 DartType invokeType, TypeArgumentList typeArguments, AstNode node) { |
| 1574 // TODO(jmesserly): support generic "call" methods on InterfaceType. |
| 1575 if (invokeType is FunctionType) { |
| 1576 List<TypeParameterElement> parameters = invokeType.typeFormals; |
| 1577 |
| 1578 NodeList<TypeName> arguments = typeArguments?.arguments; |
| 1579 if (arguments != null && arguments.length != parameters.length) { |
| 1580 _resolver.errorReporter.reportErrorForNode( |
| 1581 StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS, |
| 1582 node, |
| 1583 [invokeType, parameters.length, arguments?.length ?? 0]); |
| 1584 |
| 1585 // Wrong number of type arguments. Ignore them. |
| 1586 arguments = null; |
| 1587 } |
| 1588 if (parameters.isNotEmpty) { |
| 1589 if (arguments == null) { |
| 1590 return _resolver.typeSystem.instantiateToBounds(invokeType); |
| 1591 } else { |
| 1592 return invokeType.instantiate(arguments.map((n) => n.type).toList()); |
| 1593 } |
| 1594 } |
| 1595 } |
| 1596 return invokeType; |
| 1597 } |
| 1598 |
| 1450 /** | 1599 /** |
| 1451 * Return `true` if the given [expression] is a prefix for a deferred import. | 1600 * Return `true` if the given [expression] is a prefix for a deferred import. |
| 1452 */ | 1601 */ |
| 1453 bool _isDeferredPrefix(Expression expression) { | 1602 bool _isDeferredPrefix(Expression expression) { |
| 1454 if (expression is! SimpleIdentifier) { | 1603 if (expression is SimpleIdentifier) { |
| 1455 return false; | 1604 Element element = expression.staticElement; |
| 1605 if (element is PrefixElement) { |
| 1606 List<ImportElement> imports = |
| 1607 element.enclosingElement.getImportsWithPrefix(element); |
| 1608 if (imports.length != 1) { |
| 1609 return false; |
| 1610 } |
| 1611 return imports[0].isDeferred; |
| 1612 } |
| 1456 } | 1613 } |
| 1457 Element element = (expression as SimpleIdentifier).staticElement; | 1614 return false; |
| 1458 if (element is! PrefixElement) { | |
| 1459 return false; | |
| 1460 } | |
| 1461 PrefixElement prefixElement = element as PrefixElement; | |
| 1462 List<ImportElement> imports = | |
| 1463 prefixElement.enclosingElement.getImportsWithPrefix(prefixElement); | |
| 1464 if (imports.length != 1) { | |
| 1465 return false; | |
| 1466 } | |
| 1467 return imports[0].isDeferred; | |
| 1468 } | 1615 } |
| 1469 | 1616 |
| 1470 /** | 1617 /** |
| 1471 * Return `true` if the given [type] represents an object that could be | 1618 * Return `true` if the given [type] represents an object that could be |
| 1472 * invoked using the call operator '()'. | 1619 * invoked using the call operator '()'. |
| 1473 */ | 1620 */ |
| 1474 bool _isExecutableType(DartType type) { | 1621 bool _isExecutableType(DartType type) { |
| 1622 type = type?.resolveToBound(_resolver.typeProvider.objectType); |
| 1475 if (type.isDynamic || type is FunctionType) { | 1623 if (type.isDynamic || type is FunctionType) { |
| 1476 return true; | 1624 return true; |
| 1477 } else if (!_enableStrictCallChecks && | 1625 } else if (!_enableStrictCallChecks && |
| 1478 (type.isDartCoreFunction || type.isObject)) { | 1626 (type.isDartCoreFunction || type.isObject)) { |
| 1479 return true; | 1627 return true; |
| 1480 } else if (type is InterfaceType) { | 1628 } else if (type is InterfaceType) { |
| 1481 ClassElement classElement = type.element; | 1629 ClassElement classElement = type.element; |
| 1482 // 16078 from Gilad: If the type is a Functor with the @proxy annotation, | 1630 // 16078 from Gilad: If the type is a Functor with the @proxy annotation, |
| 1483 // treat it as an executable type. | 1631 // treat it as an executable type. |
| 1484 // example code: NonErrorResolverTest. | 1632 // example code: NonErrorResolverTest. |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1532 */ | 1680 */ |
| 1533 AstNode _lookupBreakOrContinueTarget( | 1681 AstNode _lookupBreakOrContinueTarget( |
| 1534 AstNode parentNode, SimpleIdentifier labelNode, bool isContinue) { | 1682 AstNode parentNode, SimpleIdentifier labelNode, bool isContinue) { |
| 1535 if (labelNode == null) { | 1683 if (labelNode == null) { |
| 1536 return _resolver.implicitLabelScope.getTarget(isContinue); | 1684 return _resolver.implicitLabelScope.getTarget(isContinue); |
| 1537 } else { | 1685 } else { |
| 1538 LabelScope labelScope = _resolver.labelScope; | 1686 LabelScope labelScope = _resolver.labelScope; |
| 1539 if (labelScope == null) { | 1687 if (labelScope == null) { |
| 1540 // There are no labels in scope, so by definition the label is | 1688 // There are no labels in scope, so by definition the label is |
| 1541 // undefined. | 1689 // undefined. |
| 1542 _resolver.reportErrorForNode( | 1690 _resolver.errorReporter.reportErrorForNode( |
| 1543 CompileTimeErrorCode.LABEL_UNDEFINED, labelNode, [labelNode.name]); | 1691 CompileTimeErrorCode.LABEL_UNDEFINED, labelNode, [labelNode.name]); |
| 1544 return null; | 1692 return null; |
| 1545 } | 1693 } |
| 1546 LabelScope definingScope = labelScope.lookup(labelNode.name); | 1694 LabelScope definingScope = labelScope.lookup(labelNode.name); |
| 1547 if (definingScope == null) { | 1695 if (definingScope == null) { |
| 1548 // No definition of the given label name could be found in any | 1696 // No definition of the given label name could be found in any |
| 1549 // enclosing scope. | 1697 // enclosing scope. |
| 1550 _resolver.reportErrorForNode( | 1698 _resolver.errorReporter.reportErrorForNode( |
| 1551 CompileTimeErrorCode.LABEL_UNDEFINED, labelNode, [labelNode.name]); | 1699 CompileTimeErrorCode.LABEL_UNDEFINED, labelNode, [labelNode.name]); |
| 1552 return null; | 1700 return null; |
| 1553 } | 1701 } |
| 1554 // The target has been found. | 1702 // The target has been found. |
| 1555 labelNode.staticElement = definingScope.element; | 1703 labelNode.staticElement = definingScope.element; |
| 1556 ExecutableElement labelContainer = definingScope.element | 1704 ExecutableElement labelContainer = definingScope.element |
| 1557 .getAncestor((element) => element is ExecutableElement); | 1705 .getAncestor((element) => element is ExecutableElement); |
| 1558 if (!identical(labelContainer, _resolver.enclosingFunction)) { | 1706 if (!identical(labelContainer, _resolver.enclosingFunction)) { |
| 1559 _resolver.reportErrorForNode(CompileTimeErrorCode.LABEL_IN_OUTER_SCOPE, | 1707 _resolver.errorReporter.reportErrorForNode( |
| 1560 labelNode, [labelNode.name]); | 1708 CompileTimeErrorCode.LABEL_IN_OUTER_SCOPE, |
| 1709 labelNode, |
| 1710 [labelNode.name]); |
| 1561 } | 1711 } |
| 1562 return definingScope.node; | 1712 return definingScope.node; |
| 1563 } | 1713 } |
| 1564 } | 1714 } |
| 1565 | 1715 |
| 1566 /** | 1716 /** |
| 1567 * Look up the getter with the given [getterName] in the given [type]. Return | 1717 * Look up the getter with the given [getterName] in the given [type]. Return |
| 1568 * the element representing the getter that was found, or `null` if there is | 1718 * the element representing the getter that was found, or `null` if there is |
| 1569 * no getter with the given name. The [target] is the target of the | 1719 * no getter with the given name. The [target] is the target of the |
| 1570 * invocation, or `null` if there is no target. | 1720 * invocation, or `null` if there is no target. |
| 1571 */ | 1721 */ |
| 1572 PropertyAccessorElement _lookUpGetter( | 1722 PropertyAccessorElement _lookUpGetter( |
| 1573 Expression target, DartType type, String getterName) { | 1723 Expression target, DartType type, String getterName) { |
| 1574 type = _resolveTypeParameter(type); | 1724 type = _resolveTypeParameter(type); |
| 1575 if (type is InterfaceType) { | 1725 if (type is InterfaceType) { |
| 1576 InterfaceType interfaceType = type; | 1726 return type.lookUpInheritedGetter(getterName, |
| 1577 PropertyAccessorElement accessor; | 1727 library: _definingLibrary, thisType: target is! SuperExpression); |
| 1578 if (target is SuperExpression) { | |
| 1579 accessor = interfaceType.lookUpGetterInSuperclass( | |
| 1580 getterName, _definingLibrary); | |
| 1581 } else { | |
| 1582 accessor = interfaceType.lookUpGetter(getterName, _definingLibrary); | |
| 1583 } | |
| 1584 if (accessor != null) { | |
| 1585 return accessor; | |
| 1586 } | |
| 1587 return _lookUpGetterInInterfaces( | |
| 1588 interfaceType, false, getterName, new HashSet<ClassElement>()); | |
| 1589 } | 1728 } |
| 1590 return null; | 1729 return null; |
| 1591 } | 1730 } |
| 1592 | 1731 |
| 1593 /** | 1732 /** |
| 1594 * Look up the getter with the given [getterName] in the interfaces | |
| 1595 * implemented by the given [targetType], either directly or indirectly. | |
| 1596 * Return the element representing the getter that was found, or `null` if | |
| 1597 * there is no getter with the given name. The flag [includeTargetType] should | |
| 1598 * be `true` if the search should include the target type. The | |
| 1599 * [visitedInterfaces] is a set containing all of the interfaces that have | |
| 1600 * been examined, used to prevent infinite recursion and to optimize the | |
| 1601 * search. | |
| 1602 */ | |
| 1603 PropertyAccessorElement _lookUpGetterInInterfaces( | |
| 1604 InterfaceType targetType, | |
| 1605 bool includeTargetType, | |
| 1606 String getterName, | |
| 1607 HashSet<ClassElement> visitedInterfaces) { | |
| 1608 // TODO(brianwilkerson) This isn't correct. Section 8.1.1 of the | |
| 1609 // specification (titled "Inheritance and Overriding" under "Interfaces") | |
| 1610 // describes a much more complex scheme for finding the inherited member. | |
| 1611 // We need to follow that scheme. The code below should cover the 80% case. | |
| 1612 ClassElement targetClass = targetType.element; | |
| 1613 if (visitedInterfaces.contains(targetClass)) { | |
| 1614 return null; | |
| 1615 } | |
| 1616 visitedInterfaces.add(targetClass); | |
| 1617 if (includeTargetType) { | |
| 1618 PropertyAccessorElement getter = targetType.getGetter(getterName); | |
| 1619 if (getter != null && getter.isAccessibleIn(_definingLibrary)) { | |
| 1620 return getter; | |
| 1621 } | |
| 1622 } | |
| 1623 for (InterfaceType interfaceType in targetType.interfaces) { | |
| 1624 PropertyAccessorElement getter = _lookUpGetterInInterfaces( | |
| 1625 interfaceType, true, getterName, visitedInterfaces); | |
| 1626 if (getter != null) { | |
| 1627 return getter; | |
| 1628 } | |
| 1629 } | |
| 1630 for (InterfaceType mixinType in targetType.mixins.reversed) { | |
| 1631 PropertyAccessorElement getter = _lookUpGetterInInterfaces( | |
| 1632 mixinType, true, getterName, visitedInterfaces); | |
| 1633 if (getter != null) { | |
| 1634 return getter; | |
| 1635 } | |
| 1636 } | |
| 1637 InterfaceType superclass = targetType.superclass; | |
| 1638 if (superclass == null) { | |
| 1639 return null; | |
| 1640 } | |
| 1641 return _lookUpGetterInInterfaces( | |
| 1642 superclass, true, getterName, visitedInterfaces); | |
| 1643 } | |
| 1644 | |
| 1645 /** | |
| 1646 * Look up the method or getter with the given [memberName] in the given | 1733 * Look up the method or getter with the given [memberName] in the given |
| 1647 * [type]. Return the element representing the method or getter that was | 1734 * [type]. Return the element representing the method or getter that was |
| 1648 * found, or `null` if there is no method or getter with the given name. | 1735 * found, or `null` if there is no method or getter with the given name. |
| 1649 */ | 1736 */ |
| 1650 ExecutableElement _lookupGetterOrMethod(DartType type, String memberName) { | 1737 ExecutableElement _lookupGetterOrMethod(DartType type, String memberName) { |
| 1651 type = _resolveTypeParameter(type); | 1738 type = _resolveTypeParameter(type); |
| 1652 if (type is InterfaceType) { | 1739 if (type is InterfaceType) { |
| 1653 InterfaceType interfaceType = type; | 1740 return type.lookUpInheritedGetterOrMethod(memberName, |
| 1654 ExecutableElement member = | 1741 library: _definingLibrary); |
| 1655 interfaceType.lookUpMethod(memberName, _definingLibrary); | |
| 1656 if (member != null) { | |
| 1657 return member; | |
| 1658 } | |
| 1659 member = interfaceType.lookUpGetter(memberName, _definingLibrary); | |
| 1660 if (member != null) { | |
| 1661 return member; | |
| 1662 } | |
| 1663 return _lookUpGetterOrMethodInInterfaces( | |
| 1664 interfaceType, false, memberName, new HashSet<ClassElement>()); | |
| 1665 } | 1742 } |
| 1666 return null; | 1743 return null; |
| 1667 } | 1744 } |
| 1668 | 1745 |
| 1669 /** | 1746 /** |
| 1670 * Look up the method or getter with the given [memberName] in the interfaces | |
| 1671 * implemented by the given [targetType], either directly or indirectly. | |
| 1672 * Return the element representing the method or getter that was found, or | |
| 1673 * `null` if there is no method or getter with the given name. The flag | |
| 1674 * [includeTargetType] should be `true` if the search should include the | |
| 1675 * target type. The [visitedInterfaces] is a set containing all of the | |
| 1676 * interfaces that have been examined, used to prevent infinite recursion and | |
| 1677 * to optimize the search. | |
| 1678 */ | |
| 1679 ExecutableElement _lookUpGetterOrMethodInInterfaces( | |
| 1680 InterfaceType targetType, | |
| 1681 bool includeTargetType, | |
| 1682 String memberName, | |
| 1683 HashSet<ClassElement> visitedInterfaces) { | |
| 1684 // TODO(brianwilkerson) This isn't correct. Section 8.1.1 of the | |
| 1685 // specification (titled "Inheritance and Overriding" under "Interfaces") | |
| 1686 // describes a much more complex scheme for finding the inherited member. | |
| 1687 // We need to follow that scheme. The code below should cover the 80% case. | |
| 1688 ClassElement targetClass = targetType.element; | |
| 1689 if (visitedInterfaces.contains(targetClass)) { | |
| 1690 return null; | |
| 1691 } | |
| 1692 visitedInterfaces.add(targetClass); | |
| 1693 if (includeTargetType) { | |
| 1694 ExecutableElement member = targetType.getMethod(memberName); | |
| 1695 if (member != null) { | |
| 1696 return member; | |
| 1697 } | |
| 1698 member = targetType.getGetter(memberName); | |
| 1699 if (member != null) { | |
| 1700 return member; | |
| 1701 } | |
| 1702 } | |
| 1703 for (InterfaceType interfaceType in targetType.interfaces) { | |
| 1704 ExecutableElement member = _lookUpGetterOrMethodInInterfaces( | |
| 1705 interfaceType, true, memberName, visitedInterfaces); | |
| 1706 if (member != null) { | |
| 1707 return member; | |
| 1708 } | |
| 1709 } | |
| 1710 for (InterfaceType mixinType in targetType.mixins.reversed) { | |
| 1711 ExecutableElement member = _lookUpGetterOrMethodInInterfaces( | |
| 1712 mixinType, true, memberName, visitedInterfaces); | |
| 1713 if (member != null) { | |
| 1714 return member; | |
| 1715 } | |
| 1716 } | |
| 1717 InterfaceType superclass = targetType.superclass; | |
| 1718 if (superclass == null) { | |
| 1719 return null; | |
| 1720 } | |
| 1721 return _lookUpGetterOrMethodInInterfaces( | |
| 1722 superclass, true, memberName, visitedInterfaces); | |
| 1723 } | |
| 1724 | |
| 1725 /** | |
| 1726 * Look up the method with the given [methodName] in the given [type]. Return | 1747 * Look up the method with the given [methodName] in the given [type]. Return |
| 1727 * the element representing the method that was found, or `null` if there is | 1748 * the element representing the method that was found, or `null` if there is |
| 1728 * no method with the given name. The [target] is the target of the | 1749 * no method with the given name. The [target] is the target of the |
| 1729 * invocation, or `null` if there is no target. | 1750 * invocation, or `null` if there is no target. |
| 1730 */ | 1751 */ |
| 1731 MethodElement _lookUpMethod( | 1752 MethodElement _lookUpMethod( |
| 1732 Expression target, DartType type, String methodName) { | 1753 Expression target, DartType type, String methodName) { |
| 1733 type = _resolveTypeParameter(type); | 1754 type = _resolveTypeParameter(type); |
| 1734 if (type is InterfaceType) { | 1755 if (type is InterfaceType) { |
| 1735 InterfaceType interfaceType = type; | 1756 return type.lookUpInheritedMethod(methodName, |
| 1736 MethodElement method; | 1757 library: _definingLibrary, thisType: target is! SuperExpression); |
| 1737 if (target is SuperExpression) { | |
| 1738 method = interfaceType.lookUpMethodInSuperclass( | |
| 1739 methodName, _definingLibrary); | |
| 1740 } else { | |
| 1741 method = interfaceType.lookUpMethod(methodName, _definingLibrary); | |
| 1742 } | |
| 1743 if (method != null) { | |
| 1744 return method; | |
| 1745 } | |
| 1746 return _lookUpMethodInInterfaces( | |
| 1747 interfaceType, false, methodName, new HashSet<ClassElement>()); | |
| 1748 } | 1758 } |
| 1749 return null; | 1759 return null; |
| 1750 } | 1760 } |
| 1751 | 1761 |
| 1752 /** | 1762 /** |
| 1753 * Look up the method with the given [methodName] in the interfaces | |
| 1754 * implemented by the given [targetType], either directly or indirectly. | |
| 1755 * Return the element representing the method that was found, or `null` if | |
| 1756 * there is no method with the given name. The flag [includeTargetType] should | |
| 1757 * be `true` if the search should include the target type. The | |
| 1758 * [visitedInterfaces] is a set containing all of the interfaces that have | |
| 1759 * been examined, used to prevent infinite recursion and to optimize the | |
| 1760 * search. | |
| 1761 */ | |
| 1762 MethodElement _lookUpMethodInInterfaces( | |
| 1763 InterfaceType targetType, | |
| 1764 bool includeTargetType, | |
| 1765 String methodName, | |
| 1766 HashSet<ClassElement> visitedInterfaces) { | |
| 1767 // TODO(brianwilkerson) This isn't correct. Section 8.1.1 of the | |
| 1768 // specification (titled "Inheritance and Overriding" under "Interfaces") | |
| 1769 // describes a much more complex scheme for finding the inherited member. | |
| 1770 // We need to follow that scheme. The code below should cover the 80% case. | |
| 1771 ClassElement targetClass = targetType.element; | |
| 1772 if (visitedInterfaces.contains(targetClass)) { | |
| 1773 return null; | |
| 1774 } | |
| 1775 visitedInterfaces.add(targetClass); | |
| 1776 if (includeTargetType) { | |
| 1777 MethodElement method = targetType.getMethod(methodName); | |
| 1778 if (method != null && method.isAccessibleIn(_definingLibrary)) { | |
| 1779 return method; | |
| 1780 } | |
| 1781 } | |
| 1782 for (InterfaceType interfaceType in targetType.interfaces) { | |
| 1783 MethodElement method = _lookUpMethodInInterfaces( | |
| 1784 interfaceType, true, methodName, visitedInterfaces); | |
| 1785 if (method != null) { | |
| 1786 return method; | |
| 1787 } | |
| 1788 } | |
| 1789 for (InterfaceType mixinType in targetType.mixins.reversed) { | |
| 1790 MethodElement method = _lookUpMethodInInterfaces( | |
| 1791 mixinType, true, methodName, visitedInterfaces); | |
| 1792 if (method != null) { | |
| 1793 return method; | |
| 1794 } | |
| 1795 } | |
| 1796 InterfaceType superclass = targetType.superclass; | |
| 1797 if (superclass == null) { | |
| 1798 return null; | |
| 1799 } | |
| 1800 return _lookUpMethodInInterfaces( | |
| 1801 superclass, true, methodName, visitedInterfaces); | |
| 1802 } | |
| 1803 | |
| 1804 /** | |
| 1805 * Look up the setter with the given [setterName] in the given [type]. Return | 1763 * Look up the setter with the given [setterName] in the given [type]. Return |
| 1806 * the element representing the setter that was found, or `null` if there is | 1764 * the element representing the setter that was found, or `null` if there is |
| 1807 * no setter with the given name. The [target] is the target of the | 1765 * no setter with the given name. The [target] is the target of the |
| 1808 * invocation, or `null` if there is no target. | 1766 * invocation, or `null` if there is no target. |
| 1809 */ | 1767 */ |
| 1810 PropertyAccessorElement _lookUpSetter( | 1768 PropertyAccessorElement _lookUpSetter( |
| 1811 Expression target, DartType type, String setterName) { | 1769 Expression target, DartType type, String setterName) { |
| 1812 type = _resolveTypeParameter(type); | 1770 type = _resolveTypeParameter(type); |
| 1813 if (type is InterfaceType) { | 1771 if (type is InterfaceType) { |
| 1814 InterfaceType interfaceType = type; | 1772 return type.lookUpInheritedSetter(setterName, |
| 1815 PropertyAccessorElement accessor; | 1773 library: _definingLibrary, thisType: target is! SuperExpression); |
| 1816 if (target is SuperExpression) { | |
| 1817 accessor = interfaceType.lookUpSetterInSuperclass( | |
| 1818 setterName, _definingLibrary); | |
| 1819 } else { | |
| 1820 accessor = interfaceType.lookUpSetter(setterName, _definingLibrary); | |
| 1821 } | |
| 1822 if (accessor != null) { | |
| 1823 return accessor; | |
| 1824 } | |
| 1825 return _lookUpSetterInInterfaces( | |
| 1826 interfaceType, false, setterName, new HashSet<ClassElement>()); | |
| 1827 } | 1774 } |
| 1828 return null; | 1775 return null; |
| 1829 } | 1776 } |
| 1830 | 1777 |
| 1831 /** | 1778 /** |
| 1832 * Look up the setter with the given [setterName] in the interfaces | |
| 1833 * implemented by the given [targetType], either directly or indirectly. | |
| 1834 * Return the element representing the setter that was found, or `null` if | |
| 1835 * there is no setter with the given name. The [targetType] is the type in | |
| 1836 * which the setter might be defined. The flag [includeTargetType] should be | |
| 1837 * `true` if the search should include the target type. The | |
| 1838 * [visitedInterfaces] is a set containing all of the interfaces that have | |
| 1839 * been examined, used to prevent infinite recursion and to optimize the | |
| 1840 * search. | |
| 1841 */ | |
| 1842 PropertyAccessorElement _lookUpSetterInInterfaces( | |
| 1843 InterfaceType targetType, | |
| 1844 bool includeTargetType, | |
| 1845 String setterName, | |
| 1846 HashSet<ClassElement> visitedInterfaces) { | |
| 1847 // TODO(brianwilkerson) This isn't correct. Section 8.1.1 of the | |
| 1848 // specification (titled "Inheritance and Overriding" under "Interfaces") | |
| 1849 // describes a much more complex scheme for finding the inherited member. | |
| 1850 // We need to follow that scheme. The code below should cover the 80% case. | |
| 1851 ClassElement targetClass = targetType.element; | |
| 1852 if (visitedInterfaces.contains(targetClass)) { | |
| 1853 return null; | |
| 1854 } | |
| 1855 visitedInterfaces.add(targetClass); | |
| 1856 if (includeTargetType) { | |
| 1857 PropertyAccessorElement setter = targetType.getSetter(setterName); | |
| 1858 if (setter != null && setter.isAccessibleIn(_definingLibrary)) { | |
| 1859 return setter; | |
| 1860 } | |
| 1861 } | |
| 1862 for (InterfaceType interfaceType in targetType.interfaces) { | |
| 1863 PropertyAccessorElement setter = _lookUpSetterInInterfaces( | |
| 1864 interfaceType, true, setterName, visitedInterfaces); | |
| 1865 if (setter != null) { | |
| 1866 return setter; | |
| 1867 } | |
| 1868 } | |
| 1869 for (InterfaceType mixinType in targetType.mixins.reversed) { | |
| 1870 PropertyAccessorElement setter = _lookUpSetterInInterfaces( | |
| 1871 mixinType, true, setterName, visitedInterfaces); | |
| 1872 if (setter != null) { | |
| 1873 return setter; | |
| 1874 } | |
| 1875 } | |
| 1876 InterfaceType superclass = targetType.superclass; | |
| 1877 if (superclass == null) { | |
| 1878 return null; | |
| 1879 } | |
| 1880 return _lookUpSetterInInterfaces( | |
| 1881 superclass, true, setterName, visitedInterfaces); | |
| 1882 } | |
| 1883 | |
| 1884 /** | |
| 1885 * Given some class [element], this method uses [_subtypeManager] to find the | 1779 * Given some class [element], this method uses [_subtypeManager] to find the |
| 1886 * set of all subtypes; the subtypes are then searched for a member (method, | 1780 * set of all subtypes; the subtypes are then searched for a member (method, |
| 1887 * getter, or setter), that has the given [memberName]. The flag [asMethod] | 1781 * getter, or setter), that has the given [memberName]. The flag [asMethod] |
| 1888 * should be `true` if the methods should be searched for in the subtypes. The | 1782 * should be `true` if the methods should be searched for in the subtypes. The |
| 1889 * flag [asAccessor] should be `true` if the accessors (getters and setters) | 1783 * flag [asAccessor] should be `true` if the accessors (getters and setters) |
| 1890 * should be searched for in the subtypes. | 1784 * should be searched for in the subtypes. |
| 1891 */ | 1785 */ |
| 1892 bool _memberFoundInSubclass( | 1786 bool _memberFoundInSubclass( |
| 1893 Element element, String memberName, bool asMethod, bool asAccessor) { | 1787 Element element, String memberName, bool asMethod, bool asAccessor) { |
| 1894 if (element is ClassElement) { | 1788 if (element is ClassElement) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1905 } | 1799 } |
| 1906 } | 1800 } |
| 1907 } | 1801 } |
| 1908 return false; | 1802 return false; |
| 1909 } | 1803 } |
| 1910 | 1804 |
| 1911 /** | 1805 /** |
| 1912 * Return the binary operator that is invoked by the given compound assignment | 1806 * Return the binary operator that is invoked by the given compound assignment |
| 1913 * [operator]. | 1807 * [operator]. |
| 1914 */ | 1808 */ |
| 1915 sc.TokenType _operatorFromCompoundAssignment(sc.TokenType operator) { | 1809 TokenType _operatorFromCompoundAssignment(TokenType operator) { |
| 1916 while (true) { | 1810 if (operator == TokenType.AMPERSAND_EQ) { |
| 1917 if (operator == sc.TokenType.AMPERSAND_EQ) { | 1811 return TokenType.AMPERSAND; |
| 1918 return sc.TokenType.AMPERSAND; | 1812 } else if (operator == TokenType.BAR_EQ) { |
| 1919 } else if (operator == sc.TokenType.BAR_EQ) { | 1813 return TokenType.BAR; |
| 1920 return sc.TokenType.BAR; | 1814 } else if (operator == TokenType.CARET_EQ) { |
| 1921 } else if (operator == sc.TokenType.CARET_EQ) { | 1815 return TokenType.CARET; |
| 1922 return sc.TokenType.CARET; | 1816 } else if (operator == TokenType.GT_GT_EQ) { |
| 1923 } else if (operator == sc.TokenType.GT_GT_EQ) { | 1817 return TokenType.GT_GT; |
| 1924 return sc.TokenType.GT_GT; | 1818 } else if (operator == TokenType.LT_LT_EQ) { |
| 1925 } else if (operator == sc.TokenType.LT_LT_EQ) { | 1819 return TokenType.LT_LT; |
| 1926 return sc.TokenType.LT_LT; | 1820 } else if (operator == TokenType.MINUS_EQ) { |
| 1927 } else if (operator == sc.TokenType.MINUS_EQ) { | 1821 return TokenType.MINUS; |
| 1928 return sc.TokenType.MINUS; | 1822 } else if (operator == TokenType.PERCENT_EQ) { |
| 1929 } else if (operator == sc.TokenType.PERCENT_EQ) { | 1823 return TokenType.PERCENT; |
| 1930 return sc.TokenType.PERCENT; | 1824 } else if (operator == TokenType.PLUS_EQ) { |
| 1931 } else if (operator == sc.TokenType.PLUS_EQ) { | 1825 return TokenType.PLUS; |
| 1932 return sc.TokenType.PLUS; | 1826 } else if (operator == TokenType.SLASH_EQ) { |
| 1933 } else if (operator == sc.TokenType.SLASH_EQ) { | 1827 return TokenType.SLASH; |
| 1934 return sc.TokenType.SLASH; | 1828 } else if (operator == TokenType.STAR_EQ) { |
| 1935 } else if (operator == sc.TokenType.STAR_EQ) { | 1829 return TokenType.STAR; |
| 1936 return sc.TokenType.STAR; | 1830 } else if (operator == TokenType.TILDE_SLASH_EQ) { |
| 1937 } else if (operator == sc.TokenType.TILDE_SLASH_EQ) { | 1831 return TokenType.TILDE_SLASH; |
| 1938 return sc.TokenType.TILDE_SLASH; | 1832 } else { |
| 1939 } else { | 1833 // Internal error: Unmapped assignment operator. |
| 1940 // Internal error: Unmapped assignment operator. | 1834 AnalysisEngine.instance.logger.logError( |
| 1941 AnalysisEngine.instance.logger.logError( | 1835 "Failed to map ${operator.lexeme} to it's corresponding operator"); |
| 1942 "Failed to map ${operator.lexeme} to it's corresponding operator"); | 1836 return operator; |
| 1943 return operator; | |
| 1944 } | |
| 1945 break; | |
| 1946 } | 1837 } |
| 1947 } | 1838 } |
| 1948 | 1839 |
| 1949 /** | 1840 /** |
| 1841 * Determines if the [propagatedType] of the invoke is better (more specific) |
| 1842 * than the [staticType]. If so it will be returned, otherwise returns null. |
| 1843 */ |
| 1844 // TODO(jmesserly): can we refactor Resolver.recordPropagatedTypeIfBetter to |
| 1845 // get some code sharing? Right now, this method is to support |
| 1846 // `staticInvokeType` and `propagatedInvokeType`, and the one in Resolver is |
| 1847 // for `staticType` and `propagatedType` on Expression. |
| 1848 DartType _propagatedInvokeTypeIfBetter( |
| 1849 DartType propagatedType, DartType staticType) { |
| 1850 if (_resolver.strongMode || propagatedType == null) { |
| 1851 return null; |
| 1852 } |
| 1853 if (staticType == null || propagatedType.isMoreSpecificThan(staticType)) { |
| 1854 return propagatedType; |
| 1855 } |
| 1856 return null; |
| 1857 } |
| 1858 |
| 1859 /** |
| 1950 * Record that the given [node] is undefined, causing an error to be reported | 1860 * Record that the given [node] is undefined, causing an error to be reported |
| 1951 * if appropriate. The [declaringElement] is the element inside which no | 1861 * if appropriate. The [declaringElement] is the element inside which no |
| 1952 * declaration was found. If this element is a proxy, no error will be | 1862 * declaration was found. If this element is a proxy, no error will be |
| 1953 * reported. If null, then an error will always be reported. The [errorCode] | 1863 * reported. If null, then an error will always be reported. The [errorCode] |
| 1954 * is the error code to report. The [arguments] are the arguments to the error | 1864 * is the error code to report. The [arguments] are the arguments to the error |
| 1955 * message. | 1865 * message. |
| 1956 */ | 1866 */ |
| 1957 void _recordUndefinedNode(Element declaringElement, ErrorCode errorCode, | 1867 void _recordUndefinedNode(Element declaringElement, ErrorCode errorCode, |
| 1958 AstNode node, List<Object> arguments) { | 1868 AstNode node, List<Object> arguments) { |
| 1959 if (_doesntHaveProxy(declaringElement)) { | 1869 if (_doesntHaveProxy(declaringElement)) { |
| 1960 _resolver.reportErrorForNode(errorCode, node, arguments); | 1870 _resolver.errorReporter.reportErrorForNode(errorCode, node, arguments); |
| 1961 } | 1871 } |
| 1962 } | 1872 } |
| 1963 | 1873 |
| 1964 /** | 1874 /** |
| 1965 * Record that the given [offset]/[length] is undefined, causing an error to | 1875 * Record that the given [offset]/[length] is undefined, causing an error to |
| 1966 * be reported if appropriate. The [declaringElement] is the element inside | 1876 * be reported if appropriate. The [declaringElement] is the element inside |
| 1967 * which no declaration was found. If this element is a proxy, no error will | 1877 * which no declaration was found. If this element is a proxy, no error will |
| 1968 * be reported. If null, then an error will always be reported. The | 1878 * be reported. If null, then an error will always be reported. The |
| 1969 * [errorCode] is the error code to report. The [arguments] are arguments to | 1879 * [errorCode] is the error code to report. The [arguments] are arguments to |
| 1970 * the error message. | 1880 * the error message. |
| 1971 */ | 1881 */ |
| 1972 void _recordUndefinedOffset(Element declaringElement, ErrorCode errorCode, | 1882 void _recordUndefinedOffset(Element declaringElement, ErrorCode errorCode, |
| 1973 int offset, int length, List<Object> arguments) { | 1883 int offset, int length, List<Object> arguments) { |
| 1974 if (_doesntHaveProxy(declaringElement)) { | 1884 if (_doesntHaveProxy(declaringElement)) { |
| 1975 _resolver.reportErrorForOffset(errorCode, offset, length, arguments); | 1885 _resolver.errorReporter |
| 1886 .reportErrorForOffset(errorCode, offset, length, arguments); |
| 1976 } | 1887 } |
| 1977 } | 1888 } |
| 1978 | 1889 |
| 1979 /** | 1890 /** |
| 1980 * Record that the given [token] is undefined, causing an error to be reported | 1891 * Record that the given [token] is undefined, causing an error to be reported |
| 1981 * if appropriate. The [declaringElement] is the element inside which no | 1892 * if appropriate. The [declaringElement] is the element inside which no |
| 1982 * declaration was found. If this element is a proxy, no error will be | 1893 * declaration was found. If this element is a proxy, no error will be |
| 1983 * reported. If null, then an error will always be reported. The [errorCode] | 1894 * reported. If null, then an error will always be reported. The [errorCode] |
| 1984 * is the error code to report. The [arguments] are arguments to the error | 1895 * is the error code to report. The [arguments] are arguments to the error |
| 1985 * message. | 1896 * message. |
| 1986 */ | 1897 */ |
| 1987 void _recordUndefinedToken(Element declaringElement, ErrorCode errorCode, | 1898 void _recordUndefinedToken(Element declaringElement, ErrorCode errorCode, |
| 1988 sc.Token token, List<Object> arguments) { | 1899 Token token, List<Object> arguments) { |
| 1989 if (_doesntHaveProxy(declaringElement)) { | 1900 if (_doesntHaveProxy(declaringElement)) { |
| 1990 _resolver.reportErrorForToken(errorCode, token, arguments); | 1901 _resolver.errorReporter.reportErrorForToken(errorCode, token, arguments); |
| 1991 } | 1902 } |
| 1992 } | 1903 } |
| 1993 | 1904 |
| 1994 void _resolveAnnotationConstructorInvocationArguments( | 1905 void _resolveAnnotationConstructorInvocationArguments( |
| 1995 Annotation annotation, ConstructorElement constructor) { | 1906 Annotation annotation, ConstructorElement constructor) { |
| 1996 ArgumentList argumentList = annotation.arguments; | 1907 ArgumentList argumentList = annotation.arguments; |
| 1997 // error will be reported in ConstantVerifier | 1908 // error will be reported in ConstantVerifier |
| 1998 if (argumentList == null) { | 1909 if (argumentList == null) { |
| 1999 return; | 1910 return; |
| 2000 } | 1911 } |
| 2001 // resolve arguments to parameters | 1912 // resolve arguments to parameters |
| 2002 List<ParameterElement> parameters = | 1913 List<ParameterElement> parameters = |
| 2003 _resolveArgumentsToFunction(true, argumentList, constructor); | 1914 _resolveArgumentsToFunction(true, argumentList, constructor); |
| 2004 if (parameters != null) { | 1915 if (parameters != null) { |
| 2005 argumentList.correspondingStaticParameters = parameters; | 1916 argumentList.correspondingStaticParameters = parameters; |
| 2006 } | 1917 } |
| 2007 } | 1918 } |
| 2008 | 1919 |
| 2009 /** | 1920 /** |
| 2010 * Continues resolution of the given [annotation]. | 1921 * Continues resolution of the given [annotation]. |
| 2011 */ | 1922 */ |
| 2012 void _resolveAnnotationElement(Annotation annotation) { | 1923 void _resolveAnnotationElement(Annotation annotation) { |
| 2013 SimpleIdentifier nameNode1; | 1924 SimpleIdentifier nameNode1; |
| 2014 SimpleIdentifier nameNode2; | 1925 SimpleIdentifier nameNode2; |
| 2015 { | 1926 { |
| 2016 Identifier annName = annotation.name; | 1927 Identifier annName = annotation.name; |
| 2017 if (annName is PrefixedIdentifier) { | 1928 if (annName is PrefixedIdentifier) { |
| 2018 PrefixedIdentifier prefixed = annName; | 1929 nameNode1 = annName.prefix; |
| 2019 nameNode1 = prefixed.prefix; | 1930 nameNode2 = annName.identifier; |
| 2020 nameNode2 = prefixed.identifier; | |
| 2021 } else { | 1931 } else { |
| 2022 nameNode1 = annName as SimpleIdentifier; | 1932 nameNode1 = annName as SimpleIdentifier; |
| 2023 nameNode2 = null; | 1933 nameNode2 = null; |
| 2024 } | 1934 } |
| 2025 } | 1935 } |
| 2026 SimpleIdentifier nameNode3 = annotation.constructorName; | 1936 SimpleIdentifier nameNode3 = annotation.constructorName; |
| 2027 ConstructorElement constructor = null; | 1937 ConstructorElement constructor = null; |
| 2028 // | 1938 // |
| 2029 // CONST or Class(args) | 1939 // CONST or Class(args) |
| 2030 // | 1940 // |
| 2031 if (nameNode1 != null && nameNode2 == null && nameNode3 == null) { | 1941 if (nameNode1 != null && nameNode2 == null && nameNode3 == null) { |
| 2032 Element element1 = nameNode1.staticElement; | 1942 Element element1 = nameNode1.staticElement; |
| 2033 // CONST | 1943 // CONST |
| 2034 if (element1 is PropertyAccessorElement) { | 1944 if (element1 is PropertyAccessorElement) { |
| 2035 _resolveAnnotationElementGetter(annotation, element1); | 1945 _resolveAnnotationElementGetter(annotation, element1); |
| 2036 return; | 1946 return; |
| 2037 } | 1947 } |
| 2038 // Class(args) | 1948 // Class(args) |
| 2039 if (element1 is ClassElement) { | 1949 if (element1 is ClassElement) { |
| 2040 ClassElement classElement = element1; | 1950 constructor = new InterfaceTypeImpl(element1) |
| 2041 constructor = new InterfaceTypeImpl(classElement) | |
| 2042 .lookUpConstructor(null, _definingLibrary); | 1951 .lookUpConstructor(null, _definingLibrary); |
| 2043 } | 1952 } |
| 2044 } | 1953 } |
| 2045 // | 1954 // |
| 2046 // prefix.CONST or prefix.Class() or Class.CONST or Class.constructor(args) | 1955 // prefix.CONST or prefix.Class() or Class.CONST or Class.constructor(args) |
| 2047 // | 1956 // |
| 2048 if (nameNode1 != null && nameNode2 != null && nameNode3 == null) { | 1957 if (nameNode1 != null && nameNode2 != null && nameNode3 == null) { |
| 2049 Element element1 = nameNode1.staticElement; | 1958 Element element1 = nameNode1.staticElement; |
| 2050 Element element2 = nameNode2.staticElement; | 1959 Element element2 = nameNode2.staticElement; |
| 2051 // Class.CONST - not resolved yet | 1960 // Class.CONST - not resolved yet |
| 2052 if (element1 is ClassElement) { | 1961 if (element1 is ClassElement) { |
| 2053 ClassElement classElement = element1; | 1962 element2 = element1.lookUpGetter(nameNode2.name, _definingLibrary); |
| 2054 element2 = classElement.lookUpGetter(nameNode2.name, _definingLibrary); | |
| 2055 } | 1963 } |
| 2056 // prefix.CONST or Class.CONST | 1964 // prefix.CONST or Class.CONST |
| 2057 if (element2 is PropertyAccessorElement) { | 1965 if (element2 is PropertyAccessorElement) { |
| 2058 nameNode2.staticElement = element2; | 1966 nameNode2.staticElement = element2; |
| 2059 annotation.element = element2; | 1967 annotation.element = element2; |
| 2060 _resolveAnnotationElementGetter(annotation, element2); | 1968 _resolveAnnotationElementGetter(annotation, element2); |
| 2061 return; | 1969 return; |
| 2062 } | 1970 } |
| 2063 // prefix.Class() | 1971 // prefix.Class() |
| 2064 if (element2 is ClassElement) { | 1972 if (element2 is ClassElement) { |
| 2065 constructor = element2.unnamedConstructor; | 1973 constructor = element2.unnamedConstructor; |
| 2066 } | 1974 } |
| 2067 // Class.constructor(args) | 1975 // Class.constructor(args) |
| 2068 if (element1 is ClassElement) { | 1976 if (element1 is ClassElement) { |
| 2069 ClassElement classElement = element1; | 1977 constructor = new InterfaceTypeImpl(element1) |
| 2070 constructor = new InterfaceTypeImpl(classElement) | |
| 2071 .lookUpConstructor(nameNode2.name, _definingLibrary); | 1978 .lookUpConstructor(nameNode2.name, _definingLibrary); |
| 2072 nameNode2.staticElement = constructor; | 1979 nameNode2.staticElement = constructor; |
| 2073 } | 1980 } |
| 2074 } | 1981 } |
| 2075 // | 1982 // |
| 2076 // prefix.Class.CONST or prefix.Class.constructor(args) | 1983 // prefix.Class.CONST or prefix.Class.constructor(args) |
| 2077 // | 1984 // |
| 2078 if (nameNode1 != null && nameNode2 != null && nameNode3 != null) { | 1985 if (nameNode1 != null && nameNode2 != null && nameNode3 != null) { |
| 2079 Element element2 = nameNode2.staticElement; | 1986 Element element2 = nameNode2.staticElement; |
| 2080 // element2 should be ClassElement | 1987 // element2 should be ClassElement |
| 2081 if (element2 is ClassElement) { | 1988 if (element2 is ClassElement) { |
| 2082 ClassElement classElement = element2; | |
| 2083 String name3 = nameNode3.name; | 1989 String name3 = nameNode3.name; |
| 2084 // prefix.Class.CONST | 1990 // prefix.Class.CONST |
| 2085 PropertyAccessorElement getter = | 1991 PropertyAccessorElement getter = |
| 2086 classElement.lookUpGetter(name3, _definingLibrary); | 1992 element2.lookUpGetter(name3, _definingLibrary); |
| 2087 if (getter != null) { | 1993 if (getter != null) { |
| 2088 nameNode3.staticElement = getter; | 1994 nameNode3.staticElement = getter; |
| 2089 annotation.element = element2; | 1995 annotation.element = getter; |
| 2090 _resolveAnnotationElementGetter(annotation, getter); | 1996 _resolveAnnotationElementGetter(annotation, getter); |
| 2091 return; | 1997 return; |
| 2092 } | 1998 } |
| 2093 // prefix.Class.constructor(args) | 1999 // prefix.Class.constructor(args) |
| 2094 constructor = new InterfaceTypeImpl(classElement) | 2000 constructor = new InterfaceTypeImpl(element2) |
| 2095 .lookUpConstructor(name3, _definingLibrary); | 2001 .lookUpConstructor(name3, _definingLibrary); |
| 2096 nameNode3.staticElement = constructor; | 2002 nameNode3.staticElement = constructor; |
| 2097 } | 2003 } |
| 2098 } | 2004 } |
| 2099 // we need constructor | 2005 // we need constructor |
| 2100 if (constructor == null) { | 2006 if (constructor == null) { |
| 2101 _resolver.reportErrorForNode( | 2007 _resolver.errorReporter.reportErrorForNode( |
| 2102 CompileTimeErrorCode.INVALID_ANNOTATION, annotation); | 2008 CompileTimeErrorCode.INVALID_ANNOTATION, annotation); |
| 2103 return; | 2009 return; |
| 2104 } | 2010 } |
| 2105 // record element | 2011 // record element |
| 2106 annotation.element = constructor; | 2012 annotation.element = constructor; |
| 2107 // resolve arguments | 2013 // resolve arguments |
| 2108 _resolveAnnotationConstructorInvocationArguments(annotation, constructor); | 2014 _resolveAnnotationConstructorInvocationArguments(annotation, constructor); |
| 2109 } | 2015 } |
| 2110 | 2016 |
| 2111 void _resolveAnnotationElementGetter( | 2017 void _resolveAnnotationElementGetter( |
| 2112 Annotation annotation, PropertyAccessorElement accessorElement) { | 2018 Annotation annotation, PropertyAccessorElement accessorElement) { |
| 2113 // accessor should be synthetic | 2019 // accessor should be synthetic |
| 2114 if (!accessorElement.isSynthetic) { | 2020 if (!accessorElement.isSynthetic) { |
| 2115 _resolver.reportErrorForNode( | 2021 _resolver.errorReporter.reportErrorForNode( |
| 2116 CompileTimeErrorCode.INVALID_ANNOTATION, annotation); | 2022 CompileTimeErrorCode.INVALID_ANNOTATION, annotation); |
| 2117 return; | 2023 return; |
| 2118 } | 2024 } |
| 2119 // variable should be constant | 2025 // variable should be constant |
| 2120 VariableElement variableElement = accessorElement.variable; | 2026 VariableElement variableElement = accessorElement.variable; |
| 2121 if (!variableElement.isConst) { | 2027 if (!variableElement.isConst) { |
| 2122 _resolver.reportErrorForNode( | 2028 _resolver.errorReporter.reportErrorForNode( |
| 2123 CompileTimeErrorCode.INVALID_ANNOTATION, annotation); | 2029 CompileTimeErrorCode.INVALID_ANNOTATION, annotation); |
| 2124 } | 2030 } |
| 2031 // no arguments |
| 2032 if (annotation.arguments != null) { |
| 2033 _resolver.errorReporter.reportErrorForNode( |
| 2034 CompileTimeErrorCode.ANNOTATION_WITH_NON_CLASS, |
| 2035 annotation.name, |
| 2036 [annotation.name]); |
| 2037 } |
| 2125 // OK | 2038 // OK |
| 2126 return; | 2039 return; |
| 2127 } | 2040 } |
| 2128 | 2041 |
| 2129 /** | 2042 /** |
| 2130 * Given an [argumentList] and the [executableElement] that will be invoked | 2043 * Given an [argumentList] and the [executableElement] that will be invoked |
| 2131 * using those argument, compute the list of parameters that correspond to the | 2044 * using those argument, compute the list of parameters that correspond to the |
| 2132 * list of arguments. An error will be reported if any of the arguments cannot | 2045 * list of arguments. An error will be reported if any of the arguments cannot |
| 2133 * be matched to a parameter. The flag [reportError] should be `true` if a | 2046 * be matched to a parameter. The flag [reportAsError] should be `true` if a |
| 2134 * compile-time error should be reported; or `false` if a compile-time warning | 2047 * compile-time error should be reported; or `false` if a compile-time warning |
| 2135 * should be reported. Return the parameters that correspond to the arguments, | 2048 * should be reported. Return the parameters that correspond to the arguments, |
| 2136 * or `null` if no correspondence could be computed. | 2049 * or `null` if no correspondence could be computed. |
| 2137 */ | 2050 */ |
| 2138 List<ParameterElement> _resolveArgumentsToFunction(bool reportError, | 2051 List<ParameterElement> _resolveArgumentsToFunction(bool reportAsError, |
| 2139 ArgumentList argumentList, ExecutableElement executableElement) { | 2052 ArgumentList argumentList, ExecutableElement executableElement) { |
| 2140 if (executableElement == null) { | 2053 if (executableElement == null) { |
| 2141 return null; | 2054 return null; |
| 2142 } | 2055 } |
| 2143 List<ParameterElement> parameters = executableElement.parameters; | 2056 List<ParameterElement> parameters = executableElement.parameters; |
| 2144 return _resolveArgumentsToParameters(reportError, argumentList, parameters); | 2057 return _resolveArgumentsToParameters( |
| 2058 reportAsError, argumentList, parameters); |
| 2145 } | 2059 } |
| 2146 | 2060 |
| 2147 /** | 2061 /** |
| 2148 * Given an [argumentList] and the [parameters] related to the element that | 2062 * Given an [argumentList] and the [parameters] related to the element that |
| 2149 * will be invoked using those arguments, compute the list of parameters that | 2063 * will be invoked using those arguments, compute the list of parameters that |
| 2150 * correspond to the list of arguments. An error will be reported if any of | 2064 * correspond to the list of arguments. An error will be reported if any of |
| 2151 * the arguments cannot be matched to a parameter. The flag [reportError] | 2065 * the arguments cannot be matched to a parameter. The flag [reportAsError] |
| 2152 * should be `true` if a compile-time error should be reported; or `false` if | 2066 * should be `true` if a compile-time error should be reported; or `false` if |
| 2153 * a compile-time warning should be reported. Return the parameters that | 2067 * a compile-time warning should be reported. Return the parameters that |
| 2154 * correspond to the arguments. | 2068 * correspond to the arguments. |
| 2155 */ | 2069 */ |
| 2156 List<ParameterElement> _resolveArgumentsToParameters(bool reportError, | 2070 List<ParameterElement> _resolveArgumentsToParameters(bool reportAsError, |
| 2157 ArgumentList argumentList, List<ParameterElement> parameters) { | 2071 ArgumentList argumentList, List<ParameterElement> parameters) { |
| 2158 List<ParameterElement> requiredParameters = new List<ParameterElement>(); | 2072 return ResolverVisitor.resolveArgumentsToParameters( |
| 2159 List<ParameterElement> positionalParameters = new List<ParameterElement>(); | 2073 argumentList, parameters, _resolver.errorReporter.reportErrorForNode, |
| 2160 HashMap<String, ParameterElement> namedParameters = | 2074 reportAsError: reportAsError); |
| 2161 new HashMap<String, ParameterElement>(); | |
| 2162 for (ParameterElement parameter in parameters) { | |
| 2163 ParameterKind kind = parameter.parameterKind; | |
| 2164 if (kind == ParameterKind.REQUIRED) { | |
| 2165 requiredParameters.add(parameter); | |
| 2166 } else if (kind == ParameterKind.POSITIONAL) { | |
| 2167 positionalParameters.add(parameter); | |
| 2168 } else { | |
| 2169 namedParameters[parameter.name] = parameter; | |
| 2170 } | |
| 2171 } | |
| 2172 List<ParameterElement> unnamedParameters = | |
| 2173 new List<ParameterElement>.from(requiredParameters); | |
| 2174 unnamedParameters.addAll(positionalParameters); | |
| 2175 int unnamedParameterCount = unnamedParameters.length; | |
| 2176 int unnamedIndex = 0; | |
| 2177 NodeList<Expression> arguments = argumentList.arguments; | |
| 2178 int argumentCount = arguments.length; | |
| 2179 List<ParameterElement> resolvedParameters = | |
| 2180 new List<ParameterElement>(argumentCount); | |
| 2181 int positionalArgumentCount = 0; | |
| 2182 HashSet<String> usedNames = new HashSet<String>(); | |
| 2183 bool noBlankArguments = true; | |
| 2184 for (int i = 0; i < argumentCount; i++) { | |
| 2185 Expression argument = arguments[i]; | |
| 2186 if (argument is NamedExpression) { | |
| 2187 SimpleIdentifier nameNode = argument.name.label; | |
| 2188 String name = nameNode.name; | |
| 2189 ParameterElement element = namedParameters[name]; | |
| 2190 if (element == null) { | |
| 2191 ErrorCode errorCode = (reportError | |
| 2192 ? CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER | |
| 2193 : StaticWarningCode.UNDEFINED_NAMED_PARAMETER); | |
| 2194 _resolver.reportErrorForNode(errorCode, nameNode, [name]); | |
| 2195 } else { | |
| 2196 resolvedParameters[i] = element; | |
| 2197 nameNode.staticElement = element; | |
| 2198 } | |
| 2199 if (!usedNames.add(name)) { | |
| 2200 _resolver.reportErrorForNode( | |
| 2201 CompileTimeErrorCode.DUPLICATE_NAMED_ARGUMENT, nameNode, [name]); | |
| 2202 } | |
| 2203 } else { | |
| 2204 if (argument is SimpleIdentifier && argument.name.isEmpty) { | |
| 2205 noBlankArguments = false; | |
| 2206 } | |
| 2207 positionalArgumentCount++; | |
| 2208 if (unnamedIndex < unnamedParameterCount) { | |
| 2209 resolvedParameters[i] = unnamedParameters[unnamedIndex++]; | |
| 2210 } | |
| 2211 } | |
| 2212 } | |
| 2213 if (positionalArgumentCount < requiredParameters.length && | |
| 2214 noBlankArguments) { | |
| 2215 ErrorCode errorCode = (reportError | |
| 2216 ? CompileTimeErrorCode.NOT_ENOUGH_REQUIRED_ARGUMENTS | |
| 2217 : StaticWarningCode.NOT_ENOUGH_REQUIRED_ARGUMENTS); | |
| 2218 _resolver.reportErrorForNode(errorCode, argumentList, | |
| 2219 [requiredParameters.length, positionalArgumentCount]); | |
| 2220 } else if (positionalArgumentCount > unnamedParameterCount && | |
| 2221 noBlankArguments) { | |
| 2222 ErrorCode errorCode = (reportError | |
| 2223 ? CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS | |
| 2224 : StaticWarningCode.EXTRA_POSITIONAL_ARGUMENTS); | |
| 2225 _resolver.reportErrorForNode(errorCode, argumentList, | |
| 2226 [unnamedParameterCount, positionalArgumentCount]); | |
| 2227 } | |
| 2228 return resolvedParameters; | |
| 2229 } | 2075 } |
| 2230 | 2076 |
| 2231 void _resolveBinaryExpression(BinaryExpression node, String methodName) { | 2077 void _resolveBinaryExpression(BinaryExpression node, String methodName) { |
| 2232 Expression leftOperand = node.leftOperand; | 2078 Expression leftOperand = node.leftOperand; |
| 2233 if (leftOperand != null) { | 2079 if (leftOperand != null) { |
| 2234 DartType staticType = _getStaticType(leftOperand); | 2080 DartType staticType = _getStaticType(leftOperand); |
| 2235 MethodElement staticMethod = | 2081 MethodElement staticMethod = |
| 2236 _lookUpMethod(leftOperand, staticType, methodName); | 2082 _lookUpMethod(leftOperand, staticType, methodName); |
| 2237 node.staticElement = staticMethod; | 2083 node.staticElement = staticMethod; |
| 2238 DartType propagatedType = _getPropagatedType(leftOperand); | 2084 DartType propagatedType = _getPropagatedType(leftOperand); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2283 new NamespaceBuilder().createExportNamespaceForLibrary(library); | 2129 new NamespaceBuilder().createExportNamespaceForLibrary(library); |
| 2284 for (Combinator combinator in combinators) { | 2130 for (Combinator combinator in combinators) { |
| 2285 NodeList<SimpleIdentifier> names; | 2131 NodeList<SimpleIdentifier> names; |
| 2286 if (combinator is HideCombinator) { | 2132 if (combinator is HideCombinator) { |
| 2287 names = combinator.hiddenNames; | 2133 names = combinator.hiddenNames; |
| 2288 } else { | 2134 } else { |
| 2289 names = (combinator as ShowCombinator).shownNames; | 2135 names = (combinator as ShowCombinator).shownNames; |
| 2290 } | 2136 } |
| 2291 for (SimpleIdentifier name in names) { | 2137 for (SimpleIdentifier name in names) { |
| 2292 String nameStr = name.name; | 2138 String nameStr = name.name; |
| 2293 Element element = namespace.get(nameStr); | 2139 Element element = namespace.get(nameStr) ?? namespace.get("$nameStr="); |
| 2294 if (element == null) { | |
| 2295 element = namespace.get("$nameStr="); | |
| 2296 } | |
| 2297 if (element != null) { | 2140 if (element != null) { |
| 2298 // Ensure that the name always resolves to a top-level variable | 2141 // Ensure that the name always resolves to a top-level variable |
| 2299 // rather than a getter or setter | 2142 // rather than a getter or setter |
| 2300 if (element is PropertyAccessorElement) { | 2143 if (element is PropertyAccessorElement) { |
| 2301 element = (element as PropertyAccessorElement).variable; | 2144 name.staticElement = element.variable; |
| 2145 } else { |
| 2146 name.staticElement = element; |
| 2302 } | 2147 } |
| 2303 name.staticElement = element; | |
| 2304 } | 2148 } |
| 2305 } | 2149 } |
| 2306 } | 2150 } |
| 2307 } | 2151 } |
| 2308 | 2152 |
| 2309 /** | 2153 /** |
| 2310 * Given that we are accessing a property of the given [classElement] with the | 2154 * Given that we are accessing a property of the given [classElement] with the |
| 2311 * given [propertyName], return the element that represents the property. | 2155 * given [propertyName], return the element that represents the property. |
| 2312 */ | 2156 */ |
| 2313 Element _resolveElement( | 2157 Element _resolveElement( |
| 2314 ClassElementImpl classElement, SimpleIdentifier propertyName) { | 2158 ClassElement classElement, SimpleIdentifier propertyName) { |
| 2315 String name = propertyName.name; | 2159 String name = propertyName.name; |
| 2316 Element element = null; | 2160 Element element = null; |
| 2317 if (propertyName.inSetterContext()) { | 2161 if (propertyName.inSetterContext()) { |
| 2318 element = classElement.getSetter(name); | 2162 element = classElement.getSetter(name); |
| 2319 } | 2163 } |
| 2320 if (element == null) { | 2164 if (element == null) { |
| 2321 element = classElement.getGetter(name); | 2165 element = classElement.getGetter(name); |
| 2322 } | 2166 } |
| 2323 if (element == null) { | 2167 if (element == null) { |
| 2324 element = classElement.getMethod(name); | 2168 element = classElement.getMethod(name); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2369 * element being invoked. If the returned element is a method, then the method | 2213 * element being invoked. If the returned element is a method, then the method |
| 2370 * will be invoked. If the returned element is a getter, the getter will be | 2214 * will be invoked. If the returned element is a getter, the getter will be |
| 2371 * invoked without arguments and the result of that invocation will then be | 2215 * invoked without arguments and the result of that invocation will then be |
| 2372 * invoked with the arguments. The [target] is the target of the invocation | 2216 * invoked with the arguments. The [target] is the target of the invocation |
| 2373 * ('e'). The [targetType] is the type of the target. The [methodName] is th | 2217 * ('e'). The [targetType] is the type of the target. The [methodName] is th |
| 2374 * name of the method being invoked ('m'). [isConditional] indicates | 2218 * name of the method being invoked ('m'). [isConditional] indicates |
| 2375 * whether the invocatoin uses a '?.' operator. | 2219 * whether the invocatoin uses a '?.' operator. |
| 2376 */ | 2220 */ |
| 2377 Element _resolveInvokedElementWithTarget(Expression target, | 2221 Element _resolveInvokedElementWithTarget(Expression target, |
| 2378 DartType targetType, SimpleIdentifier methodName, bool isConditional) { | 2222 DartType targetType, SimpleIdentifier methodName, bool isConditional) { |
| 2223 String name = methodName.name; |
| 2379 if (targetType is InterfaceType) { | 2224 if (targetType is InterfaceType) { |
| 2380 Element element = _lookUpMethod(target, targetType, methodName.name); | 2225 Element element = _lookUpMethod(target, targetType, name); |
| 2381 if (element == null) { | 2226 if (element == null) { |
| 2382 // | 2227 // |
| 2383 // If there's no method, then it's possible that 'm' is a getter that | 2228 // If there's no method, then it's possible that 'm' is a getter that |
| 2384 // returns a function. | 2229 // returns a function. |
| 2385 // | 2230 // |
| 2386 // TODO (collinsn): need to add union type support here too, in the | 2231 // TODO (collinsn): need to add union type support here too, in the |
| 2387 // style of [lookUpMethod]. | 2232 // style of [lookUpMethod]. |
| 2388 element = _lookUpGetter(target, targetType, methodName.name); | 2233 element = _lookUpGetter(target, targetType, name); |
| 2389 } | 2234 } |
| 2390 return element; | 2235 return element; |
| 2236 } else if (targetType is FunctionType && |
| 2237 _resolver.typeProvider.isObjectMethod(name)) { |
| 2238 return _resolver.typeProvider.objectType.element.getMethod(name); |
| 2391 } else if (target is SimpleIdentifier) { | 2239 } else if (target is SimpleIdentifier) { |
| 2392 Element targetElement = target.staticElement; | 2240 Element targetElement = target.staticElement; |
| 2241 if (targetType is FunctionType && |
| 2242 name == FunctionElement.CALL_METHOD_NAME) { |
| 2243 return targetElement; |
| 2244 } |
| 2393 if (targetElement is PrefixElement) { | 2245 if (targetElement is PrefixElement) { |
| 2394 if (isConditional) { | 2246 if (isConditional) { |
| 2395 _resolver.reportErrorForNode( | 2247 _resolver.errorReporter.reportErrorForNode( |
| 2396 CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, | 2248 CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, |
| 2397 target, | 2249 target, |
| 2398 [target.name]); | 2250 [target.name]); |
| 2399 } | 2251 } |
| 2400 // | 2252 // |
| 2401 // Look to see whether the name of the method is really part of a | 2253 // Look to see whether the name of the method is really part of a |
| 2402 // prefixed identifier for an imported top-level function or top-level | 2254 // prefixed identifier for an imported top-level function or top-level |
| 2403 // getter that returns a function. | 2255 // getter that returns a function. |
| 2404 // | 2256 // |
| 2405 String name = "${target.name}.$methodName"; | 2257 Identifier functionName = |
| 2406 Identifier functionName = new SyntheticIdentifier(name, methodName); | 2258 new PrefixedIdentifierImpl.temp(target, methodName); |
| 2407 Element element = | 2259 Element element = |
| 2408 _resolver.nameScope.lookup(functionName, _definingLibrary); | 2260 _resolver.nameScope.lookup(functionName, _definingLibrary); |
| 2409 if (element != null) { | 2261 if (element != null) { |
| 2410 // TODO(brianwilkerson) This isn't a method invocation, it's a | 2262 // TODO(brianwilkerson) This isn't a method invocation, it's a |
| 2411 // function invocation where the function name is a prefixed | 2263 // function invocation where the function name is a prefixed |
| 2412 // identifier. Consider re-writing the AST. | 2264 // identifier. Consider re-writing the AST. |
| 2413 return element; | 2265 return element; |
| 2414 } | 2266 } |
| 2415 } | 2267 } |
| 2416 } | 2268 } |
| 2417 // TODO(brianwilkerson) Report this error. | 2269 // TODO(brianwilkerson) Report this error. |
| 2418 return null; | 2270 return null; |
| 2419 } | 2271 } |
| 2420 | 2272 |
| 2421 /** | 2273 /** |
| 2274 * Given a [node] that can have annotations associated with it, resolve the |
| 2275 * annotations in the element model representing annotations to the node. |
| 2276 */ |
| 2277 void _resolveMetadataForParameter(NormalFormalParameter node) { |
| 2278 _resolveAnnotations(node.metadata); |
| 2279 } |
| 2280 |
| 2281 /** |
| 2422 * Given that we are accessing a property of the given [targetType] with the | 2282 * Given that we are accessing a property of the given [targetType] with the |
| 2423 * given [propertyName], return the element that represents the property. The | 2283 * given [propertyName], return the element that represents the property. The |
| 2424 * [target] is the target of the invocation ('e'). | 2284 * [target] is the target of the invocation ('e'). |
| 2425 */ | 2285 */ |
| 2426 ExecutableElement _resolveProperty( | 2286 ExecutableElement _resolveProperty( |
| 2427 Expression target, DartType targetType, SimpleIdentifier propertyName) { | 2287 Expression target, DartType targetType, SimpleIdentifier propertyName) { |
| 2428 ExecutableElement memberElement = null; | 2288 ExecutableElement memberElement = null; |
| 2429 if (propertyName.inSetterContext()) { | 2289 if (propertyName.inSetterContext()) { |
| 2430 memberElement = _lookUpSetter(target, targetType, propertyName.name); | 2290 memberElement = _lookUpSetter(target, targetType, propertyName.name); |
| 2431 } | 2291 } |
| 2432 if (memberElement == null) { | 2292 if (memberElement == null) { |
| 2433 memberElement = _lookUpGetter(target, targetType, propertyName.name); | 2293 memberElement = _lookUpGetter(target, targetType, propertyName.name); |
| 2434 } | 2294 } |
| 2435 if (memberElement == null) { | 2295 if (memberElement == null) { |
| 2436 memberElement = _lookUpMethod(target, targetType, propertyName.name); | 2296 memberElement = _lookUpMethod(target, targetType, propertyName.name); |
| 2437 } | 2297 } |
| 2438 return memberElement; | 2298 return memberElement; |
| 2439 } | 2299 } |
| 2440 | 2300 |
| 2441 void _resolvePropertyAccess( | 2301 void _resolvePropertyAccess( |
| 2442 Expression target, SimpleIdentifier propertyName) { | 2302 Expression target, SimpleIdentifier propertyName, bool isCascaded) { |
| 2443 DartType staticType = _getStaticType(target); | 2303 DartType staticType = _getStaticType(target); |
| 2444 DartType propagatedType = _getPropagatedType(target); | 2304 DartType propagatedType = _getPropagatedType(target); |
| 2445 Element staticElement = null; | 2305 Element staticElement = null; |
| 2446 Element propagatedElement = null; | 2306 Element propagatedElement = null; |
| 2447 // | 2307 // |
| 2448 // If this property access is of the form 'C.m' where 'C' is a class, | 2308 // If this property access is of the form 'C.m' where 'C' is a class, |
| 2449 // then we don't call resolveProperty(...) which walks up the class | 2309 // then we don't call resolveProperty(...) which walks up the class |
| 2450 // hierarchy, instead we just look for the member in the type only. This | 2310 // hierarchy, instead we just look for the member in the type only. This |
| 2451 // does not apply to conditional property accesses (i.e. 'C?.m'). | 2311 // does not apply to conditional property accesses (i.e. 'C?.m'). |
| 2452 // | 2312 // |
| 2453 ClassElementImpl typeReference = getTypeReference(target); | 2313 ClassElement typeReference = getTypeReference(target); |
| 2454 if (typeReference != null) { | 2314 if (typeReference != null) { |
| 2315 if (isCascaded) { |
| 2316 typeReference = _typeType.element; |
| 2317 } |
| 2455 // TODO(brianwilkerson) Why are we setting the propagated element here? | 2318 // TODO(brianwilkerson) Why are we setting the propagated element here? |
| 2456 // It looks wrong. | 2319 // It looks wrong. |
| 2457 staticElement = | 2320 staticElement = |
| 2458 propagatedElement = _resolveElement(typeReference, propertyName); | 2321 propagatedElement = _resolveElement(typeReference, propertyName); |
| 2459 } else { | 2322 } else { |
| 2460 staticElement = _resolveProperty(target, staticType, propertyName); | 2323 staticElement = _resolveProperty(target, staticType, propertyName); |
| 2461 propagatedElement = | 2324 propagatedElement = |
| 2462 _resolveProperty(target, propagatedType, propertyName); | 2325 _resolveProperty(target, propagatedType, propertyName); |
| 2463 } | 2326 } |
| 2464 // May be part of annotation, record property element only if exists. | 2327 // May be part of annotation, record property element only if exists. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2478 _enableHints && | 2341 _enableHints && |
| 2479 _shouldReportMissingMember(propagatedType, propagatedElement) && | 2342 _shouldReportMissingMember(propagatedType, propagatedElement) && |
| 2480 !_memberFoundInSubclass( | 2343 !_memberFoundInSubclass( |
| 2481 propagatedType.element, propertyName.name, false, true); | 2344 propagatedType.element, propertyName.name, false, true); |
| 2482 if (shouldReportMissingMember_static || | 2345 if (shouldReportMissingMember_static || |
| 2483 shouldReportMissingMember_propagated) { | 2346 shouldReportMissingMember_propagated) { |
| 2484 DartType staticOrPropagatedType = | 2347 DartType staticOrPropagatedType = |
| 2485 shouldReportMissingMember_static ? staticType : propagatedType; | 2348 shouldReportMissingMember_static ? staticType : propagatedType; |
| 2486 Element staticOrPropagatedEnclosingElt = staticOrPropagatedType.element; | 2349 Element staticOrPropagatedEnclosingElt = staticOrPropagatedType.element; |
| 2487 bool isStaticProperty = _isStatic(staticOrPropagatedEnclosingElt); | 2350 bool isStaticProperty = _isStatic(staticOrPropagatedEnclosingElt); |
| 2488 DartType displayType = staticOrPropagatedType != null | 2351 DartType displayType = |
| 2489 ? staticOrPropagatedType | 2352 staticOrPropagatedType ?? propagatedType ?? staticType; |
| 2490 : propagatedType != null ? propagatedType : staticType; | |
| 2491 // Special getter cases. | 2353 // Special getter cases. |
| 2492 if (propertyName.inGetterContext()) { | 2354 if (propertyName.inGetterContext()) { |
| 2493 if (!isStaticProperty && | 2355 if (!isStaticProperty && |
| 2494 staticOrPropagatedEnclosingElt is ClassElement) { | 2356 staticOrPropagatedEnclosingElt is ClassElement) { |
| 2495 ClassElement classElement = staticOrPropagatedEnclosingElt; | 2357 InterfaceType targetType = staticOrPropagatedEnclosingElt.type; |
| 2496 InterfaceType targetType = classElement.type; | |
| 2497 if (!_enableStrictCallChecks && | 2358 if (!_enableStrictCallChecks && |
| 2498 targetType != null && | 2359 targetType != null && |
| 2499 targetType.isDartCoreFunction && | 2360 targetType.isDartCoreFunction && |
| 2500 propertyName.name == FunctionElement.CALL_METHOD_NAME) { | 2361 propertyName.name == FunctionElement.CALL_METHOD_NAME) { |
| 2501 // TODO(brianwilkerson) Can we ever resolve the function being | 2362 // TODO(brianwilkerson) Can we ever resolve the function being |
| 2502 // invoked? | 2363 // invoked? |
| 2503 // resolveArgumentsToParameters(node.getArgumentList(), invokedFuncti
on); | 2364 // resolveArgumentsToParameters(node.getArgumentList(), invokedFuncti
on); |
| 2504 return; | 2365 return; |
| 2505 } else if (classElement.isEnum && propertyName.name == "_name") { | 2366 } else if (staticOrPropagatedEnclosingElt.isEnum && |
| 2506 _resolver.reportErrorForNode( | 2367 propertyName.name == "_name") { |
| 2368 _resolver.errorReporter.reportErrorForNode( |
| 2507 CompileTimeErrorCode.ACCESS_PRIVATE_ENUM_FIELD, | 2369 CompileTimeErrorCode.ACCESS_PRIVATE_ENUM_FIELD, |
| 2508 propertyName, | 2370 propertyName, |
| 2509 [propertyName.name]); | 2371 [propertyName.name]); |
| 2510 return; | 2372 return; |
| 2511 } | 2373 } |
| 2512 } | 2374 } |
| 2513 } | 2375 } |
| 2514 Element declaringElement = | 2376 Element declaringElement = |
| 2515 staticType.isVoid ? null : staticOrPropagatedEnclosingElt; | 2377 staticType.isVoid ? null : staticOrPropagatedEnclosingElt; |
| 2516 if (propertyName.inSetterContext()) { | 2378 if (propertyName.inSetterContext()) { |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2587 setter = _lookUpSetter(null, enclosingClass.type, identifier.name); | 2449 setter = _lookUpSetter(null, enclosingClass.type, identifier.name); |
| 2588 } | 2450 } |
| 2589 } | 2451 } |
| 2590 if (setter != null) { | 2452 if (setter != null) { |
| 2591 element = setter; | 2453 element = setter; |
| 2592 } | 2454 } |
| 2593 } | 2455 } |
| 2594 } else if (element == null && | 2456 } else if (element == null && |
| 2595 (identifier.inSetterContext() || | 2457 (identifier.inSetterContext() || |
| 2596 identifier.parent is CommentReference)) { | 2458 identifier.parent is CommentReference)) { |
| 2597 element = _resolver.nameScope.lookup( | 2459 Identifier setterId = |
| 2598 new SyntheticIdentifier("${identifier.name}=", identifier), | 2460 new SyntheticIdentifier('${identifier.name}=', identifier); |
| 2599 _definingLibrary); | 2461 element = _resolver.nameScope.lookup(setterId, _definingLibrary); |
| 2462 identifier.setProperty(LibraryImportScope.conflictingSdkElements, |
| 2463 setterId.getProperty(LibraryImportScope.conflictingSdkElements)); |
| 2600 } | 2464 } |
| 2601 ClassElement enclosingClass = _resolver.enclosingClass; | 2465 ClassElement enclosingClass = _resolver.enclosingClass; |
| 2602 if (element == null && enclosingClass != null) { | 2466 if (element == null && enclosingClass != null) { |
| 2603 InterfaceType enclosingType = enclosingClass.type; | 2467 InterfaceType enclosingType = enclosingClass.type; |
| 2604 if (element == null && | 2468 if (element == null && |
| 2605 (identifier.inSetterContext() || | 2469 (identifier.inSetterContext() || |
| 2606 identifier.parent is CommentReference)) { | 2470 identifier.parent is CommentReference)) { |
| 2607 element = _lookUpSetter(null, enclosingType, identifier.name); | 2471 element = _lookUpSetter(null, enclosingType, identifier.name); |
| 2608 } | 2472 } |
| 2609 if (element == null && identifier.inGetterContext()) { | 2473 if (element == null && identifier.inGetterContext()) { |
| 2610 element = _lookUpGetter(null, enclosingType, identifier.name); | 2474 element = _lookUpGetter(null, enclosingType, identifier.name); |
| 2611 } | 2475 } |
| 2612 if (element == null) { | 2476 if (element == null) { |
| 2613 element = _lookUpMethod(null, enclosingType, identifier.name); | 2477 element = _lookUpMethod(null, enclosingType, identifier.name); |
| 2614 } | 2478 } |
| 2615 } | 2479 } |
| 2616 return element; | 2480 return element; |
| 2617 } | 2481 } |
| 2618 | 2482 |
| 2619 /** | 2483 /** |
| 2620 * If the given [type] is a type parameter, resolve it to the type that should | 2484 * If the given [type] is a type parameter, resolve it to the type that should |
| 2621 * be used when looking up members. Otherwise, return the original type. | 2485 * be used when looking up members. Otherwise, return the original type. |
| 2622 */ | 2486 */ |
| 2623 DartType _resolveTypeParameter(DartType type) { | 2487 DartType _resolveTypeParameter(DartType type) => |
| 2624 if (type is TypeParameterType) { | 2488 type?.resolveToBound(_resolver.typeProvider.objectType); |
| 2625 DartType bound = type.element.bound; | |
| 2626 if (bound == null) { | |
| 2627 return _resolver.typeProvider.objectType; | |
| 2628 } | |
| 2629 return bound; | |
| 2630 } | |
| 2631 return type; | |
| 2632 } | |
| 2633 | |
| 2634 /** | |
| 2635 * Given a [node] that can have annotations associated with it and the | |
| 2636 * [element] to which that node has been resolved, create the annotations in | |
| 2637 * the element model representing the annotations on the node. | |
| 2638 */ | |
| 2639 void _setMetadataForParameter(Element element, NormalFormalParameter node) { | |
| 2640 if (element is! ElementImpl) { | |
| 2641 return; | |
| 2642 } | |
| 2643 List<ElementAnnotationImpl> annotationList = | |
| 2644 new List<ElementAnnotationImpl>(); | |
| 2645 _addAnnotations(annotationList, node.metadata); | |
| 2646 if (!annotationList.isEmpty) { | |
| 2647 (element as ElementImpl).metadata = annotationList; | |
| 2648 } | |
| 2649 } | |
| 2650 | 2489 |
| 2651 /** | 2490 /** |
| 2652 * Return `true` if we should report an error as a result of looking up a | 2491 * Return `true` if we should report an error as a result of looking up a |
| 2653 * [member] in the given [type] and not finding any member. | 2492 * [member] in the given [type] and not finding any member. |
| 2654 */ | 2493 */ |
| 2655 bool _shouldReportMissingMember(DartType type, Element member) { | 2494 bool _shouldReportMissingMember(DartType type, Element member) { |
| 2656 if (member != null || type == null || type.isDynamic || type.isBottom) { | 2495 return member == null && type != null && !type.isDynamic && !type.isBottom; |
| 2657 return false; | |
| 2658 } | |
| 2659 return true; | |
| 2660 } | 2496 } |
| 2661 | 2497 |
| 2662 /** | 2498 /** |
| 2663 * Checks whether the given [expression] is a reference to a class. If it is | 2499 * Checks whether the given [expression] is a reference to a class. If it is |
| 2664 * then the element representing the class is returned, otherwise `null` is | 2500 * then the element representing the class is returned, otherwise `null` is |
| 2665 * returned. | 2501 * returned. |
| 2666 */ | 2502 */ |
| 2667 static ClassElementImpl getTypeReference(Expression expression) { | 2503 static ClassElement getTypeReference(Expression expression) { |
| 2668 if (expression is Identifier) { | 2504 if (expression is Identifier) { |
| 2669 Element staticElement = expression.staticElement; | 2505 Element staticElement = expression.staticElement; |
| 2670 if (staticElement is ClassElementImpl) { | 2506 if (staticElement is ClassElement) { |
| 2671 return staticElement; | 2507 return staticElement; |
| 2672 } | 2508 } |
| 2673 } | 2509 } |
| 2674 return null; | 2510 return null; |
| 2675 } | 2511 } |
| 2676 | 2512 |
| 2677 /** | 2513 /** |
| 2678 * Given a [node] that can have annotations associated with it and the | 2514 * Given a [node] that can have annotations associated with it, resolve the |
| 2679 * [element] to which that node has been resolved, create the annotations in | 2515 * annotations in the element model representing the annotations on the node. |
| 2680 * the element model representing the annotations on the node. | |
| 2681 */ | 2516 */ |
| 2682 static void setMetadata(Element element, AnnotatedNode node) { | 2517 static void resolveMetadata(AnnotatedNode node) { |
| 2683 if (element is! ElementImpl) { | 2518 _resolveAnnotations(node.metadata); |
| 2684 return; | 2519 if (node is VariableDeclaration) { |
| 2685 } | 2520 AstNode parent = node.parent; |
| 2686 List<ElementAnnotationImpl> annotationList = <ElementAnnotationImpl>[]; | 2521 if (parent is VariableDeclarationList) { |
| 2687 _addAnnotations(annotationList, node.metadata); | 2522 _resolveAnnotations(parent.metadata); |
| 2688 if (node is VariableDeclaration && node.parent is VariableDeclarationList) { | 2523 AstNode grandParent = parent.parent; |
| 2689 VariableDeclarationList list = node.parent as VariableDeclarationList; | 2524 if (grandParent is FieldDeclaration) { |
| 2690 _addAnnotations(annotationList, list.metadata); | 2525 _resolveAnnotations(grandParent.metadata); |
| 2691 if (list.parent is FieldDeclaration) { | 2526 } else if (grandParent is TopLevelVariableDeclaration) { |
| 2692 FieldDeclaration fieldDeclaration = list.parent as FieldDeclaration; | 2527 _resolveAnnotations(grandParent.metadata); |
| 2693 _addAnnotations(annotationList, fieldDeclaration.metadata); | 2528 } |
| 2694 } else if (list.parent is TopLevelVariableDeclaration) { | |
| 2695 TopLevelVariableDeclaration variableDeclaration = | |
| 2696 list.parent as TopLevelVariableDeclaration; | |
| 2697 _addAnnotations(annotationList, variableDeclaration.metadata); | |
| 2698 } | |
| 2699 } | |
| 2700 if (!annotationList.isEmpty) { | |
| 2701 (element as ElementImpl).metadata = annotationList; | |
| 2702 } | |
| 2703 } | |
| 2704 | |
| 2705 /** | |
| 2706 * Generate annotation elements for each of the annotations in the | |
| 2707 * [annotationList] and add them to the given list of [annotations]. | |
| 2708 */ | |
| 2709 static void _addAnnotations(List<ElementAnnotationImpl> annotationList, | |
| 2710 NodeList<Annotation> annotations) { | |
| 2711 int annotationCount = annotations.length; | |
| 2712 for (int i = 0; i < annotationCount; i++) { | |
| 2713 Annotation annotation = annotations[i]; | |
| 2714 Element resolvedElement = annotation.element; | |
| 2715 if (resolvedElement != null) { | |
| 2716 ElementAnnotationImpl elementAnnotation = | |
| 2717 new ElementAnnotationImpl(resolvedElement); | |
| 2718 annotation.elementAnnotation = elementAnnotation; | |
| 2719 annotationList.add(elementAnnotation); | |
| 2720 } | 2529 } |
| 2721 } | 2530 } |
| 2722 } | 2531 } |
| 2723 | 2532 |
| 2724 /** | 2533 /** |
| 2725 * Return `true` if the given [identifier] is the return type of a constructor | 2534 * Return `true` if the given [identifier] is the return type of a constructor |
| 2726 * declaration. | 2535 * declaration. |
| 2727 */ | 2536 */ |
| 2728 static bool _isConstructorReturnType(SimpleIdentifier identifier) { | 2537 static bool _isConstructorReturnType(SimpleIdentifier identifier) { |
| 2729 AstNode parent = identifier.parent; | 2538 AstNode parent = identifier.parent; |
| 2730 if (parent is ConstructorDeclaration) { | 2539 if (parent is ConstructorDeclaration) { |
| 2731 return identical(parent.returnType, identifier); | 2540 return identical(parent.returnType, identifier); |
| 2732 } | 2541 } |
| 2733 return false; | 2542 return false; |
| 2734 } | 2543 } |
| 2735 | 2544 |
| 2736 /** | 2545 /** |
| 2737 * Return `true` if the given [identifier] is the return type of a factory | 2546 * Return `true` if the given [identifier] is the return type of a factory |
| 2738 * constructor. | 2547 * constructor. |
| 2739 */ | 2548 */ |
| 2740 static bool _isFactoryConstructorReturnType(SimpleIdentifier identifier) { | 2549 static bool _isFactoryConstructorReturnType(SimpleIdentifier identifier) { |
| 2741 AstNode parent = identifier.parent; | 2550 AstNode parent = identifier.parent; |
| 2742 if (parent is ConstructorDeclaration) { | 2551 if (parent is ConstructorDeclaration) { |
| 2743 ConstructorDeclaration constructor = parent; | 2552 return identical(parent.returnType, identifier) && |
| 2744 return identical(constructor.returnType, identifier) && | 2553 parent.factoryKeyword != null; |
| 2745 constructor.factoryKeyword != null; | |
| 2746 } | 2554 } |
| 2747 return false; | 2555 return false; |
| 2748 } | 2556 } |
| 2749 | 2557 |
| 2750 /** | 2558 /** |
| 2751 * Return `true` if the given 'super' [expression] is used in a valid context. | 2559 * Return `true` if the given 'super' [expression] is used in a valid context. |
| 2752 */ | 2560 */ |
| 2753 static bool _isSuperInValidContext(SuperExpression expression) { | 2561 static bool _isSuperInValidContext(SuperExpression expression) { |
| 2754 for (AstNode node = expression; node != null; node = node.parent) { | 2562 for (AstNode node = expression; node != null; node = node.parent) { |
| 2755 if (node is CompilationUnit) { | 2563 if (node is CompilationUnit) { |
| 2756 return false; | 2564 return false; |
| 2757 } | 2565 } else if (node is ConstructorDeclaration) { |
| 2758 if (node is ConstructorDeclaration) { | |
| 2759 return node.factoryKeyword == null; | 2566 return node.factoryKeyword == null; |
| 2760 } | 2567 } else if (node is ConstructorFieldInitializer) { |
| 2761 if (node is ConstructorFieldInitializer) { | |
| 2762 return false; | 2568 return false; |
| 2763 } | 2569 } else if (node is MethodDeclaration) { |
| 2764 if (node is MethodDeclaration) { | |
| 2765 return !node.isStatic; | 2570 return !node.isStatic; |
| 2766 } | 2571 } |
| 2767 } | 2572 } |
| 2768 return false; | 2573 return false; |
| 2769 } | 2574 } |
| 2575 |
| 2576 /** |
| 2577 * Resolve each of the annotations in the given list of [annotations]. |
| 2578 */ |
| 2579 static void _resolveAnnotations(NodeList<Annotation> annotations) { |
| 2580 for (Annotation annotation in annotations) { |
| 2581 ElementAnnotationImpl elementAnnotation = annotation.elementAnnotation; |
| 2582 elementAnnotation.element = annotation.element; |
| 2583 } |
| 2584 } |
| 2770 } | 2585 } |
| 2771 | 2586 |
| 2772 /** | 2587 /** |
| 2773 * An identifier that can be used to look up names in the lexical scope when | 2588 * An identifier that can be used to look up names in the lexical scope when |
| 2774 * there is no identifier in the AST structure. There is no identifier in the | 2589 * there is no identifier in the AST structure. There is no identifier in the |
| 2775 * AST when the parser could not distinguish between a method invocation and an | 2590 * AST when the parser could not distinguish between a method invocation and an |
| 2776 * invocation of a top-level function imported with a prefix. | 2591 * invocation of a top-level function imported with a prefix. |
| 2777 */ | 2592 */ |
| 2778 class SyntheticIdentifier extends Identifier { | 2593 class SyntheticIdentifier extends IdentifierImpl { |
| 2779 /** | 2594 /** |
| 2780 * The name of the synthetic identifier. | 2595 * The name of the synthetic identifier. |
| 2781 */ | 2596 */ |
| 2597 @override |
| 2782 final String name; | 2598 final String name; |
| 2783 | 2599 |
| 2784 /** | 2600 /** |
| 2785 * The identifier to be highlighted in case of an error | 2601 * The identifier to be highlighted in case of an error |
| 2786 */ | 2602 */ |
| 2787 final Identifier targetIdentifier; | 2603 final Identifier targetIdentifier; |
| 2788 | 2604 |
| 2789 /** | 2605 /** |
| 2790 * Initialize a newly created synthetic identifier to have the given [name] | 2606 * Initialize a newly created synthetic identifier to have the given [name] |
| 2791 * and [targetIdentifier]. | 2607 * and [targetIdentifier]. |
| 2792 */ | 2608 */ |
| 2793 SyntheticIdentifier(this.name, this.targetIdentifier); | 2609 SyntheticIdentifier(this.name, this.targetIdentifier); |
| 2794 | 2610 |
| 2795 @override | 2611 @override |
| 2796 sc.Token get beginToken => null; | 2612 Token get beginToken => null; |
| 2797 | 2613 |
| 2798 @override | 2614 @override |
| 2799 Element get bestElement => null; | 2615 Element get bestElement => null; |
| 2800 | 2616 |
| 2801 @override | 2617 @override |
| 2802 Iterable get childEntities { | 2618 Iterable<SyntacticEntity> get childEntities { |
| 2803 // Should never be called, since a SyntheticIdentifier never appears in the | 2619 // Should never be called, since a SyntheticIdentifier never appears in the |
| 2804 // AST--it is just used for lookup. | 2620 // AST--it is just used for lookup. |
| 2805 assert(false); | 2621 assert(false); |
| 2806 return new ChildEntities(); | 2622 return new ChildEntities(); |
| 2807 } | 2623 } |
| 2808 | 2624 |
| 2809 @override | 2625 @override |
| 2810 sc.Token get endToken => null; | 2626 Token get endToken => null; |
| 2811 | 2627 |
| 2812 @override | 2628 @override |
| 2813 int get length => targetIdentifier.length; | 2629 int get length => targetIdentifier.length; |
| 2814 | 2630 |
| 2815 @override | 2631 @override |
| 2816 int get offset => targetIdentifier.offset; | 2632 int get offset => targetIdentifier.offset; |
| 2817 | 2633 |
| 2818 @override | 2634 @override |
| 2819 int get precedence => 16; | 2635 int get precedence => 16; |
| 2820 | 2636 |
| 2821 @override | 2637 @override |
| 2822 Element get propagatedElement => null; | 2638 Element get propagatedElement => null; |
| 2823 | 2639 |
| 2824 @override | 2640 @override |
| 2825 Element get staticElement => null; | 2641 Element get staticElement => null; |
| 2826 | 2642 |
| 2827 @override | 2643 @override |
| 2828 accept(AstVisitor visitor) => null; | 2644 dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) => null; |
| 2829 | 2645 |
| 2830 @override | 2646 @override |
| 2831 void visitChildren(AstVisitor visitor) {} | 2647 void visitChildren(AstVisitor visitor) {} |
| 2832 } | 2648 } |
| OLD | NEW |