| 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.error_verifier; | 5 library analyzer.src.generated.error_verifier; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 import "dart:math" as math; | 8 import "dart:math" as math; |
| 9 | 9 |
| 10 import 'package:analyzer/src/generated/static_type_analyzer.dart'; | 10 import 'package:analyzer/dart/ast/ast.dart'; |
| 11 | 11 import 'package:analyzer/dart/ast/token.dart'; |
| 12 import 'ast.dart'; | 12 import 'package:analyzer/dart/ast/visitor.dart'; |
| 13 import 'constant.dart'; | 13 import 'package:analyzer/dart/element/element.dart'; |
| 14 import 'element.dart'; | 14 import 'package:analyzer/dart/element/type.dart'; |
| 15 import 'element_resolver.dart'; | 15 import 'package:analyzer/dart/element/visitor.dart'; |
| 16 import 'error.dart'; | 16 import 'package:analyzer/error/error.dart'; |
| 17 import 'java_engine.dart'; | 17 import 'package:analyzer/error/listener.dart'; |
| 18 import 'parser.dart' show Parser, ParserErrorCode; | 18 import 'package:analyzer/src/dart/element/element.dart'; |
| 19 import 'resolver.dart'; | 19 import 'package:analyzer/src/dart/element/member.dart'; |
| 20 import 'scanner.dart' as sc; | 20 import 'package:analyzer/src/dart/element/type.dart'; |
| 21 import 'sdk.dart' show DartSdk, SdkLibrary; | 21 import 'package:analyzer/src/dart/resolver/inheritance_manager.dart'; |
| 22 import 'utilities_dart.dart'; | 22 import 'package:analyzer/src/error/codes.dart'; |
| 23 import 'package:analyzer/src/error/pending_error.dart'; |
| 24 import 'package:analyzer/src/generated/constant.dart'; |
| 25 import 'package:analyzer/src/generated/element_resolver.dart'; |
| 26 import 'package:analyzer/src/generated/engine.dart'; |
| 27 import 'package:analyzer/src/generated/java_engine.dart'; |
| 28 import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode; |
| 29 import 'package:analyzer/src/generated/resolver.dart'; |
| 30 import 'package:analyzer/src/generated/sdk.dart' show DartSdk, SdkLibrary; |
| 31 import 'package:analyzer/src/generated/source.dart'; |
| 32 import 'package:analyzer/src/generated/utilities_dart.dart'; |
| 33 import 'package:analyzer/src/task/dart.dart'; |
| 34 import 'package:analyzer/src/task/strong/checker.dart' as checker |
| 35 show isKnownFunction; |
| 23 | 36 |
| 24 /** | 37 /** |
| 25 * A visitor used to traverse an AST structure looking for additional errors and | 38 * A visitor used to traverse an AST structure looking for additional errors and |
| 26 * warnings not covered by the parser and resolver. | 39 * warnings not covered by the parser and resolver. |
| 27 */ | 40 */ |
| 28 class ErrorVerifier extends RecursiveAstVisitor<Object> { | 41 class ErrorVerifier extends RecursiveAstVisitor<Object> { |
| 29 /** | 42 /** |
| 30 * Static final string with value `"getter "` used in the construction of the | 43 * Static final string with value `"getter "` used in the construction of the |
| 31 * [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE], and | 44 * [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE], and |
| 32 * similar, error code messages. | 45 * similar, error code messages. |
| (...skipping 25 matching lines...) Expand all Loading... |
| 58 * The type representing the type 'bool'. | 71 * The type representing the type 'bool'. |
| 59 */ | 72 */ |
| 60 InterfaceType _boolType; | 73 InterfaceType _boolType; |
| 61 | 74 |
| 62 /** | 75 /** |
| 63 * The type representing the type 'int'. | 76 * The type representing the type 'int'. |
| 64 */ | 77 */ |
| 65 InterfaceType _intType; | 78 InterfaceType _intType; |
| 66 | 79 |
| 67 /** | 80 /** |
| 81 * The options for verification. |
| 82 */ |
| 83 AnalysisOptionsImpl _options; |
| 84 |
| 85 /** |
| 68 * The object providing access to the types defined by the language. | 86 * The object providing access to the types defined by the language. |
| 69 */ | 87 */ |
| 70 final TypeProvider _typeProvider; | 88 final TypeProvider _typeProvider; |
| 71 | 89 |
| 72 /** | 90 /** |
| 73 * The type system primitives | 91 * The type system primitives |
| 74 */ | 92 */ |
| 75 TypeSystem _typeSystem; | 93 TypeSystem _typeSystem; |
| 76 | 94 |
| 77 /** | 95 /** |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 * [StaticWarningCode.MIXED_RETURN_TYPES] and | 203 * [StaticWarningCode.MIXED_RETURN_TYPES] and |
| 186 * [StaticWarningCode.RETURN_WITHOUT_VALUE] from being generated in the same | 204 * [StaticWarningCode.RETURN_WITHOUT_VALUE] from being generated in the same |
| 187 * function body. | 205 * function body. |
| 188 */ | 206 */ |
| 189 bool _hasReturnWithoutValue = false; | 207 bool _hasReturnWithoutValue = false; |
| 190 | 208 |
| 191 /** | 209 /** |
| 192 * The class containing the AST nodes being visited, or `null` if we are not | 210 * The class containing the AST nodes being visited, or `null` if we are not |
| 193 * in the scope of a class. | 211 * in the scope of a class. |
| 194 */ | 212 */ |
| 195 ClassElement _enclosingClass; | 213 ClassElementImpl _enclosingClass; |
| 214 |
| 215 /** |
| 216 * The enum containing the AST nodes being visited, or `null` if we are not |
| 217 * in the scope of an enum. |
| 218 */ |
| 219 ClassElement _enclosingEnum; |
| 196 | 220 |
| 197 /** | 221 /** |
| 198 * The method or function that we are currently visiting, or `null` if we are | 222 * The method or function that we are currently visiting, or `null` if we are |
| 199 * not inside a method or function. | 223 * not inside a method or function. |
| 200 */ | 224 */ |
| 201 ExecutableElement _enclosingFunction; | 225 ExecutableElement _enclosingFunction; |
| 202 | 226 |
| 203 /** | 227 /** |
| 204 * The return statements found in the method or function that we are currently | 228 * The return statements found in the method or function that we are currently |
| 205 * visiting that have a return value. | 229 * visiting that have a return value. |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 247 */ | 271 */ |
| 248 HashMap<String, Element> _exportedElements = new HashMap<String, Element>(); | 272 HashMap<String, Element> _exportedElements = new HashMap<String, Element>(); |
| 249 | 273 |
| 250 /** | 274 /** |
| 251 * A set of the names of the variable initializers we are visiting now. | 275 * A set of the names of the variable initializers we are visiting now. |
| 252 */ | 276 */ |
| 253 HashSet<String> _namesForReferenceToDeclaredVariableInInitializer = | 277 HashSet<String> _namesForReferenceToDeclaredVariableInInitializer = |
| 254 new HashSet<String>(); | 278 new HashSet<String>(); |
| 255 | 279 |
| 256 /** | 280 /** |
| 281 * The elements that will be defined later in the current scope, but right |
| 282 * now are not declared. |
| 283 */ |
| 284 HiddenElements _hiddenElements = null; |
| 285 |
| 286 /** |
| 257 * A list of types used by the [CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS] | 287 * A list of types used by the [CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS] |
| 258 * and [CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS] error codes. | 288 * and [CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS] error codes. |
| 259 */ | 289 */ |
| 260 List<InterfaceType> _DISALLOWED_TYPES_TO_EXTEND_OR_IMPLEMENT; | 290 List<InterfaceType> _DISALLOWED_TYPES_TO_EXTEND_OR_IMPLEMENT; |
| 261 | 291 |
| 262 /** | 292 /** |
| 263 * If `true`, mixins are allowed to inherit from types other than Object, and | 293 * If `true`, mixins are allowed to inherit from types other than Object, and |
| 264 * are allowed to reference `super`. | 294 * are allowed to reference `super`. |
| 265 */ | 295 */ |
| 266 final bool enableSuperMixins; | 296 final bool enableSuperMixins; |
| 267 | 297 |
| 268 /** | 298 /** |
| 299 * If `true`, asserts are allowed to take a second argument representing the |
| 300 * assertion failure message (see DEP 37). |
| 301 */ |
| 302 final bool enableAssertMessage; |
| 303 |
| 304 /** |
| 269 * Initialize a newly created error verifier. | 305 * Initialize a newly created error verifier. |
| 270 */ | 306 */ |
| 271 ErrorVerifier(this._errorReporter, this._currentLibrary, this._typeProvider, | 307 ErrorVerifier( |
| 272 this._inheritanceManager, this.enableSuperMixins) { | 308 this._errorReporter, |
| 309 this._currentLibrary, |
| 310 this._typeProvider, |
| 311 this._inheritanceManager, |
| 312 this.enableSuperMixins, |
| 313 this.enableAssertMessage) { |
| 273 this._isInSystemLibrary = _currentLibrary.source.isInSystemLibrary; | 314 this._isInSystemLibrary = _currentLibrary.source.isInSystemLibrary; |
| 274 this._hasExtUri = _currentLibrary.hasExtUri; | 315 this._hasExtUri = _currentLibrary.hasExtUri; |
| 275 _isEnclosingConstructorConst = false; | 316 _isEnclosingConstructorConst = false; |
| 276 _isInCatchClause = false; | 317 _isInCatchClause = false; |
| 277 _isInStaticVariableDeclaration = false; | 318 _isInStaticVariableDeclaration = false; |
| 278 _isInInstanceVariableDeclaration = false; | 319 _isInInstanceVariableDeclaration = false; |
| 279 _isInInstanceVariableInitializer = false; | 320 _isInInstanceVariableInitializer = false; |
| 280 _isInConstructorInitializer = false; | 321 _isInConstructorInitializer = false; |
| 281 _isInStaticMethod = false; | 322 _isInStaticMethod = false; |
| 282 _boolType = _typeProvider.boolType; | 323 _boolType = _typeProvider.boolType; |
| 283 _intType = _typeProvider.intType; | 324 _intType = _typeProvider.intType; |
| 284 _DISALLOWED_TYPES_TO_EXTEND_OR_IMPLEMENT = _typeProvider.nonSubtypableTypes; | 325 _DISALLOWED_TYPES_TO_EXTEND_OR_IMPLEMENT = _typeProvider.nonSubtypableTypes; |
| 285 _typeSystem = _currentLibrary.context.typeSystem; | 326 _typeSystem = _currentLibrary.context.typeSystem; |
| 327 _options = _currentLibrary.context.analysisOptions; |
| 286 } | 328 } |
| 287 | 329 |
| 288 @override | 330 @override |
| 289 Object visitAnnotation(Annotation node) { | 331 Object visitAnnotation(Annotation node) { |
| 290 _checkForInvalidAnnotationFromDeferredLibrary(node); | 332 _checkForInvalidAnnotationFromDeferredLibrary(node); |
| 333 _checkForMissingJSLibAnnotation(node); |
| 291 return super.visitAnnotation(node); | 334 return super.visitAnnotation(node); |
| 292 } | 335 } |
| 293 | 336 |
| 294 @override | 337 @override |
| 295 Object visitArgumentList(ArgumentList node) { | 338 Object visitArgumentList(ArgumentList node) { |
| 296 _checkForArgumentTypesNotAssignableInList(node); | 339 _checkForArgumentTypesNotAssignableInList(node); |
| 297 return super.visitArgumentList(node); | 340 return super.visitArgumentList(node); |
| 298 } | 341 } |
| 299 | 342 |
| 300 @override | 343 @override |
| 301 Object visitAsExpression(AsExpression node) { | 344 Object visitAsExpression(AsExpression node) { |
| 302 _checkForTypeAnnotationDeferredClass(node.type); | 345 _checkForTypeAnnotationDeferredClass(node.type); |
| 303 return super.visitAsExpression(node); | 346 return super.visitAsExpression(node); |
| 304 } | 347 } |
| 305 | 348 |
| 306 @override | 349 @override |
| 307 Object visitAssertStatement(AssertStatement node) { | 350 Object visitAssertStatement(AssertStatement node) { |
| 308 _checkForNonBoolExpression(node); | 351 _checkForNonBoolExpression(node); |
| 352 _checkAssertMessage(node); |
| 309 return super.visitAssertStatement(node); | 353 return super.visitAssertStatement(node); |
| 310 } | 354 } |
| 311 | 355 |
| 312 @override | 356 @override |
| 313 Object visitAssignmentExpression(AssignmentExpression node) { | 357 Object visitAssignmentExpression(AssignmentExpression node) { |
| 314 sc.TokenType operatorType = node.operator.type; | 358 TokenType operatorType = node.operator.type; |
| 315 Expression lhs = node.leftHandSide; | 359 Expression lhs = node.leftHandSide; |
| 316 Expression rhs = node.rightHandSide; | 360 Expression rhs = node.rightHandSide; |
| 317 if (operatorType == sc.TokenType.EQ || | 361 if (operatorType == TokenType.EQ || |
| 318 operatorType == sc.TokenType.QUESTION_QUESTION_EQ) { | 362 operatorType == TokenType.QUESTION_QUESTION_EQ) { |
| 319 _checkForInvalidAssignment(lhs, rhs); | 363 _checkForInvalidAssignment(lhs, rhs); |
| 320 } else { | 364 } else { |
| 321 _checkForInvalidCompoundAssignment(node, lhs, rhs); | 365 _checkForInvalidCompoundAssignment(node, lhs, rhs); |
| 322 _checkForArgumentTypeNotAssignableForArgument(rhs); | 366 _checkForArgumentTypeNotAssignableForArgument(rhs); |
| 323 } | 367 } |
| 324 _checkForAssignmentToFinal(lhs); | 368 _checkForAssignmentToFinal(lhs); |
| 325 return super.visitAssignmentExpression(node); | 369 return super.visitAssignmentExpression(node); |
| 326 } | 370 } |
| 327 | 371 |
| 328 @override | 372 @override |
| 329 Object visitAwaitExpression(AwaitExpression node) { | 373 Object visitAwaitExpression(AwaitExpression node) { |
| 330 if (!_inAsync) { | 374 if (!_inAsync) { |
| 331 _errorReporter.reportErrorForToken( | 375 _errorReporter.reportErrorForToken( |
| 332 CompileTimeErrorCode.AWAIT_IN_WRONG_CONTEXT, node.awaitKeyword); | 376 CompileTimeErrorCode.AWAIT_IN_WRONG_CONTEXT, node.awaitKeyword); |
| 333 } | 377 } |
| 334 return super.visitAwaitExpression(node); | 378 return super.visitAwaitExpression(node); |
| 335 } | 379 } |
| 336 | 380 |
| 337 @override | 381 @override |
| 338 Object visitBinaryExpression(BinaryExpression node) { | 382 Object visitBinaryExpression(BinaryExpression node) { |
| 339 sc.Token operator = node.operator; | 383 Token operator = node.operator; |
| 340 sc.TokenType type = operator.type; | 384 TokenType type = operator.type; |
| 341 if (type == sc.TokenType.AMPERSAND_AMPERSAND || | 385 if (type == TokenType.AMPERSAND_AMPERSAND || type == TokenType.BAR_BAR) { |
| 342 type == sc.TokenType.BAR_BAR) { | |
| 343 String lexeme = operator.lexeme; | 386 String lexeme = operator.lexeme; |
| 344 _checkForAssignability(node.leftOperand, _boolType, | 387 _checkForAssignability(node.leftOperand, _boolType, |
| 345 StaticTypeWarningCode.NON_BOOL_OPERAND, [lexeme]); | 388 StaticTypeWarningCode.NON_BOOL_OPERAND, [lexeme]); |
| 346 _checkForAssignability(node.rightOperand, _boolType, | 389 _checkForAssignability(node.rightOperand, _boolType, |
| 347 StaticTypeWarningCode.NON_BOOL_OPERAND, [lexeme]); | 390 StaticTypeWarningCode.NON_BOOL_OPERAND, [lexeme]); |
| 348 } else { | 391 } else { |
| 349 _checkForArgumentTypeNotAssignableForArgument(node.rightOperand); | 392 _checkForArgumentTypeNotAssignableForArgument(node.rightOperand); |
| 350 } | 393 } |
| 351 return super.visitBinaryExpression(node); | 394 return super.visitBinaryExpression(node); |
| 352 } | 395 } |
| 353 | 396 |
| 354 @override | 397 @override |
| 398 Object visitBlock(Block node) { |
| 399 _hiddenElements = new HiddenElements(_hiddenElements, node); |
| 400 try { |
| 401 _checkDuplicateDeclarationInStatements(node.statements); |
| 402 return super.visitBlock(node); |
| 403 } finally { |
| 404 _hiddenElements = _hiddenElements.outerElements; |
| 405 } |
| 406 } |
| 407 |
| 408 @override |
| 355 Object visitBlockFunctionBody(BlockFunctionBody node) { | 409 Object visitBlockFunctionBody(BlockFunctionBody node) { |
| 356 bool wasInAsync = _inAsync; | 410 bool wasInAsync = _inAsync; |
| 357 bool wasInGenerator = _inGenerator; | 411 bool wasInGenerator = _inGenerator; |
| 358 bool previousHasReturnWithoutValue = _hasReturnWithoutValue; | 412 bool previousHasReturnWithoutValue = _hasReturnWithoutValue; |
| 359 _hasReturnWithoutValue = false; | 413 _hasReturnWithoutValue = false; |
| 360 List<ReturnStatement> previousReturnsWith = _returnsWith; | 414 List<ReturnStatement> previousReturnsWith = _returnsWith; |
| 361 List<ReturnStatement> previousReturnsWithout = _returnsWithout; | 415 List<ReturnStatement> previousReturnsWithout = _returnsWithout; |
| 362 try { | 416 try { |
| 363 _inAsync = node.isAsynchronous; | 417 _inAsync = node.isAsynchronous; |
| 364 _inGenerator = node.isGenerator; | 418 _inGenerator = node.isGenerator; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 384 if (labelElement is LabelElementImpl && labelElement.isOnSwitchMember) { | 438 if (labelElement is LabelElementImpl && labelElement.isOnSwitchMember) { |
| 385 _errorReporter.reportErrorForNode( | 439 _errorReporter.reportErrorForNode( |
| 386 ResolverErrorCode.BREAK_LABEL_ON_SWITCH_MEMBER, labelNode); | 440 ResolverErrorCode.BREAK_LABEL_ON_SWITCH_MEMBER, labelNode); |
| 387 } | 441 } |
| 388 } | 442 } |
| 389 return null; | 443 return null; |
| 390 } | 444 } |
| 391 | 445 |
| 392 @override | 446 @override |
| 393 Object visitCatchClause(CatchClause node) { | 447 Object visitCatchClause(CatchClause node) { |
| 448 _checkDuplicateDefinitionInCatchClause(node); |
| 394 bool previousIsInCatchClause = _isInCatchClause; | 449 bool previousIsInCatchClause = _isInCatchClause; |
| 395 try { | 450 try { |
| 396 _isInCatchClause = true; | 451 _isInCatchClause = true; |
| 397 _checkForTypeAnnotationDeferredClass(node.exceptionType); | 452 _checkForTypeAnnotationDeferredClass(node.exceptionType); |
| 398 return super.visitCatchClause(node); | 453 return super.visitCatchClause(node); |
| 399 } finally { | 454 } finally { |
| 400 _isInCatchClause = previousIsInCatchClause; | 455 _isInCatchClause = previousIsInCatchClause; |
| 401 } | 456 } |
| 402 } | 457 } |
| 403 | 458 |
| 404 @override | 459 @override |
| 405 Object visitClassDeclaration(ClassDeclaration node) { | 460 Object visitClassDeclaration(ClassDeclaration node) { |
| 406 ClassElement outerClass = _enclosingClass; | 461 ClassElementImpl outerClass = _enclosingClass; |
| 407 try { | 462 try { |
| 408 _isInNativeClass = node.nativeClause != null; | 463 _isInNativeClass = node.nativeClause != null; |
| 409 _enclosingClass = node.element; | 464 _enclosingClass = AbstractClassElementImpl.getImpl(node.element); |
| 410 ExtendsClause extendsClause = node.extendsClause; | 465 _checkDuplicateClassMembers(node); |
| 411 ImplementsClause implementsClause = node.implementsClause; | |
| 412 WithClause withClause = node.withClause; | |
| 413 _checkForBuiltInIdentifierAsName( | 466 _checkForBuiltInIdentifierAsName( |
| 414 node.name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_NAME); | 467 node.name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_NAME); |
| 415 _checkForMemberWithClassName(); | 468 _checkForMemberWithClassName(); |
| 416 _checkForNoDefaultSuperConstructorImplicit(node); | 469 _checkForNoDefaultSuperConstructorImplicit(node); |
| 417 _checkForConflictingTypeVariableErrorCodes(node); | 470 _checkForConflictingTypeVariableErrorCodes(node); |
| 471 ExtendsClause extendsClause = node.extendsClause; |
| 472 ImplementsClause implementsClause = node.implementsClause; |
| 473 WithClause withClause = node.withClause; |
| 418 // Only do error checks on the clause nodes if there is a non-null clause | 474 // Only do error checks on the clause nodes if there is a non-null clause |
| 419 if (implementsClause != null || | 475 if (implementsClause != null || |
| 420 extendsClause != null || | 476 extendsClause != null || |
| 421 withClause != null) { | 477 withClause != null) { |
| 422 // Only check for all of the inheritance logic around clauses if there | 478 // Only check for all of the inheritance logic around clauses if there |
| 423 // isn't an error code such as "Cannot extend double" already on the | 479 // isn't an error code such as "Cannot extend double" already on the |
| 424 // class. | 480 // class. |
| 425 if (!_checkForImplementsDisallowedClass(implementsClause) && | 481 if (!_checkForImplementsDisallowedClass(implementsClause) && |
| 426 !_checkForExtendsDisallowedClass(extendsClause) && | 482 !_checkForExtendsDisallowedClass(extendsClause) && |
| 427 !_checkForAllMixinErrorCodes(withClause)) { | 483 !_checkForAllMixinErrorCodes(withClause)) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 448 _enclosingClass = outerClass; | 504 _enclosingClass = outerClass; |
| 449 } | 505 } |
| 450 } | 506 } |
| 451 | 507 |
| 452 /** | 508 /** |
| 453 * Implementation of this method should be synchronized with | 509 * Implementation of this method should be synchronized with |
| 454 * [visitClassDeclaration]. | 510 * [visitClassDeclaration]. |
| 455 */ | 511 */ |
| 456 void visitClassDeclarationIncrementally(ClassDeclaration node) { | 512 void visitClassDeclarationIncrementally(ClassDeclaration node) { |
| 457 _isInNativeClass = node.nativeClause != null; | 513 _isInNativeClass = node.nativeClause != null; |
| 458 _enclosingClass = node.element; | 514 _enclosingClass = AbstractClassElementImpl.getImpl(node.element); |
| 459 // initialize initialFieldElementsMap | 515 // initialize initialFieldElementsMap |
| 460 if (_enclosingClass != null) { | 516 if (_enclosingClass != null) { |
| 461 List<FieldElement> fieldElements = _enclosingClass.fields; | 517 List<FieldElement> fieldElements = _enclosingClass.fields; |
| 462 _initialFieldElementsMap = new HashMap<FieldElement, INIT_STATE>(); | 518 _initialFieldElementsMap = new HashMap<FieldElement, INIT_STATE>(); |
| 463 for (FieldElement fieldElement in fieldElements) { | 519 for (FieldElement fieldElement in fieldElements) { |
| 464 if (!fieldElement.isSynthetic) { | 520 if (!fieldElement.isSynthetic) { |
| 465 _initialFieldElementsMap[fieldElement] = fieldElement.initializer == | 521 _initialFieldElementsMap[fieldElement] = |
| 466 null ? INIT_STATE.NOT_INIT : INIT_STATE.INIT_IN_DECLARATION; | 522 fieldElement.initializer == null |
| 523 ? INIT_STATE.NOT_INIT |
| 524 : INIT_STATE.INIT_IN_DECLARATION; |
| 467 } | 525 } |
| 468 } | 526 } |
| 469 } | 527 } |
| 470 } | 528 } |
| 471 | 529 |
| 472 @override | 530 @override |
| 473 Object visitClassTypeAlias(ClassTypeAlias node) { | 531 Object visitClassTypeAlias(ClassTypeAlias node) { |
| 474 _checkForBuiltInIdentifierAsName( | 532 _checkForBuiltInIdentifierAsName( |
| 475 node.name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME); | 533 node.name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME); |
| 476 ClassElement outerClassElement = _enclosingClass; | 534 ClassElementImpl outerClassElement = _enclosingClass; |
| 477 try { | 535 try { |
| 478 _enclosingClass = node.element; | 536 _enclosingClass = AbstractClassElementImpl.getImpl(node.element); |
| 479 ImplementsClause implementsClause = node.implementsClause; | 537 ImplementsClause implementsClause = node.implementsClause; |
| 480 // Only check for all of the inheritance logic around clauses if there | 538 // Only check for all of the inheritance logic around clauses if there |
| 481 // isn't an error code such as "Cannot extend double" already on the | 539 // isn't an error code such as "Cannot extend double" already on the |
| 482 // class. | 540 // class. |
| 483 if (!_checkForExtendsDisallowedClassInTypeAlias(node) && | 541 if (!_checkForExtendsDisallowedClassInTypeAlias(node) && |
| 484 !_checkForImplementsDisallowedClass(implementsClause) && | 542 !_checkForImplementsDisallowedClass(implementsClause) && |
| 485 !_checkForAllMixinErrorCodes(node.withClause)) { | 543 !_checkForAllMixinErrorCodes(node.withClause)) { |
| 486 _checkForExtendsDeferredClassInTypeAlias(node); | 544 _checkForExtendsDeferredClassInTypeAlias(node); |
| 487 _checkForImplementsDeferredClass(implementsClause); | 545 _checkForImplementsDeferredClass(implementsClause); |
| 488 _checkForRecursiveInterfaceInheritance(_enclosingClass); | 546 _checkForRecursiveInterfaceInheritance(_enclosingClass); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 500 _isInComment = true; | 558 _isInComment = true; |
| 501 try { | 559 try { |
| 502 return super.visitComment(node); | 560 return super.visitComment(node); |
| 503 } finally { | 561 } finally { |
| 504 _isInComment = false; | 562 _isInComment = false; |
| 505 } | 563 } |
| 506 } | 564 } |
| 507 | 565 |
| 508 @override | 566 @override |
| 509 Object visitCompilationUnit(CompilationUnit node) { | 567 Object visitCompilationUnit(CompilationUnit node) { |
| 568 _checkDuplicateUnitMembers(node); |
| 510 _checkForDeferredPrefixCollisions(node); | 569 _checkForDeferredPrefixCollisions(node); |
| 511 return super.visitCompilationUnit(node); | 570 return super.visitCompilationUnit(node); |
| 512 } | 571 } |
| 513 | 572 |
| 514 @override | 573 @override |
| 515 Object visitConditionalExpression(ConditionalExpression node) { | 574 Object visitConditionalExpression(ConditionalExpression node) { |
| 516 _checkForNonBoolCondition(node.condition); | 575 _checkForNonBoolCondition(node.condition); |
| 517 return super.visitConditionalExpression(node); | 576 return super.visitConditionalExpression(node); |
| 518 } | 577 } |
| 519 | 578 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 548 } | 607 } |
| 549 } | 608 } |
| 550 | 609 |
| 551 @override | 610 @override |
| 552 Object visitConstructorFieldInitializer(ConstructorFieldInitializer node) { | 611 Object visitConstructorFieldInitializer(ConstructorFieldInitializer node) { |
| 553 _isInConstructorInitializer = true; | 612 _isInConstructorInitializer = true; |
| 554 try { | 613 try { |
| 555 SimpleIdentifier fieldName = node.fieldName; | 614 SimpleIdentifier fieldName = node.fieldName; |
| 556 Element staticElement = fieldName.staticElement; | 615 Element staticElement = fieldName.staticElement; |
| 557 _checkForInvalidField(node, fieldName, staticElement); | 616 _checkForInvalidField(node, fieldName, staticElement); |
| 558 _checkForFieldInitializerNotAssignable(node, staticElement); | 617 if (staticElement is FieldElement) { |
| 618 _checkForFieldInitializerNotAssignable(node, staticElement); |
| 619 } |
| 559 return super.visitConstructorFieldInitializer(node); | 620 return super.visitConstructorFieldInitializer(node); |
| 560 } finally { | 621 } finally { |
| 561 _isInConstructorInitializer = false; | 622 _isInConstructorInitializer = false; |
| 562 } | 623 } |
| 563 } | 624 } |
| 564 | 625 |
| 565 @override | 626 @override |
| 566 Object visitContinueStatement(ContinueStatement node) { | 627 Object visitContinueStatement(ContinueStatement node) { |
| 567 SimpleIdentifier labelNode = node.label; | 628 SimpleIdentifier labelNode = node.label; |
| 568 if (labelNode != null) { | 629 if (labelNode != null) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 584 } | 645 } |
| 585 | 646 |
| 586 @override | 647 @override |
| 587 Object visitDoStatement(DoStatement node) { | 648 Object visitDoStatement(DoStatement node) { |
| 588 _checkForNonBoolCondition(node.condition); | 649 _checkForNonBoolCondition(node.condition); |
| 589 return super.visitDoStatement(node); | 650 return super.visitDoStatement(node); |
| 590 } | 651 } |
| 591 | 652 |
| 592 @override | 653 @override |
| 593 Object visitEnumDeclaration(EnumDeclaration node) { | 654 Object visitEnumDeclaration(EnumDeclaration node) { |
| 594 ClassElement outerClass = _enclosingClass; | 655 ClassElement outerEnum = _enclosingEnum; |
| 595 try { | 656 try { |
| 596 _isInNativeClass = false; | 657 _enclosingEnum = node.element; |
| 597 _enclosingClass = node.element; | 658 _checkDuplicateEnumMembers(node); |
| 598 return super.visitEnumDeclaration(node); | 659 return super.visitEnumDeclaration(node); |
| 599 } finally { | 660 } finally { |
| 600 _enclosingClass = outerClass; | 661 _enclosingEnum = outerEnum; |
| 601 } | 662 } |
| 602 } | 663 } |
| 603 | 664 |
| 604 @override | 665 @override |
| 605 Object visitExportDirective(ExportDirective node) { | 666 Object visitExportDirective(ExportDirective node) { |
| 606 ExportElement exportElement = node.element; | 667 ExportElement exportElement = node.element; |
| 607 if (exportElement != null) { | 668 if (exportElement != null) { |
| 608 LibraryElement exportedLibrary = exportElement.exportedLibrary; | 669 LibraryElement exportedLibrary = exportElement.exportedLibrary; |
| 609 _checkForAmbiguousExport(node, exportElement, exportedLibrary); | 670 _checkForAmbiguousExport(node, exportElement, exportedLibrary); |
| 610 _checkForExportDuplicateLibraryName(node, exportElement, exportedLibrary); | 671 _checkForExportDuplicateLibraryName(node, exportElement, exportedLibrary); |
| 611 _checkForExportInternalLibrary(node, exportElement); | 672 _checkForExportInternalLibrary(node, exportElement); |
| 612 } | 673 } |
| 613 return super.visitExportDirective(node); | 674 return super.visitExportDirective(node); |
| 614 } | 675 } |
| 615 | 676 |
| 616 @override | 677 @override |
| 617 Object visitExpressionFunctionBody(ExpressionFunctionBody node) { | 678 Object visitExpressionFunctionBody(ExpressionFunctionBody node) { |
| 618 bool wasInAsync = _inAsync; | 679 bool wasInAsync = _inAsync; |
| 619 bool wasInGenerator = _inGenerator; | 680 bool wasInGenerator = _inGenerator; |
| 620 try { | 681 try { |
| 621 _inAsync = node.isAsynchronous; | 682 _inAsync = node.isAsynchronous; |
| 622 _inGenerator = node.isGenerator; | 683 _inGenerator = node.isGenerator; |
| 623 FunctionType functionType = | 684 FunctionType functionType = _enclosingFunction?.type; |
| 624 _enclosingFunction == null ? null : _enclosingFunction.type; | |
| 625 DartType expectedReturnType = functionType == null | 685 DartType expectedReturnType = functionType == null |
| 626 ? DynamicTypeImpl.instance | 686 ? DynamicTypeImpl.instance |
| 627 : functionType.returnType; | 687 : functionType.returnType; |
| 628 _checkForReturnOfInvalidType(node.expression, expectedReturnType); | 688 ExecutableElement function = _enclosingFunction; |
| 689 bool isSetterWithImplicitReturn = function.hasImplicitReturnType && |
| 690 function is PropertyAccessorElement && |
| 691 function.isSetter; |
| 692 if (!isSetterWithImplicitReturn) { |
| 693 _checkForReturnOfInvalidType(node.expression, expectedReturnType); |
| 694 } |
| 629 return super.visitExpressionFunctionBody(node); | 695 return super.visitExpressionFunctionBody(node); |
| 630 } finally { | 696 } finally { |
| 631 _inAsync = wasInAsync; | 697 _inAsync = wasInAsync; |
| 632 _inGenerator = wasInGenerator; | 698 _inGenerator = wasInGenerator; |
| 633 } | 699 } |
| 634 } | 700 } |
| 635 | 701 |
| 636 @override | 702 @override |
| 703 Object visitExtendsClause(ExtendsClause node) { |
| 704 _checkForImplicitDynamicType(node.superclass); |
| 705 return super.visitExtendsClause(node); |
| 706 } |
| 707 |
| 708 @override |
| 637 Object visitFieldDeclaration(FieldDeclaration node) { | 709 Object visitFieldDeclaration(FieldDeclaration node) { |
| 638 _isInStaticVariableDeclaration = node.isStatic; | 710 _isInStaticVariableDeclaration = node.isStatic; |
| 639 _isInInstanceVariableDeclaration = !_isInStaticVariableDeclaration; | 711 _isInInstanceVariableDeclaration = !_isInStaticVariableDeclaration; |
| 640 if (_isInInstanceVariableDeclaration) { | 712 if (_isInInstanceVariableDeclaration) { |
| 641 VariableDeclarationList variables = node.fields; | 713 VariableDeclarationList variables = node.fields; |
| 642 if (variables.isConst) { | 714 if (variables.isConst) { |
| 643 _errorReporter.reportErrorForToken( | 715 _errorReporter.reportErrorForToken( |
| 644 CompileTimeErrorCode.CONST_INSTANCE_FIELD, variables.keyword); | 716 CompileTimeErrorCode.CONST_INSTANCE_FIELD, variables.keyword); |
| 645 } | 717 } |
| 646 } | 718 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 657 Object visitFieldFormalParameter(FieldFormalParameter node) { | 729 Object visitFieldFormalParameter(FieldFormalParameter node) { |
| 658 _checkForValidField(node); | 730 _checkForValidField(node); |
| 659 _checkForConstFormalParameter(node); | 731 _checkForConstFormalParameter(node); |
| 660 _checkForPrivateOptionalParameter(node); | 732 _checkForPrivateOptionalParameter(node); |
| 661 _checkForFieldInitializingFormalRedirectingConstructor(node); | 733 _checkForFieldInitializingFormalRedirectingConstructor(node); |
| 662 _checkForTypeAnnotationDeferredClass(node.type); | 734 _checkForTypeAnnotationDeferredClass(node.type); |
| 663 return super.visitFieldFormalParameter(node); | 735 return super.visitFieldFormalParameter(node); |
| 664 } | 736 } |
| 665 | 737 |
| 666 @override | 738 @override |
| 739 Object visitForEachStatement(ForEachStatement node) { |
| 740 _checkForInIterable(node); |
| 741 return super.visitForEachStatement(node); |
| 742 } |
| 743 |
| 744 @override |
| 745 Object visitFormalParameterList(FormalParameterList node) { |
| 746 _checkDuplicateDefinitionInParameterList(node); |
| 747 return super.visitFormalParameterList(node); |
| 748 } |
| 749 |
| 750 @override |
| 751 Object visitForStatement(ForStatement node) { |
| 752 if (node.condition != null) { |
| 753 _checkForNonBoolCondition(node.condition); |
| 754 } |
| 755 if (node.variables != null) { |
| 756 _checkDuplicateVariables(node.variables); |
| 757 } |
| 758 return super.visitForStatement(node); |
| 759 } |
| 760 |
| 761 @override |
| 667 Object visitFunctionDeclaration(FunctionDeclaration node) { | 762 Object visitFunctionDeclaration(FunctionDeclaration node) { |
| 763 ExecutableElement functionElement = node.element; |
| 764 if (functionElement != null && |
| 765 functionElement.enclosingElement is! CompilationUnitElement) { |
| 766 _hiddenElements.declare(functionElement); |
| 767 } |
| 668 ExecutableElement outerFunction = _enclosingFunction; | 768 ExecutableElement outerFunction = _enclosingFunction; |
| 669 try { | 769 try { |
| 670 SimpleIdentifier identifier = node.name; | 770 SimpleIdentifier identifier = node.name; |
| 671 String methodName = ""; | 771 String methodName = ""; |
| 672 if (identifier != null) { | 772 if (identifier != null) { |
| 673 methodName = identifier.name; | 773 methodName = identifier.name; |
| 674 } | 774 } |
| 675 _enclosingFunction = node.element; | 775 _enclosingFunction = functionElement; |
| 676 TypeName returnType = node.returnType; | 776 TypeName returnType = node.returnType; |
| 677 if (node.isSetter || node.isGetter) { | 777 if (node.isSetter || node.isGetter) { |
| 678 _checkForMismatchedAccessorTypes(node, methodName); | 778 _checkForMismatchedAccessorTypes(node, methodName); |
| 679 if (node.isSetter) { | 779 if (node.isSetter) { |
| 680 FunctionExpression functionExpression = node.functionExpression; | 780 FunctionExpression functionExpression = node.functionExpression; |
| 681 if (functionExpression != null) { | 781 if (functionExpression != null) { |
| 682 _checkForWrongNumberOfParametersForSetter( | 782 _checkForWrongNumberOfParametersForSetter( |
| 683 identifier, functionExpression.parameters); | 783 identifier, functionExpression.parameters); |
| 684 } | 784 } |
| 685 _checkForNonVoidReturnTypeForSetter(returnType); | 785 _checkForNonVoidReturnTypeForSetter(returnType); |
| 686 } | 786 } |
| 687 } | 787 } |
| 688 if (node.isSetter) { | 788 if (node.isSetter) { |
| 689 _checkForInvalidModifierOnBody(node.functionExpression.body, | 789 _checkForInvalidModifierOnBody(node.functionExpression.body, |
| 690 CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER); | 790 CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER); |
| 691 } | 791 } |
| 692 _checkForTypeAnnotationDeferredClass(returnType); | 792 _checkForTypeAnnotationDeferredClass(returnType); |
| 693 _checkForIllegalReturnType(returnType); | 793 _checkForIllegalReturnType(returnType); |
| 794 _checkForImplicitDynamicReturn(node, node.element); |
| 694 return super.visitFunctionDeclaration(node); | 795 return super.visitFunctionDeclaration(node); |
| 695 } finally { | 796 } finally { |
| 696 _enclosingFunction = outerFunction; | 797 _enclosingFunction = outerFunction; |
| 697 } | 798 } |
| 698 } | 799 } |
| 699 | 800 |
| 700 @override | 801 @override |
| 701 Object visitFunctionExpression(FunctionExpression node) { | 802 Object visitFunctionExpression(FunctionExpression node) { |
| 702 // If this function expression is wrapped in a function declaration, don't | 803 // If this function expression is wrapped in a function declaration, don't |
| 703 // change the enclosingFunction field. | 804 // change the enclosingFunction field. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 715 } | 816 } |
| 716 | 817 |
| 717 @override | 818 @override |
| 718 Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { | 819 Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { |
| 719 Expression functionExpression = node.function; | 820 Expression functionExpression = node.function; |
| 720 DartType expressionType = functionExpression.staticType; | 821 DartType expressionType = functionExpression.staticType; |
| 721 if (!_isFunctionType(expressionType)) { | 822 if (!_isFunctionType(expressionType)) { |
| 722 _errorReporter.reportErrorForNode( | 823 _errorReporter.reportErrorForNode( |
| 723 StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION_EXPRESSION, | 824 StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION_EXPRESSION, |
| 724 functionExpression); | 825 functionExpression); |
| 826 } else if (expressionType is FunctionType) { |
| 827 _checkTypeArguments(expressionType.element, node.typeArguments); |
| 725 } | 828 } |
| 829 _checkForImplicitDynamicInvoke(node); |
| 726 return super.visitFunctionExpressionInvocation(node); | 830 return super.visitFunctionExpressionInvocation(node); |
| 727 } | 831 } |
| 728 | 832 |
| 729 @override | 833 @override |
| 730 Object visitFunctionTypeAlias(FunctionTypeAlias node) { | 834 Object visitFunctionTypeAlias(FunctionTypeAlias node) { |
| 731 _checkForBuiltInIdentifierAsName( | 835 _checkForBuiltInIdentifierAsName( |
| 732 node.name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME); | 836 node.name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME); |
| 733 _checkForDefaultValueInFunctionTypeAlias(node); | 837 _checkForDefaultValueInFunctionTypeAlias(node); |
| 734 _checkForTypeAliasCannotReferenceItself_function(node); | 838 _checkForTypeAliasCannotReferenceItself_function(node); |
| 735 return super.visitFunctionTypeAlias(node); | 839 return super.visitFunctionTypeAlias(node); |
| 736 } | 840 } |
| 737 | 841 |
| 738 @override | 842 @override |
| 739 Object visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) { | 843 Object visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) { |
| 740 bool old = _isInFunctionTypedFormalParameter; | 844 bool old = _isInFunctionTypedFormalParameter; |
| 741 _isInFunctionTypedFormalParameter = true; | 845 _isInFunctionTypedFormalParameter = true; |
| 742 try { | 846 try { |
| 743 _checkForTypeAnnotationDeferredClass(node.returnType); | 847 _checkForTypeAnnotationDeferredClass(node.returnType); |
| 848 |
| 849 // TODO(jmesserly): ideally we'd use _checkForImplicitDynamicReturn, and |
| 850 // we can get the function element via `node?.element?.type?.element` but |
| 851 // it doesn't have hasImplicitReturnType set correctly. |
| 852 if (!_options.implicitDynamic && node.returnType == null) { |
| 853 DartType parameterType = node.element.type; |
| 854 if (parameterType is FunctionType && |
| 855 parameterType.returnType.isDynamic) { |
| 856 _errorReporter.reportErrorForNode( |
| 857 StrongModeCode.IMPLICIT_DYNAMIC_RETURN, node, [node.identifier]); |
| 858 } |
| 859 } |
| 744 return super.visitFunctionTypedFormalParameter(node); | 860 return super.visitFunctionTypedFormalParameter(node); |
| 745 } finally { | 861 } finally { |
| 746 _isInFunctionTypedFormalParameter = old; | 862 _isInFunctionTypedFormalParameter = old; |
| 747 } | 863 } |
| 748 } | 864 } |
| 749 | 865 |
| 750 @override | 866 @override |
| 751 Object visitIfStatement(IfStatement node) { | 867 Object visitIfStatement(IfStatement node) { |
| 752 _checkForNonBoolCondition(node.condition); | 868 _checkForNonBoolCondition(node.condition); |
| 753 return super.visitIfStatement(node); | 869 return super.visitIfStatement(node); |
| 754 } | 870 } |
| 755 | 871 |
| 756 @override | 872 @override |
| 873 Object visitImplementsClause(ImplementsClause node) { |
| 874 node.interfaces.forEach(_checkForImplicitDynamicType); |
| 875 return super.visitImplementsClause(node); |
| 876 } |
| 877 |
| 878 @override |
| 757 Object visitImportDirective(ImportDirective node) { | 879 Object visitImportDirective(ImportDirective node) { |
| 758 ImportElement importElement = node.element; | 880 ImportElement importElement = node.element; |
| 759 if (importElement != null) { | 881 if (importElement != null) { |
| 760 _checkForImportDuplicateLibraryName(node, importElement); | 882 _checkForImportDuplicateLibraryName(node, importElement); |
| 761 _checkForImportInternalLibrary(node, importElement); | 883 _checkForImportInternalLibrary(node, importElement); |
| 762 } | 884 } |
| 763 return super.visitImportDirective(node); | 885 return super.visitImportDirective(node); |
| 764 } | 886 } |
| 765 | 887 |
| 766 @override | 888 @override |
| 767 Object visitIndexExpression(IndexExpression node) { | 889 Object visitIndexExpression(IndexExpression node) { |
| 768 _checkForArgumentTypeNotAssignableForArgument(node.index); | 890 _checkForArgumentTypeNotAssignableForArgument(node.index); |
| 769 return super.visitIndexExpression(node); | 891 return super.visitIndexExpression(node); |
| 770 } | 892 } |
| 771 | 893 |
| 772 @override | 894 @override |
| 773 Object visitInstanceCreationExpression(InstanceCreationExpression node) { | 895 Object visitInstanceCreationExpression(InstanceCreationExpression node) { |
| 774 bool wasInConstInstanceCreation = _isInConstInstanceCreation; | 896 bool wasInConstInstanceCreation = _isInConstInstanceCreation; |
| 775 _isInConstInstanceCreation = node.isConst; | 897 _isInConstInstanceCreation = node.isConst; |
| 776 try { | 898 try { |
| 777 ConstructorName constructorName = node.constructorName; | 899 ConstructorName constructorName = node.constructorName; |
| 778 TypeName typeName = constructorName.type; | 900 TypeName typeName = constructorName.type; |
| 779 DartType type = typeName.type; | 901 DartType type = typeName.type; |
| 780 if (type is InterfaceType) { | 902 if (type is InterfaceType) { |
| 781 InterfaceType interfaceType = type; | 903 _checkForConstOrNewWithAbstractClass(node, typeName, type); |
| 782 _checkForConstOrNewWithAbstractClass(node, typeName, interfaceType); | 904 _checkForConstOrNewWithEnum(node, typeName, type); |
| 783 _checkForConstOrNewWithEnum(node, typeName, interfaceType); | |
| 784 if (_isInConstInstanceCreation) { | 905 if (_isInConstInstanceCreation) { |
| 785 _checkForConstWithNonConst(node); | 906 _checkForConstWithNonConst(node); |
| 786 _checkForConstWithUndefinedConstructor( | 907 _checkForConstWithUndefinedConstructor( |
| 787 node, constructorName, typeName); | 908 node, constructorName, typeName); |
| 788 _checkForConstWithTypeParameters(typeName); | 909 if (!_options.strongMode) { |
| 910 _checkForConstWithTypeParameters(typeName); |
| 911 } |
| 789 _checkForConstDeferredClass(node, constructorName, typeName); | 912 _checkForConstDeferredClass(node, constructorName, typeName); |
| 790 } else { | 913 } else { |
| 791 _checkForNewWithUndefinedConstructor(node, constructorName, typeName); | 914 _checkForNewWithUndefinedConstructor(node, constructorName, typeName); |
| 792 } | 915 } |
| 793 } | 916 } |
| 917 _checkForImplicitDynamicType(typeName); |
| 794 return super.visitInstanceCreationExpression(node); | 918 return super.visitInstanceCreationExpression(node); |
| 795 } finally { | 919 } finally { |
| 796 _isInConstInstanceCreation = wasInConstInstanceCreation; | 920 _isInConstInstanceCreation = wasInConstInstanceCreation; |
| 797 } | 921 } |
| 798 } | 922 } |
| 799 | 923 |
| 800 @override | 924 @override |
| 801 Object visitIsExpression(IsExpression node) { | 925 Object visitIsExpression(IsExpression node) { |
| 802 _checkForTypeAnnotationDeferredClass(node.type); | 926 _checkForTypeAnnotationDeferredClass(node.type); |
| 803 return super.visitIsExpression(node); | 927 return super.visitIsExpression(node); |
| 804 } | 928 } |
| 805 | 929 |
| 806 @override | 930 @override |
| 807 Object visitListLiteral(ListLiteral node) { | 931 Object visitListLiteral(ListLiteral node) { |
| 808 TypeArgumentList typeArguments = node.typeArguments; | 932 TypeArgumentList typeArguments = node.typeArguments; |
| 809 if (typeArguments != null) { | 933 if (typeArguments != null) { |
| 810 if (node.constKeyword != null) { | 934 if (!_options.strongMode && node.constKeyword != null) { |
| 811 NodeList<TypeName> arguments = typeArguments.arguments; | 935 NodeList<TypeName> arguments = typeArguments.arguments; |
| 812 if (arguments.length != 0) { | 936 if (arguments.isNotEmpty) { |
| 813 _checkForInvalidTypeArgumentInConstTypedLiteral(arguments, | 937 _checkForInvalidTypeArgumentInConstTypedLiteral(arguments, |
| 814 CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_LIST); | 938 CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_LIST); |
| 815 } | 939 } |
| 816 } | 940 } |
| 817 _checkForExpectedOneListTypeArgument(node, typeArguments); | 941 _checkForExpectedOneListTypeArgument(node, typeArguments); |
| 818 _checkForListElementTypeNotAssignable(node, typeArguments); | |
| 819 } | 942 } |
| 943 _checkForImplicitDynamicTypedLiteral(node); |
| 944 _checkForListElementTypeNotAssignable(node); |
| 820 return super.visitListLiteral(node); | 945 return super.visitListLiteral(node); |
| 821 } | 946 } |
| 822 | 947 |
| 823 @override | 948 @override |
| 824 Object visitMapLiteral(MapLiteral node) { | 949 Object visitMapLiteral(MapLiteral node) { |
| 825 TypeArgumentList typeArguments = node.typeArguments; | 950 TypeArgumentList typeArguments = node.typeArguments; |
| 826 if (typeArguments != null) { | 951 if (typeArguments != null) { |
| 827 NodeList<TypeName> arguments = typeArguments.arguments; | 952 NodeList<TypeName> arguments = typeArguments.arguments; |
| 828 if (arguments.length != 0) { | 953 if (!_options.strongMode && arguments.isNotEmpty) { |
| 829 if (node.constKeyword != null) { | 954 if (node.constKeyword != null) { |
| 830 _checkForInvalidTypeArgumentInConstTypedLiteral(arguments, | 955 _checkForInvalidTypeArgumentInConstTypedLiteral(arguments, |
| 831 CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP); | 956 CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP); |
| 832 } | 957 } |
| 833 } | 958 } |
| 834 _checkExpectedTwoMapTypeArguments(typeArguments); | 959 _checkExpectedTwoMapTypeArguments(typeArguments); |
| 835 _checkForMapTypeNotAssignable(node, typeArguments); | |
| 836 } | 960 } |
| 961 _checkForImplicitDynamicTypedLiteral(node); |
| 962 _checkForMapTypeNotAssignable(node); |
| 837 _checkForNonConstMapAsExpressionStatement(node); | 963 _checkForNonConstMapAsExpressionStatement(node); |
| 838 return super.visitMapLiteral(node); | 964 return super.visitMapLiteral(node); |
| 839 } | 965 } |
| 840 | 966 |
| 841 @override | 967 @override |
| 842 Object visitMethodDeclaration(MethodDeclaration node) { | 968 Object visitMethodDeclaration(MethodDeclaration node) { |
| 843 ExecutableElement previousFunction = _enclosingFunction; | 969 ExecutableElement previousFunction = _enclosingFunction; |
| 844 try { | 970 try { |
| 845 _isInStaticMethod = node.isStatic; | 971 _isInStaticMethod = node.isStatic; |
| 846 _enclosingFunction = node.element; | 972 _enclosingFunction = node.element; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 864 _checkForConflictingStaticSetterAndInstanceMember(node); | 990 _checkForConflictingStaticSetterAndInstanceMember(node); |
| 865 } else if (node.isOperator) { | 991 } else if (node.isOperator) { |
| 866 _checkForOptionalParameterInOperator(node); | 992 _checkForOptionalParameterInOperator(node); |
| 867 _checkForWrongNumberOfParametersForOperator(node); | 993 _checkForWrongNumberOfParametersForOperator(node); |
| 868 _checkForNonVoidReturnTypeForOperator(node); | 994 _checkForNonVoidReturnTypeForOperator(node); |
| 869 } | 995 } |
| 870 _checkForConcreteClassWithAbstractMember(node); | 996 _checkForConcreteClassWithAbstractMember(node); |
| 871 _checkForAllInvalidOverrideErrorCodesForMethod(node); | 997 _checkForAllInvalidOverrideErrorCodesForMethod(node); |
| 872 _checkForTypeAnnotationDeferredClass(returnTypeName); | 998 _checkForTypeAnnotationDeferredClass(returnTypeName); |
| 873 _checkForIllegalReturnType(returnTypeName); | 999 _checkForIllegalReturnType(returnTypeName); |
| 1000 _checkForImplicitDynamicReturn(node, node.element); |
| 1001 _checkForMustCallSuper(node); |
| 874 return super.visitMethodDeclaration(node); | 1002 return super.visitMethodDeclaration(node); |
| 875 } finally { | 1003 } finally { |
| 876 _enclosingFunction = previousFunction; | 1004 _enclosingFunction = previousFunction; |
| 877 _isInStaticMethod = false; | 1005 _isInStaticMethod = false; |
| 878 } | 1006 } |
| 879 } | 1007 } |
| 880 | 1008 |
| 881 @override | 1009 @override |
| 882 Object visitMethodInvocation(MethodInvocation node) { | 1010 Object visitMethodInvocation(MethodInvocation node) { |
| 883 Expression target = node.realTarget; | 1011 Expression target = node.realTarget; |
| 884 SimpleIdentifier methodName = node.methodName; | 1012 SimpleIdentifier methodName = node.methodName; |
| 885 if (target != null) { | 1013 if (target != null) { |
| 886 ClassElement typeReference = ElementResolver.getTypeReference(target); | 1014 ClassElement typeReference = ElementResolver.getTypeReference(target); |
| 887 _checkForStaticAccessToInstanceMember(typeReference, methodName); | 1015 _checkForStaticAccessToInstanceMember(typeReference, methodName); |
| 888 _checkForInstanceAccessToStaticMember(typeReference, methodName); | 1016 _checkForInstanceAccessToStaticMember(typeReference, methodName); |
| 889 } else { | 1017 } else { |
| 890 _checkForUnqualifiedReferenceToNonLocalStaticMember(methodName); | 1018 _checkForUnqualifiedReferenceToNonLocalStaticMember(methodName); |
| 891 } | 1019 } |
| 1020 _checkTypeArguments( |
| 1021 node.methodName.staticElement, node.typeArguments, target?.staticType); |
| 1022 _checkForImplicitDynamicInvoke(node); |
| 892 return super.visitMethodInvocation(node); | 1023 return super.visitMethodInvocation(node); |
| 893 } | 1024 } |
| 894 | 1025 |
| 895 @override | 1026 @override |
| 896 Object visitNativeClause(NativeClause node) { | 1027 Object visitNativeClause(NativeClause node) { |
| 897 // TODO(brianwilkerson) Figure out the right rule for when 'native' is | 1028 // TODO(brianwilkerson) Figure out the right rule for when 'native' is |
| 898 // allowed. | 1029 // allowed. |
| 899 if (!_isInSystemLibrary) { | 1030 if (!_isInSystemLibrary) { |
| 900 _errorReporter.reportErrorForNode( | 1031 _errorReporter.reportErrorForNode( |
| 901 ParserErrorCode.NATIVE_CLAUSE_IN_NON_SDK_CODE, node); | 1032 ParserErrorCode.NATIVE_CLAUSE_IN_NON_SDK_CODE, node); |
| 902 } | 1033 } |
| 903 return super.visitNativeClause(node); | 1034 return super.visitNativeClause(node); |
| 904 } | 1035 } |
| 905 | 1036 |
| 906 @override | 1037 @override |
| 907 Object visitNativeFunctionBody(NativeFunctionBody node) { | 1038 Object visitNativeFunctionBody(NativeFunctionBody node) { |
| 908 _checkForNativeFunctionBodyInNonSDKCode(node); | 1039 _checkForNativeFunctionBodyInNonSdkCode(node); |
| 909 return super.visitNativeFunctionBody(node); | 1040 return super.visitNativeFunctionBody(node); |
| 910 } | 1041 } |
| 911 | 1042 |
| 912 @override | 1043 @override |
| 913 Object visitPostfixExpression(PostfixExpression node) { | 1044 Object visitPostfixExpression(PostfixExpression node) { |
| 914 _checkForAssignmentToFinal(node.operand); | 1045 _checkForAssignmentToFinal(node.operand); |
| 915 _checkForIntNotAssignable(node.operand); | 1046 _checkForIntNotAssignable(node.operand); |
| 916 return super.visitPostfixExpression(node); | 1047 return super.visitPostfixExpression(node); |
| 917 } | 1048 } |
| 918 | 1049 |
| 919 @override | 1050 @override |
| 920 Object visitPrefixedIdentifier(PrefixedIdentifier node) { | 1051 Object visitPrefixedIdentifier(PrefixedIdentifier node) { |
| 921 if (node.parent is! Annotation) { | 1052 if (node.parent is! Annotation) { |
| 922 ClassElement typeReference = | 1053 ClassElement typeReference = |
| 923 ElementResolver.getTypeReference(node.prefix); | 1054 ElementResolver.getTypeReference(node.prefix); |
| 924 SimpleIdentifier name = node.identifier; | 1055 SimpleIdentifier name = node.identifier; |
| 925 _checkForStaticAccessToInstanceMember(typeReference, name); | 1056 _checkForStaticAccessToInstanceMember(typeReference, name); |
| 926 _checkForInstanceAccessToStaticMember(typeReference, name); | 1057 _checkForInstanceAccessToStaticMember(typeReference, name); |
| 927 } | 1058 } |
| 928 return super.visitPrefixedIdentifier(node); | 1059 return super.visitPrefixedIdentifier(node); |
| 929 } | 1060 } |
| 930 | 1061 |
| 931 @override | 1062 @override |
| 932 Object visitPrefixExpression(PrefixExpression node) { | 1063 Object visitPrefixExpression(PrefixExpression node) { |
| 933 sc.TokenType operatorType = node.operator.type; | 1064 TokenType operatorType = node.operator.type; |
| 934 Expression operand = node.operand; | 1065 Expression operand = node.operand; |
| 935 if (operatorType == sc.TokenType.BANG) { | 1066 if (operatorType == TokenType.BANG) { |
| 936 _checkForNonBoolNegationExpression(operand); | 1067 _checkForNonBoolNegationExpression(operand); |
| 937 } else if (operatorType.isIncrementOperator) { | 1068 } else if (operatorType.isIncrementOperator) { |
| 938 _checkForAssignmentToFinal(operand); | 1069 _checkForAssignmentToFinal(operand); |
| 939 } | 1070 } |
| 940 _checkForIntNotAssignable(operand); | 1071 _checkForIntNotAssignable(operand); |
| 941 return super.visitPrefixExpression(node); | 1072 return super.visitPrefixExpression(node); |
| 942 } | 1073 } |
| 943 | 1074 |
| 944 @override | 1075 @override |
| 945 Object visitPropertyAccess(PropertyAccess node) { | 1076 Object visitPropertyAccess(PropertyAccess node) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 977 } | 1108 } |
| 978 _checkForAllReturnStatementErrorCodes(node); | 1109 _checkForAllReturnStatementErrorCodes(node); |
| 979 return super.visitReturnStatement(node); | 1110 return super.visitReturnStatement(node); |
| 980 } | 1111 } |
| 981 | 1112 |
| 982 @override | 1113 @override |
| 983 Object visitSimpleFormalParameter(SimpleFormalParameter node) { | 1114 Object visitSimpleFormalParameter(SimpleFormalParameter node) { |
| 984 _checkForConstFormalParameter(node); | 1115 _checkForConstFormalParameter(node); |
| 985 _checkForPrivateOptionalParameter(node); | 1116 _checkForPrivateOptionalParameter(node); |
| 986 _checkForTypeAnnotationDeferredClass(node.type); | 1117 _checkForTypeAnnotationDeferredClass(node.type); |
| 1118 |
| 1119 // Checks for an implicit dynamic parameter type. |
| 1120 // |
| 1121 // We can skip other parameter kinds besides simple formal, because: |
| 1122 // - DefaultFormalParameter contains a simple one, so it gets here, |
| 1123 // - FieldFormalParameter error should be reported on the field, |
| 1124 // - FunctionTypedFormalParameter is a function type, not dynamic. |
| 1125 _checkForImplicitDynamicIdentifier(node, node.identifier); |
| 1126 |
| 987 return super.visitSimpleFormalParameter(node); | 1127 return super.visitSimpleFormalParameter(node); |
| 988 } | 1128 } |
| 989 | 1129 |
| 990 @override | 1130 @override |
| 991 Object visitSimpleIdentifier(SimpleIdentifier node) { | 1131 Object visitSimpleIdentifier(SimpleIdentifier node) { |
| 1132 _checkForAmbiguousImport(node); |
| 1133 _checkForReferenceBeforeDeclaration(node); |
| 992 _checkForImplicitThisReferenceInInitializer(node); | 1134 _checkForImplicitThisReferenceInInitializer(node); |
| 993 if (!_isUnqualifiedReferenceToNonLocalStaticMemberAllowed(node)) { | 1135 if (!_isUnqualifiedReferenceToNonLocalStaticMemberAllowed(node)) { |
| 994 _checkForUnqualifiedReferenceToNonLocalStaticMember(node); | 1136 _checkForUnqualifiedReferenceToNonLocalStaticMember(node); |
| 995 } | 1137 } |
| 996 return super.visitSimpleIdentifier(node); | 1138 return super.visitSimpleIdentifier(node); |
| 997 } | 1139 } |
| 998 | 1140 |
| 999 @override | 1141 @override |
| 1000 Object visitSuperConstructorInvocation(SuperConstructorInvocation node) { | 1142 Object visitSuperConstructorInvocation(SuperConstructorInvocation node) { |
| 1001 _isInConstructorInitializer = true; | 1143 _isInConstructorInitializer = true; |
| 1002 try { | 1144 try { |
| 1003 return super.visitSuperConstructorInvocation(node); | 1145 return super.visitSuperConstructorInvocation(node); |
| 1004 } finally { | 1146 } finally { |
| 1005 _isInConstructorInitializer = false; | 1147 _isInConstructorInitializer = false; |
| 1006 } | 1148 } |
| 1007 } | 1149 } |
| 1008 | 1150 |
| 1009 @override | 1151 @override |
| 1152 Object visitSwitchCase(SwitchCase node) { |
| 1153 _checkDuplicateDeclarationInStatements(node.statements); |
| 1154 return super.visitSwitchCase(node); |
| 1155 } |
| 1156 |
| 1157 @override |
| 1158 Object visitSwitchDefault(SwitchDefault node) { |
| 1159 _checkDuplicateDeclarationInStatements(node.statements); |
| 1160 return super.visitSwitchDefault(node); |
| 1161 } |
| 1162 |
| 1163 @override |
| 1010 Object visitSwitchStatement(SwitchStatement node) { | 1164 Object visitSwitchStatement(SwitchStatement node) { |
| 1011 _checkForSwitchExpressionNotAssignable(node); | 1165 _checkForSwitchExpressionNotAssignable(node); |
| 1012 _checkForCaseBlocksNotTerminated(node); | 1166 _checkForCaseBlocksNotTerminated(node); |
| 1013 _checkForMissingEnumConstantInSwitch(node); | 1167 _checkForMissingEnumConstantInSwitch(node); |
| 1014 return super.visitSwitchStatement(node); | 1168 return super.visitSwitchStatement(node); |
| 1015 } | 1169 } |
| 1016 | 1170 |
| 1017 @override | 1171 @override |
| 1018 Object visitThisExpression(ThisExpression node) { | 1172 Object visitThisExpression(ThisExpression node) { |
| 1019 _checkForInvalidReferenceToThis(node); | 1173 _checkForInvalidReferenceToThis(node); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1047 _checkForTypeParameterReferencedByStatic(node); | 1201 _checkForTypeParameterReferencedByStatic(node); |
| 1048 return super.visitTypeName(node); | 1202 return super.visitTypeName(node); |
| 1049 } | 1203 } |
| 1050 | 1204 |
| 1051 @override | 1205 @override |
| 1052 Object visitTypeParameter(TypeParameter node) { | 1206 Object visitTypeParameter(TypeParameter node) { |
| 1053 _checkForBuiltInIdentifierAsName(node.name, | 1207 _checkForBuiltInIdentifierAsName(node.name, |
| 1054 CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_PARAMETER_NAME); | 1208 CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_PARAMETER_NAME); |
| 1055 _checkForTypeParameterSupertypeOfItsBound(node); | 1209 _checkForTypeParameterSupertypeOfItsBound(node); |
| 1056 _checkForTypeAnnotationDeferredClass(node.bound); | 1210 _checkForTypeAnnotationDeferredClass(node.bound); |
| 1211 _checkForImplicitDynamicType(node.bound); |
| 1057 return super.visitTypeParameter(node); | 1212 return super.visitTypeParameter(node); |
| 1058 } | 1213 } |
| 1059 | 1214 |
| 1060 @override | 1215 @override |
| 1216 Object visitTypeParameterList(TypeParameterList node) { |
| 1217 _checkDuplicateDefinitionInTypeParameterList(node); |
| 1218 return super.visitTypeParameterList(node); |
| 1219 } |
| 1220 |
| 1221 @override |
| 1061 Object visitVariableDeclaration(VariableDeclaration node) { | 1222 Object visitVariableDeclaration(VariableDeclaration node) { |
| 1062 SimpleIdentifier nameNode = node.name; | 1223 SimpleIdentifier nameNode = node.name; |
| 1063 Expression initializerNode = node.initializer; | 1224 Expression initializerNode = node.initializer; |
| 1064 // do checks | 1225 // do checks |
| 1065 _checkForInvalidAssignment(nameNode, initializerNode); | 1226 _checkForInvalidAssignment(nameNode, initializerNode); |
| 1227 _checkForImplicitDynamicIdentifier(node, nameNode); |
| 1066 // visit name | 1228 // visit name |
| 1067 nameNode.accept(this); | 1229 nameNode.accept(this); |
| 1068 // visit initializer | 1230 // visit initializer |
| 1069 String name = nameNode.name; | 1231 String name = nameNode.name; |
| 1070 _namesForReferenceToDeclaredVariableInInitializer.add(name); | 1232 _namesForReferenceToDeclaredVariableInInitializer.add(name); |
| 1071 bool wasInInstanceVariableInitializer = _isInInstanceVariableInitializer; | 1233 bool wasInInstanceVariableInitializer = _isInInstanceVariableInitializer; |
| 1072 _isInInstanceVariableInitializer = _isInInstanceVariableDeclaration; | 1234 _isInInstanceVariableInitializer = _isInInstanceVariableDeclaration; |
| 1073 try { | 1235 try { |
| 1074 if (initializerNode != null) { | 1236 if (initializerNode != null) { |
| 1075 initializerNode.accept(this); | 1237 initializerNode.accept(this); |
| 1076 } | 1238 } |
| 1077 } finally { | 1239 } finally { |
| 1078 _isInInstanceVariableInitializer = wasInInstanceVariableInitializer; | 1240 _isInInstanceVariableInitializer = wasInInstanceVariableInitializer; |
| 1079 _namesForReferenceToDeclaredVariableInInitializer.remove(name); | 1241 _namesForReferenceToDeclaredVariableInInitializer.remove(name); |
| 1080 } | 1242 } |
| 1243 // declare the variable |
| 1244 AstNode grandparent = node.parent.parent; |
| 1245 if (grandparent is! TopLevelVariableDeclaration && |
| 1246 grandparent is! FieldDeclaration) { |
| 1247 VariableElement element = node.element; |
| 1248 if (element != null) { |
| 1249 _hiddenElements.declare(element); |
| 1250 } |
| 1251 } |
| 1081 // done | 1252 // done |
| 1082 return null; | 1253 return null; |
| 1083 } | 1254 } |
| 1084 | 1255 |
| 1085 @override | 1256 @override |
| 1086 Object visitVariableDeclarationList(VariableDeclarationList node) { | 1257 Object visitVariableDeclarationList(VariableDeclarationList node) { |
| 1087 _checkForTypeAnnotationDeferredClass(node.type); | 1258 _checkForTypeAnnotationDeferredClass(node.type); |
| 1088 return super.visitVariableDeclarationList(node); | 1259 return super.visitVariableDeclarationList(node); |
| 1089 } | 1260 } |
| 1090 | 1261 |
| 1091 @override | 1262 @override |
| 1092 Object visitVariableDeclarationStatement(VariableDeclarationStatement node) { | 1263 Object visitVariableDeclarationStatement(VariableDeclarationStatement node) { |
| 1093 _checkForFinalNotInitialized(node.variables); | 1264 _checkForFinalNotInitialized(node.variables); |
| 1094 return super.visitVariableDeclarationStatement(node); | 1265 return super.visitVariableDeclarationStatement(node); |
| 1095 } | 1266 } |
| 1096 | 1267 |
| 1097 @override | 1268 @override |
| 1098 Object visitWhileStatement(WhileStatement node) { | 1269 Object visitWhileStatement(WhileStatement node) { |
| 1099 _checkForNonBoolCondition(node.condition); | 1270 _checkForNonBoolCondition(node.condition); |
| 1100 return super.visitWhileStatement(node); | 1271 return super.visitWhileStatement(node); |
| 1101 } | 1272 } |
| 1102 | 1273 |
| 1103 @override | 1274 @override |
| 1275 Object visitWithClause(WithClause node) { |
| 1276 node.mixinTypes.forEach(_checkForImplicitDynamicType); |
| 1277 return super.visitWithClause(node); |
| 1278 } |
| 1279 |
| 1280 @override |
| 1104 Object visitYieldStatement(YieldStatement node) { | 1281 Object visitYieldStatement(YieldStatement node) { |
| 1105 if (_inGenerator) { | 1282 if (_inGenerator) { |
| 1106 _checkForYieldOfInvalidType(node.expression, node.star != null); | 1283 _checkForYieldOfInvalidType(node.expression, node.star != null); |
| 1107 } else { | 1284 } else { |
| 1108 CompileTimeErrorCode errorCode; | 1285 CompileTimeErrorCode errorCode; |
| 1109 if (node.star != null) { | 1286 if (node.star != null) { |
| 1110 errorCode = CompileTimeErrorCode.YIELD_EACH_IN_NON_GENERATOR; | 1287 errorCode = CompileTimeErrorCode.YIELD_EACH_IN_NON_GENERATOR; |
| 1111 } else { | 1288 } else { |
| 1112 errorCode = CompileTimeErrorCode.YIELD_IN_NON_GENERATOR; | 1289 errorCode = CompileTimeErrorCode.YIELD_IN_NON_GENERATOR; |
| 1113 } | 1290 } |
| 1114 _errorReporter.reportErrorForNode(errorCode, node); | 1291 _errorReporter.reportErrorForNode(errorCode, node); |
| 1115 } | 1292 } |
| 1116 return super.visitYieldStatement(node); | 1293 return super.visitYieldStatement(node); |
| 1117 } | 1294 } |
| 1118 | 1295 |
| 1119 /** | 1296 /** |
| 1297 * If the given assert [statement] specifies a message, verify that support |
| 1298 * for assertions with messages is enabled. |
| 1299 */ |
| 1300 void _checkAssertMessage(AssertStatement statement) { |
| 1301 Expression expression = statement.message; |
| 1302 if (expression != null && !enableAssertMessage) { |
| 1303 _errorReporter.reportErrorForNode( |
| 1304 CompileTimeErrorCode.EXTRA_ARGUMENT_TO_ASSERT, expression); |
| 1305 } |
| 1306 } |
| 1307 |
| 1308 /** |
| 1309 * Given a list of [directives] that have the same prefix, generate an error |
| 1310 * if there is more than one import and any of those imports is deferred. |
| 1311 * |
| 1312 * See [CompileTimeErrorCode.SHARED_DEFERRED_PREFIX]. |
| 1313 */ |
| 1314 void _checkDeferredPrefixCollision(List<ImportDirective> directives) { |
| 1315 int count = directives.length; |
| 1316 if (count > 1) { |
| 1317 for (int i = 0; i < count; i++) { |
| 1318 Token deferredToken = directives[i].deferredKeyword; |
| 1319 if (deferredToken != null) { |
| 1320 _errorReporter.reportErrorForToken( |
| 1321 CompileTimeErrorCode.SHARED_DEFERRED_PREFIX, deferredToken); |
| 1322 } |
| 1323 } |
| 1324 } |
| 1325 } |
| 1326 |
| 1327 /** |
| 1328 * Check that there are no members with the same name. |
| 1329 */ |
| 1330 void _checkDuplicateClassMembers(ClassDeclaration node) { |
| 1331 Map<String, Element> definedNames = new HashMap<String, Element>(); |
| 1332 Set<String> visitedFields = new HashSet<String>(); |
| 1333 for (ClassMember member in node.members) { |
| 1334 // We ignore constructors because they are checked in the method |
| 1335 // _checkForConflictingConstructorNameAndMember. |
| 1336 if (member is FieldDeclaration) { |
| 1337 for (VariableDeclaration field in member.fields.variables) { |
| 1338 SimpleIdentifier identifier = field.name; |
| 1339 _checkDuplicateIdentifier(definedNames, identifier); |
| 1340 String name = identifier.name; |
| 1341 if (!field.isFinal && |
| 1342 !field.isConst && |
| 1343 !visitedFields.contains(name)) { |
| 1344 _checkDuplicateIdentifier(definedNames, identifier, |
| 1345 implicitSetter: true); |
| 1346 } |
| 1347 visitedFields.add(name); |
| 1348 } |
| 1349 } else if (member is MethodDeclaration) { |
| 1350 _checkDuplicateIdentifier(definedNames, member.name); |
| 1351 } |
| 1352 } |
| 1353 } |
| 1354 |
| 1355 /** |
| 1356 * Check that all of the parameters have unique names. |
| 1357 */ |
| 1358 void _checkDuplicateDeclarationInStatements(List<Statement> statements) { |
| 1359 Map<String, Element> definedNames = new HashMap<String, Element>(); |
| 1360 for (Statement statement in statements) { |
| 1361 if (statement is VariableDeclarationStatement) { |
| 1362 for (VariableDeclaration variable in statement.variables.variables) { |
| 1363 _checkDuplicateIdentifier(definedNames, variable.name); |
| 1364 } |
| 1365 } else if (statement is FunctionDeclarationStatement) { |
| 1366 _checkDuplicateIdentifier( |
| 1367 definedNames, statement.functionDeclaration.name); |
| 1368 } |
| 1369 } |
| 1370 } |
| 1371 |
| 1372 /** |
| 1373 * Check that the exception and stack trace parameters have different names. |
| 1374 */ |
| 1375 void _checkDuplicateDefinitionInCatchClause(CatchClause node) { |
| 1376 SimpleIdentifier exceptionParameter = node.exceptionParameter; |
| 1377 SimpleIdentifier stackTraceParameter = node.stackTraceParameter; |
| 1378 if (exceptionParameter != null && stackTraceParameter != null) { |
| 1379 String exceptionName = exceptionParameter.name; |
| 1380 if (exceptionName == stackTraceParameter.name) { |
| 1381 _errorReporter.reportErrorForNode( |
| 1382 CompileTimeErrorCode.DUPLICATE_DEFINITION, |
| 1383 stackTraceParameter, |
| 1384 [exceptionName]); |
| 1385 } |
| 1386 } |
| 1387 } |
| 1388 |
| 1389 /** |
| 1390 * Check that all of the parameters have unique names. |
| 1391 */ |
| 1392 void _checkDuplicateDefinitionInParameterList(FormalParameterList node) { |
| 1393 Map<String, Element> definedNames = new HashMap<String, Element>(); |
| 1394 for (FormalParameter parameter in node.parameters) { |
| 1395 _checkDuplicateIdentifier(definedNames, parameter.identifier); |
| 1396 } |
| 1397 } |
| 1398 |
| 1399 /** |
| 1400 * Check that all of the parameters have unique names. |
| 1401 */ |
| 1402 void _checkDuplicateDefinitionInTypeParameterList(TypeParameterList node) { |
| 1403 Map<String, Element> definedNames = new HashMap<String, Element>(); |
| 1404 for (TypeParameter parameter in node.typeParameters) { |
| 1405 _checkDuplicateIdentifier(definedNames, parameter.name); |
| 1406 } |
| 1407 } |
| 1408 |
| 1409 /** |
| 1410 * Check that there are no members with the same name. |
| 1411 */ |
| 1412 void _checkDuplicateEnumMembers(EnumDeclaration node) { |
| 1413 Map<String, Element> definedNames = new HashMap<String, Element>(); |
| 1414 ClassElement element = node.element; |
| 1415 String indexName = 'index'; |
| 1416 String valuesName = 'values'; |
| 1417 definedNames[indexName] = element.getField(indexName); |
| 1418 definedNames[valuesName] = element.getField(valuesName); |
| 1419 for (EnumConstantDeclaration constant in node.constants) { |
| 1420 _checkDuplicateIdentifier(definedNames, constant.name); |
| 1421 } |
| 1422 } |
| 1423 |
| 1424 /** |
| 1425 * Check whether the given [identifier] is already in the set of |
| 1426 * [definedNames], and produce an error if it is. If [implicitSetter] is |
| 1427 * `true`, then the identifier represents the definition of a setter. |
| 1428 */ |
| 1429 void _checkDuplicateIdentifier( |
| 1430 Map<String, Element> definedNames, SimpleIdentifier identifier, |
| 1431 {bool implicitSetter: false}) { |
| 1432 ErrorCode getError(Element previous, Element current) { |
| 1433 if (previous is MethodElement && current is PropertyAccessorElement) { |
| 1434 if (current.isGetter) { |
| 1435 return CompileTimeErrorCode.GETTER_AND_METHOD_WITH_SAME_NAME; |
| 1436 } |
| 1437 } else if (previous is PropertyAccessorElement && |
| 1438 current is MethodElement) { |
| 1439 if (previous.isGetter) { |
| 1440 return CompileTimeErrorCode.METHOD_AND_GETTER_WITH_SAME_NAME; |
| 1441 } |
| 1442 } else if (previous is PrefixElement) { |
| 1443 return CompileTimeErrorCode.PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER; |
| 1444 } |
| 1445 return CompileTimeErrorCode.DUPLICATE_DEFINITION; |
| 1446 } |
| 1447 |
| 1448 Element current = identifier.staticElement; |
| 1449 String name = identifier.name; |
| 1450 if (current is PropertyAccessorElement && current.isSetter) { |
| 1451 name += '='; |
| 1452 } else if (current is MethodElement && current.isOperator && name == '-') { |
| 1453 if (current.parameters.length == 0) { |
| 1454 name = 'unary-'; |
| 1455 } |
| 1456 } else if (implicitSetter) { |
| 1457 name += '='; |
| 1458 } |
| 1459 Element previous = definedNames[name]; |
| 1460 if (previous != null) { |
| 1461 _errorReporter |
| 1462 .reportErrorForNode(getError(previous, current), identifier, [name]); |
| 1463 } else { |
| 1464 definedNames[name] = identifier.staticElement; |
| 1465 } |
| 1466 } |
| 1467 |
| 1468 /** |
| 1469 * Check that there are no members with the same name. |
| 1470 */ |
| 1471 void _checkDuplicateUnitMembers(CompilationUnit node) { |
| 1472 Map<String, Element> definedNames = new HashMap<String, Element>(); |
| 1473 void addWithoutChecking(CompilationUnitElement element) { |
| 1474 for (PropertyAccessorElement accessor in element.accessors) { |
| 1475 String name = accessor.name; |
| 1476 if (accessor.isSetter) { |
| 1477 name += '='; |
| 1478 } |
| 1479 definedNames[name] = accessor; |
| 1480 } |
| 1481 for (ClassElement type in element.enums) { |
| 1482 definedNames[type.name] = type; |
| 1483 } |
| 1484 for (FunctionElement function in element.functions) { |
| 1485 definedNames[function.name] = function; |
| 1486 } |
| 1487 for (FunctionTypeAliasElement alias in element.functionTypeAliases) { |
| 1488 definedNames[alias.name] = alias; |
| 1489 } |
| 1490 for (TopLevelVariableElement variable in element.topLevelVariables) { |
| 1491 definedNames[variable.name] = variable; |
| 1492 if (!variable.isFinal && !variable.isConst) { |
| 1493 definedNames[variable.name + '='] = variable; |
| 1494 } |
| 1495 } |
| 1496 for (ClassElement type in element.types) { |
| 1497 definedNames[type.name] = type; |
| 1498 } |
| 1499 } |
| 1500 |
| 1501 for (ImportElement importElement in _currentLibrary.imports) { |
| 1502 PrefixElement prefix = importElement.prefix; |
| 1503 if (prefix != null) { |
| 1504 definedNames[prefix.name] = prefix; |
| 1505 } |
| 1506 } |
| 1507 CompilationUnitElement element = node.element; |
| 1508 if (element != _currentLibrary.definingCompilationUnit) { |
| 1509 addWithoutChecking(_currentLibrary.definingCompilationUnit); |
| 1510 for (CompilationUnitElement part in _currentLibrary.parts) { |
| 1511 if (element == part) { |
| 1512 break; |
| 1513 } |
| 1514 addWithoutChecking(part); |
| 1515 } |
| 1516 } |
| 1517 for (CompilationUnitMember member in node.declarations) { |
| 1518 if (member is NamedCompilationUnitMember) { |
| 1519 _checkDuplicateIdentifier(definedNames, member.name); |
| 1520 } else if (member is TopLevelVariableDeclaration) { |
| 1521 for (VariableDeclaration variable in member.variables.variables) { |
| 1522 _checkDuplicateIdentifier(definedNames, variable.name); |
| 1523 if (!variable.isFinal && !variable.isConst) { |
| 1524 _checkDuplicateIdentifier(definedNames, variable.name, |
| 1525 implicitSetter: true); |
| 1526 } |
| 1527 } |
| 1528 } |
| 1529 } |
| 1530 } |
| 1531 |
| 1532 /** |
| 1533 * Check that the given list of variable declarations does not define multiple |
| 1534 * variables of the same name. |
| 1535 */ |
| 1536 void _checkDuplicateVariables(VariableDeclarationList node) { |
| 1537 Map<String, Element> definedNames = new HashMap<String, Element>(); |
| 1538 for (VariableDeclaration variable in node.variables) { |
| 1539 _checkDuplicateIdentifier(definedNames, variable.name); |
| 1540 } |
| 1541 } |
| 1542 |
| 1543 /** |
| 1120 * Verify that the given list of [typeArguments] contains exactly two | 1544 * Verify that the given list of [typeArguments] contains exactly two |
| 1121 * elements. | 1545 * elements. |
| 1122 * | 1546 * |
| 1123 * See [StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS]. | 1547 * See [StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS]. |
| 1124 */ | 1548 */ |
| 1125 bool _checkExpectedTwoMapTypeArguments(TypeArgumentList typeArguments) { | 1549 void _checkExpectedTwoMapTypeArguments(TypeArgumentList typeArguments) { |
| 1126 // check number of type arguments | |
| 1127 int num = typeArguments.arguments.length; | 1550 int num = typeArguments.arguments.length; |
| 1128 if (num == 2) { | 1551 if (num != 2) { |
| 1129 return false; | 1552 _errorReporter.reportErrorForNode( |
| 1130 } | 1553 StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS, |
| 1131 // report problem | 1554 typeArguments, |
| 1132 _errorReporter.reportErrorForNode( | 1555 [num]); |
| 1133 StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS, | 1556 } |
| 1134 typeArguments, | 1557 } |
| 1135 [num]); | 1558 |
| 1136 return true; | 1559 /** |
| 1137 } | |
| 1138 | |
| 1139 /** | |
| 1140 * Verify that the given [constructor] declaration does not violate any of the | 1560 * Verify that the given [constructor] declaration does not violate any of the |
| 1141 * error codes relating to the initialization of fields in the enclosing | 1561 * error codes relating to the initialization of fields in the enclosing |
| 1142 * class. | 1562 * class. |
| 1143 * | 1563 * |
| 1144 * See [_initialFieldElementsMap], | 1564 * See [_initialFieldElementsMap], |
| 1145 * [StaticWarningCode.FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR], and | 1565 * [StaticWarningCode.FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR], and |
| 1146 * [CompileTimeErrorCode.FINAL_INITIALIZED_MULTIPLE_TIMES]. | 1566 * [CompileTimeErrorCode.FINAL_INITIALIZED_MULTIPLE_TIMES]. |
| 1147 */ | 1567 */ |
| 1148 bool _checkForAllFinalInitializedErrorCodes( | 1568 void _checkForAllFinalInitializedErrorCodes( |
| 1149 ConstructorDeclaration constructor) { | 1569 ConstructorDeclaration constructor) { |
| 1150 if (constructor.factoryKeyword != null || | 1570 if (constructor.factoryKeyword != null || |
| 1151 constructor.redirectedConstructor != null || | 1571 constructor.redirectedConstructor != null || |
| 1152 constructor.externalKeyword != null) { | 1572 constructor.externalKeyword != null) { |
| 1153 return false; | 1573 return; |
| 1154 } | 1574 } |
| 1155 // Ignore if native class. | 1575 // Ignore if native class. |
| 1156 if (_isInNativeClass) { | 1576 if (_isInNativeClass) { |
| 1157 return false; | 1577 return; |
| 1158 } | 1578 } |
| 1159 bool foundError = false; | 1579 |
| 1160 HashMap<FieldElement, INIT_STATE> fieldElementsMap = | 1580 HashMap<FieldElement, INIT_STATE> fieldElementsMap = |
| 1161 new HashMap<FieldElement, INIT_STATE>.from(_initialFieldElementsMap); | 1581 new HashMap<FieldElement, INIT_STATE>.from(_initialFieldElementsMap); |
| 1162 // Visit all of the field formal parameters | 1582 // Visit all of the field formal parameters |
| 1163 NodeList<FormalParameter> formalParameters = | 1583 NodeList<FormalParameter> formalParameters = |
| 1164 constructor.parameters.parameters; | 1584 constructor.parameters.parameters; |
| 1165 for (FormalParameter formalParameter in formalParameters) { | 1585 for (FormalParameter formalParameter in formalParameters) { |
| 1166 FormalParameter parameter = formalParameter; | 1586 FormalParameter baseParameter(FormalParameter parameter) { |
| 1167 if (parameter is DefaultFormalParameter) { | 1587 if (parameter is DefaultFormalParameter) { |
| 1168 parameter = (parameter as DefaultFormalParameter).parameter; | 1588 return parameter.parameter; |
| 1589 } |
| 1590 return parameter; |
| 1169 } | 1591 } |
| 1592 |
| 1593 FormalParameter parameter = baseParameter(formalParameter); |
| 1170 if (parameter is FieldFormalParameter) { | 1594 if (parameter is FieldFormalParameter) { |
| 1171 FieldElement fieldElement = | 1595 FieldElement fieldElement = |
| 1172 (parameter.element as FieldFormalParameterElementImpl).field; | 1596 (parameter.element as FieldFormalParameterElementImpl).field; |
| 1173 INIT_STATE state = fieldElementsMap[fieldElement]; | 1597 INIT_STATE state = fieldElementsMap[fieldElement]; |
| 1174 if (state == INIT_STATE.NOT_INIT) { | 1598 if (state == INIT_STATE.NOT_INIT) { |
| 1175 fieldElementsMap[fieldElement] = INIT_STATE.INIT_IN_FIELD_FORMAL; | 1599 fieldElementsMap[fieldElement] = INIT_STATE.INIT_IN_FIELD_FORMAL; |
| 1176 } else if (state == INIT_STATE.INIT_IN_DECLARATION) { | 1600 } else if (state == INIT_STATE.INIT_IN_DECLARATION) { |
| 1177 if (fieldElement.isFinal || fieldElement.isConst) { | 1601 if (fieldElement.isFinal || fieldElement.isConst) { |
| 1178 _errorReporter.reportErrorForNode( | 1602 _errorReporter.reportErrorForNode( |
| 1179 StaticWarningCode.FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCT
OR, | 1603 StaticWarningCode |
| 1604 .FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR, |
| 1180 formalParameter.identifier, | 1605 formalParameter.identifier, |
| 1181 [fieldElement.displayName]); | 1606 [fieldElement.displayName]); |
| 1182 foundError = true; | |
| 1183 } | 1607 } |
| 1184 } else if (state == INIT_STATE.INIT_IN_FIELD_FORMAL) { | 1608 } else if (state == INIT_STATE.INIT_IN_FIELD_FORMAL) { |
| 1185 if (fieldElement.isFinal || fieldElement.isConst) { | 1609 if (fieldElement.isFinal || fieldElement.isConst) { |
| 1186 _errorReporter.reportErrorForNode( | 1610 _errorReporter.reportErrorForNode( |
| 1187 CompileTimeErrorCode.FINAL_INITIALIZED_MULTIPLE_TIMES, | 1611 CompileTimeErrorCode.FINAL_INITIALIZED_MULTIPLE_TIMES, |
| 1188 formalParameter.identifier, | 1612 formalParameter.identifier, |
| 1189 [fieldElement.displayName]); | 1613 [fieldElement.displayName]); |
| 1190 foundError = true; | |
| 1191 } | 1614 } |
| 1192 } | 1615 } |
| 1193 } | 1616 } |
| 1194 } | 1617 } |
| 1195 // Visit all of the initializers | 1618 // Visit all of the initializers |
| 1196 NodeList<ConstructorInitializer> initializers = constructor.initializers; | 1619 NodeList<ConstructorInitializer> initializers = constructor.initializers; |
| 1197 for (ConstructorInitializer constructorInitializer in initializers) { | 1620 for (ConstructorInitializer constructorInitializer in initializers) { |
| 1198 if (constructorInitializer is RedirectingConstructorInvocation) { | 1621 if (constructorInitializer is RedirectingConstructorInvocation) { |
| 1199 return false; | 1622 return; |
| 1200 } | 1623 } |
| 1201 if (constructorInitializer is ConstructorFieldInitializer) { | 1624 if (constructorInitializer is ConstructorFieldInitializer) { |
| 1202 ConstructorFieldInitializer constructorFieldInitializer = | 1625 SimpleIdentifier fieldName = constructorInitializer.fieldName; |
| 1203 constructorInitializer; | |
| 1204 SimpleIdentifier fieldName = constructorFieldInitializer.fieldName; | |
| 1205 Element element = fieldName.staticElement; | 1626 Element element = fieldName.staticElement; |
| 1206 if (element is FieldElement) { | 1627 if (element is FieldElement) { |
| 1207 FieldElement fieldElement = element; | 1628 INIT_STATE state = fieldElementsMap[element]; |
| 1208 INIT_STATE state = fieldElementsMap[fieldElement]; | |
| 1209 if (state == INIT_STATE.NOT_INIT) { | 1629 if (state == INIT_STATE.NOT_INIT) { |
| 1210 fieldElementsMap[fieldElement] = INIT_STATE.INIT_IN_INITIALIZERS; | 1630 fieldElementsMap[element] = INIT_STATE.INIT_IN_INITIALIZERS; |
| 1211 } else if (state == INIT_STATE.INIT_IN_DECLARATION) { | 1631 } else if (state == INIT_STATE.INIT_IN_DECLARATION) { |
| 1212 if (fieldElement.isFinal || fieldElement.isConst) { | 1632 if (element.isFinal || element.isConst) { |
| 1213 _errorReporter.reportErrorForNode( | 1633 _errorReporter.reportErrorForNode( |
| 1214 StaticWarningCode.FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARA
TION, | 1634 StaticWarningCode |
| 1635 .FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION, |
| 1215 fieldName); | 1636 fieldName); |
| 1216 foundError = true; | |
| 1217 } | 1637 } |
| 1218 } else if (state == INIT_STATE.INIT_IN_FIELD_FORMAL) { | 1638 } else if (state == INIT_STATE.INIT_IN_FIELD_FORMAL) { |
| 1219 _errorReporter.reportErrorForNode( | 1639 _errorReporter.reportErrorForNode( |
| 1220 CompileTimeErrorCode.FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALI
ZER, | 1640 CompileTimeErrorCode |
| 1641 .FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER, |
| 1221 fieldName); | 1642 fieldName); |
| 1222 foundError = true; | |
| 1223 } else if (state == INIT_STATE.INIT_IN_INITIALIZERS) { | 1643 } else if (state == INIT_STATE.INIT_IN_INITIALIZERS) { |
| 1224 _errorReporter.reportErrorForNode( | 1644 _errorReporter.reportErrorForNode( |
| 1225 CompileTimeErrorCode.FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS, | 1645 CompileTimeErrorCode.FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS, |
| 1226 fieldName, | 1646 fieldName, |
| 1227 [fieldElement.displayName]); | 1647 [element.displayName]); |
| 1228 foundError = true; | |
| 1229 } | 1648 } |
| 1230 } | 1649 } |
| 1231 } | 1650 } |
| 1232 } | 1651 } |
| 1233 // Prepare a list of not initialized fields. | 1652 // Prepare a list of not initialized fields. |
| 1234 List<FieldElement> notInitFinalFields = <FieldElement>[]; | 1653 List<FieldElement> notInitFinalFields = <FieldElement>[]; |
| 1235 fieldElementsMap.forEach((FieldElement fieldElement, INIT_STATE state) { | 1654 fieldElementsMap.forEach((FieldElement fieldElement, INIT_STATE state) { |
| 1236 if (state == INIT_STATE.NOT_INIT) { | 1655 if (state == INIT_STATE.NOT_INIT) { |
| 1237 if (fieldElement.isFinal) { | 1656 if (fieldElement.isFinal) { |
| 1238 notInitFinalFields.add(fieldElement); | 1657 notInitFinalFields.add(fieldElement); |
| 1239 } | 1658 } |
| 1240 } | 1659 } |
| 1241 }); | 1660 }); |
| 1242 // Visit all of the states in the map to ensure that none were never | 1661 // Visit all of the states in the map to ensure that none were never |
| 1243 // initialized. | 1662 // initialized. |
| 1244 fieldElementsMap.forEach((FieldElement fieldElement, INIT_STATE state) { | 1663 fieldElementsMap.forEach((FieldElement fieldElement, INIT_STATE state) { |
| 1245 if (state == INIT_STATE.NOT_INIT) { | 1664 if (state == INIT_STATE.NOT_INIT) { |
| 1246 if (fieldElement.isConst) { | 1665 if (fieldElement.isConst) { |
| 1247 _errorReporter.reportErrorForNode( | 1666 _errorReporter.reportErrorForNode( |
| 1248 CompileTimeErrorCode.CONST_NOT_INITIALIZED, | 1667 CompileTimeErrorCode.CONST_NOT_INITIALIZED, |
| 1249 constructor.returnType, | 1668 constructor.returnType, |
| 1250 [fieldElement.name]); | 1669 [fieldElement.name]); |
| 1251 foundError = true; | |
| 1252 } | 1670 } |
| 1253 } | 1671 } |
| 1254 }); | 1672 }); |
| 1673 |
| 1255 if (notInitFinalFields.isNotEmpty) { | 1674 if (notInitFinalFields.isNotEmpty) { |
| 1256 foundError = true; | |
| 1257 AnalysisErrorWithProperties analysisError; | 1675 AnalysisErrorWithProperties analysisError; |
| 1258 if (notInitFinalFields.length == 1) { | 1676 List<String> names = notInitFinalFields.map((item) => item.name).toList(); |
| 1677 names.sort(); |
| 1678 if (names.length == 1) { |
| 1259 analysisError = _errorReporter.newErrorWithProperties( | 1679 analysisError = _errorReporter.newErrorWithProperties( |
| 1260 StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_1, | 1680 StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_1, |
| 1261 constructor.returnType, | 1681 constructor.returnType, |
| 1262 [notInitFinalFields[0].name]); | 1682 names); |
| 1263 } else if (notInitFinalFields.length == 2) { | 1683 } else if (names.length == 2) { |
| 1264 analysisError = _errorReporter.newErrorWithProperties( | 1684 analysisError = _errorReporter.newErrorWithProperties( |
| 1265 StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_2, | 1685 StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_2, |
| 1266 constructor.returnType, | 1686 constructor.returnType, |
| 1267 [notInitFinalFields[0].name, notInitFinalFields[1].name]); | 1687 names); |
| 1268 } else { | 1688 } else { |
| 1269 analysisError = _errorReporter.newErrorWithProperties( | 1689 analysisError = _errorReporter.newErrorWithProperties( |
| 1270 StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_3_PLUS, | 1690 StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_3_PLUS, |
| 1271 constructor.returnType, [ | 1691 constructor.returnType, |
| 1272 notInitFinalFields[0].name, | 1692 [names[0], names[1], names.length - 2]); |
| 1273 notInitFinalFields[1].name, | |
| 1274 notInitFinalFields.length - 2 | |
| 1275 ]); | |
| 1276 } | 1693 } |
| 1277 analysisError.setProperty( | 1694 analysisError.setProperty( |
| 1278 ErrorProperty.NOT_INITIALIZED_FIELDS, notInitFinalFields); | 1695 ErrorProperty.NOT_INITIALIZED_FIELDS, notInitFinalFields); |
| 1279 _errorReporter.reportError(analysisError); | 1696 _errorReporter.reportError(analysisError); |
| 1280 } | 1697 } |
| 1281 return foundError; | |
| 1282 } | 1698 } |
| 1283 | 1699 |
| 1284 /** | 1700 /** |
| 1285 * Check the given [executableElement] against override-error codes. The | 1701 * Check the given [derivedElement] against override-error codes. The |
| 1286 * [overriddenExecutable] is the element that the executable element is | 1702 * [baseElement] is the element that the executable element is |
| 1287 * overriding. The [parameters] is the parameters of the executable element. | 1703 * overriding. The [parameters] is the parameters of the executable element. |
| 1288 * The [errorNameTarget] is the node to report problems on. | 1704 * The [errorNameTarget] is the node to report problems on. |
| 1289 * | 1705 * |
| 1290 * See [StaticWarningCode.INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_STATIC
], | 1706 * See [StaticWarningCode.INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_STATIC
], |
| 1291 * [CompileTimeErrorCode.INVALID_OVERRIDE_REQUIRED], | 1707 * [CompileTimeErrorCode.INVALID_OVERRIDE_REQUIRED], |
| 1292 * [CompileTimeErrorCode.INVALID_OVERRIDE_POSITIONAL], | 1708 * [CompileTimeErrorCode.INVALID_OVERRIDE_POSITIONAL], |
| 1293 * [CompileTimeErrorCode.INVALID_OVERRIDE_NAMED], | 1709 * [CompileTimeErrorCode.INVALID_OVERRIDE_NAMED], |
| 1294 * [StaticWarningCode.INVALID_GETTER_OVERRIDE_RETURN_TYPE], | 1710 * [StaticWarningCode.INVALID_GETTER_OVERRIDE_RETURN_TYPE], |
| 1295 * [StaticWarningCode.INVALID_METHOD_OVERRIDE_RETURN_TYPE], | 1711 * [StaticWarningCode.INVALID_METHOD_OVERRIDE_RETURN_TYPE], |
| 1296 * [StaticWarningCode.INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE], | 1712 * [StaticWarningCode.INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE], |
| 1297 * [StaticWarningCode.INVALID_SETTER_OVERRIDE_NORMAL_PARAM_TYPE], | 1713 * [StaticWarningCode.INVALID_SETTER_OVERRIDE_NORMAL_PARAM_TYPE], |
| 1298 * [StaticWarningCode.INVALID_METHOD_OVERRIDE_OPTIONAL_PARAM_TYPE], | 1714 * [StaticWarningCode.INVALID_METHOD_OVERRIDE_OPTIONAL_PARAM_TYPE], |
| 1299 * [StaticWarningCode.INVALID_METHOD_OVERRIDE_NAMED_PARAM_TYPE], and | 1715 * [StaticWarningCode.INVALID_METHOD_OVERRIDE_NAMED_PARAM_TYPE], and |
| 1300 * [StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES]. | 1716 * [StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES]. |
| 1301 */ | 1717 */ |
| 1302 bool _checkForAllInvalidOverrideErrorCodes( | 1718 bool _checkForAllInvalidOverrideErrorCodes( |
| 1303 ExecutableElement executableElement, | 1719 ExecutableElement derivedElement, |
| 1304 ExecutableElement overriddenExecutable, | 1720 ExecutableElement baseElement, |
| 1305 List<ParameterElement> parameters, | 1721 List<ParameterElement> parameters, |
| 1306 List<AstNode> parameterLocations, | 1722 List<AstNode> parameterLocations, |
| 1307 SimpleIdentifier errorNameTarget) { | 1723 SimpleIdentifier errorNameTarget) { |
| 1724 if (_options.strongMode) { |
| 1725 return false; // strong mode already checked for this |
| 1726 } |
| 1727 |
| 1308 bool isGetter = false; | 1728 bool isGetter = false; |
| 1309 bool isSetter = false; | 1729 bool isSetter = false; |
| 1310 if (executableElement is PropertyAccessorElement) { | 1730 if (derivedElement is PropertyAccessorElement) { |
| 1311 PropertyAccessorElement accessorElement = executableElement; | 1731 isGetter = derivedElement.isGetter; |
| 1312 isGetter = accessorElement.isGetter; | 1732 isSetter = derivedElement.isSetter; |
| 1313 isSetter = accessorElement.isSetter; | |
| 1314 } | 1733 } |
| 1315 String executableElementName = executableElement.name; | 1734 String executableElementName = derivedElement.name; |
| 1316 FunctionType overridingFT = executableElement.type; | 1735 FunctionType derivedFT = derivedElement.type; |
| 1317 FunctionType overriddenFT = overriddenExecutable.type; | 1736 FunctionType baseFT = baseElement.type; |
| 1318 InterfaceType enclosingType = _enclosingClass.type; | 1737 InterfaceType enclosingType = _enclosingClass.type; |
| 1319 overriddenFT = _inheritanceManager | 1738 baseFT = _inheritanceManager.substituteTypeArgumentsInMemberFromInheritance( |
| 1320 .substituteTypeArgumentsInMemberFromInheritance( | 1739 baseFT, executableElementName, enclosingType); |
| 1321 overriddenFT, executableElementName, enclosingType); | 1740 if (derivedFT == null || baseFT == null) { |
| 1322 if (overridingFT == null || overriddenFT == null) { | |
| 1323 return false; | 1741 return false; |
| 1324 } | 1742 } |
| 1325 DartType overridingFTReturnType = overridingFT.returnType; | 1743 |
| 1326 DartType overriddenFTReturnType = overriddenFT.returnType; | 1744 // Handle generic function type parameters. |
| 1327 List<DartType> overridingNormalPT = overridingFT.normalParameterTypes; | 1745 // TODO(jmesserly): this duplicates some code in isSubtypeOf and most of |
| 1328 List<DartType> overriddenNormalPT = overriddenFT.normalParameterTypes; | 1746 // _isGenericFunctionSubtypeOf. Ideally, we'd let TypeSystem produce |
| 1329 List<DartType> overridingPositionalPT = overridingFT.optionalParameterTypes; | 1747 // an error message once it's ready to "return false". |
| 1330 List<DartType> overriddenPositionalPT = overriddenFT.optionalParameterTypes; | 1748 if (!derivedFT.typeFormals.isEmpty) { |
| 1331 Map<String, DartType> overridingNamedPT = overridingFT.namedParameterTypes; | 1749 if (baseFT.typeFormals.isEmpty) { |
| 1332 Map<String, DartType> overriddenNamedPT = overriddenFT.namedParameterTypes; | 1750 derivedFT = _typeSystem.instantiateToBounds(derivedFT); |
| 1751 } else { |
| 1752 List<TypeParameterElement> params1 = derivedFT.typeFormals; |
| 1753 List<TypeParameterElement> params2 = baseFT.typeFormals; |
| 1754 int count = params1.length; |
| 1755 if (params2.length != count) { |
| 1756 _errorReporter.reportErrorForNode( |
| 1757 StaticWarningCode.INVALID_METHOD_OVERRIDE_TYPE_PARAMETERS, |
| 1758 errorNameTarget, [ |
| 1759 count, |
| 1760 params2.length, |
| 1761 baseElement.enclosingElement.displayName |
| 1762 ]); |
| 1763 return true; |
| 1764 } |
| 1765 // We build up a substitution matching up the type parameters |
| 1766 // from the two types, {variablesFresh/variables1} and |
| 1767 // {variablesFresh/variables2} |
| 1768 List<DartType> variables1 = new List<DartType>(); |
| 1769 List<DartType> variables2 = new List<DartType>(); |
| 1770 List<DartType> variablesFresh = new List<DartType>(); |
| 1771 for (int i = 0; i < count; i++) { |
| 1772 TypeParameterElement p1 = params1[i]; |
| 1773 TypeParameterElement p2 = params2[i]; |
| 1774 TypeParameterElementImpl pFresh = |
| 1775 new TypeParameterElementImpl(p1.name, -1); |
| 1776 |
| 1777 DartType variable1 = p1.type; |
| 1778 DartType variable2 = p2.type; |
| 1779 DartType variableFresh = new TypeParameterTypeImpl(pFresh); |
| 1780 |
| 1781 variables1.add(variable1); |
| 1782 variables2.add(variable2); |
| 1783 variablesFresh.add(variableFresh); |
| 1784 DartType bound1 = p1.bound ?? DynamicTypeImpl.instance; |
| 1785 DartType bound2 = p2.bound ?? DynamicTypeImpl.instance; |
| 1786 bound1 = bound1.substitute2(variablesFresh, variables1); |
| 1787 bound2 = bound2.substitute2(variablesFresh, variables2); |
| 1788 pFresh.bound = bound2; |
| 1789 if (!_typeSystem.isSubtypeOf(bound2, bound1)) { |
| 1790 _errorReporter.reportErrorForNode( |
| 1791 StaticWarningCode.INVALID_METHOD_OVERRIDE_TYPE_PARAMETER_BOUND, |
| 1792 errorNameTarget, [ |
| 1793 p1.displayName, |
| 1794 p1.bound, |
| 1795 p2.displayName, |
| 1796 p2.bound, |
| 1797 baseElement.enclosingElement.displayName |
| 1798 ]); |
| 1799 return true; |
| 1800 } |
| 1801 } |
| 1802 // Proceed with the rest of the checks, using instantiated types. |
| 1803 derivedFT = derivedFT.instantiate(variablesFresh); |
| 1804 baseFT = baseFT.instantiate(variablesFresh); |
| 1805 } |
| 1806 } |
| 1807 |
| 1808 DartType derivedFTReturnType = derivedFT.returnType; |
| 1809 DartType baseFTReturnType = baseFT.returnType; |
| 1810 List<DartType> derivedNormalPT = derivedFT.normalParameterTypes; |
| 1811 List<DartType> baseNormalPT = baseFT.normalParameterTypes; |
| 1812 List<DartType> derivedPositionalPT = derivedFT.optionalParameterTypes; |
| 1813 List<DartType> basePositionalPT = baseFT.optionalParameterTypes; |
| 1814 Map<String, DartType> derivedNamedPT = derivedFT.namedParameterTypes; |
| 1815 Map<String, DartType> baseNamedPT = baseFT.namedParameterTypes; |
| 1333 // CTEC.INVALID_OVERRIDE_REQUIRED, CTEC.INVALID_OVERRIDE_POSITIONAL and | 1816 // CTEC.INVALID_OVERRIDE_REQUIRED, CTEC.INVALID_OVERRIDE_POSITIONAL and |
| 1334 // CTEC.INVALID_OVERRIDE_NAMED | 1817 // CTEC.INVALID_OVERRIDE_NAMED |
| 1335 if (overridingNormalPT.length > overriddenNormalPT.length) { | 1818 if (derivedNormalPT.length > baseNormalPT.length) { |
| 1336 _errorReporter.reportErrorForNode( | 1819 _errorReporter.reportErrorForNode( |
| 1337 StaticWarningCode.INVALID_OVERRIDE_REQUIRED, errorNameTarget, [ | 1820 StaticWarningCode.INVALID_OVERRIDE_REQUIRED, errorNameTarget, [ |
| 1338 overriddenNormalPT.length, | 1821 baseNormalPT.length, |
| 1339 overriddenExecutable.enclosingElement.displayName | 1822 baseElement, |
| 1823 baseElement.enclosingElement.displayName |
| 1340 ]); | 1824 ]); |
| 1341 return true; | 1825 return true; |
| 1342 } | 1826 } |
| 1343 if (overridingNormalPT.length + overridingPositionalPT.length < | 1827 if (derivedNormalPT.length + derivedPositionalPT.length < |
| 1344 overriddenPositionalPT.length + overriddenNormalPT.length) { | 1828 basePositionalPT.length + baseNormalPT.length) { |
| 1345 _errorReporter.reportErrorForNode( | 1829 _errorReporter.reportErrorForNode( |
| 1346 StaticWarningCode.INVALID_OVERRIDE_POSITIONAL, errorNameTarget, [ | 1830 StaticWarningCode.INVALID_OVERRIDE_POSITIONAL, errorNameTarget, [ |
| 1347 overriddenPositionalPT.length + overriddenNormalPT.length, | 1831 basePositionalPT.length + baseNormalPT.length, |
| 1348 overriddenExecutable.enclosingElement.displayName | 1832 baseElement, |
| 1833 baseElement.enclosingElement.displayName |
| 1349 ]); | 1834 ]); |
| 1350 return true; | 1835 return true; |
| 1351 } | 1836 } |
| 1352 // For each named parameter in the overridden method, verify that there is | 1837 // For each named parameter in the overridden method, verify that there is |
| 1353 // the same name in the overriding method. | 1838 // the same name in the overriding method. |
| 1354 for (String overriddenParamName in overriddenNamedPT.keys) { | 1839 for (String overriddenParamName in baseNamedPT.keys) { |
| 1355 if (!overridingNamedPT.containsKey(overriddenParamName)) { | 1840 if (!derivedNamedPT.containsKey(overriddenParamName)) { |
| 1356 // The overridden method expected the overriding method to have | 1841 // The overridden method expected the overriding method to have |
| 1357 // overridingParamName, but it does not. | 1842 // overridingParamName, but it does not. |
| 1358 _errorReporter.reportErrorForNode( | 1843 _errorReporter.reportErrorForNode( |
| 1359 StaticWarningCode.INVALID_OVERRIDE_NAMED, errorNameTarget, [ | 1844 StaticWarningCode.INVALID_OVERRIDE_NAMED, errorNameTarget, [ |
| 1360 overriddenParamName, | 1845 overriddenParamName, |
| 1361 overriddenExecutable.enclosingElement.displayName | 1846 baseElement, |
| 1847 baseElement.enclosingElement.displayName |
| 1362 ]); | 1848 ]); |
| 1363 return true; | 1849 return true; |
| 1364 } | 1850 } |
| 1365 } | 1851 } |
| 1366 // SWC.INVALID_METHOD_OVERRIDE_RETURN_TYPE | 1852 // SWC.INVALID_METHOD_OVERRIDE_RETURN_TYPE |
| 1367 if (overriddenFTReturnType != VoidTypeImpl.instance && | 1853 if (baseFTReturnType != VoidTypeImpl.instance && |
| 1368 !_typeSystem.isAssignableTo( | 1854 !_typeSystem.isAssignableTo(derivedFTReturnType, baseFTReturnType)) { |
| 1369 overridingFTReturnType, overriddenFTReturnType)) { | |
| 1370 _errorReporter.reportTypeErrorForNode( | 1855 _errorReporter.reportTypeErrorForNode( |
| 1371 !isGetter | 1856 !isGetter |
| 1372 ? StaticWarningCode.INVALID_METHOD_OVERRIDE_RETURN_TYPE | 1857 ? StaticWarningCode.INVALID_METHOD_OVERRIDE_RETURN_TYPE |
| 1373 : StaticWarningCode.INVALID_GETTER_OVERRIDE_RETURN_TYPE, | 1858 : StaticWarningCode.INVALID_GETTER_OVERRIDE_RETURN_TYPE, |
| 1374 errorNameTarget, | 1859 errorNameTarget, |
| 1375 [ | 1860 [ |
| 1376 overridingFTReturnType, | 1861 derivedFTReturnType, |
| 1377 overriddenFTReturnType, | 1862 baseFTReturnType, |
| 1378 overriddenExecutable.enclosingElement.displayName | 1863 baseElement.enclosingElement.displayName |
| 1379 ]); | 1864 ]); |
| 1380 return true; | 1865 return true; |
| 1381 } | 1866 } |
| 1382 // SWC.INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE | 1867 // SWC.INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE |
| 1383 if (parameterLocations == null) { | 1868 if (parameterLocations == null) { |
| 1384 return false; | 1869 return false; |
| 1385 } | 1870 } |
| 1386 int parameterIndex = 0; | 1871 int parameterIndex = 0; |
| 1387 for (int i = 0; i < overridingNormalPT.length; i++) { | 1872 for (int i = 0; i < derivedNormalPT.length; i++) { |
| 1388 if (!_typeSystem.isAssignableTo( | 1873 if (!_typeSystem.isAssignableTo(baseNormalPT[i], derivedNormalPT[i])) { |
| 1389 overridingNormalPT[i], overriddenNormalPT[i])) { | |
| 1390 _errorReporter.reportTypeErrorForNode( | 1874 _errorReporter.reportTypeErrorForNode( |
| 1391 !isSetter | 1875 !isSetter |
| 1392 ? StaticWarningCode.INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE | 1876 ? StaticWarningCode.INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE |
| 1393 : StaticWarningCode.INVALID_SETTER_OVERRIDE_NORMAL_PARAM_TYPE, | 1877 : StaticWarningCode.INVALID_SETTER_OVERRIDE_NORMAL_PARAM_TYPE, |
| 1394 parameterLocations[parameterIndex], | 1878 parameterLocations[parameterIndex], |
| 1395 [ | 1879 [ |
| 1396 overridingNormalPT[i], | 1880 derivedNormalPT[i], |
| 1397 overriddenNormalPT[i], | 1881 baseNormalPT[i], |
| 1398 overriddenExecutable.enclosingElement.displayName | 1882 baseElement.enclosingElement.displayName |
| 1399 ]); | 1883 ]); |
| 1400 return true; | 1884 return true; |
| 1401 } | 1885 } |
| 1402 parameterIndex++; | 1886 parameterIndex++; |
| 1403 } | 1887 } |
| 1404 // SWC.INVALID_METHOD_OVERRIDE_OPTIONAL_PARAM_TYPE | 1888 // SWC.INVALID_METHOD_OVERRIDE_OPTIONAL_PARAM_TYPE |
| 1405 for (int i = 0; i < overriddenPositionalPT.length; i++) { | 1889 for (int i = 0; i < basePositionalPT.length; i++) { |
| 1406 if (!_typeSystem.isAssignableTo( | 1890 if (!_typeSystem.isAssignableTo( |
| 1407 overridingPositionalPT[i], overriddenPositionalPT[i])) { | 1891 basePositionalPT[i], derivedPositionalPT[i])) { |
| 1408 _errorReporter.reportTypeErrorForNode( | 1892 _errorReporter.reportTypeErrorForNode( |
| 1409 StaticWarningCode.INVALID_METHOD_OVERRIDE_OPTIONAL_PARAM_TYPE, | 1893 StaticWarningCode.INVALID_METHOD_OVERRIDE_OPTIONAL_PARAM_TYPE, |
| 1410 parameterLocations[parameterIndex], [ | 1894 parameterLocations[parameterIndex], [ |
| 1411 overridingPositionalPT[i], | 1895 derivedPositionalPT[i], |
| 1412 overriddenPositionalPT[i], | 1896 basePositionalPT[i], |
| 1413 overriddenExecutable.enclosingElement.displayName | 1897 baseElement.enclosingElement.displayName |
| 1414 ]); | 1898 ]); |
| 1415 return true; | 1899 return true; |
| 1416 } | 1900 } |
| 1417 parameterIndex++; | 1901 parameterIndex++; |
| 1418 } | 1902 } |
| 1419 // SWC.INVALID_METHOD_OVERRIDE_NAMED_PARAM_TYPE & | 1903 // SWC.INVALID_METHOD_OVERRIDE_NAMED_PARAM_TYPE & |
| 1420 // SWC.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES | 1904 // SWC.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES |
| 1421 for (String overriddenName in overriddenNamedPT.keys) { | 1905 for (String overriddenName in baseNamedPT.keys) { |
| 1422 DartType overridingType = overridingNamedPT[overriddenName]; | 1906 DartType derivedType = derivedNamedPT[overriddenName]; |
| 1423 if (overridingType == null) { | 1907 if (derivedType == null) { |
| 1424 // Error, this is never reached- INVALID_OVERRIDE_NAMED would have been | 1908 // Error, this is never reached- INVALID_OVERRIDE_NAMED would have been |
| 1425 // created above if this could be reached. | 1909 // created above if this could be reached. |
| 1426 continue; | 1910 continue; |
| 1427 } | 1911 } |
| 1428 DartType overriddenType = overriddenNamedPT[overriddenName]; | 1912 DartType baseType = baseNamedPT[overriddenName]; |
| 1429 if (!_typeSystem.isAssignableTo(overriddenType, overridingType)) { | 1913 if (!_typeSystem.isAssignableTo(baseType, derivedType)) { |
| 1430 // lookup the parameter for the error to select | 1914 // lookup the parameter for the error to select |
| 1431 ParameterElement parameterToSelect = null; | 1915 ParameterElement parameterToSelect = null; |
| 1432 AstNode parameterLocationToSelect = null; | 1916 AstNode parameterLocationToSelect = null; |
| 1433 for (int i = 0; i < parameters.length; i++) { | 1917 for (int i = 0; i < parameters.length; i++) { |
| 1434 ParameterElement parameter = parameters[i]; | 1918 ParameterElement parameter = parameters[i]; |
| 1435 if (parameter.parameterKind == ParameterKind.NAMED && | 1919 if (parameter.parameterKind == ParameterKind.NAMED && |
| 1436 overriddenName == parameter.name) { | 1920 overriddenName == parameter.name) { |
| 1437 parameterToSelect = parameter; | 1921 parameterToSelect = parameter; |
| 1438 parameterLocationToSelect = parameterLocations[i]; | 1922 parameterLocationToSelect = parameterLocations[i]; |
| 1439 break; | 1923 break; |
| 1440 } | 1924 } |
| 1441 } | 1925 } |
| 1442 if (parameterToSelect != null) { | 1926 if (parameterToSelect != null) { |
| 1443 _errorReporter.reportTypeErrorForNode( | 1927 _errorReporter.reportTypeErrorForNode( |
| 1444 StaticWarningCode.INVALID_METHOD_OVERRIDE_NAMED_PARAM_TYPE, | 1928 StaticWarningCode.INVALID_METHOD_OVERRIDE_NAMED_PARAM_TYPE, |
| 1445 parameterLocationToSelect, [ | 1929 parameterLocationToSelect, [ |
| 1446 overridingType, | 1930 derivedType, |
| 1447 overriddenType, | 1931 baseType, |
| 1448 overriddenExecutable.enclosingElement.displayName | 1932 baseElement.enclosingElement.displayName |
| 1449 ]); | 1933 ]); |
| 1450 return true; | 1934 return true; |
| 1451 } | 1935 } |
| 1452 } | 1936 } |
| 1453 } | 1937 } |
| 1454 // SWC.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES | 1938 // SWC.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES |
| 1455 // | 1939 // |
| 1456 // Create three lists: a list of the optional parameter ASTs | 1940 // Create three lists: a list of the optional parameter ASTs |
| 1457 // (FormalParameters), a list of the optional parameters elements from our | 1941 // (FormalParameters), a list of the optional parameters elements from our |
| 1458 // method, and finally a list of the optional parameter elements from the | 1942 // method, and finally a list of the optional parameter elements from the |
| 1459 // method we are overriding. | 1943 // method we are overriding. |
| 1460 // | 1944 // |
| 1461 bool foundError = false; | 1945 bool foundError = false; |
| 1462 List<AstNode> formalParameters = new List<AstNode>(); | 1946 List<AstNode> formalParameters = new List<AstNode>(); |
| 1463 List<ParameterElementImpl> parameterElts = new List<ParameterElementImpl>(); | 1947 List<ParameterElementImpl> parameterElts = new List<ParameterElementImpl>(); |
| 1464 List<ParameterElementImpl> overriddenParameterElts = | 1948 List<ParameterElementImpl> overriddenParameterElts = |
| 1465 new List<ParameterElementImpl>(); | 1949 new List<ParameterElementImpl>(); |
| 1466 List<ParameterElement> overriddenPEs = overriddenExecutable.parameters; | 1950 List<ParameterElement> overriddenPEs = baseElement.parameters; |
| 1467 for (int i = 0; i < parameters.length; i++) { | 1951 for (int i = 0; i < parameters.length; i++) { |
| 1468 ParameterElement parameter = parameters[i]; | 1952 ParameterElement parameter = parameters[i]; |
| 1469 if (parameter.parameterKind.isOptional) { | 1953 if (parameter.parameterKind.isOptional) { |
| 1470 formalParameters.add(parameterLocations[i]); | 1954 formalParameters.add(parameterLocations[i]); |
| 1471 parameterElts.add(parameter as ParameterElementImpl); | 1955 parameterElts.add(parameter as ParameterElementImpl); |
| 1472 } | 1956 } |
| 1473 } | 1957 } |
| 1474 for (ParameterElement parameterElt in overriddenPEs) { | 1958 for (ParameterElement parameterElt in overriddenPEs) { |
| 1475 if (parameterElt.parameterKind.isOptional) { | 1959 if (parameterElt.parameterKind.isOptional) { |
| 1476 if (parameterElt is ParameterElementImpl) { | 1960 if (parameterElt is ParameterElementImpl) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1505 String overriddenParameterName = overriddenParameterElt.name; | 1989 String overriddenParameterName = overriddenParameterElt.name; |
| 1506 if (parameterName != null && | 1990 if (parameterName != null && |
| 1507 parameterName == overriddenParameterName) { | 1991 parameterName == overriddenParameterName) { |
| 1508 EvaluationResultImpl overriddenResult = | 1992 EvaluationResultImpl overriddenResult = |
| 1509 overriddenParameterElt.evaluationResult; | 1993 overriddenParameterElt.evaluationResult; |
| 1510 if (_isUserDefinedObject(overriddenResult)) { | 1994 if (_isUserDefinedObject(overriddenResult)) { |
| 1511 break; | 1995 break; |
| 1512 } | 1996 } |
| 1513 if (!result.equalValues(_typeProvider, overriddenResult)) { | 1997 if (!result.equalValues(_typeProvider, overriddenResult)) { |
| 1514 _errorReporter.reportErrorForNode( | 1998 _errorReporter.reportErrorForNode( |
| 1515 StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_
NAMED, | 1999 StaticWarningCode |
| 1516 formalParameters[i], [ | 2000 .INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED, |
| 1517 overriddenExecutable.enclosingElement.displayName, | 2001 formalParameters[i], |
| 1518 overriddenExecutable.displayName, | 2002 [ |
| 1519 parameterName | 2003 baseElement.enclosingElement.displayName, |
| 1520 ]); | 2004 baseElement.displayName, |
| 2005 parameterName |
| 2006 ]); |
| 1521 foundError = true; | 2007 foundError = true; |
| 1522 } | 2008 } |
| 1523 } | 2009 } |
| 1524 } | 2010 } |
| 1525 } | 2011 } |
| 1526 } else { | 2012 } else { |
| 1527 // Positional parameters, consider the positions when matching the | 2013 // Positional parameters, consider the positions when matching the |
| 1528 // parameterElts to the overriddenParameterElts | 2014 // parameterElts to the overriddenParameterElts |
| 1529 for (int i = 0; | 2015 for (int i = 0; |
| 1530 i < parameterElts.length && i < overriddenParameterElts.length; | 2016 i < parameterElts.length && i < overriddenParameterElts.length; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1542 // default. | 2028 // default. |
| 1543 continue; | 2029 continue; |
| 1544 } | 2030 } |
| 1545 EvaluationResultImpl overriddenResult = | 2031 EvaluationResultImpl overriddenResult = |
| 1546 overriddenParameterElt.evaluationResult; | 2032 overriddenParameterElt.evaluationResult; |
| 1547 if (_isUserDefinedObject(overriddenResult)) { | 2033 if (_isUserDefinedObject(overriddenResult)) { |
| 1548 continue; | 2034 continue; |
| 1549 } | 2035 } |
| 1550 if (!result.equalValues(_typeProvider, overriddenResult)) { | 2036 if (!result.equalValues(_typeProvider, overriddenResult)) { |
| 1551 _errorReporter.reportErrorForNode( | 2037 _errorReporter.reportErrorForNode( |
| 1552 StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSI
TIONAL, | 2038 StaticWarningCode |
| 1553 formalParameters[i], [ | 2039 .INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL, |
| 1554 overriddenExecutable.enclosingElement.displayName, | 2040 formalParameters[i], |
| 1555 overriddenExecutable.displayName | 2041 [ |
| 1556 ]); | 2042 baseElement.enclosingElement.displayName, |
| 2043 baseElement.displayName |
| 2044 ]); |
| 1557 foundError = true; | 2045 foundError = true; |
| 1558 } | 2046 } |
| 1559 } | 2047 } |
| 1560 } | 2048 } |
| 1561 } | 2049 } |
| 1562 return foundError; | 2050 return foundError; |
| 1563 } | 2051 } |
| 1564 | 2052 |
| 1565 /** | 2053 /** |
| 1566 * Check the given [executableElement] against override-error codes. This | 2054 * Check the given [executableElement] against override-error codes. This |
| 1567 * method computes the given executableElement is overriding and calls | 2055 * method computes the given executableElement is overriding and calls |
| 1568 * [_checkForAllInvalidOverrideErrorCodes] when the [InheritanceManager] | 2056 * [_checkForAllInvalidOverrideErrorCodes] when the [InheritanceManager] |
| 1569 * returns a [MultiplyInheritedExecutableElement], this method loops through | 2057 * returns a [MultiplyInheritedExecutableElement], this method loops through |
| 1570 * the list in the [MultiplyInheritedExecutableElement]. The [parameters] are | 2058 * the list in the [MultiplyInheritedExecutableElement]. The [parameters] are |
| 1571 * the parameters of the executable element. The [errorNameTarget] is the node | 2059 * the parameters of the executable element. The [errorNameTarget] is the node |
| 1572 * to report problems on. | 2060 * to report problems on. |
| 1573 */ | 2061 */ |
| 1574 bool _checkForAllInvalidOverrideErrorCodesForExecutable( | 2062 void _checkForAllInvalidOverrideErrorCodesForExecutable( |
| 1575 ExecutableElement executableElement, | 2063 ExecutableElement executableElement, |
| 1576 List<ParameterElement> parameters, | 2064 List<ParameterElement> parameters, |
| 1577 List<AstNode> parameterLocations, | 2065 List<AstNode> parameterLocations, |
| 1578 SimpleIdentifier errorNameTarget) { | 2066 SimpleIdentifier errorNameTarget) { |
| 2067 assert(!_options.strongMode); // strong mode already checked for these |
| 1579 // | 2068 // |
| 1580 // Compute the overridden executable from the InheritanceManager | 2069 // Compute the overridden executable from the InheritanceManager |
| 1581 // | 2070 // |
| 1582 List<ExecutableElement> overriddenExecutables = _inheritanceManager | 2071 List<ExecutableElement> overriddenExecutables = _inheritanceManager |
| 1583 .lookupOverrides(_enclosingClass, executableElement.name); | 2072 .lookupOverrides(_enclosingClass, executableElement.name); |
| 1584 if (_checkForInstanceMethodNameCollidesWithSuperclassStatic( | 2073 if (_checkForInstanceMethodNameCollidesWithSuperclassStatic( |
| 1585 executableElement, errorNameTarget)) { | 2074 executableElement, errorNameTarget)) { |
| 1586 return true; | 2075 return; |
| 1587 } | 2076 } |
| 1588 for (ExecutableElement overriddenElement in overriddenExecutables) { | 2077 for (ExecutableElement overriddenElement in overriddenExecutables) { |
| 1589 if (_checkForAllInvalidOverrideErrorCodes(executableElement, | 2078 if (_checkForAllInvalidOverrideErrorCodes(executableElement, |
| 1590 overriddenElement, parameters, parameterLocations, errorNameTarget)) { | 2079 overriddenElement, parameters, parameterLocations, errorNameTarget)) { |
| 1591 return true; | 2080 return; |
| 1592 } | 2081 } |
| 1593 } | 2082 } |
| 1594 return false; | |
| 1595 } | 2083 } |
| 1596 | 2084 |
| 1597 /** | 2085 /** |
| 1598 * Check the given field [declaration] against override-error codes. | 2086 * Check the given field [declaration] against override-error codes. |
| 1599 * | 2087 * |
| 1600 * See [_checkForAllInvalidOverrideErrorCodes]. | 2088 * See [_checkForAllInvalidOverrideErrorCodes]. |
| 1601 */ | 2089 */ |
| 1602 bool _checkForAllInvalidOverrideErrorCodesForField( | 2090 void _checkForAllInvalidOverrideErrorCodesForField( |
| 1603 FieldDeclaration declaration) { | 2091 FieldDeclaration declaration) { |
| 2092 if (_options.strongMode) { |
| 2093 return; // strong mode already checked for this |
| 2094 } |
| 2095 |
| 1604 if (_enclosingClass == null || declaration.isStatic) { | 2096 if (_enclosingClass == null || declaration.isStatic) { |
| 1605 return false; | 2097 return; |
| 1606 } | 2098 } |
| 1607 bool hasProblems = false; | 2099 |
| 1608 VariableDeclarationList fields = declaration.fields; | 2100 VariableDeclarationList fields = declaration.fields; |
| 1609 for (VariableDeclaration field in fields.variables) { | 2101 for (VariableDeclaration field in fields.variables) { |
| 1610 FieldElement element = field.element as FieldElement; | 2102 FieldElement element = field.element as FieldElement; |
| 1611 if (element == null) { | 2103 if (element == null) { |
| 1612 continue; | 2104 continue; |
| 1613 } | 2105 } |
| 1614 PropertyAccessorElement getter = element.getter; | 2106 PropertyAccessorElement getter = element.getter; |
| 1615 PropertyAccessorElement setter = element.setter; | 2107 PropertyAccessorElement setter = element.setter; |
| 1616 SimpleIdentifier fieldName = field.name; | 2108 SimpleIdentifier fieldName = field.name; |
| 1617 if (getter != null) { | 2109 if (getter != null) { |
| 1618 if (_checkForAllInvalidOverrideErrorCodesForExecutable(getter, | 2110 _checkForAllInvalidOverrideErrorCodesForExecutable( |
| 1619 ParameterElement.EMPTY_LIST, AstNode.EMPTY_LIST, fieldName)) { | 2111 getter, ParameterElement.EMPTY_LIST, AstNode.EMPTY_LIST, fieldName); |
| 1620 hasProblems = true; | |
| 1621 } | |
| 1622 } | 2112 } |
| 1623 if (setter != null) { | 2113 if (setter != null) { |
| 1624 if (_checkForAllInvalidOverrideErrorCodesForExecutable( | 2114 _checkForAllInvalidOverrideErrorCodesForExecutable( |
| 1625 setter, setter.parameters, <AstNode>[fieldName], fieldName)) { | 2115 setter, setter.parameters, <AstNode>[fieldName], fieldName); |
| 1626 hasProblems = true; | |
| 1627 } | |
| 1628 } | 2116 } |
| 1629 } | 2117 } |
| 1630 return hasProblems; | |
| 1631 } | 2118 } |
| 1632 | 2119 |
| 1633 /** | 2120 /** |
| 1634 * Check the given [method] declaration against override-error codes. | 2121 * Check the given [method] declaration against override-error codes. |
| 1635 * | 2122 * |
| 1636 * See [_checkForAllInvalidOverrideErrorCodes]. | 2123 * See [_checkForAllInvalidOverrideErrorCodes]. |
| 1637 */ | 2124 */ |
| 1638 bool _checkForAllInvalidOverrideErrorCodesForMethod( | 2125 void _checkForAllInvalidOverrideErrorCodesForMethod( |
| 1639 MethodDeclaration method) { | 2126 MethodDeclaration method) { |
| 2127 if (_options.strongMode) { |
| 2128 return; // strong mode already checked for this |
| 2129 } |
| 1640 if (_enclosingClass == null || | 2130 if (_enclosingClass == null || |
| 1641 method.isStatic || | 2131 method.isStatic || |
| 1642 method.body is NativeFunctionBody) { | 2132 method.body is NativeFunctionBody) { |
| 1643 return false; | 2133 return; |
| 1644 } | 2134 } |
| 1645 ExecutableElement executableElement = method.element; | 2135 ExecutableElement executableElement = method.element; |
| 1646 if (executableElement == null) { | 2136 if (executableElement == null) { |
| 1647 return false; | 2137 return; |
| 1648 } | 2138 } |
| 1649 SimpleIdentifier methodName = method.name; | 2139 SimpleIdentifier methodName = method.name; |
| 1650 if (methodName.isSynthetic) { | 2140 if (methodName.isSynthetic) { |
| 1651 return false; | 2141 return; |
| 1652 } | 2142 } |
| 1653 FormalParameterList formalParameterList = method.parameters; | 2143 FormalParameterList formalParameterList = method.parameters; |
| 1654 NodeList<FormalParameter> parameterList = | 2144 NodeList<FormalParameter> parameterList = formalParameterList?.parameters; |
| 1655 formalParameterList != null ? formalParameterList.parameters : null; | |
| 1656 List<AstNode> parameters = | 2145 List<AstNode> parameters = |
| 1657 parameterList != null ? new List.from(parameterList) : null; | 2146 parameterList != null ? new List.from(parameterList) : null; |
| 1658 return _checkForAllInvalidOverrideErrorCodesForExecutable(executableElement, | 2147 _checkForAllInvalidOverrideErrorCodesForExecutable(executableElement, |
| 1659 executableElement.parameters, parameters, methodName); | 2148 executableElement.parameters, parameters, methodName); |
| 1660 } | 2149 } |
| 1661 | 2150 |
| 1662 /** | 2151 /** |
| 1663 * Verify that all classes of the given [withClause] are valid. | 2152 * Verify that all classes of the given [withClause] are valid. |
| 1664 * | 2153 * |
| 1665 * See [CompileTimeErrorCode.MIXIN_DECLARES_CONSTRUCTOR], | 2154 * See [CompileTimeErrorCode.MIXIN_DECLARES_CONSTRUCTOR], |
| 1666 * [CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT], and | 2155 * [CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT], and |
| 1667 * [CompileTimeErrorCode.MIXIN_REFERENCES_SUPER]. | 2156 * [CompileTimeErrorCode.MIXIN_REFERENCES_SUPER]. |
| 1668 */ | 2157 */ |
| 1669 bool _checkForAllMixinErrorCodes(WithClause withClause) { | 2158 bool _checkForAllMixinErrorCodes(WithClause withClause) { |
| 1670 if (withClause == null) { | 2159 if (withClause == null) { |
| 1671 return false; | 2160 return false; |
| 1672 } | 2161 } |
| 1673 bool problemReported = false; | 2162 bool problemReported = false; |
| 1674 for (TypeName mixinName in withClause.mixinTypes) { | 2163 for (TypeName mixinName in withClause.mixinTypes) { |
| 1675 DartType mixinType = mixinName.type; | 2164 DartType mixinType = mixinName.type; |
| 1676 if (mixinType is! InterfaceType) { | 2165 if (mixinType is InterfaceType) { |
| 1677 continue; | 2166 if (_checkForExtendsOrImplementsDisallowedClass( |
| 1678 } | 2167 mixinName, CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS)) { |
| 1679 if (_checkForExtendsOrImplementsDisallowedClass( | |
| 1680 mixinName, CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS)) { | |
| 1681 problemReported = true; | |
| 1682 } else { | |
| 1683 ClassElement mixinElement = (mixinType as InterfaceType).element; | |
| 1684 if (_checkForExtendsOrImplementsDeferredClass( | |
| 1685 mixinName, CompileTimeErrorCode.MIXIN_DEFERRED_CLASS)) { | |
| 1686 problemReported = true; | 2168 problemReported = true; |
| 1687 } | 2169 } else { |
| 1688 if (_checkForMixinDeclaresConstructor(mixinName, mixinElement)) { | 2170 ClassElement mixinElement = mixinType.element; |
| 1689 problemReported = true; | 2171 if (_checkForExtendsOrImplementsDeferredClass( |
| 1690 } | 2172 mixinName, CompileTimeErrorCode.MIXIN_DEFERRED_CLASS)) { |
| 1691 if (!enableSuperMixins && | 2173 problemReported = true; |
| 1692 _checkForMixinInheritsNotFromObject(mixinName, mixinElement)) { | 2174 } |
| 1693 problemReported = true; | 2175 if (_checkForMixinDeclaresConstructor(mixinName, mixinElement)) { |
| 1694 } | 2176 problemReported = true; |
| 1695 if (_checkForMixinReferencesSuper(mixinName, mixinElement)) { | 2177 } |
| 1696 problemReported = true; | 2178 if (!enableSuperMixins && |
| 2179 _checkForMixinInheritsNotFromObject(mixinName, mixinElement)) { |
| 2180 problemReported = true; |
| 2181 } |
| 2182 if (_checkForMixinReferencesSuper(mixinName, mixinElement)) { |
| 2183 problemReported = true; |
| 2184 } |
| 1697 } | 2185 } |
| 1698 } | 2186 } |
| 1699 } | 2187 } |
| 1700 return problemReported; | 2188 return problemReported; |
| 1701 } | 2189 } |
| 1702 | 2190 |
| 1703 /** | 2191 /** |
| 1704 * Check for errors related to the redirected constructors. | 2192 * Check for errors related to the redirected constructors. |
| 1705 * | 2193 * |
| 1706 * See [StaticWarningCode.REDIRECT_TO_INVALID_RETURN_TYPE], | 2194 * See [StaticWarningCode.REDIRECT_TO_INVALID_RETURN_TYPE], |
| 1707 * [StaticWarningCode.REDIRECT_TO_INVALID_FUNCTION_TYPE], and | 2195 * [StaticWarningCode.REDIRECT_TO_INVALID_FUNCTION_TYPE], and |
| 1708 * [StaticWarningCode.REDIRECT_TO_MISSING_CONSTRUCTOR]. | 2196 * [StaticWarningCode.REDIRECT_TO_MISSING_CONSTRUCTOR]. |
| 1709 */ | 2197 */ |
| 1710 bool _checkForAllRedirectConstructorErrorCodes( | 2198 void _checkForAllRedirectConstructorErrorCodes( |
| 1711 ConstructorDeclaration declaration) { | 2199 ConstructorDeclaration declaration) { |
| 1712 // | |
| 1713 // Prepare redirected constructor node | 2200 // Prepare redirected constructor node |
| 1714 // | |
| 1715 ConstructorName redirectedConstructor = declaration.redirectedConstructor; | 2201 ConstructorName redirectedConstructor = declaration.redirectedConstructor; |
| 1716 if (redirectedConstructor == null) { | 2202 if (redirectedConstructor == null) { |
| 1717 return false; | 2203 return; |
| 1718 } | 2204 } |
| 1719 // | 2205 |
| 1720 // Prepare redirected constructor type | 2206 // Prepare redirected constructor type |
| 1721 // | |
| 1722 ConstructorElement redirectedElement = redirectedConstructor.staticElement; | 2207 ConstructorElement redirectedElement = redirectedConstructor.staticElement; |
| 1723 if (redirectedElement == null) { | 2208 if (redirectedElement == null) { |
| 1724 // | |
| 1725 // If the element is null, we check for the | 2209 // If the element is null, we check for the |
| 1726 // REDIRECT_TO_MISSING_CONSTRUCTOR case | 2210 // REDIRECT_TO_MISSING_CONSTRUCTOR case |
| 1727 // | |
| 1728 TypeName constructorTypeName = redirectedConstructor.type; | 2211 TypeName constructorTypeName = redirectedConstructor.type; |
| 1729 DartType redirectedType = constructorTypeName.type; | 2212 DartType redirectedType = constructorTypeName.type; |
| 1730 if (redirectedType != null && | 2213 if (redirectedType != null && |
| 1731 redirectedType.element != null && | 2214 redirectedType.element != null && |
| 1732 !redirectedType.isDynamic) { | 2215 !redirectedType.isDynamic) { |
| 1733 // | |
| 1734 // Prepare the constructor name | 2216 // Prepare the constructor name |
| 1735 // | |
| 1736 String constructorStrName = constructorTypeName.name.name; | 2217 String constructorStrName = constructorTypeName.name.name; |
| 1737 if (redirectedConstructor.name != null) { | 2218 if (redirectedConstructor.name != null) { |
| 1738 constructorStrName += ".${redirectedConstructor.name.name}"; | 2219 constructorStrName += ".${redirectedConstructor.name.name}"; |
| 1739 } | 2220 } |
| 1740 ErrorCode errorCode = (declaration.constKeyword != null | 2221 ErrorCode errorCode = (declaration.constKeyword != null |
| 1741 ? CompileTimeErrorCode.REDIRECT_TO_MISSING_CONSTRUCTOR | 2222 ? CompileTimeErrorCode.REDIRECT_TO_MISSING_CONSTRUCTOR |
| 1742 : StaticWarningCode.REDIRECT_TO_MISSING_CONSTRUCTOR); | 2223 : StaticWarningCode.REDIRECT_TO_MISSING_CONSTRUCTOR); |
| 1743 _errorReporter.reportErrorForNode(errorCode, redirectedConstructor, | 2224 _errorReporter.reportErrorForNode(errorCode, redirectedConstructor, |
| 1744 [constructorStrName, redirectedType.displayName]); | 2225 [constructorStrName, redirectedType.displayName]); |
| 1745 return true; | |
| 1746 } | 2226 } |
| 1747 return false; | 2227 return; |
| 1748 } | 2228 } |
| 1749 FunctionType redirectedType = redirectedElement.type; | 2229 FunctionType redirectedType = redirectedElement.type; |
| 1750 DartType redirectedReturnType = redirectedType.returnType; | 2230 DartType redirectedReturnType = redirectedType.returnType; |
| 1751 // | 2231 |
| 1752 // Report specific problem when return type is incompatible | 2232 // Report specific problem when return type is incompatible |
| 1753 // | |
| 1754 FunctionType constructorType = declaration.element.type; | 2233 FunctionType constructorType = declaration.element.type; |
| 1755 DartType constructorReturnType = constructorType.returnType; | 2234 DartType constructorReturnType = constructorType.returnType; |
| 1756 if (!_typeSystem.isAssignableTo( | 2235 if (!_typeSystem.isAssignableTo( |
| 1757 redirectedReturnType, constructorReturnType)) { | 2236 redirectedReturnType, constructorReturnType)) { |
| 1758 _errorReporter.reportErrorForNode( | 2237 _errorReporter.reportErrorForNode( |
| 1759 StaticWarningCode.REDIRECT_TO_INVALID_RETURN_TYPE, | 2238 StaticWarningCode.REDIRECT_TO_INVALID_RETURN_TYPE, |
| 1760 redirectedConstructor, | 2239 redirectedConstructor, |
| 1761 [redirectedReturnType, constructorReturnType]); | 2240 [redirectedReturnType, constructorReturnType]); |
| 1762 return true; | 2241 return; |
| 1763 } | 2242 } else if (!_typeSystem.isSubtypeOf(redirectedType, constructorType)) { |
| 1764 // | 2243 // Check parameters. |
| 1765 // Check parameters | |
| 1766 // | |
| 1767 if (!_typeSystem.isSubtypeOf(redirectedType, constructorType)) { | |
| 1768 _errorReporter.reportErrorForNode( | 2244 _errorReporter.reportErrorForNode( |
| 1769 StaticWarningCode.REDIRECT_TO_INVALID_FUNCTION_TYPE, | 2245 StaticWarningCode.REDIRECT_TO_INVALID_FUNCTION_TYPE, |
| 1770 redirectedConstructor, | 2246 redirectedConstructor, |
| 1771 [redirectedType, constructorType]); | 2247 [redirectedType, constructorType]); |
| 1772 return true; | |
| 1773 } | 2248 } |
| 1774 return false; | |
| 1775 } | 2249 } |
| 1776 | 2250 |
| 1777 /** | 2251 /** |
| 1778 * Check that the return [statement] of the form <i>return e;</i> is not in a | 2252 * Check that the return [statement] of the form <i>return e;</i> is not in a |
| 1779 * generative constructor. | 2253 * generative constructor. |
| 1780 * | 2254 * |
| 1781 * Check that return statements without expressions are not in a generative | 2255 * Check that return statements without expressions are not in a generative |
| 1782 * constructor and the return type is not assignable to `null`; that is, we | 2256 * constructor and the return type is not assignable to `null`; that is, we |
| 1783 * don't have `return;` if the enclosing method has a return type. | 2257 * don't have `return;` if the enclosing method has a return type. |
| 1784 * | 2258 * |
| 1785 * Check that the return type matches the type of the declared return type in | 2259 * Check that the return type matches the type of the declared return type in |
| 1786 * the enclosing method or function. | 2260 * the enclosing method or function. |
| 1787 * | 2261 * |
| 1788 * See [CompileTimeErrorCode.RETURN_IN_GENERATIVE_CONSTRUCTOR], | 2262 * See [CompileTimeErrorCode.RETURN_IN_GENERATIVE_CONSTRUCTOR], |
| 1789 * [StaticWarningCode.RETURN_WITHOUT_VALUE], and | 2263 * [StaticWarningCode.RETURN_WITHOUT_VALUE], and |
| 1790 * [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]. | 2264 * [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]. |
| 1791 */ | 2265 */ |
| 1792 bool _checkForAllReturnStatementErrorCodes(ReturnStatement statement) { | 2266 void _checkForAllReturnStatementErrorCodes(ReturnStatement statement) { |
| 1793 FunctionType functionType = | 2267 FunctionType functionType = _enclosingFunction?.type; |
| 1794 _enclosingFunction == null ? null : _enclosingFunction.type; | |
| 1795 DartType expectedReturnType = functionType == null | 2268 DartType expectedReturnType = functionType == null |
| 1796 ? DynamicTypeImpl.instance | 2269 ? DynamicTypeImpl.instance |
| 1797 : functionType.returnType; | 2270 : functionType.returnType; |
| 1798 Expression returnExpression = statement.expression; | 2271 Expression returnExpression = statement.expression; |
| 1799 // RETURN_IN_GENERATIVE_CONSTRUCTOR | 2272 // RETURN_IN_GENERATIVE_CONSTRUCTOR |
| 1800 bool isGenerativeConstructor = _enclosingFunction is ConstructorElement && | 2273 bool isGenerativeConstructor(ExecutableElement element) => |
| 1801 !(_enclosingFunction as ConstructorElement).isFactory; | 2274 element is ConstructorElement && !element.isFactory; |
| 1802 if (isGenerativeConstructor) { | 2275 if (isGenerativeConstructor(_enclosingFunction)) { |
| 1803 if (returnExpression == null) { | 2276 if (returnExpression == null) { |
| 1804 return false; | 2277 return; |
| 1805 } | 2278 } |
| 1806 _errorReporter.reportErrorForNode( | 2279 _errorReporter.reportErrorForNode( |
| 1807 CompileTimeErrorCode.RETURN_IN_GENERATIVE_CONSTRUCTOR, | 2280 CompileTimeErrorCode.RETURN_IN_GENERATIVE_CONSTRUCTOR, |
| 1808 returnExpression); | 2281 returnExpression); |
| 1809 return true; | 2282 return; |
| 1810 } | 2283 } |
| 1811 // RETURN_WITHOUT_VALUE | 2284 // RETURN_WITHOUT_VALUE |
| 1812 if (returnExpression == null) { | 2285 if (returnExpression == null) { |
| 1813 if (_inGenerator || | 2286 if (_inGenerator || |
| 1814 _typeSystem.isAssignableTo( | 2287 _typeSystem.isAssignableTo( |
| 1815 _computeReturnTypeForMethod(null), expectedReturnType)) { | 2288 _computeReturnTypeForMethod(null), expectedReturnType)) { |
| 1816 return false; | 2289 return; |
| 1817 } | 2290 } |
| 1818 _hasReturnWithoutValue = true; | 2291 _hasReturnWithoutValue = true; |
| 1819 _errorReporter.reportErrorForNode( | 2292 _errorReporter.reportErrorForNode( |
| 1820 StaticWarningCode.RETURN_WITHOUT_VALUE, statement); | 2293 StaticWarningCode.RETURN_WITHOUT_VALUE, statement); |
| 1821 return true; | 2294 return; |
| 1822 } else if (_inGenerator) { | 2295 } else if (_inGenerator) { |
| 1823 // RETURN_IN_GENERATOR | 2296 // RETURN_IN_GENERATOR |
| 1824 _errorReporter.reportErrorForNode( | 2297 _errorReporter.reportErrorForNode( |
| 1825 CompileTimeErrorCode.RETURN_IN_GENERATOR, statement); | 2298 CompileTimeErrorCode.RETURN_IN_GENERATOR, |
| 2299 statement, |
| 2300 [_inAsync ? "async*" : "sync*"]); |
| 1826 } | 2301 } |
| 1827 // RETURN_OF_INVALID_TYPE | 2302 |
| 1828 return _checkForReturnOfInvalidType(returnExpression, expectedReturnType); | 2303 _checkForReturnOfInvalidType(returnExpression, expectedReturnType); |
| 1829 } | 2304 } |
| 1830 | 2305 |
| 1831 /** | 2306 /** |
| 1832 * Verify that the export namespace of the given export [directive] does not | 2307 * Verify that the export namespace of the given export [directive] does not |
| 1833 * export any name already exported by another export directive. The | 2308 * export any name already exported by another export directive. The |
| 1834 * [exportElement] is the [ExportElement] retrieved from the node. If the | 2309 * [exportElement] is the [ExportElement] retrieved from the node. If the |
| 1835 * element in the node was `null`, then this method is not called. The | 2310 * element in the node was `null`, then this method is not called. The |
| 1836 * [exportedLibrary] is the library element containing the exported element. | 2311 * [exportedLibrary] is the library element containing the exported element. |
| 1837 * | 2312 * |
| 1838 * See [CompileTimeErrorCode.AMBIGUOUS_EXPORT]. | 2313 * See [CompileTimeErrorCode.AMBIGUOUS_EXPORT]. |
| 1839 */ | 2314 */ |
| 1840 bool _checkForAmbiguousExport(ExportDirective directive, | 2315 void _checkForAmbiguousExport(ExportDirective directive, |
| 1841 ExportElement exportElement, LibraryElement exportedLibrary) { | 2316 ExportElement exportElement, LibraryElement exportedLibrary) { |
| 1842 if (exportedLibrary == null) { | 2317 if (exportedLibrary == null) { |
| 1843 return false; | 2318 return; |
| 1844 } | 2319 } |
| 1845 // check exported names | 2320 // check exported names |
| 1846 Namespace namespace = | 2321 Namespace namespace = |
| 1847 new NamespaceBuilder().createExportNamespaceForDirective(exportElement); | 2322 new NamespaceBuilder().createExportNamespaceForDirective(exportElement); |
| 1848 Map<String, Element> definedNames = namespace.definedNames; | 2323 Map<String, Element> definedNames = namespace.definedNames; |
| 1849 for (String name in definedNames.keys) { | 2324 for (String name in definedNames.keys) { |
| 1850 Element element = definedNames[name]; | 2325 Element element = definedNames[name]; |
| 1851 Element prevElement = _exportedElements[name]; | 2326 Element prevElement = _exportedElements[name]; |
| 1852 if (element != null && prevElement != null && prevElement != element) { | 2327 if (element != null && prevElement != null && prevElement != element) { |
| 1853 _errorReporter.reportErrorForNode( | 2328 _errorReporter.reportErrorForNode( |
| 1854 CompileTimeErrorCode.AMBIGUOUS_EXPORT, directive, [ | 2329 CompileTimeErrorCode.AMBIGUOUS_EXPORT, directive, [ |
| 1855 name, | 2330 name, |
| 1856 prevElement.library.definingCompilationUnit.displayName, | 2331 prevElement.library.definingCompilationUnit.displayName, |
| 1857 element.library.definingCompilationUnit.displayName | 2332 element.library.definingCompilationUnit.displayName |
| 1858 ]); | 2333 ]); |
| 1859 return true; | 2334 return; |
| 1860 } else { | 2335 } else { |
| 1861 _exportedElements[name] = element; | 2336 _exportedElements[name] = element; |
| 1862 } | 2337 } |
| 1863 } | 2338 } |
| 1864 return false; | |
| 1865 } | 2339 } |
| 1866 | 2340 |
| 1867 /** | 2341 /** |
| 2342 * Check the given node to see whether it was ambiguous because the name was |
| 2343 * imported from two or more imports. |
| 2344 */ |
| 2345 void _checkForAmbiguousImport(SimpleIdentifier node) { |
| 2346 Element element = node.staticElement; |
| 2347 if (element is MultiplyDefinedElementImpl) { |
| 2348 String name = element.displayName; |
| 2349 List<Element> conflictingMembers = element.conflictingElements; |
| 2350 int count = conflictingMembers.length; |
| 2351 List<String> libraryNames = new List<String>(count); |
| 2352 for (int i = 0; i < count; i++) { |
| 2353 libraryNames[i] = _getLibraryName(conflictingMembers[i]); |
| 2354 } |
| 2355 libraryNames.sort(); |
| 2356 _errorReporter.reportErrorForNode(StaticWarningCode.AMBIGUOUS_IMPORT, |
| 2357 node, [name, StringUtilities.printListOfQuotedNames(libraryNames)]); |
| 2358 } else { |
| 2359 List<Element> sdkElements = |
| 2360 node.getProperty(LibraryImportScope.conflictingSdkElements); |
| 2361 if (sdkElements != null) { |
| 2362 _errorReporter.reportErrorForNode( |
| 2363 StaticWarningCode.CONFLICTING_DART_IMPORT, node, [ |
| 2364 element.displayName, |
| 2365 _getLibraryName(sdkElements[0]), |
| 2366 _getLibraryName(element) |
| 2367 ]); |
| 2368 } |
| 2369 } |
| 2370 } |
| 2371 |
| 2372 /** |
| 1868 * Verify that the given [expression] can be assigned to its corresponding | 2373 * Verify that the given [expression] can be assigned to its corresponding |
| 1869 * parameters. The [expectedStaticType] is the expected static type of the | 2374 * parameters. The [expectedStaticType] is the expected static type of the |
| 1870 * parameter. The [actualStaticType] is the actual static type of the | 2375 * parameter. The [actualStaticType] is the actual static type of the |
| 1871 * argument. | 2376 * argument. |
| 1872 * | 2377 * |
| 1873 * This method corresponds to | 2378 * This method corresponds to |
| 1874 * [BestPracticesVerifier.checkForArgumentTypeNotAssignable]. | 2379 * [BestPracticesVerifier.checkForArgumentTypeNotAssignable]. |
| 1875 * | 2380 * |
| 1876 * See [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE], | 2381 * See [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE], |
| 1877 * [CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE], | 2382 * [CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE], |
| 1878 * [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE], | 2383 * [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE], |
| 1879 * [CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE], | 2384 * [CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE], |
| 1880 * [CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE], | 2385 * [CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE], |
| 1881 * [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE], and | 2386 * [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE], and |
| 1882 * [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]. | 2387 * [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]. |
| 1883 */ | 2388 */ |
| 1884 bool _checkForArgumentTypeNotAssignable( | 2389 void _checkForArgumentTypeNotAssignable( |
| 1885 Expression expression, | 2390 Expression expression, |
| 1886 DartType expectedStaticType, | 2391 DartType expectedStaticType, |
| 1887 DartType actualStaticType, | 2392 DartType actualStaticType, |
| 1888 ErrorCode errorCode) { | 2393 ErrorCode errorCode) { |
| 1889 // | |
| 1890 // Warning case: test static type information | 2394 // Warning case: test static type information |
| 1891 // | |
| 1892 if (actualStaticType != null && expectedStaticType != null) { | 2395 if (actualStaticType != null && expectedStaticType != null) { |
| 1893 if (!_typeSystem.isAssignableTo(actualStaticType, expectedStaticType)) { | 2396 _checkForAssignableExpressionAtType( |
| 1894 _errorReporter.reportTypeErrorForNode( | 2397 expression, actualStaticType, expectedStaticType, errorCode); |
| 1895 errorCode, expression, [actualStaticType, expectedStaticType]); | |
| 1896 return true; | |
| 1897 } | |
| 1898 } | 2398 } |
| 1899 return false; | |
| 1900 } | 2399 } |
| 1901 | 2400 |
| 1902 /** | 2401 /** |
| 1903 * Verify that the given [argument] can be assigned to its corresponding | 2402 * Verify that the given [argument] can be assigned to its corresponding |
| 1904 * parameter. | 2403 * parameter. |
| 1905 * | 2404 * |
| 1906 * This method corresponds to | 2405 * This method corresponds to |
| 1907 * [BestPracticesVerifier.checkForArgumentTypeNotAssignableForArgument]. | 2406 * [BestPracticesVerifier.checkForArgumentTypeNotAssignableForArgument]. |
| 1908 * | 2407 * |
| 1909 * See [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]. | 2408 * See [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]. |
| 1910 */ | 2409 */ |
| 1911 bool _checkForArgumentTypeNotAssignableForArgument(Expression argument) { | 2410 void _checkForArgumentTypeNotAssignableForArgument(Expression argument) { |
| 1912 if (argument == null) { | 2411 if (argument == null) { |
| 1913 return false; | 2412 return; |
| 1914 } | 2413 } |
| 1915 ParameterElement staticParameterElement = argument.staticParameterElement; | 2414 ParameterElement staticParameterElement = argument.staticParameterElement; |
| 1916 DartType staticParameterType = | 2415 DartType staticParameterType = staticParameterElement?.type; |
| 1917 staticParameterElement == null ? null : staticParameterElement.type; | 2416 _checkForArgumentTypeNotAssignableWithExpectedTypes(argument, |
| 1918 return _checkForArgumentTypeNotAssignableWithExpectedTypes(argument, | |
| 1919 staticParameterType, StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE); | 2417 staticParameterType, StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE); |
| 1920 } | 2418 } |
| 1921 | 2419 |
| 1922 /** | 2420 /** |
| 1923 * Verify that the given [expression] can be assigned to its corresponding | 2421 * Verify that the given [expression] can be assigned to its corresponding |
| 1924 * parameters. The [expectedStaticType] is the expected static type. | 2422 * parameters. The [expectedStaticType] is the expected static type. |
| 1925 * | 2423 * |
| 1926 * This method corresponds to | 2424 * This method corresponds to |
| 1927 * [BestPracticesVerifier.checkForArgumentTypeNotAssignableWithExpectedTypes]. | 2425 * [BestPracticesVerifier.checkForArgumentTypeNotAssignableWithExpectedTypes]. |
| 1928 * | 2426 * |
| 1929 * See [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE], | 2427 * See [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE], |
| 1930 * [CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE], | 2428 * [CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE], |
| 1931 * [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE], | 2429 * [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE], |
| 1932 * [CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE], | 2430 * [CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE], |
| 1933 * [CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE], | 2431 * [CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE], |
| 1934 * [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE], and | 2432 * [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE], and |
| 1935 * [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]. | 2433 * [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]. |
| 1936 */ | 2434 */ |
| 1937 bool _checkForArgumentTypeNotAssignableWithExpectedTypes( | 2435 void _checkForArgumentTypeNotAssignableWithExpectedTypes( |
| 1938 Expression expression, | 2436 Expression expression, DartType expectedStaticType, ErrorCode errorCode) { |
| 1939 DartType expectedStaticType, | 2437 _checkForArgumentTypeNotAssignable( |
| 1940 ErrorCode errorCode) => | 2438 expression, expectedStaticType, getStaticType(expression), errorCode); |
| 1941 _checkForArgumentTypeNotAssignable( | 2439 } |
| 1942 expression, expectedStaticType, getStaticType(expression), errorCode); | |
| 1943 | 2440 |
| 1944 /** | 2441 /** |
| 1945 * Verify that the arguments in the given [argumentList] can be assigned to | 2442 * Verify that the arguments in the given [argumentList] can be assigned to |
| 1946 * their corresponding parameters. | 2443 * their corresponding parameters. |
| 1947 * | 2444 * |
| 1948 * This method corresponds to | 2445 * This method corresponds to |
| 1949 * [BestPracticesVerifier.checkForArgumentTypesNotAssignableInList]. | 2446 * [BestPracticesVerifier.checkForArgumentTypesNotAssignableInList]. |
| 1950 * | 2447 * |
| 1951 * See [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]. | 2448 * See [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]. |
| 1952 */ | 2449 */ |
| 1953 bool _checkForArgumentTypesNotAssignableInList(ArgumentList argumentList) { | 2450 void _checkForArgumentTypesNotAssignableInList(ArgumentList argumentList) { |
| 1954 if (argumentList == null) { | 2451 if (argumentList == null) { |
| 1955 return false; | 2452 return; |
| 1956 } | 2453 } |
| 1957 bool problemReported = false; | 2454 |
| 1958 for (Expression argument in argumentList.arguments) { | 2455 for (Expression argument in argumentList.arguments) { |
| 1959 if (_checkForArgumentTypeNotAssignableForArgument(argument)) { | 2456 _checkForArgumentTypeNotAssignableForArgument(argument); |
| 1960 problemReported = true; | |
| 1961 } | |
| 1962 } | 2457 } |
| 1963 return problemReported; | |
| 1964 } | 2458 } |
| 1965 | 2459 |
| 1966 /** | 2460 /** |
| 1967 * Check that the static type of the given expression is assignable to the | 2461 * Check that the static type of the given expression is assignable to the |
| 1968 * given type. If it isn't, report an error with the given error code. The | 2462 * given type. If it isn't, report an error with the given error code. The |
| 1969 * [type] is the type that the expression must be assignable to. The | 2463 * [type] is the type that the expression must be assignable to. The |
| 1970 * [errorCode] is the error code to be reported. The [arguments] are the | 2464 * [errorCode] is the error code to be reported. The [arguments] are the |
| 1971 * arguments to pass in when creating the error. | 2465 * arguments to pass in when creating the error. |
| 1972 */ | 2466 */ |
| 1973 bool _checkForAssignability(Expression expression, InterfaceType type, | 2467 void _checkForAssignability(Expression expression, InterfaceType type, |
| 1974 ErrorCode errorCode, List<Object> arguments) { | 2468 ErrorCode errorCode, List<Object> arguments) { |
| 1975 if (expression == null) { | 2469 if (expression == null) { |
| 1976 return false; | 2470 return; |
| 1977 } | 2471 } |
| 1978 DartType expressionType = expression.staticType; | 2472 DartType expressionType = expression.staticType; |
| 1979 if (expressionType == null) { | 2473 if (expressionType == null) { |
| 2474 return; |
| 2475 } |
| 2476 if (_expressionIsAssignableAtType(expression, expressionType, type)) { |
| 2477 return; |
| 2478 } |
| 2479 _errorReporter.reportErrorForNode(errorCode, expression, arguments); |
| 2480 } |
| 2481 |
| 2482 bool _checkForAssignableExpression( |
| 2483 Expression expression, DartType expectedStaticType, ErrorCode errorCode) { |
| 2484 DartType actualStaticType = getStaticType(expression); |
| 2485 return actualStaticType != null && |
| 2486 _checkForAssignableExpressionAtType( |
| 2487 expression, actualStaticType, expectedStaticType, errorCode); |
| 2488 } |
| 2489 |
| 2490 bool _checkForAssignableExpressionAtType( |
| 2491 Expression expression, |
| 2492 DartType actualStaticType, |
| 2493 DartType expectedStaticType, |
| 2494 ErrorCode errorCode) { |
| 2495 // TODO(leafp): Move the Downcast functionality here. |
| 2496 if (!_expressionIsAssignableAtType( |
| 2497 expression, actualStaticType, expectedStaticType)) { |
| 2498 _errorReporter.reportTypeErrorForNode( |
| 2499 errorCode, expression, [actualStaticType, expectedStaticType]); |
| 1980 return false; | 2500 return false; |
| 1981 } | 2501 } |
| 1982 if (_typeSystem.isAssignableTo(expressionType, type)) { | |
| 1983 return false; | |
| 1984 } | |
| 1985 _errorReporter.reportErrorForNode(errorCode, expression, arguments); | |
| 1986 return true; | 2502 return true; |
| 1987 } | 2503 } |
| 1988 | 2504 |
| 1989 /** | 2505 /** |
| 1990 * Verify that the given [expression] is not final. | 2506 * Verify that the given [expression] is not final. |
| 1991 * | 2507 * |
| 1992 * See [StaticWarningCode.ASSIGNMENT_TO_CONST], | 2508 * See [StaticWarningCode.ASSIGNMENT_TO_CONST], |
| 1993 * [StaticWarningCode.ASSIGNMENT_TO_FINAL], and | 2509 * [StaticWarningCode.ASSIGNMENT_TO_FINAL], and |
| 1994 * [StaticWarningCode.ASSIGNMENT_TO_METHOD]. | 2510 * [StaticWarningCode.ASSIGNMENT_TO_METHOD]. |
| 1995 */ | 2511 */ |
| 1996 bool _checkForAssignmentToFinal(Expression expression) { | 2512 void _checkForAssignmentToFinal(Expression expression) { |
| 1997 // prepare element | 2513 // prepare element |
| 1998 Element element = null; | 2514 Element element = null; |
| 1999 AstNode highlightedNode = expression; | 2515 AstNode highlightedNode = expression; |
| 2000 if (expression is Identifier) { | 2516 if (expression is Identifier) { |
| 2001 element = expression.staticElement; | 2517 element = expression.staticElement; |
| 2002 if (expression is PrefixedIdentifier) { | 2518 if (expression is PrefixedIdentifier) { |
| 2003 highlightedNode = expression.identifier; | 2519 highlightedNode = expression.identifier; |
| 2004 } | 2520 } |
| 2005 } else if (expression is PropertyAccess) { | 2521 } else if (expression is PropertyAccess) { |
| 2006 PropertyAccess propertyAccess = expression; | 2522 element = expression.propertyName.staticElement; |
| 2007 element = propertyAccess.propertyName.staticElement; | 2523 highlightedNode = expression.propertyName; |
| 2008 highlightedNode = propertyAccess.propertyName; | |
| 2009 } | 2524 } |
| 2010 // check if element is assignable | 2525 // check if element is assignable |
| 2011 if (element is PropertyAccessorElement) { | 2526 Element toVariable(Element element) { |
| 2012 PropertyAccessorElement accessor = element as PropertyAccessorElement; | 2527 return element is PropertyAccessorElement ? element.variable : element; |
| 2013 element = accessor.variable; | |
| 2014 } | 2528 } |
| 2529 |
| 2530 element = toVariable(element); |
| 2015 if (element is VariableElement) { | 2531 if (element is VariableElement) { |
| 2016 if (element.isConst) { | 2532 if (element.isConst) { |
| 2017 _errorReporter.reportErrorForNode( | 2533 _errorReporter.reportErrorForNode( |
| 2018 StaticWarningCode.ASSIGNMENT_TO_CONST, expression); | 2534 StaticWarningCode.ASSIGNMENT_TO_CONST, expression); |
| 2019 return true; | 2535 } else if (element.isFinal) { |
| 2020 } | |
| 2021 if (element.isFinal) { | |
| 2022 if (element is FieldElementImpl && | 2536 if (element is FieldElementImpl && |
| 2023 element.setter == null && | 2537 element.setter == null && |
| 2024 element.isSynthetic) { | 2538 element.isSynthetic) { |
| 2025 _errorReporter.reportErrorForNode( | 2539 _errorReporter.reportErrorForNode( |
| 2026 StaticWarningCode.ASSIGNMENT_TO_FINAL_NO_SETTER, | 2540 StaticWarningCode.ASSIGNMENT_TO_FINAL_NO_SETTER, |
| 2027 highlightedNode, | 2541 highlightedNode, |
| 2028 [element.name, element.enclosingElement.displayName]); | 2542 [element.name, element.enclosingElement.displayName]); |
| 2029 return true; | 2543 return; |
| 2030 } | 2544 } |
| 2031 _errorReporter.reportErrorForNode(StaticWarningCode.ASSIGNMENT_TO_FINAL, | 2545 _errorReporter.reportErrorForNode(StaticWarningCode.ASSIGNMENT_TO_FINAL, |
| 2032 highlightedNode, [element.name]); | 2546 highlightedNode, [element.name]); |
| 2033 return true; | |
| 2034 } | 2547 } |
| 2035 return false; | 2548 } else if (element is FunctionElement) { |
| 2036 } | |
| 2037 if (element is FunctionElement) { | |
| 2038 _errorReporter.reportErrorForNode( | 2549 _errorReporter.reportErrorForNode( |
| 2039 StaticWarningCode.ASSIGNMENT_TO_FUNCTION, expression); | 2550 StaticWarningCode.ASSIGNMENT_TO_FUNCTION, expression); |
| 2040 return true; | 2551 } else if (element is MethodElement) { |
| 2041 } | |
| 2042 if (element is MethodElement) { | |
| 2043 _errorReporter.reportErrorForNode( | 2552 _errorReporter.reportErrorForNode( |
| 2044 StaticWarningCode.ASSIGNMENT_TO_METHOD, expression); | 2553 StaticWarningCode.ASSIGNMENT_TO_METHOD, expression); |
| 2045 return true; | 2554 } else if (element is ClassElement || |
| 2046 } | |
| 2047 if (element is ClassElement || | |
| 2048 element is FunctionTypeAliasElement || | 2555 element is FunctionTypeAliasElement || |
| 2049 element is TypeParameterElement) { | 2556 element is TypeParameterElement) { |
| 2050 _errorReporter.reportErrorForNode( | 2557 _errorReporter.reportErrorForNode( |
| 2051 StaticWarningCode.ASSIGNMENT_TO_TYPE, expression); | 2558 StaticWarningCode.ASSIGNMENT_TO_TYPE, expression); |
| 2052 return true; | |
| 2053 } | 2559 } |
| 2054 return false; | |
| 2055 } | 2560 } |
| 2056 | 2561 |
| 2057 /** | 2562 /** |
| 2058 * Verify that the given [identifier] is not a keyword, and generates the | 2563 * Verify that the given [identifier] is not a keyword, and generates the |
| 2059 * given [errorCode] on the identifier if it is a keyword. | 2564 * given [errorCode] on the identifier if it is a keyword. |
| 2060 * | 2565 * |
| 2061 * See [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_NAME], | 2566 * See [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_NAME], |
| 2062 * [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_PARAMETER_NAME], and | 2567 * [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_PARAMETER_NAME], and |
| 2063 * [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME]. | 2568 * [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME]. |
| 2064 */ | 2569 */ |
| 2065 bool _checkForBuiltInIdentifierAsName( | 2570 void _checkForBuiltInIdentifierAsName( |
| 2066 SimpleIdentifier identifier, ErrorCode errorCode) { | 2571 SimpleIdentifier identifier, ErrorCode errorCode) { |
| 2067 sc.Token token = identifier.token; | 2572 Token token = identifier.token; |
| 2068 if (token.type == sc.TokenType.KEYWORD) { | 2573 if (token.type == TokenType.KEYWORD) { |
| 2069 _errorReporter.reportErrorForNode( | 2574 _errorReporter |
| 2070 errorCode, identifier, [identifier.name]); | 2575 .reportErrorForNode(errorCode, identifier, [identifier.name]); |
| 2071 return true; | |
| 2072 } | 2576 } |
| 2073 return false; | |
| 2074 } | 2577 } |
| 2075 | 2578 |
| 2076 /** | 2579 /** |
| 2077 * Verify that the given [switchCase] is terminated with 'break', 'continue', | 2580 * Verify that the given [switchCase] is terminated with 'break', 'continue', |
| 2078 * 'return' or 'throw'. | 2581 * 'return' or 'throw'. |
| 2079 * | 2582 * |
| 2080 * see [StaticWarningCode.CASE_BLOCK_NOT_TERMINATED]. | 2583 * see [StaticWarningCode.CASE_BLOCK_NOT_TERMINATED]. |
| 2081 */ | 2584 */ |
| 2082 bool _checkForCaseBlockNotTerminated(SwitchCase switchCase) { | 2585 void _checkForCaseBlockNotTerminated(SwitchCase switchCase) { |
| 2083 NodeList<Statement> statements = switchCase.statements; | 2586 NodeList<Statement> statements = switchCase.statements; |
| 2084 if (statements.isEmpty) { | 2587 if (statements.isEmpty) { |
| 2085 // fall-through without statements at all | 2588 // fall-through without statements at all |
| 2086 AstNode parent = switchCase.parent; | 2589 AstNode parent = switchCase.parent; |
| 2087 if (parent is SwitchStatement) { | 2590 if (parent is SwitchStatement) { |
| 2088 SwitchStatement switchStatement = parent; | 2591 NodeList<SwitchMember> members = parent.members; |
| 2089 NodeList<SwitchMember> members = switchStatement.members; | |
| 2090 int index = members.indexOf(switchCase); | 2592 int index = members.indexOf(switchCase); |
| 2091 if (index != -1 && index < members.length - 1) { | 2593 if (index != -1 && index < members.length - 1) { |
| 2092 return false; | 2594 return; |
| 2093 } | 2595 } |
| 2094 } | 2596 } |
| 2095 // no other switch member after this one | 2597 // no other switch member after this one |
| 2096 } else { | 2598 } else { |
| 2097 Statement statement = statements[statements.length - 1]; | 2599 Statement statement = statements[statements.length - 1]; |
| 2098 // terminated with statement | 2600 // terminated with statement |
| 2099 if (statement is BreakStatement || | 2601 if (statement is BreakStatement || |
| 2100 statement is ContinueStatement || | 2602 statement is ContinueStatement || |
| 2101 statement is ReturnStatement) { | 2603 statement is ReturnStatement) { |
| 2102 return false; | 2604 return; |
| 2103 } | 2605 } |
| 2104 // terminated with 'throw' expression | 2606 // terminated with 'throw' expression |
| 2105 if (statement is ExpressionStatement) { | 2607 if (statement is ExpressionStatement) { |
| 2106 Expression expression = statement.expression; | 2608 Expression expression = statement.expression; |
| 2107 if (expression is ThrowExpression) { | 2609 if (expression is ThrowExpression) { |
| 2108 return false; | 2610 return; |
| 2109 } | 2611 } |
| 2110 } | 2612 } |
| 2111 } | 2613 } |
| 2112 // report error | 2614 |
| 2113 _errorReporter.reportErrorForToken( | 2615 _errorReporter.reportErrorForToken( |
| 2114 StaticWarningCode.CASE_BLOCK_NOT_TERMINATED, switchCase.keyword); | 2616 StaticWarningCode.CASE_BLOCK_NOT_TERMINATED, switchCase.keyword); |
| 2115 return true; | |
| 2116 } | 2617 } |
| 2117 | 2618 |
| 2118 /** | 2619 /** |
| 2119 * Verify that the switch cases in the given switch [statement] are terminated | 2620 * Verify that the switch cases in the given switch [statement] are terminated |
| 2120 * with 'break', 'continue', 'return' or 'throw'. | 2621 * with 'break', 'continue', 'return' or 'throw'. |
| 2121 * | 2622 * |
| 2122 * See [StaticWarningCode.CASE_BLOCK_NOT_TERMINATED]. | 2623 * See [StaticWarningCode.CASE_BLOCK_NOT_TERMINATED]. |
| 2123 */ | 2624 */ |
| 2124 bool _checkForCaseBlocksNotTerminated(SwitchStatement statement) { | 2625 void _checkForCaseBlocksNotTerminated(SwitchStatement statement) { |
| 2125 bool foundError = false; | |
| 2126 NodeList<SwitchMember> members = statement.members; | 2626 NodeList<SwitchMember> members = statement.members; |
| 2127 int lastMember = members.length - 1; | 2627 int lastMember = members.length - 1; |
| 2128 for (int i = 0; i < lastMember; i++) { | 2628 for (int i = 0; i < lastMember; i++) { |
| 2129 SwitchMember member = members[i]; | 2629 SwitchMember member = members[i]; |
| 2130 if (member is SwitchCase && _checkForCaseBlockNotTerminated(member)) { | 2630 if (member is SwitchCase) { |
| 2131 foundError = true; | 2631 _checkForCaseBlockNotTerminated(member); |
| 2132 } | 2632 } |
| 2133 } | 2633 } |
| 2134 return foundError; | |
| 2135 } | 2634 } |
| 2136 | 2635 |
| 2137 /** | 2636 /** |
| 2138 * Verify that the given [method] declaration is abstract only if the | 2637 * Verify that the given [method] declaration is abstract only if the |
| 2139 * enclosing class is also abstract. | 2638 * enclosing class is also abstract. |
| 2140 * | 2639 * |
| 2141 * See [StaticWarningCode.CONCRETE_CLASS_WITH_ABSTRACT_MEMBER]. | 2640 * See [StaticWarningCode.CONCRETE_CLASS_WITH_ABSTRACT_MEMBER]. |
| 2142 */ | 2641 */ |
| 2143 bool _checkForConcreteClassWithAbstractMember(MethodDeclaration method) { | 2642 void _checkForConcreteClassWithAbstractMember(MethodDeclaration method) { |
| 2144 if (method.isAbstract && | 2643 if (method.isAbstract && |
| 2145 _enclosingClass != null && | 2644 _enclosingClass != null && |
| 2146 !_enclosingClass.isAbstract) { | 2645 !_enclosingClass.isAbstract) { |
| 2147 SimpleIdentifier nameNode = method.name; | 2646 SimpleIdentifier nameNode = method.name; |
| 2148 String memberName = nameNode.name; | 2647 String memberName = nameNode.name; |
| 2149 ExecutableElement overriddenMember; | 2648 ExecutableElement overriddenMember; |
| 2150 if (method.isGetter) { | 2649 if (method.isGetter) { |
| 2151 overriddenMember = _enclosingClass.lookUpInheritedConcreteGetter( | 2650 overriddenMember = _enclosingClass.lookUpInheritedConcreteGetter( |
| 2152 memberName, _currentLibrary); | 2651 memberName, _currentLibrary); |
| 2153 } else if (method.isSetter) { | 2652 } else if (method.isSetter) { |
| 2154 overriddenMember = _enclosingClass.lookUpInheritedConcreteSetter( | 2653 overriddenMember = _enclosingClass.lookUpInheritedConcreteSetter( |
| 2155 memberName, _currentLibrary); | 2654 memberName, _currentLibrary); |
| 2156 } else { | 2655 } else { |
| 2157 overriddenMember = _enclosingClass.lookUpInheritedConcreteMethod( | 2656 overriddenMember = _enclosingClass.lookUpInheritedConcreteMethod( |
| 2158 memberName, _currentLibrary); | 2657 memberName, _currentLibrary); |
| 2159 } | 2658 } |
| 2160 if (overriddenMember == null) { | 2659 if (overriddenMember == null && !_enclosingClass.hasNoSuchMethod) { |
| 2161 _errorReporter.reportErrorForNode( | 2660 _errorReporter.reportErrorForNode( |
| 2162 StaticWarningCode.CONCRETE_CLASS_WITH_ABSTRACT_MEMBER, | 2661 StaticWarningCode.CONCRETE_CLASS_WITH_ABSTRACT_MEMBER, |
| 2163 nameNode, | 2662 nameNode, |
| 2164 [memberName, _enclosingClass.displayName]); | 2663 [memberName, _enclosingClass.displayName]); |
| 2165 return true; | |
| 2166 } | 2664 } |
| 2167 } | 2665 } |
| 2168 return false; | |
| 2169 } | 2666 } |
| 2170 | 2667 |
| 2171 /** | 2668 /** |
| 2172 * Verify all possible conflicts of the given [constructor]'s name with other | 2669 * Verify all possible conflicts of the given [constructor]'s name with other |
| 2173 * constructors and members of the same class. The [constructorElement] is the | 2670 * constructors and members of the same class. The [constructorElement] is the |
| 2174 * constructor's element. | 2671 * constructor's element. |
| 2175 * | 2672 * |
| 2176 * See [CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_DEFAULT], | 2673 * See [CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_DEFAULT], |
| 2177 * [CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_NAME], | 2674 * [CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_NAME], |
| 2178 * [CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_NAME_AND_FIELD], and | 2675 * [CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_NAME_AND_FIELD], and |
| 2179 * [CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_NAME_AND_METHOD]. | 2676 * [CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_NAME_AND_METHOD]. |
| 2180 */ | 2677 */ |
| 2181 bool _checkForConflictingConstructorNameAndMember( | 2678 void _checkForConflictingConstructorNameAndMember( |
| 2182 ConstructorDeclaration constructor, | 2679 ConstructorDeclaration constructor, |
| 2183 ConstructorElement constructorElement) { | 2680 ConstructorElement constructorElement) { |
| 2184 SimpleIdentifier constructorName = constructor.name; | 2681 SimpleIdentifier constructorName = constructor.name; |
| 2185 String name = constructorElement.name; | 2682 String name = constructorElement.name; |
| 2186 ClassElement classElement = constructorElement.enclosingElement; | 2683 ClassElement classElement = constructorElement.enclosingElement; |
| 2187 // constructors | 2684 // constructors |
| 2188 List<ConstructorElement> constructors = classElement.constructors; | 2685 List<ConstructorElement> constructors = classElement.constructors; |
| 2189 for (ConstructorElement otherConstructor in constructors) { | 2686 for (ConstructorElement otherConstructor in constructors) { |
| 2190 if (identical(otherConstructor, constructorElement)) { | 2687 if (identical(otherConstructor, constructorElement)) { |
| 2191 continue; | 2688 continue; |
| 2192 } | 2689 } |
| 2193 if (name == otherConstructor.name) { | 2690 if (name == otherConstructor.name) { |
| 2194 if (name == null || name.length == 0) { | 2691 if (name == null || name.length == 0) { |
| 2195 _errorReporter.reportErrorForNode( | 2692 _errorReporter.reportErrorForNode( |
| 2196 CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_DEFAULT, constructor); | 2693 CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_DEFAULT, constructor); |
| 2197 } else { | 2694 } else { |
| 2198 _errorReporter.reportErrorForNode( | 2695 _errorReporter.reportErrorForNode( |
| 2199 CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_NAME, | 2696 CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_NAME, |
| 2200 constructor, | 2697 constructor, |
| 2201 [name]); | 2698 [name]); |
| 2202 } | 2699 } |
| 2203 return true; | 2700 return; |
| 2204 } | 2701 } |
| 2205 } | 2702 } |
| 2206 // conflict with class member | 2703 // conflict with class member |
| 2207 if (constructorName != null && | 2704 if (constructorName != null && |
| 2208 constructorElement != null && | 2705 constructorElement != null && |
| 2209 !constructorName.isSynthetic) { | 2706 !constructorName.isSynthetic) { |
| 2210 // fields | 2707 if (classElement.getField(name) != null) { |
| 2211 FieldElement field = classElement.getField(name); | 2708 // fields |
| 2212 if (field != null) { | |
| 2213 _errorReporter.reportErrorForNode( | 2709 _errorReporter.reportErrorForNode( |
| 2214 CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_NAME_AND_FIELD, | 2710 CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_NAME_AND_FIELD, |
| 2215 constructor, | 2711 constructor, |
| 2216 [name]); | 2712 [name]); |
| 2217 return true; | 2713 } else if (classElement.getMethod(name) != null) { |
| 2218 } | 2714 // methods |
| 2219 // methods | |
| 2220 MethodElement method = classElement.getMethod(name); | |
| 2221 if (method != null) { | |
| 2222 _errorReporter.reportErrorForNode( | 2715 _errorReporter.reportErrorForNode( |
| 2223 CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_NAME_AND_METHOD, | 2716 CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_NAME_AND_METHOD, |
| 2224 constructor, | 2717 constructor, |
| 2225 [name]); | 2718 [name]); |
| 2226 return true; | |
| 2227 } | 2719 } |
| 2228 } | 2720 } |
| 2229 return false; | |
| 2230 } | 2721 } |
| 2231 | 2722 |
| 2232 /** | 2723 /** |
| 2233 * Verify that the [_enclosingClass] does not have a method and getter pair | 2724 * Verify that the [_enclosingClass] does not have a method and getter pair |
| 2234 * with the same name on, via inheritance. | 2725 * with the same name on, via inheritance. |
| 2235 * | 2726 * |
| 2236 * See [CompileTimeErrorCode.CONFLICTING_GETTER_AND_METHOD], and | 2727 * See [CompileTimeErrorCode.CONFLICTING_GETTER_AND_METHOD], and |
| 2237 * [CompileTimeErrorCode.CONFLICTING_METHOD_AND_GETTER]. | 2728 * [CompileTimeErrorCode.CONFLICTING_METHOD_AND_GETTER]. |
| 2238 */ | 2729 */ |
| 2239 bool _checkForConflictingGetterAndMethod() { | 2730 void _checkForConflictingGetterAndMethod() { |
| 2240 if (_enclosingClass == null) { | 2731 if (_enclosingClass == null) { |
| 2241 return false; | 2732 return; |
| 2242 } | 2733 } |
| 2243 bool hasProblem = false; | 2734 |
| 2244 // method declared in the enclosing class vs. inherited getter | 2735 // method declared in the enclosing class vs. inherited getter |
| 2245 for (MethodElement method in _enclosingClass.methods) { | 2736 for (MethodElement method in _enclosingClass.methods) { |
| 2246 String name = method.name; | 2737 String name = method.name; |
| 2247 // find inherited property accessor (and can be only getter) | 2738 // find inherited property accessor (and can be only getter) |
| 2248 ExecutableElement inherited = | 2739 ExecutableElement inherited = |
| 2249 _inheritanceManager.lookupInheritance(_enclosingClass, name); | 2740 _inheritanceManager.lookupInheritance(_enclosingClass, name); |
| 2250 if (inherited is! PropertyAccessorElement) { | 2741 if (inherited is! PropertyAccessorElement) { |
| 2251 continue; | 2742 continue; |
| 2252 } | 2743 } |
| 2253 // report problem | 2744 |
| 2254 hasProblem = true; | |
| 2255 _errorReporter.reportErrorForElement( | 2745 _errorReporter.reportErrorForElement( |
| 2256 CompileTimeErrorCode.CONFLICTING_GETTER_AND_METHOD, method, [ | 2746 CompileTimeErrorCode.CONFLICTING_GETTER_AND_METHOD, method, [ |
| 2257 _enclosingClass.displayName, | 2747 _enclosingClass.displayName, |
| 2258 inherited.enclosingElement.displayName, | 2748 inherited.enclosingElement.displayName, |
| 2259 name | 2749 name |
| 2260 ]); | 2750 ]); |
| 2261 } | 2751 } |
| 2262 // getter declared in the enclosing class vs. inherited method | 2752 // getter declared in the enclosing class vs. inherited method |
| 2263 for (PropertyAccessorElement accessor in _enclosingClass.accessors) { | 2753 for (PropertyAccessorElement accessor in _enclosingClass.accessors) { |
| 2264 if (!accessor.isGetter) { | 2754 if (!accessor.isGetter) { |
| 2265 continue; | 2755 continue; |
| 2266 } | 2756 } |
| 2267 String name = accessor.name; | 2757 String name = accessor.name; |
| 2268 // find inherited method | 2758 // find inherited method |
| 2269 ExecutableElement inherited = | 2759 ExecutableElement inherited = |
| 2270 _inheritanceManager.lookupInheritance(_enclosingClass, name); | 2760 _inheritanceManager.lookupInheritance(_enclosingClass, name); |
| 2271 if (inherited is! MethodElement) { | 2761 if (inherited is! MethodElement) { |
| 2272 continue; | 2762 continue; |
| 2273 } | 2763 } |
| 2274 // report problem | 2764 |
| 2275 hasProblem = true; | |
| 2276 _errorReporter.reportErrorForElement( | 2765 _errorReporter.reportErrorForElement( |
| 2277 CompileTimeErrorCode.CONFLICTING_METHOD_AND_GETTER, accessor, [ | 2766 CompileTimeErrorCode.CONFLICTING_METHOD_AND_GETTER, accessor, [ |
| 2278 _enclosingClass.displayName, | 2767 _enclosingClass.displayName, |
| 2279 inherited.enclosingElement.displayName, | 2768 inherited.enclosingElement.displayName, |
| 2280 name | 2769 name |
| 2281 ]); | 2770 ]); |
| 2282 } | 2771 } |
| 2283 // done | |
| 2284 return hasProblem; | |
| 2285 } | 2772 } |
| 2286 | 2773 |
| 2287 /** | 2774 /** |
| 2288 * Verify that the superclass of the [_enclosingClass] does not declare | 2775 * Verify that the superclass of the [_enclosingClass] does not declare |
| 2289 * accessible static members with the same name as the instance | 2776 * accessible static members with the same name as the instance |
| 2290 * getters/setters declared in [_enclosingClass]. | 2777 * getters/setters declared in [_enclosingClass]. |
| 2291 * | 2778 * |
| 2292 * See [StaticWarningCode.CONFLICTING_INSTANCE_GETTER_AND_SUPERCLASS_MEMBER],
and | 2779 * See [StaticWarningCode.CONFLICTING_INSTANCE_GETTER_AND_SUPERCLASS_MEMBER],
and |
| 2293 * [StaticWarningCode.CONFLICTING_INSTANCE_SETTER_AND_SUPERCLASS_MEMBER]. | 2780 * [StaticWarningCode.CONFLICTING_INSTANCE_SETTER_AND_SUPERCLASS_MEMBER]. |
| 2294 */ | 2781 */ |
| 2295 bool _checkForConflictingInstanceGetterAndSuperclassMember() { | 2782 void _checkForConflictingInstanceGetterAndSuperclassMember() { |
| 2296 if (_enclosingClass == null) { | 2783 if (_enclosingClass == null) { |
| 2297 return false; | 2784 return; |
| 2298 } | 2785 } |
| 2299 InterfaceType enclosingType = _enclosingClass.type; | 2786 InterfaceType enclosingType = _enclosingClass.type; |
| 2300 // check every accessor | 2787 // check every accessor |
| 2301 bool hasProblem = false; | |
| 2302 for (PropertyAccessorElement accessor in _enclosingClass.accessors) { | 2788 for (PropertyAccessorElement accessor in _enclosingClass.accessors) { |
| 2303 // we analyze instance accessors here | 2789 // we analyze instance accessors here |
| 2304 if (accessor.isStatic) { | 2790 if (accessor.isStatic) { |
| 2305 continue; | 2791 continue; |
| 2306 } | 2792 } |
| 2307 // prepare accessor properties | 2793 // prepare accessor properties |
| 2308 String name = accessor.displayName; | 2794 String name = accessor.displayName; |
| 2309 bool getter = accessor.isGetter; | 2795 bool getter = accessor.isGetter; |
| 2310 // if non-final variable, ignore setter - we alreay reported problem for | 2796 // if non-final variable, ignore setter - we alreay reported problem for |
| 2311 // getter | 2797 // getter |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2328 continue; | 2814 continue; |
| 2329 } | 2815 } |
| 2330 // OK, not static | 2816 // OK, not static |
| 2331 if (!superElement.isStatic) { | 2817 if (!superElement.isStatic) { |
| 2332 continue; | 2818 continue; |
| 2333 } | 2819 } |
| 2334 // prepare "super" type to report its name | 2820 // prepare "super" type to report its name |
| 2335 ClassElement superElementClass = | 2821 ClassElement superElementClass = |
| 2336 superElement.enclosingElement as ClassElement; | 2822 superElement.enclosingElement as ClassElement; |
| 2337 InterfaceType superElementType = superElementClass.type; | 2823 InterfaceType superElementType = superElementClass.type; |
| 2338 // report problem | 2824 |
| 2339 hasProblem = true; | |
| 2340 if (getter) { | 2825 if (getter) { |
| 2341 _errorReporter.reportErrorForElement( | 2826 _errorReporter.reportErrorForElement( |
| 2342 StaticWarningCode.CONFLICTING_INSTANCE_GETTER_AND_SUPERCLASS_MEMBER, | 2827 StaticWarningCode.CONFLICTING_INSTANCE_GETTER_AND_SUPERCLASS_MEMBER, |
| 2343 accessor, | 2828 accessor, |
| 2344 [superElementType.displayName]); | 2829 [superElementType.displayName]); |
| 2345 } else { | 2830 } else { |
| 2346 _errorReporter.reportErrorForElement( | 2831 _errorReporter.reportErrorForElement( |
| 2347 StaticWarningCode.CONFLICTING_INSTANCE_SETTER_AND_SUPERCLASS_MEMBER, | 2832 StaticWarningCode.CONFLICTING_INSTANCE_SETTER_AND_SUPERCLASS_MEMBER, |
| 2348 accessor, | 2833 accessor, |
| 2349 [superElementType.displayName]); | 2834 [superElementType.displayName]); |
| 2350 } | 2835 } |
| 2351 } | 2836 } |
| 2352 // done | |
| 2353 return hasProblem; | |
| 2354 } | 2837 } |
| 2355 | 2838 |
| 2356 /** | 2839 /** |
| 2357 * Verify that the enclosing class does not have a setter with the same name | 2840 * Verify that the enclosing class does not have a setter with the same name |
| 2358 * as the given instance method declaration. | 2841 * as the given instance method declaration. |
| 2359 * | 2842 * |
| 2360 * TODO(jwren) add other "conflicting" error codes into algorithm/ data | 2843 * TODO(jwren) add other "conflicting" error codes into algorithm/ data |
| 2361 * structure. | 2844 * structure. |
| 2362 * | 2845 * |
| 2363 * See [StaticWarningCode.CONFLICTING_INSTANCE_METHOD_SETTER]. | 2846 * See [StaticWarningCode.CONFLICTING_INSTANCE_METHOD_SETTER]. |
| 2364 */ | 2847 */ |
| 2365 bool _checkForConflictingInstanceMethodSetter(ClassDeclaration declaration) { | 2848 void _checkForConflictingInstanceMethodSetter(ClassDeclaration declaration) { |
| 2366 // Reference all of the class members in this class. | 2849 // Reference all of the class members in this class. |
| 2367 NodeList<ClassMember> classMembers = declaration.members; | 2850 NodeList<ClassMember> classMembers = declaration.members; |
| 2368 if (classMembers.isEmpty) { | 2851 if (classMembers.isEmpty) { |
| 2369 return false; | 2852 return; |
| 2370 } | 2853 } |
| 2371 // Create a HashMap to track conflicting members, and then loop through | 2854 // Create a HashMap to track conflicting members, and then loop through |
| 2372 // members in the class to construct the HashMap, at the same time, | 2855 // members in the class to construct the HashMap, at the same time, |
| 2373 // look for violations. Don't add members if they are part of a conflict, | 2856 // look for violations. Don't add members if they are part of a conflict, |
| 2374 // this prevents multiple warnings for one issue. | 2857 // this prevents multiple warnings for one issue. |
| 2375 bool foundError = false; | |
| 2376 HashMap<String, ClassMember> memberHashMap = | 2858 HashMap<String, ClassMember> memberHashMap = |
| 2377 new HashMap<String, ClassMember>(); | 2859 new HashMap<String, ClassMember>(); |
| 2378 for (ClassMember classMember in classMembers) { | 2860 for (ClassMember member in classMembers) { |
| 2379 if (classMember is MethodDeclaration) { | 2861 if (member is MethodDeclaration) { |
| 2380 MethodDeclaration method = classMember; | 2862 if (member.isStatic) { |
| 2381 if (method.isStatic) { | |
| 2382 continue; | 2863 continue; |
| 2383 } | 2864 } |
| 2384 // prepare name | 2865 // prepare name |
| 2385 SimpleIdentifier name = method.name; | 2866 SimpleIdentifier name = member.name; |
| 2386 if (name == null) { | 2867 if (name == null) { |
| 2387 continue; | 2868 continue; |
| 2388 } | 2869 } |
| 2389 bool addThisMemberToTheMap = true; | 2870 bool addThisMemberToTheMap = true; |
| 2390 bool isGetter = method.isGetter; | 2871 bool isGetter = member.isGetter; |
| 2391 bool isSetter = method.isSetter; | 2872 bool isSetter = member.isSetter; |
| 2392 bool isOperator = method.isOperator; | 2873 bool isOperator = member.isOperator; |
| 2393 bool isMethod = !isGetter && !isSetter && !isOperator; | 2874 bool isMethod = !isGetter && !isSetter && !isOperator; |
| 2394 // Do lookups in the enclosing class (and the inherited member) if the | 2875 // Do lookups in the enclosing class (and the inherited member) if the |
| 2395 // member is a method or a setter for | 2876 // member is a method or a setter for |
| 2396 // StaticWarningCode.CONFLICTING_INSTANCE_METHOD_SETTER warning. | 2877 // StaticWarningCode.CONFLICTING_INSTANCE_METHOD_SETTER warning. |
| 2397 if (isMethod) { | 2878 if (isMethod) { |
| 2398 String setterName = "${name.name}="; | 2879 String setterName = "${name.name}="; |
| 2399 Element enclosingElementOfSetter = null; | 2880 Element enclosingElementOfSetter = null; |
| 2400 ClassMember conflictingSetter = memberHashMap[setterName]; | 2881 ClassMember conflictingSetter = memberHashMap[setterName]; |
| 2401 if (conflictingSetter != null) { | 2882 if (conflictingSetter != null) { |
| 2402 enclosingElementOfSetter = | 2883 enclosingElementOfSetter = |
| 2403 conflictingSetter.element.enclosingElement; | 2884 conflictingSetter.element.enclosingElement; |
| 2404 } else { | 2885 } else { |
| 2405 ExecutableElement elementFromInheritance = _inheritanceManager | 2886 ExecutableElement elementFromInheritance = _inheritanceManager |
| 2406 .lookupInheritance(_enclosingClass, setterName); | 2887 .lookupInheritance(_enclosingClass, setterName); |
| 2407 if (elementFromInheritance != null) { | 2888 if (elementFromInheritance != null) { |
| 2408 enclosingElementOfSetter = | 2889 enclosingElementOfSetter = |
| 2409 elementFromInheritance.enclosingElement; | 2890 elementFromInheritance.enclosingElement; |
| 2410 } | 2891 } |
| 2411 } | 2892 } |
| 2412 if (enclosingElementOfSetter != null) { | 2893 if (enclosingElementOfSetter != null) { |
| 2413 // report problem | |
| 2414 _errorReporter.reportErrorForNode( | 2894 _errorReporter.reportErrorForNode( |
| 2415 StaticWarningCode.CONFLICTING_INSTANCE_METHOD_SETTER, name, [ | 2895 StaticWarningCode.CONFLICTING_INSTANCE_METHOD_SETTER, name, [ |
| 2416 _enclosingClass.displayName, | 2896 _enclosingClass.displayName, |
| 2417 name.name, | 2897 name.name, |
| 2418 enclosingElementOfSetter.displayName | 2898 enclosingElementOfSetter.displayName |
| 2419 ]); | 2899 ]); |
| 2420 foundError = true; | |
| 2421 addThisMemberToTheMap = false; | 2900 addThisMemberToTheMap = false; |
| 2422 } | 2901 } |
| 2423 } else if (isSetter) { | 2902 } else if (isSetter) { |
| 2424 String methodName = name.name; | 2903 String methodName = name.name; |
| 2425 ClassMember conflictingMethod = memberHashMap[methodName]; | 2904 ClassMember conflictingMethod = memberHashMap[methodName]; |
| 2426 if (conflictingMethod != null && | 2905 if (conflictingMethod != null && |
| 2427 conflictingMethod is MethodDeclaration && | 2906 conflictingMethod is MethodDeclaration && |
| 2428 !conflictingMethod.isGetter) { | 2907 !conflictingMethod.isGetter) { |
| 2429 // report problem | |
| 2430 _errorReporter.reportErrorForNode( | 2908 _errorReporter.reportErrorForNode( |
| 2431 StaticWarningCode.CONFLICTING_INSTANCE_METHOD_SETTER2, | 2909 StaticWarningCode.CONFLICTING_INSTANCE_METHOD_SETTER2, |
| 2432 name, | 2910 name, |
| 2433 [_enclosingClass.displayName, name.name]); | 2911 [_enclosingClass.displayName, name.name]); |
| 2434 foundError = true; | |
| 2435 addThisMemberToTheMap = false; | 2912 addThisMemberToTheMap = false; |
| 2436 } | 2913 } |
| 2437 } | 2914 } |
| 2438 // Finally, add this member into the HashMap. | 2915 // Finally, add this member into the HashMap. |
| 2439 if (addThisMemberToTheMap) { | 2916 if (addThisMemberToTheMap) { |
| 2440 if (method.isSetter) { | 2917 if (member.isSetter) { |
| 2441 memberHashMap["${name.name}="] = method; | 2918 memberHashMap["${name.name}="] = member; |
| 2442 } else { | 2919 } else { |
| 2443 memberHashMap[name.name] = method; | 2920 memberHashMap[name.name] = member; |
| 2444 } | 2921 } |
| 2445 } | 2922 } |
| 2446 } | 2923 } |
| 2447 } | 2924 } |
| 2448 return foundError; | |
| 2449 } | 2925 } |
| 2450 | 2926 |
| 2451 /** | 2927 /** |
| 2452 * Verify that the enclosing class does not have an instance member with the | 2928 * Verify that the enclosing class does not have an instance member with the |
| 2453 * same name as the given static [method] declaration. | 2929 * same name as the given static [method] declaration. |
| 2454 * | 2930 * |
| 2455 * See [StaticWarningCode.CONFLICTING_STATIC_GETTER_AND_INSTANCE_SETTER]. | 2931 * See [StaticWarningCode.CONFLICTING_STATIC_GETTER_AND_INSTANCE_SETTER]. |
| 2456 */ | 2932 */ |
| 2457 bool _checkForConflictingStaticGetterAndInstanceSetter( | 2933 void _checkForConflictingStaticGetterAndInstanceSetter( |
| 2458 MethodDeclaration method) { | 2934 MethodDeclaration method) { |
| 2459 if (!method.isStatic) { | 2935 if (!method.isStatic) { |
| 2460 return false; | 2936 return; |
| 2461 } | 2937 } |
| 2462 // prepare name | 2938 // prepare name |
| 2463 SimpleIdentifier nameNode = method.name; | 2939 SimpleIdentifier nameNode = method.name; |
| 2464 if (nameNode == null) { | 2940 if (nameNode == null) { |
| 2465 return false; | 2941 return; |
| 2466 } | 2942 } |
| 2467 String name = nameNode.name; | 2943 String name = nameNode.name; |
| 2468 // prepare enclosing type | 2944 // prepare enclosing type |
| 2469 if (_enclosingClass == null) { | 2945 if (_enclosingClass == null) { |
| 2470 return false; | 2946 return; |
| 2471 } | 2947 } |
| 2472 InterfaceType enclosingType = _enclosingClass.type; | 2948 InterfaceType enclosingType = _enclosingClass.type; |
| 2473 // try to find setter | 2949 // try to find setter |
| 2474 ExecutableElement setter = | 2950 ExecutableElement setter = |
| 2475 enclosingType.lookUpSetter(name, _currentLibrary); | 2951 enclosingType.lookUpSetter(name, _currentLibrary); |
| 2476 if (setter == null) { | 2952 if (setter == null) { |
| 2477 return false; | 2953 return; |
| 2478 } | 2954 } |
| 2479 // OK, also static | 2955 // OK, also static |
| 2480 if (setter.isStatic) { | 2956 if (setter.isStatic) { |
| 2481 return false; | 2957 return; |
| 2482 } | 2958 } |
| 2483 // prepare "setter" type to report its name | 2959 // prepare "setter" type to report its name |
| 2484 ClassElement setterClass = setter.enclosingElement as ClassElement; | 2960 ClassElement setterClass = setter.enclosingElement as ClassElement; |
| 2485 InterfaceType setterType = setterClass.type; | 2961 InterfaceType setterType = setterClass.type; |
| 2486 // report problem | 2962 |
| 2487 _errorReporter.reportErrorForNode( | 2963 _errorReporter.reportErrorForNode( |
| 2488 StaticWarningCode.CONFLICTING_STATIC_GETTER_AND_INSTANCE_SETTER, | 2964 StaticWarningCode.CONFLICTING_STATIC_GETTER_AND_INSTANCE_SETTER, |
| 2489 nameNode, | 2965 nameNode, |
| 2490 [setterType.displayName]); | 2966 [setterType.displayName]); |
| 2491 return true; | |
| 2492 } | 2967 } |
| 2493 | 2968 |
| 2494 /** | 2969 /** |
| 2495 * Verify that the enclosing class does not have an instance member with the | 2970 * Verify that the enclosing class does not have an instance member with the |
| 2496 * same name as the given static [method] declaration. | 2971 * same name as the given static [method] declaration. |
| 2497 * | 2972 * |
| 2498 * See [StaticWarningCode.CONFLICTING_STATIC_SETTER_AND_INSTANCE_MEMBER]. | 2973 * See [StaticWarningCode.CONFLICTING_STATIC_SETTER_AND_INSTANCE_MEMBER]. |
| 2499 */ | 2974 */ |
| 2500 bool _checkForConflictingStaticSetterAndInstanceMember( | 2975 void _checkForConflictingStaticSetterAndInstanceMember( |
| 2501 MethodDeclaration method) { | 2976 MethodDeclaration method) { |
| 2502 if (!method.isStatic) { | 2977 if (!method.isStatic) { |
| 2503 return false; | 2978 return; |
| 2504 } | 2979 } |
| 2505 // prepare name | 2980 // prepare name |
| 2506 SimpleIdentifier nameNode = method.name; | 2981 SimpleIdentifier nameNode = method.name; |
| 2507 if (nameNode == null) { | 2982 if (nameNode == null) { |
| 2508 return false; | 2983 return; |
| 2509 } | 2984 } |
| 2510 String name = nameNode.name; | 2985 String name = nameNode.name; |
| 2511 // prepare enclosing type | 2986 // prepare enclosing type |
| 2512 if (_enclosingClass == null) { | 2987 if (_enclosingClass == null) { |
| 2513 return false; | 2988 return; |
| 2514 } | 2989 } |
| 2515 InterfaceType enclosingType = _enclosingClass.type; | 2990 InterfaceType enclosingType = _enclosingClass.type; |
| 2516 // try to find member | 2991 // try to find member |
| 2517 ExecutableElement member; | 2992 ExecutableElement member; |
| 2518 member = enclosingType.lookUpMethod(name, _currentLibrary); | 2993 member = enclosingType.lookUpMethod(name, _currentLibrary); |
| 2519 if (member == null) { | 2994 if (member == null) { |
| 2520 member = enclosingType.lookUpGetter(name, _currentLibrary); | 2995 member = enclosingType.lookUpGetter(name, _currentLibrary); |
| 2521 } | 2996 } |
| 2522 if (member == null) { | 2997 if (member == null) { |
| 2523 member = enclosingType.lookUpSetter(name, _currentLibrary); | 2998 member = enclosingType.lookUpSetter(name, _currentLibrary); |
| 2524 } | 2999 } |
| 2525 if (member == null) { | 3000 if (member == null) { |
| 2526 return false; | 3001 return; |
| 2527 } | 3002 } |
| 2528 // OK, also static | 3003 // OK, also static |
| 2529 if (member.isStatic) { | 3004 if (member.isStatic) { |
| 2530 return false; | 3005 return; |
| 2531 } | 3006 } |
| 2532 // prepare "member" type to report its name | 3007 // prepare "member" type to report its name |
| 2533 ClassElement memberClass = member.enclosingElement as ClassElement; | 3008 ClassElement memberClass = member.enclosingElement as ClassElement; |
| 2534 InterfaceType memberType = memberClass.type; | 3009 InterfaceType memberType = memberClass.type; |
| 2535 // report problem | 3010 |
| 2536 _errorReporter.reportErrorForNode( | 3011 _errorReporter.reportErrorForNode( |
| 2537 StaticWarningCode.CONFLICTING_STATIC_SETTER_AND_INSTANCE_MEMBER, | 3012 StaticWarningCode.CONFLICTING_STATIC_SETTER_AND_INSTANCE_MEMBER, |
| 2538 nameNode, | 3013 nameNode, |
| 2539 [memberType.displayName]); | 3014 [memberType.displayName]); |
| 2540 return true; | |
| 2541 } | 3015 } |
| 2542 | 3016 |
| 2543 /** | 3017 /** |
| 2544 * Verify all conflicts between type variable and enclosing class. | 3018 * Verify all conflicts between type variable and enclosing class. |
| 2545 * TODO(scheglov) | 3019 * TODO(scheglov) |
| 2546 * | 3020 * |
| 2547 * See [CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_CLASS], and | 3021 * See [CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_CLASS], and |
| 2548 * [CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER]. | 3022 * [CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER]. |
| 2549 */ | 3023 */ |
| 2550 bool _checkForConflictingTypeVariableErrorCodes( | 3024 void _checkForConflictingTypeVariableErrorCodes( |
| 2551 ClassDeclaration declaration) { | 3025 ClassDeclaration declaration) { |
| 2552 bool problemReported = false; | |
| 2553 for (TypeParameterElement typeParameter in _enclosingClass.typeParameters) { | 3026 for (TypeParameterElement typeParameter in _enclosingClass.typeParameters) { |
| 2554 String name = typeParameter.name; | 3027 String name = typeParameter.name; |
| 2555 // name is same as the name of the enclosing class | 3028 // name is same as the name of the enclosing class |
| 2556 if (_enclosingClass.name == name) { | 3029 if (_enclosingClass.name == name) { |
| 2557 _errorReporter.reportErrorForElement( | 3030 _errorReporter.reportErrorForElement( |
| 2558 CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_CLASS, | 3031 CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_CLASS, |
| 2559 typeParameter, | 3032 typeParameter, |
| 2560 [name]); | 3033 [name]); |
| 2561 problemReported = true; | |
| 2562 } | 3034 } |
| 2563 // check members | 3035 // check members |
| 2564 if (_enclosingClass.getMethod(name) != null || | 3036 if (_enclosingClass.getMethod(name) != null || |
| 2565 _enclosingClass.getGetter(name) != null || | 3037 _enclosingClass.getGetter(name) != null || |
| 2566 _enclosingClass.getSetter(name) != null) { | 3038 _enclosingClass.getSetter(name) != null) { |
| 2567 _errorReporter.reportErrorForElement( | 3039 _errorReporter.reportErrorForElement( |
| 2568 CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER, | 3040 CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER, |
| 2569 typeParameter, | 3041 typeParameter, |
| 2570 [name]); | 3042 [name]); |
| 2571 problemReported = true; | |
| 2572 } | 3043 } |
| 2573 } | 3044 } |
| 2574 return problemReported; | |
| 2575 } | 3045 } |
| 2576 | 3046 |
| 2577 /** | 3047 /** |
| 2578 * Verify that if the given [constructor] declaration is 'const' then there | 3048 * Verify that if the given [constructor] declaration is 'const' then there |
| 2579 * are no invocations of non-'const' super constructors. | 3049 * are no invocations of non-'const' super constructors. |
| 2580 * | 3050 * |
| 2581 * See [CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER]. | 3051 * See [CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER]. |
| 2582 */ | 3052 */ |
| 2583 bool _checkForConstConstructorWithNonConstSuper( | 3053 void _checkForConstConstructorWithNonConstSuper( |
| 2584 ConstructorDeclaration constructor) { | 3054 ConstructorDeclaration constructor) { |
| 2585 if (!_isEnclosingConstructorConst) { | 3055 if (!_isEnclosingConstructorConst) { |
| 2586 return false; | 3056 return; |
| 2587 } | 3057 } |
| 2588 // OK, const factory, checked elsewhere | 3058 // OK, const factory, checked elsewhere |
| 2589 if (constructor.factoryKeyword != null) { | 3059 if (constructor.factoryKeyword != null) { |
| 2590 return false; | 3060 return; |
| 2591 } | 3061 } |
| 2592 // check for mixins | 3062 // check for mixins |
| 2593 if (_enclosingClass.mixins.length != 0) { | 3063 if (_enclosingClass.mixins.length != 0) { |
| 2594 _errorReporter.reportErrorForNode( | 3064 _errorReporter.reportErrorForNode( |
| 2595 CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN, | 3065 CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN, |
| 2596 constructor.returnType); | 3066 constructor.returnType); |
| 2597 return true; | 3067 return; |
| 2598 } | 3068 } |
| 2599 // try to find and check super constructor invocation | 3069 // try to find and check super constructor invocation |
| 2600 for (ConstructorInitializer initializer in constructor.initializers) { | 3070 for (ConstructorInitializer initializer in constructor.initializers) { |
| 2601 if (initializer is SuperConstructorInvocation) { | 3071 if (initializer is SuperConstructorInvocation) { |
| 2602 SuperConstructorInvocation superInvocation = initializer; | 3072 ConstructorElement element = initializer.staticElement; |
| 2603 ConstructorElement element = superInvocation.staticElement; | |
| 2604 if (element == null || element.isConst) { | 3073 if (element == null || element.isConst) { |
| 2605 return false; | 3074 return; |
| 2606 } | 3075 } |
| 2607 _errorReporter.reportErrorForNode( | 3076 _errorReporter.reportErrorForNode( |
| 2608 CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER, | 3077 CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER, |
| 2609 superInvocation, | 3078 initializer, |
| 2610 [element.enclosingElement.displayName]); | 3079 [element.enclosingElement.displayName]); |
| 2611 return true; | 3080 return; |
| 2612 } | 3081 } |
| 2613 } | 3082 } |
| 2614 // no explicit super constructor invocation, check default constructor | 3083 // no explicit super constructor invocation, check default constructor |
| 2615 InterfaceType supertype = _enclosingClass.supertype; | 3084 InterfaceType supertype = _enclosingClass.supertype; |
| 2616 if (supertype == null) { | 3085 if (supertype == null) { |
| 2617 return false; | 3086 return; |
| 2618 } | 3087 } |
| 2619 if (supertype.isObject) { | 3088 if (supertype.isObject) { |
| 2620 return false; | 3089 return; |
| 2621 } | 3090 } |
| 2622 ConstructorElement unnamedConstructor = | 3091 ConstructorElement unnamedConstructor = |
| 2623 supertype.element.unnamedConstructor; | 3092 supertype.element.unnamedConstructor; |
| 2624 if (unnamedConstructor == null) { | 3093 if (unnamedConstructor == null || unnamedConstructor.isConst) { |
| 2625 return false; | 3094 return; |
| 2626 } | 3095 } |
| 2627 if (unnamedConstructor.isConst) { | 3096 |
| 2628 return false; | |
| 2629 } | |
| 2630 // default constructor is not 'const', report problem | 3097 // default constructor is not 'const', report problem |
| 2631 _errorReporter.reportErrorForNode( | 3098 _errorReporter.reportErrorForNode( |
| 2632 CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER, | 3099 CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER, |
| 2633 constructor.returnType, | 3100 constructor.returnType, |
| 2634 [supertype.displayName]); | 3101 [supertype.displayName]); |
| 2635 return true; | |
| 2636 } | 3102 } |
| 2637 | 3103 |
| 2638 /** | 3104 /** |
| 2639 * Verify that if the given [constructor] declaration is 'const' then there | 3105 * Verify that if the given [constructor] declaration is 'const' then there |
| 2640 * are no non-final instance variable. The [constructorElement] is the | 3106 * are no non-final instance variable. The [constructorElement] is the |
| 2641 * constructor element. | 3107 * constructor element. |
| 2642 * | 3108 * |
| 2643 * See [CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD]. | 3109 * See [CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD]. |
| 2644 */ | 3110 */ |
| 2645 bool _checkForConstConstructorWithNonFinalField( | 3111 void _checkForConstConstructorWithNonFinalField( |
| 2646 ConstructorDeclaration constructor, | 3112 ConstructorDeclaration constructor, |
| 2647 ConstructorElement constructorElement) { | 3113 ConstructorElement constructorElement) { |
| 2648 if (!_isEnclosingConstructorConst) { | 3114 if (!_isEnclosingConstructorConst) { |
| 2649 return false; | 3115 return; |
| 2650 } | 3116 } |
| 2651 // check if there is non-final field | 3117 // check if there is non-final field |
| 2652 ClassElement classElement = constructorElement.enclosingElement; | 3118 ClassElement classElement = constructorElement.enclosingElement; |
| 2653 if (!classElement.hasNonFinalField) { | 3119 if (!classElement.hasNonFinalField) { |
| 2654 return false; | 3120 return; |
| 2655 } | 3121 } |
| 2656 // report problem | 3122 |
| 2657 _errorReporter.reportErrorForNode( | 3123 _errorReporter.reportErrorForNode( |
| 2658 CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD, | 3124 CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD, |
| 2659 constructor); | 3125 constructor); |
| 2660 return true; | |
| 2661 } | 3126 } |
| 2662 | 3127 |
| 2663 /** | 3128 /** |
| 2664 * Verify that the given 'const' instance creation [expression] is not | 3129 * Verify that the given 'const' instance creation [expression] is not |
| 2665 * creating a deferred type. The [constructorName] is the constructor name, | 3130 * creating a deferred type. The [constructorName] is the constructor name, |
| 2666 * always non-`null`. The [typeName] is the name of the type defining the | 3131 * always non-`null`. The [typeName] is the name of the type defining the |
| 2667 * constructor, always non-`null`. | 3132 * constructor, always non-`null`. |
| 2668 * | 3133 * |
| 2669 * See [CompileTimeErrorCode.CONST_DEFERRED_CLASS]. | 3134 * See [CompileTimeErrorCode.CONST_DEFERRED_CLASS]. |
| 2670 */ | 3135 */ |
| 2671 bool _checkForConstDeferredClass(InstanceCreationExpression expression, | 3136 void _checkForConstDeferredClass(InstanceCreationExpression expression, |
| 2672 ConstructorName constructorName, TypeName typeName) { | 3137 ConstructorName constructorName, TypeName typeName) { |
| 2673 if (typeName.isDeferred) { | 3138 if (typeName.isDeferred) { |
| 2674 _errorReporter.reportErrorForNode( | 3139 _errorReporter.reportErrorForNode( |
| 2675 CompileTimeErrorCode.CONST_DEFERRED_CLASS, | 3140 CompileTimeErrorCode.CONST_DEFERRED_CLASS, |
| 2676 constructorName, | 3141 constructorName, |
| 2677 [typeName.name.name]); | 3142 [typeName.name.name]); |
| 2678 return true; | |
| 2679 } | 3143 } |
| 2680 return false; | |
| 2681 } | 3144 } |
| 2682 | 3145 |
| 2683 /** | 3146 /** |
| 2684 * Verify that the given throw [expression] is not enclosed in a 'const' | 3147 * Verify that the given throw [expression] is not enclosed in a 'const' |
| 2685 * constructor declaration. | 3148 * constructor declaration. |
| 2686 * | 3149 * |
| 2687 * See [CompileTimeErrorCode.CONST_CONSTRUCTOR_THROWS_EXCEPTION]. | 3150 * See [CompileTimeErrorCode.CONST_CONSTRUCTOR_THROWS_EXCEPTION]. |
| 2688 */ | 3151 */ |
| 2689 bool _checkForConstEvalThrowsException(ThrowExpression expression) { | 3152 void _checkForConstEvalThrowsException(ThrowExpression expression) { |
| 2690 if (_isEnclosingConstructorConst) { | 3153 if (_isEnclosingConstructorConst) { |
| 2691 _errorReporter.reportErrorForNode( | 3154 _errorReporter.reportErrorForNode( |
| 2692 CompileTimeErrorCode.CONST_CONSTRUCTOR_THROWS_EXCEPTION, expression); | 3155 CompileTimeErrorCode.CONST_CONSTRUCTOR_THROWS_EXCEPTION, expression); |
| 2693 return true; | |
| 2694 } | 3156 } |
| 2695 return false; | |
| 2696 } | 3157 } |
| 2697 | 3158 |
| 2698 /** | 3159 /** |
| 2699 * Verify that the given normal formal [parameter] is not 'const'. | 3160 * Verify that the given normal formal [parameter] is not 'const'. |
| 2700 * | 3161 * |
| 2701 * See [CompileTimeErrorCode.CONST_FORMAL_PARAMETER]. | 3162 * See [CompileTimeErrorCode.CONST_FORMAL_PARAMETER]. |
| 2702 */ | 3163 */ |
| 2703 bool _checkForConstFormalParameter(NormalFormalParameter parameter) { | 3164 void _checkForConstFormalParameter(NormalFormalParameter parameter) { |
| 2704 if (parameter.isConst) { | 3165 if (parameter.isConst) { |
| 2705 _errorReporter.reportErrorForNode( | 3166 _errorReporter.reportErrorForNode( |
| 2706 CompileTimeErrorCode.CONST_FORMAL_PARAMETER, parameter); | 3167 CompileTimeErrorCode.CONST_FORMAL_PARAMETER, parameter); |
| 2707 return true; | |
| 2708 } | 3168 } |
| 2709 return false; | |
| 2710 } | 3169 } |
| 2711 | 3170 |
| 2712 /** | 3171 /** |
| 2713 * Verify that the given instance creation [expression] is not being invoked | 3172 * Verify that the given instance creation [expression] is not being invoked |
| 2714 * on an abstract class. The [typeName] is the [TypeName] of the | 3173 * on an abstract class. The [typeName] is the [TypeName] of the |
| 2715 * [ConstructorName] from the [InstanceCreationExpression], this is the AST | 3174 * [ConstructorName] from the [InstanceCreationExpression], this is the AST |
| 2716 * node that the error is attached to. The [type] is the type being | 3175 * node that the error is attached to. The [type] is the type being |
| 2717 * constructed with this [InstanceCreationExpression]. | 3176 * constructed with this [InstanceCreationExpression]. |
| 2718 * | 3177 * |
| 2719 * See [StaticWarningCode.CONST_WITH_ABSTRACT_CLASS], and | 3178 * See [StaticWarningCode.CONST_WITH_ABSTRACT_CLASS], and |
| 2720 * [StaticWarningCode.NEW_WITH_ABSTRACT_CLASS]. | 3179 * [StaticWarningCode.NEW_WITH_ABSTRACT_CLASS]. |
| 2721 */ | 3180 */ |
| 2722 bool _checkForConstOrNewWithAbstractClass( | 3181 void _checkForConstOrNewWithAbstractClass( |
| 2723 InstanceCreationExpression expression, | 3182 InstanceCreationExpression expression, |
| 2724 TypeName typeName, | 3183 TypeName typeName, |
| 2725 InterfaceType type) { | 3184 InterfaceType type) { |
| 2726 if (type.element.isAbstract) { | 3185 if (type.element.isAbstract) { |
| 2727 ConstructorElement element = expression.staticElement; | 3186 ConstructorElement element = expression.staticElement; |
| 2728 if (element != null && !element.isFactory) { | 3187 if (element != null && !element.isFactory) { |
| 2729 if ((expression.keyword as sc.KeywordToken).keyword == | 3188 if (expression.keyword.keyword == Keyword.CONST) { |
| 2730 sc.Keyword.CONST) { | |
| 2731 _errorReporter.reportErrorForNode( | 3189 _errorReporter.reportErrorForNode( |
| 2732 StaticWarningCode.CONST_WITH_ABSTRACT_CLASS, typeName); | 3190 StaticWarningCode.CONST_WITH_ABSTRACT_CLASS, typeName); |
| 2733 } else { | 3191 } else { |
| 2734 _errorReporter.reportErrorForNode( | 3192 _errorReporter.reportErrorForNode( |
| 2735 StaticWarningCode.NEW_WITH_ABSTRACT_CLASS, typeName); | 3193 StaticWarningCode.NEW_WITH_ABSTRACT_CLASS, typeName); |
| 2736 } | 3194 } |
| 2737 return true; | |
| 2738 } | 3195 } |
| 2739 } | 3196 } |
| 2740 return false; | |
| 2741 } | 3197 } |
| 2742 | 3198 |
| 2743 /** | 3199 /** |
| 2744 * Verify that the given instance creation [expression] is not being invoked | 3200 * Verify that the given instance creation [expression] is not being invoked |
| 2745 * on an enum. The [typeName] is the [TypeName] of the [ConstructorName] from | 3201 * on an enum. The [typeName] is the [TypeName] of the [ConstructorName] from |
| 2746 * the [InstanceCreationExpression], this is the AST node that the error is | 3202 * the [InstanceCreationExpression], this is the AST node that the error is |
| 2747 * attached to. The [type] is the type being constructed with this | 3203 * attached to. The [type] is the type being constructed with this |
| 2748 * [InstanceCreationExpression]. | 3204 * [InstanceCreationExpression]. |
| 2749 * | 3205 * |
| 2750 * See [CompileTimeErrorCode.INSTANTIATE_ENUM]. | 3206 * See [CompileTimeErrorCode.INSTANTIATE_ENUM]. |
| 2751 */ | 3207 */ |
| 2752 bool _checkForConstOrNewWithEnum(InstanceCreationExpression expression, | 3208 void _checkForConstOrNewWithEnum(InstanceCreationExpression expression, |
| 2753 TypeName typeName, InterfaceType type) { | 3209 TypeName typeName, InterfaceType type) { |
| 2754 if (type.element.isEnum) { | 3210 if (type.element.isEnum) { |
| 2755 _errorReporter.reportErrorForNode( | 3211 _errorReporter.reportErrorForNode( |
| 2756 CompileTimeErrorCode.INSTANTIATE_ENUM, typeName); | 3212 CompileTimeErrorCode.INSTANTIATE_ENUM, typeName); |
| 2757 return true; | |
| 2758 } | 3213 } |
| 2759 return false; | |
| 2760 } | 3214 } |
| 2761 | 3215 |
| 2762 /** | 3216 /** |
| 2763 * Verify that the given 'const' instance creation [expression] is not being | 3217 * Verify that the given 'const' instance creation [expression] is not being |
| 2764 * invoked on a constructor that is not 'const'. | 3218 * invoked on a constructor that is not 'const'. |
| 2765 * | 3219 * |
| 2766 * This method assumes that the instance creation was tested to be 'const' | 3220 * This method assumes that the instance creation was tested to be 'const' |
| 2767 * before being called. | 3221 * before being called. |
| 2768 * | 3222 * |
| 2769 * See [CompileTimeErrorCode.CONST_WITH_NON_CONST]. | 3223 * See [CompileTimeErrorCode.CONST_WITH_NON_CONST]. |
| 2770 */ | 3224 */ |
| 2771 bool _checkForConstWithNonConst(InstanceCreationExpression expression) { | 3225 void _checkForConstWithNonConst(InstanceCreationExpression expression) { |
| 2772 ConstructorElement constructorElement = expression.staticElement; | 3226 ConstructorElement constructorElement = expression.staticElement; |
| 2773 if (constructorElement != null && !constructorElement.isConst) { | 3227 if (constructorElement != null && !constructorElement.isConst) { |
| 2774 _errorReporter.reportErrorForNode( | 3228 _errorReporter.reportErrorForNode( |
| 2775 CompileTimeErrorCode.CONST_WITH_NON_CONST, expression); | 3229 CompileTimeErrorCode.CONST_WITH_NON_CONST, expression); |
| 2776 return true; | |
| 2777 } | 3230 } |
| 2778 return false; | |
| 2779 } | 3231 } |
| 2780 | 3232 |
| 2781 /** | 3233 /** |
| 2782 * Verify that the given [typeName] does not reference any type parameters. | 3234 * Verify that the given [typeName] does not reference any type parameters. |
| 2783 * | 3235 * |
| 2784 * See [CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS]. | 3236 * See [CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS]. |
| 2785 */ | 3237 */ |
| 2786 bool _checkForConstWithTypeParameters(TypeName typeName) { | 3238 void _checkForConstWithTypeParameters(TypeName typeName) { |
| 2787 // something wrong with AST | 3239 // something wrong with AST |
| 2788 if (typeName == null) { | 3240 if (typeName == null) { |
| 2789 return false; | 3241 return; |
| 2790 } | 3242 } |
| 2791 Identifier name = typeName.name; | 3243 Identifier name = typeName.name; |
| 2792 if (name == null) { | 3244 if (name == null) { |
| 2793 return false; | 3245 return; |
| 2794 } | 3246 } |
| 2795 // should not be a type parameter | 3247 // should not be a type parameter |
| 2796 if (name.staticElement is TypeParameterElement) { | 3248 if (name.staticElement is TypeParameterElement) { |
| 2797 _errorReporter.reportErrorForNode( | 3249 _errorReporter.reportErrorForNode( |
| 2798 CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS, name); | 3250 CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS, name); |
| 2799 } | 3251 } |
| 2800 // check type arguments | 3252 // check type arguments |
| 2801 TypeArgumentList typeArguments = typeName.typeArguments; | 3253 TypeArgumentList typeArguments = typeName.typeArguments; |
| 2802 if (typeArguments != null) { | 3254 if (typeArguments != null) { |
| 2803 bool hasError = false; | |
| 2804 for (TypeName argument in typeArguments.arguments) { | 3255 for (TypeName argument in typeArguments.arguments) { |
| 2805 if (_checkForConstWithTypeParameters(argument)) { | 3256 _checkForConstWithTypeParameters(argument); |
| 2806 hasError = true; | |
| 2807 } | |
| 2808 } | 3257 } |
| 2809 return hasError; | |
| 2810 } | 3258 } |
| 2811 // OK | |
| 2812 return false; | |
| 2813 } | 3259 } |
| 2814 | 3260 |
| 2815 /** | 3261 /** |
| 2816 * Verify that if the given 'const' instance creation [expression] is being | 3262 * Verify that if the given 'const' instance creation [expression] is being |
| 2817 * invoked on the resolved constructor. The [constructorName] is the | 3263 * invoked on the resolved constructor. The [constructorName] is the |
| 2818 * constructor name, always non-`null`. The [typeName] is the name of the type | 3264 * constructor name, always non-`null`. The [typeName] is the name of the type |
| 2819 * defining the constructor, always non-`null`. | 3265 * defining the constructor, always non-`null`. |
| 2820 * | 3266 * |
| 2821 * This method assumes that the instance creation was tested to be 'const' | 3267 * This method assumes that the instance creation was tested to be 'const' |
| 2822 * before being called. | 3268 * before being called. |
| 2823 * | 3269 * |
| 2824 * See [CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR], and | 3270 * See [CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR], and |
| 2825 * [CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT]. | 3271 * [CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT]. |
| 2826 */ | 3272 */ |
| 2827 bool _checkForConstWithUndefinedConstructor( | 3273 void _checkForConstWithUndefinedConstructor( |
| 2828 InstanceCreationExpression expression, | 3274 InstanceCreationExpression expression, |
| 2829 ConstructorName constructorName, | 3275 ConstructorName constructorName, |
| 2830 TypeName typeName) { | 3276 TypeName typeName) { |
| 2831 // OK if resolved | 3277 // OK if resolved |
| 2832 if (expression.staticElement != null) { | 3278 if (expression.staticElement != null) { |
| 2833 return false; | 3279 return; |
| 2834 } | 3280 } |
| 2835 DartType type = typeName.type; | 3281 DartType type = typeName.type; |
| 2836 if (type is InterfaceType) { | 3282 if (type is InterfaceType) { |
| 2837 ClassElement element = type.element; | 3283 ClassElement element = type.element; |
| 2838 if (element != null && element.isEnum) { | 3284 if (element != null && element.isEnum) { |
| 2839 // We have already reported the error. | 3285 // We have already reported the error. |
| 2840 return false; | 3286 return; |
| 2841 } | 3287 } |
| 2842 } | 3288 } |
| 2843 Identifier className = typeName.name; | 3289 Identifier className = typeName.name; |
| 2844 // report as named or default constructor absence | 3290 // report as named or default constructor absence |
| 2845 SimpleIdentifier name = constructorName.name; | 3291 SimpleIdentifier name = constructorName.name; |
| 2846 if (name != null) { | 3292 if (name != null) { |
| 2847 _errorReporter.reportErrorForNode( | 3293 _errorReporter.reportErrorForNode( |
| 2848 CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR, | 3294 CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR, |
| 2849 name, | 3295 name, |
| 2850 [className, name]); | 3296 [className, name]); |
| 2851 } else { | 3297 } else { |
| 2852 _errorReporter.reportErrorForNode( | 3298 _errorReporter.reportErrorForNode( |
| 2853 CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT, | 3299 CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT, |
| 2854 constructorName, | 3300 constructorName, |
| 2855 [className]); | 3301 [className]); |
| 2856 } | 3302 } |
| 2857 return true; | |
| 2858 } | 3303 } |
| 2859 | 3304 |
| 2860 /** | 3305 /** |
| 2861 * Verify that there are no default parameters in the given function type | 3306 * Verify that there are no default parameters in the given function type |
| 2862 * [alias]. | 3307 * [alias]. |
| 2863 * | 3308 * |
| 2864 * See [CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS]. | 3309 * See [CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS]. |
| 2865 */ | 3310 */ |
| 2866 bool _checkForDefaultValueInFunctionTypeAlias(FunctionTypeAlias alias) { | 3311 void _checkForDefaultValueInFunctionTypeAlias(FunctionTypeAlias alias) { |
| 2867 bool result = false; | |
| 2868 FormalParameterList formalParameterList = alias.parameters; | 3312 FormalParameterList formalParameterList = alias.parameters; |
| 2869 NodeList<FormalParameter> parameters = formalParameterList.parameters; | 3313 NodeList<FormalParameter> parameters = formalParameterList.parameters; |
| 2870 for (FormalParameter formalParameter in parameters) { | 3314 for (FormalParameter parameter in parameters) { |
| 2871 if (formalParameter is DefaultFormalParameter) { | 3315 if (parameter is DefaultFormalParameter) { |
| 2872 DefaultFormalParameter defaultFormalParameter = formalParameter; | 3316 if (parameter.defaultValue != null) { |
| 2873 if (defaultFormalParameter.defaultValue != null) { | |
| 2874 _errorReporter.reportErrorForNode( | 3317 _errorReporter.reportErrorForNode( |
| 2875 CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS, alias); | 3318 CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS, alias); |
| 2876 result = true; | |
| 2877 } | 3319 } |
| 2878 } | 3320 } |
| 2879 } | 3321 } |
| 2880 return result; | |
| 2881 } | 3322 } |
| 2882 | 3323 |
| 2883 /** | 3324 /** |
| 2884 * Verify that the given default formal [parameter] is not part of a function | 3325 * Verify that the given default formal [parameter] is not part of a function |
| 2885 * typed parameter. | 3326 * typed parameter. |
| 2886 * | 3327 * |
| 2887 * See [CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER]. | 3328 * See [CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER]. |
| 2888 */ | 3329 */ |
| 2889 bool _checkForDefaultValueInFunctionTypedParameter( | 3330 void _checkForDefaultValueInFunctionTypedParameter( |
| 2890 DefaultFormalParameter parameter) { | 3331 DefaultFormalParameter parameter) { |
| 2891 // OK, not in a function typed parameter. | 3332 // OK, not in a function typed parameter. |
| 2892 if (!_isInFunctionTypedFormalParameter) { | 3333 if (!_isInFunctionTypedFormalParameter) { |
| 2893 return false; | 3334 return; |
| 2894 } | 3335 } |
| 2895 // OK, no default value. | 3336 // OK, no default value. |
| 2896 if (parameter.defaultValue == null) { | 3337 if (parameter.defaultValue == null) { |
| 2897 return false; | 3338 return; |
| 2898 } | 3339 } |
| 2899 // Report problem. | 3340 |
| 2900 _errorReporter.reportErrorForNode( | 3341 _errorReporter.reportErrorForNode( |
| 2901 CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER, | 3342 CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER, |
| 2902 parameter); | 3343 parameter); |
| 2903 return true; | |
| 2904 } | 3344 } |
| 2905 | 3345 |
| 2906 /** | 3346 /** |
| 2907 * Verify that any deferred imports in the given compilation [unit] have a | 3347 * Verify that any deferred imports in the given compilation [unit] have a |
| 2908 * unique prefix. | 3348 * unique prefix. |
| 2909 * | 3349 * |
| 2910 * See [CompileTimeErrorCode.SHARED_DEFERRED_PREFIX]. | 3350 * See [CompileTimeErrorCode.SHARED_DEFERRED_PREFIX]. |
| 2911 */ | 3351 */ |
| 2912 bool _checkForDeferredPrefixCollisions(CompilationUnit unit) { | 3352 void _checkForDeferredPrefixCollisions(CompilationUnit unit) { |
| 2913 bool foundError = false; | |
| 2914 NodeList<Directive> directives = unit.directives; | 3353 NodeList<Directive> directives = unit.directives; |
| 2915 int count = directives.length; | 3354 int count = directives.length; |
| 2916 if (count > 0) { | 3355 if (count > 0) { |
| 2917 HashMap<PrefixElement, List<ImportDirective>> prefixToDirectivesMap = | 3356 HashMap<PrefixElement, List<ImportDirective>> prefixToDirectivesMap = |
| 2918 new HashMap<PrefixElement, List<ImportDirective>>(); | 3357 new HashMap<PrefixElement, List<ImportDirective>>(); |
| 2919 for (int i = 0; i < count; i++) { | 3358 for (int i = 0; i < count; i++) { |
| 2920 Directive directive = directives[i]; | 3359 Directive directive = directives[i]; |
| 2921 if (directive is ImportDirective) { | 3360 if (directive is ImportDirective) { |
| 2922 ImportDirective importDirective = directive; | 3361 SimpleIdentifier prefix = directive.prefix; |
| 2923 SimpleIdentifier prefix = importDirective.prefix; | |
| 2924 if (prefix != null) { | 3362 if (prefix != null) { |
| 2925 Element element = prefix.staticElement; | 3363 Element element = prefix.staticElement; |
| 2926 if (element is PrefixElement) { | 3364 if (element is PrefixElement) { |
| 2927 PrefixElement prefixElement = element; | 3365 List<ImportDirective> elements = prefixToDirectivesMap[element]; |
| 2928 List<ImportDirective> elements = | |
| 2929 prefixToDirectivesMap[prefixElement]; | |
| 2930 if (elements == null) { | 3366 if (elements == null) { |
| 2931 elements = new List<ImportDirective>(); | 3367 elements = new List<ImportDirective>(); |
| 2932 prefixToDirectivesMap[prefixElement] = elements; | 3368 prefixToDirectivesMap[element] = elements; |
| 2933 } | 3369 } |
| 2934 elements.add(importDirective); | 3370 elements.add(directive); |
| 2935 } | 3371 } |
| 2936 } | 3372 } |
| 2937 } | 3373 } |
| 2938 } | 3374 } |
| 2939 for (List<ImportDirective> imports in prefixToDirectivesMap.values) { | 3375 for (List<ImportDirective> imports in prefixToDirectivesMap.values) { |
| 2940 if (_hasDeferredPrefixCollision(imports)) { | 3376 _checkDeferredPrefixCollision(imports); |
| 2941 foundError = true; | |
| 2942 } | |
| 2943 } | 3377 } |
| 2944 } | 3378 } |
| 2945 return foundError; | |
| 2946 } | 3379 } |
| 2947 | 3380 |
| 2948 /** | 3381 /** |
| 2949 * Verify that the enclosing class does not have an instance member with the | 3382 * Verify that the enclosing class does not have an instance member with the |
| 2950 * given name of the static member. | 3383 * given name of the static member. |
| 2951 * | 3384 * |
| 2952 * See [CompileTimeErrorCode.DUPLICATE_DEFINITION_INHERITANCE]. | 3385 * See [CompileTimeErrorCode.DUPLICATE_DEFINITION_INHERITANCE]. |
| 2953 */ | 3386 */ |
| 2954 bool _checkForDuplicateDefinitionInheritance() { | 3387 void _checkForDuplicateDefinitionInheritance() { |
| 2955 if (_enclosingClass == null) { | 3388 if (_enclosingClass == null) { |
| 2956 return false; | 3389 return; |
| 2957 } | 3390 } |
| 2958 bool hasProblem = false; | 3391 |
| 2959 for (ExecutableElement member in _enclosingClass.methods) { | 3392 for (ExecutableElement member in _enclosingClass.methods) { |
| 2960 if (member.isStatic && _checkForDuplicateDefinitionOfMember(member)) { | 3393 if (member.isStatic) { |
| 2961 hasProblem = true; | 3394 _checkForDuplicateDefinitionOfMember(member); |
| 2962 } | 3395 } |
| 2963 } | 3396 } |
| 2964 for (ExecutableElement member in _enclosingClass.accessors) { | 3397 for (ExecutableElement member in _enclosingClass.accessors) { |
| 2965 if (member.isStatic && _checkForDuplicateDefinitionOfMember(member)) { | 3398 if (member.isStatic) { |
| 2966 hasProblem = true; | 3399 _checkForDuplicateDefinitionOfMember(member); |
| 2967 } | 3400 } |
| 2968 } | 3401 } |
| 2969 return hasProblem; | |
| 2970 } | 3402 } |
| 2971 | 3403 |
| 2972 /** | 3404 /** |
| 2973 * Verify that the enclosing class does not have an instance member with the | 3405 * Verify that the enclosing class does not have an instance member with the |
| 2974 * given name of the [staticMember]. | 3406 * given name of the [staticMember]. |
| 2975 * | 3407 * |
| 2976 * See [CompileTimeErrorCode.DUPLICATE_DEFINITION_INHERITANCE]. | 3408 * See [CompileTimeErrorCode.DUPLICATE_DEFINITION_INHERITANCE]. |
| 2977 */ | 3409 */ |
| 2978 bool _checkForDuplicateDefinitionOfMember(ExecutableElement staticMember) { | 3410 void _checkForDuplicateDefinitionOfMember(ExecutableElement staticMember) { |
| 2979 // prepare name | 3411 // prepare name |
| 2980 String name = staticMember.name; | 3412 String name = staticMember.name; |
| 2981 if (name == null) { | 3413 if (name == null) { |
| 2982 return false; | 3414 return; |
| 2983 } | 3415 } |
| 2984 // try to find member | 3416 // try to find member |
| 2985 ExecutableElement inheritedMember = | 3417 ExecutableElement inheritedMember = |
| 2986 _inheritanceManager.lookupInheritance(_enclosingClass, name); | 3418 _inheritanceManager.lookupInheritance(_enclosingClass, name); |
| 2987 if (inheritedMember == null) { | 3419 if (inheritedMember == null) { |
| 2988 return false; | 3420 return; |
| 2989 } | 3421 } |
| 2990 // OK, also static | 3422 // OK, also static |
| 2991 if (inheritedMember.isStatic) { | 3423 if (inheritedMember.isStatic) { |
| 2992 return false; | 3424 return; |
| 2993 } | 3425 } |
| 2994 // determine the display name, use the extended display name if the | 3426 // determine the display name, use the extended display name if the |
| 2995 // enclosing class of the inherited member is in a different source | 3427 // enclosing class of the inherited member is in a different source |
| 2996 String displayName; | 3428 String displayName; |
| 2997 Element enclosingElement = inheritedMember.enclosingElement; | 3429 Element enclosingElement = inheritedMember.enclosingElement; |
| 2998 if (enclosingElement.source == _enclosingClass.source) { | 3430 if (enclosingElement.source == _enclosingClass.source) { |
| 2999 displayName = enclosingElement.displayName; | 3431 displayName = enclosingElement.displayName; |
| 3000 } else { | 3432 } else { |
| 3001 displayName = enclosingElement.getExtendedDisplayName(null); | 3433 displayName = enclosingElement.getExtendedDisplayName(null); |
| 3002 } | 3434 } |
| 3003 // report problem | 3435 |
| 3004 _errorReporter.reportErrorForElement( | 3436 _errorReporter.reportErrorForElement( |
| 3005 CompileTimeErrorCode.DUPLICATE_DEFINITION_INHERITANCE, | 3437 CompileTimeErrorCode.DUPLICATE_DEFINITION_INHERITANCE, |
| 3006 staticMember, | 3438 staticMember, |
| 3007 [name, displayName]); | 3439 [name, displayName]); |
| 3008 return true; | |
| 3009 } | 3440 } |
| 3010 | 3441 |
| 3011 /** | 3442 /** |
| 3012 * Verify that if the given list [literal] has type arguments then there is | 3443 * Verify that if the given list [literal] has type arguments then there is |
| 3013 * exactly one. The [typeArguments] are the type arguments. | 3444 * exactly one. The [typeArguments] are the type arguments. |
| 3014 * | 3445 * |
| 3015 * See [StaticTypeWarningCode.EXPECTED_ONE_LIST_TYPE_ARGUMENTS]. | 3446 * See [StaticTypeWarningCode.EXPECTED_ONE_LIST_TYPE_ARGUMENTS]. |
| 3016 */ | 3447 */ |
| 3017 bool _checkForExpectedOneListTypeArgument( | 3448 void _checkForExpectedOneListTypeArgument( |
| 3018 ListLiteral literal, TypeArgumentList typeArguments) { | 3449 ListLiteral literal, TypeArgumentList typeArguments) { |
| 3019 // check number of type arguments | 3450 // check number of type arguments |
| 3020 int num = typeArguments.arguments.length; | 3451 int num = typeArguments.arguments.length; |
| 3021 if (num == 1) { | 3452 if (num != 1) { |
| 3022 return false; | 3453 _errorReporter.reportErrorForNode( |
| 3454 StaticTypeWarningCode.EXPECTED_ONE_LIST_TYPE_ARGUMENTS, |
| 3455 typeArguments, |
| 3456 [num]); |
| 3023 } | 3457 } |
| 3024 // report problem | |
| 3025 _errorReporter.reportErrorForNode( | |
| 3026 StaticTypeWarningCode.EXPECTED_ONE_LIST_TYPE_ARGUMENTS, | |
| 3027 typeArguments, | |
| 3028 [num]); | |
| 3029 return true; | |
| 3030 } | 3458 } |
| 3031 | 3459 |
| 3032 /** | 3460 /** |
| 3033 * Verify that the given export [directive] has a unique name among other | 3461 * Verify that the given export [directive] has a unique name among other |
| 3034 * exported libraries. The [exportElement] is the [ExportElement] retrieved | 3462 * exported libraries. The [exportElement] is the [ExportElement] retrieved |
| 3035 * from the node, if the element in the node was `null`, then this method is | 3463 * from the node, if the element in the node was `null`, then this method is |
| 3036 * not called. The [exportedLibrary] is the library element containing the | 3464 * not called. The [exportedLibrary] is the library element containing the |
| 3037 * exported element. | 3465 * exported element. |
| 3038 * | 3466 * |
| 3039 * See [CompileTimeErrorCode.EXPORT_DUPLICATED_LIBRARY_NAME]. | 3467 * See [CompileTimeErrorCode.EXPORT_DUPLICATED_LIBRARY_NAME]. |
| 3040 */ | 3468 */ |
| 3041 bool _checkForExportDuplicateLibraryName(ExportDirective directive, | 3469 void _checkForExportDuplicateLibraryName(ExportDirective directive, |
| 3042 ExportElement exportElement, LibraryElement exportedLibrary) { | 3470 ExportElement exportElement, LibraryElement exportedLibrary) { |
| 3043 if (exportedLibrary == null) { | 3471 if (exportedLibrary == null) { |
| 3044 return false; | 3472 return; |
| 3045 } | 3473 } |
| 3046 String name = exportedLibrary.name; | 3474 String name = exportedLibrary.name; |
| 3047 // check if there is other exported library with the same name | 3475 // check if there is other exported library with the same name |
| 3048 LibraryElement prevLibrary = _nameToExportElement[name]; | 3476 LibraryElement prevLibrary = _nameToExportElement[name]; |
| 3049 if (prevLibrary != null) { | 3477 if (prevLibrary != null) { |
| 3050 if (prevLibrary != exportedLibrary) { | 3478 if (prevLibrary != exportedLibrary) { |
| 3051 if (!name.isEmpty) { | 3479 if (!name.isEmpty) { |
| 3052 _errorReporter.reportErrorForNode( | 3480 _errorReporter.reportErrorForNode( |
| 3053 StaticWarningCode.EXPORT_DUPLICATED_LIBRARY_NAMED, directive, [ | 3481 StaticWarningCode.EXPORT_DUPLICATED_LIBRARY_NAMED, directive, [ |
| 3054 prevLibrary.definingCompilationUnit.displayName, | 3482 prevLibrary.definingCompilationUnit.displayName, |
| 3055 exportedLibrary.definingCompilationUnit.displayName, | 3483 exportedLibrary.definingCompilationUnit.displayName, |
| 3056 name | 3484 name |
| 3057 ]); | 3485 ]); |
| 3058 } | 3486 } |
| 3059 return true; | 3487 return; |
| 3060 } | 3488 } |
| 3061 } else { | 3489 } else { |
| 3062 _nameToExportElement[name] = exportedLibrary; | 3490 _nameToExportElement[name] = exportedLibrary; |
| 3063 } | 3491 } |
| 3064 // OK | |
| 3065 return false; | |
| 3066 } | 3492 } |
| 3067 | 3493 |
| 3068 /** | 3494 /** |
| 3069 * Check that if the visiting library is not system, then any given library | 3495 * Check that if the visiting library is not system, then any given library |
| 3070 * should not be SDK internal library. The [exportElement] is the | 3496 * should not be SDK internal library. The [exportElement] is the |
| 3071 * [ExportElement] retrieved from the node, if the element in the node was | 3497 * [ExportElement] retrieved from the node, if the element in the node was |
| 3072 * `null`, then this method is not called. | 3498 * `null`, then this method is not called. |
| 3073 * | 3499 * |
| 3074 * See [CompileTimeErrorCode.EXPORT_INTERNAL_LIBRARY]. | 3500 * See [CompileTimeErrorCode.EXPORT_INTERNAL_LIBRARY]. |
| 3075 */ | 3501 */ |
| 3076 bool _checkForExportInternalLibrary( | 3502 void _checkForExportInternalLibrary( |
| 3077 ExportDirective directive, ExportElement exportElement) { | 3503 ExportDirective directive, ExportElement exportElement) { |
| 3078 if (_isInSystemLibrary) { | 3504 if (_isInSystemLibrary) { |
| 3079 return false; | 3505 return; |
| 3080 } | 3506 } |
| 3081 // should be private | 3507 // should be private |
| 3082 DartSdk sdk = _currentLibrary.context.sourceFactory.dartSdk; | 3508 DartSdk sdk = _currentLibrary.context.sourceFactory.dartSdk; |
| 3083 String uri = exportElement.uri; | 3509 String uri = exportElement.uri; |
| 3084 SdkLibrary sdkLibrary = sdk.getSdkLibrary(uri); | 3510 SdkLibrary sdkLibrary = sdk.getSdkLibrary(uri); |
| 3085 if (sdkLibrary == null) { | 3511 if (sdkLibrary == null) { |
| 3086 return false; | 3512 return; |
| 3087 } | 3513 } |
| 3088 if (!sdkLibrary.isInternal) { | 3514 if (!sdkLibrary.isInternal) { |
| 3089 return false; | 3515 return; |
| 3090 } | 3516 } |
| 3091 // report problem | 3517 |
| 3092 _errorReporter.reportErrorForNode( | 3518 _errorReporter.reportErrorForNode( |
| 3093 CompileTimeErrorCode.EXPORT_INTERNAL_LIBRARY, | 3519 CompileTimeErrorCode.EXPORT_INTERNAL_LIBRARY, |
| 3094 directive, | 3520 directive, |
| 3095 [directive.uri]); | 3521 [directive.uri]); |
| 3096 return true; | |
| 3097 } | 3522 } |
| 3098 | 3523 |
| 3099 /** | 3524 /** |
| 3100 * Verify that the given extends [clause] does not extend a deferred class. | 3525 * Verify that the given extends [clause] does not extend a deferred class. |
| 3101 * | 3526 * |
| 3102 * See [CompileTimeErrorCode.EXTENDS_DEFERRED_CLASS]. | 3527 * See [CompileTimeErrorCode.EXTENDS_DEFERRED_CLASS]. |
| 3103 */ | 3528 */ |
| 3104 bool _checkForExtendsDeferredClass(ExtendsClause clause) { | 3529 void _checkForExtendsDeferredClass(ExtendsClause clause) { |
| 3105 if (clause == null) { | 3530 if (clause == null) { |
| 3106 return false; | 3531 return; |
| 3107 } | 3532 } |
| 3108 return _checkForExtendsOrImplementsDeferredClass( | 3533 _checkForExtendsOrImplementsDeferredClass( |
| 3109 clause.superclass, CompileTimeErrorCode.EXTENDS_DEFERRED_CLASS); | 3534 clause.superclass, CompileTimeErrorCode.EXTENDS_DEFERRED_CLASS); |
| 3110 } | 3535 } |
| 3111 | 3536 |
| 3112 /** | 3537 /** |
| 3113 * Verify that the given type [alias] does not extend a deferred class. | 3538 * Verify that the given type [alias] does not extend a deferred class. |
| 3114 * | 3539 * |
| 3115 * See [CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS]. | 3540 * See [CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS]. |
| 3116 */ | 3541 */ |
| 3117 bool _checkForExtendsDeferredClassInTypeAlias(ClassTypeAlias alias) { | 3542 void _checkForExtendsDeferredClassInTypeAlias(ClassTypeAlias alias) { |
| 3118 if (alias == null) { | 3543 if (alias == null) { |
| 3119 return false; | 3544 return; |
| 3120 } | 3545 } |
| 3121 return _checkForExtendsOrImplementsDeferredClass( | 3546 _checkForExtendsOrImplementsDeferredClass( |
| 3122 alias.superclass, CompileTimeErrorCode.EXTENDS_DEFERRED_CLASS); | 3547 alias.superclass, CompileTimeErrorCode.EXTENDS_DEFERRED_CLASS); |
| 3123 } | 3548 } |
| 3124 | 3549 |
| 3125 /** | 3550 /** |
| 3126 * Verify that the given extends [clause] does not extend classes such as | 3551 * Verify that the given extends [clause] does not extend classes such as |
| 3127 * 'num' or 'String'. | 3552 * 'num' or 'String'. |
| 3128 * | 3553 * |
| 3129 * See [CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS]. | 3554 * See [CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS]. |
| 3130 */ | 3555 */ |
| 3131 bool _checkForExtendsDisallowedClass(ExtendsClause clause) { | 3556 bool _checkForExtendsDisallowedClass(ExtendsClause clause) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 3161 * [CompileTimeErrorCode.EXTENDS_DEFERRED_CLASS], | 3586 * [CompileTimeErrorCode.EXTENDS_DEFERRED_CLASS], |
| 3162 * [CompileTimeErrorCode.IMPLEMENTS_DEFERRED_CLASS], and | 3587 * [CompileTimeErrorCode.IMPLEMENTS_DEFERRED_CLASS], and |
| 3163 * [CompileTimeErrorCode.MIXIN_DEFERRED_CLASS]. | 3588 * [CompileTimeErrorCode.MIXIN_DEFERRED_CLASS]. |
| 3164 */ | 3589 */ |
| 3165 bool _checkForExtendsOrImplementsDeferredClass( | 3590 bool _checkForExtendsOrImplementsDeferredClass( |
| 3166 TypeName typeName, ErrorCode errorCode) { | 3591 TypeName typeName, ErrorCode errorCode) { |
| 3167 if (typeName.isSynthetic) { | 3592 if (typeName.isSynthetic) { |
| 3168 return false; | 3593 return false; |
| 3169 } | 3594 } |
| 3170 if (typeName.isDeferred) { | 3595 if (typeName.isDeferred) { |
| 3171 _errorReporter.reportErrorForNode( | 3596 _errorReporter |
| 3172 errorCode, typeName, [typeName.name.name]); | 3597 .reportErrorForNode(errorCode, typeName, [typeName.name.name]); |
| 3173 return true; | 3598 return true; |
| 3174 } | 3599 } |
| 3175 return false; | 3600 return false; |
| 3176 } | 3601 } |
| 3177 | 3602 |
| 3178 /** | 3603 /** |
| 3179 * Verify that the given [typeName] does not extend, implement or mixin | 3604 * Verify that the given [typeName] does not extend, implement or mixin |
| 3180 * classes such as 'num' or 'String'. | 3605 * classes such as 'num' or 'String'. |
| 3181 * | 3606 * |
| 3182 * See [_checkForExtendsDisallowedClass], | 3607 * See [_checkForExtendsDisallowedClass], |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3224 _errorReporter.reportErrorForNode( | 3649 _errorReporter.reportErrorForNode( |
| 3225 errorCode, typeName, [disallowedType.displayName]); | 3650 errorCode, typeName, [disallowedType.displayName]); |
| 3226 return true; | 3651 return true; |
| 3227 } | 3652 } |
| 3228 } | 3653 } |
| 3229 return false; | 3654 return false; |
| 3230 } | 3655 } |
| 3231 | 3656 |
| 3232 /** | 3657 /** |
| 3233 * Verify that the given constructor field [initializer] has compatible field | 3658 * Verify that the given constructor field [initializer] has compatible field |
| 3234 * and initializer expression types. The [staticElement] is the static element | 3659 * and initializer expression types. The [fieldElement] is the static element |
| 3235 * from the name in the [ConstructorFieldInitializer]. | 3660 * from the name in the [ConstructorFieldInitializer]. |
| 3236 * | 3661 * |
| 3237 * See [CompileTimeErrorCode.CONST_FIELD_INITIALIZER_NOT_ASSIGNABLE], and | 3662 * See [CompileTimeErrorCode.CONST_FIELD_INITIALIZER_NOT_ASSIGNABLE], and |
| 3238 * [StaticWarningCode.FIELD_INITIALIZER_NOT_ASSIGNABLE]. | 3663 * [StaticWarningCode.FIELD_INITIALIZER_NOT_ASSIGNABLE]. |
| 3239 */ | 3664 */ |
| 3240 bool _checkForFieldInitializerNotAssignable( | 3665 void _checkForFieldInitializerNotAssignable( |
| 3241 ConstructorFieldInitializer initializer, Element staticElement) { | 3666 ConstructorFieldInitializer initializer, FieldElement fieldElement) { |
| 3242 // prepare field element | |
| 3243 if (staticElement is! FieldElement) { | |
| 3244 return false; | |
| 3245 } | |
| 3246 FieldElement fieldElement = staticElement as FieldElement; | |
| 3247 // prepare field type | 3667 // prepare field type |
| 3248 DartType fieldType = fieldElement.type; | 3668 DartType fieldType = fieldElement.type; |
| 3249 // prepare expression type | 3669 // prepare expression type |
| 3250 Expression expression = initializer.expression; | 3670 Expression expression = initializer.expression; |
| 3251 if (expression == null) { | 3671 if (expression == null) { |
| 3252 return false; | 3672 return; |
| 3253 } | 3673 } |
| 3254 // test the static type of the expression | 3674 // test the static type of the expression |
| 3255 DartType staticType = getStaticType(expression); | 3675 DartType staticType = getStaticType(expression); |
| 3256 if (staticType == null) { | 3676 if (staticType == null) { |
| 3257 return false; | 3677 return; |
| 3258 } | 3678 } |
| 3259 if (_typeSystem.isAssignableTo(staticType, fieldType)) { | 3679 if (_expressionIsAssignableAtType(expression, staticType, fieldType)) { |
| 3260 return false; | 3680 return; |
| 3261 } | 3681 } |
| 3262 // report problem | 3682 // report problem |
| 3263 if (_isEnclosingConstructorConst) { | 3683 if (_isEnclosingConstructorConst) { |
| 3264 // TODO(paulberry): this error should be based on the actual type of the | 3684 // TODO(paulberry): this error should be based on the actual type of the |
| 3265 // constant, not the static type. See dartbug.com/21119. | 3685 // constant, not the static type. See dartbug.com/21119. |
| 3266 _errorReporter.reportTypeErrorForNode( | 3686 _errorReporter.reportTypeErrorForNode( |
| 3267 CheckedModeCompileTimeErrorCode.CONST_FIELD_INITIALIZER_NOT_ASSIGNABLE
, | 3687 CheckedModeCompileTimeErrorCode |
| 3688 .CONST_FIELD_INITIALIZER_NOT_ASSIGNABLE, |
| 3268 expression, | 3689 expression, |
| 3269 [staticType, fieldType]); | 3690 [staticType, fieldType]); |
| 3270 } | 3691 } |
| 3271 _errorReporter.reportTypeErrorForNode( | 3692 _errorReporter.reportTypeErrorForNode( |
| 3272 StaticWarningCode.FIELD_INITIALIZER_NOT_ASSIGNABLE, | 3693 StaticWarningCode.FIELD_INITIALIZER_NOT_ASSIGNABLE, |
| 3273 expression, | 3694 expression, |
| 3274 [staticType, fieldType]); | 3695 [staticType, fieldType]); |
| 3275 return true; | |
| 3276 // TODO(brianwilkerson) Define a hint corresponding to these errors and | 3696 // TODO(brianwilkerson) Define a hint corresponding to these errors and |
| 3277 // report it if appropriate. | 3697 // report it if appropriate. |
| 3278 // // test the propagated type of the expression | 3698 // // test the propagated type of the expression |
| 3279 // Type propagatedType = expression.getPropagatedType(); | 3699 // Type propagatedType = expression.getPropagatedType(); |
| 3280 // if (propagatedType != null && propagatedType.isAssignableTo(fieldType)
) { | 3700 // if (propagatedType != null && propagatedType.isAssignableTo(fieldType)
) { |
| 3281 // return false; | 3701 // return false; |
| 3282 // } | 3702 // } |
| 3283 // // report problem | 3703 // // report problem |
| 3284 // if (isEnclosingConstructorConst) { | 3704 // if (isEnclosingConstructorConst) { |
| 3285 // errorReporter.reportTypeErrorForNode( | 3705 // errorReporter.reportTypeErrorForNode( |
| (...skipping 10 matching lines...) Expand all Loading... |
| 3296 // } | 3716 // } |
| 3297 // return true; | 3717 // return true; |
| 3298 } | 3718 } |
| 3299 | 3719 |
| 3300 /** | 3720 /** |
| 3301 * Verify that the given field formal [parameter] is in a constructor | 3721 * Verify that the given field formal [parameter] is in a constructor |
| 3302 * declaration. | 3722 * declaration. |
| 3303 * | 3723 * |
| 3304 * See [CompileTimeErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR]. | 3724 * See [CompileTimeErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR]. |
| 3305 */ | 3725 */ |
| 3306 bool _checkForFieldInitializingFormalRedirectingConstructor( | 3726 void _checkForFieldInitializingFormalRedirectingConstructor( |
| 3307 FieldFormalParameter parameter) { | 3727 FieldFormalParameter parameter) { |
| 3308 ConstructorDeclaration constructor = | 3728 // prepare the node that should be a ConstructorDeclaration |
| 3309 parameter.getAncestor((node) => node is ConstructorDeclaration); | 3729 AstNode formalParameterList = parameter.parent; |
| 3310 if (constructor == null) { | 3730 if (formalParameterList is! FormalParameterList) { |
| 3731 formalParameterList = formalParameterList?.parent; |
| 3732 } |
| 3733 AstNode constructor = formalParameterList?.parent; |
| 3734 // now check whether the node is actually a ConstructorDeclaration |
| 3735 if (constructor is ConstructorDeclaration) { |
| 3736 // constructor cannot be a factory |
| 3737 if (constructor.factoryKeyword != null) { |
| 3738 _errorReporter.reportErrorForNode( |
| 3739 CompileTimeErrorCode.FIELD_INITIALIZER_FACTORY_CONSTRUCTOR, |
| 3740 parameter); |
| 3741 return; |
| 3742 } |
| 3743 // constructor cannot have a redirection |
| 3744 for (ConstructorInitializer initializer in constructor.initializers) { |
| 3745 if (initializer is RedirectingConstructorInvocation) { |
| 3746 _errorReporter.reportErrorForNode( |
| 3747 CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR, |
| 3748 parameter); |
| 3749 return; |
| 3750 } |
| 3751 } |
| 3752 } else { |
| 3311 _errorReporter.reportErrorForNode( | 3753 _errorReporter.reportErrorForNode( |
| 3312 CompileTimeErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR, | 3754 CompileTimeErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR, |
| 3313 parameter); | 3755 parameter); |
| 3314 return true; | |
| 3315 } | 3756 } |
| 3316 // constructor cannot be a factory | |
| 3317 if (constructor.factoryKeyword != null) { | |
| 3318 _errorReporter.reportErrorForNode( | |
| 3319 CompileTimeErrorCode.FIELD_INITIALIZER_FACTORY_CONSTRUCTOR, | |
| 3320 parameter); | |
| 3321 return true; | |
| 3322 } | |
| 3323 // constructor cannot have a redirection | |
| 3324 for (ConstructorInitializer initializer in constructor.initializers) { | |
| 3325 if (initializer is RedirectingConstructorInvocation) { | |
| 3326 _errorReporter.reportErrorForNode( | |
| 3327 CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR, | |
| 3328 parameter); | |
| 3329 return true; | |
| 3330 } | |
| 3331 } | |
| 3332 // OK | |
| 3333 return false; | |
| 3334 } | 3757 } |
| 3335 | 3758 |
| 3336 /** | 3759 /** |
| 3337 * Verify that the given variable declaration [list] has only initialized | 3760 * Verify that the given variable declaration [list] has only initialized |
| 3338 * variables if the list is final or const. | 3761 * variables if the list is final or const. |
| 3339 * | 3762 * |
| 3340 * See [CompileTimeErrorCode.CONST_NOT_INITIALIZED], and | 3763 * See [CompileTimeErrorCode.CONST_NOT_INITIALIZED], and |
| 3341 * [StaticWarningCode.FINAL_NOT_INITIALIZED]. | 3764 * [StaticWarningCode.FINAL_NOT_INITIALIZED]. |
| 3342 */ | 3765 */ |
| 3343 bool _checkForFinalNotInitialized(VariableDeclarationList list) { | 3766 void _checkForFinalNotInitialized(VariableDeclarationList list) { |
| 3344 if (_isInNativeClass) { | 3767 if (_isInNativeClass || list.isSynthetic) { |
| 3345 return false; | 3768 return; |
| 3346 } | 3769 } |
| 3347 bool foundError = false; | 3770 |
| 3348 if (!list.isSynthetic) { | 3771 NodeList<VariableDeclaration> variables = list.variables; |
| 3349 NodeList<VariableDeclaration> variables = list.variables; | 3772 for (VariableDeclaration variable in variables) { |
| 3350 for (VariableDeclaration variable in variables) { | 3773 if (variable.initializer == null) { |
| 3351 if (variable.initializer == null) { | 3774 if (list.isConst) { |
| 3352 if (list.isConst) { | 3775 _errorReporter.reportErrorForNode( |
| 3353 _errorReporter.reportErrorForNode( | 3776 CompileTimeErrorCode.CONST_NOT_INITIALIZED, |
| 3354 CompileTimeErrorCode.CONST_NOT_INITIALIZED, | 3777 variable.name, |
| 3355 variable.name, | 3778 [variable.name.name]); |
| 3356 [variable.name.name]); | 3779 } else if (list.isFinal) { |
| 3357 } else if (list.isFinal) { | 3780 _errorReporter.reportErrorForNode( |
| 3358 _errorReporter.reportErrorForNode( | 3781 StaticWarningCode.FINAL_NOT_INITIALIZED, |
| 3359 StaticWarningCode.FINAL_NOT_INITIALIZED, | 3782 variable.name, |
| 3360 variable.name, | 3783 [variable.name.name]); |
| 3361 [variable.name.name]); | |
| 3362 } | |
| 3363 foundError = true; | |
| 3364 } | 3784 } |
| 3365 } | 3785 } |
| 3366 } | 3786 } |
| 3367 return foundError; | |
| 3368 } | 3787 } |
| 3369 | 3788 |
| 3370 /** | 3789 /** |
| 3371 * Verify that final fields in the given clas [declaration] that are declared, | 3790 * Verify that final fields in the given clas [declaration] that are declared, |
| 3372 * without any constructors in the enclosing class, are initialized. Cases in | 3791 * without any constructors in the enclosing class, are initialized. Cases in |
| 3373 * which there is at least one constructor are handled at the end of | 3792 * which there is at least one constructor are handled at the end of |
| 3374 * [_checkForAllFinalInitializedErrorCodes]. | 3793 * [_checkForAllFinalInitializedErrorCodes]. |
| 3375 * | 3794 * |
| 3376 * See [CompileTimeErrorCode.CONST_NOT_INITIALIZED], and | 3795 * See [CompileTimeErrorCode.CONST_NOT_INITIALIZED], and |
| 3377 * [StaticWarningCode.FINAL_NOT_INITIALIZED]. | 3796 * [StaticWarningCode.FINAL_NOT_INITIALIZED]. |
| 3378 */ | 3797 */ |
| 3379 bool _checkForFinalNotInitializedInClass(ClassDeclaration declaration) { | 3798 void _checkForFinalNotInitializedInClass(ClassDeclaration declaration) { |
| 3380 NodeList<ClassMember> classMembers = declaration.members; | 3799 NodeList<ClassMember> classMembers = declaration.members; |
| 3381 for (ClassMember classMember in classMembers) { | 3800 for (ClassMember classMember in classMembers) { |
| 3382 if (classMember is ConstructorDeclaration) { | 3801 if (classMember is ConstructorDeclaration) { |
| 3383 return false; | 3802 return; |
| 3384 } | 3803 } |
| 3385 } | 3804 } |
| 3386 bool foundError = false; | |
| 3387 for (ClassMember classMember in classMembers) { | 3805 for (ClassMember classMember in classMembers) { |
| 3388 if (classMember is FieldDeclaration && | 3806 if (classMember is FieldDeclaration) { |
| 3389 _checkForFinalNotInitialized(classMember.fields)) { | 3807 _checkForFinalNotInitialized(classMember.fields); |
| 3390 foundError = true; | |
| 3391 } | 3808 } |
| 3392 } | 3809 } |
| 3393 return foundError; | |
| 3394 } | 3810 } |
| 3395 | 3811 |
| 3396 /** | 3812 /** |
| 3397 * If the current function is async, async*, or sync*, verify that its | 3813 * If the current function is async, async*, or sync*, verify that its |
| 3398 * declared return type is assignable to Future, Stream, or Iterable, | 3814 * declared return type is assignable to Future, Stream, or Iterable, |
| 3399 * respectively. If not, report the error using [returnType]. | 3815 * respectively. If not, report the error using [returnType]. |
| 3400 */ | 3816 */ |
| 3401 void _checkForIllegalReturnType(TypeName returnType) { | 3817 void _checkForIllegalReturnType(TypeName returnType) { |
| 3402 if (returnType == null) { | 3818 if (returnType == null) { |
| 3403 // No declared return type, so the return type must be dynamic, which is | 3819 // No declared return type, so the return type must be dynamic, which is |
| 3404 // assignable to everything. | 3820 // assignable to everything. |
| 3405 return; | 3821 return; |
| 3406 } | 3822 } |
| 3407 if (_enclosingFunction.isAsynchronous) { | 3823 if (_enclosingFunction.isAsynchronous) { |
| 3408 if (_enclosingFunction.isGenerator) { | 3824 if (_enclosingFunction.isGenerator) { |
| 3409 if (!_typeSystem.isAssignableTo( | 3825 _checkForIllegalReturnTypeCode( |
| 3410 _enclosingFunction.returnType, _typeProvider.streamDynamicType)) { | 3826 returnType, |
| 3411 _errorReporter.reportErrorForNode( | 3827 _typeProvider.streamDynamicType, |
| 3412 StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE, | 3828 StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE); |
| 3413 returnType); | |
| 3414 } | |
| 3415 } else { | 3829 } else { |
| 3416 if (!_typeSystem.isAssignableTo( | 3830 _checkForIllegalReturnTypeCode( |
| 3417 _enclosingFunction.returnType, _typeProvider.futureDynamicType)) { | 3831 returnType, |
| 3418 _errorReporter.reportErrorForNode( | 3832 _typeProvider.futureDynamicType, |
| 3419 StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE, returnType); | 3833 StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE); |
| 3420 } | |
| 3421 } | 3834 } |
| 3422 } else if (_enclosingFunction.isGenerator) { | 3835 } else if (_enclosingFunction.isGenerator) { |
| 3423 if (!_typeSystem.isAssignableTo( | 3836 _checkForIllegalReturnTypeCode( |
| 3424 _enclosingFunction.returnType, _typeProvider.iterableDynamicType)) { | 3837 returnType, |
| 3425 _errorReporter.reportErrorForNode( | 3838 _typeProvider.iterableDynamicType, |
| 3426 StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE, | 3839 StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE); |
| 3427 returnType); | |
| 3428 } | |
| 3429 } | 3840 } |
| 3430 } | 3841 } |
| 3431 | 3842 |
| 3843 /** |
| 3844 * If the current function is async, async*, or sync*, verify that its |
| 3845 * declared return type is assignable to Future, Stream, or Iterable, |
| 3846 * respectively. This is called by [_checkForIllegalReturnType] to check if |
| 3847 * the declared [returnTypeName] is assignable to the required [expectedType] |
| 3848 * and if not report [errorCode]. |
| 3849 */ |
| 3850 void _checkForIllegalReturnTypeCode(TypeName returnTypeName, |
| 3851 DartType expectedType, StaticTypeWarningCode errorCode) { |
| 3852 DartType returnType = _enclosingFunction.returnType; |
| 3853 if (_options.strongMode) { |
| 3854 // |
| 3855 // When checking an async/sync*/async* method, we know the exact type |
| 3856 // that will be returned (e.g. Future, Iterable, or Stream). |
| 3857 // |
| 3858 // For example an `async` function body will return a `Future<T>` for |
| 3859 // some `T` (possibly `dynamic`). |
| 3860 // |
| 3861 // We allow the declared return type to be a supertype of that |
| 3862 // (e.g. `dynamic`, `Object`), or Future<S> for some S. |
| 3863 // (We assume the T <: S relation is checked elsewhere.) |
| 3864 // |
| 3865 // We do not allow user-defined subtypes of Future, because an `async` |
| 3866 // method will never return those. |
| 3867 // |
| 3868 // To check for this, we ensure that `Future<bottom> <: returnType`. |
| 3869 // |
| 3870 // Similar logic applies for sync* and async*. |
| 3871 // |
| 3872 InterfaceType genericType = (expectedType.element as ClassElement).type; |
| 3873 DartType lowerBound = genericType.instantiate([BottomTypeImpl.instance]); |
| 3874 if (!_typeSystem.isSubtypeOf(lowerBound, returnType)) { |
| 3875 _errorReporter.reportErrorForNode(errorCode, returnTypeName); |
| 3876 } |
| 3877 } else if (!_typeSystem.isAssignableTo(returnType, expectedType)) { |
| 3878 _errorReporter.reportErrorForNode(errorCode, returnTypeName); |
| 3879 } |
| 3880 } |
| 3881 |
| 3432 /** | 3882 /** |
| 3433 * Verify that the given implements [clause] does not implement classes that | 3883 * Verify that the given implements [clause] does not implement classes that |
| 3434 * are deferred. | 3884 * are deferred. |
| 3435 * | 3885 * |
| 3436 * See [CompileTimeErrorCode.IMPLEMENTS_DEFERRED_CLASS]. | 3886 * See [CompileTimeErrorCode.IMPLEMENTS_DEFERRED_CLASS]. |
| 3437 */ | 3887 */ |
| 3438 bool _checkForImplementsDeferredClass(ImplementsClause clause) { | 3888 void _checkForImplementsDeferredClass(ImplementsClause clause) { |
| 3439 if (clause == null) { | 3889 if (clause == null) { |
| 3440 return false; | 3890 return; |
| 3441 } | 3891 } |
| 3442 bool foundError = false; | |
| 3443 for (TypeName type in clause.interfaces) { | 3892 for (TypeName type in clause.interfaces) { |
| 3444 if (_checkForExtendsOrImplementsDeferredClass( | 3893 _checkForExtendsOrImplementsDeferredClass( |
| 3445 type, CompileTimeErrorCode.IMPLEMENTS_DEFERRED_CLASS)) { | 3894 type, CompileTimeErrorCode.IMPLEMENTS_DEFERRED_CLASS); |
| 3446 foundError = true; | |
| 3447 } | |
| 3448 } | 3895 } |
| 3449 return foundError; | |
| 3450 } | 3896 } |
| 3451 | 3897 |
| 3452 /** | 3898 /** |
| 3453 * Verify that the given implements [clause] does not implement classes such | 3899 * Verify that the given implements [clause] does not implement classes such |
| 3454 * as 'num' or 'String'. | 3900 * as 'num' or 'String'. |
| 3455 * | 3901 * |
| 3456 * See [CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS]. | 3902 * See [CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS]. |
| 3457 */ | 3903 */ |
| 3458 bool _checkForImplementsDisallowedClass(ImplementsClause clause) { | 3904 bool _checkForImplementsDisallowedClass(ImplementsClause clause) { |
| 3459 if (clause == null) { | 3905 if (clause == null) { |
| 3460 return false; | 3906 return false; |
| 3461 } | 3907 } |
| 3462 bool foundError = false; | 3908 bool foundError = false; |
| 3463 for (TypeName type in clause.interfaces) { | 3909 for (TypeName type in clause.interfaces) { |
| 3464 if (_checkForExtendsOrImplementsDisallowedClass( | 3910 if (_checkForExtendsOrImplementsDisallowedClass( |
| 3465 type, CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS)) { | 3911 type, CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS)) { |
| 3466 foundError = true; | 3912 foundError = true; |
| 3467 } | 3913 } |
| 3468 } | 3914 } |
| 3469 return foundError; | 3915 return foundError; |
| 3470 } | 3916 } |
| 3471 | 3917 |
| 3918 void _checkForImplicitDynamicIdentifier(AstNode node, Identifier id) { |
| 3919 if (_options.implicitDynamic) { |
| 3920 return; |
| 3921 } |
| 3922 VariableElement variable = getVariableElement(id); |
| 3923 if (variable != null && |
| 3924 variable.hasImplicitType && |
| 3925 variable.type.isDynamic) { |
| 3926 ErrorCode errorCode; |
| 3927 if (variable is FieldElement) { |
| 3928 errorCode = StrongModeCode.IMPLICIT_DYNAMIC_FIELD; |
| 3929 } else if (variable is ParameterElement) { |
| 3930 errorCode = StrongModeCode.IMPLICIT_DYNAMIC_PARAMETER; |
| 3931 } else { |
| 3932 errorCode = StrongModeCode.IMPLICIT_DYNAMIC_VARIABLE; |
| 3933 } |
| 3934 _errorReporter.reportErrorForNode(errorCode, node, [id]); |
| 3935 } |
| 3936 } |
| 3937 |
| 3938 void _checkForImplicitDynamicInvoke(InvocationExpression node) { |
| 3939 if (_options.implicitDynamic || |
| 3940 node == null || |
| 3941 node.typeArguments != null) { |
| 3942 return; |
| 3943 } |
| 3944 DartType invokeType = node.staticInvokeType; |
| 3945 DartType declaredType = node.function.staticType; |
| 3946 if (invokeType is FunctionType && declaredType is FunctionType) { |
| 3947 Iterable<DartType> typeArgs = |
| 3948 FunctionTypeImpl.recoverTypeArguments(declaredType, invokeType); |
| 3949 if (typeArgs.any((t) => t.isDynamic)) { |
| 3950 // Issue an error depending on what we're trying to call. |
| 3951 Expression function = node.function; |
| 3952 if (function is Identifier) { |
| 3953 Element element = function.staticElement; |
| 3954 if (element is MethodElement) { |
| 3955 _errorReporter.reportErrorForNode( |
| 3956 StrongModeCode.IMPLICIT_DYNAMIC_METHOD, |
| 3957 node.function, |
| 3958 [element.displayName, element.typeParameters.join(', ')]); |
| 3959 return; |
| 3960 } |
| 3961 |
| 3962 if (element is FunctionElement) { |
| 3963 _errorReporter.reportErrorForNode( |
| 3964 StrongModeCode.IMPLICIT_DYNAMIC_FUNCTION, |
| 3965 node.function, |
| 3966 [element.displayName, element.typeParameters.join(', ')]); |
| 3967 return; |
| 3968 } |
| 3969 } |
| 3970 |
| 3971 // The catch all case if neither of those matched. |
| 3972 // For example, invoking a function expression. |
| 3973 _errorReporter.reportErrorForNode( |
| 3974 StrongModeCode.IMPLICIT_DYNAMIC_INVOKE, |
| 3975 node.function, |
| 3976 [declaredType]); |
| 3977 } |
| 3978 } |
| 3979 } |
| 3980 |
| 3981 void _checkForImplicitDynamicReturn(AstNode node, ExecutableElement element) { |
| 3982 if (_options.implicitDynamic) { |
| 3983 return; |
| 3984 } |
| 3985 if (element is PropertyAccessorElement && element.isSetter) { |
| 3986 return; |
| 3987 } |
| 3988 if (element != null && |
| 3989 element.hasImplicitReturnType && |
| 3990 element.returnType.isDynamic) { |
| 3991 _errorReporter.reportErrorForNode( |
| 3992 StrongModeCode.IMPLICIT_DYNAMIC_RETURN, node, [element.displayName]); |
| 3993 } |
| 3994 } |
| 3995 |
| 3996 void _checkForImplicitDynamicType(TypeName node) { |
| 3997 if (_options.implicitDynamic || |
| 3998 node == null || |
| 3999 node.typeArguments != null) { |
| 4000 return; |
| 4001 } |
| 4002 DartType type = node.type; |
| 4003 if (type is ParameterizedType && |
| 4004 type.typeArguments.isNotEmpty && |
| 4005 type.typeArguments.any((t) => t.isDynamic)) { |
| 4006 _errorReporter.reportErrorForNode( |
| 4007 StrongModeCode.IMPLICIT_DYNAMIC_TYPE, node, [type]); |
| 4008 } |
| 4009 } |
| 4010 |
| 4011 void _checkForImplicitDynamicTypedLiteral(TypedLiteral node) { |
| 4012 if (_options.implicitDynamic || node.typeArguments != null) { |
| 4013 return; |
| 4014 } |
| 4015 DartType type = node.staticType; |
| 4016 // It's an error if either the key or value was inferred as dynamic. |
| 4017 if (type is InterfaceType && type.typeArguments.any((t) => t.isDynamic)) { |
| 4018 ErrorCode errorCode = node is ListLiteral |
| 4019 ? StrongModeCode.IMPLICIT_DYNAMIC_LIST_LITERAL |
| 4020 : StrongModeCode.IMPLICIT_DYNAMIC_MAP_LITERAL; |
| 4021 _errorReporter.reportErrorForNode(errorCode, node); |
| 4022 } |
| 4023 } |
| 4024 |
| 3472 /** | 4025 /** |
| 3473 * Verify that if the given [identifier] is part of a constructor initializer, | 4026 * Verify that if the given [identifier] is part of a constructor initializer, |
| 3474 * then it does not implicitly reference 'this' expression. | 4027 * then it does not implicitly reference 'this' expression. |
| 3475 * | 4028 * |
| 3476 * See [CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER], and | 4029 * See [CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER], and |
| 3477 * [CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FROM_STATIC]. | 4030 * [CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FROM_STATIC]. |
| 3478 * TODO(scheglov) rename thid method | 4031 * TODO(scheglov) rename thid method |
| 3479 */ | 4032 */ |
| 3480 bool _checkForImplicitThisReferenceInInitializer( | 4033 void _checkForImplicitThisReferenceInInitializer( |
| 3481 SimpleIdentifier identifier) { | 4034 SimpleIdentifier identifier) { |
| 3482 if (!_isInConstructorInitializer && | 4035 if (!_isInConstructorInitializer && |
| 3483 !_isInStaticMethod && | 4036 !_isInStaticMethod && |
| 3484 !_isInFactory && | 4037 !_isInFactory && |
| 3485 !_isInInstanceVariableInitializer && | 4038 !_isInInstanceVariableInitializer && |
| 3486 !_isInStaticVariableDeclaration) { | 4039 !_isInStaticVariableDeclaration) { |
| 3487 return false; | 4040 return; |
| 3488 } | 4041 } |
| 3489 // prepare element | 4042 // prepare element |
| 3490 Element element = identifier.staticElement; | 4043 Element element = identifier.staticElement; |
| 3491 if (!(element is MethodElement || element is PropertyAccessorElement)) { | 4044 if (!(element is MethodElement || element is PropertyAccessorElement)) { |
| 3492 return false; | 4045 return; |
| 3493 } | 4046 } |
| 3494 // static element | 4047 // static element |
| 3495 ExecutableElement executableElement = element as ExecutableElement; | 4048 ExecutableElement executableElement = element as ExecutableElement; |
| 3496 if (executableElement.isStatic) { | 4049 if (executableElement.isStatic) { |
| 3497 return false; | 4050 return; |
| 3498 } | 4051 } |
| 3499 // not a class member | 4052 // not a class member |
| 3500 Element enclosingElement = element.enclosingElement; | 4053 Element enclosingElement = element.enclosingElement; |
| 3501 if (enclosingElement is! ClassElement) { | 4054 if (enclosingElement is! ClassElement) { |
| 3502 return false; | 4055 return; |
| 3503 } | 4056 } |
| 3504 // comment | 4057 // comment |
| 3505 AstNode parent = identifier.parent; | 4058 AstNode parent = identifier.parent; |
| 3506 if (parent is CommentReference) { | 4059 if (parent is CommentReference) { |
| 3507 return false; | 4060 return; |
| 3508 } | 4061 } |
| 3509 // qualified method invocation | 4062 // qualified method invocation |
| 3510 if (parent is MethodInvocation) { | 4063 if (parent is MethodInvocation) { |
| 3511 MethodInvocation invocation = parent; | 4064 if (identical(parent.methodName, identifier) && |
| 3512 if (identical(invocation.methodName, identifier) && | 4065 parent.realTarget != null) { |
| 3513 invocation.realTarget != null) { | 4066 return; |
| 3514 return false; | |
| 3515 } | 4067 } |
| 3516 } | 4068 } |
| 3517 // qualified property access | 4069 // qualified property access |
| 3518 if (parent is PropertyAccess) { | 4070 if (parent is PropertyAccess) { |
| 3519 PropertyAccess access = parent; | 4071 if (identical(parent.propertyName, identifier) && |
| 3520 if (identical(access.propertyName, identifier) && | 4072 parent.realTarget != null) { |
| 3521 access.realTarget != null) { | 4073 return; |
| 3522 return false; | |
| 3523 } | 4074 } |
| 3524 } | 4075 } |
| 3525 if (parent is PrefixedIdentifier) { | 4076 if (parent is PrefixedIdentifier) { |
| 3526 PrefixedIdentifier prefixed = parent; | 4077 if (identical(parent.identifier, identifier)) { |
| 3527 if (identical(prefixed.identifier, identifier)) { | 4078 return; |
| 3528 return false; | |
| 3529 } | 4079 } |
| 3530 } | 4080 } |
| 3531 // report problem | 4081 |
| 3532 if (_isInStaticMethod) { | 4082 if (_isInStaticMethod) { |
| 3533 _errorReporter.reportErrorForNode( | 4083 _errorReporter.reportErrorForNode( |
| 3534 CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FROM_STATIC, identifier); | 4084 CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FROM_STATIC, identifier); |
| 3535 } else if (_isInFactory) { | 4085 } else if (_isInFactory) { |
| 3536 _errorReporter.reportErrorForNode( | 4086 _errorReporter.reportErrorForNode( |
| 3537 CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FROM_FACTORY, identifier); | 4087 CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FROM_FACTORY, identifier); |
| 3538 } else { | 4088 } else { |
| 3539 _errorReporter.reportErrorForNode( | 4089 _errorReporter.reportErrorForNode( |
| 3540 CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER, | 4090 CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER, |
| 3541 identifier); | 4091 identifier); |
| 3542 } | 4092 } |
| 3543 return true; | |
| 3544 } | 4093 } |
| 3545 | 4094 |
| 3546 /** | 4095 /** |
| 3547 * Verify that the given import [directive] has a unique name among other | 4096 * Verify that the given import [directive] has a unique name among other |
| 3548 * imported libraries. The [importElement] is the [ImportElement] retrieved | 4097 * imported libraries. The [importElement] is the [ImportElement] retrieved |
| 3549 * from the node, if the element in the node was `null`, then this method is | 4098 * from the node, if the element in the node was `null`, then this method is |
| 3550 * not called. | 4099 * not called. |
| 3551 * | 4100 * |
| 3552 * See [CompileTimeErrorCode.IMPORT_DUPLICATED_LIBRARY_NAME]. | 4101 * See [CompileTimeErrorCode.IMPORT_DUPLICATED_LIBRARY_NAME]. |
| 3553 */ | 4102 */ |
| 3554 bool _checkForImportDuplicateLibraryName( | 4103 void _checkForImportDuplicateLibraryName( |
| 3555 ImportDirective directive, ImportElement importElement) { | 4104 ImportDirective directive, ImportElement importElement) { |
| 3556 // prepare imported library | 4105 // prepare imported library |
| 3557 LibraryElement nodeLibrary = importElement.importedLibrary; | 4106 LibraryElement nodeLibrary = importElement.importedLibrary; |
| 3558 if (nodeLibrary == null) { | 4107 if (nodeLibrary == null) { |
| 3559 return false; | 4108 return; |
| 3560 } | 4109 } |
| 3561 String name = nodeLibrary.name; | 4110 String name = nodeLibrary.name; |
| 3562 // check if there is another imported library with the same name | 4111 // check if there is another imported library with the same name |
| 3563 LibraryElement prevLibrary = _nameToImportElement[name]; | 4112 LibraryElement prevLibrary = _nameToImportElement[name]; |
| 3564 if (prevLibrary != null) { | 4113 if (prevLibrary != null) { |
| 3565 if (prevLibrary != nodeLibrary) { | 4114 if (prevLibrary != nodeLibrary && !name.isEmpty) { |
| 3566 if (!name.isEmpty) { | 4115 _errorReporter.reportErrorForNode( |
| 3567 _errorReporter.reportErrorForNode( | 4116 StaticWarningCode.IMPORT_DUPLICATED_LIBRARY_NAMED, directive, [ |
| 3568 StaticWarningCode.IMPORT_DUPLICATED_LIBRARY_NAMED, directive, [ | 4117 prevLibrary.definingCompilationUnit.displayName, |
| 3569 prevLibrary.definingCompilationUnit.displayName, | 4118 nodeLibrary.definingCompilationUnit.displayName, |
| 3570 nodeLibrary.definingCompilationUnit.displayName, | 4119 name |
| 3571 name | 4120 ]); |
| 3572 ]); | |
| 3573 } | |
| 3574 return true; | |
| 3575 } | 4121 } |
| 3576 } else { | 4122 } else { |
| 3577 _nameToImportElement[name] = nodeLibrary; | 4123 _nameToImportElement[name] = nodeLibrary; |
| 3578 } | 4124 } |
| 3579 // OK | |
| 3580 return false; | |
| 3581 } | 4125 } |
| 3582 | 4126 |
| 3583 /** | 4127 /** |
| 3584 * Check that if the visiting library is not system, then any given library | 4128 * Check that if the visiting library is not system, then any given library |
| 3585 * should not be SDK internal library. The [importElement] is the | 4129 * should not be SDK internal library. The [importElement] is the |
| 3586 * [ImportElement] retrieved from the node, if the element in the node was | 4130 * [ImportElement] retrieved from the node, if the element in the node was |
| 3587 * `null`, then this method is not called | 4131 * `null`, then this method is not called |
| 3588 * | 4132 * |
| 3589 * See [CompileTimeErrorCode.IMPORT_INTERNAL_LIBRARY]. | 4133 * See [CompileTimeErrorCode.IMPORT_INTERNAL_LIBRARY]. |
| 3590 */ | 4134 */ |
| 3591 bool _checkForImportInternalLibrary( | 4135 void _checkForImportInternalLibrary( |
| 3592 ImportDirective directive, ImportElement importElement) { | 4136 ImportDirective directive, ImportElement importElement) { |
| 3593 if (_isInSystemLibrary) { | 4137 if (_isInSystemLibrary) { |
| 3594 return false; | 4138 return; |
| 3595 } | 4139 } |
| 3596 // should be private | 4140 // should be private |
| 3597 DartSdk sdk = _currentLibrary.context.sourceFactory.dartSdk; | 4141 DartSdk sdk = _currentLibrary.context.sourceFactory.dartSdk; |
| 3598 String uri = importElement.uri; | 4142 String uri = importElement.uri; |
| 3599 SdkLibrary sdkLibrary = sdk.getSdkLibrary(uri); | 4143 SdkLibrary sdkLibrary = sdk.getSdkLibrary(uri); |
| 3600 if (sdkLibrary == null) { | 4144 if (sdkLibrary == null || !sdkLibrary.isInternal) { |
| 3601 return false; | 4145 return; |
| 3602 } | 4146 } |
| 3603 if (!sdkLibrary.isInternal) { | 4147 |
| 3604 return false; | |
| 3605 } | |
| 3606 // report problem | |
| 3607 _errorReporter.reportErrorForNode( | 4148 _errorReporter.reportErrorForNode( |
| 3608 CompileTimeErrorCode.IMPORT_INTERNAL_LIBRARY, | 4149 CompileTimeErrorCode.IMPORT_INTERNAL_LIBRARY, |
| 3609 directive, | 4150 directive, |
| 3610 [directive.uri]); | 4151 [directive.uri]); |
| 3611 return true; | |
| 3612 } | 4152 } |
| 3613 | 4153 |
| 3614 /** | 4154 /** |
| 3615 * For each class declaration, this method is called which verifies that all | 4155 * For each class declaration, this method is called which verifies that all |
| 3616 * inherited members are inherited consistently. | 4156 * inherited members are inherited consistently. |
| 3617 * | 4157 * |
| 3618 * See [StaticTypeWarningCode.INCONSISTENT_METHOD_INHERITANCE]. | 4158 * See [StaticTypeWarningCode.INCONSISTENT_METHOD_INHERITANCE]. |
| 3619 */ | 4159 */ |
| 3620 bool _checkForInconsistentMethodInheritance() { | 4160 void _checkForInconsistentMethodInheritance() { |
| 3621 // Ensure that the inheritance manager has a chance to generate all errors | 4161 // Ensure that the inheritance manager has a chance to generate all errors |
| 3622 // we may care about, note that we ensure that the interfaces data since | 4162 // we may care about, note that we ensure that the interfaces data since |
| 3623 // there are no errors. | 4163 // there are no errors. |
| 3624 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(_enclosingClass); | 4164 _inheritanceManager.getMembersInheritedFromInterfaces(_enclosingClass); |
| 3625 HashSet<AnalysisError> errors = | 4165 Set<AnalysisError> errors = _inheritanceManager.getErrors(_enclosingClass); |
| 3626 _inheritanceManager.getErrors(_enclosingClass); | |
| 3627 if (errors == null || errors.isEmpty) { | 4166 if (errors == null || errors.isEmpty) { |
| 3628 return false; | 4167 return; |
| 3629 } | 4168 } |
| 3630 for (AnalysisError error in errors) { | 4169 for (AnalysisError error in errors) { |
| 3631 _errorReporter.reportError(error); | 4170 _errorReporter.reportError(error); |
| 3632 } | 4171 } |
| 3633 return true; | 4172 return; |
| 3634 } | 4173 } |
| 3635 | 4174 |
| 3636 /** | 4175 /** |
| 4176 * Check for a type mis-match between the iterable expression and the |
| 4177 * assigned variable in a for-in statement. |
| 4178 */ |
| 4179 void _checkForInIterable(ForEachStatement node) { |
| 4180 // Ignore malformed for statements. |
| 4181 if (node.identifier == null && node.loopVariable == null) { |
| 4182 return; |
| 4183 } |
| 4184 |
| 4185 DartType iterableType = getStaticType(node.iterable); |
| 4186 if (iterableType.isDynamic) { |
| 4187 return; |
| 4188 } |
| 4189 |
| 4190 // The type of the loop variable. |
| 4191 SimpleIdentifier variable = node.identifier ?? node.loopVariable.identifier; |
| 4192 DartType variableType = getStaticType(variable); |
| 4193 |
| 4194 DartType loopType = node.awaitKeyword != null |
| 4195 ? _typeProvider.streamType |
| 4196 : _typeProvider.iterableType; |
| 4197 |
| 4198 // Use an explicit string instead of [loopType] to remove the "<E>". |
| 4199 String loopTypeName = node.awaitKeyword != null ? "Stream" : "Iterable"; |
| 4200 |
| 4201 // The object being iterated has to implement Iterable<T> for some T that |
| 4202 // is assignable to the variable's type. |
| 4203 // TODO(rnystrom): Move this into mostSpecificTypeArgument()? |
| 4204 iterableType = iterableType.resolveToBound(_typeProvider.objectType); |
| 4205 DartType bestIterableType = |
| 4206 _typeSystem.mostSpecificTypeArgument(iterableType, loopType); |
| 4207 |
| 4208 // Allow it to be a supertype of Iterable<T> (basically just Object) and do |
| 4209 // an implicit downcast to Iterable<dynamic>. |
| 4210 if (bestIterableType == null) { |
| 4211 if (_typeSystem.isSubtypeOf(loopType, iterableType)) { |
| 4212 bestIterableType = DynamicTypeImpl.instance; |
| 4213 } |
| 4214 } |
| 4215 |
| 4216 if (bestIterableType == null) { |
| 4217 _errorReporter.reportTypeErrorForNode( |
| 4218 StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE, |
| 4219 node.iterable, |
| 4220 [iterableType, loopTypeName]); |
| 4221 } else if (!_typeSystem.isAssignableTo(bestIterableType, variableType)) { |
| 4222 _errorReporter.reportTypeErrorForNode( |
| 4223 StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, |
| 4224 node.iterable, |
| 4225 [iterableType, loopTypeName, variableType]); |
| 4226 } |
| 4227 } |
| 4228 |
| 4229 /** |
| 3637 * Check that the given [typeReference] is not a type reference and that then | 4230 * Check that the given [typeReference] is not a type reference and that then |
| 3638 * the [name] is reference to an instance member. | 4231 * the [name] is reference to an instance member. |
| 3639 * | 4232 * |
| 3640 * See [StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER]. | 4233 * See [StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER]. |
| 3641 */ | 4234 */ |
| 3642 bool _checkForInstanceAccessToStaticMember( | 4235 void _checkForInstanceAccessToStaticMember( |
| 3643 ClassElement typeReference, SimpleIdentifier name) { | 4236 ClassElement typeReference, SimpleIdentifier name) { |
| 3644 // OK, in comment | 4237 // OK, in comment |
| 3645 if (_isInComment) { | 4238 if (_isInComment) { |
| 3646 return false; | 4239 return; |
| 3647 } | 4240 } |
| 3648 // OK, target is a type | 4241 // OK, target is a type |
| 3649 if (typeReference != null) { | 4242 if (typeReference != null) { |
| 3650 return false; | 4243 return; |
| 3651 } | 4244 } |
| 3652 // prepare member Element | 4245 // prepare member Element |
| 3653 Element element = name.staticElement; | 4246 Element element = name.staticElement; |
| 3654 if (element is! ExecutableElement) { | 4247 if (element is ExecutableElement) { |
| 3655 return false; | 4248 // OK, top-level element |
| 4249 if (element.enclosingElement is! ClassElement) { |
| 4250 return; |
| 4251 } |
| 4252 // OK, instance member |
| 4253 if (!element.isStatic) { |
| 4254 return; |
| 4255 } |
| 4256 _errorReporter.reportErrorForNode( |
| 4257 StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER, |
| 4258 name, |
| 4259 [name.name]); |
| 3656 } | 4260 } |
| 3657 ExecutableElement executableElement = element as ExecutableElement; | |
| 3658 // OK, top-level element | |
| 3659 if (executableElement.enclosingElement is! ClassElement) { | |
| 3660 return false; | |
| 3661 } | |
| 3662 // OK, instance member | |
| 3663 if (!executableElement.isStatic) { | |
| 3664 return false; | |
| 3665 } | |
| 3666 // report problem | |
| 3667 _errorReporter.reportErrorForNode( | |
| 3668 StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER, | |
| 3669 name, | |
| 3670 [name.name]); | |
| 3671 return true; | |
| 3672 } | 4261 } |
| 3673 | 4262 |
| 3674 /** | 4263 /** |
| 3675 * Check whether the given [executableElement] collides with the name of a | 4264 * Check whether the given [executableElement] collides with the name of a |
| 3676 * static method in one of its superclasses, and reports the appropriate | 4265 * static method in one of its superclasses, and reports the appropriate |
| 3677 * warning if it does. The [errorNameTarget] is the node to report problems | 4266 * warning if it does. The [errorNameTarget] is the node to report problems |
| 3678 * on. | 4267 * on. |
| 3679 * | 4268 * |
| 3680 * See [StaticTypeWarningCode.INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_ST
ATIC]. | 4269 * See [StaticTypeWarningCode.INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_ST
ATIC]. |
| 3681 */ | 4270 */ |
| 3682 bool _checkForInstanceMethodNameCollidesWithSuperclassStatic( | 4271 bool _checkForInstanceMethodNameCollidesWithSuperclassStatic( |
| 3683 ExecutableElement executableElement, SimpleIdentifier errorNameTarget) { | 4272 ExecutableElement executableElement, SimpleIdentifier errorNameTarget) { |
| 3684 String executableElementName = executableElement.name; | 4273 String executableElementName = executableElement.name; |
| 3685 if (executableElement is! PropertyAccessorElement && | 4274 if (executableElement is! PropertyAccessorElement && |
| 3686 !executableElement.isOperator) { | 4275 !executableElement.isOperator) { |
| 3687 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>(); | 4276 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>(); |
| 3688 InterfaceType superclassType = _enclosingClass.supertype; | 4277 InterfaceType superclassType = _enclosingClass.supertype; |
| 3689 ClassElement superclassElement = | 4278 ClassElement superclassElement = superclassType?.element; |
| 3690 superclassType == null ? null : superclassType.element; | |
| 3691 bool executableElementPrivate = | 4279 bool executableElementPrivate = |
| 3692 Identifier.isPrivateName(executableElementName); | 4280 Identifier.isPrivateName(executableElementName); |
| 3693 while (superclassElement != null && | 4281 while (superclassElement != null && |
| 3694 !visitedClasses.contains(superclassElement)) { | 4282 !visitedClasses.contains(superclassElement)) { |
| 3695 visitedClasses.add(superclassElement); | 4283 visitedClasses.add(superclassElement); |
| 3696 LibraryElement superclassLibrary = superclassElement.library; | 4284 LibraryElement superclassLibrary = superclassElement.library; |
| 3697 // Check fields. | 4285 // Check fields. |
| 3698 FieldElement fieldElt = | 4286 FieldElement fieldElt = |
| 3699 superclassElement.getField(executableElementName); | 4287 superclassElement.getField(executableElementName); |
| 3700 if (fieldElt != null) { | 4288 if (fieldElt != null) { |
| 3701 // Ignore if private in a different library - cannot collide. | 4289 // Ignore if private in a different library - cannot collide. |
| 3702 if (executableElementPrivate && | 4290 if (executableElementPrivate && |
| 3703 _currentLibrary != superclassLibrary) { | 4291 _currentLibrary != superclassLibrary) { |
| 3704 continue; | 4292 continue; |
| 3705 } | 4293 } |
| 3706 // instance vs. static | 4294 // instance vs. static |
| 3707 if (fieldElt.isStatic) { | 4295 if (fieldElt.isStatic) { |
| 3708 _errorReporter.reportErrorForNode( | 4296 _errorReporter.reportErrorForNode( |
| 3709 StaticWarningCode.INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_
STATIC, | 4297 StaticWarningCode |
| 4298 .INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_STATIC, |
| 3710 errorNameTarget, | 4299 errorNameTarget, |
| 3711 [executableElementName, fieldElt.enclosingElement.displayName]); | 4300 [executableElementName, fieldElt.enclosingElement.displayName]); |
| 3712 return true; | 4301 return true; |
| 3713 } | 4302 } |
| 3714 } | 4303 } |
| 3715 // Check methods. | 4304 // Check methods. |
| 3716 List<MethodElement> methodElements = superclassElement.methods; | 4305 List<MethodElement> methodElements = superclassElement.methods; |
| 3717 for (MethodElement methodElement in methodElements) { | 4306 int length = methodElements.length; |
| 4307 for (int i = 0; i < length; i++) { |
| 4308 MethodElement methodElement = methodElements[i]; |
| 3718 // We need the same name. | 4309 // We need the same name. |
| 3719 if (methodElement.name != executableElementName) { | 4310 if (methodElement.name != executableElementName) { |
| 3720 continue; | 4311 continue; |
| 3721 } | 4312 } |
| 3722 // Ignore if private in a different library - cannot collide. | 4313 // Ignore if private in a different library - cannot collide. |
| 3723 if (executableElementPrivate && | 4314 if (executableElementPrivate && |
| 3724 _currentLibrary != superclassLibrary) { | 4315 _currentLibrary != superclassLibrary) { |
| 3725 continue; | 4316 continue; |
| 3726 } | 4317 } |
| 3727 // instance vs. static | 4318 // instance vs. static |
| 3728 if (methodElement.isStatic) { | 4319 if (methodElement.isStatic) { |
| 3729 _errorReporter.reportErrorForNode( | 4320 _errorReporter.reportErrorForNode( |
| 3730 StaticWarningCode.INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_
STATIC, | 4321 StaticWarningCode |
| 3731 errorNameTarget, [ | 4322 .INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_STATIC, |
| 3732 executableElementName, | 4323 errorNameTarget, |
| 3733 methodElement.enclosingElement.displayName | 4324 [ |
| 3734 ]); | 4325 executableElementName, |
| 4326 methodElement.enclosingElement.displayName |
| 4327 ]); |
| 3735 return true; | 4328 return true; |
| 3736 } | 4329 } |
| 3737 } | 4330 } |
| 3738 superclassType = superclassElement.supertype; | 4331 superclassType = superclassElement.supertype; |
| 3739 superclassElement = | 4332 superclassElement = superclassType?.element; |
| 3740 superclassType == null ? null : superclassType.element; | |
| 3741 } | 4333 } |
| 3742 } | 4334 } |
| 3743 return false; | 4335 return false; |
| 3744 } | 4336 } |
| 3745 | 4337 |
| 3746 /** | 4338 /** |
| 3747 * Verify that an 'int' can be assigned to the parameter corresponding to the | 4339 * Verify that an 'int' can be assigned to the parameter corresponding to the |
| 3748 * given [argument]. This is used for prefix and postfix expressions where | 4340 * given [argument]. This is used for prefix and postfix expressions where |
| 3749 * the argument value is implicit. | 4341 * the argument value is implicit. |
| 3750 * | 4342 * |
| 3751 * See [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]. | 4343 * See [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]. |
| 3752 */ | 4344 */ |
| 3753 bool _checkForIntNotAssignable(Expression argument) { | 4345 void _checkForIntNotAssignable(Expression argument) { |
| 3754 if (argument == null) { | 4346 if (argument == null) { |
| 3755 return false; | 4347 return; |
| 3756 } | 4348 } |
| 3757 ParameterElement staticParameterElement = argument.staticParameterElement; | 4349 ParameterElement staticParameterElement = argument.staticParameterElement; |
| 3758 DartType staticParameterType = | 4350 DartType staticParameterType = staticParameterElement?.type; |
| 3759 staticParameterElement == null ? null : staticParameterElement.type; | 4351 _checkForArgumentTypeNotAssignable(argument, staticParameterType, _intType, |
| 3760 return _checkForArgumentTypeNotAssignable(argument, staticParameterType, | 4352 StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE); |
| 3761 _intType, StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE); | |
| 3762 } | 4353 } |
| 3763 | 4354 |
| 3764 /** | 4355 /** |
| 3765 * Verify that the given [annotation] isn't defined in a deferred library. | 4356 * Verify that the given [annotation] isn't defined in a deferred library. |
| 3766 * | 4357 * |
| 3767 * See [CompileTimeErrorCode.INVALID_ANNOTATION_FROM_DEFERRED_LIBRARY]. | 4358 * See [CompileTimeErrorCode.INVALID_ANNOTATION_FROM_DEFERRED_LIBRARY]. |
| 3768 */ | 4359 */ |
| 3769 bool _checkForInvalidAnnotationFromDeferredLibrary(Annotation annotation) { | 4360 void _checkForInvalidAnnotationFromDeferredLibrary(Annotation annotation) { |
| 3770 Identifier nameIdentifier = annotation.name; | 4361 Identifier nameIdentifier = annotation.name; |
| 3771 if (nameIdentifier is PrefixedIdentifier) { | 4362 if (nameIdentifier is PrefixedIdentifier && nameIdentifier.isDeferred) { |
| 3772 if (nameIdentifier.isDeferred) { | 4363 _errorReporter.reportErrorForNode( |
| 3773 _errorReporter.reportErrorForNode( | 4364 CompileTimeErrorCode.INVALID_ANNOTATION_FROM_DEFERRED_LIBRARY, |
| 3774 CompileTimeErrorCode.INVALID_ANNOTATION_FROM_DEFERRED_LIBRARY, | 4365 annotation.name); |
| 3775 annotation.name); | |
| 3776 return true; | |
| 3777 } | |
| 3778 } | 4366 } |
| 3779 return false; | |
| 3780 } | 4367 } |
| 3781 | 4368 |
| 3782 /** | 4369 /** |
| 3783 * Verify that the given left hand side ([lhs]) and right hand side ([rhs]) | 4370 * Verify that the given left hand side ([lhs]) and right hand side ([rhs]) |
| 3784 * represent a valid assignment. | 4371 * represent a valid assignment. |
| 3785 * | 4372 * |
| 3786 * See [StaticTypeWarningCode.INVALID_ASSIGNMENT]. | 4373 * See [StaticTypeWarningCode.INVALID_ASSIGNMENT]. |
| 3787 */ | 4374 */ |
| 3788 bool _checkForInvalidAssignment(Expression lhs, Expression rhs) { | 4375 void _checkForInvalidAssignment(Expression lhs, Expression rhs) { |
| 3789 if (lhs == null || rhs == null) { | 4376 if (lhs == null || rhs == null) { |
| 3790 return false; | 4377 return; |
| 3791 } | 4378 } |
| 3792 VariableElement leftVariableElement = getVariableElement(lhs); | 4379 VariableElement leftVariableElement = getVariableElement(lhs); |
| 3793 DartType leftType = (leftVariableElement == null) | 4380 DartType leftType = (leftVariableElement == null) |
| 3794 ? getStaticType(lhs) | 4381 ? getStaticType(lhs) |
| 3795 : leftVariableElement.type; | 4382 : leftVariableElement.type; |
| 3796 DartType staticRightType = getStaticType(rhs); | 4383 _checkForAssignableExpression( |
| 3797 if (!_typeSystem.isAssignableTo(staticRightType, leftType)) { | 4384 rhs, leftType, StaticTypeWarningCode.INVALID_ASSIGNMENT); |
| 3798 _errorReporter.reportTypeErrorForNode( | |
| 3799 StaticTypeWarningCode.INVALID_ASSIGNMENT, | |
| 3800 rhs, | |
| 3801 [staticRightType, leftType]); | |
| 3802 return true; | |
| 3803 } | |
| 3804 return false; | |
| 3805 } | 4385 } |
| 3806 | 4386 |
| 3807 /** | 4387 /** |
| 3808 * Given an [assignment] using a compound assignment operator, this verifies | 4388 * Given an [assignment] using a compound assignment operator, this verifies |
| 3809 * that the given assignment is valid. The [lhs] is the left hand side | 4389 * that the given assignment is valid. The [lhs] is the left hand side |
| 3810 * expression. The [rhs] is the right hand side expression. | 4390 * expression. The [rhs] is the right hand side expression. |
| 3811 * | 4391 * |
| 3812 * See [StaticTypeWarningCode.INVALID_ASSIGNMENT]. | 4392 * See [StaticTypeWarningCode.INVALID_ASSIGNMENT]. |
| 3813 */ | 4393 */ |
| 3814 bool _checkForInvalidCompoundAssignment( | 4394 void _checkForInvalidCompoundAssignment( |
| 3815 AssignmentExpression assignment, Expression lhs, Expression rhs) { | 4395 AssignmentExpression assignment, Expression lhs, Expression rhs) { |
| 3816 if (lhs == null) { | 4396 if (lhs == null) { |
| 3817 return false; | 4397 return; |
| 3818 } | 4398 } |
| 3819 VariableElement leftVariableElement = getVariableElement(lhs); | 4399 DartType leftType = getStaticType(lhs); |
| 3820 DartType leftType = (leftVariableElement == null) | 4400 DartType rightType = getStaticType(assignment); |
| 3821 ? getStaticType(lhs) | |
| 3822 : leftVariableElement.type; | |
| 3823 MethodElement invokedMethod = assignment.staticElement; | |
| 3824 if (invokedMethod == null) { | |
| 3825 return false; | |
| 3826 } | |
| 3827 DartType rightType = invokedMethod.type.returnType; | |
| 3828 if (leftType == null || rightType == null) { | |
| 3829 return false; | |
| 3830 } | |
| 3831 if (!_typeSystem.isAssignableTo(rightType, leftType)) { | 4401 if (!_typeSystem.isAssignableTo(rightType, leftType)) { |
| 3832 _errorReporter.reportTypeErrorForNode( | 4402 _errorReporter.reportTypeErrorForNode( |
| 3833 StaticTypeWarningCode.INVALID_ASSIGNMENT, rhs, [rightType, leftType]); | 4403 StaticTypeWarningCode.INVALID_ASSIGNMENT, rhs, [rightType, leftType]); |
| 3834 return true; | |
| 3835 } | 4404 } |
| 3836 return false; | |
| 3837 } | 4405 } |
| 3838 | 4406 |
| 3839 /** | 4407 /** |
| 3840 * Check the given [initializer] to ensure that the field being initialized is | 4408 * Check the given [initializer] to ensure that the field being initialized is |
| 3841 * a valid field. The [fieldName] is the field name from the | 4409 * a valid field. The [fieldName] is the field name from the |
| 3842 * [ConstructorFieldInitializer]. The [staticElement] is the static element | 4410 * [ConstructorFieldInitializer]. The [staticElement] is the static element |
| 3843 * from the name in the [ConstructorFieldInitializer]. | 4411 * from the name in the [ConstructorFieldInitializer]. |
| 3844 */ | 4412 */ |
| 3845 void _checkForInvalidField(ConstructorFieldInitializer initializer, | 4413 void _checkForInvalidField(ConstructorFieldInitializer initializer, |
| 3846 SimpleIdentifier fieldName, Element staticElement) { | 4414 SimpleIdentifier fieldName, Element staticElement) { |
| 3847 if (staticElement is FieldElement) { | 4415 if (staticElement is FieldElement) { |
| 3848 FieldElement fieldElement = staticElement; | 4416 if (staticElement.isSynthetic) { |
| 3849 if (fieldElement.isSynthetic) { | |
| 3850 _errorReporter.reportErrorForNode( | 4417 _errorReporter.reportErrorForNode( |
| 3851 CompileTimeErrorCode.INITIALIZER_FOR_NON_EXISTENT_FIELD, | 4418 CompileTimeErrorCode.INITIALIZER_FOR_NON_EXISTENT_FIELD, |
| 3852 initializer, | 4419 initializer, |
| 3853 [fieldName]); | 4420 [fieldName]); |
| 3854 } else if (fieldElement.isStatic) { | 4421 } else if (staticElement.isStatic) { |
| 3855 _errorReporter.reportErrorForNode( | 4422 _errorReporter.reportErrorForNode( |
| 3856 CompileTimeErrorCode.INITIALIZER_FOR_STATIC_FIELD, | 4423 CompileTimeErrorCode.INITIALIZER_FOR_STATIC_FIELD, |
| 3857 initializer, | 4424 initializer, |
| 3858 [fieldName]); | 4425 [fieldName]); |
| 3859 } | 4426 } |
| 3860 } else { | 4427 } else { |
| 3861 _errorReporter.reportErrorForNode( | 4428 _errorReporter.reportErrorForNode( |
| 3862 CompileTimeErrorCode.INITIALIZER_FOR_NON_EXISTENT_FIELD, | 4429 CompileTimeErrorCode.INITIALIZER_FOR_NON_EXISTENT_FIELD, |
| 3863 initializer, | 4430 initializer, |
| 3864 [fieldName]); | 4431 [fieldName]); |
| 3865 return; | 4432 return; |
| 3866 } | 4433 } |
| 3867 } | 4434 } |
| 3868 | 4435 |
| 3869 /** | 4436 /** |
| 3870 * Check to see whether the given function [body] has a modifier associated | 4437 * Check to see whether the given function [body] has a modifier associated |
| 3871 * with it, and report it as an error if it does. | 4438 * with it, and report it as an error if it does. |
| 3872 */ | 4439 */ |
| 3873 bool _checkForInvalidModifierOnBody( | 4440 void _checkForInvalidModifierOnBody( |
| 3874 FunctionBody body, CompileTimeErrorCode errorCode) { | 4441 FunctionBody body, CompileTimeErrorCode errorCode) { |
| 3875 sc.Token keyword = body.keyword; | 4442 Token keyword = body.keyword; |
| 3876 if (keyword != null) { | 4443 if (keyword != null) { |
| 3877 _errorReporter.reportErrorForToken(errorCode, keyword, [keyword.lexeme]); | 4444 _errorReporter.reportErrorForToken(errorCode, keyword, [keyword.lexeme]); |
| 3878 return true; | |
| 3879 } | 4445 } |
| 3880 return false; | |
| 3881 } | 4446 } |
| 3882 | 4447 |
| 3883 /** | 4448 /** |
| 3884 * Verify that the usage of the given 'this' is valid. | 4449 * Verify that the usage of the given 'this' is valid. |
| 3885 * | 4450 * |
| 3886 * See [CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS]. | 4451 * See [CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS]. |
| 3887 */ | 4452 */ |
| 3888 bool _checkForInvalidReferenceToThis(ThisExpression expression) { | 4453 void _checkForInvalidReferenceToThis(ThisExpression expression) { |
| 3889 if (!_isThisInValidContext(expression)) { | 4454 if (!_isThisInValidContext(expression)) { |
| 3890 _errorReporter.reportErrorForNode( | 4455 _errorReporter.reportErrorForNode( |
| 3891 CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS, expression); | 4456 CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS, expression); |
| 3892 return true; | |
| 3893 } | 4457 } |
| 3894 return false; | |
| 3895 } | 4458 } |
| 3896 | 4459 |
| 3897 /** | 4460 /** |
| 3898 * Checks to ensure that the given list of type [arguments] does not have a | 4461 * Checks to ensure that the given list of type [arguments] does not have a |
| 3899 * type parameter as a type argument. The [errorCode] is either | 4462 * type parameter as a type argument. The [errorCode] is either |
| 3900 * [CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_LIST] or | 4463 * [CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_LIST] or |
| 3901 * [CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP]. | 4464 * [CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP]. |
| 3902 */ | 4465 */ |
| 3903 bool _checkForInvalidTypeArgumentInConstTypedLiteral( | 4466 void _checkForInvalidTypeArgumentInConstTypedLiteral( |
| 3904 NodeList<TypeName> arguments, ErrorCode errorCode) { | 4467 NodeList<TypeName> arguments, ErrorCode errorCode) { |
| 3905 bool foundError = false; | |
| 3906 for (TypeName typeName in arguments) { | 4468 for (TypeName typeName in arguments) { |
| 3907 if (typeName.type is TypeParameterType) { | 4469 if (typeName.type is TypeParameterType) { |
| 3908 _errorReporter.reportErrorForNode(errorCode, typeName, [typeName.name]); | 4470 _errorReporter.reportErrorForNode(errorCode, typeName, [typeName.name]); |
| 3909 foundError = true; | |
| 3910 } | 4471 } |
| 3911 } | 4472 } |
| 3912 return foundError; | |
| 3913 } | 4473 } |
| 3914 | 4474 |
| 3915 /** | 4475 /** |
| 3916 * Verify that the elements given list [literal] are subtypes of the specified | 4476 * Verify that the elements given list [literal] are subtypes of the list's |
| 3917 * element type. The [typeArguments] are the type arguments. | 4477 * static type. |
| 3918 * | 4478 * |
| 3919 * See [CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE], and | 4479 * See [CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE], and |
| 3920 * [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]. | 4480 * [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]. |
| 3921 */ | 4481 */ |
| 3922 bool _checkForListElementTypeNotAssignable( | 4482 void _checkForListElementTypeNotAssignable(ListLiteral literal) { |
| 3923 ListLiteral literal, TypeArgumentList typeArguments) { | 4483 // Determine the list's element type. We base this on the static type and |
| 3924 NodeList<TypeName> typeNames = typeArguments.arguments; | 4484 // not the literal's type arguments because in strong mode, the type |
| 3925 if (typeNames.length < 1) { | 4485 // arguments may be inferred. |
| 3926 return false; | 4486 DartType listType = literal.staticType; |
| 3927 } | 4487 assert(listType is InterfaceTypeImpl); |
| 3928 DartType listElementType = typeNames[0].type; | 4488 |
| 4489 List<DartType> typeArguments = |
| 4490 (listType as InterfaceTypeImpl).typeArguments; |
| 4491 assert(typeArguments.length == 1); |
| 4492 |
| 4493 DartType listElementType = typeArguments[0]; |
| 4494 |
| 3929 // Check every list element. | 4495 // Check every list element. |
| 3930 bool hasProblems = false; | |
| 3931 for (Expression element in literal.elements) { | 4496 for (Expression element in literal.elements) { |
| 3932 if (literal.constKeyword != null) { | 4497 if (literal.constKeyword != null) { |
| 3933 // TODO(paulberry): this error should be based on the actual type of the | 4498 // TODO(paulberry): this error should be based on the actual type of the |
| 3934 // list element, not the static type. See dartbug.com/21119. | 4499 // list element, not the static type. See dartbug.com/21119. |
| 3935 if (_checkForArgumentTypeNotAssignableWithExpectedTypes( | 4500 _checkForArgumentTypeNotAssignableWithExpectedTypes( |
| 3936 element, | 4501 element, |
| 3937 listElementType, | 4502 listElementType, |
| 3938 CheckedModeCompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE)) { | 4503 CheckedModeCompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE); |
| 3939 hasProblems = true; | |
| 3940 } | |
| 3941 } | 4504 } |
| 3942 if (_checkForArgumentTypeNotAssignableWithExpectedTypes( | 4505 _checkForArgumentTypeNotAssignableWithExpectedTypes(element, |
| 3943 element, | 4506 listElementType, StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE); |
| 3944 listElementType, | |
| 3945 StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE)) { | |
| 3946 hasProblems = true; | |
| 3947 } | |
| 3948 } | 4507 } |
| 3949 return hasProblems; | |
| 3950 } | 4508 } |
| 3951 | 4509 |
| 3952 /** | 4510 /** |
| 3953 * Verify that the key/value of entries of the given map [literal] are | 4511 * Verify that the key/value of entries of the given map [literal] are |
| 3954 * subtypes of the key/value types specified in the type arguments. The | 4512 * subtypes of the map's static type. |
| 3955 * [typeArguments] are the type arguments. | |
| 3956 * | 4513 * |
| 3957 * See [CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE], | 4514 * See [CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE], |
| 3958 * [CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE], | 4515 * [CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE], |
| 3959 * [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE], and | 4516 * [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE], and |
| 3960 * [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]. | 4517 * [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]. |
| 3961 */ | 4518 */ |
| 3962 bool _checkForMapTypeNotAssignable( | 4519 void _checkForMapTypeNotAssignable(MapLiteral literal) { |
| 3963 MapLiteral literal, TypeArgumentList typeArguments) { | 4520 // Determine the map's key and value types. We base this on the static type |
| 3964 // Prepare maps key/value types. | 4521 // and not the literal's type arguments because in strong mode, the type |
| 3965 NodeList<TypeName> typeNames = typeArguments.arguments; | 4522 // arguments may be inferred. |
| 3966 if (typeNames.length < 2) { | 4523 DartType mapType = literal.staticType; |
| 3967 return false; | 4524 assert(mapType is InterfaceTypeImpl); |
| 3968 } | 4525 |
| 3969 DartType keyType = typeNames[0].type; | 4526 List<DartType> typeArguments = (mapType as InterfaceTypeImpl).typeArguments; |
| 3970 DartType valueType = typeNames[1].type; | 4527 assert(typeArguments.length == 2); |
| 3971 // Check every map entry. | 4528 DartType keyType = typeArguments[0]; |
| 3972 bool hasProblems = false; | 4529 DartType valueType = typeArguments[1]; |
| 4530 |
| 3973 NodeList<MapLiteralEntry> entries = literal.entries; | 4531 NodeList<MapLiteralEntry> entries = literal.entries; |
| 3974 for (MapLiteralEntry entry in entries) { | 4532 for (MapLiteralEntry entry in entries) { |
| 3975 Expression key = entry.key; | 4533 Expression key = entry.key; |
| 3976 Expression value = entry.value; | 4534 Expression value = entry.value; |
| 3977 if (literal.constKeyword != null) { | 4535 if (literal.constKeyword != null) { |
| 3978 // TODO(paulberry): this error should be based on the actual type of the | 4536 // TODO(paulberry): this error should be based on the actual type of the |
| 3979 // list element, not the static type. See dartbug.com/21119. | 4537 // list element, not the static type. See dartbug.com/21119. |
| 3980 if (_checkForArgumentTypeNotAssignableWithExpectedTypes(key, keyType, | 4538 _checkForArgumentTypeNotAssignableWithExpectedTypes(key, keyType, |
| 3981 CheckedModeCompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE)) { | 4539 CheckedModeCompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE); |
| 3982 hasProblems = true; | 4540 _checkForArgumentTypeNotAssignableWithExpectedTypes(value, valueType, |
| 3983 } | 4541 CheckedModeCompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE); |
| 3984 if (_checkForArgumentTypeNotAssignableWithExpectedTypes( | |
| 3985 value, | |
| 3986 valueType, | |
| 3987 CheckedModeCompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE)) { | |
| 3988 hasProblems = true; | |
| 3989 } | |
| 3990 } | 4542 } |
| 3991 if (_checkForArgumentTypeNotAssignableWithExpectedTypes( | 4543 _checkForArgumentTypeNotAssignableWithExpectedTypes( |
| 3992 key, keyType, StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE)) { | 4544 key, keyType, StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE); |
| 3993 hasProblems = true; | 4545 _checkForArgumentTypeNotAssignableWithExpectedTypes( |
| 3994 } | 4546 value, valueType, StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE); |
| 3995 if (_checkForArgumentTypeNotAssignableWithExpectedTypes( | |
| 3996 value, valueType, StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE)) { | |
| 3997 hasProblems = true; | |
| 3998 } | |
| 3999 } | 4547 } |
| 4000 return hasProblems; | |
| 4001 } | 4548 } |
| 4002 | 4549 |
| 4003 /** | 4550 /** |
| 4004 * Verify that the [_enclosingClass] does not define members with the same nam
e | 4551 * Verify that the [_enclosingClass] does not define members with the same nam
e |
| 4005 * as the enclosing class. | 4552 * as the enclosing class. |
| 4006 * | 4553 * |
| 4007 * See [CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME]. | 4554 * See [CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME]. |
| 4008 */ | 4555 */ |
| 4009 bool _checkForMemberWithClassName() { | 4556 void _checkForMemberWithClassName() { |
| 4010 if (_enclosingClass == null) { | 4557 if (_enclosingClass == null) { |
| 4011 return false; | 4558 return; |
| 4012 } | 4559 } |
| 4013 String className = _enclosingClass.name; | 4560 String className = _enclosingClass.name; |
| 4014 if (className == null) { | 4561 if (className == null) { |
| 4015 return false; | 4562 return; |
| 4016 } | 4563 } |
| 4017 bool problemReported = false; | 4564 |
| 4018 // check accessors | 4565 // check accessors |
| 4019 for (PropertyAccessorElement accessor in _enclosingClass.accessors) { | 4566 for (PropertyAccessorElement accessor in _enclosingClass.accessors) { |
| 4020 if (className == accessor.name) { | 4567 if (className == accessor.name) { |
| 4021 _errorReporter.reportErrorForElement( | 4568 _errorReporter.reportErrorForElement( |
| 4022 CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME, accessor); | 4569 CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME, accessor); |
| 4023 problemReported = true; | |
| 4024 } | 4570 } |
| 4025 } | 4571 } |
| 4026 // don't check methods, they would be constructors | 4572 // don't check methods, they would be constructors |
| 4027 // done | |
| 4028 return problemReported; | |
| 4029 } | 4573 } |
| 4030 | 4574 |
| 4031 /** | 4575 /** |
| 4032 * Check to make sure that all similarly typed accessors are of the same type | 4576 * Check to make sure that all similarly typed accessors are of the same type |
| 4033 * (including inherited accessors). | 4577 * (including inherited accessors). |
| 4034 * | 4578 * |
| 4035 * See [StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES], and | 4579 * See [StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES], and |
| 4036 * [StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES_FROM_SUPERTYPE]. | 4580 * [StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES_FROM_SUPERTYPE]. |
| 4037 */ | 4581 */ |
| 4038 bool _checkForMismatchedAccessorTypes( | 4582 void _checkForMismatchedAccessorTypes( |
| 4039 Declaration accessorDeclaration, String accessorTextName) { | 4583 Declaration accessorDeclaration, String accessorTextName) { |
| 4040 ExecutableElement accessorElement = | 4584 ExecutableElement accessorElement = |
| 4041 accessorDeclaration.element as ExecutableElement; | 4585 accessorDeclaration.element as ExecutableElement; |
| 4042 if (accessorElement is! PropertyAccessorElement) { | 4586 if (accessorElement is PropertyAccessorElement) { |
| 4043 return false; | 4587 PropertyAccessorElement counterpartAccessor = null; |
| 4044 } | 4588 ClassElement enclosingClassForCounterpart = null; |
| 4045 PropertyAccessorElement propertyAccessorElement = | 4589 if (accessorElement.isGetter) { |
| 4046 accessorElement as PropertyAccessorElement; | 4590 counterpartAccessor = accessorElement.correspondingSetter; |
| 4047 PropertyAccessorElement counterpartAccessor = null; | 4591 } else { |
| 4048 ClassElement enclosingClassForCounterpart = null; | 4592 counterpartAccessor = accessorElement.correspondingGetter; |
| 4049 if (propertyAccessorElement.isGetter) { | 4593 // If the setter and getter are in the same enclosing element, return, |
| 4050 counterpartAccessor = propertyAccessorElement.correspondingSetter; | 4594 // this prevents having MISMATCHED_GETTER_AND_SETTER_TYPES reported twic
e. |
| 4051 } else { | 4595 if (counterpartAccessor != null && |
| 4052 counterpartAccessor = propertyAccessorElement.correspondingGetter; | 4596 identical(counterpartAccessor.enclosingElement, |
| 4053 // If the setter and getter are in the same enclosing element, return, | 4597 accessorElement.enclosingElement)) { |
| 4054 // this prevents having MISMATCHED_GETTER_AND_SETTER_TYPES reported twice. | 4598 return; |
| 4055 if (counterpartAccessor != null && | |
| 4056 identical(counterpartAccessor.enclosingElement, | |
| 4057 propertyAccessorElement.enclosingElement)) { | |
| 4058 return false; | |
| 4059 } | |
| 4060 } | |
| 4061 if (counterpartAccessor == null) { | |
| 4062 // If the accessor is declared in a class, check the superclasses. | |
| 4063 if (_enclosingClass != null) { | |
| 4064 // Figure out the correct identifier to lookup in the inheritance graph, | |
| 4065 // if 'x', then 'x=', or if 'x=', then 'x'. | |
| 4066 String lookupIdentifier = propertyAccessorElement.name; | |
| 4067 if (StringUtilities.endsWithChar(lookupIdentifier, 0x3D)) { | |
| 4068 lookupIdentifier = | |
| 4069 lookupIdentifier.substring(0, lookupIdentifier.length - 1); | |
| 4070 } else { | |
| 4071 lookupIdentifier += "="; | |
| 4072 } | |
| 4073 // lookup with the identifier. | |
| 4074 ExecutableElement elementFromInheritance = _inheritanceManager | |
| 4075 .lookupInheritance(_enclosingClass, lookupIdentifier); | |
| 4076 // Verify that we found something, and that it is an accessor | |
| 4077 if (elementFromInheritance != null && | |
| 4078 elementFromInheritance is PropertyAccessorElement) { | |
| 4079 enclosingClassForCounterpart = | |
| 4080 elementFromInheritance.enclosingElement as ClassElement; | |
| 4081 counterpartAccessor = elementFromInheritance; | |
| 4082 } | 4599 } |
| 4083 } | 4600 } |
| 4084 if (counterpartAccessor == null) { | 4601 if (counterpartAccessor == null) { |
| 4085 return false; | 4602 // If the accessor is declared in a class, check the superclasses. |
| 4603 if (_enclosingClass != null) { |
| 4604 // Figure out the correct identifier to lookup in the inheritance grap
h, |
| 4605 // if 'x', then 'x=', or if 'x=', then 'x'. |
| 4606 String lookupIdentifier = accessorElement.name; |
| 4607 if (StringUtilities.endsWithChar(lookupIdentifier, 0x3D)) { |
| 4608 lookupIdentifier = |
| 4609 lookupIdentifier.substring(0, lookupIdentifier.length - 1); |
| 4610 } else { |
| 4611 lookupIdentifier += "="; |
| 4612 } |
| 4613 // lookup with the identifier. |
| 4614 ExecutableElement elementFromInheritance = _inheritanceManager |
| 4615 .lookupInheritance(_enclosingClass, lookupIdentifier); |
| 4616 // Verify that we found something, and that it is an accessor |
| 4617 if (elementFromInheritance != null && |
| 4618 elementFromInheritance is PropertyAccessorElement) { |
| 4619 enclosingClassForCounterpart = |
| 4620 elementFromInheritance.enclosingElement as ClassElement; |
| 4621 counterpartAccessor = elementFromInheritance; |
| 4622 } |
| 4623 } |
| 4624 if (counterpartAccessor == null) { |
| 4625 return; |
| 4626 } |
| 4627 } |
| 4628 // Default of null == no accessor or no type (dynamic) |
| 4629 DartType getterType = null; |
| 4630 DartType setterType = null; |
| 4631 // Get an existing counterpart accessor if any. |
| 4632 if (accessorElement.isGetter) { |
| 4633 getterType = _getGetterType(accessorElement); |
| 4634 setterType = _getSetterType(counterpartAccessor); |
| 4635 } else if (accessorElement.isSetter) { |
| 4636 setterType = _getSetterType(accessorElement); |
| 4637 getterType = _getGetterType(counterpartAccessor); |
| 4638 } |
| 4639 // If either types are not assignable to each other, report an error |
| 4640 // (if the getter is null, it is dynamic which is assignable to everything
). |
| 4641 if (setterType != null && |
| 4642 getterType != null && |
| 4643 !_typeSystem.isAssignableTo(getterType, setterType)) { |
| 4644 if (enclosingClassForCounterpart == null) { |
| 4645 _errorReporter.reportTypeErrorForNode( |
| 4646 StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES, |
| 4647 accessorDeclaration, |
| 4648 [accessorTextName, setterType, getterType]); |
| 4649 } else { |
| 4650 _errorReporter.reportTypeErrorForNode( |
| 4651 StaticWarningCode |
| 4652 .MISMATCHED_GETTER_AND_SETTER_TYPES_FROM_SUPERTYPE, |
| 4653 accessorDeclaration, |
| 4654 [ |
| 4655 accessorTextName, |
| 4656 setterType, |
| 4657 getterType, |
| 4658 enclosingClassForCounterpart.displayName |
| 4659 ]); |
| 4660 } |
| 4086 } | 4661 } |
| 4087 } | 4662 } |
| 4088 // Default of null == no accessor or no type (dynamic) | |
| 4089 DartType getterType = null; | |
| 4090 DartType setterType = null; | |
| 4091 // Get an existing counterpart accessor if any. | |
| 4092 if (propertyAccessorElement.isGetter) { | |
| 4093 getterType = _getGetterType(propertyAccessorElement); | |
| 4094 setterType = _getSetterType(counterpartAccessor); | |
| 4095 } else if (propertyAccessorElement.isSetter) { | |
| 4096 setterType = _getSetterType(propertyAccessorElement); | |
| 4097 getterType = _getGetterType(counterpartAccessor); | |
| 4098 } | |
| 4099 // If either types are not assignable to each other, report an error | |
| 4100 // (if the getter is null, it is dynamic which is assignable to everything). | |
| 4101 if (setterType != null && | |
| 4102 getterType != null && | |
| 4103 !_typeSystem.isAssignableTo(getterType, setterType)) { | |
| 4104 if (enclosingClassForCounterpart == null) { | |
| 4105 _errorReporter.reportTypeErrorForNode( | |
| 4106 StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES, | |
| 4107 accessorDeclaration, | |
| 4108 [accessorTextName, setterType, getterType]); | |
| 4109 return true; | |
| 4110 } else { | |
| 4111 _errorReporter.reportTypeErrorForNode( | |
| 4112 StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES_FROM_SUPERTYPE, | |
| 4113 accessorDeclaration, [ | |
| 4114 accessorTextName, | |
| 4115 setterType, | |
| 4116 getterType, | |
| 4117 enclosingClassForCounterpart.displayName | |
| 4118 ]); | |
| 4119 } | |
| 4120 } | |
| 4121 return false; | |
| 4122 } | 4663 } |
| 4123 | 4664 |
| 4124 /** | 4665 /** |
| 4125 * Check to make sure that the given switch [statement] whose static type is | 4666 * Check to make sure that the given switch [statement] whose static type is |
| 4126 * an enum type either have a default case or include all of the enum | 4667 * an enum type either have a default case or include all of the enum |
| 4127 * constants. | 4668 * constants. |
| 4128 */ | 4669 */ |
| 4129 bool _checkForMissingEnumConstantInSwitch(SwitchStatement statement) { | 4670 void _checkForMissingEnumConstantInSwitch(SwitchStatement statement) { |
| 4130 // TODO(brianwilkerson) This needs to be checked after constant values have | 4671 // TODO(brianwilkerson) This needs to be checked after constant values have |
| 4131 // been computed. | 4672 // been computed. |
| 4132 Expression expression = statement.expression; | 4673 Expression expression = statement.expression; |
| 4133 DartType expressionType = getStaticType(expression); | 4674 DartType expressionType = getStaticType(expression); |
| 4134 if (expressionType == null) { | 4675 if (expressionType == null) { |
| 4135 return false; | 4676 return; |
| 4136 } | 4677 } |
| 4137 Element expressionElement = expressionType.element; | 4678 Element expressionElement = expressionType.element; |
| 4138 if (expressionElement is! ClassElement) { | 4679 if (expressionElement is ClassElement) { |
| 4139 return false; | 4680 if (!expressionElement.isEnum) { |
| 4140 } | 4681 return; |
| 4141 ClassElement classElement = expressionElement as ClassElement; | 4682 } |
| 4142 if (!classElement.isEnum) { | 4683 List<String> constantNames = <String>[]; |
| 4143 return false; | 4684 List<FieldElement> fields = expressionElement.fields; |
| 4144 } | 4685 int fieldCount = fields.length; |
| 4145 List<String> constantNames = new List<String>(); | 4686 for (int i = 0; i < fieldCount; i++) { |
| 4146 List<FieldElement> fields = classElement.fields; | 4687 FieldElement field = fields[i]; |
| 4147 int fieldCount = fields.length; | 4688 if (field.isStatic && !field.isSynthetic) { |
| 4148 for (int i = 0; i < fieldCount; i++) { | 4689 constantNames.add(field.name); |
| 4149 FieldElement field = fields[i]; | 4690 } |
| 4150 if (field.isStatic && !field.isSynthetic) { | 4691 } |
| 4151 constantNames.add(field.name); | 4692 NodeList<SwitchMember> members = statement.members; |
| 4693 int memberCount = members.length; |
| 4694 for (int i = 0; i < memberCount; i++) { |
| 4695 SwitchMember member = members[i]; |
| 4696 if (member is SwitchDefault) { |
| 4697 return; |
| 4698 } |
| 4699 String constantName = |
| 4700 _getConstantName((member as SwitchCase).expression); |
| 4701 if (constantName != null) { |
| 4702 constantNames.remove(constantName); |
| 4703 } |
| 4704 } |
| 4705 if (constantNames.isEmpty) { |
| 4706 return; |
| 4707 } |
| 4708 for (int i = 0; i < constantNames.length; i++) { |
| 4709 int offset = statement.offset; |
| 4710 int end = statement.rightParenthesis.end; |
| 4711 _errorReporter.reportErrorForOffset( |
| 4712 StaticWarningCode.MISSING_ENUM_CONSTANT_IN_SWITCH, |
| 4713 offset, |
| 4714 end - offset, |
| 4715 [constantNames[i]]); |
| 4152 } | 4716 } |
| 4153 } | 4717 } |
| 4154 NodeList<SwitchMember> members = statement.members; | 4718 } |
| 4155 int memberCount = members.length; | 4719 |
| 4156 for (int i = 0; i < memberCount; i++) { | 4720 void _checkForMissingJSLibAnnotation(Annotation node) { |
| 4157 SwitchMember member = members[i]; | 4721 if (node.elementAnnotation?.isJS ?? false) { |
| 4158 if (member is SwitchDefault) { | 4722 if (_currentLibrary.isJS != true) { |
| 4159 return false; | 4723 _errorReporter.reportErrorForNode( |
| 4160 } | 4724 HintCode.MISSING_JS_LIB_ANNOTATION, node); |
| 4161 String constantName = _getConstantName((member as SwitchCase).expression); | |
| 4162 if (constantName != null) { | |
| 4163 constantNames.remove(constantName); | |
| 4164 } | 4725 } |
| 4165 } | 4726 } |
| 4166 int nameCount = constantNames.length; | |
| 4167 if (nameCount == 0) { | |
| 4168 return false; | |
| 4169 } | |
| 4170 for (int i = 0; i < nameCount; i++) { | |
| 4171 int offset = statement.offset; | |
| 4172 int end = statement.rightParenthesis.end; | |
| 4173 _errorReporter.reportErrorForOffset( | |
| 4174 CompileTimeErrorCode.MISSING_ENUM_CONSTANT_IN_SWITCH, | |
| 4175 offset, | |
| 4176 end - offset, | |
| 4177 [constantNames[i]]); | |
| 4178 } | |
| 4179 return true; | |
| 4180 } | 4727 } |
| 4181 | 4728 |
| 4182 /** | 4729 /** |
| 4183 * Verify that the given function [body] does not contain return statements | 4730 * Verify that the given function [body] does not contain return statements |
| 4184 * that both have and do not have return values. | 4731 * that both have and do not have return values. |
| 4185 * | 4732 * |
| 4186 * See [StaticWarningCode.MIXED_RETURN_TYPES]. | 4733 * See [StaticWarningCode.MIXED_RETURN_TYPES]. |
| 4187 */ | 4734 */ |
| 4188 bool _checkForMixedReturns(BlockFunctionBody body) { | 4735 void _checkForMixedReturns(BlockFunctionBody body) { |
| 4189 if (_hasReturnWithoutValue) { | 4736 if (_hasReturnWithoutValue) { |
| 4190 return false; | 4737 return; |
| 4191 } | 4738 } |
| 4192 int withCount = _returnsWith.length; | 4739 if (_returnsWith.isNotEmpty && _returnsWithout.isNotEmpty) { |
| 4193 int withoutCount = _returnsWithout.length; | 4740 for (ReturnStatement returnWith in _returnsWith) { |
| 4194 if (withCount > 0 && withoutCount > 0) { | 4741 _errorReporter.reportErrorForToken( |
| 4195 for (int i = 0; i < withCount; i++) { | 4742 StaticWarningCode.MIXED_RETURN_TYPES, returnWith.returnKeyword); |
| 4196 _errorReporter.reportErrorForToken(StaticWarningCode.MIXED_RETURN_TYPES, | |
| 4197 _returnsWith[i].returnKeyword); | |
| 4198 } | 4743 } |
| 4199 for (int i = 0; i < withoutCount; i++) { | 4744 for (ReturnStatement returnWithout in _returnsWithout) { |
| 4200 _errorReporter.reportErrorForToken(StaticWarningCode.MIXED_RETURN_TYPES, | 4745 _errorReporter.reportErrorForToken( |
| 4201 _returnsWithout[i].returnKeyword); | 4746 StaticWarningCode.MIXED_RETURN_TYPES, returnWithout.returnKeyword); |
| 4202 } | 4747 } |
| 4203 return true; | |
| 4204 } | 4748 } |
| 4205 return false; | |
| 4206 } | 4749 } |
| 4207 | 4750 |
| 4208 /** | 4751 /** |
| 4209 * Verify that the given mixin does not have an explicitly declared | 4752 * Verify that the given mixin does not have an explicitly declared |
| 4210 * constructor. The [mixinName] is the node to report problem on. The | 4753 * constructor. The [mixinName] is the node to report problem on. The |
| 4211 * [mixinElement] is the mixing to evaluate. | 4754 * [mixinElement] is the mixing to evaluate. |
| 4212 * | 4755 * |
| 4213 * See [CompileTimeErrorCode.MIXIN_DECLARES_CONSTRUCTOR]. | 4756 * See [CompileTimeErrorCode.MIXIN_DECLARES_CONSTRUCTOR]. |
| 4214 */ | 4757 */ |
| 4215 bool _checkForMixinDeclaresConstructor( | 4758 bool _checkForMixinDeclaresConstructor( |
| 4216 TypeName mixinName, ClassElement mixinElement) { | 4759 TypeName mixinName, ClassElement mixinElement) { |
| 4217 for (ConstructorElement constructor in mixinElement.constructors) { | 4760 for (ConstructorElement constructor in mixinElement.constructors) { |
| 4218 if (!constructor.isSynthetic && !constructor.isFactory) { | 4761 if (!constructor.isSynthetic && !constructor.isFactory) { |
| 4219 _errorReporter.reportErrorForNode( | 4762 _errorReporter.reportErrorForNode( |
| 4220 CompileTimeErrorCode.MIXIN_DECLARES_CONSTRUCTOR, | 4763 CompileTimeErrorCode.MIXIN_DECLARES_CONSTRUCTOR, |
| 4221 mixinName, | 4764 mixinName, |
| 4222 [mixinElement.name]); | 4765 [mixinElement.name]); |
| 4223 return true; | 4766 return true; |
| 4224 } | 4767 } |
| 4225 } | 4768 } |
| 4226 return false; | 4769 return false; |
| 4227 } | 4770 } |
| 4228 | 4771 |
| 4229 /** | 4772 /** |
| 4230 * Report the error [CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS] if | 4773 * Report the error [CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS] if |
| 4231 * appropriate. | 4774 * appropriate. |
| 4232 */ | 4775 */ |
| 4233 void _checkForMixinHasNoConstructors(AstNode node) { | 4776 void _checkForMixinHasNoConstructors(AstNode node) { |
| 4234 if ((_enclosingClass as ClassElementImpl).doesMixinLackConstructors) { | 4777 if (_enclosingClass.doesMixinLackConstructors) { |
| 4235 ErrorCode errorCode = CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS; | 4778 ErrorCode errorCode = CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS; |
| 4236 _errorReporter.reportErrorForNode( | 4779 _errorReporter |
| 4237 errorCode, node, [_enclosingClass.supertype]); | 4780 .reportErrorForNode(errorCode, node, [_enclosingClass.supertype]); |
| 4238 } | 4781 } |
| 4239 } | 4782 } |
| 4240 | 4783 |
| 4241 /** | 4784 /** |
| 4242 * Verify that the given mixin has the 'Object' superclass. The [mixinName] is | 4785 * Verify that the given mixin has the 'Object' superclass. The [mixinName] is |
| 4243 * the node to report problem on. The [mixinElement] is the mixing to | 4786 * the node to report problem on. The [mixinElement] is the mixing to |
| 4244 * evaluate. | 4787 * evaluate. |
| 4245 * | 4788 * |
| 4246 * See [CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT]. | 4789 * See [CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT]. |
| 4247 */ | 4790 */ |
| (...skipping 29 matching lines...) Expand all Loading... |
| 4277 [mixinElement.name]); | 4820 [mixinElement.name]); |
| 4278 } | 4821 } |
| 4279 return false; | 4822 return false; |
| 4280 } | 4823 } |
| 4281 | 4824 |
| 4282 /** | 4825 /** |
| 4283 * Verify that the given [constructor] has at most one 'super' initializer. | 4826 * Verify that the given [constructor] has at most one 'super' initializer. |
| 4284 * | 4827 * |
| 4285 * See [CompileTimeErrorCode.MULTIPLE_SUPER_INITIALIZERS]. | 4828 * See [CompileTimeErrorCode.MULTIPLE_SUPER_INITIALIZERS]. |
| 4286 */ | 4829 */ |
| 4287 bool _checkForMultipleSuperInitializers(ConstructorDeclaration constructor) { | 4830 void _checkForMultipleSuperInitializers(ConstructorDeclaration constructor) { |
| 4288 int numSuperInitializers = 0; | 4831 bool hasSuperInitializer = false; |
| 4289 for (ConstructorInitializer initializer in constructor.initializers) { | 4832 for (ConstructorInitializer initializer in constructor.initializers) { |
| 4290 if (initializer is SuperConstructorInvocation) { | 4833 if (initializer is SuperConstructorInvocation) { |
| 4291 numSuperInitializers++; | 4834 if (hasSuperInitializer) { |
| 4292 if (numSuperInitializers > 1) { | |
| 4293 _errorReporter.reportErrorForNode( | 4835 _errorReporter.reportErrorForNode( |
| 4294 CompileTimeErrorCode.MULTIPLE_SUPER_INITIALIZERS, initializer); | 4836 CompileTimeErrorCode.MULTIPLE_SUPER_INITIALIZERS, initializer); |
| 4295 } | 4837 } |
| 4838 hasSuperInitializer = true; |
| 4296 } | 4839 } |
| 4297 } | 4840 } |
| 4298 return numSuperInitializers > 0; | 4841 } |
| 4842 |
| 4843 void _checkForMustCallSuper(MethodDeclaration node) { |
| 4844 MethodElement element = _findOverriddenMemberThatMustCallSuper(node); |
| 4845 if (element != null) { |
| 4846 _InvocationCollector collector = new _InvocationCollector(); |
| 4847 node.accept(collector); |
| 4848 if (!collector.superCalls.contains(element.name)) { |
| 4849 _errorReporter.reportErrorForNode(HintCode.MUST_CALL_SUPER, node.name, |
| 4850 [element.enclosingElement.name]); |
| 4851 } |
| 4852 } |
| 4299 } | 4853 } |
| 4300 | 4854 |
| 4301 /** | 4855 /** |
| 4302 * Checks to ensure that the given native function [body] is in SDK code. | 4856 * Checks to ensure that the given native function [body] is in SDK code. |
| 4303 * | 4857 * |
| 4304 * See [ParserErrorCode.NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE]. | 4858 * See [ParserErrorCode.NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE]. |
| 4305 */ | 4859 */ |
| 4306 bool _checkForNativeFunctionBodyInNonSDKCode(NativeFunctionBody body) { | 4860 void _checkForNativeFunctionBodyInNonSdkCode(NativeFunctionBody body) { |
| 4307 if (!_isInSystemLibrary && !_hasExtUri) { | 4861 if (!_isInSystemLibrary && !_hasExtUri) { |
| 4308 _errorReporter.reportErrorForNode( | 4862 _errorReporter.reportErrorForNode( |
| 4309 ParserErrorCode.NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE, body); | 4863 ParserErrorCode.NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE, body); |
| 4310 return true; | |
| 4311 } | 4864 } |
| 4312 return false; | |
| 4313 } | 4865 } |
| 4314 | 4866 |
| 4315 /** | 4867 /** |
| 4316 * Verify that the given instance creation [expression] invokes an existing | 4868 * Verify that the given instance creation [expression] invokes an existing |
| 4317 * constructor. The [constructorName] is the constructor name. The [typeName] | 4869 * constructor. The [constructorName] is the constructor name. The [typeName] |
| 4318 * is the name of the type defining the constructor. | 4870 * is the name of the type defining the constructor. |
| 4319 * | 4871 * |
| 4320 * This method assumes that the instance creation was tested to be 'new' | 4872 * This method assumes that the instance creation was tested to be 'new' |
| 4321 * before being called. | 4873 * before being called. |
| 4322 * | 4874 * |
| 4323 * See [StaticWarningCode.NEW_WITH_UNDEFINED_CONSTRUCTOR]. | 4875 * See [StaticWarningCode.NEW_WITH_UNDEFINED_CONSTRUCTOR]. |
| 4324 */ | 4876 */ |
| 4325 bool _checkForNewWithUndefinedConstructor( | 4877 void _checkForNewWithUndefinedConstructor( |
| 4326 InstanceCreationExpression expression, | 4878 InstanceCreationExpression expression, |
| 4327 ConstructorName constructorName, | 4879 ConstructorName constructorName, |
| 4328 TypeName typeName) { | 4880 TypeName typeName) { |
| 4329 // OK if resolved | 4881 // OK if resolved |
| 4330 if (expression.staticElement != null) { | 4882 if (expression.staticElement != null) { |
| 4331 return false; | 4883 return; |
| 4332 } | 4884 } |
| 4333 DartType type = typeName.type; | 4885 DartType type = typeName.type; |
| 4334 if (type is InterfaceType) { | 4886 if (type is InterfaceType) { |
| 4335 ClassElement element = type.element; | 4887 ClassElement element = type.element; |
| 4336 if (element != null && element.isEnum) { | 4888 if (element != null && element.isEnum) { |
| 4337 // We have already reported the error. | 4889 // We have already reported the error. |
| 4338 return false; | 4890 return; |
| 4339 } | 4891 } |
| 4340 } | 4892 } |
| 4341 // prepare class name | 4893 // prepare class name |
| 4342 Identifier className = typeName.name; | 4894 Identifier className = typeName.name; |
| 4343 // report as named or default constructor absence | 4895 // report as named or default constructor absence |
| 4344 SimpleIdentifier name = constructorName.name; | 4896 SimpleIdentifier name = constructorName.name; |
| 4345 if (name != null) { | 4897 if (name != null) { |
| 4346 _errorReporter.reportErrorForNode( | 4898 _errorReporter.reportErrorForNode( |
| 4347 StaticWarningCode.NEW_WITH_UNDEFINED_CONSTRUCTOR, | 4899 StaticWarningCode.NEW_WITH_UNDEFINED_CONSTRUCTOR, |
| 4348 name, | 4900 name, |
| 4349 [className, name]); | 4901 [className, name]); |
| 4350 } else { | 4902 } else { |
| 4351 _errorReporter.reportErrorForNode( | 4903 _errorReporter.reportErrorForNode( |
| 4352 StaticWarningCode.NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT, | 4904 StaticWarningCode.NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT, |
| 4353 constructorName, | 4905 constructorName, |
| 4354 [className]); | 4906 [className]); |
| 4355 } | 4907 } |
| 4356 return true; | |
| 4357 } | 4908 } |
| 4358 | 4909 |
| 4359 /** | 4910 /** |
| 4360 * Check that if the given class [declaration] implicitly calls default | 4911 * Check that if the given class [declaration] implicitly calls default |
| 4361 * constructor of its superclass, there should be such default constructor - | 4912 * constructor of its superclass, there should be such default constructor - |
| 4362 * implicit or explicit. | 4913 * implicit or explicit. |
| 4363 * | 4914 * |
| 4364 * See [CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT]. | 4915 * See [CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT]. |
| 4365 */ | 4916 */ |
| 4366 bool _checkForNoDefaultSuperConstructorImplicit( | 4917 void _checkForNoDefaultSuperConstructorImplicit( |
| 4367 ClassDeclaration declaration) { | 4918 ClassDeclaration declaration) { |
| 4368 // do nothing if mixin errors have already been reported for this class. | 4919 // do nothing if mixin errors have already been reported for this class. |
| 4369 ClassElementImpl enclosingClass = _enclosingClass; | 4920 if (_enclosingClass.doesMixinLackConstructors) { |
| 4370 if (enclosingClass.doesMixinLackConstructors) { | 4921 return; |
| 4371 return false; | |
| 4372 } | 4922 } |
| 4373 // do nothing if there is explicit constructor | 4923 // do nothing if there is explicit constructor |
| 4374 List<ConstructorElement> constructors = _enclosingClass.constructors; | 4924 List<ConstructorElement> constructors = _enclosingClass.constructors; |
| 4375 if (!constructors[0].isSynthetic) { | 4925 if (!constructors[0].isSynthetic) { |
| 4376 return false; | 4926 return; |
| 4377 } | 4927 } |
| 4378 // prepare super | 4928 // prepare super |
| 4379 InterfaceType superType = _enclosingClass.supertype; | 4929 InterfaceType superType = _enclosingClass.supertype; |
| 4380 if (superType == null) { | 4930 if (superType == null) { |
| 4381 return false; | 4931 return; |
| 4382 } | 4932 } |
| 4383 ClassElement superElement = superType.element; | 4933 ClassElement superElement = superType.element; |
| 4384 // try to find default generative super constructor | 4934 // try to find default generative super constructor |
| 4385 ConstructorElement superUnnamedConstructor = | 4935 ConstructorElement superUnnamedConstructor = |
| 4386 superElement.unnamedConstructor; | 4936 superElement.unnamedConstructor; |
| 4387 if (superUnnamedConstructor != null) { | 4937 if (superUnnamedConstructor != null) { |
| 4388 if (superUnnamedConstructor.isFactory) { | 4938 if (superUnnamedConstructor.isFactory) { |
| 4389 _errorReporter.reportErrorForNode( | 4939 _errorReporter.reportErrorForNode( |
| 4390 CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR, | 4940 CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR, |
| 4391 declaration.name, | 4941 declaration.name, |
| 4392 [superUnnamedConstructor]); | 4942 [superUnnamedConstructor]); |
| 4393 return true; | 4943 return; |
| 4394 } | 4944 } |
| 4395 if (superUnnamedConstructor.isDefaultConstructor && | 4945 if (superUnnamedConstructor.isDefaultConstructor && |
| 4396 _enclosingClass | 4946 _enclosingClass |
| 4397 .isSuperConstructorAccessible(superUnnamedConstructor)) { | 4947 .isSuperConstructorAccessible(superUnnamedConstructor)) { |
| 4398 return true; | 4948 return; |
| 4399 } | 4949 } |
| 4400 } | 4950 } |
| 4401 // report problem | 4951 |
| 4402 _errorReporter.reportErrorForNode( | 4952 _errorReporter.reportErrorForNode( |
| 4403 CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT, | 4953 CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT, |
| 4404 declaration.name, | 4954 declaration.name, |
| 4405 [superType.displayName]); | 4955 [superType.displayName]); |
| 4406 return true; | |
| 4407 } | 4956 } |
| 4408 | 4957 |
| 4409 /** | 4958 /** |
| 4410 * Check that the given class declaration overrides all members required by | 4959 * Check that the given class declaration overrides all members required by |
| 4411 * its superclasses and interfaces. The [classNameNode] is the | 4960 * its superclasses and interfaces. The [classNameNode] is the |
| 4412 * [SimpleIdentifier] to be used if there is a violation, this is either the | 4961 * [SimpleIdentifier] to be used if there is a violation, this is either the |
| 4413 * named from the [ClassDeclaration] or from the [ClassTypeAlias]. | 4962 * named from the [ClassDeclaration] or from the [ClassTypeAlias]. |
| 4414 * | 4963 * |
| 4415 * See [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE], | 4964 * See [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE], |
| 4416 * [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO], | 4965 * [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO], |
| 4417 * [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_THREE], | 4966 * [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_THREE], |
| 4418 * [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR], and | 4967 * [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR], and |
| 4419 * [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLUS]. | 4968 * [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLUS]. |
| 4420 */ | 4969 */ |
| 4421 bool _checkForNonAbstractClassInheritsAbstractMember( | 4970 void _checkForNonAbstractClassInheritsAbstractMember( |
| 4422 SimpleIdentifier classNameNode) { | 4971 SimpleIdentifier classNameNode) { |
| 4423 if (_enclosingClass.isAbstract) { | 4972 if (_enclosingClass.isAbstract) { |
| 4424 return false; | 4973 return; |
| 4974 } else if (_enclosingClass.hasNoSuchMethod) { |
| 4975 return; |
| 4425 } | 4976 } |
| 4426 // | 4977 // |
| 4427 // Store in local sets the set of all method and accessor names | 4978 // Store in local sets the set of all method and accessor names |
| 4428 // | 4979 // |
| 4429 MethodElement method = | |
| 4430 _enclosingClass.getMethod(FunctionElement.NO_SUCH_METHOD_METHOD_NAME); | |
| 4431 if (method != null) { | |
| 4432 // If the enclosing class declares the method noSuchMethod(), then return. | |
| 4433 // From Spec: It is a static warning if a concrete class does not have an | |
| 4434 // implementation for a method in any of its superinterfaces unless it | |
| 4435 // declares its own noSuchMethod method (7.10). | |
| 4436 return false; | |
| 4437 } | |
| 4438 HashSet<ExecutableElement> missingOverrides = | 4980 HashSet<ExecutableElement> missingOverrides = |
| 4439 new HashSet<ExecutableElement>(); | 4981 new HashSet<ExecutableElement>(); |
| 4440 // | 4982 // |
| 4441 // Loop through the set of all executable elements declared in the implicit | 4983 // Loop through the set of all executable elements declared in the implicit |
| 4442 // interface. | 4984 // interface. |
| 4443 // | 4985 // |
| 4444 MemberMap membersInheritedFromInterfaces = _inheritanceManager | 4986 Map<String, ExecutableElement> membersInheritedFromInterfaces = |
| 4445 .getMapOfMembersInheritedFromInterfaces(_enclosingClass); | 4987 _inheritanceManager.getMembersInheritedFromInterfaces(_enclosingClass); |
| 4446 MemberMap membersInheritedFromSuperclasses = _inheritanceManager | 4988 Map<String, ExecutableElement> membersInheritedFromSuperclasses = |
| 4447 .getMapOfMembersInheritedFromClasses(_enclosingClass); | 4989 _inheritanceManager.getMembersInheritedFromClasses(_enclosingClass); |
| 4448 for (int i = 0; i < membersInheritedFromInterfaces.size; i++) { | 4990 for (String memberName in membersInheritedFromInterfaces.keys) { |
| 4449 String memberName = membersInheritedFromInterfaces.getKey(i); | |
| 4450 ExecutableElement executableElt = | 4991 ExecutableElement executableElt = |
| 4451 membersInheritedFromInterfaces.getValue(i); | 4992 membersInheritedFromInterfaces[memberName]; |
| 4452 if (memberName == null) { | 4993 if (memberName == null) { |
| 4453 break; | 4994 break; |
| 4454 } | 4995 } |
| 4455 // If the element is not synthetic and can be determined to be defined in | 4996 // If the element is not synthetic and can be determined to be defined in |
| 4456 // Object, skip it. | 4997 // Object, skip it. |
| 4457 if (executableElt.enclosingElement != null && | 4998 if (executableElt.enclosingElement != null && |
| 4458 (executableElt.enclosingElement as ClassElement).type.isObject) { | 4999 (executableElt.enclosingElement as ClassElement).type.isObject) { |
| 4459 continue; | 5000 continue; |
| 4460 } | 5001 } |
| 4461 // Check to see if some element is in local enclosing class that matches | 5002 // Check to see if some element is in local enclosing class that matches |
| 4462 // the name of the required member. | 5003 // the name of the required member. |
| 4463 if (_isMemberInClassOrMixin(executableElt, _enclosingClass)) { | 5004 if (_isMemberInClassOrMixin(executableElt, _enclosingClass)) { |
| 4464 // We do not have to verify that this implementation of the found method | 5005 // We do not have to verify that this implementation of the found method |
| 4465 // matches the required function type: the set of | 5006 // matches the required function type: the set of |
| 4466 // StaticWarningCode.INVALID_METHOD_OVERRIDE_* warnings break out the | 5007 // StaticWarningCode.INVALID_METHOD_OVERRIDE_* warnings break out the |
| 4467 // different specific situations. | 5008 // different specific situations. |
| 4468 continue; | 5009 continue; |
| 4469 } | 5010 } |
| 4470 // First check to see if this element was declared in the superclass | 5011 // First check to see if this element was declared in the superclass |
| 4471 // chain, in which case there is already a concrete implementation. | 5012 // chain, in which case there is already a concrete implementation. |
| 4472 ExecutableElement elt = membersInheritedFromSuperclasses.get(memberName); | 5013 ExecutableElement elt = membersInheritedFromSuperclasses[memberName]; |
| 4473 // Check to see if an element was found in the superclass chain with the | 5014 // Check to see if an element was found in the superclass chain with the |
| 4474 // correct name. | 5015 // correct name. |
| 4475 if (elt != null) { | 5016 if (elt != null) { |
| 4476 // Reference the types, if any are null then continue. | 5017 // Reference the types, if any are null then continue. |
| 4477 InterfaceType enclosingType = _enclosingClass.type; | 5018 InterfaceType enclosingType = _enclosingClass.type; |
| 4478 FunctionType concreteType = elt.type; | 5019 FunctionType concreteType = elt.type; |
| 4479 FunctionType requiredMemberType = executableElt.type; | 5020 FunctionType requiredMemberType = executableElt.type; |
| 4480 if (enclosingType == null || | 5021 if (enclosingType == null || |
| 4481 concreteType == null || | 5022 concreteType == null || |
| 4482 requiredMemberType == null) { | 5023 requiredMemberType == null) { |
| 4483 continue; | 5024 continue; |
| 4484 } | 5025 } |
| 4485 // Some element was found in the superclass chain that matches the name | 5026 // Some element was found in the superclass chain that matches the name |
| 4486 // of the required member. | 5027 // of the required member. |
| 4487 // If it is not abstract and it is the correct one (types match- the | 5028 // If it is not abstract and it is the correct one (types match- the |
| 4488 // version of this method that we have has the correct number of | 5029 // version of this method that we have has the correct number of |
| 4489 // parameters, etc), then this class has a valid implementation of this | 5030 // parameters, etc), then this class has a valid implementation of this |
| 4490 // method, so skip it. | 5031 // method, so skip it. |
| 4491 if ((elt is MethodElement && !elt.isAbstract) || | 5032 if ((elt is MethodElement && !elt.isAbstract) || |
| 4492 (elt is PropertyAccessorElement && !elt.isAbstract)) { | 5033 (elt is PropertyAccessorElement && !elt.isAbstract)) { |
| 4493 // Since we are comparing two function types, we need to do the | 5034 // Since we are comparing two function types, we need to do the |
| 4494 // appropriate type substitutions first (). | 5035 // appropriate type substitutions first (). |
| 4495 FunctionType foundConcreteFT = _inheritanceManager | 5036 FunctionType foundConcreteFT = _inheritanceManager |
| 4496 .substituteTypeArgumentsInMemberFromInheritance( | 5037 .substituteTypeArgumentsInMemberFromInheritance( |
| 4497 concreteType, memberName, enclosingType); | 5038 concreteType, memberName, enclosingType); |
| 4498 FunctionType requiredMemberFT = _inheritanceManager | 5039 FunctionType requiredMemberFT = _inheritanceManager |
| 4499 .substituteTypeArgumentsInMemberFromInheritance( | 5040 .substituteTypeArgumentsInMemberFromInheritance( |
| 4500 requiredMemberType, memberName, enclosingType); | 5041 requiredMemberType, memberName, enclosingType); |
| 4501 if (_typeSystem.isSubtypeOf(foundConcreteFT, requiredMemberFT)) { | 5042 foundConcreteFT = _typeSystem.functionTypeToConcreteType( |
| 5043 _typeProvider, foundConcreteFT); |
| 5044 requiredMemberFT = _typeSystem.functionTypeToConcreteType( |
| 5045 _typeProvider, requiredMemberFT); |
| 5046 |
| 5047 // Strong mode does override checking for types in CodeChecker, so |
| 5048 // we can skip it here. Doing it here leads to unnecessary duplicate |
| 5049 // error messages in subclasses that inherit from one that has an |
| 5050 // override error. |
| 5051 // |
| 5052 // See: https://github.com/dart-lang/sdk/issues/25232 |
| 5053 if (_options.strongMode || |
| 5054 _typeSystem.isSubtypeOf(foundConcreteFT, requiredMemberFT)) { |
| 4502 continue; | 5055 continue; |
| 4503 } | 5056 } |
| 4504 } | 5057 } |
| 4505 } | 5058 } |
| 4506 // The not qualifying concrete executable element was found, add it to the | 5059 // The not qualifying concrete executable element was found, add it to the |
| 4507 // list. | 5060 // list. |
| 4508 missingOverrides.add(executableElt); | 5061 missingOverrides.add(executableElt); |
| 4509 } | 5062 } |
| 4510 // Now that we have the set of missing overrides, generate a warning on this | 5063 // Now that we have the set of missing overrides, generate a warning on this |
| 4511 // class. | 5064 // class. |
| 4512 int missingOverridesSize = missingOverrides.length; | 5065 int missingOverridesSize = missingOverrides.length; |
| 4513 if (missingOverridesSize == 0) { | 5066 if (missingOverridesSize == 0) { |
| 4514 return false; | 5067 return; |
| 4515 } | 5068 } |
| 4516 List<ExecutableElement> missingOverridesArray = | 5069 List<ExecutableElement> missingOverridesArray = |
| 4517 new List.from(missingOverrides); | 5070 new List.from(missingOverrides); |
| 4518 List<String> stringMembersArrayListSet = new List<String>(); | 5071 List<String> stringMembersArrayListSet = new List<String>(); |
| 4519 for (int i = 0; i < missingOverridesArray.length; i++) { | 5072 for (int i = 0; i < missingOverridesArray.length; i++) { |
| 4520 String newStrMember; | 5073 String newStrMember; |
| 4521 Element enclosingElement = missingOverridesArray[i].enclosingElement; | 5074 ExecutableElement element = missingOverridesArray[i]; |
| 5075 Element enclosingElement = element.enclosingElement; |
| 4522 String prefix = StringUtilities.EMPTY; | 5076 String prefix = StringUtilities.EMPTY; |
| 4523 if (missingOverridesArray[i] is PropertyAccessorElement) { | 5077 if (element is PropertyAccessorElement) { |
| 4524 PropertyAccessorElement propertyAccessorElement = | 5078 if (element.isGetter) { |
| 4525 missingOverridesArray[i] as PropertyAccessorElement; | |
| 4526 if (propertyAccessorElement.isGetter) { | |
| 4527 prefix = _GETTER_SPACE; | 5079 prefix = _GETTER_SPACE; |
| 4528 // "getter " | 5080 // "getter " |
| 4529 } else { | 5081 } else { |
| 4530 prefix = _SETTER_SPACE; | 5082 prefix = _SETTER_SPACE; |
| 4531 // "setter " | 5083 // "setter " |
| 4532 } | 5084 } |
| 4533 } | 5085 } |
| 4534 if (enclosingElement != null) { | 5086 if (enclosingElement != null) { |
| 4535 newStrMember = | 5087 newStrMember = |
| 4536 "$prefix'${enclosingElement.displayName}.${missingOverridesArray[i].
displayName}'"; | 5088 "$prefix'${enclosingElement.displayName}.${element.displayName}'"; |
| 4537 } else { | 5089 } else { |
| 4538 newStrMember = "$prefix'${missingOverridesArray[i].displayName}'"; | 5090 newStrMember = "$prefix'${element.displayName}'"; |
| 4539 } | 5091 } |
| 4540 stringMembersArrayListSet.add(newStrMember); | 5092 stringMembersArrayListSet.add(newStrMember); |
| 4541 } | 5093 } |
| 4542 List<String> stringMembersArray = new List.from(stringMembersArrayListSet); | 5094 List<String> stringMembersArray = new List.from(stringMembersArrayListSet); |
| 5095 stringMembersArray.sort(); |
| 4543 AnalysisErrorWithProperties analysisError; | 5096 AnalysisErrorWithProperties analysisError; |
| 4544 if (stringMembersArray.length == 1) { | 5097 if (stringMembersArray.length == 1) { |
| 4545 analysisError = _errorReporter.newErrorWithProperties( | 5098 analysisError = _errorReporter.newErrorWithProperties( |
| 4546 StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE, | 5099 StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE, |
| 4547 classNameNode, | 5100 classNameNode, |
| 4548 [stringMembersArray[0]]); | 5101 [stringMembersArray[0]]); |
| 4549 } else if (stringMembersArray.length == 2) { | 5102 } else if (stringMembersArray.length == 2) { |
| 4550 analysisError = _errorReporter.newErrorWithProperties( | 5103 analysisError = _errorReporter.newErrorWithProperties( |
| 4551 StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO, | 5104 StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO, |
| 4552 classNameNode, | 5105 classNameNode, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 4563 analysisError = _errorReporter.newErrorWithProperties( | 5116 analysisError = _errorReporter.newErrorWithProperties( |
| 4564 StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR, | 5117 StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR, |
| 4565 classNameNode, [ | 5118 classNameNode, [ |
| 4566 stringMembersArray[0], | 5119 stringMembersArray[0], |
| 4567 stringMembersArray[1], | 5120 stringMembersArray[1], |
| 4568 stringMembersArray[2], | 5121 stringMembersArray[2], |
| 4569 stringMembersArray[3] | 5122 stringMembersArray[3] |
| 4570 ]); | 5123 ]); |
| 4571 } else { | 5124 } else { |
| 4572 analysisError = _errorReporter.newErrorWithProperties( | 5125 analysisError = _errorReporter.newErrorWithProperties( |
| 4573 StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLU
S, | 5126 StaticWarningCode |
| 4574 classNameNode, [ | 5127 .NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLUS, |
| 4575 stringMembersArray[0], | 5128 classNameNode, |
| 4576 stringMembersArray[1], | 5129 [ |
| 4577 stringMembersArray[2], | 5130 stringMembersArray[0], |
| 4578 stringMembersArray[3], | 5131 stringMembersArray[1], |
| 4579 stringMembersArray.length - 4 | 5132 stringMembersArray[2], |
| 4580 ]); | 5133 stringMembersArray[3], |
| 5134 stringMembersArray.length - 4 |
| 5135 ]); |
| 4581 } | 5136 } |
| 4582 analysisError.setProperty( | 5137 analysisError.setProperty( |
| 4583 ErrorProperty.UNIMPLEMENTED_METHODS, missingOverridesArray); | 5138 ErrorProperty.UNIMPLEMENTED_METHODS, missingOverridesArray); |
| 4584 _errorReporter.reportError(analysisError); | 5139 _errorReporter.reportError(analysisError); |
| 4585 return true; | |
| 4586 } | 5140 } |
| 4587 | 5141 |
| 4588 /** | 5142 /** |
| 4589 * Check to ensure that the [condition] is of type bool, are. Otherwise an | 5143 * Check to ensure that the [condition] is of type bool, are. Otherwise an |
| 4590 * error is reported on the expression. | 5144 * error is reported on the expression. |
| 4591 * | 5145 * |
| 4592 * See [StaticTypeWarningCode.NON_BOOL_CONDITION]. | 5146 * See [StaticTypeWarningCode.NON_BOOL_CONDITION]. |
| 4593 */ | 5147 */ |
| 4594 bool _checkForNonBoolCondition(Expression condition) { | 5148 void _checkForNonBoolCondition(Expression condition) { |
| 4595 DartType conditionType = getStaticType(condition); | 5149 DartType conditionType = getStaticType(condition); |
| 4596 if (conditionType != null && | 5150 if (conditionType != null && |
| 4597 !_typeSystem.isAssignableTo(conditionType, _boolType)) { | 5151 !_typeSystem.isAssignableTo(conditionType, _boolType)) { |
| 4598 _errorReporter.reportErrorForNode( | 5152 _errorReporter.reportErrorForNode( |
| 4599 StaticTypeWarningCode.NON_BOOL_CONDITION, condition); | 5153 StaticTypeWarningCode.NON_BOOL_CONDITION, condition); |
| 4600 return true; | |
| 4601 } | 5154 } |
| 4602 return false; | |
| 4603 } | 5155 } |
| 4604 | 5156 |
| 4605 /** | 5157 /** |
| 4606 * Verify that the given assert [statement] has either a 'bool' or | 5158 * Verify that the given assert [statement] has either a 'bool' or |
| 4607 * '() -> bool' input. | 5159 * '() -> bool' input. |
| 4608 * | 5160 * |
| 4609 * See [StaticTypeWarningCode.NON_BOOL_EXPRESSION]. | 5161 * See [StaticTypeWarningCode.NON_BOOL_EXPRESSION]. |
| 4610 */ | 5162 */ |
| 4611 bool _checkForNonBoolExpression(AssertStatement statement) { | 5163 void _checkForNonBoolExpression(AssertStatement statement) { |
| 4612 Expression expression = statement.condition; | 5164 Expression expression = statement.condition; |
| 4613 DartType type = getStaticType(expression); | 5165 DartType type = getStaticType(expression); |
| 4614 if (type is InterfaceType) { | 5166 if (type is InterfaceType) { |
| 4615 if (!_typeSystem.isAssignableTo(type, _boolType)) { | 5167 if (!_typeSystem.isAssignableTo(type, _boolType)) { |
| 4616 _errorReporter.reportErrorForNode( | 5168 _errorReporter.reportErrorForNode( |
| 4617 StaticTypeWarningCode.NON_BOOL_EXPRESSION, expression); | 5169 StaticTypeWarningCode.NON_BOOL_EXPRESSION, expression); |
| 4618 return true; | |
| 4619 } | 5170 } |
| 4620 } else if (type is FunctionType) { | 5171 } else if (type is FunctionType) { |
| 4621 FunctionType functionType = type; | 5172 if (type.typeArguments.length == 0 && |
| 4622 if (functionType.typeArguments.length == 0 && | 5173 !_typeSystem.isAssignableTo(type.returnType, _boolType)) { |
| 4623 !_typeSystem.isAssignableTo(functionType.returnType, _boolType)) { | |
| 4624 _errorReporter.reportErrorForNode( | 5174 _errorReporter.reportErrorForNode( |
| 4625 StaticTypeWarningCode.NON_BOOL_EXPRESSION, expression); | 5175 StaticTypeWarningCode.NON_BOOL_EXPRESSION, expression); |
| 4626 return true; | |
| 4627 } | 5176 } |
| 4628 } | 5177 } |
| 4629 return false; | |
| 4630 } | 5178 } |
| 4631 | 5179 |
| 4632 /** | 5180 /** |
| 4633 * Checks to ensure that the given [expression] is assignable to bool. | 5181 * Checks to ensure that the given [expression] is assignable to bool. |
| 4634 * | 5182 * |
| 4635 * See [StaticTypeWarningCode.NON_BOOL_NEGATION_EXPRESSION]. | 5183 * See [StaticTypeWarningCode.NON_BOOL_NEGATION_EXPRESSION]. |
| 4636 */ | 5184 */ |
| 4637 bool _checkForNonBoolNegationExpression(Expression expression) { | 5185 void _checkForNonBoolNegationExpression(Expression expression) { |
| 4638 DartType conditionType = getStaticType(expression); | 5186 DartType conditionType = getStaticType(expression); |
| 4639 if (conditionType != null && | 5187 if (conditionType != null && |
| 4640 !_typeSystem.isAssignableTo(conditionType, _boolType)) { | 5188 !_typeSystem.isAssignableTo(conditionType, _boolType)) { |
| 4641 _errorReporter.reportErrorForNode( | 5189 _errorReporter.reportErrorForNode( |
| 4642 StaticTypeWarningCode.NON_BOOL_NEGATION_EXPRESSION, expression); | 5190 StaticTypeWarningCode.NON_BOOL_NEGATION_EXPRESSION, expression); |
| 4643 return true; | |
| 4644 } | 5191 } |
| 4645 return false; | |
| 4646 } | 5192 } |
| 4647 | 5193 |
| 4648 /** | 5194 /** |
| 4649 * Verify the given map [literal] either: | 5195 * Verify the given map [literal] either: |
| 4650 * * has `const modifier` | 5196 * * has `const modifier` |
| 4651 * * has explicit type arguments | 5197 * * has explicit type arguments |
| 4652 * * is not start of the statement | 5198 * * is not start of the statement |
| 4653 * | 5199 * |
| 4654 * See [CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION_STATEMENT]. | 5200 * See [CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION_STATEMENT]. |
| 4655 */ | 5201 */ |
| 4656 bool _checkForNonConstMapAsExpressionStatement(MapLiteral literal) { | 5202 void _checkForNonConstMapAsExpressionStatement(MapLiteral literal) { |
| 4657 // "const" | 5203 // "const" |
| 4658 if (literal.constKeyword != null) { | 5204 if (literal.constKeyword != null) { |
| 4659 return false; | 5205 return; |
| 4660 } | 5206 } |
| 4661 // has type arguments | 5207 // has type arguments |
| 4662 if (literal.typeArguments != null) { | 5208 if (literal.typeArguments != null) { |
| 4663 return false; | 5209 return; |
| 4664 } | 5210 } |
| 4665 // prepare statement | 5211 // prepare statement |
| 4666 Statement statement = | 5212 Statement statement = |
| 4667 literal.getAncestor((node) => node is ExpressionStatement); | 5213 literal.getAncestor((node) => node is ExpressionStatement); |
| 4668 if (statement == null) { | 5214 if (statement == null) { |
| 4669 return false; | 5215 return; |
| 4670 } | 5216 } |
| 4671 // OK, statement does not start with map | 5217 // OK, statement does not start with map |
| 4672 if (!identical(statement.beginToken, literal.beginToken)) { | 5218 if (!identical(statement.beginToken, literal.beginToken)) { |
| 4673 return false; | 5219 return; |
| 4674 } | 5220 } |
| 4675 // report problem | 5221 |
| 4676 _errorReporter.reportErrorForNode( | 5222 _errorReporter.reportErrorForNode( |
| 4677 CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION_STATEMENT, literal); | 5223 CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION_STATEMENT, literal); |
| 4678 return true; | |
| 4679 } | 5224 } |
| 4680 | 5225 |
| 4681 /** | 5226 /** |
| 4682 * Verify that the given method [declaration] of operator `[]=`, has `void` | 5227 * Verify that the given method [declaration] of operator `[]=`, has `void` |
| 4683 * return type. | 5228 * return type. |
| 4684 * | 5229 * |
| 4685 * See [StaticWarningCode.NON_VOID_RETURN_FOR_OPERATOR]. | 5230 * See [StaticWarningCode.NON_VOID_RETURN_FOR_OPERATOR]. |
| 4686 */ | 5231 */ |
| 4687 bool _checkForNonVoidReturnTypeForOperator(MethodDeclaration declaration) { | 5232 void _checkForNonVoidReturnTypeForOperator(MethodDeclaration declaration) { |
| 4688 // check that []= operator | 5233 // check that []= operator |
| 4689 SimpleIdentifier name = declaration.name; | 5234 SimpleIdentifier name = declaration.name; |
| 4690 if (name.name != "[]=") { | 5235 if (name.name != "[]=") { |
| 4691 return false; | 5236 return; |
| 4692 } | 5237 } |
| 4693 // check return type | 5238 // check return type |
| 4694 TypeName typeName = declaration.returnType; | 5239 TypeName typeName = declaration.returnType; |
| 4695 if (typeName != null) { | 5240 if (typeName != null) { |
| 4696 DartType type = typeName.type; | 5241 DartType type = typeName.type; |
| 4697 if (type != null && !type.isVoid) { | 5242 if (type != null && !type.isVoid) { |
| 4698 _errorReporter.reportErrorForNode( | 5243 _errorReporter.reportErrorForNode( |
| 4699 StaticWarningCode.NON_VOID_RETURN_FOR_OPERATOR, typeName); | 5244 StaticWarningCode.NON_VOID_RETURN_FOR_OPERATOR, typeName); |
| 4700 } | 5245 } |
| 4701 } | 5246 } |
| 4702 // no warning | |
| 4703 return false; | |
| 4704 } | 5247 } |
| 4705 | 5248 |
| 4706 /** | 5249 /** |
| 4707 * Verify the [typeName], used as the return type of a setter, is valid | 5250 * Verify the [typeName], used as the return type of a setter, is valid |
| 4708 * (either `null` or the type 'void'). | 5251 * (either `null` or the type 'void'). |
| 4709 * | 5252 * |
| 4710 * See [StaticWarningCode.NON_VOID_RETURN_FOR_SETTER]. | 5253 * See [StaticWarningCode.NON_VOID_RETURN_FOR_SETTER]. |
| 4711 */ | 5254 */ |
| 4712 bool _checkForNonVoidReturnTypeForSetter(TypeName typeName) { | 5255 void _checkForNonVoidReturnTypeForSetter(TypeName typeName) { |
| 4713 if (typeName != null) { | 5256 if (typeName != null) { |
| 4714 DartType type = typeName.type; | 5257 DartType type = typeName.type; |
| 4715 if (type != null && !type.isVoid) { | 5258 if (type != null && !type.isVoid) { |
| 4716 _errorReporter.reportErrorForNode( | 5259 _errorReporter.reportErrorForNode( |
| 4717 StaticWarningCode.NON_VOID_RETURN_FOR_SETTER, typeName); | 5260 StaticWarningCode.NON_VOID_RETURN_FOR_SETTER, typeName); |
| 4718 } | 5261 } |
| 4719 } | 5262 } |
| 4720 return false; | |
| 4721 } | 5263 } |
| 4722 | 5264 |
| 4723 /** | 5265 /** |
| 4724 * Verify the given operator-method [declaration], does not have an optional | 5266 * Verify the given operator-method [declaration], does not have an optional |
| 4725 * parameter. This method assumes that the method declaration was tested to be | 5267 * parameter. This method assumes that the method declaration was tested to be |
| 4726 * an operator declaration before being called. | 5268 * an operator declaration before being called. |
| 4727 * | 5269 * |
| 4728 * See [CompileTimeErrorCode.OPTIONAL_PARAMETER_IN_OPERATOR]. | 5270 * See [CompileTimeErrorCode.OPTIONAL_PARAMETER_IN_OPERATOR]. |
| 4729 */ | 5271 */ |
| 4730 bool _checkForOptionalParameterInOperator(MethodDeclaration declaration) { | 5272 void _checkForOptionalParameterInOperator(MethodDeclaration declaration) { |
| 4731 FormalParameterList parameterList = declaration.parameters; | 5273 FormalParameterList parameterList = declaration.parameters; |
| 4732 if (parameterList == null) { | 5274 if (parameterList == null) { |
| 4733 return false; | 5275 return; |
| 4734 } | 5276 } |
| 4735 bool foundError = false; | 5277 |
| 4736 NodeList<FormalParameter> formalParameters = parameterList.parameters; | 5278 NodeList<FormalParameter> formalParameters = parameterList.parameters; |
| 4737 for (FormalParameter formalParameter in formalParameters) { | 5279 for (FormalParameter formalParameter in formalParameters) { |
| 4738 if (formalParameter.kind.isOptional) { | 5280 if (formalParameter.kind.isOptional) { |
| 4739 _errorReporter.reportErrorForNode( | 5281 _errorReporter.reportErrorForNode( |
| 4740 CompileTimeErrorCode.OPTIONAL_PARAMETER_IN_OPERATOR, | 5282 CompileTimeErrorCode.OPTIONAL_PARAMETER_IN_OPERATOR, |
| 4741 formalParameter); | 5283 formalParameter); |
| 4742 foundError = true; | |
| 4743 } | 5284 } |
| 4744 } | 5285 } |
| 4745 return foundError; | |
| 4746 } | 5286 } |
| 4747 | 5287 |
| 4748 /** | 5288 /** |
| 4749 * Check that the given named optional [parameter] does not begin with '_'. | 5289 * Check that the given named optional [parameter] does not begin with '_'. |
| 4750 * | 5290 * |
| 4751 * See [CompileTimeErrorCode.PRIVATE_OPTIONAL_PARAMETER]. | 5291 * See [CompileTimeErrorCode.PRIVATE_OPTIONAL_PARAMETER]. |
| 4752 */ | 5292 */ |
| 4753 bool _checkForPrivateOptionalParameter(FormalParameter parameter) { | 5293 void _checkForPrivateOptionalParameter(FormalParameter parameter) { |
| 4754 // should be named parameter | 5294 // should be named parameter |
| 4755 if (parameter.kind != ParameterKind.NAMED) { | 5295 if (parameter.kind != ParameterKind.NAMED) { |
| 4756 return false; | 5296 return; |
| 4757 } | 5297 } |
| 4758 // name should start with '_' | 5298 // name should start with '_' |
| 4759 SimpleIdentifier name = parameter.identifier; | 5299 SimpleIdentifier name = parameter.identifier; |
| 4760 if (name.isSynthetic || !StringUtilities.startsWithChar(name.name, 0x5F)) { | 5300 if (name.isSynthetic || !StringUtilities.startsWithChar(name.name, 0x5F)) { |
| 4761 return false; | 5301 return; |
| 4762 } | 5302 } |
| 4763 // report problem | 5303 |
| 4764 _errorReporter.reportErrorForNode( | 5304 _errorReporter.reportErrorForNode( |
| 4765 CompileTimeErrorCode.PRIVATE_OPTIONAL_PARAMETER, parameter); | 5305 CompileTimeErrorCode.PRIVATE_OPTIONAL_PARAMETER, parameter); |
| 4766 return true; | |
| 4767 } | 5306 } |
| 4768 | 5307 |
| 4769 /** | 5308 /** |
| 4770 * Check whether the given constructor [declaration] is the redirecting | 5309 * Check whether the given constructor [declaration] is the redirecting |
| 4771 * generative constructor and references itself directly or indirectly. The | 5310 * generative constructor and references itself directly or indirectly. The |
| 4772 * [constructorElement] is the constructor element. | 5311 * [constructorElement] is the constructor element. |
| 4773 * | 5312 * |
| 4774 * See [CompileTimeErrorCode.RECURSIVE_CONSTRUCTOR_REDIRECT]. | 5313 * See [CompileTimeErrorCode.RECURSIVE_CONSTRUCTOR_REDIRECT]. |
| 4775 */ | 5314 */ |
| 4776 bool _checkForRecursiveConstructorRedirect(ConstructorDeclaration declaration, | 5315 void _checkForRecursiveConstructorRedirect(ConstructorDeclaration declaration, |
| 4777 ConstructorElement constructorElement) { | 5316 ConstructorElement constructorElement) { |
| 4778 // we check generative constructor here | 5317 // we check generative constructor here |
| 4779 if (declaration.factoryKeyword != null) { | 5318 if (declaration.factoryKeyword != null) { |
| 4780 return false; | 5319 return; |
| 4781 } | 5320 } |
| 4782 // try to find redirecting constructor invocation and analyzer it for | 5321 // try to find redirecting constructor invocation and analyze it for |
| 4783 // recursion | 5322 // recursion |
| 4784 for (ConstructorInitializer initializer in declaration.initializers) { | 5323 for (ConstructorInitializer initializer in declaration.initializers) { |
| 4785 if (initializer is RedirectingConstructorInvocation) { | 5324 if (initializer is RedirectingConstructorInvocation) { |
| 4786 // OK if no cycle | 5325 if (_hasRedirectingFactoryConstructorCycle(constructorElement)) { |
| 4787 if (!_hasRedirectingFactoryConstructorCycle(constructorElement)) { | 5326 _errorReporter.reportErrorForNode( |
| 4788 return false; | 5327 CompileTimeErrorCode.RECURSIVE_CONSTRUCTOR_REDIRECT, initializer); |
| 4789 } | 5328 } |
| 4790 // report error | 5329 return; |
| 4791 _errorReporter.reportErrorForNode( | |
| 4792 CompileTimeErrorCode.RECURSIVE_CONSTRUCTOR_REDIRECT, initializer); | |
| 4793 return true; | |
| 4794 } | 5330 } |
| 4795 } | 5331 } |
| 4796 // OK, no redirecting constructor invocation | |
| 4797 return false; | |
| 4798 } | 5332 } |
| 4799 | 5333 |
| 4800 /** | 5334 /** |
| 4801 * Check whether the given constructor [declaration] has redirected | 5335 * Check whether the given constructor [declaration] has redirected |
| 4802 * constructor and references itself directly or indirectly. The | 5336 * constructor and references itself directly or indirectly. The |
| 4803 * constructor [element] is the element introduced by the declaration. | 5337 * constructor [element] is the element introduced by the declaration. |
| 4804 * | 5338 * |
| 4805 * See [CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT]. | 5339 * See [CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT]. |
| 4806 */ | 5340 */ |
| 4807 bool _checkForRecursiveFactoryRedirect( | 5341 bool _checkForRecursiveFactoryRedirect( |
| (...skipping 15 matching lines...) Expand all Loading... |
| 4823 return true; | 5357 return true; |
| 4824 } | 5358 } |
| 4825 | 5359 |
| 4826 /** | 5360 /** |
| 4827 * Check that the class [element] is not a superinterface to itself. | 5361 * Check that the class [element] is not a superinterface to itself. |
| 4828 * | 5362 * |
| 4829 * See [CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE], | 5363 * See [CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE], |
| 4830 * [CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_EXTENDS], a
nd | 5364 * [CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_EXTENDS], a
nd |
| 4831 * [CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_IMPLEMENTS]
. | 5365 * [CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_IMPLEMENTS]
. |
| 4832 */ | 5366 */ |
| 4833 bool _checkForRecursiveInterfaceInheritance(ClassElement element) { | 5367 void _checkForRecursiveInterfaceInheritance(ClassElement element) { |
| 4834 if (element == null) { | 5368 if (element == null) { |
| 4835 return false; | 5369 return; |
| 4836 } | 5370 } |
| 4837 return _safeCheckForRecursiveInterfaceInheritance( | 5371 |
| 4838 element, new List<ClassElement>()); | 5372 _safeCheckForRecursiveInterfaceInheritance(element, <ClassElement>[]); |
| 4839 } | 5373 } |
| 4840 | 5374 |
| 4841 /** | 5375 /** |
| 4842 * Check that the given constructor [declaration] has a valid combination of | 5376 * Check that the given constructor [declaration] has a valid combination of |
| 4843 * redirected constructor invocation(s), super constructor invocations and | 5377 * redirected constructor invocation(s), super constructor invocations and |
| 4844 * field initializers. | 5378 * field initializers. |
| 4845 * | 5379 * |
| 4846 * See [CompileTimeErrorCode.DEFAULT_VALUE_IN_REDIRECTING_FACTORY_CONSTRUCTOR]
, | 5380 * See [CompileTimeErrorCode.DEFAULT_VALUE_IN_REDIRECTING_FACTORY_CONSTRUCTOR]
, |
| 4847 * [CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR], | 5381 * [CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR], |
| 4848 * [CompileTimeErrorCode.MULTIPLE_REDIRECTING_CONSTRUCTOR_INVOCATIONS], | 5382 * [CompileTimeErrorCode.MULTIPLE_REDIRECTING_CONSTRUCTOR_INVOCATIONS], |
| 4849 * [CompileTimeErrorCode.SUPER_IN_REDIRECTING_CONSTRUCTOR], and | 5383 * [CompileTimeErrorCode.SUPER_IN_REDIRECTING_CONSTRUCTOR], and |
| 4850 * [CompileTimeErrorCode.REDIRECT_GENERATIVE_TO_NON_GENERATIVE_CONSTRUCTOR]. | 5384 * [CompileTimeErrorCode.REDIRECT_GENERATIVE_TO_NON_GENERATIVE_CONSTRUCTOR]. |
| 4851 */ | 5385 */ |
| 4852 bool _checkForRedirectingConstructorErrorCodes( | 5386 void _checkForRedirectingConstructorErrorCodes( |
| 4853 ConstructorDeclaration declaration) { | 5387 ConstructorDeclaration declaration) { |
| 4854 bool errorReported = false; | |
| 4855 // | |
| 4856 // Check for default values in the parameters | 5388 // Check for default values in the parameters |
| 4857 // | |
| 4858 ConstructorName redirectedConstructor = declaration.redirectedConstructor; | 5389 ConstructorName redirectedConstructor = declaration.redirectedConstructor; |
| 4859 if (redirectedConstructor != null) { | 5390 if (redirectedConstructor != null) { |
| 4860 for (FormalParameter parameter in declaration.parameters.parameters) { | 5391 for (FormalParameter parameter in declaration.parameters.parameters) { |
| 4861 if (parameter is DefaultFormalParameter && | 5392 if (parameter is DefaultFormalParameter && |
| 4862 parameter.defaultValue != null) { | 5393 parameter.defaultValue != null) { |
| 4863 _errorReporter.reportErrorForNode( | 5394 _errorReporter.reportErrorForNode( |
| 4864 CompileTimeErrorCode.DEFAULT_VALUE_IN_REDIRECTING_FACTORY_CONSTRUC
TOR, | 5395 CompileTimeErrorCode |
| 5396 .DEFAULT_VALUE_IN_REDIRECTING_FACTORY_CONSTRUCTOR, |
| 4865 parameter.identifier); | 5397 parameter.identifier); |
| 4866 errorReported = true; | |
| 4867 } | 5398 } |
| 4868 } | 5399 } |
| 4869 } | 5400 } |
| 4870 // check if there are redirected invocations | 5401 // check if there are redirected invocations |
| 4871 int numRedirections = 0; | 5402 int numRedirections = 0; |
| 4872 for (ConstructorInitializer initializer in declaration.initializers) { | 5403 for (ConstructorInitializer initializer in declaration.initializers) { |
| 4873 if (initializer is RedirectingConstructorInvocation) { | 5404 if (initializer is RedirectingConstructorInvocation) { |
| 4874 if (numRedirections > 0) { | 5405 if (numRedirections > 0) { |
| 4875 _errorReporter.reportErrorForNode( | 5406 _errorReporter.reportErrorForNode( |
| 4876 CompileTimeErrorCode.MULTIPLE_REDIRECTING_CONSTRUCTOR_INVOCATIONS, | 5407 CompileTimeErrorCode.MULTIPLE_REDIRECTING_CONSTRUCTOR_INVOCATIONS, |
| 4877 initializer); | 5408 initializer); |
| 4878 errorReported = true; | |
| 4879 } | 5409 } |
| 4880 if (declaration.factoryKeyword == null) { | 5410 if (declaration.factoryKeyword == null) { |
| 4881 RedirectingConstructorInvocation invocation = initializer; | 5411 RedirectingConstructorInvocation invocation = initializer; |
| 4882 ConstructorElement redirectingElement = invocation.staticElement; | 5412 ConstructorElement redirectingElement = invocation.staticElement; |
| 4883 if (redirectingElement == null) { | 5413 if (redirectingElement == null) { |
| 4884 String enclosingTypeName = _enclosingClass.displayName; | 5414 String enclosingTypeName = _enclosingClass.displayName; |
| 4885 String constructorStrName = enclosingTypeName; | 5415 String constructorStrName = enclosingTypeName; |
| 4886 if (invocation.constructorName != null) { | 5416 if (invocation.constructorName != null) { |
| 4887 constructorStrName += ".${invocation.constructorName.name}"; | 5417 constructorStrName += ".${invocation.constructorName.name}"; |
| 4888 } | 5418 } |
| 4889 _errorReporter.reportErrorForNode( | 5419 _errorReporter.reportErrorForNode( |
| 4890 CompileTimeErrorCode.REDIRECT_GENERATIVE_TO_MISSING_CONSTRUCTOR, | 5420 CompileTimeErrorCode.REDIRECT_GENERATIVE_TO_MISSING_CONSTRUCTOR, |
| 4891 invocation, | 5421 invocation, |
| 4892 [constructorStrName, enclosingTypeName]); | 5422 [constructorStrName, enclosingTypeName]); |
| 4893 } else { | 5423 } else { |
| 4894 if (redirectingElement.isFactory) { | 5424 if (redirectingElement.isFactory) { |
| 4895 _errorReporter.reportErrorForNode( | 5425 _errorReporter.reportErrorForNode( |
| 4896 CompileTimeErrorCode.REDIRECT_GENERATIVE_TO_NON_GENERATIVE_CON
STRUCTOR, | 5426 CompileTimeErrorCode |
| 5427 .REDIRECT_GENERATIVE_TO_NON_GENERATIVE_CONSTRUCTOR, |
| 4897 initializer); | 5428 initializer); |
| 4898 } | 5429 } |
| 4899 } | 5430 } |
| 4900 } | 5431 } |
| 4901 numRedirections++; | 5432 numRedirections++; |
| 4902 } | 5433 } |
| 4903 } | 5434 } |
| 4904 // check for other initializers | 5435 // check for other initializers |
| 4905 if (numRedirections > 0) { | 5436 if (numRedirections > 0) { |
| 4906 for (ConstructorInitializer initializer in declaration.initializers) { | 5437 for (ConstructorInitializer initializer in declaration.initializers) { |
| 4907 if (initializer is SuperConstructorInvocation) { | 5438 if (initializer is SuperConstructorInvocation) { |
| 4908 _errorReporter.reportErrorForNode( | 5439 _errorReporter.reportErrorForNode( |
| 4909 CompileTimeErrorCode.SUPER_IN_REDIRECTING_CONSTRUCTOR, | 5440 CompileTimeErrorCode.SUPER_IN_REDIRECTING_CONSTRUCTOR, |
| 4910 initializer); | 5441 initializer); |
| 4911 errorReported = true; | |
| 4912 } | 5442 } |
| 4913 if (initializer is ConstructorFieldInitializer) { | 5443 if (initializer is ConstructorFieldInitializer) { |
| 4914 _errorReporter.reportErrorForNode( | 5444 _errorReporter.reportErrorForNode( |
| 4915 CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR, | 5445 CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR, |
| 4916 initializer); | 5446 initializer); |
| 4917 errorReported = true; | |
| 4918 } | 5447 } |
| 4919 } | 5448 } |
| 4920 } | 5449 } |
| 4921 // done | |
| 4922 return errorReported; | |
| 4923 } | 5450 } |
| 4924 | 5451 |
| 4925 /** | 5452 /** |
| 4926 * Check whether the given constructor [declaration] has redirected | 5453 * Check whether the given constructor [declaration] has redirected |
| 4927 * constructor and references itself directly or indirectly. The | 5454 * constructor and references itself directly or indirectly. The |
| 4928 * constructor [element] is the element introduced by the declaration. | 5455 * constructor [element] is the element introduced by the declaration. |
| 4929 * | 5456 * |
| 4930 * See [CompileTimeErrorCode.REDIRECT_TO_NON_CONST_CONSTRUCTOR]. | 5457 * See [CompileTimeErrorCode.REDIRECT_TO_NON_CONST_CONSTRUCTOR]. |
| 4931 */ | 5458 */ |
| 4932 bool _checkForRedirectToNonConstConstructor( | 5459 void _checkForRedirectToNonConstConstructor( |
| 4933 ConstructorDeclaration declaration, ConstructorElement element) { | 5460 ConstructorDeclaration declaration, ConstructorElement element) { |
| 4934 // prepare redirected constructor | 5461 // prepare redirected constructor |
| 4935 ConstructorName redirectedConstructorNode = | 5462 ConstructorName redirectedConstructorNode = |
| 4936 declaration.redirectedConstructor; | 5463 declaration.redirectedConstructor; |
| 4937 if (redirectedConstructorNode == null) { | 5464 if (redirectedConstructorNode == null) { |
| 4938 return false; | 5465 return; |
| 4939 } | 5466 } |
| 4940 // prepare element | 5467 // prepare element |
| 4941 if (element == null) { | 5468 if (element == null) { |
| 4942 return false; | 5469 return; |
| 4943 } | 5470 } |
| 4944 // OK, it is not 'const' | 5471 // OK, it is not 'const' |
| 4945 if (!element.isConst) { | 5472 if (!element.isConst) { |
| 4946 return false; | 5473 return; |
| 4947 } | 5474 } |
| 4948 // prepare redirected constructor | 5475 // prepare redirected constructor |
| 4949 ConstructorElement redirectedConstructor = element.redirectedConstructor; | 5476 ConstructorElement redirectedConstructor = element.redirectedConstructor; |
| 4950 if (redirectedConstructor == null) { | 5477 if (redirectedConstructor == null) { |
| 4951 return false; | 5478 return; |
| 4952 } | 5479 } |
| 4953 // OK, it is also 'const' | 5480 // OK, it is also 'const' |
| 4954 if (redirectedConstructor.isConst) { | 5481 if (redirectedConstructor.isConst) { |
| 4955 return false; | 5482 return; |
| 4956 } | 5483 } |
| 4957 // report error | 5484 |
| 4958 _errorReporter.reportErrorForNode( | 5485 _errorReporter.reportErrorForNode( |
| 4959 CompileTimeErrorCode.REDIRECT_TO_NON_CONST_CONSTRUCTOR, | 5486 CompileTimeErrorCode.REDIRECT_TO_NON_CONST_CONSTRUCTOR, |
| 4960 redirectedConstructorNode); | 5487 redirectedConstructorNode); |
| 4961 return true; | 5488 } |
| 5489 |
| 5490 void _checkForReferenceBeforeDeclaration(SimpleIdentifier node) { |
| 5491 if (!node.inDeclarationContext() && |
| 5492 _hiddenElements != null && |
| 5493 _hiddenElements.contains(node.staticElement)) { |
| 5494 _errorReporter.reportErrorForNode( |
| 5495 CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION, |
| 5496 node, |
| 5497 [node.name]); |
| 5498 } |
| 4962 } | 5499 } |
| 4963 | 5500 |
| 4964 /** | 5501 /** |
| 4965 * Check that the given rethrow [expression] is inside of a catch clause. | 5502 * Check that the given rethrow [expression] is inside of a catch clause. |
| 4966 * | 5503 * |
| 4967 * See [CompileTimeErrorCode.RETHROW_OUTSIDE_CATCH]. | 5504 * See [CompileTimeErrorCode.RETHROW_OUTSIDE_CATCH]. |
| 4968 */ | 5505 */ |
| 4969 bool _checkForRethrowOutsideCatch(RethrowExpression expression) { | 5506 void _checkForRethrowOutsideCatch(RethrowExpression expression) { |
| 4970 if (!_isInCatchClause) { | 5507 if (!_isInCatchClause) { |
| 4971 _errorReporter.reportErrorForNode( | 5508 _errorReporter.reportErrorForNode( |
| 4972 CompileTimeErrorCode.RETHROW_OUTSIDE_CATCH, expression); | 5509 CompileTimeErrorCode.RETHROW_OUTSIDE_CATCH, expression); |
| 4973 return true; | |
| 4974 } | 5510 } |
| 4975 return false; | |
| 4976 } | 5511 } |
| 4977 | 5512 |
| 4978 /** | 5513 /** |
| 4979 * Check that if the the given constructor [declaration] is generative, then | 5514 * Check that if the given constructor [declaration] is generative, then |
| 4980 * it does not have an expression function body. | 5515 * it does not have an expression function body. |
| 4981 * | 5516 * |
| 4982 * See [CompileTimeErrorCode.RETURN_IN_GENERATIVE_CONSTRUCTOR]. | 5517 * See [CompileTimeErrorCode.RETURN_IN_GENERATIVE_CONSTRUCTOR]. |
| 4983 */ | 5518 */ |
| 4984 bool _checkForReturnInGenerativeConstructor( | 5519 void _checkForReturnInGenerativeConstructor( |
| 4985 ConstructorDeclaration declaration) { | 5520 ConstructorDeclaration declaration) { |
| 4986 // ignore factory | 5521 // ignore factory |
| 4987 if (declaration.factoryKeyword != null) { | 5522 if (declaration.factoryKeyword != null) { |
| 4988 return false; | 5523 return; |
| 4989 } | 5524 } |
| 4990 // block body (with possible return statement) is checked elsewhere | 5525 // block body (with possible return statement) is checked elsewhere |
| 4991 FunctionBody body = declaration.body; | 5526 FunctionBody body = declaration.body; |
| 4992 if (body is! ExpressionFunctionBody) { | 5527 if (body is! ExpressionFunctionBody) { |
| 4993 return false; | 5528 return; |
| 4994 } | 5529 } |
| 4995 // report error | 5530 |
| 4996 _errorReporter.reportErrorForNode( | 5531 _errorReporter.reportErrorForNode( |
| 4997 CompileTimeErrorCode.RETURN_IN_GENERATIVE_CONSTRUCTOR, body); | 5532 CompileTimeErrorCode.RETURN_IN_GENERATIVE_CONSTRUCTOR, body); |
| 4998 return true; | |
| 4999 } | 5533 } |
| 5000 | 5534 |
| 5001 /** | 5535 /** |
| 5002 * Check that a type mis-match between the type of the [returnExpression] and | 5536 * Check that a type mis-match between the type of the [returnExpression] and |
| 5003 * the [expectedReturnType] by the enclosing method or function. | 5537 * the [expectedReturnType] by the enclosing method or function. |
| 5004 * | 5538 * |
| 5005 * This method is called both by [_checkForAllReturnStatementErrorCodes] | 5539 * This method is called both by [_checkForAllReturnStatementErrorCodes] |
| 5006 * and [visitExpressionFunctionBody]. | 5540 * and [visitExpressionFunctionBody]. |
| 5007 * | 5541 * |
| 5008 * See [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]. | 5542 * See [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]. |
| 5009 */ | 5543 */ |
| 5010 bool _checkForReturnOfInvalidType( | 5544 void _checkForReturnOfInvalidType( |
| 5011 Expression returnExpression, DartType expectedReturnType) { | 5545 Expression returnExpression, DartType expectedReturnType) { |
| 5012 if (_enclosingFunction == null) { | 5546 if (_enclosingFunction == null) { |
| 5013 return false; | 5547 return; |
| 5014 } | 5548 } |
| 5015 if (_inGenerator) { | 5549 if (_inGenerator) { |
| 5016 // "return expression;" is disallowed in generators, but this is checked | 5550 // "return expression;" is disallowed in generators, but this is checked |
| 5017 // elsewhere. Bare "return" is always allowed in generators regardless | 5551 // elsewhere. Bare "return" is always allowed in generators regardless |
| 5018 // of the return type. So no need to do any further checking. | 5552 // of the return type. So no need to do any further checking. |
| 5019 return false; | 5553 return; |
| 5020 } | 5554 } |
| 5021 DartType staticReturnType = _computeReturnTypeForMethod(returnExpression); | 5555 DartType staticReturnType = _computeReturnTypeForMethod(returnExpression); |
| 5022 if (expectedReturnType.isVoid) { | 5556 if (expectedReturnType.isVoid) { |
| 5023 if (staticReturnType.isVoid || | 5557 if (staticReturnType.isVoid || |
| 5024 staticReturnType.isDynamic || | 5558 staticReturnType.isDynamic || |
| 5025 staticReturnType.isBottom) { | 5559 staticReturnType.isBottom) { |
| 5026 return false; | 5560 return; |
| 5027 } | 5561 } |
| 5028 _errorReporter.reportTypeErrorForNode( | 5562 _errorReporter.reportTypeErrorForNode( |
| 5029 StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, returnExpression, [ | 5563 StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, returnExpression, [ |
| 5030 staticReturnType, | 5564 staticReturnType, |
| 5031 expectedReturnType, | 5565 expectedReturnType, |
| 5032 _enclosingFunction.displayName | 5566 _enclosingFunction.displayName |
| 5033 ]); | 5567 ]); |
| 5034 return true; | 5568 return; |
| 5035 } | 5569 } |
| 5036 if (_typeSystem.isAssignableTo(staticReturnType, expectedReturnType)) { | 5570 if (_expressionIsAssignableAtType( |
| 5037 return false; | 5571 returnExpression, staticReturnType, expectedReturnType)) { |
| 5572 return; |
| 5038 } | 5573 } |
| 5039 _errorReporter.reportTypeErrorForNode( | 5574 _errorReporter.reportTypeErrorForNode( |
| 5040 StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, | 5575 StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, |
| 5041 returnExpression, | 5576 returnExpression, |
| 5042 [staticReturnType, expectedReturnType, _enclosingFunction.displayName]); | 5577 [staticReturnType, expectedReturnType, _enclosingFunction.displayName]); |
| 5043 return true; | 5578 |
| 5044 // TODO(brianwilkerson) Define a hint corresponding to the warning and | 5579 // TODO(brianwilkerson) Define a hint corresponding to the warning and |
| 5045 // report it if appropriate. | 5580 // report it if appropriate. |
| 5046 // Type propagatedReturnType = returnExpression.getPropagatedType(); | 5581 // Type propagatedReturnType = returnExpression.getPropagatedType(); |
| 5047 // boolean isPropagatedAssignable = propagatedReturnType.isAssignableTo(e
xpectedReturnType); | 5582 // boolean isPropagatedAssignable = propagatedReturnType.isAssignableTo(e
xpectedReturnType); |
| 5048 // if (isStaticAssignable || isPropagatedAssignable) { | 5583 // if (isStaticAssignable || isPropagatedAssignable) { |
| 5049 // return false; | 5584 // return false; |
| 5050 // } | 5585 // } |
| 5051 // errorReporter.reportTypeErrorForNode( | 5586 // errorReporter.reportTypeErrorForNode( |
| 5052 // StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, | 5587 // StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, |
| 5053 // returnExpression, | 5588 // returnExpression, |
| 5054 // staticReturnType, | 5589 // staticReturnType, |
| 5055 // expectedReturnType, | 5590 // expectedReturnType, |
| 5056 // enclosingFunction.getDisplayName()); | 5591 // enclosingFunction.getDisplayName()); |
| 5057 // return true; | 5592 // return true; |
| 5058 } | 5593 } |
| 5059 | 5594 |
| 5060 /** | 5595 /** |
| 5061 * Check the given [typeReference] and that the [name] is not the reference to | 5596 * Check the given [typeReference] and that the [name] is not a reference to |
| 5062 * an instance member. | 5597 * an instance member. |
| 5063 * | 5598 * |
| 5064 * See [StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER]. | 5599 * See [StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER]. |
| 5065 */ | 5600 */ |
| 5066 bool _checkForStaticAccessToInstanceMember( | 5601 void _checkForStaticAccessToInstanceMember( |
| 5067 ClassElement typeReference, SimpleIdentifier name) { | 5602 ClassElement typeReference, SimpleIdentifier name) { |
| 5603 // OK, in comment |
| 5604 if (_isInComment) { |
| 5605 return; |
| 5606 } |
| 5068 // OK, target is not a type | 5607 // OK, target is not a type |
| 5069 if (typeReference == null) { | 5608 if (typeReference == null) { |
| 5070 return false; | 5609 return; |
| 5071 } | 5610 } |
| 5072 // prepare member Element | 5611 // prepare member Element |
| 5073 Element element = name.staticElement; | 5612 Element element = name.staticElement; |
| 5074 if (element is! ExecutableElement) { | 5613 if (element is ExecutableElement) { |
| 5075 return false; | 5614 // OK, static |
| 5615 if (element.isStatic) { |
| 5616 return; |
| 5617 } |
| 5618 _errorReporter.reportErrorForNode( |
| 5619 StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER, |
| 5620 name, |
| 5621 [name.name]); |
| 5076 } | 5622 } |
| 5077 ExecutableElement memberElement = element as ExecutableElement; | |
| 5078 // OK, static | |
| 5079 if (memberElement.isStatic) { | |
| 5080 return false; | |
| 5081 } | |
| 5082 // report problem | |
| 5083 _errorReporter.reportErrorForNode( | |
| 5084 StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER, name, [name.name]); | |
| 5085 return true; | |
| 5086 } | 5623 } |
| 5087 | 5624 |
| 5088 /** | 5625 /** |
| 5089 * Check that the type of the expression in the given 'switch' [statement] is | 5626 * Check that the type of the expression in the given 'switch' [statement] is |
| 5090 * assignable to the type of the 'case' members. | 5627 * assignable to the type of the 'case' members. |
| 5091 * | 5628 * |
| 5092 * See [StaticWarningCode.SWITCH_EXPRESSION_NOT_ASSIGNABLE]. | 5629 * See [StaticWarningCode.SWITCH_EXPRESSION_NOT_ASSIGNABLE]. |
| 5093 */ | 5630 */ |
| 5094 bool _checkForSwitchExpressionNotAssignable(SwitchStatement statement) { | 5631 void _checkForSwitchExpressionNotAssignable(SwitchStatement statement) { |
| 5095 // prepare 'switch' expression type | 5632 // prepare 'switch' expression type |
| 5096 Expression expression = statement.expression; | 5633 Expression expression = statement.expression; |
| 5097 DartType expressionType = getStaticType(expression); | 5634 DartType expressionType = getStaticType(expression); |
| 5098 if (expressionType == null) { | 5635 if (expressionType == null) { |
| 5099 return false; | 5636 return; |
| 5100 } | 5637 } |
| 5101 // compare with type of the first 'case' | 5638 |
| 5102 NodeList<SwitchMember> members = statement.members; | 5639 // compare with type of the first non-default 'case' |
| 5103 for (SwitchMember switchMember in members) { | 5640 SwitchCase switchCase = statement.members |
| 5104 if (switchMember is! SwitchCase) { | 5641 .firstWhere((member) => member is SwitchCase, orElse: () => null); |
| 5105 continue; | 5642 if (switchCase == null) { |
| 5106 } | 5643 return; |
| 5107 SwitchCase switchCase = switchMember as SwitchCase; | 5644 } |
| 5108 // prepare 'case' type | 5645 |
| 5109 Expression caseExpression = switchCase.expression; | 5646 Expression caseExpression = switchCase.expression; |
| 5110 DartType caseType = getStaticType(caseExpression); | 5647 DartType caseType = getStaticType(caseExpression); |
| 5111 // check types | 5648 |
| 5112 if (_typeSystem.isAssignableTo(expressionType, caseType)) { | 5649 // check types |
| 5113 return false; | 5650 if (!_expressionIsAssignableAtType(expression, expressionType, caseType)) { |
| 5114 } | |
| 5115 // report problem | |
| 5116 _errorReporter.reportErrorForNode( | 5651 _errorReporter.reportErrorForNode( |
| 5117 StaticWarningCode.SWITCH_EXPRESSION_NOT_ASSIGNABLE, | 5652 StaticWarningCode.SWITCH_EXPRESSION_NOT_ASSIGNABLE, |
| 5118 expression, | 5653 expression, |
| 5119 [expressionType, caseType]); | 5654 [expressionType, caseType]); |
| 5120 return true; | |
| 5121 } | 5655 } |
| 5122 return false; | |
| 5123 } | 5656 } |
| 5124 | 5657 |
| 5125 /** | 5658 /** |
| 5126 * Verify that the given function type [alias] does not reference itself | 5659 * Verify that the given function type [alias] does not reference itself |
| 5127 * directly. | 5660 * directly. |
| 5128 * | 5661 * |
| 5129 * See [CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF]. | 5662 * See [CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF]. |
| 5130 */ | 5663 */ |
| 5131 bool _checkForTypeAliasCannotReferenceItself_function( | 5664 void _checkForTypeAliasCannotReferenceItself_function( |
| 5132 FunctionTypeAlias alias) { | 5665 FunctionTypeAlias alias) { |
| 5133 FunctionTypeAliasElement element = alias.element; | 5666 if (_hasTypedefSelfReference(alias.element)) { |
| 5134 if (!_hasTypedefSelfReference(element)) { | 5667 _errorReporter.reportErrorForNode( |
| 5135 return false; | 5668 CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, alias); |
| 5136 } | 5669 } |
| 5137 _errorReporter.reportErrorForNode( | |
| 5138 CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, alias); | |
| 5139 return true; | |
| 5140 } | 5670 } |
| 5141 | 5671 |
| 5142 /** | 5672 /** |
| 5143 * Verify that the given type [name] is not a deferred type. | 5673 * Verify that the given type [name] is not a deferred type. |
| 5144 * | 5674 * |
| 5145 * See [StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS]. | 5675 * See [StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS]. |
| 5146 */ | 5676 */ |
| 5147 bool _checkForTypeAnnotationDeferredClass(TypeName name) { | 5677 void _checkForTypeAnnotationDeferredClass(TypeName name) { |
| 5148 if (name != null && name.isDeferred) { | 5678 if (name != null && name.isDeferred) { |
| 5149 _errorReporter.reportErrorForNode( | 5679 _errorReporter.reportErrorForNode( |
| 5150 StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, name, [name.name]); | 5680 StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, name, [name.name]); |
| 5151 } | 5681 } |
| 5152 return false; | |
| 5153 } | 5682 } |
| 5154 | 5683 |
| 5155 /** | 5684 /** |
| 5156 * Verify that the type arguments in the given [typeName] are all within | 5685 * Verify that the type arguments in the given [typeName] are all within |
| 5157 * their bounds. | 5686 * their bounds. |
| 5158 * | 5687 * |
| 5159 * See [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]. | 5688 * See [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]. |
| 5160 */ | 5689 */ |
| 5161 bool _checkForTypeArgumentNotMatchingBounds(TypeName typeName) { | 5690 void _checkForTypeArgumentNotMatchingBounds(TypeName typeName) { |
| 5162 if (typeName.typeArguments == null) { | 5691 if (typeName.typeArguments == null) { |
| 5163 return false; | 5692 return; |
| 5164 } | 5693 } |
| 5165 // prepare Type | 5694 // prepare Type |
| 5166 DartType type = typeName.type; | 5695 DartType type = typeName.type; |
| 5167 if (type == null) { | 5696 if (type == null) { |
| 5168 return false; | 5697 return; |
| 5169 } | 5698 } |
| 5170 // prepare ClassElement | |
| 5171 Element element = type.element; | 5699 Element element = type.element; |
| 5172 if (element is! ClassElement) { | 5700 if (element is ClassElement) { |
| 5173 return false; | 5701 // prepare type parameters |
| 5174 } | 5702 List<TypeParameterElement> parameterElements = element.typeParameters; |
| 5175 ClassElement classElement = element as ClassElement; | 5703 List<DartType> parameterTypes = element.type.typeArguments; |
| 5176 // prepare type parameters | 5704 List<DartType> arguments = (type as ParameterizedType).typeArguments; |
| 5177 List<DartType> typeParameters = classElement.type.typeArguments; | 5705 // iterate over each bounded type parameter and corresponding argument |
| 5178 List<TypeParameterElement> boundingElts = classElement.typeParameters; | 5706 NodeList<TypeName> typeNameArgList = typeName.typeArguments.arguments; |
| 5179 // iterate over each bounded type parameter and corresponding argument | 5707 int loopThroughIndex = |
| 5180 NodeList<TypeName> typeNameArgList = typeName.typeArguments.arguments; | 5708 math.min(typeNameArgList.length, parameterElements.length); |
| 5181 List<DartType> typeArguments = (type as InterfaceType).typeArguments; | 5709 bool shouldSubstitute = |
| 5182 int loopThroughIndex = | 5710 arguments.length != 0 && arguments.length == parameterTypes.length; |
| 5183 math.min(typeNameArgList.length, boundingElts.length); | 5711 for (int i = 0; i < loopThroughIndex; i++) { |
| 5184 bool foundError = false; | 5712 TypeName argTypeName = typeNameArgList[i]; |
| 5185 for (int i = 0; i < loopThroughIndex; i++) { | 5713 DartType argType = argTypeName.type; |
| 5186 TypeName argTypeName = typeNameArgList[i]; | 5714 DartType boundType = parameterElements[i].bound; |
| 5187 DartType argType = argTypeName.type; | 5715 if (argType != null && boundType != null) { |
| 5188 DartType boundType = boundingElts[i].bound; | 5716 if (shouldSubstitute) { |
| 5189 if (argType != null && boundType != null) { | 5717 boundType = boundType.substitute2(arguments, parameterTypes); |
| 5190 if (typeArguments.length != 0 && | |
| 5191 typeArguments.length == typeParameters.length) { | |
| 5192 boundType = boundType.substitute2(typeArguments, typeParameters); | |
| 5193 } | |
| 5194 if (!_typeSystem.isSubtypeOf(argType, boundType)) { | |
| 5195 ErrorCode errorCode; | |
| 5196 if (_isInConstInstanceCreation) { | |
| 5197 errorCode = CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS; | |
| 5198 } else { | |
| 5199 errorCode = StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS; | |
| 5200 } | 5718 } |
| 5201 _errorReporter.reportTypeErrorForNode( | 5719 if (!_typeSystem.isSubtypeOf(argType, boundType)) { |
| 5202 errorCode, argTypeName, [argType, boundType]); | 5720 ErrorCode errorCode; |
| 5203 foundError = true; | 5721 if (_isInConstInstanceCreation) { |
| 5722 errorCode = |
| 5723 CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS; |
| 5724 } else { |
| 5725 errorCode = |
| 5726 StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS; |
| 5727 } |
| 5728 _errorReporter.reportTypeErrorForNode( |
| 5729 errorCode, argTypeName, [argType, boundType]); |
| 5730 } |
| 5204 } | 5731 } |
| 5205 } | 5732 } |
| 5206 } | 5733 } |
| 5207 return foundError; | |
| 5208 } | 5734 } |
| 5209 | 5735 |
| 5210 /** | 5736 /** |
| 5211 * Check whether the given type [name] is a type parameter being used to | 5737 * Check whether the given type [name] is a type parameter being used to |
| 5212 * define a static member. | 5738 * define a static member. |
| 5213 * | 5739 * |
| 5214 * See [StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC]. | 5740 * See [StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC]. |
| 5215 */ | 5741 */ |
| 5216 bool _checkForTypeParameterReferencedByStatic(TypeName name) { | 5742 void _checkForTypeParameterReferencedByStatic(TypeName name) { |
| 5217 if (_isInStaticMethod || _isInStaticVariableDeclaration) { | 5743 if (_isInStaticMethod || _isInStaticVariableDeclaration) { |
| 5218 DartType type = name.type; | 5744 DartType type = name.type; |
| 5219 if (type is TypeParameterType) { | 5745 // The class's type parameters are not in scope for static methods. |
| 5746 // However all other type parameters are legal (e.g. the static method's |
| 5747 // type parameters, or a local function's type parameters). |
| 5748 if (type is TypeParameterType && |
| 5749 type.element.enclosingElement is ClassElement) { |
| 5220 _errorReporter.reportErrorForNode( | 5750 _errorReporter.reportErrorForNode( |
| 5221 StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC, name); | 5751 StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC, name); |
| 5222 return true; | |
| 5223 } | 5752 } |
| 5224 } | 5753 } |
| 5225 return false; | |
| 5226 } | 5754 } |
| 5227 | 5755 |
| 5228 /** | 5756 /** |
| 5229 * Check whether the given type [parameter] is a supertype of its bound. | 5757 * Check whether the given type [parameter] is a supertype of its bound. |
| 5230 * | 5758 * |
| 5231 * See [StaticTypeWarningCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND]. | 5759 * See [StaticTypeWarningCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND]. |
| 5232 */ | 5760 */ |
| 5233 bool _checkForTypeParameterSupertypeOfItsBound(TypeParameter parameter) { | 5761 void _checkForTypeParameterSupertypeOfItsBound(TypeParameter parameter) { |
| 5234 TypeParameterElement element = parameter.element; | 5762 TypeParameterElement element = parameter.element; |
| 5235 // prepare bound | 5763 // prepare bound |
| 5236 DartType bound = element.bound; | 5764 DartType bound = element.bound; |
| 5237 if (bound == null) { | 5765 if (bound == null) { |
| 5238 return false; | 5766 return; |
| 5239 } | 5767 } |
| 5240 // OK, type parameter is not supertype of its bound | 5768 // OK, type parameter is not supertype of its bound |
| 5241 if (!bound.isMoreSpecificThan(element.type)) { | 5769 if (!bound.isMoreSpecificThan(element.type)) { |
| 5242 return false; | 5770 return; |
| 5243 } | 5771 } |
| 5244 // report problem | 5772 |
| 5245 _errorReporter.reportErrorForNode( | 5773 _errorReporter.reportErrorForNode( |
| 5246 StaticTypeWarningCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND, | 5774 StaticTypeWarningCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND, |
| 5247 parameter, | 5775 parameter, |
| 5248 [element.displayName]); | 5776 [element.displayName]); |
| 5249 return true; | |
| 5250 } | 5777 } |
| 5251 | 5778 |
| 5252 /** | 5779 /** |
| 5253 * Check that if the given generative [constructor] has neither an explicit | 5780 * Check that if the given generative [constructor] has neither an explicit |
| 5254 * super constructor invocation nor a redirecting constructor invocation, that | 5781 * super constructor invocation nor a redirecting constructor invocation, that |
| 5255 * the superclass has a default generative constructor. | 5782 * the superclass has a default generative constructor. |
| 5256 * | 5783 * |
| 5257 * See [CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT], | 5784 * See [CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT], |
| 5258 * [CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR], and | 5785 * [CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR], and |
| 5259 * [StaticWarningCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT]. | 5786 * [StaticWarningCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT]. |
| 5260 */ | 5787 */ |
| 5261 bool _checkForUndefinedConstructorInInitializerImplicit( | 5788 void _checkForUndefinedConstructorInInitializerImplicit( |
| 5262 ConstructorDeclaration constructor) { | 5789 ConstructorDeclaration constructor) { |
| 5263 if (_enclosingClass == null) { | 5790 if (_enclosingClass == null) { |
| 5264 return false; | 5791 return; |
| 5265 } | 5792 } |
| 5266 // do nothing if mixin errors have already been reported for this class. | 5793 // do nothing if mixin errors have already been reported for this class. |
| 5267 ClassElementImpl enclosingClass = _enclosingClass; | 5794 if (_enclosingClass.doesMixinLackConstructors) { |
| 5268 if (enclosingClass.doesMixinLackConstructors) { | 5795 return; |
| 5269 return false; | |
| 5270 } | 5796 } |
| 5271 // | 5797 |
| 5272 // Ignore if the constructor is not generative. | 5798 // Ignore if the constructor is not generative. |
| 5273 // | |
| 5274 if (constructor.factoryKeyword != null) { | 5799 if (constructor.factoryKeyword != null) { |
| 5275 return false; | 5800 return; |
| 5276 } | 5801 } |
| 5277 // | 5802 |
| 5278 // Ignore if the constructor has either an implicit super constructor | 5803 // Ignore if the constructor has either an implicit super constructor |
| 5279 // invocation or a redirecting constructor invocation. | 5804 // invocation or a redirecting constructor invocation. |
| 5280 // | |
| 5281 for (ConstructorInitializer constructorInitializer | 5805 for (ConstructorInitializer constructorInitializer |
| 5282 in constructor.initializers) { | 5806 in constructor.initializers) { |
| 5283 if (constructorInitializer is SuperConstructorInvocation || | 5807 if (constructorInitializer is SuperConstructorInvocation || |
| 5284 constructorInitializer is RedirectingConstructorInvocation) { | 5808 constructorInitializer is RedirectingConstructorInvocation) { |
| 5285 return false; | 5809 return; |
| 5286 } | 5810 } |
| 5287 } | 5811 } |
| 5288 // | 5812 |
| 5289 // Check to see whether the superclass has a non-factory unnamed | 5813 // Check to see whether the superclass has a non-factory unnamed |
| 5290 // constructor. | 5814 // constructor. |
| 5291 // | |
| 5292 InterfaceType superType = _enclosingClass.supertype; | 5815 InterfaceType superType = _enclosingClass.supertype; |
| 5293 if (superType == null) { | 5816 if (superType == null) { |
| 5294 return false; | 5817 return; |
| 5295 } | 5818 } |
| 5296 ClassElement superElement = superType.element; | 5819 ClassElement superElement = superType.element; |
| 5297 ConstructorElement superUnnamedConstructor = | 5820 ConstructorElement superUnnamedConstructor = |
| 5298 superElement.unnamedConstructor; | 5821 superElement.unnamedConstructor; |
| 5299 if (superUnnamedConstructor != null) { | 5822 if (superUnnamedConstructor != null) { |
| 5300 if (superUnnamedConstructor.isFactory) { | 5823 if (superUnnamedConstructor.isFactory) { |
| 5301 _errorReporter.reportErrorForNode( | 5824 _errorReporter.reportErrorForNode( |
| 5302 CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR, | 5825 CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR, |
| 5303 constructor.returnType, | 5826 constructor.returnType, |
| 5304 [superUnnamedConstructor]); | 5827 [superUnnamedConstructor]); |
| 5305 return true; | 5828 } else if (!superUnnamedConstructor.isDefaultConstructor || |
| 5306 } | |
| 5307 if (!superUnnamedConstructor.isDefaultConstructor || | |
| 5308 !_enclosingClass | 5829 !_enclosingClass |
| 5309 .isSuperConstructorAccessible(superUnnamedConstructor)) { | 5830 .isSuperConstructorAccessible(superUnnamedConstructor)) { |
| 5310 int offset; | 5831 Identifier returnType = constructor.returnType; |
| 5311 int length; | 5832 SimpleIdentifier name = constructor.name; |
| 5312 { | 5833 int offset = returnType.offset; |
| 5313 Identifier returnType = constructor.returnType; | 5834 int length = (name != null ? name.end : returnType.end) - offset; |
| 5314 SimpleIdentifier name = constructor.name; | |
| 5315 offset = returnType.offset; | |
| 5316 length = (name != null ? name.end : returnType.end) - offset; | |
| 5317 } | |
| 5318 _errorReporter.reportErrorForOffset( | 5835 _errorReporter.reportErrorForOffset( |
| 5319 CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT, | 5836 CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT, |
| 5320 offset, | 5837 offset, |
| 5321 length, | 5838 length, |
| 5322 [superType.displayName]); | 5839 [superType.displayName]); |
| 5323 } | 5840 } |
| 5324 return false; | 5841 } else { |
| 5842 _errorReporter.reportErrorForNode( |
| 5843 CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT, |
| 5844 constructor.returnType, |
| 5845 [superElement.name]); |
| 5325 } | 5846 } |
| 5326 _errorReporter.reportErrorForNode( | |
| 5327 CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT, | |
| 5328 constructor.returnType, | |
| 5329 [superElement.name]); | |
| 5330 return true; | |
| 5331 } | 5847 } |
| 5332 | 5848 |
| 5333 /** | 5849 /** |
| 5334 * Check that if the given [name] is a reference to a static member it is | 5850 * Check that if the given [name] is a reference to a static member it is |
| 5335 * defined in the enclosing class rather than in a superclass. | 5851 * defined in the enclosing class rather than in a superclass. |
| 5336 * | 5852 * |
| 5337 * See [StaticTypeWarningCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER
]. | 5853 * See [StaticTypeWarningCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER
]. |
| 5338 */ | 5854 */ |
| 5339 bool _checkForUnqualifiedReferenceToNonLocalStaticMember( | 5855 void _checkForUnqualifiedReferenceToNonLocalStaticMember( |
| 5340 SimpleIdentifier name) { | 5856 SimpleIdentifier name) { |
| 5341 Element element = name.staticElement; | 5857 Element element = name.staticElement; |
| 5342 if (element == null || element is TypeParameterElement) { | 5858 if (element == null || element is TypeParameterElement) { |
| 5343 return false; | 5859 return; |
| 5344 } | 5860 } |
| 5345 Element enclosingElement = element.enclosingElement; | 5861 Element enclosingElement = element.enclosingElement; |
| 5862 if (identical(enclosingElement, _enclosingClass)) { |
| 5863 return; |
| 5864 } |
| 5865 if (identical(enclosingElement, _enclosingEnum)) { |
| 5866 return; |
| 5867 } |
| 5346 if (enclosingElement is! ClassElement) { | 5868 if (enclosingElement is! ClassElement) { |
| 5347 return false; | 5869 return; |
| 5348 } | 5870 } |
| 5349 if ((element is MethodElement && !element.isStatic) || | 5871 if ((element is MethodElement && !element.isStatic) || |
| 5350 (element is PropertyAccessorElement && !element.isStatic)) { | 5872 (element is PropertyAccessorElement && !element.isStatic)) { |
| 5351 return false; | 5873 return; |
| 5352 } | |
| 5353 if (identical(enclosingElement, _enclosingClass)) { | |
| 5354 return false; | |
| 5355 } | 5874 } |
| 5356 _errorReporter.reportErrorForNode( | 5875 _errorReporter.reportErrorForNode( |
| 5357 StaticTypeWarningCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER, | 5876 StaticTypeWarningCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER, |
| 5358 name, | 5877 name, |
| 5359 [name.name]); | 5878 [name.name]); |
| 5360 return true; | |
| 5361 } | 5879 } |
| 5362 | 5880 |
| 5363 void _checkForValidField(FieldFormalParameter parameter) { | 5881 void _checkForValidField(FieldFormalParameter parameter) { |
| 5364 ParameterElement element = parameter.element; | 5882 ParameterElement element = parameter.element; |
| 5365 if (element is FieldFormalParameterElement) { | 5883 if (element is FieldFormalParameterElement) { |
| 5366 FieldElement fieldElement = element.field; | 5884 FieldElement fieldElement = element.field; |
| 5367 if (fieldElement == null || fieldElement.isSynthetic) { | 5885 if (fieldElement == null || fieldElement.isSynthetic) { |
| 5368 _errorReporter.reportErrorForNode( | 5886 _errorReporter.reportErrorForNode( |
| 5369 CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD, | 5887 CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD, |
| 5370 parameter, | 5888 parameter, |
| 5371 [parameter.identifier.name]); | 5889 [parameter.identifier.name]); |
| 5372 } else { | 5890 } else { |
| 5373 ParameterElement parameterElement = parameter.element; | 5891 ParameterElement parameterElement = parameter.element; |
| 5374 if (parameterElement is FieldFormalParameterElementImpl) { | 5892 if (parameterElement is FieldFormalParameterElementImpl) { |
| 5375 FieldFormalParameterElementImpl fieldFormal = parameterElement; | 5893 DartType declaredType = parameterElement.type; |
| 5376 DartType declaredType = fieldFormal.type; | |
| 5377 DartType fieldType = fieldElement.type; | 5894 DartType fieldType = fieldElement.type; |
| 5378 if (fieldElement.isSynthetic) { | 5895 if (fieldElement.isSynthetic) { |
| 5379 _errorReporter.reportErrorForNode( | 5896 _errorReporter.reportErrorForNode( |
| 5380 CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD, | 5897 CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD, |
| 5381 parameter, | 5898 parameter, |
| 5382 [parameter.identifier.name]); | 5899 [parameter.identifier.name]); |
| 5383 } else if (fieldElement.isStatic) { | 5900 } else if (fieldElement.isStatic) { |
| 5384 _errorReporter.reportErrorForNode( | 5901 _errorReporter.reportErrorForNode( |
| 5385 CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_STATIC_FIELD, | 5902 CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_STATIC_FIELD, |
| 5386 parameter, | 5903 parameter, |
| (...skipping 25 matching lines...) Expand all Loading... |
| 5412 // // TODO(jwren) Report error, constructor initializer variable is a top
level element | 5929 // // TODO(jwren) Report error, constructor initializer variable is a top
level element |
| 5413 // // (Either here or in ErrorVerifier.checkForAllFinalInitializedErrorCo
des) | 5930 // // (Either here or in ErrorVerifier.checkForAllFinalInitializedErrorCo
des) |
| 5414 // } | 5931 // } |
| 5415 } | 5932 } |
| 5416 | 5933 |
| 5417 /** | 5934 /** |
| 5418 * Verify that the given [getter] does not have a return type of 'void'. | 5935 * Verify that the given [getter] does not have a return type of 'void'. |
| 5419 * | 5936 * |
| 5420 * See [StaticWarningCode.VOID_RETURN_FOR_GETTER]. | 5937 * See [StaticWarningCode.VOID_RETURN_FOR_GETTER]. |
| 5421 */ | 5938 */ |
| 5422 bool _checkForVoidReturnType(MethodDeclaration getter) { | 5939 void _checkForVoidReturnType(MethodDeclaration getter) { |
| 5423 TypeName returnType = getter.returnType; | 5940 TypeName returnType = getter.returnType; |
| 5424 if (returnType == null || returnType.name.name != "void") { | 5941 if (returnType == null || returnType.name.name != "void") { |
| 5425 return false; | 5942 return; |
| 5426 } | 5943 } |
| 5427 _errorReporter.reportErrorForNode( | 5944 _errorReporter.reportErrorForNode( |
| 5428 StaticWarningCode.VOID_RETURN_FOR_GETTER, returnType); | 5945 StaticWarningCode.VOID_RETURN_FOR_GETTER, returnType); |
| 5429 return true; | |
| 5430 } | 5946 } |
| 5431 | 5947 |
| 5432 /** | 5948 /** |
| 5433 * Verify the given operator-method [declaration], has correct number of | 5949 * Verify the given operator-method [declaration], has correct number of |
| 5434 * parameters. | 5950 * parameters. |
| 5435 * | 5951 * |
| 5436 * This method assumes that the method declaration was tested to be an | 5952 * This method assumes that the method declaration was tested to be an |
| 5437 * operator declaration before being called. | 5953 * operator declaration before being called. |
| 5438 * | 5954 * |
| 5439 * See [CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR]. | 5955 * See [CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR]. |
| 5440 */ | 5956 */ |
| 5441 bool _checkForWrongNumberOfParametersForOperator( | 5957 void _checkForWrongNumberOfParametersForOperator( |
| 5442 MethodDeclaration declaration) { | 5958 MethodDeclaration declaration) { |
| 5443 // prepare number of parameters | 5959 // prepare number of parameters |
| 5444 FormalParameterList parameterList = declaration.parameters; | 5960 FormalParameterList parameterList = declaration.parameters; |
| 5445 if (parameterList == null) { | 5961 if (parameterList == null) { |
| 5446 return false; | 5962 return; |
| 5447 } | 5963 } |
| 5448 int numParameters = parameterList.parameters.length; | 5964 int numParameters = parameterList.parameters.length; |
| 5449 // prepare operator name | 5965 // prepare operator name |
| 5450 SimpleIdentifier nameNode = declaration.name; | 5966 SimpleIdentifier nameNode = declaration.name; |
| 5451 if (nameNode == null) { | 5967 if (nameNode == null) { |
| 5452 return false; | 5968 return; |
| 5453 } | 5969 } |
| 5454 String name = nameNode.name; | 5970 String name = nameNode.name; |
| 5455 // check for exact number of parameters | 5971 // check for exact number of parameters |
| 5456 int expected = -1; | 5972 int expected = -1; |
| 5457 if ("[]=" == name) { | 5973 if ("[]=" == name) { |
| 5458 expected = 2; | 5974 expected = 2; |
| 5459 } else if ("<" == name || | 5975 } else if ("<" == name || |
| 5460 ">" == name || | 5976 ">" == name || |
| 5461 "<=" == name || | 5977 "<=" == name || |
| 5462 ">=" == name || | 5978 ">=" == name || |
| (...skipping 11 matching lines...) Expand all Loading... |
| 5474 "[]" == name) { | 5990 "[]" == name) { |
| 5475 expected = 1; | 5991 expected = 1; |
| 5476 } else if ("~" == name) { | 5992 } else if ("~" == name) { |
| 5477 expected = 0; | 5993 expected = 0; |
| 5478 } | 5994 } |
| 5479 if (expected != -1 && numParameters != expected) { | 5995 if (expected != -1 && numParameters != expected) { |
| 5480 _errorReporter.reportErrorForNode( | 5996 _errorReporter.reportErrorForNode( |
| 5481 CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR, | 5997 CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR, |
| 5482 nameNode, | 5998 nameNode, |
| 5483 [name, expected, numParameters]); | 5999 [name, expected, numParameters]); |
| 5484 return true; | 6000 } else if ("-" == name && numParameters > 1) { |
| 5485 } | |
| 5486 // check for operator "-" | |
| 5487 if ("-" == name && numParameters > 1) { | |
| 5488 _errorReporter.reportErrorForNode( | 6001 _errorReporter.reportErrorForNode( |
| 5489 CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS, | 6002 CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS, |
| 5490 nameNode, | 6003 nameNode, |
| 5491 [numParameters]); | 6004 [numParameters]); |
| 5492 return true; | |
| 5493 } | 6005 } |
| 5494 // OK | |
| 5495 return false; | |
| 5496 } | 6006 } |
| 5497 | 6007 |
| 5498 /** | 6008 /** |
| 5499 * Verify that the given setter [parameterList] has only one required | 6009 * Verify that the given setter [parameterList] has only one required |
| 5500 * parameter. The [setterName] is the name of the setter to report problems | 6010 * parameter. The [setterName] is the name of the setter to report problems |
| 5501 * on. | 6011 * on. |
| 5502 * | 6012 * |
| 5503 * This method assumes that the method declaration was tested to be a setter | 6013 * This method assumes that the method declaration was tested to be a setter |
| 5504 * before being called. | 6014 * before being called. |
| 5505 * | 6015 * |
| 5506 * See [CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER]. | 6016 * See [CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER]. |
| 5507 */ | 6017 */ |
| 5508 bool _checkForWrongNumberOfParametersForSetter( | 6018 void _checkForWrongNumberOfParametersForSetter( |
| 5509 SimpleIdentifier setterName, FormalParameterList parameterList) { | 6019 SimpleIdentifier setterName, FormalParameterList parameterList) { |
| 5510 if (setterName == null) { | 6020 if (setterName == null || parameterList == null) { |
| 5511 return false; | 6021 return; |
| 5512 } | 6022 } |
| 5513 if (parameterList == null) { | 6023 |
| 5514 return false; | |
| 5515 } | |
| 5516 NodeList<FormalParameter> parameters = parameterList.parameters; | 6024 NodeList<FormalParameter> parameters = parameterList.parameters; |
| 5517 if (parameters.length != 1 || | 6025 if (parameters.length != 1 || |
| 5518 parameters[0].kind != ParameterKind.REQUIRED) { | 6026 parameters[0].kind != ParameterKind.REQUIRED) { |
| 5519 _errorReporter.reportErrorForNode( | 6027 _errorReporter.reportErrorForNode( |
| 5520 CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER, | 6028 CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER, |
| 5521 setterName); | 6029 setterName); |
| 5522 return true; | |
| 5523 } | 6030 } |
| 5524 return false; | |
| 5525 } | 6031 } |
| 5526 | 6032 |
| 5527 /** | 6033 /** |
| 5528 * Check for a type mis-match between the yielded type and the declared | 6034 * Check for a type mis-match between the yielded type and the declared |
| 5529 * return type of a generator function. | 6035 * return type of a generator function. |
| 5530 * | 6036 * |
| 5531 * This method should only be called in generator functions. | 6037 * This method should only be called in generator functions. |
| 5532 */ | 6038 */ |
| 5533 bool _checkForYieldOfInvalidType( | 6039 void _checkForYieldOfInvalidType( |
| 5534 Expression yieldExpression, bool isYieldEach) { | 6040 Expression yieldExpression, bool isYieldEach) { |
| 5535 assert(_inGenerator); | 6041 assert(_inGenerator); |
| 5536 if (_enclosingFunction == null) { | 6042 if (_enclosingFunction == null) { |
| 5537 return false; | 6043 return; |
| 5538 } | 6044 } |
| 5539 DartType declaredReturnType = _enclosingFunction.returnType; | 6045 DartType declaredReturnType = _enclosingFunction.returnType; |
| 5540 DartType staticYieldedType = getStaticType(yieldExpression); | 6046 DartType staticYieldedType = getStaticType(yieldExpression); |
| 5541 DartType impliedReturnType; | 6047 DartType impliedReturnType; |
| 5542 if (isYieldEach) { | 6048 if (isYieldEach) { |
| 5543 impliedReturnType = staticYieldedType; | 6049 impliedReturnType = staticYieldedType; |
| 5544 } else if (_enclosingFunction.isAsynchronous) { | 6050 } else if (_enclosingFunction.isAsynchronous) { |
| 5545 impliedReturnType = | 6051 impliedReturnType = |
| 5546 _typeProvider.streamType.substitute4(<DartType>[staticYieldedType]); | 6052 _typeProvider.streamType.instantiate(<DartType>[staticYieldedType]); |
| 5547 } else { | 6053 } else { |
| 5548 impliedReturnType = | 6054 impliedReturnType = |
| 5549 _typeProvider.iterableType.substitute4(<DartType>[staticYieldedType]); | 6055 _typeProvider.iterableType.instantiate(<DartType>[staticYieldedType]); |
| 5550 } | 6056 } |
| 5551 if (!_typeSystem.isAssignableTo(impliedReturnType, declaredReturnType)) { | 6057 if (!_checkForAssignableExpressionAtType(yieldExpression, impliedReturnType, |
| 5552 _errorReporter.reportTypeErrorForNode( | 6058 declaredReturnType, StaticTypeWarningCode.YIELD_OF_INVALID_TYPE)) { |
| 5553 StaticTypeWarningCode.YIELD_OF_INVALID_TYPE, | 6059 return; |
| 5554 yieldExpression, | |
| 5555 [impliedReturnType, declaredReturnType]); | |
| 5556 return true; | |
| 5557 } | 6060 } |
| 5558 if (isYieldEach) { | 6061 if (isYieldEach) { |
| 5559 // Since the declared return type might have been "dynamic", we need to | 6062 // Since the declared return type might have been "dynamic", we need to |
| 5560 // also check that the implied return type is assignable to generic | 6063 // also check that the implied return type is assignable to generic |
| 5561 // Stream/Iterable. | 6064 // Stream/Iterable. |
| 5562 DartType requiredReturnType; | 6065 DartType requiredReturnType; |
| 5563 if (_enclosingFunction.isAsynchronous) { | 6066 if (_enclosingFunction.isAsynchronous) { |
| 5564 requiredReturnType = _typeProvider.streamDynamicType; | 6067 requiredReturnType = _typeProvider.streamDynamicType; |
| 5565 } else { | 6068 } else { |
| 5566 requiredReturnType = _typeProvider.iterableDynamicType; | 6069 requiredReturnType = _typeProvider.iterableDynamicType; |
| 5567 } | 6070 } |
| 5568 if (!_typeSystem.isAssignableTo(impliedReturnType, requiredReturnType)) { | 6071 if (!_typeSystem.isAssignableTo(impliedReturnType, requiredReturnType)) { |
| 5569 _errorReporter.reportTypeErrorForNode( | 6072 _errorReporter.reportTypeErrorForNode( |
| 5570 StaticTypeWarningCode.YIELD_OF_INVALID_TYPE, | 6073 StaticTypeWarningCode.YIELD_OF_INVALID_TYPE, |
| 5571 yieldExpression, | 6074 yieldExpression, |
| 5572 [impliedReturnType, requiredReturnType]); | 6075 [impliedReturnType, requiredReturnType]); |
| 5573 return true; | 6076 return; |
| 5574 } | 6077 } |
| 5575 } | 6078 } |
| 5576 return false; | |
| 5577 } | 6079 } |
| 5578 | 6080 |
| 5579 /** | 6081 /** |
| 5580 * Verify that if the given class [declaration] implements the class Function | 6082 * Verify that if the given class [declaration] implements the class Function |
| 5581 * that it has a concrete implementation of the call method. | 6083 * that it has a concrete implementation of the call method. |
| 5582 * | 6084 * |
| 5583 * See [StaticWarningCode.FUNCTION_WITHOUT_CALL]. | 6085 * See [StaticWarningCode.FUNCTION_WITHOUT_CALL]. |
| 5584 */ | 6086 */ |
| 5585 bool _checkImplementsFunctionWithoutCall(ClassDeclaration declaration) { | 6087 void _checkImplementsFunctionWithoutCall(ClassDeclaration declaration) { |
| 5586 if (declaration.isAbstract) { | 6088 if (declaration.isAbstract) { |
| 5587 return false; | 6089 return; |
| 5588 } | 6090 } |
| 5589 ClassElement classElement = declaration.element; | 6091 ClassElement classElement = declaration.element; |
| 5590 if (classElement == null) { | 6092 if (classElement == null) { |
| 5591 return false; | 6093 return; |
| 5592 } | 6094 } |
| 5593 if (!_typeSystem.isSubtypeOf( | 6095 if (!_typeSystem.isSubtypeOf( |
| 5594 classElement.type, _typeProvider.functionType)) { | 6096 classElement.type, _typeProvider.functionType)) { |
| 5595 return false; | 6097 return; |
| 5596 } | 6098 } |
| 5597 // If there is a noSuchMethod method, then don't report the warning, | 6099 // If there is a noSuchMethod method, then don't report the warning, |
| 5598 // see dartbug.com/16078 | 6100 // see dartbug.com/16078 |
| 5599 if (classElement.getMethod(FunctionElement.NO_SUCH_METHOD_METHOD_NAME) != | 6101 if (_enclosingClass.hasNoSuchMethod) { |
| 5600 null) { | 6102 return; |
| 5601 return false; | |
| 5602 } | 6103 } |
| 5603 ExecutableElement callMethod = _inheritanceManager.lookupMember( | 6104 ExecutableElement callMethod = _inheritanceManager.lookupMember( |
| 5604 classElement, FunctionElement.CALL_METHOD_NAME); | 6105 classElement, FunctionElement.CALL_METHOD_NAME); |
| 5605 if (callMethod == null || | 6106 if (callMethod == null || |
| 5606 callMethod is! MethodElement || | 6107 callMethod is! MethodElement || |
| 5607 (callMethod as MethodElement).isAbstract) { | 6108 (callMethod as MethodElement).isAbstract) { |
| 5608 _errorReporter.reportErrorForNode( | 6109 _errorReporter.reportErrorForNode( |
| 5609 StaticWarningCode.FUNCTION_WITHOUT_CALL, declaration.name); | 6110 StaticWarningCode.FUNCTION_WITHOUT_CALL, declaration.name); |
| 5610 return true; | |
| 5611 } | 6111 } |
| 5612 return false; | |
| 5613 } | 6112 } |
| 5614 | 6113 |
| 5615 /** | 6114 /** |
| 5616 * Verify that the given class [declaration] does not have the same class in | 6115 * Verify that the given class [declaration] does not have the same class in |
| 5617 * the 'extends' and 'implements' clauses. | 6116 * the 'extends' and 'implements' clauses. |
| 5618 * | 6117 * |
| 5619 * See [CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS]. | 6118 * See [CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS]. |
| 5620 */ | 6119 */ |
| 5621 bool _checkImplementsSuperClass(ClassDeclaration declaration) { | 6120 void _checkImplementsSuperClass(ClassDeclaration declaration) { |
| 5622 // prepare super type | 6121 // prepare super type |
| 5623 InterfaceType superType = _enclosingClass.supertype; | 6122 InterfaceType superType = _enclosingClass.supertype; |
| 5624 if (superType == null) { | 6123 if (superType == null) { |
| 5625 return false; | 6124 return; |
| 5626 } | 6125 } |
| 5627 // prepare interfaces | 6126 // prepare interfaces |
| 5628 ImplementsClause implementsClause = declaration.implementsClause; | 6127 ImplementsClause implementsClause = declaration.implementsClause; |
| 5629 if (implementsClause == null) { | 6128 if (implementsClause == null) { |
| 5630 return false; | 6129 return; |
| 5631 } | 6130 } |
| 5632 // check interfaces | 6131 // check interfaces |
| 5633 bool hasProblem = false; | |
| 5634 for (TypeName interfaceNode in implementsClause.interfaces) { | 6132 for (TypeName interfaceNode in implementsClause.interfaces) { |
| 5635 if (interfaceNode.type == superType) { | 6133 if (interfaceNode.type == superType) { |
| 5636 hasProblem = true; | |
| 5637 _errorReporter.reportErrorForNode( | 6134 _errorReporter.reportErrorForNode( |
| 5638 CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS, | 6135 CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS, |
| 5639 interfaceNode, | 6136 interfaceNode, |
| 5640 [superType.displayName]); | 6137 [superType.displayName]); |
| 5641 } | 6138 } |
| 5642 } | 6139 } |
| 5643 // done | 6140 } |
| 5644 return hasProblem; | 6141 |
| 6142 /** |
| 6143 * Verify that the given [typeArguments] are all within their bounds, as |
| 6144 * defined by the given [element]. |
| 6145 * |
| 6146 * See [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]. |
| 6147 */ |
| 6148 void _checkTypeArguments(Element element, TypeArgumentList typeArguments, |
| 6149 [DartType targetType]) { |
| 6150 if (element == null || typeArguments == null) { |
| 6151 return; |
| 6152 } |
| 6153 void reportError( |
| 6154 TypeName argument, DartType argumentType, DartType parameterType) { |
| 6155 _errorReporter.reportTypeErrorForNode( |
| 6156 StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, |
| 6157 argument, |
| 6158 [argumentType, parameterType]); |
| 6159 } |
| 6160 |
| 6161 if (element is FunctionTypedElement) { |
| 6162 _checkTypeArgumentsAgainstBounds( |
| 6163 element.typeParameters, typeArguments, targetType, reportError); |
| 6164 } else if (element is ClassElement) { |
| 6165 _checkTypeArgumentsAgainstBounds( |
| 6166 element.typeParameters, typeArguments, targetType, reportError); |
| 6167 } else if (element is ParameterElement || element is LocalVariableElement) { |
| 6168 // TODO(brianwilkerson) Implement this case |
| 6169 } else { |
| 6170 print('Unhandled element type: ${element.runtimeType}'); |
| 6171 } |
| 6172 } |
| 6173 |
| 6174 void _checkTypeArgumentsAgainstBounds( |
| 6175 List<TypeParameterElement> typeParameters, |
| 6176 TypeArgumentList typeArgumentList, |
| 6177 DartType targetType, |
| 6178 void reportError( |
| 6179 TypeName argument, DartType argumentType, DartType parameterType)) { |
| 6180 NodeList<TypeName> typeArguments = typeArgumentList.arguments; |
| 6181 int argumentsLength = typeArguments.length; |
| 6182 int maxIndex = math.min(typeParameters.length, argumentsLength); |
| 6183 |
| 6184 bool shouldSubstitute = |
| 6185 argumentsLength != 0 && argumentsLength == typeParameters.length; |
| 6186 List<DartType> argumentTypes = shouldSubstitute |
| 6187 ? typeArguments.map((TypeName typeName) => typeName.type).toList() |
| 6188 : null; |
| 6189 List<DartType> parameterTypes = shouldSubstitute |
| 6190 ? typeParameters |
| 6191 .map((TypeParameterElement element) => element.type) |
| 6192 .toList() |
| 6193 : null; |
| 6194 List<DartType> targetTypeParameterTypes = null; |
| 6195 for (int i = 0; i < maxIndex; i++) { |
| 6196 TypeName argTypeName = typeArguments[i]; |
| 6197 DartType argType = argTypeName.type; |
| 6198 DartType boundType = typeParameters[i].bound; |
| 6199 if (argType != null && boundType != null) { |
| 6200 if (targetType is ParameterizedType) { |
| 6201 if (targetTypeParameterTypes == null) { |
| 6202 targetTypeParameterTypes = targetType.typeParameters |
| 6203 .map((TypeParameterElement element) => element.type) |
| 6204 .toList(); |
| 6205 } |
| 6206 boundType = boundType.substitute2( |
| 6207 targetType.typeArguments, targetTypeParameterTypes); |
| 6208 } |
| 6209 if (shouldSubstitute) { |
| 6210 boundType = boundType.substitute2(argumentTypes, parameterTypes); |
| 6211 } |
| 6212 if (!_typeSystem.isSubtypeOf(argType, boundType)) { |
| 6213 reportError(argTypeName, argType, boundType); |
| 6214 } |
| 6215 } |
| 6216 } |
| 5645 } | 6217 } |
| 5646 | 6218 |
| 5647 DartType _computeReturnTypeForMethod(Expression returnExpression) { | 6219 DartType _computeReturnTypeForMethod(Expression returnExpression) { |
| 5648 // This method should never be called for generators, since generators are | 6220 // This method should never be called for generators, since generators are |
| 5649 // never allowed to contain return statements with expressions. | 6221 // never allowed to contain return statements with expressions. |
| 5650 assert(!_inGenerator); | 6222 assert(!_inGenerator); |
| 5651 if (returnExpression == null) { | 6223 if (returnExpression == null) { |
| 5652 if (_enclosingFunction.isAsynchronous) { | 6224 if (_enclosingFunction.isAsynchronous) { |
| 5653 return _typeProvider.futureNullType; | 6225 return _typeProvider.futureNullType; |
| 5654 } else { | 6226 } else { |
| 5655 return VoidTypeImpl.instance; | 6227 return VoidTypeImpl.instance; |
| 5656 } | 6228 } |
| 5657 } | 6229 } |
| 5658 DartType staticReturnType = getStaticType(returnExpression); | 6230 DartType staticReturnType = getStaticType(returnExpression); |
| 5659 if (staticReturnType != null && _enclosingFunction.isAsynchronous) { | 6231 if (staticReturnType != null && _enclosingFunction.isAsynchronous) { |
| 5660 return _typeProvider.futureType.substitute4(<DartType>[ | 6232 return _typeProvider.futureType.instantiate( |
| 5661 StaticTypeAnalyzer.flattenFutures(_typeProvider, staticReturnType) | 6233 <DartType>[staticReturnType.flattenFutures(_typeSystem)]); |
| 5662 ]); | |
| 5663 } | 6234 } |
| 5664 return staticReturnType; | 6235 return staticReturnType; |
| 5665 } | 6236 } |
| 5666 | 6237 |
| 6238 bool _expressionIsAssignableAtType(Expression expression, |
| 6239 DartType actualStaticType, DartType expectedStaticType) { |
| 6240 bool concrete = _options.strongMode && checker.isKnownFunction(expression); |
| 6241 if (concrete && actualStaticType is FunctionType) { |
| 6242 actualStaticType = _typeSystem.functionTypeToConcreteType( |
| 6243 _typeProvider, actualStaticType); |
| 6244 // TODO(leafp): Move the Downcast functionality here. |
| 6245 } |
| 6246 return _typeSystem.isAssignableTo(actualStaticType, expectedStaticType); |
| 6247 } |
| 6248 |
| 6249 MethodElement _findOverriddenMemberThatMustCallSuper(MethodDeclaration node) { |
| 6250 ExecutableElement overriddenMember = _getOverriddenMember(node.element); |
| 6251 List<ExecutableElement> seen = <ExecutableElement>[]; |
| 6252 while ( |
| 6253 overriddenMember is MethodElement && !seen.contains(overriddenMember)) { |
| 6254 for (ElementAnnotation annotation in overriddenMember.metadata) { |
| 6255 if (annotation.isMustCallSuper) { |
| 6256 return overriddenMember; |
| 6257 } |
| 6258 } |
| 6259 seen.add(overriddenMember); |
| 6260 // Keep looking up the chain. |
| 6261 overriddenMember = _getOverriddenMember(overriddenMember); |
| 6262 } |
| 6263 return null; |
| 6264 } |
| 6265 |
| 5667 /** | 6266 /** |
| 5668 * Return the error code that should be used when the given class [element] | 6267 * Return the error code that should be used when the given class [element] |
| 5669 * references itself directly. | 6268 * references itself directly. |
| 5670 */ | 6269 */ |
| 5671 ErrorCode _getBaseCaseErrorCode(ClassElement element) { | 6270 ErrorCode _getBaseCaseErrorCode(ClassElement element) { |
| 5672 InterfaceType supertype = element.supertype; | 6271 InterfaceType supertype = element.supertype; |
| 5673 if (supertype != null && _enclosingClass == supertype.element) { | 6272 if (supertype != null && _enclosingClass == supertype.element) { |
| 5674 return CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_EXTE
NDS; | 6273 return CompileTimeErrorCode |
| 6274 .RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_EXTENDS; |
| 5675 } | 6275 } |
| 5676 List<InterfaceType> mixins = element.mixins; | 6276 List<InterfaceType> mixins = element.mixins; |
| 5677 for (int i = 0; i < mixins.length; i++) { | 6277 for (int i = 0; i < mixins.length; i++) { |
| 5678 if (_enclosingClass == mixins[i].element) { | 6278 if (_enclosingClass == mixins[i].element) { |
| 5679 return CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_WI
TH; | 6279 return CompileTimeErrorCode |
| 6280 .RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_WITH; |
| 5680 } | 6281 } |
| 5681 } | 6282 } |
| 5682 return CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_IMPLEM
ENTS; | 6283 return CompileTimeErrorCode |
| 6284 .RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_IMPLEMENTS; |
| 5683 } | 6285 } |
| 5684 | 6286 |
| 5685 /** | 6287 /** |
| 5686 * Given an [expression] in a switch case whose value is expected to be an | 6288 * Given an [expression] in a switch case whose value is expected to be an |
| 5687 * enum constant, return the name of the constant. | 6289 * enum constant, return the name of the constant. |
| 5688 */ | 6290 */ |
| 5689 String _getConstantName(Expression expression) { | 6291 String _getConstantName(Expression expression) { |
| 5690 // TODO(brianwilkerson) Convert this to return the element representing the | 6292 // TODO(brianwilkerson) Convert this to return the element representing the |
| 5691 // constant. | 6293 // constant. |
| 5692 if (expression is SimpleIdentifier) { | 6294 if (expression is SimpleIdentifier) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 5705 DartType _getGetterType(PropertyAccessorElement getter) { | 6307 DartType _getGetterType(PropertyAccessorElement getter) { |
| 5706 FunctionType functionType = getter.type; | 6308 FunctionType functionType = getter.type; |
| 5707 if (functionType != null) { | 6309 if (functionType != null) { |
| 5708 return functionType.returnType; | 6310 return functionType.returnType; |
| 5709 } else { | 6311 } else { |
| 5710 return null; | 6312 return null; |
| 5711 } | 6313 } |
| 5712 } | 6314 } |
| 5713 | 6315 |
| 5714 /** | 6316 /** |
| 6317 * Return the name of the library that defines given [element]. |
| 6318 */ |
| 6319 String _getLibraryName(Element element) { |
| 6320 if (element == null) { |
| 6321 return StringUtilities.EMPTY; |
| 6322 } |
| 6323 LibraryElement library = element.library; |
| 6324 if (library == null) { |
| 6325 return StringUtilities.EMPTY; |
| 6326 } |
| 6327 List<ImportElement> imports = _currentLibrary.imports; |
| 6328 int count = imports.length; |
| 6329 for (int i = 0; i < count; i++) { |
| 6330 if (identical(imports[i].importedLibrary, library)) { |
| 6331 return library.definingCompilationUnit.displayName; |
| 6332 } |
| 6333 } |
| 6334 List<String> indirectSources = new List<String>(); |
| 6335 for (int i = 0; i < count; i++) { |
| 6336 LibraryElement importedLibrary = imports[i].importedLibrary; |
| 6337 if (importedLibrary != null) { |
| 6338 for (LibraryElement exportedLibrary |
| 6339 in importedLibrary.exportedLibraries) { |
| 6340 if (identical(exportedLibrary, library)) { |
| 6341 indirectSources |
| 6342 .add(importedLibrary.definingCompilationUnit.displayName); |
| 6343 } |
| 6344 } |
| 6345 } |
| 6346 } |
| 6347 int indirectCount = indirectSources.length; |
| 6348 StringBuffer buffer = new StringBuffer(); |
| 6349 buffer.write(library.definingCompilationUnit.displayName); |
| 6350 if (indirectCount > 0) { |
| 6351 buffer.write(" (via "); |
| 6352 if (indirectCount > 1) { |
| 6353 indirectSources.sort(); |
| 6354 buffer.write(StringUtilities.printListOfQuotedNames(indirectSources)); |
| 6355 } else { |
| 6356 buffer.write(indirectSources[0]); |
| 6357 } |
| 6358 buffer.write(")"); |
| 6359 } |
| 6360 return buffer.toString(); |
| 6361 } |
| 6362 |
| 6363 ExecutableElement _getOverriddenMember(Element member) { |
| 6364 if (member == null) { |
| 6365 return null; |
| 6366 } |
| 6367 ClassElement classElement = |
| 6368 member.getAncestor((element) => element is ClassElement); |
| 6369 if (classElement == null) { |
| 6370 return null; |
| 6371 } |
| 6372 String name = member.name; |
| 6373 ClassElement superclass = classElement.supertype?.element; |
| 6374 while (superclass != null) { |
| 6375 ExecutableElement member = superclass.getMethod(name) ?? superclass.getGet
ter(name) ?? superclass.getSetter(name); |
| 6376 if (member != null) { |
| 6377 return member; |
| 6378 } |
| 6379 superclass = superclass.supertype?.element; |
| 6380 } |
| 6381 return null; |
| 6382 } |
| 6383 |
| 6384 /** |
| 5715 * Return the type of the first and only parameter of the given [setter]. | 6385 * Return the type of the first and only parameter of the given [setter]. |
| 5716 */ | 6386 */ |
| 5717 DartType _getSetterType(PropertyAccessorElement setter) { | 6387 DartType _getSetterType(PropertyAccessorElement setter) { |
| 5718 // Get the parameters for MethodDeclaration or FunctionDeclaration | 6388 // Get the parameters for MethodDeclaration or FunctionDeclaration |
| 5719 List<ParameterElement> setterParameters = setter.parameters; | 6389 List<ParameterElement> setterParameters = setter.parameters; |
| 5720 // If there are no setter parameters, return no type. | 6390 // If there are no setter parameters, return no type. |
| 5721 if (setterParameters.length == 0) { | 6391 if (setterParameters.length == 0) { |
| 5722 return null; | 6392 return null; |
| 5723 } | 6393 } |
| 5724 return setterParameters[0].type; | 6394 return setterParameters[0].type; |
| 5725 } | 6395 } |
| 5726 | 6396 |
| 5727 /** | 6397 /** |
| 5728 * Given a list of [directives] that have the same prefix, generate an error | |
| 5729 * if there is more than one import and any of those imports is deferred. | |
| 5730 * | |
| 5731 * See [CompileTimeErrorCode.SHARED_DEFERRED_PREFIX]. | |
| 5732 */ | |
| 5733 bool _hasDeferredPrefixCollision(List<ImportDirective> directives) { | |
| 5734 bool foundError = false; | |
| 5735 int count = directives.length; | |
| 5736 if (count > 1) { | |
| 5737 for (int i = 0; i < count; i++) { | |
| 5738 sc.Token deferredToken = directives[i].deferredKeyword; | |
| 5739 if (deferredToken != null) { | |
| 5740 _errorReporter.reportErrorForToken( | |
| 5741 CompileTimeErrorCode.SHARED_DEFERRED_PREFIX, deferredToken); | |
| 5742 foundError = true; | |
| 5743 } | |
| 5744 } | |
| 5745 } | |
| 5746 return foundError; | |
| 5747 } | |
| 5748 | |
| 5749 /** | |
| 5750 * Return `true` if the given [constructor] redirects to itself, directly or | 6398 * Return `true` if the given [constructor] redirects to itself, directly or |
| 5751 * indirectly. | 6399 * indirectly. |
| 5752 */ | 6400 */ |
| 5753 bool _hasRedirectingFactoryConstructorCycle(ConstructorElement constructor) { | 6401 bool _hasRedirectingFactoryConstructorCycle(ConstructorElement constructor) { |
| 6402 ConstructorElement nonMember(ConstructorElement constructor) { |
| 6403 return constructor is ConstructorMember |
| 6404 ? constructor.baseElement |
| 6405 : constructor; |
| 6406 } |
| 6407 |
| 5754 Set<ConstructorElement> constructors = new HashSet<ConstructorElement>(); | 6408 Set<ConstructorElement> constructors = new HashSet<ConstructorElement>(); |
| 5755 ConstructorElement current = constructor; | 6409 ConstructorElement current = constructor; |
| 5756 while (current != null) { | 6410 while (current != null) { |
| 5757 if (constructors.contains(current)) { | 6411 if (constructors.contains(current)) { |
| 5758 return identical(current, constructor); | 6412 return identical(current, constructor); |
| 5759 } | 6413 } |
| 5760 constructors.add(current); | 6414 constructors.add(current); |
| 5761 current = current.redirectedConstructor; | 6415 current = nonMember(current.redirectedConstructor); |
| 5762 if (current is ConstructorMember) { | |
| 5763 current = (current as ConstructorMember).baseElement; | |
| 5764 } | |
| 5765 } | 6416 } |
| 5766 return false; | 6417 return false; |
| 5767 } | 6418 } |
| 5768 | 6419 |
| 5769 /** | 6420 /** |
| 5770 * Return `true` if the given [element] has direct or indirect reference to | 6421 * Return `true` if the given [element] has direct or indirect reference to |
| 5771 * itself from anywhere except a class element or type parameter bounds. | 6422 * itself from anywhere except a class element or type parameter bounds. |
| 5772 */ | 6423 */ |
| 5773 bool _hasTypedefSelfReference(Element element) { | 6424 bool _hasTypedefSelfReference(Element element) { |
| 5774 Set<Element> checked = new HashSet<Element>(); | 6425 Set<Element> checked = new HashSet<Element>(); |
| 5775 List<Element> toCheck = new List<Element>(); | 6426 List<Element> toCheck = new List<Element>(); |
| 5776 GeneralizingElementVisitor_ErrorVerifier_hasTypedefSelfReference elementVisi
tor = | 6427 GeneralizingElementVisitor_ErrorVerifier_hasTypedefSelfReference |
| 6428 elementVisitor = |
| 5777 new GeneralizingElementVisitor_ErrorVerifier_hasTypedefSelfReference( | 6429 new GeneralizingElementVisitor_ErrorVerifier_hasTypedefSelfReference( |
| 5778 toCheck); | 6430 toCheck); |
| 5779 toCheck.add(element); | 6431 toCheck.add(element); |
| 5780 bool firstIteration = true; | 6432 bool firstIteration = true; |
| 5781 while (true) { | 6433 while (true) { |
| 5782 Element current; | 6434 Element current; |
| 5783 // get next element | 6435 // get next element |
| 5784 while (true) { | 6436 while (true) { |
| 5785 // may be no more elements to check | 6437 // may be no more elements to check |
| 5786 if (toCheck.isEmpty) { | 6438 if (toCheck.isEmpty) { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5828 * have to equal or be a subtype of the given executable element, this is due | 6480 * have to equal or be a subtype of the given executable element, this is due |
| 5829 * to the specific use where this method is used in | 6481 * to the specific use where this method is used in |
| 5830 * [_checkForNonAbstractClassInheritsAbstractMember]. | 6482 * [_checkForNonAbstractClassInheritsAbstractMember]. |
| 5831 */ | 6483 */ |
| 5832 bool _isMemberInClassOrMixin( | 6484 bool _isMemberInClassOrMixin( |
| 5833 ExecutableElement executableElement, ClassElement classElement) { | 6485 ExecutableElement executableElement, ClassElement classElement) { |
| 5834 ExecutableElement foundElt = null; | 6486 ExecutableElement foundElt = null; |
| 5835 String executableName = executableElement.name; | 6487 String executableName = executableElement.name; |
| 5836 if (executableElement is MethodElement) { | 6488 if (executableElement is MethodElement) { |
| 5837 foundElt = classElement.getMethod(executableName); | 6489 foundElt = classElement.getMethod(executableName); |
| 5838 if (foundElt != null && !(foundElt as MethodElement).isAbstract) { | 6490 if (foundElt != null && !foundElt.isAbstract) { |
| 5839 return true; | 6491 return true; |
| 5840 } | 6492 } |
| 5841 List<InterfaceType> mixins = classElement.mixins; | 6493 List<InterfaceType> mixins = classElement.mixins; |
| 5842 for (int i = 0; i < mixins.length && foundElt == null; i++) { | 6494 for (int i = 0; i < mixins.length && foundElt == null; i++) { |
| 5843 foundElt = mixins[i].getMethod(executableName); | 6495 foundElt = mixins[i].getMethod(executableName); |
| 5844 } | 6496 } |
| 5845 if (foundElt != null && !(foundElt as MethodElement).isAbstract) { | 6497 if (foundElt != null && !foundElt.isAbstract) { |
| 5846 return true; | 6498 return true; |
| 5847 } | 6499 } |
| 5848 } else if (executableElement is PropertyAccessorElement) { | 6500 } else if (executableElement is PropertyAccessorElement) { |
| 5849 PropertyAccessorElement propertyAccessorElement = executableElement; | 6501 if (executableElement.isGetter) { |
| 5850 if (propertyAccessorElement.isGetter) { | |
| 5851 foundElt = classElement.getGetter(executableName); | 6502 foundElt = classElement.getGetter(executableName); |
| 5852 } | 6503 } |
| 5853 if (foundElt == null && propertyAccessorElement.isSetter) { | 6504 if (foundElt == null && executableElement.isSetter) { |
| 5854 foundElt = classElement.getSetter(executableName); | 6505 foundElt = classElement.getSetter(executableName); |
| 5855 } | 6506 } |
| 5856 if (foundElt != null && | 6507 if (foundElt != null && |
| 5857 !(foundElt as PropertyAccessorElement).isAbstract) { | 6508 !(foundElt as PropertyAccessorElement).isAbstract) { |
| 5858 return true; | 6509 return true; |
| 5859 } | 6510 } |
| 5860 List<InterfaceType> mixins = classElement.mixins; | 6511 List<InterfaceType> mixins = classElement.mixins; |
| 5861 for (int i = 0; i < mixins.length && foundElt == null; i++) { | 6512 for (int i = 0; i < mixins.length && foundElt == null; i++) { |
| 5862 foundElt = mixins[i].getGetter(executableName); | 6513 foundElt = mixins[i].getGetter(executableName); |
| 5863 if (foundElt == null) { | 6514 if (foundElt == null) { |
| 5864 foundElt = mixins[i].getSetter(executableName); | 6515 foundElt = mixins[i].getSetter(executableName); |
| 5865 } | 6516 } |
| 5866 } | 6517 } |
| 5867 if (foundElt != null && | 6518 if (foundElt != null && !foundElt.isAbstract) { |
| 5868 !(foundElt as PropertyAccessorElement).isAbstract) { | |
| 5869 return true; | 6519 return true; |
| 5870 } | 6520 } |
| 5871 } | 6521 } |
| 5872 return false; | 6522 return false; |
| 5873 } | 6523 } |
| 5874 | 6524 |
| 5875 /** | 6525 /** |
| 5876 * Return `true` if the given 'this' [expression] is in a valid context. | 6526 * Return `true` if the given 'this' [expression] is in a valid context. |
| 5877 */ | 6527 */ |
| 5878 bool _isThisInValidContext(ThisExpression expression) { | 6528 bool _isThisInValidContext(ThisExpression expression) { |
| 5879 for (AstNode node = expression.parent; node != null; node = node.parent) { | 6529 for (AstNode node = expression.parent; node != null; node = node.parent) { |
| 5880 if (node is CompilationUnit) { | 6530 if (node is CompilationUnit) { |
| 5881 return false; | 6531 return false; |
| 5882 } | 6532 } else if (node is ConstructorDeclaration) { |
| 5883 if (node is ConstructorDeclaration) { | |
| 5884 return node.factoryKeyword == null; | 6533 return node.factoryKeyword == null; |
| 5885 } | 6534 } else if (node is ConstructorInitializer) { |
| 5886 if (node is ConstructorInitializer) { | |
| 5887 return false; | 6535 return false; |
| 5888 } | 6536 } else if (node is MethodDeclaration) { |
| 5889 if (node is MethodDeclaration) { | |
| 5890 return !node.isStatic; | 6537 return !node.isStatic; |
| 5891 } | 6538 } |
| 5892 } | 6539 } |
| 5893 return false; | 6540 return false; |
| 5894 } | 6541 } |
| 5895 | 6542 |
| 5896 /** | 6543 /** |
| 5897 * Return `true` if the given [identifier] is in a location where it is | 6544 * Return `true` if the given [identifier] is in a location where it is |
| 5898 * allowed to resolve to a static member of a supertype. | 6545 * allowed to resolve to a static member of a supertype. |
| 5899 */ | 6546 */ |
| 5900 bool _isUnqualifiedReferenceToNonLocalStaticMemberAllowed( | 6547 bool _isUnqualifiedReferenceToNonLocalStaticMemberAllowed( |
| 5901 SimpleIdentifier identifier) { | 6548 SimpleIdentifier identifier) { |
| 5902 if (identifier.inDeclarationContext()) { | 6549 if (identifier.inDeclarationContext()) { |
| 5903 return true; | 6550 return true; |
| 5904 } | 6551 } |
| 5905 AstNode parent = identifier.parent; | 6552 AstNode parent = identifier.parent; |
| 5906 if (parent is ConstructorName || | 6553 if (parent is Annotation) { |
| 5907 parent is MethodInvocation || | 6554 return identical(parent.constructorName, identifier); |
| 5908 parent is PropertyAccess || | |
| 5909 parent is SuperConstructorInvocation) { | |
| 5910 return true; | |
| 5911 } | |
| 5912 if (parent is PrefixedIdentifier && | |
| 5913 identical(parent.identifier, identifier)) { | |
| 5914 return true; | |
| 5915 } | |
| 5916 if (parent is Annotation && identical(parent.constructorName, identifier)) { | |
| 5917 return true; | |
| 5918 } | 6555 } |
| 5919 if (parent is CommentReference) { | 6556 if (parent is CommentReference) { |
| 5920 CommentReference commentReference = parent; | 6557 return parent.newKeyword != null; |
| 5921 if (commentReference.newKeyword != null) { | 6558 } |
| 5922 return true; | 6559 if (parent is ConstructorName) { |
| 5923 } | 6560 return identical(parent.name, identifier); |
| 6561 } |
| 6562 if (parent is MethodInvocation) { |
| 6563 return identical(parent.methodName, identifier); |
| 6564 } |
| 6565 if (parent is PrefixedIdentifier) { |
| 6566 return identical(parent.identifier, identifier); |
| 6567 } |
| 6568 if (parent is PropertyAccess) { |
| 6569 return identical(parent.propertyName, identifier); |
| 6570 } |
| 6571 if (parent is SuperConstructorInvocation) { |
| 6572 return identical(parent.constructorName, identifier); |
| 5924 } | 6573 } |
| 5925 return false; | 6574 return false; |
| 5926 } | 6575 } |
| 5927 | 6576 |
| 5928 bool _isUserDefinedObject(EvaluationResultImpl result) => result == null || | 6577 bool _isUserDefinedObject(EvaluationResultImpl result) => |
| 6578 result == null || |
| 5929 (result.value != null && result.value.isUserDefinedObject); | 6579 (result.value != null && result.value.isUserDefinedObject); |
| 5930 | 6580 |
| 5931 /** | 6581 /** |
| 5932 * Check that the given class [element] is not a superinterface to itself. The | 6582 * Check that the given class [element] is not a superinterface to itself. The |
| 5933 * [path] is a list containing the potentially cyclic implements path. | 6583 * [path] is a list containing the potentially cyclic implements path. |
| 5934 * | 6584 * |
| 5935 * See [CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE], | 6585 * See [CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE], |
| 5936 * [CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_EXTENDS], | 6586 * [CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_EXTENDS], |
| 5937 * [CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_IMPLEMENTS]
, | 6587 * [CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_IMPLEMENTS]
, |
| 5938 * and [CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_WITH]. | 6588 * and [CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_WITH]. |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6031 GeneralizingElementVisitor_ErrorVerifier_hasTypedefSelfReference(this.toCheck) | 6681 GeneralizingElementVisitor_ErrorVerifier_hasTypedefSelfReference(this.toCheck) |
| 6032 : super(); | 6682 : super(); |
| 6033 | 6683 |
| 6034 @override | 6684 @override |
| 6035 Object visitClassElement(ClassElement element) { | 6685 Object visitClassElement(ClassElement element) { |
| 6036 // Typedefs are allowed to reference themselves via classes. | 6686 // Typedefs are allowed to reference themselves via classes. |
| 6037 return null; | 6687 return null; |
| 6038 } | 6688 } |
| 6039 | 6689 |
| 6040 @override | 6690 @override |
| 6691 Object visitFunctionElement(FunctionElement element) { |
| 6692 _addTypeToCheck(element.returnType); |
| 6693 return super.visitFunctionElement(element); |
| 6694 } |
| 6695 |
| 6696 @override |
| 6041 Object visitFunctionTypeAliasElement(FunctionTypeAliasElement element) { | 6697 Object visitFunctionTypeAliasElement(FunctionTypeAliasElement element) { |
| 6042 _addTypeToCheck(element.returnType); | 6698 _addTypeToCheck(element.returnType); |
| 6043 return super.visitFunctionTypeAliasElement(element); | 6699 return super.visitFunctionTypeAliasElement(element); |
| 6044 } | 6700 } |
| 6045 | 6701 |
| 6046 @override | 6702 @override |
| 6047 Object visitParameterElement(ParameterElement element) { | 6703 Object visitParameterElement(ParameterElement element) { |
| 6048 _addTypeToCheck(element.type); | 6704 _addTypeToCheck(element.type); |
| 6049 return super.visitParameterElement(element); | 6705 return super.visitParameterElement(element); |
| 6050 } | 6706 } |
| 6051 | 6707 |
| 6052 @override | 6708 @override |
| 6053 Object visitTypeParameterElement(TypeParameterElement element) { | 6709 Object visitTypeParameterElement(TypeParameterElement element) { |
| 6054 _addTypeToCheck(element.bound); | 6710 _addTypeToCheck(element.bound); |
| 6055 return super.visitTypeParameterElement(element); | 6711 return super.visitTypeParameterElement(element); |
| 6056 } | 6712 } |
| 6057 | 6713 |
| 6058 void _addTypeToCheck(DartType type) { | 6714 void _addTypeToCheck(DartType type) { |
| 6059 if (type == null) { | 6715 if (type == null) { |
| 6060 return; | 6716 return; |
| 6061 } | 6717 } |
| 6062 // schedule for checking | 6718 // schedule for checking |
| 6063 toCheck.add(type.element); | 6719 toCheck.add(type.element); |
| 6064 // type arguments | 6720 // type arguments |
| 6065 if (type is InterfaceType) { | 6721 if (type is InterfaceType) { |
| 6066 InterfaceType interfaceType = type; | 6722 for (DartType typeArgument in type.typeArguments) { |
| 6067 for (DartType typeArgument in interfaceType.typeArguments) { | |
| 6068 _addTypeToCheck(typeArgument); | 6723 _addTypeToCheck(typeArgument); |
| 6069 } | 6724 } |
| 6070 } | 6725 } |
| 6071 } | 6726 } |
| 6072 } | 6727 } |
| 6728 |
| 6729 /** |
| 6730 * A record of the elements that will be declared in some scope (block), but are |
| 6731 * not yet declared. |
| 6732 */ |
| 6733 class HiddenElements { |
| 6734 /** |
| 6735 * The elements hidden in outer scopes, or `null` if this is the outermost |
| 6736 * scope. |
| 6737 */ |
| 6738 final HiddenElements outerElements; |
| 6739 |
| 6740 /** |
| 6741 * A set containing the elements that will be declared in this scope, but are |
| 6742 * not yet declared. |
| 6743 */ |
| 6744 Set<Element> _elements = new HashSet<Element>(); |
| 6745 |
| 6746 /** |
| 6747 * Initialize a newly created set of hidden elements to include all of the |
| 6748 * elements defined in the set of [outerElements] and all of the elements |
| 6749 * declared in the given [block]. |
| 6750 */ |
| 6751 HiddenElements(this.outerElements, Block block) { |
| 6752 _initializeElements(block); |
| 6753 } |
| 6754 |
| 6755 /** |
| 6756 * Return `true` if this set of elements contains the given [element]. |
| 6757 */ |
| 6758 bool contains(Element element) { |
| 6759 if (_elements.contains(element)) { |
| 6760 return true; |
| 6761 } else if (outerElements != null) { |
| 6762 return outerElements.contains(element); |
| 6763 } |
| 6764 return false; |
| 6765 } |
| 6766 |
| 6767 /** |
| 6768 * Record that the given [element] has been declared, so it is no longer |
| 6769 * hidden. |
| 6770 */ |
| 6771 void declare(Element element) { |
| 6772 _elements.remove(element); |
| 6773 } |
| 6774 |
| 6775 /** |
| 6776 * Initialize the list of elements that are not yet declared to be all of the |
| 6777 * elements declared somewhere in the given [block]. |
| 6778 */ |
| 6779 void _initializeElements(Block block) { |
| 6780 _elements.addAll(BlockScope.elementsInBlock(block)); |
| 6781 } |
| 6782 } |
| 6783 |
| 6784 /** |
| 6785 * A class used to compute a list of the constants whose value needs to be |
| 6786 * computed before errors can be computed by the [VerifyUnitTask]. |
| 6787 */ |
| 6788 class RequiredConstantsComputer extends RecursiveAstVisitor { |
| 6789 /** |
| 6790 * The source with which any pending errors will be associated. |
| 6791 */ |
| 6792 final Source source; |
| 6793 |
| 6794 /** |
| 6795 * A list of the pending errors that were computed. |
| 6796 */ |
| 6797 final List<PendingError> pendingErrors = <PendingError>[]; |
| 6798 |
| 6799 /** |
| 6800 * A list of the constants whose value needs to be computed before the pending |
| 6801 * errors can be used to compute an analysis error. |
| 6802 */ |
| 6803 final List<ConstantEvaluationTarget> requiredConstants = |
| 6804 <ConstantEvaluationTarget>[]; |
| 6805 |
| 6806 /** |
| 6807 * Initialize a newly created computer to compute required constants within |
| 6808 * the given [source]. |
| 6809 */ |
| 6810 RequiredConstantsComputer(this.source); |
| 6811 |
| 6812 @override |
| 6813 Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { |
| 6814 _checkForMissingRequiredParam( |
| 6815 node.staticInvokeType, node.argumentList, node); |
| 6816 return super.visitFunctionExpressionInvocation(node); |
| 6817 } |
| 6818 |
| 6819 @override |
| 6820 Object visitInstanceCreationExpression(InstanceCreationExpression node) { |
| 6821 DartType type = node.constructorName.type.type; |
| 6822 if (type is InterfaceType) { |
| 6823 _checkForMissingRequiredParam( |
| 6824 node.staticElement?.type, node.argumentList, node.constructorName); |
| 6825 } |
| 6826 return super.visitInstanceCreationExpression(node); |
| 6827 } |
| 6828 |
| 6829 @override |
| 6830 Object visitMethodInvocation(MethodInvocation node) { |
| 6831 _checkForMissingRequiredParam( |
| 6832 node.staticInvokeType, node.argumentList, node.methodName); |
| 6833 return super.visitMethodInvocation(node); |
| 6834 } |
| 6835 |
| 6836 @override |
| 6837 Object visitRedirectingConstructorInvocation( |
| 6838 RedirectingConstructorInvocation node) { |
| 6839 DartType type = node.staticElement?.type; |
| 6840 if (type != null) { |
| 6841 _checkForMissingRequiredParam(type, node.argumentList, node); |
| 6842 } |
| 6843 return super.visitRedirectingConstructorInvocation(node); |
| 6844 } |
| 6845 |
| 6846 @override |
| 6847 Object visitSuperConstructorInvocation(SuperConstructorInvocation node) { |
| 6848 DartType type = node.staticElement?.type; |
| 6849 if (type != null) { |
| 6850 _checkForMissingRequiredParam(type, node.argumentList, node); |
| 6851 } |
| 6852 return super.visitSuperConstructorInvocation(node); |
| 6853 } |
| 6854 |
| 6855 void _checkForMissingRequiredParam( |
| 6856 DartType type, ArgumentList argumentList, AstNode node) { |
| 6857 if (type is FunctionType) { |
| 6858 for (ParameterElement parameter in type.parameters) { |
| 6859 if (parameter.parameterKind == ParameterKind.NAMED) { |
| 6860 ElementAnnotationImpl annotation = _getRequiredAnnotation(parameter); |
| 6861 if (annotation != null) { |
| 6862 String parameterName = parameter.name; |
| 6863 if (!_containsNamedExpression(argumentList, parameterName)) { |
| 6864 requiredConstants.add(annotation); |
| 6865 pendingErrors.add(new PendingMissingRequiredParameterError( |
| 6866 source, parameterName, node, annotation)); |
| 6867 } |
| 6868 } |
| 6869 } |
| 6870 } |
| 6871 } |
| 6872 } |
| 6873 |
| 6874 bool _containsNamedExpression(ArgumentList args, String name) { |
| 6875 NodeList<Expression> arguments = args.arguments; |
| 6876 for (int i = arguments.length - 1; i >= 0; i--) { |
| 6877 Expression expression = arguments[i]; |
| 6878 if (expression is NamedExpression) { |
| 6879 if (expression.name.label.name == name) { |
| 6880 return true; |
| 6881 } |
| 6882 } |
| 6883 } |
| 6884 return false; |
| 6885 } |
| 6886 |
| 6887 ElementAnnotationImpl _getRequiredAnnotation(ParameterElement param) => param |
| 6888 .metadata |
| 6889 .firstWhere((ElementAnnotation e) => e.isRequired, orElse: () => null); |
| 6890 } |
| 6891 |
| 6892 /** |
| 6893 * Recursively visits an AST, looking for method invocations. |
| 6894 */ |
| 6895 class _InvocationCollector extends RecursiveAstVisitor { |
| 6896 final List<String> superCalls = <String>[]; |
| 6897 |
| 6898 @override |
| 6899 visitMethodInvocation(MethodInvocation node) { |
| 6900 if (node.target is SuperExpression) { |
| 6901 superCalls.add(node.methodName.name); |
| 6902 } |
| 6903 } |
| 6904 } |
| OLD | NEW |