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

Side by Side Diff: analyzer/lib/src/generated/error_verifier.dart

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

Powered by Google App Engine
This is Rietveld 408576698