analyzer: Use docImport scope in field and top-level variable declarations
Fixes https://github.com/dart-lang/sdk/issues/56100
Also privatize and inline some code.
Cq-Include-Trybots: luci.dart.try:flutter-analyze-try,analyzer-win-release-try,pkg-win-release-try
Change-Id: Ie9fea09cd719a62d2ef58373deaeb1fd43fa9cef
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/373601
Commit-Queue: Sam Rawlins <srawlins@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index f386972..a58b64c 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -4483,28 +4483,20 @@
element.typeParameters,
);
node.nameScope = nameScope;
- visitClassDeclarationInScope(node);
+ node.typeParameters?.accept(this);
+ node.extendsClause?.accept(this);
+ node.withClause?.accept(this);
+ node.implementsClause?.accept(this);
+ node.nativeClause?.accept(this);
nameScope = InstanceScope(nameScope, element);
- visitClassMembersInScope(node);
+ _visitDocumentationComment(node.documentationComment);
+ node.members.accept(this);
} finally {
nameScope = outerScope;
}
}
- void visitClassDeclarationInScope(ClassDeclaration node) {
- node.typeParameters?.accept(this);
- node.extendsClause?.accept(this);
- node.withClause?.accept(this);
- node.implementsClause?.accept(this);
- node.nativeClause?.accept(this);
- }
-
- void visitClassMembersInScope(ClassDeclarationImpl node) {
- visitDocumentationComment(node.documentationComment);
- node.members.accept(this);
- }
-
@override
void visitClassTypeAlias(covariant ClassTypeAliasImpl node) {
node.metadata.accept(this);
@@ -4525,7 +4517,7 @@
// Note: we don't visit metadata because it's not inside the class type
// alias's type parameter scope. It was already visited in
// [visitClassTypeAlias].
- visitDocumentationComment(node.documentationComment);
+ _visitDocumentationComment(node.documentationComment);
node.typeParameters?.accept(this);
node.superclass.accept(this);
node.withClause.accept(this);
@@ -4555,7 +4547,7 @@
element,
);
node.initializers.accept(this);
- visitDocumentationComment(node.documentationComment);
+ _visitDocumentationComment(node.documentationComment);
} finally {
nameScope = outerScope;
}
@@ -4583,25 +4575,6 @@
super.visitDeclaredIdentifier(node);
}
- /// Visits a documentation comment with a [DocImportScope] that encloses the
- /// current [nameScope].
- void visitDocumentationComment(CommentImpl? node) {
- if (node == null) return;
-
- Scope outerScope = nameScope;
- Scope docImportInnerScope = _docImportScope.innerScope;
- try {
- _docImportScope.innerScope = nameScope;
- nameScope = _docImportScope;
-
- node.nameScope = nameScope;
- node.accept(this);
- } finally {
- nameScope = outerScope;
- _docImportScope.innerScope = docImportInnerScope;
- }
- }
-
@override
void visitDoStatement(DoStatement node) {
ImplicitLabelScope outerImplicitScope = _implicitLabelScope;
@@ -4630,27 +4603,19 @@
element.typeParameters,
);
node.nameScope = nameScope;
- visitEnumDeclarationInScope(node);
+ node.typeParameters?.accept(this);
+ node.withClause?.accept(this);
+ node.implementsClause?.accept(this);
nameScope = InstanceScope(nameScope, element);
- visitEnumMembersInScope(node);
+ _visitDocumentationComment(node.documentationComment);
+ node.constants.accept(this);
+ node.members.accept(this);
} finally {
nameScope = outerScope;
}
}
- void visitEnumDeclarationInScope(EnumDeclaration node) {
- node.typeParameters?.accept(this);
- node.withClause?.accept(this);
- node.implementsClause?.accept(this);
- }
-
- void visitEnumMembersInScope(covariant EnumDeclarationImpl node) {
- visitDocumentationComment(node.documentationComment);
- node.constants.accept(this);
- node.members.accept(this);
- }
-
@override
void visitExpressionFunctionBody(covariant ExpressionFunctionBodyImpl node) {
node.nameScope = nameScope;
@@ -4684,7 +4649,7 @@
}
void visitExtensionMembersInScope(ExtensionDeclarationImpl node) {
- visitDocumentationComment(node.documentationComment);
+ _visitDocumentationComment(node.documentationComment);
node.members.accept(this);
}
@@ -4707,7 +4672,7 @@
node.implementsClause?.accept(this);
nameScope = InstanceScope(nameScope, element);
- visitDocumentationComment(node.documentationComment);
+ _visitDocumentationComment(node.documentationComment);
node.members.accept(this);
} finally {
nameScope = outerScope;
@@ -4715,6 +4680,13 @@
}
@override
+ void visitFieldDeclaration(covariant FieldDeclarationImpl node) {
+ node.metadata.accept(this);
+ _visitDocumentationComment(node.documentationComment);
+ node.fields.accept(this);
+ }
+
+ @override
void visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node) {
//
// We visit the iterator before the loop variable because the loop variable
@@ -4859,7 +4831,7 @@
if (parent is FunctionDeclarationImpl) {
// We have already created a function scope and don't need to do so again.
super.visitFunctionExpression(node);
- visitDocumentationComment(parent.documentationComment);
+ _visitDocumentationComment(parent.documentationComment);
return;
}
@@ -4897,7 +4869,7 @@
node.parameters.accept(this);
// Visiting the parameters added them to the scope as a side effect. So it
// is safe to visit the documentation comment now.
- visitDocumentationComment(node.documentationComment);
+ _visitDocumentationComment(node.documentationComment);
}
@override
@@ -4922,7 +4894,7 @@
// Note: we don't visit metadata because it's not inside the function typed
// formal parameter's type parameter scope. It was already visited in
// [visitFunctionTypedFormalParameter].
- visitDocumentationComment(node.documentationComment);
+ _visitDocumentationComment(node.documentationComment);
node.returnType?.accept(this);
node.typeParameters?.accept(this);
node.parameters.accept(this);
@@ -4965,7 +4937,7 @@
TypeParameterScope(nameScope, aliasedElement.typeParameters),
aliasedElement.parameters);
}
- visitDocumentationComment(node.documentationComment);
+ _visitDocumentationComment(node.documentationComment);
} finally {
nameScope = outerScope;
}
@@ -5022,7 +4994,7 @@
@override
void visitLibraryDirective(covariant LibraryDirectiveImpl node) {
node.metadata.accept(this);
- visitDocumentationComment(node.documentationComment);
+ _visitDocumentationComment(node.documentationComment);
}
@override
@@ -5031,30 +5003,24 @@
node.metadata.accept(this);
Scope outerScope = nameScope;
try {
- ExecutableElement element = node.declaredElement!;
+ var element = node.declaredElement!;
nameScope = TypeParameterScope(
nameScope,
element.typeParameters,
);
node.nameScope = nameScope;
- visitMethodDeclarationInScope(node);
+ node.returnType?.accept(this);
+ node.typeParameters?.accept(this);
+ node.parameters?.accept(this);
+ // Visiting the parameters added them to the scope as a side effect. So it
+ // is safe to visit the documentation comment now.
+ _visitDocumentationComment(node.documentationComment);
+ node.body.accept(this);
} finally {
nameScope = outerScope;
}
}
- void visitMethodDeclarationInScope(MethodDeclarationImpl node) {
- // Note: we don't visit metadata because it's not inside the method's type
- // parameter scope. It was already visited in [visitMethodDeclaration].
- node.returnType?.accept(this);
- node.typeParameters?.accept(this);
- node.parameters?.accept(this);
- // Visiting the parameters added them to the scope as a side effect. So it
- // is safe to visit the documentation comment now.
- visitDocumentationComment(node.documentationComment);
- node.body.accept(this);
- }
-
@override
void visitMethodInvocation(MethodInvocation node) {
// Only visit the method name if there's no real target (so this is an
@@ -5094,7 +5060,7 @@
}
void visitMixinMembersInScope(MixinDeclarationImpl node) {
- visitDocumentationComment(node.documentationComment);
+ _visitDocumentationComment(node.documentationComment);
node.members.accept(this);
}
@@ -5262,6 +5228,14 @@
}
@override
+ void visitTopLevelVariableDeclaration(
+ covariant TopLevelVariableDeclarationImpl node) {
+ node.metadata.accept(this);
+ _visitDocumentationComment(node.documentationComment);
+ node.variables.accept(this);
+ }
+
+ @override
void visitVariableDeclaration(VariableDeclaration node) {
super.visitVariableDeclaration(node);
@@ -5360,6 +5334,25 @@
}
}
+ /// Visits a documentation comment with a [DocImportScope] that encloses the
+ /// current [nameScope].
+ void _visitDocumentationComment(CommentImpl? node) {
+ if (node == null) return;
+
+ Scope outerScope = nameScope;
+ Scope docImportInnerScope = _docImportScope.innerScope;
+ try {
+ _docImportScope.innerScope = nameScope;
+ nameScope = _docImportScope;
+
+ node.nameScope = nameScope;
+ node.accept(this);
+ } finally {
+ nameScope = outerScope;
+ _docImportScope.innerScope = docImportInnerScope;
+ }
+ }
+
void _visitIf(IfElementOrStatementImpl node) {
node.expression.accept(this);
diff --git a/pkg/analyzer/test/src/dart/resolution/comment_test.dart b/pkg/analyzer/test/src/dart/resolution/comment_test.dart
index 56e56d5..7ad7bb3 100644
--- a/pkg/analyzer/test/src/dart/resolution/comment_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/comment_test.dart
@@ -1719,6 +1719,28 @@
''');
}
+ test_docImport_onField() async {
+ newFile('$testPackageLibPath/foo.dart', r'''
+class A {}
+''');
+ await assertNoErrorsInCode(r'''
+/// @docImport 'foo.dart';
+library;
+class C {
+ /// Text [A].
+ int x = 1;
+}
+''');
+
+ assertResolvedNodeText(findNode.commentReference('A]'), r'''
+CommentReference
+ expression: SimpleIdentifier
+ token: A
+ staticElement: package:test/foo.dart::@class::A
+ staticType: null
+''');
+ }
+
test_docImport_onLibrary() async {
newFile('$testPackageLibPath/foo.dart', r'''
class A {}
@@ -1739,6 +1761,26 @@
''');
}
+ test_docImport_onTopLevelVariable() async {
+ newFile('$testPackageLibPath/foo.dart', r'''
+class A {}
+''');
+ await assertNoErrorsInCode(r'''
+/// @docImport 'foo.dart';
+library;
+/// Text [A].
+int x = 1;
+''');
+
+ assertResolvedNodeText(findNode.commentReference('A]'), r'''
+CommentReference
+ expression: SimpleIdentifier
+ token: A
+ staticElement: package:test/foo.dart::@class::A
+ staticType: null
+''');
+ }
+
test_docImport_topLevelFunction() async {
newFile('$testPackageLibPath/foo.dart', r'''
void foo() {}