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