OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library analyzer.src.task.strong_mode; | 5 library analyzer.src.task.strong_mode; |
6 | 6 |
7 import 'dart:collection'; | 7 import 'dart:collection'; |
8 | 8 |
9 import 'package:analyzer/dart/ast/ast.dart'; | 9 import 'package:analyzer/dart/ast/ast.dart'; |
10 import 'package:analyzer/dart/ast/visitor.dart'; | 10 import 'package:analyzer/dart/ast/visitor.dart'; |
11 import 'package:analyzer/dart/element/element.dart'; | 11 import 'package:analyzer/dart/element/element.dart'; |
12 import 'package:analyzer/dart/element/type.dart'; | 12 import 'package:analyzer/dart/element/type.dart'; |
13 import 'package:analyzer/src/dart/element/element.dart'; | 13 import 'package:analyzer/src/dart/element/element.dart'; |
14 import 'package:analyzer/src/dart/element/type.dart'; | 14 import 'package:analyzer/src/dart/element/type.dart'; |
15 import 'package:analyzer/src/dart/resolver/inheritance_manager.dart'; | 15 import 'package:analyzer/src/dart/resolver/inheritance_manager.dart'; |
16 import 'package:analyzer/src/generated/resolver.dart' | 16 import 'package:analyzer/src/generated/resolver.dart' |
17 show TypeProvider, InheritanceManager; | 17 show TypeProvider, InheritanceManager; |
18 import 'package:analyzer/src/generated/type_system.dart'; | 18 import 'package:analyzer/src/generated/type_system.dart'; |
19 import 'package:analyzer/src/generated/utilities_dart.dart'; | 19 import 'package:analyzer/src/generated/utilities_dart.dart'; |
20 import 'package:analyzer/src/summary/format.dart'; | 20 import 'package:analyzer/src/summary/format.dart'; |
21 import 'package:analyzer/src/summary/idl.dart'; | 21 import 'package:analyzer/src/summary/idl.dart'; |
22 import 'package:analyzer/src/summary/link.dart' | 22 import 'package:analyzer/src/summary/link.dart' |
23 show FieldElementForLink_ClassField, ParameterElementForLink; | 23 show FieldElementForLink_ClassField, ParameterElementForLink; |
24 | 24 |
25 /** | 25 /** |
26 * Return `true` if the given [expression] is an immediately-evident expression, | |
27 * so can be used to infer the type for a top-level variable or a class field. | |
28 */ | |
29 bool isValidForTypeInference(Expression expression) { | |
30 var visitor = new _IsValidForTypeInferenceVisitor(); | |
31 expression.accept(visitor); | |
32 return visitor.isValid; | |
33 } | |
34 | |
35 /** | |
36 * Sets the type of the field. The types in implicit accessors are updated | 26 * Sets the type of the field. The types in implicit accessors are updated |
37 * implicitly, and the types of explicit accessors should be updated separately. | 27 * implicitly, and the types of explicit accessors should be updated separately. |
38 */ | 28 */ |
39 void setFieldType(VariableElement field, DartType newType) { | 29 void setFieldType(VariableElement field, DartType newType) { |
40 (field as VariableElementImpl).type = newType; | 30 (field as VariableElementImpl).type = newType; |
41 } | 31 } |
42 | 32 |
43 /** | 33 /** |
44 * A function that return the [InheritanceManager] for the class [element]. | 34 * A function that return the [InheritanceManager] for the class [element]. |
45 */ | 35 */ |
(...skipping 18 matching lines...) Expand all Loading... |
64 * The type system used to compute the least upper bound of types. | 54 * The type system used to compute the least upper bound of types. |
65 */ | 55 */ |
66 TypeSystem typeSystem; | 56 TypeSystem typeSystem; |
67 | 57 |
68 /** | 58 /** |
69 * The provider for inheritance managers used to find overridden method. | 59 * The provider for inheritance managers used to find overridden method. |
70 */ | 60 */ |
71 final InheritanceManagerProvider inheritanceManagerProvider; | 61 final InheritanceManagerProvider inheritanceManagerProvider; |
72 | 62 |
73 /** | 63 /** |
74 * The set of fields for which type inference from initializer should be | |
75 * disabled, because their initializers are not immediately-evident | |
76 * expressions. | |
77 */ | |
78 final Set<FieldElement> fieldsWithDisabledInitializerInference; | |
79 | |
80 /** | |
81 * The classes that have been visited while attempting to infer the types of | 64 * The classes that have been visited while attempting to infer the types of |
82 * instance members of some base class. | 65 * instance members of some base class. |
83 */ | 66 */ |
84 HashSet<ClassElementImpl> elementsBeingInferred = | 67 HashSet<ClassElementImpl> elementsBeingInferred = |
85 new HashSet<ClassElementImpl>(); | 68 new HashSet<ClassElementImpl>(); |
86 | 69 |
87 /** | 70 /** |
88 * Initialize a newly create inferrer. | 71 * Initialize a newly create inferrer. |
89 */ | 72 */ |
90 InstanceMemberInferrer( | 73 InstanceMemberInferrer( |
91 TypeProvider typeProvider, | 74 TypeProvider typeProvider, this.inheritanceManagerProvider, |
92 this.inheritanceManagerProvider, | |
93 this.fieldsWithDisabledInitializerInference, | |
94 {TypeSystem typeSystem}) | 75 {TypeSystem typeSystem}) |
95 : typeSystem = (typeSystem != null) | 76 : typeSystem = (typeSystem != null) |
96 ? typeSystem | 77 ? typeSystem |
97 : new TypeSystemImpl(typeProvider), | 78 : new TypeSystemImpl(typeProvider), |
98 this.typeProvider = typeProvider; | 79 this.typeProvider = typeProvider; |
99 | 80 |
100 /** | 81 /** |
101 * Infer type information for all of the instance members in the given | 82 * Infer type information for all of the instance members in the given |
102 * compilation [unit]. | 83 * compilation [unit]. |
103 */ | 84 */ |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
423 if (typeResult.isError) { | 404 if (typeResult.isError) { |
424 if (field is FieldElementForLink_ClassField) { | 405 if (field is FieldElementForLink_ClassField) { |
425 field.setInferenceError(new TopLevelInferenceErrorBuilder( | 406 field.setInferenceError(new TopLevelInferenceErrorBuilder( |
426 kind: TopLevelInferenceErrorKind.overrideConflictFieldType)); | 407 kind: TopLevelInferenceErrorKind.overrideConflictFieldType)); |
427 } | 408 } |
428 return; | 409 return; |
429 } | 410 } |
430 | 411 |
431 if (field.hasImplicitType) { | 412 if (field.hasImplicitType) { |
432 DartType newType = typeResult.type; | 413 DartType newType = typeResult.type; |
433 if (newType == null && | 414 if (newType == null && field.initializer != null) { |
434 field.initializer != null && | |
435 !fieldsWithDisabledInitializerInference.contains(field)) { | |
436 newType = field.initializer.returnType; | 415 newType = field.initializer.returnType; |
437 } | 416 } |
438 | 417 |
439 if (newType == null || newType.isBottom || newType.isDartCoreNull) { | 418 if (newType == null || newType.isBottom || newType.isDartCoreNull) { |
440 newType = typeProvider.dynamicType; | 419 newType = typeProvider.dynamicType; |
441 } | 420 } |
442 | 421 |
443 setFieldType(field, newType); | 422 setFieldType(field, newType); |
444 } | 423 } |
445 | 424 |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
601 /** | 580 /** |
602 * The result of field type inference. | 581 * The result of field type inference. |
603 */ | 582 */ |
604 class _FieldOverrideInferenceResult { | 583 class _FieldOverrideInferenceResult { |
605 final bool isCovariant; | 584 final bool isCovariant; |
606 final DartType type; | 585 final DartType type; |
607 final bool isError; | 586 final bool isError; |
608 | 587 |
609 _FieldOverrideInferenceResult(this.isCovariant, this.type, this.isError); | 588 _FieldOverrideInferenceResult(this.isCovariant, this.type, this.isError); |
610 } | 589 } |
611 | |
612 /** | |
613 * The visitor for [isValidForTypeInference]. | |
614 */ | |
615 class _IsValidForTypeInferenceVisitor extends RecursiveAstVisitor { | |
616 bool isValid = true; | |
617 | |
618 @override | |
619 void visitAssignmentExpression(AssignmentExpression node) { | |
620 isValid = false; | |
621 } | |
622 | |
623 @override | |
624 void visitCascadeExpression(CascadeExpression node) { | |
625 node.target.accept(this); | |
626 } | |
627 | |
628 @override | |
629 void visitFunctionExpression(FunctionExpression node) { | |
630 FunctionBody body = node.body; | |
631 if (body is ExpressionFunctionBody) { | |
632 body.accept(this); | |
633 } else { | |
634 isValid = false; | |
635 } | |
636 } | |
637 | |
638 @override | |
639 void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { | |
640 node.function?.accept(this); | |
641 } | |
642 | |
643 @override | |
644 void visitIndexExpression(IndexExpression node) { | |
645 isValid = false; | |
646 } | |
647 | |
648 @override | |
649 void visitInstanceCreationExpression(InstanceCreationExpression node) { | |
650 ConstructorElement constructor = node.staticElement; | |
651 if (constructor != null) { | |
652 ClassElement clazz = constructor?.enclosingElement; | |
653 if (clazz.typeParameters.isNotEmpty && | |
654 node.constructorName.type.typeArguments == null) { | |
655 isValid = false; | |
656 return; | |
657 } | |
658 } | |
659 } | |
660 | |
661 @override | |
662 void visitListLiteral(ListLiteral node) { | |
663 if (node.typeArguments == null) { | |
664 super.visitListLiteral(node); | |
665 } | |
666 } | |
667 | |
668 @override | |
669 void visitMapLiteral(MapLiteral node) { | |
670 if (node.typeArguments == null) { | |
671 super.visitMapLiteral(node); | |
672 } | |
673 } | |
674 | |
675 @override | |
676 void visitMethodInvocation(MethodInvocation node) { | |
677 Element element = node.methodName.staticElement; | |
678 if (element is ExecutableElement) { | |
679 if (element.type.typeFormals.isNotEmpty && node.typeArguments == null) { | |
680 isValid = false; | |
681 return; | |
682 } | |
683 } | |
684 node.target?.accept(this); | |
685 } | |
686 | |
687 @override | |
688 void visitSimpleIdentifier(SimpleIdentifier node) { | |
689 Element element = node.staticElement; | |
690 if (element == null) { | |
691 AstNode parent = node.parent; | |
692 if (parent is PropertyAccess && parent.propertyName == node || | |
693 parent is PrefixedIdentifier && parent.identifier == node) { | |
694 isValid = false; | |
695 } | |
696 } else if (element is PropertyAccessorElement && !element.isStatic) { | |
697 isValid = false; | |
698 } | |
699 } | |
700 } | |
OLD | NEW |