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

Side by Side Diff: pkg/analyzer/lib/src/task/strong_mode.dart

Issue 2741033004: Infer types of instance methods before any other inference. (Closed)
Patch Set: Created 3 years, 9 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 | « pkg/analyzer/lib/src/task/dart.dart ('k') | pkg/analyzer/test/src/task/strong_mode_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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';
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
66 66
67 /** 67 /**
68 * The inheritance manager used to find overridden method. 68 * The inheritance manager used to find overridden method.
69 */ 69 */
70 final InheritanceManager inheritanceManager; 70 final InheritanceManager inheritanceManager;
71 71
72 /** 72 /**
73 * The classes that have been visited while attempting to infer the types of 73 * The classes that have been visited while attempting to infer the types of
74 * instance members of some base class. 74 * instance members of some base class.
75 */ 75 */
76 HashSet<ClassElementImpl> elementsBeingInferred = 76 HashSet<ClassElementImpl> classesBeingInferred =
77 new HashSet<ClassElementImpl>(); 77 new HashSet<ClassElementImpl>();
78 78
79 /** 79 /**
80 * Initialize a newly create inferrer. 80 * Initialize a newly create inferrer.
81 */ 81 */
82 InstanceMemberInferrer(TypeProvider typeProvider, this.inheritanceManager, 82 InstanceMemberInferrer(TypeProvider typeProvider, this.inheritanceManager,
83 {TypeSystem typeSystem}) 83 {TypeSystem typeSystem})
84 : typeSystem = (typeSystem != null) 84 : typeSystem = (typeSystem != null)
85 ? typeSystem 85 ? typeSystem
86 : new TypeSystemImpl(typeProvider), 86 : new TypeSystemImpl(typeProvider),
87 this.typeProvider = typeProvider; 87 this.typeProvider = typeProvider;
88 88
89 /** 89 /**
90 * Infer type information for all of the instance members in the given 90 * Infer type information for all of the instance members in the given
91 * compilation [unit]. 91 * compilation [unit].
92 */ 92 */
93 void inferCompilationUnit(CompilationUnitElement unit) { 93 void inferCompilationUnit(CompilationUnitElement unit) {
94 for (ClassElement classElement in unit.types) { 94 for (ClassElement classElement in unit.types) {
95 try { 95 try {
96 _inferClass(classElement); 96 _inferClass(classElement);
97 } on _CycleException { 97 } on _CycleException {
98 // This is a short circuit return to prevent types that inherit from 98 // This is a short circuit return to prevent types that inherit from
99 // types containing a circular reference from being inferred. 99 // types containing a circular reference from being inferred.
100 } 100 }
101 } 101 }
102 } 102 }
103 103
104 /** 104 /**
105 * Infer types for all of the instance methods in [unit].
106 */
107 void inferInstanceMethods(CompilationUnitElement unit) {
108 for (ClassElement classElement in unit.types) {
109 try {
110 _inferClassInstanceMethods(classElement);
111 } on _CycleException {}
112 }
113 }
114
115 /**
105 * Return `true` if the list of [elements] contains only methods. 116 * Return `true` if the list of [elements] contains only methods.
106 */ 117 */
107 bool _allSameElementKind( 118 bool _allSameElementKind(
108 ExecutableElement element, List<ExecutableElement> elements) { 119 ExecutableElement element, List<ExecutableElement> elements) {
109 return elements.every((e) => e.kind == element.kind); 120 return elements.every((e) => e.kind == element.kind);
110 } 121 }
111 122
112 /** 123 /**
113 * Compute the best type for the [parameter] at the given [index] that must be 124 * Compute the best type for the [parameter] at the given [index] that must be
114 * compatible with the types of the corresponding parameters of the given 125 * compatible with the types of the corresponding parameters of the given
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 207
197 /** 208 /**
198 * Infer type information for all of the instance members in the given 209 * Infer type information for all of the instance members in the given
199 * [classElement]. 210 * [classElement].
200 */ 211 */
201 void _inferClass(ClassElement classElement) { 212 void _inferClass(ClassElement classElement) {
202 if (classElement is ClassElementImpl) { 213 if (classElement is ClassElementImpl) {
203 if (classElement.hasBeenInferred) { 214 if (classElement.hasBeenInferred) {
204 return; 215 return;
205 } 216 }
206 if (!elementsBeingInferred.add(classElement)) { 217 if (!classesBeingInferred.add(classElement)) {
207 // We have found a circularity in the class hierarchy. For now we just 218 // We have found a circularity in the class hierarchy. For now we just
208 // stop trying to infer any type information for any classes that 219 // stop trying to infer any type information for any classes that
209 // inherit from any class in the cycle. We could potentially limit the 220 // inherit from any class in the cycle. We could potentially limit the
210 // algorithm to only not inferring types in the classes in the cycle, 221 // algorithm to only not inferring types in the classes in the cycle,
211 // but it isn't clear that the results would be significantly better. 222 // but it isn't clear that the results would be significantly better.
212 throw new _CycleException(); 223 throw new _CycleException();
213 } 224 }
214 try { 225 try {
215 // 226 //
216 // Ensure that all of instance members in the supertypes have had types 227 // Ensure that all of instance members in the supertypes have had types
217 // inferred for them. 228 // inferred for them.
218 // 229 //
219 _inferType(classElement.supertype); 230 _inferType(classElement.supertype);
220 classElement.mixins.forEach(_inferType); 231 classElement.mixins.forEach(_inferType);
221 classElement.interfaces.forEach(_inferType); 232 classElement.interfaces.forEach(_inferType);
222 // 233 //
223 // Then infer the types for the members. 234 // Then infer the types for the members.
224 // 235 //
225 classElement.fields.forEach(_inferField); 236 classElement.fields.forEach(_inferField);
226 classElement.accessors.forEach(_inferExecutable); 237 classElement.accessors.forEach(_inferExecutable);
227 classElement.methods.forEach(_inferExecutable);
228 // 238 //
229 // Infer initializing formal parameter types. This must happen after 239 // Infer initializing formal parameter types. This must happen after
230 // field types are inferred. 240 // field types are inferred.
231 // 241 //
232 classElement.constructors.forEach(_inferConstructorFieldFormals); 242 classElement.constructors.forEach(_inferConstructorFieldFormals);
233 classElement.hasBeenInferred = true; 243 classElement.hasBeenInferred = true;
234 } finally { 244 } finally {
235 elementsBeingInferred.remove(classElement); 245 classesBeingInferred.remove(classElement);
236 } 246 }
237 } 247 }
238 } 248 }
249
250 /**
251 * Infer types for all of the instance methods in the given [classElement].
252 */
253 void _inferClassInstanceMethods(ClassElement classElement) {
254 if (classElement is ClassElementImpl) {
255 if (classElement.hasInferredInstanceMethods) {
256 return;
257 }
258 if (!classesBeingInferred.add(classElement)) {
259 // We have found a circularity in the class hierarchy. For now we just
260 // stop trying to infer any type information for any classes that
261 // inherit from any class in the cycle. We could potentially limit the
262 // algorithm to only not inferring types in the classes in the cycle,
263 // but it isn't clear that the results would be significantly better.
264 throw new _CycleException();
265 }
266 try {
267 //
268 // Process supertypes first.
269 //
270 void processSupertype(InterfaceType type) {
271 ClassElement element = type?.element;
272 if (element != null) {
273 _inferClassInstanceMethods(element);
274 }
275 }
276
277 processSupertype(classElement.supertype);
278 classElement.mixins.forEach(processSupertype);
279 classElement.interfaces.forEach(processSupertype);
280
281 //
282 // Then infer the types for the instance methods in this class.
283 //
284 classElement.methods.forEach(_inferExecutable);
285 classElement.hasInferredInstanceMethods = true;
286 } finally {
287 classesBeingInferred.remove(classElement);
288 }
289 }
290 }
239 291
240 void _inferConstructorFieldFormals(ConstructorElement element) { 292 void _inferConstructorFieldFormals(ConstructorElement element) {
241 for (ParameterElement p in element.parameters) { 293 for (ParameterElement p in element.parameters) {
242 if (p is FieldFormalParameterElementImpl) { 294 if (p is FieldFormalParameterElementImpl) {
243 _inferFieldFormalParameter(p); 295 _inferFieldFormalParameter(p);
244 } 296 }
245 } 297 }
246 } 298 }
247 299
248 /** 300 /**
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
498 results.add(element); 550 results.add(element);
499 } 551 }
500 } 552 }
501 } 553 }
502 } 554 }
503 555
504 /** 556 /**
505 * A class of exception that is not used anywhere else. 557 * A class of exception that is not used anywhere else.
506 */ 558 */
507 class _CycleException implements Exception {} 559 class _CycleException implements Exception {}
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/task/dart.dart ('k') | pkg/analyzer/test/src/task/strong_mode_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698