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

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

Issue 2832893002: Issue 29398. Infer instance members using InheritanceManager of the ClassElement. (Closed)
Patch Set: Created 3 years, 8 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
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 23 matching lines...) Expand all
34 34
35 /** 35 /**
36 * Sets the type of the field. The types in implicit accessors are updated 36 * 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. 37 * implicitly, and the types of explicit accessors should be updated separately.
38 */ 38 */
39 void setFieldType(VariableElement field, DartType newType) { 39 void setFieldType(VariableElement field, DartType newType) {
40 (field as VariableElementImpl).type = newType; 40 (field as VariableElementImpl).type = newType;
41 } 41 }
42 42
43 /** 43 /**
44 * A function that return the [InheritanceManager] for the class [element].
45 */
46 typedef InheritanceManager InheritanceManagerProvider(ClassElement element);
47
48 /**
44 * A function that returns `true` if the given [element] passes the filter. 49 * A function that returns `true` if the given [element] passes the filter.
45 */ 50 */
46 typedef bool VariableFilter(VariableElement element); 51 typedef bool VariableFilter(VariableElement element);
47 52
48 /** 53 /**
49 * An object used to infer the type of instance fields and the return types of 54 * An object used to infer the type of instance fields and the return types of
50 * instance methods within a single compilation unit. 55 * instance methods within a single compilation unit.
51 */ 56 */
52 class InstanceMemberInferrer { 57 class InstanceMemberInferrer {
53 /** 58 /**
54 * The type provider used to look up types. 59 * The type provider used to look up types.
55 */ 60 */
56 final TypeProvider typeProvider; 61 final TypeProvider typeProvider;
57 62
58 /** 63 /**
59 * The type system used to compute the least upper bound of types. 64 * The type system used to compute the least upper bound of types.
60 */ 65 */
61 TypeSystem typeSystem; 66 TypeSystem typeSystem;
62 67
63 /** 68 /**
64 * The inheritance manager used to find overridden method. 69 * The provider for inheritance managers used to find overridden method.
65 */ 70 */
66 final InheritanceManager inheritanceManager; 71 final InheritanceManagerProvider inheritanceManagerProvider;
67 72
68 /** 73 /**
69 * The set of fields for which type inference from initializer should be 74 * The set of fields for which type inference from initializer should be
70 * disabled, because their initializers are not immediately-evident 75 * disabled, because their initializers are not immediately-evident
71 * expressions. 76 * expressions.
72 */ 77 */
73 final Set<FieldElement> fieldsWithDisabledInitializerInference; 78 final Set<FieldElement> fieldsWithDisabledInitializerInference;
74 79
75 /** 80 /**
76 * The classes that have been visited while attempting to infer the types of 81 * The classes that have been visited while attempting to infer the types of
77 * instance members of some base class. 82 * instance members of some base class.
78 */ 83 */
79 HashSet<ClassElementImpl> elementsBeingInferred = 84 HashSet<ClassElementImpl> elementsBeingInferred =
80 new HashSet<ClassElementImpl>(); 85 new HashSet<ClassElementImpl>();
81 86
82 /** 87 /**
83 * Initialize a newly create inferrer. 88 * Initialize a newly create inferrer.
84 */ 89 */
85 InstanceMemberInferrer(TypeProvider typeProvider, this.inheritanceManager, 90 InstanceMemberInferrer(
91 TypeProvider typeProvider,
92 this.inheritanceManagerProvider,
86 this.fieldsWithDisabledInitializerInference, 93 this.fieldsWithDisabledInitializerInference,
87 {TypeSystem typeSystem}) 94 {TypeSystem typeSystem})
88 : typeSystem = (typeSystem != null) 95 : typeSystem = (typeSystem != null)
89 ? typeSystem 96 ? typeSystem
90 : new TypeSystemImpl(typeProvider), 97 : new TypeSystemImpl(typeProvider),
91 this.typeProvider = typeProvider; 98 this.typeProvider = typeProvider;
92 99
93 /** 100 /**
94 * Infer type information for all of the instance members in the given 101 * Infer type information for all of the instance members in the given
95 * compilation [unit]. 102 * compilation [unit].
(...skipping 15 matching lines...) Expand all
111 bool _allSameElementKind( 118 bool _allSameElementKind(
112 ExecutableElement element, List<ExecutableElement> elements) { 119 ExecutableElement element, List<ExecutableElement> elements) {
113 return elements.every((e) => e.kind == element.kind); 120 return elements.every((e) => e.kind == element.kind);
114 } 121 }
115 122
116 /** 123 /**
117 * Compute the inferred type for the given property [accessor]. The returned 124 * Compute the inferred type for the given property [accessor]. The returned
118 * value is never `null`, but might be an error, and/or have the `null` type. 125 * value is never `null`, but might be an error, and/or have the `null` type.
119 */ 126 */
120 _FieldOverrideInferenceResult _computeFieldOverrideType( 127 _FieldOverrideInferenceResult _computeFieldOverrideType(
121 PropertyAccessorElement accessor) { 128 InheritanceManager inheritanceManager, PropertyAccessorElement accessor) {
122 String name = accessor.displayName; 129 String name = accessor.displayName;
123 130
124 var overriddenElements = <ExecutableElement>[]; 131 var overriddenElements = <ExecutableElement>[];
125 overriddenElements.addAll( 132 overriddenElements.addAll(
126 inheritanceManager.lookupOverrides(accessor.enclosingElement, name)); 133 inheritanceManager.lookupOverrides(accessor.enclosingElement, name));
127 if (overriddenElements.isEmpty || !accessor.variable.isFinal) { 134 if (overriddenElements.isEmpty || !accessor.variable.isFinal) {
128 List<ExecutableElement> overriddenSetters = inheritanceManager 135 List<ExecutableElement> overriddenSetters = inheritanceManager
129 .lookupOverrides(accessor.enclosingElement, '$name='); 136 .lookupOverrides(accessor.enclosingElement, '$name=');
130 overriddenElements.addAll(overriddenSetters); 137 overriddenElements.addAll(overriddenSetters);
131 } 138 }
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
248 return matchingParameter; 255 return matchingParameter;
249 } 256 }
250 } 257 }
251 return null; 258 return null;
252 } 259 }
253 260
254 /** 261 /**
255 * If the given [element] represents a non-synthetic instance property 262 * If the given [element] represents a non-synthetic instance property
256 * accessor for which no type was provided, infer its types. 263 * accessor for which no type was provided, infer its types.
257 */ 264 */
258 void _inferAccessor(PropertyAccessorElement element) { 265 void _inferAccessor(
266 InheritanceManager inheritanceManager, PropertyAccessorElement element) {
259 if (element.isSynthetic || element.isStatic) { 267 if (element.isSynthetic || element.isStatic) {
260 return; 268 return;
261 } 269 }
262 270
263 if (element.kind == ElementKind.GETTER && !element.hasImplicitReturnType) { 271 if (element.kind == ElementKind.GETTER && !element.hasImplicitReturnType) {
264 return; 272 return;
265 } 273 }
266 274
267 _FieldOverrideInferenceResult typeResult = 275 _FieldOverrideInferenceResult typeResult =
268 _computeFieldOverrideType(element); 276 _computeFieldOverrideType(inheritanceManager, element);
269 if (typeResult.isError == null || typeResult.type == null) { 277 if (typeResult.isError == null || typeResult.type == null) {
270 return; 278 return;
271 } 279 }
272 280
273 if (element.kind == ElementKind.GETTER) { 281 if (element.kind == ElementKind.GETTER) {
274 (element as ExecutableElementImpl).returnType = typeResult.type; 282 (element as ExecutableElementImpl).returnType = typeResult.type;
275 } else if (element.kind == ElementKind.SETTER) { 283 } else if (element.kind == ElementKind.SETTER) {
276 List<ParameterElement> parameters = element.parameters; 284 List<ParameterElement> parameters = element.parameters;
277 if (parameters.isNotEmpty) { 285 if (parameters.isNotEmpty) {
278 var parameter = parameters[0] as ParameterElementImpl; 286 var parameter = parameters[0] as ParameterElementImpl;
(...skipping 17 matching lines...) Expand all
296 } 304 }
297 if (!elementsBeingInferred.add(classElement)) { 305 if (!elementsBeingInferred.add(classElement)) {
298 // We have found a circularity in the class hierarchy. For now we just 306 // We have found a circularity in the class hierarchy. For now we just
299 // stop trying to infer any type information for any classes that 307 // stop trying to infer any type information for any classes that
300 // inherit from any class in the cycle. We could potentially limit the 308 // inherit from any class in the cycle. We could potentially limit the
301 // algorithm to only not inferring types in the classes in the cycle, 309 // algorithm to only not inferring types in the classes in the cycle,
302 // but it isn't clear that the results would be significantly better. 310 // but it isn't clear that the results would be significantly better.
303 throw new _CycleException(); 311 throw new _CycleException();
304 } 312 }
305 try { 313 try {
314 InheritanceManager inheritanceManager =
315 inheritanceManagerProvider(classElement);
306 // 316 //
307 // Ensure that all of instance members in the supertypes have had types 317 // Ensure that all of instance members in the supertypes have had types
308 // inferred for them. 318 // inferred for them.
309 // 319 //
310 _inferType(classElement.supertype); 320 _inferType(classElement.supertype);
311 classElement.mixins.forEach(_inferType); 321 classElement.mixins.forEach(_inferType);
312 classElement.interfaces.forEach(_inferType); 322 classElement.interfaces.forEach(_inferType);
313 // 323 //
314 // Then infer the types for the members. 324 // Then infer the types for the members.
315 // 325 //
316 classElement.fields.forEach(_inferField); 326 classElement.fields.forEach((field) {
317 classElement.accessors.forEach(_inferAccessor); 327 _inferField(inheritanceManager, field);
318 classElement.methods.forEach(_inferExecutable); 328 });
329 classElement.accessors.forEach((accessor) {
330 _inferAccessor(inheritanceManager, accessor);
331 });
332 classElement.methods.forEach((method) {
333 _inferExecutable(inheritanceManager, method);
334 });
319 // 335 //
320 // Infer initializing formal parameter types. This must happen after 336 // Infer initializing formal parameter types. This must happen after
321 // field types are inferred. 337 // field types are inferred.
322 // 338 //
323 classElement.constructors.forEach(_inferConstructorFieldFormals); 339 classElement.constructors.forEach(_inferConstructorFieldFormals);
324 classElement.hasBeenInferred = true; 340 classElement.hasBeenInferred = true;
325 } finally { 341 } finally {
326 elementsBeingInferred.remove(classElement); 342 elementsBeingInferred.remove(classElement);
327 } 343 }
328 } 344 }
329 } 345 }
330 346
331 void _inferConstructorFieldFormals(ConstructorElement constructor) { 347 void _inferConstructorFieldFormals(ConstructorElement constructor) {
332 for (ParameterElement parameter in constructor.parameters) { 348 for (ParameterElement parameter in constructor.parameters) {
333 if (parameter.hasImplicitType && 349 if (parameter.hasImplicitType &&
334 parameter is FieldFormalParameterElementImpl) { 350 parameter is FieldFormalParameterElementImpl) {
335 FieldElement field = parameter.field; 351 FieldElement field = parameter.field;
336 if (field != null) { 352 if (field != null) {
337 parameter.type = field.type; 353 parameter.type = field.type;
338 } 354 }
339 } 355 }
340 } 356 }
341 } 357 }
342 358
343 /** 359 /**
344 * If the given [element] represents a non-synthetic instance method, 360 * If the given [element] represents a non-synthetic instance method,
345 * getter or setter, infer the return type and any parameter type(s) where 361 * getter or setter, infer the return type and any parameter type(s) where
346 * they were not provided. 362 * they were not provided.
347 */ 363 */
348 void _inferExecutable(ExecutableElement element) { 364 void _inferExecutable(
365 InheritanceManager inheritanceManager, ExecutableElement element) {
349 if (element.isSynthetic || element.isStatic) { 366 if (element.isSynthetic || element.isStatic) {
350 return; 367 return;
351 } 368 }
352 List<ExecutableElement> overriddenElements = inheritanceManager 369 List<ExecutableElement> overriddenElements = inheritanceManager
353 .lookupOverrides(element.enclosingElement, element.displayName); 370 .lookupOverrides(element.enclosingElement, element.displayName);
354 if (overriddenElements.isEmpty || 371 if (overriddenElements.isEmpty ||
355 !_allSameElementKind(element, overriddenElements)) { 372 !_allSameElementKind(element, overriddenElements)) {
356 return; 373 return;
357 } 374 }
358 375
(...skipping 30 matching lines...) Expand all
389 } 406 }
390 } 407 }
391 } 408 }
392 } 409 }
393 } 410 }
394 411
395 /** 412 /**
396 * If the given [field] represents a non-synthetic instance field for 413 * If the given [field] represents a non-synthetic instance field for
397 * which no type was provided, infer the type of the field. 414 * which no type was provided, infer the type of the field.
398 */ 415 */
399 void _inferField(FieldElement field) { 416 void _inferField(InheritanceManager inheritanceManager, FieldElement field) {
400 if (field.isSynthetic || field.isStatic) { 417 if (field.isSynthetic || field.isStatic) {
401 return; 418 return;
402 } 419 }
403 420
404 _FieldOverrideInferenceResult typeResult = 421 _FieldOverrideInferenceResult typeResult =
405 _computeFieldOverrideType(field.getter); 422 _computeFieldOverrideType(inheritanceManager, field.getter);
406 if (typeResult.isError) { 423 if (typeResult.isError) {
407 if (field is FieldElementForLink_ClassField) { 424 if (field is FieldElementForLink_ClassField) {
408 field.setInferenceError(new TopLevelInferenceErrorBuilder( 425 field.setInferenceError(new TopLevelInferenceErrorBuilder(
409 kind: TopLevelInferenceErrorKind.overrideConflictFieldType)); 426 kind: TopLevelInferenceErrorKind.overrideConflictFieldType));
410 } 427 }
411 return; 428 return;
412 } 429 }
413 430
414 if (field.hasImplicitType) { 431 if (field.hasImplicitType) {
415 DartType newType = typeResult.type; 432 DartType newType = typeResult.type;
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
674 AstNode parent = node.parent; 691 AstNode parent = node.parent;
675 if (parent is PropertyAccess && parent.propertyName == node || 692 if (parent is PropertyAccess && parent.propertyName == node ||
676 parent is PrefixedIdentifier && parent.identifier == node) { 693 parent is PrefixedIdentifier && parent.identifier == node) {
677 isValid = false; 694 isValid = false;
678 } 695 }
679 } else if (element is PropertyAccessorElement && !element.isStatic) { 696 } else if (element is PropertyAccessorElement && !element.isStatic) {
680 isValid = false; 697 isValid = false;
681 } 698 }
682 } 699 }
683 } 700 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/task/dart.dart ('k') | pkg/analyzer/test/src/summary/top_level_inference_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698