Chromium Code Reviews| Index: pkg/analyzer/lib/src/generated/resolver.dart |
| diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart |
| index 1c2e60b1f1027fee689d0dc3521dc08c2c8bd8f1..758ab7217f9ddafc673a4fe8352d8abb461173dc 100644 |
| --- a/pkg/analyzer/lib/src/generated/resolver.dart |
| +++ b/pkg/analyzer/lib/src/generated/resolver.dart |
| @@ -10921,6 +10921,27 @@ class ResolverVisitor extends ScopedVisitor { |
| } |
| @override |
| + void visitClassMembersInScope(ClassDeclaration node) { |
| + safelyVisit(node.documentationComment); |
| + node.metadata.accept(this); |
| + // |
| + // Visit the fields before other members so that instance fields will have |
| + // propagated types associated with them before we see their use sites. |
| + // |
| + List<ClassMember> nonFields = <ClassMember>[]; |
| + for (ClassMember member in node.members) { |
| + if (member is FieldDeclaration) { |
| + member.accept(this); |
| + } else { |
| + nonFields.add(member); |
| + } |
| + } |
| + for (ClassMember member in nonFields) { |
| + member.accept(this); |
| + } |
| + } |
| + |
| + @override |
| Object visitComment(Comment node) { |
| if (node.parent is FunctionDeclaration || |
| node.parent is ConstructorDeclaration || |
| @@ -11532,9 +11553,26 @@ class ResolverVisitor extends ScopedVisitor { |
| Object visitVariableDeclaration(VariableDeclaration node) { |
| super.visitVariableDeclaration(node); |
| VariableElement element = node.element; |
| - if (element.initializer != null && node.initializer != null) { |
| - (element.initializer as FunctionElementImpl).returnType = |
| - node.initializer.staticType; |
| + FunctionElement initializerElement = element.initializer; |
| + Expression initializer = node.initializer; |
| + if (initializerElement is FunctionElementImpl && initializer != null) { |
| + initializerElement.returnType = initializer.staticType; |
| + } |
| + // |
| + // Propagate types for instance fields. Top-level variables and static |
| + // fields are handled elsewhere. |
| + // |
| + if (initializer != null && |
| + element is FieldElementImpl && |
| + !element.isStatic && |
| + (element.isFinal || element.isConst)) { |
|
Paul Berry
2015/10/29 17:49:17
Isn't the test for `element.isConst` redundant? I
Brian Wilkerson
2015/10/29 18:31:04
Actually, no. With illegal code, such as "const in
|
| + DartType staticType = element.type; |
| + DartType bestType = initializer.bestType; |
| + if (bestType != null && |
| + bestType != staticType && |
| + bestType.isMoreSpecificThan(staticType)) { |
| + element.propagatedType = bestType; |
| + } |
| } |
| // Note: in addition to cloning the initializers for const variables, we |
| // have to clone the initializers for non-static final fields (because if |
| @@ -11544,9 +11582,9 @@ class ResolverVisitor extends ScopedVisitor { |
| (element is FieldElement && |
| element.isFinal && |
| !element.isStatic)) && |
| - node.initializer != null) { |
| + initializer != null) { |
| (element as ConstVariableElement).constantInitializer = |
| - new ConstantAstCloner().cloneNode(node.initializer); |
| + new ConstantAstCloner().cloneNode(initializer); |
| } |
| return null; |
| } |