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 fc0fb787922d5b785dd2b024a97d97643499ba06..a294fa3ad37f92286a7026bf6db7318c0c0d43ac 100644 |
| --- a/pkg/analyzer/lib/src/generated/resolver.dart |
| +++ b/pkg/analyzer/lib/src/generated/resolver.dart |
| @@ -9395,6 +9395,10 @@ enum TypeResolverMode { |
| /** |
| * Resolve only type names that would be skipped during [api]. |
| + * |
| + * Resolution must start from a unit member or a class member. For example |
| + * it is not allowed to resolve types in a separate statement, or a function |
| + * body. |
| */ |
| local |
| } |
| @@ -9438,7 +9442,16 @@ class TypeResolverVisitor extends ScopedVisitor { |
| final TypeResolverMode mode; |
| - bool _visitAllInLocalMode = false; |
| + /** |
| + * Is `true` when we are visiting all nodes in [TypeResolverMode.local] mode. |
| + */ |
| + bool _localModeVisitAll = false; |
| + |
| + /** |
| + * Is `true` is we are in [TypeResolverMode.local] mode, and the initial |
|
Brian Wilkerson
2016/10/19 21:00:36
"is we" --> "if we"
|
| + * [nameScope] was computed. |
| + */ |
| + bool _localModeScopeReady = false; |
| /** |
| * Initialize a newly created visitor to resolve the nodes in an AST node. |
| @@ -9794,21 +9807,47 @@ class TypeResolverVisitor extends ScopedVisitor { |
| // resolve only type names that are local. |
| if (mode == TypeResolverMode.local) { |
| // We are in the state of visiting all nodes. |
| - if (_visitAllInLocalMode) { |
| + if (_localModeVisitAll) { |
| return super.visitNode(node); |
| } |
| + // Ensure that the name scope is ready. |
| + if (!_localModeScopeReady) { |
| + void fillNameScope(AstNode node) { |
| + if (node is FunctionBody || |
| + node is FormalParameterList || |
| + node is VariableDeclaration) { |
| + throw new StateError( |
| + 'Local type resolution must start from a class or unit member.'); |
| + } |
| + // Create enclosing name scopes. |
| + AstNode parent = node.parent; |
| + if (parent != null) { |
| + fillNameScope(parent); |
| + } |
| + // Create the name scope for the node. |
| + if (node is ClassDeclaration) { |
| + ClassElement classElement = node.element; |
| + nameScope = new TypeParameterScope(nameScope, classElement); |
| + nameScope = new ClassScope(nameScope, classElement); |
| + } |
| + } |
| + |
| + fillNameScope(node); |
| + _localModeScopeReady = true; |
| + } |
| + |
| /** |
| * Visit the given [node] and all its children. |
| */ |
| void visitAllNodes(AstNode node) { |
| if (node != null) { |
| - bool wasVisitAllInLocalMode = _visitAllInLocalMode; |
| + bool wasVisitAllInLocalMode = _localModeVisitAll; |
| try { |
| - _visitAllInLocalMode = true; |
| + _localModeVisitAll = true; |
| node.accept(this); |
| } finally { |
| - _visitAllInLocalMode = wasVisitAllInLocalMode; |
| + _localModeVisitAll = wasVisitAllInLocalMode; |
| } |
| } |
| } |