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; |
} |
} |
} |