Version 2.15.0-17.0.dev
Merge commit 'f0f94705a49fca9789490987bfc5181d71a3b827' into 'dev'
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 9fdb59c..d776e90 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -2325,9 +2325,12 @@
}
}
-/// The abstract class `ScopedVisitor` maintains name and label scopes as an AST
-/// structure is being visited.
-abstract class ScopedVisitor extends ResolverBase {
+/// Instances of the class `ScopeResolverVisitor` are used to resolve
+/// [SimpleIdentifier]s to declarations using scoping rules.
+///
+/// TODO(paulberry): migrate the responsibility for all scope resolution into
+/// this visitor.
+class ScopeResolverVisitor extends ResolverBase {
static const _nameScopeProperty = 'nameScope';
/// The scope used to resolve identifiers.
@@ -2340,12 +2343,20 @@
/// `null` if no labels have been defined in the current context.
LabelScope? labelScope;
- /// Initialize a newly created visitor to resolve the nodes in a compilation
- /// unit.
+ /// The container with information about local variables.
+ final LocalVariableInfo _localVariableInfo = LocalVariableInfo();
+
+ /// If the current function is contained within a closure (a local function or
+ /// function expression inside another executable declaration), the element
+ /// representing the closure; otherwise `null`.
+ ExecutableElement? _enclosingClosure;
+
+ /// Initialize a newly created visitor to resolve the nodes in an AST node.
///
- /// [definingLibrary] is the element for the library containing the
- /// compilation unit being visited.
- /// [source] is the source representing the compilation unit being visited.
+ /// [definingLibrary] is the element for the library containing the node being
+ /// visited.
+ /// [source] is the source representing the compilation unit containing the
+ /// node being visited
/// [typeProvider] is the object used to access the types from the core
/// library.
/// [errorListener] is the error listener that will be informed of any errors
@@ -2353,33 +2364,17 @@
/// [nameScope] is the scope used to resolve identifiers in the node that will
/// first be visited. If `null` or unspecified, a new [LibraryScope] will be
/// created based on [definingLibrary] and [typeProvider].
- ScopedVisitor(LibraryElementImpl definingLibrary, Source source,
- TypeProviderImpl typeProvider, AnalysisErrorListener errorListener,
+ ScopeResolverVisitor(LibraryElementImpl definingLibrary, Source source,
+ TypeProvider typeProvider, AnalysisErrorListener errorListener,
{Scope? nameScope})
: nameScope = nameScope ?? LibraryScope(definingLibrary),
- super(definingLibrary, source, typeProvider, errorListener);
+ super(definingLibrary, source, typeProvider as TypeProviderImpl,
+ errorListener);
/// Return the implicit label scope in which the current node is being
/// resolved.
ImplicitLabelScope get implicitLabelScope => _implicitLabelScope;
- /// Replaces the current [Scope] with the enclosing [Scope].
- ///
- /// @return the enclosing [Scope].
- Scope popNameScope() {
- nameScope = (nameScope as EnclosedScope).parent;
- return nameScope;
- }
-
- /// Pushes a new [Scope] into the visitor.
- ///
- /// @return the new [Scope].
- Scope pushNameScope() {
- Scope newScope = LocalScope(nameScope);
- nameScope = newScope;
- return nameScope;
- }
-
@override
void visitBlock(Block node) {
_withDeclaredLocals(node, node.statements, () {
@@ -2399,6 +2394,11 @@
}
@override
+ void visitBreakStatement(covariant BreakStatementImpl node) {
+ node.target = _lookupBreakOrContinueTarget(node, node.label, false);
+ }
+
+ @override
void visitCatchClause(CatchClause node) {
var exception = node.exceptionParameter;
if (exception != null) {
@@ -2490,6 +2490,7 @@
@override
void visitConstructorDeclaration(ConstructorDeclaration node) {
+ (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo;
Scope outerScope = nameScope;
try {
ConstructorElement element = node.declaredElement!;
@@ -2527,6 +2528,11 @@
}
@override
+ void visitContinueStatement(covariant ContinueStatementImpl node) {
+ node.target = _lookupBreakOrContinueTarget(node, node.label, true);
+ }
+
+ @override
void visitDeclaredIdentifier(DeclaredIdentifier node) {
_define(node.declaredElement!);
super.visitDeclaredIdentifier(node);
@@ -2692,9 +2698,15 @@
@override
void visitFunctionDeclaration(FunctionDeclaration node) {
- node.metadata.accept(this);
+ (node.functionExpression.body as FunctionBodyImpl).localVariableInfo =
+ _localVariableInfo;
+ var outerClosure = _enclosingClosure;
Scope outerScope = nameScope;
try {
+ _enclosingClosure = node.parent is FunctionDeclarationStatement
+ ? node.declaredElement
+ : null;
+ node.metadata.accept(this);
var element = node.declaredElement!;
nameScope = TypeParameterScope(
nameScope,
@@ -2704,6 +2716,7 @@
visitFunctionDeclarationInScope(node);
} finally {
nameScope = outerScope;
+ _enclosingClosure = outerClosure;
}
}
@@ -2717,16 +2730,21 @@
@override
void visitFunctionExpression(FunctionExpression node) {
- var parent = node.parent;
- if (parent is FunctionDeclaration) {
- // We have already created a function scope and don't need to do so again.
- super.visitFunctionExpression(node);
- parent.documentationComment?.accept(this);
- return;
- }
-
+ var outerClosure = _enclosingClosure;
Scope outerScope = nameScope;
try {
+ if (node.parent is! FunctionDeclaration) {
+ (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo;
+ _enclosingClosure = node.declaredElement;
+ }
+ var parent = node.parent;
+ if (parent is FunctionDeclaration) {
+ // We have already created a function scope and don't need to do so again.
+ super.visitFunctionExpression(node);
+ parent.documentationComment?.accept(this);
+ return;
+ }
+
ExecutableElement element = node.declaredElement!;
nameScope = FormalParameterScope(
TypeParameterScope(nameScope, element.typeParameters),
@@ -2735,6 +2753,7 @@
super.visitFunctionExpression(node);
} finally {
nameScope = outerScope;
+ _enclosingClosure = outerClosure;
}
}
@@ -2864,6 +2883,7 @@
@override
void visitMethodDeclaration(MethodDeclaration node) {
+ (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo;
node.metadata.accept(this);
Scope outerScope = nameScope;
try {
@@ -2893,6 +2913,20 @@
}
@override
+ void visitMethodInvocation(MethodInvocation node) {
+ // Only visit the method name if there's no real target (so this is an
+ // unprefixed function invocation, outside a cascade). This is the only
+ // circumstance in which the method name is meant to be looked up in the
+ // current scope.
+ node.target?.accept(this);
+ if (node.realTarget == null) {
+ node.methodName.accept(this);
+ }
+ node.typeArguments?.accept(this);
+ node.argumentList.accept(this);
+ }
+
+ @override
void visitMixinDeclaration(MixinDeclaration node) {
Scope outerScope = nameScope;
try {
@@ -2922,6 +2956,64 @@
node.members.accept(this);
}
+ @override
+ void visitPrefixedIdentifier(PrefixedIdentifier node) {
+ // Do not visit the identifier after the `.`, since it is not meant to be
+ // looked up in the current scope.
+ node.prefix.accept(this);
+ }
+
+ @override
+ void visitPropertyAccess(PropertyAccess node) {
+ // Do not visit the property name, since it is not meant to be looked up in
+ // the current scope.
+ node.target?.accept(this);
+ }
+
+ @override
+ void visitSimpleIdentifier(covariant SimpleIdentifierImpl node) {
+ // Ignore if already resolved - declaration or type.
+ if (node.inDeclarationContext()) {
+ return;
+ }
+ // Ignore if qualified.
+ var parent = node.parent;
+ var scopeLookupResult = nameScope.lookup(node.name);
+ node.scopeLookupResult = scopeLookupResult;
+ // Ignore if it cannot be a reference to a local variable.
+ if (parent is FieldFormalParameter) {
+ return;
+ } else if (parent is ConstructorDeclaration && parent.returnType == node) {
+ return;
+ } else if (parent is ConstructorFieldInitializer &&
+ parent.fieldName == node) {
+ return;
+ }
+ if (parent is ConstructorName) {
+ return;
+ }
+ if (parent is Label) {
+ return;
+ }
+ // Prepare VariableElement.
+ var element = scopeLookupResult.getter;
+ if (element is! VariableElement) {
+ return;
+ }
+ // Must be local or parameter.
+ ElementKind kind = element.kind;
+ if (kind == ElementKind.LOCAL_VARIABLE || kind == ElementKind.PARAMETER) {
+ node.staticElement = element;
+ if (node.inSetterContext()) {
+ _localVariableInfo.potentiallyMutatedInScope.add(element);
+ if (_enclosingClosure != null &&
+ element.enclosingElement != _enclosingClosure) {
+ _localVariableInfo.potentiallyMutatedInClosure.add(element);
+ }
+ }
+ }
+ }
+
/// Visit the given statement after it's scope has been created. This is used
/// by ResolverVisitor to correctly visit the 'then' and 'else' statements of
/// an 'if' statement.
@@ -2985,6 +3077,9 @@
}
@override
+ void visitTypeName(TypeName node) {}
+
+ @override
void visitVariableDeclaration(VariableDeclaration node) {
super.visitVariableDeclaration(node);
@@ -3024,185 +3119,6 @@
(nameScope as LocalScope).add(element);
}
- void _withDeclaredLocals(
- AstNode node,
- List<Statement> statements,
- void Function() f,
- ) {
- var outerScope = nameScope;
- try {
- var enclosedScope = LocalScope(nameScope);
- BlockScope.elementsInStatements(statements).forEach(enclosedScope.add);
-
- nameScope = enclosedScope;
- _setNodeNameScope(node, nameScope);
-
- f();
- } finally {
- nameScope = outerScope;
- }
- }
-
- /// Return the [Scope] to use while resolving inside the [node].
- ///
- /// Not every node has the scope set, for example we set the scopes for
- /// blocks, but statements don't have separate scopes. The compilation unit
- /// has the library scope.
- static Scope? getNodeNameScope(AstNode node) {
- return node.getProperty(_nameScopeProperty);
- }
-
- /// Set the [Scope] to use while resolving inside the [node].
- static void _setNodeNameScope(AstNode node, Scope scope) {
- node.setProperty(_nameScopeProperty, scope);
- }
-}
-
-/// Instances of the class `ScopeResolverVisitor` are used to resolve
-/// [SimpleIdentifier]s to declarations using scoping rules.
-///
-/// TODO(paulberry): migrate the responsibility for all scope resolution into
-/// this visitor.
-class ScopeResolverVisitor extends ScopedVisitor {
- /// The container with information about local variables.
- final LocalVariableInfo _localVariableInfo = LocalVariableInfo();
-
- /// If the current function is contained within a closure (a local function or
- /// function expression inside another executable declaration), the element
- /// representing the closure; otherwise `null`.
- ExecutableElement? _enclosingClosure;
-
- /// Initialize a newly created visitor to resolve the nodes in an AST node.
- ///
- /// [definingLibrary] is the element for the library containing the node being
- /// visited.
- /// [source] is the source representing the compilation unit containing the
- /// node being visited
- /// [typeProvider] is the object used to access the types from the core
- /// library.
- /// [errorListener] is the error listener that will be informed of any errors
- /// that are found during resolution.
- /// [nameScope] is the scope used to resolve identifiers in the node that will
- /// first be visited. If `null` or unspecified, a new [LibraryScope] will be
- /// created based on [definingLibrary] and [typeProvider].
- ScopeResolverVisitor(LibraryElementImpl definingLibrary, Source source,
- TypeProvider typeProvider, AnalysisErrorListener errorListener,
- {Scope? nameScope})
- : super(definingLibrary, source, typeProvider as TypeProviderImpl,
- errorListener,
- nameScope: nameScope);
-
- @override
- void visitBreakStatement(covariant BreakStatementImpl node) {
- node.target = _lookupBreakOrContinueTarget(node, node.label, false);
- }
-
- @override
- void visitConstructorDeclaration(ConstructorDeclaration node) {
- (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo;
- super.visitConstructorDeclaration(node);
- }
-
- @override
- void visitContinueStatement(covariant ContinueStatementImpl node) {
- node.target = _lookupBreakOrContinueTarget(node, node.label, true);
- }
-
- @override
- void visitFunctionDeclaration(FunctionDeclaration node) {
- (node.functionExpression.body as FunctionBodyImpl).localVariableInfo =
- _localVariableInfo;
- var outerClosure = _enclosingClosure;
- try {
- _enclosingClosure = node.parent is FunctionDeclarationStatement
- ? node.declaredElement
- : null;
- super.visitFunctionDeclaration(node);
- } finally {
- _enclosingClosure = outerClosure;
- }
- }
-
- @override
- void visitFunctionExpression(FunctionExpression node) {
- if (node.parent is! FunctionDeclaration) {
- (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo;
- var outerClosure = _enclosingClosure;
- try {
- _enclosingClosure = node.declaredElement;
- super.visitFunctionExpression(node);
- } finally {
- _enclosingClosure = outerClosure;
- }
- } else {
- super.visitFunctionExpression(node);
- }
- }
-
- @override
- void visitMethodDeclaration(MethodDeclaration node) {
- (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo;
- super.visitMethodDeclaration(node);
- }
-
- @override
- void visitSimpleIdentifier(covariant SimpleIdentifierImpl node) {
- // Ignore if already resolved - declaration or type.
- if (node.inDeclarationContext()) {
- return;
- }
- // Ignore if qualified.
- var parent = node.parent;
- if (parent is PrefixedIdentifier && identical(parent.identifier, node)) {
- return;
- }
- if (parent is PropertyAccess && identical(parent.propertyName, node)) {
- return;
- }
- if (parent is MethodInvocation &&
- identical(parent.methodName, node) &&
- parent.realTarget != null) {
- return;
- }
- var scopeLookupResult = nameScope.lookup(node.name);
- node.scopeLookupResult = scopeLookupResult;
- // Ignore if it cannot be a reference to a local variable.
- if (parent is FieldFormalParameter) {
- return;
- } else if (parent is ConstructorDeclaration && parent.returnType == node) {
- return;
- } else if (parent is ConstructorFieldInitializer &&
- parent.fieldName == node) {
- return;
- }
- if (parent is ConstructorName) {
- return;
- }
- if (parent is Label) {
- return;
- }
- // Prepare VariableElement.
- var element = scopeLookupResult.getter;
- if (element is! VariableElement) {
- return;
- }
- // Must be local or parameter.
- ElementKind kind = element.kind;
- if (kind == ElementKind.LOCAL_VARIABLE || kind == ElementKind.PARAMETER) {
- node.staticElement = element;
- if (node.inSetterContext()) {
- _localVariableInfo.potentiallyMutatedInScope.add(element);
- if (_enclosingClosure != null &&
- element.enclosingElement != _enclosingClosure) {
- _localVariableInfo.potentiallyMutatedInClosure.add(element);
- }
- }
- }
- }
-
- @override
- void visitTypeName(TypeName node) {}
-
/// Return the target of a break or continue statement, and update the static
/// element of its label (if any). The [parentNode] is the AST node of the
/// break or continue statement. The [labelNode] is the label contained in
@@ -3243,6 +3159,39 @@
return definingScope.node;
}
}
+
+ void _withDeclaredLocals(
+ AstNode node,
+ List<Statement> statements,
+ void Function() f,
+ ) {
+ var outerScope = nameScope;
+ try {
+ var enclosedScope = LocalScope(nameScope);
+ BlockScope.elementsInStatements(statements).forEach(enclosedScope.add);
+
+ nameScope = enclosedScope;
+ _setNodeNameScope(node, nameScope);
+
+ f();
+ } finally {
+ nameScope = outerScope;
+ }
+ }
+
+ /// Return the [Scope] to use while resolving inside the [node].
+ ///
+ /// Not every node has the scope set, for example we set the scopes for
+ /// blocks, but statements don't have separate scopes. The compilation unit
+ /// has the library scope.
+ static Scope? getNodeNameScope(AstNode node) {
+ return node.getProperty(_nameScopeProperty);
+ }
+
+ /// Set the [Scope] to use while resolving inside the [node].
+ static void _setNodeNameScope(AstNode node, Scope scope) {
+ node.setProperty(_nameScopeProperty, scope);
+ }
}
/// Tracker for whether a `switch` statement has `default` or is on an
diff --git a/pkg/analyzer/lib/src/lint/linter.dart b/pkg/analyzer/lib/src/lint/linter.dart
index 2eaeac7..8670eee 100644
--- a/pkg/analyzer/lib/src/lint/linter.dart
+++ b/pkg/analyzer/lib/src/lint/linter.dart
@@ -33,7 +33,7 @@
AnalysisErrorInfoImpl,
AnalysisOptions,
AnalysisOptionsImpl;
-import 'package:analyzer/src/generated/resolver.dart' show ScopedVisitor;
+import 'package:analyzer/src/generated/resolver.dart' show ScopeResolverVisitor;
import 'package:analyzer/src/generated/source.dart' show LineInfo;
import 'package:analyzer/src/generated/source_io.dart';
import 'package:analyzer/src/lint/analysis.dart';
@@ -399,7 +399,7 @@
String id, bool setter, AstNode node) {
Scope? scope;
for (AstNode? context = node; context != null; context = context.parent) {
- scope = ScopedVisitor.getNodeNameScope(context);
+ scope = ScopeResolverVisitor.getNodeNameScope(context);
if (scope != null) {
break;
}
diff --git a/tools/VERSION b/tools/VERSION
index f6002f4..0aeed3a 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 15
PATCH 0
-PRERELEASE 16
+PRERELEASE 17
PRERELEASE_PATCH 0
\ No newline at end of file