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/src/generated/ast.dart'; | 9 import 'package:analyzer/src/generated/ast.dart'; |
10 import 'package:analyzer/src/generated/element.dart'; | 10 import 'package:analyzer/src/generated/element.dart'; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
76 } | 76 } |
77 return null; | 77 return null; |
78 } | 78 } |
79 | 79 |
80 /** | 80 /** |
81 * A function that returns `true` if the given [variable] passes the filter. | 81 * A function that returns `true` if the given [variable] passes the filter. |
82 */ | 82 */ |
83 typedef bool VariableFilter(VariableElement element); | 83 typedef bool VariableFilter(VariableElement element); |
84 | 84 |
85 /** | 85 /** |
86 * An object used to find static variables whose types should be inferred and | |
87 * classes whose members should have types inferred. Clients are expected to | |
88 * visit a [CompilationUnit]. | |
89 */ | |
90 class InferrenceFinder extends SimpleAstVisitor { | |
91 /** | |
92 * The static variables that should have types inferred for them. | |
93 */ | |
94 final List<VariableElement> staticVariables = <VariableElement>[]; | |
95 | |
96 /** | |
97 * The classes defined in the unit. | |
98 * | |
99 * TODO(brianwilkerson) We don't currently remove classes whose members do not | |
100 * need to be processed, but we potentially could. | |
101 */ | |
102 final List<ClassElement> classes = <ClassElement>[]; | |
103 | |
104 /** | |
105 * Initialize a newly created finder. | |
106 */ | |
107 InferrenceFinder(); | |
108 | |
109 @override | |
110 void visitClassDeclaration(ClassDeclaration node) { | |
111 classes.add(node.element); | |
112 for (ClassMember member in node.members) { | |
113 member.accept(this); | |
114 } | |
115 } | |
116 | |
117 @override | |
118 void visitClassTypeAlias(ClassTypeAlias node) { | |
119 classes.add(node.element); | |
120 } | |
121 | |
122 @override | |
123 void visitCompilationUnit(CompilationUnit node) { | |
124 for (CompilationUnitMember declaration in node.declarations) { | |
125 declaration.accept(this); | |
126 } | |
127 } | |
128 | |
129 @override | |
130 void visitFieldDeclaration(FieldDeclaration node) { | |
131 if (node.isStatic && node.fields.type == null) { | |
132 _addVariables(node.fields.variables); | |
133 } | |
134 } | |
135 | |
136 @override | |
137 void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { | |
138 if (node.variables.type == null) { | |
139 _addVariables(node.variables.variables); | |
140 } | |
141 } | |
142 | |
143 /** | |
144 * Add all of the [variables] with initializers to the list of variables whose | |
145 * type can be inferred. Technically, we only infer the types of variables | |
146 * that do not have a static type, but all variables with initializers | |
147 * potentially need to be re-resolved after inference because they might | |
148 * refer to fields whose type was inferred. | |
149 */ | |
150 void _addVariables(NodeList<VariableDeclaration> variables) { | |
151 for (VariableDeclaration variable in variables) { | |
152 if (variable.initializer != null) { | |
153 VariableElement element = variable.element; | |
154 if (element.hasImplicitType) { | |
155 staticVariables.add(element); | |
156 } | |
157 } | |
158 } | |
159 } | |
160 } | |
161 | |
162 /** | |
163 * An object used to infer the type of instance fields and the return types of | 86 * An object used to infer the type of instance fields and the return types of |
164 * instance methods within a single compilation unit. | 87 * instance methods within a single compilation unit. |
165 */ | 88 */ |
166 class InstanceMemberInferrer { | 89 class InstanceMemberInferrer { |
167 /** | 90 /** |
168 * The type provider used to look up types. | 91 * The type provider used to look up types. |
169 */ | 92 */ |
170 final TypeProvider typeProvider; | 93 final TypeProvider typeProvider; |
171 | 94 |
172 /** | 95 /** |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
409 (fieldElement.isFinal || overriddenGetters.isEmpty)) { | 332 (fieldElement.isFinal || overriddenGetters.isEmpty)) { |
410 newType = fieldElement.initializer.returnType; | 333 newType = fieldElement.initializer.returnType; |
411 } | 334 } |
412 } | 335 } |
413 if (newType == null || newType.isBottom) { | 336 if (newType == null || newType.isBottom) { |
414 newType = typeProvider.dynamicType; | 337 newType = typeProvider.dynamicType; |
415 } | 338 } |
416 (fieldElement as FieldElementImpl).type = newType; | 339 (fieldElement as FieldElementImpl).type = newType; |
417 setReturnType(fieldElement.getter, newType); | 340 setReturnType(fieldElement.getter, newType); |
418 if (!fieldElement.isFinal && !fieldElement.isConst) { | 341 if (!fieldElement.isFinal && !fieldElement.isConst) { |
419 setParameterType(fieldElement.setter, newType); | 342 setParameterType(fieldElement.setter, newType); |
420 } | 343 } |
421 } | 344 } |
422 } | 345 } |
423 | 346 |
424 /** | 347 /** |
425 * If the given [methodElement] represents a non-synthetic instance method | 348 * If the given [methodElement] represents a non-synthetic instance method |
426 * for which no return type was provided, infer the return type of the method. | 349 * for which no return type was provided, infer the return type of the method. |
427 */ | 350 */ |
428 void _inferMethod(MethodElement methodElement) { | 351 void _inferMethod(MethodElement methodElement) { |
429 if (methodElement.isSynthetic || methodElement.isStatic) { | 352 if (methodElement.isSynthetic || methodElement.isStatic) { |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
548 results.add(element); | 471 results.add(element); |
549 } | 472 } |
550 } | 473 } |
551 } | 474 } |
552 } | 475 } |
553 | 476 |
554 /** | 477 /** |
555 * A class of exception that is not used anywhere else. | 478 * A class of exception that is not used anywhere else. |
556 */ | 479 */ |
557 class _CycleException implements Exception {} | 480 class _CycleException implements Exception {} |
OLD | NEW |