Skip to content

Commit c3e15ce

Browse files
pqCommit Queue
authored and
Commit Queue
committed
[wildcards] fix scoping for local functions
See: #55680 Change-Id: I74e41257e1537ce371d10d4bb7aa24afbb911b6f Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/376024 Reviewed-by: Brian Wilkerson <[email protected]> Commit-Queue: Phil Quitslund <[email protected]>
1 parent af270e4 commit c3e15ce

File tree

6 files changed

+177
-11
lines changed

6 files changed

+177
-11
lines changed

pkg/analyzer/lib/src/dart/element/extensions.dart

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -119,15 +119,16 @@ extension ElementExtension on Element {
119119
}
120120

121121
/// Return true if this element is a wildcard variable.
122-
bool get isWildcardVariable =>
123-
name == '_' &&
124-
(this is LocalVariableElement ||
125-
this is PrefixElement ||
126-
this is TypeParameterElement ||
127-
(this is ParameterElement &&
128-
this is! FieldFormalParameterElement &&
129-
this is! SuperFormalParameterElement)) &&
130-
(library?.featureSet.isEnabled(Feature.wildcard_variables) ?? false);
122+
bool get isWildcardVariable {
123+
return name == '_' &&
124+
(this is LocalVariableElement ||
125+
this is PrefixElement ||
126+
this is TypeParameterElement ||
127+
(this is ParameterElement &&
128+
this is! FieldFormalParameterElement &&
129+
this is! SuperFormalParameterElement)) &&
130+
library.hasWildcardVariablesFeatureEnabled;
131+
}
131132
}
132133

133134
extension ExecutableElementExtension on ExecutableElement {
@@ -154,6 +155,13 @@ extension InterfaceTypeExtension on InterfaceType {
154155
}
155156
}
156157

158+
extension LibraryExtension on LibraryElement? {
159+
bool get hasWildcardVariablesFeatureEnabled {
160+
var self = this;
161+
return self?.featureSet.isEnabled(Feature.wildcard_variables) ?? false;
162+
}
163+
}
164+
157165
extension ParameterElementExtensions on ParameterElement {
158166
/// Return [ParameterElement] with the specified properties replaced.
159167
ParameterElement copyWith({

pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import 'package:analyzer/error/listener.dart';
1616
import 'package:analyzer/src/dart/ast/ast.dart';
1717
import 'package:analyzer/src/dart/ast/extensions.dart';
1818
import 'package:analyzer/src/dart/element/element.dart';
19+
import 'package:analyzer/src/dart/element/extensions.dart';
1920
import 'package:analyzer/src/dart/element/scope.dart';
2021
import 'package:analyzer/src/dart/element/type.dart';
2122
import 'package:analyzer/src/dart/element/type_constraint_gatherer.dart';
@@ -1494,7 +1495,10 @@ class ResolutionVisitor extends RecursiveAstVisitor<void> {
14941495
var nameToken = node.name;
14951496
var element = FunctionElementImpl(nameToken.lexeme, nameToken.offset);
14961497
node.declaredElement = element;
1497-
_define(element);
1498+
if (nameToken.lexeme != '_' ||
1499+
!_libraryElement.hasWildcardVariablesFeatureEnabled) {
1500+
_define(element);
1501+
}
14981502
_elementHolder.enclose(element);
14991503
}
15001504

pkg/analyzer/lib/src/generated/resolver.dart

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5307,7 +5307,11 @@ class ScopeResolverVisitor extends UnifyingAstVisitor<void> {
53075307
var outerScope = nameScope;
53085308
try {
53095309
var enclosedScope = LocalScope(nameScope);
5310-
BlockScope.elementsInStatements(statements).forEach(enclosedScope.add);
5310+
for (var statement in BlockScope.elementsInStatements(statements)) {
5311+
if (!statement.isWildcardFunction) {
5312+
enclosedScope.add(statement);
5313+
}
5314+
}
53115315

53125316
nameScope = enclosedScope;
53135317
node.nameScope = nameScope;
@@ -5607,3 +5611,10 @@ class _WhyNotPromotedVisitor
56075611
url: NonPromotionDocumentationLink.fieldPromotionUnavailable.url);
56085612
}
56095613
}
5614+
5615+
extension on Element {
5616+
bool get isWildcardFunction =>
5617+
this is FunctionElement &&
5618+
name == '_' &&
5619+
library.hasWildcardVariablesFeatureEnabled;
5620+
}

pkg/analyzer/test/src/dart/resolution/function_declaration_test.dart

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,63 @@ FunctionDeclaration
279279
staticType: Iterable<int> Function()
280280
declaredElement: self::@function::f
281281
type: Iterable<int> Function()
282+
''');
283+
}
284+
285+
test_wildCardFunction() async {
286+
await assertErrorsInCode('''
287+
_() {}
288+
''', [
289+
error(WarningCode.UNUSED_ELEMENT, 0, 1),
290+
]);
291+
292+
var node = findNode.singleFunctionDeclaration;
293+
assertResolvedNodeText(node, r'''
294+
FunctionDeclaration
295+
name: _
296+
functionExpression: FunctionExpression
297+
parameters: FormalParameterList
298+
leftParenthesis: (
299+
rightParenthesis: )
300+
body: BlockFunctionBody
301+
block: Block
302+
leftBracket: {
303+
rightBracket: }
304+
declaredElement: self::@function::_
305+
type: dynamic Function()
306+
staticType: dynamic Function()
307+
declaredElement: self::@function::_
308+
type: dynamic Function()
309+
''');
310+
}
311+
312+
test_wildCardFunction_preWildCards() async {
313+
await assertErrorsInCode('''
314+
// @dart = 3.4
315+
// (pre wildcard-variables)
316+
317+
_() {}
318+
''', [
319+
error(WarningCode.UNUSED_ELEMENT, 44, 1),
320+
]);
321+
322+
var node = findNode.singleFunctionDeclaration;
323+
assertResolvedNodeText(node, r'''
324+
FunctionDeclaration
325+
name: _
326+
functionExpression: FunctionExpression
327+
parameters: FormalParameterList
328+
leftParenthesis: (
329+
rightParenthesis: )
330+
body: BlockFunctionBody
331+
block: Block
332+
leftBracket: {
333+
rightBracket: }
334+
declaredElement: self::@function::_
335+
type: dynamic Function()
336+
staticType: dynamic Function()
337+
declaredElement: self::@function::_
338+
type: dynamic Function()
282339
''');
283340
}
284341
}

pkg/analyzer/test/src/dart/resolution/local_variable_test.dart

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,38 @@ void f() {
134134
expect(x.isStatic, isFalse);
135135
}
136136

137+
test_localVariable_wildcardFunction() async {
138+
await assertErrorsInCode('''
139+
f() {
140+
_() {}
141+
_();
142+
}
143+
''', [
144+
error(WarningCode.DEAD_CODE, 8, 6),
145+
error(CompileTimeErrorCode.UNDEFINED_FUNCTION, 17, 1),
146+
]);
147+
}
148+
149+
test_localVariable_wildcardFunction_preWildcards() async {
150+
await assertNoErrorsInCode('''
151+
// @dart = 3.4
152+
// (pre wildcard-variables)
153+
154+
f() {
155+
_() {}
156+
_();
157+
}
158+
''');
159+
160+
var node = findNode.simple('_();');
161+
assertResolvedNodeText(node, r'''
162+
SimpleIdentifier
163+
token: _
164+
staticElement: _@52
165+
staticType: Null Function()
166+
''');
167+
}
168+
137169
test_localVariable_wildcardVariable_field() async {
138170
await assertNoErrorsInCode('''
139171
class C {

pkg/analyzer/test/src/dart/resolution/method_declaration_test.dart

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
import 'package:analyzer/src/error/codes.dart';
56
import 'package:test_reflective_loader/test_reflective_loader.dart';
67

78
import 'context_collection_resolution.dart';
@@ -68,6 +69,59 @@ SimpleIdentifier
6869
token: _
6970
staticElement: self::@class::A::@getter::_
7071
staticType: int
72+
''');
73+
}
74+
75+
test_wildCardMethod() async {
76+
await assertErrorsInCode('''
77+
class C {
78+
_() {}
79+
}
80+
''', [
81+
error(WarningCode.UNUSED_ELEMENT, 12, 1),
82+
]);
83+
84+
var node = findNode.methodDeclaration('_');
85+
assertResolvedNodeText(node, r'''
86+
MethodDeclaration
87+
name: _
88+
parameters: FormalParameterList
89+
leftParenthesis: (
90+
rightParenthesis: )
91+
body: BlockFunctionBody
92+
block: Block
93+
leftBracket: {
94+
rightBracket: }
95+
declaredElement: self::@class::C::@method::_
96+
type: dynamic Function()
97+
''');
98+
}
99+
100+
test_wildCardMethod_preWildCards() async {
101+
await assertErrorsInCode('''
102+
// @dart = 3.4
103+
// (pre wildcard-variables)
104+
105+
class C {
106+
_() {}
107+
}
108+
''', [
109+
error(WarningCode.UNUSED_ELEMENT, 56, 1),
110+
]);
111+
112+
var node = findNode.methodDeclaration('_');
113+
assertResolvedNodeText(node, r'''
114+
MethodDeclaration
115+
name: _
116+
parameters: FormalParameterList
117+
leftParenthesis: (
118+
rightParenthesis: )
119+
body: BlockFunctionBody
120+
block: Block
121+
leftBracket: {
122+
rightBracket: }
123+
declaredElement: self::@class::C::@method::_
124+
type: dynamic Function()
71125
''');
72126
}
73127
}

0 commit comments

Comments
 (0)