[private named parameters] Handle rename refactoring.
Remove the special case handling that would add a public parameter and a separate initializer in the initializer list since you can now use the private name as a parameter directly. Handle updating references at constructor callsites where we need to rename the argument to the corresponding public name. Bug: https://github.com/dart-lang/sdk/issues/61644 Change-Id: I76160f2a702073f57a45b9ea0425e4a7567ba466 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/466960 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Reviewed-by: Konstantin Shcheglov <scheglov@google.com> Commit-Queue: Bob Nystrom <rnystrom@google.com> Auto-Submit: Bob Nystrom <rnystrom@google.com>
This commit is contained in:
committed by
Commit Queue
parent
8ed0065bf6
commit
b6c19cbe13
@@ -88,6 +88,9 @@ class SourceReference {
|
||||
bool get isInvocationByEnumConstantWithoutArguments =>
|
||||
_match.kind == MatchKind.INVOCATION_BY_ENUM_CONSTANT_WITHOUT_ARGUMENTS;
|
||||
|
||||
bool get isNamedArgumentReference =>
|
||||
_match.kind == MatchKind.REFERENCE_BY_NAMED_ARGUMENT;
|
||||
|
||||
bool get isReferenceInPatternField =>
|
||||
_match.kind == MatchKind.REFERENCE_IN_PATTERN_FIELD;
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'package:_fe_analyzer_shared/src/scanner/token_impl.dart';
|
||||
import 'package:analysis_server/src/protocol_server.dart' hide Element;
|
||||
import 'package:analysis_server/src/services/correction/status.dart';
|
||||
import 'package:analysis_server/src/services/correction/util.dart';
|
||||
@@ -9,8 +10,10 @@ import 'package:analysis_server/src/services/refactoring/legacy/refactoring.dart
|
||||
import 'package:analysis_server/src/services/refactoring/legacy/refactoring_internal.dart';
|
||||
import 'package:analysis_server/src/services/search/search_engine.dart';
|
||||
import 'package:analyzer/dart/analysis/code_style_options.dart';
|
||||
import 'package:analyzer/dart/analysis/features.dart';
|
||||
import 'package:analyzer/dart/element/element.dart';
|
||||
import 'package:analyzer/file_system/file_system.dart';
|
||||
import 'package:analyzer/source/source_range.dart';
|
||||
import 'package:analyzer/src/dart/analysis/session_helper.dart';
|
||||
import 'package:analyzer/src/dart/element/element.dart';
|
||||
import 'package:analyzer/src/generated/java_core.dart';
|
||||
@@ -46,12 +49,46 @@ class RenameProcessor {
|
||||
doSourceChange_addFragmentEdit(change, element.firstFragment, edit);
|
||||
} else if (workspace.containsElement(element)) {
|
||||
Fragment? fragment = element.firstFragment;
|
||||
SourceRange? nameRange;
|
||||
var replacement = newName;
|
||||
var supportsPrivateNamedParameters =
|
||||
element.library?.featureSet.isEnabled(
|
||||
Feature.private_named_parameters,
|
||||
) ??
|
||||
false;
|
||||
while (fragment != null) {
|
||||
var nameRange = range.fragmentName(fragment);
|
||||
switch (fragment) {
|
||||
// ignore: experimental_member_use
|
||||
case FieldFormalParameterFragment(:var privateName?)
|
||||
when supportsPrivateNamedParameters:
|
||||
// A private named parameter's element has the public name ("foo"),
|
||||
// but the identifer we are renaming is the original private name
|
||||
// ("_foo"). In that case, use the private name so that we have the
|
||||
// correct length including the underscore.
|
||||
nameRange = range.startOffsetLength(
|
||||
fragment.nameOffset!,
|
||||
privateName.length,
|
||||
);
|
||||
|
||||
case SuperFormalParameterFragment()
|
||||
when supportsPrivateNamedParameters &&
|
||||
fragment.element.isNamed &&
|
||||
newName.startsWith('_'):
|
||||
// A super parameter works more like a named *argument* than a
|
||||
// named parameter. If the corresponding parameter in the
|
||||
// supertype is named and private, then refer to it by its public
|
||||
// name in the super parameter.
|
||||
nameRange = range.fragmentName(fragment);
|
||||
replacement = correspondingPublicName(newName) ?? newName;
|
||||
default:
|
||||
nameRange = range.fragmentName(fragment);
|
||||
}
|
||||
|
||||
if (nameRange != null) {
|
||||
var edit = newSourceEdit_range(nameRange, newName);
|
||||
var edit = newSourceEdit_range(nameRange, replacement);
|
||||
doSourceChange_addFragmentEdit(change, fragment, edit);
|
||||
}
|
||||
|
||||
fragment = fragment.nextFragment;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'package:_fe_analyzer_shared/src/scanner/token_impl.dart';
|
||||
import 'package:analysis_server/src/protocol_server.dart'
|
||||
hide Element, ElementKind;
|
||||
import 'package:analysis_server/src/services/correction/status.dart';
|
||||
@@ -14,6 +15,7 @@ import 'package:analysis_server/src/services/refactoring/legacy/visible_ranges_c
|
||||
import 'package:analysis_server/src/services/search/hierarchy.dart';
|
||||
import 'package:analysis_server/src/services/search/search_engine.dart';
|
||||
import 'package:analysis_server/src/utilities/strings.dart';
|
||||
import 'package:analyzer/dart/analysis/features.dart';
|
||||
import 'package:analyzer/dart/ast/ast.dart';
|
||||
import 'package:analyzer/dart/ast/visitor.dart';
|
||||
import 'package:analyzer/dart/element/element.dart';
|
||||
@@ -180,7 +182,8 @@ class RenameClassMemberRefactoringImpl extends RenameRefactoringImpl {
|
||||
|
||||
if (newName.startsWith('_') &&
|
||||
element is FieldFormalParameterElement &&
|
||||
element.isNamed) {
|
||||
element.isNamed &&
|
||||
!element.supportsPrivateNamedParameters) {
|
||||
await _addPrivateNamedFormalParameterEdit(reference, element);
|
||||
continue;
|
||||
}
|
||||
@@ -195,7 +198,17 @@ class RenameClassMemberRefactoringImpl extends RenameRefactoringImpl {
|
||||
continue;
|
||||
}
|
||||
|
||||
reference.addEdit(change, newName);
|
||||
if (reference.isNamedArgumentReference && newName.startsWith('_')) {
|
||||
// The named argument refers to a field whose new name is private.
|
||||
// At the callsite, the named argument should use its corresponding
|
||||
// public name if there is one. (If they are renaming the field to a
|
||||
// private name with no corresponding name, then use the private name
|
||||
// at the named argument site so they can see the resulting error and
|
||||
// fix it.)
|
||||
reference.addEdit(change, correspondingPublicName(newName) ?? newName);
|
||||
} else {
|
||||
reference.addEdit(change, newName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -528,8 +541,9 @@ class _RenameClassMemberValidator extends _BaseClassMemberValidator {
|
||||
.cast<FormalParameterElement>()
|
||||
.toList();
|
||||
|
||||
// The language doesn't allow private named formal parameters.
|
||||
if (name.startsWith('_')) {
|
||||
// Skip private named parameters if we are in a library that doesn't
|
||||
// support them.
|
||||
if (name.startsWith('_') && !element.supportsPrivateNamedParameters) {
|
||||
formalParameters.removeWhere((formalParameter) {
|
||||
return formalParameter.isNamed;
|
||||
});
|
||||
@@ -579,6 +593,11 @@ extension on Element {
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
bool get supportsPrivateNamedParameters {
|
||||
return library?.featureSet.isEnabled(Feature.private_named_parameters) ??
|
||||
true;
|
||||
}
|
||||
}
|
||||
|
||||
extension on List<Element> {
|
||||
|
||||
@@ -49,6 +49,9 @@ enum MatchKind {
|
||||
/// A tear-off reference to a constructor.
|
||||
REFERENCE_BY_CONSTRUCTOR_TEAR_OFF(isReference: true),
|
||||
|
||||
/// A named argument that refers to a formal parameter.
|
||||
REFERENCE_BY_NAMED_ARGUMENT(isReference: true),
|
||||
|
||||
/// A reference to an element in an extends clause.
|
||||
REFERENCE_IN_EXTENDS_CLAUSE(isReference: true),
|
||||
|
||||
|
||||
@@ -344,46 +344,32 @@ class SearchMatchImpl implements SearchMatch {
|
||||
}
|
||||
|
||||
static MatchKind toMatchKind(SearchResultKind kind) {
|
||||
if (kind == SearchResultKind.READ) {
|
||||
return MatchKind.READ;
|
||||
}
|
||||
if (kind == SearchResultKind.READ_WRITE) {
|
||||
return MatchKind.READ_WRITE;
|
||||
}
|
||||
if (kind == SearchResultKind.WRITE) {
|
||||
return MatchKind.WRITE;
|
||||
}
|
||||
if (kind == SearchResultKind.INVOCATION) {
|
||||
return MatchKind.INVOCATION;
|
||||
}
|
||||
if (kind == SearchResultKind.DOT_SHORTHANDS_CONSTRUCTOR_TEAR_OFF) {
|
||||
return MatchKind.DOT_SHORTHANDS_CONSTRUCTOR_TEAR_OFF;
|
||||
}
|
||||
if (kind == SearchResultKind.DOT_SHORTHANDS_CONSTRUCTOR_INVOCATION) {
|
||||
return MatchKind.DOT_SHORTHANDS_CONSTRUCTOR_INVOCATION;
|
||||
}
|
||||
if (kind ==
|
||||
SearchResultKind.INVOCATION_BY_ENUM_CONSTANT_WITHOUT_ARGUMENTS) {
|
||||
return MatchKind.INVOCATION_BY_ENUM_CONSTANT_WITHOUT_ARGUMENTS;
|
||||
}
|
||||
if (kind == SearchResultKind.REFERENCE_BY_CONSTRUCTOR_TEAR_OFF) {
|
||||
return MatchKind.REFERENCE_BY_CONSTRUCTOR_TEAR_OFF;
|
||||
}
|
||||
if (kind == SearchResultKind.REFERENCE_IN_EXTENDS_CLAUSE) {
|
||||
return MatchKind.REFERENCE_IN_EXTENDS_CLAUSE;
|
||||
}
|
||||
if (kind == SearchResultKind.REFERENCE_IN_IMPLEMENTS_CLAUSE) {
|
||||
return MatchKind.REFERENCE_IN_IMPLEMENTS_CLAUSE;
|
||||
}
|
||||
if (kind == SearchResultKind.REFERENCE_IN_ON_CLAUSE) {
|
||||
return MatchKind.REFERENCE_IN_ON_CLAUSE;
|
||||
}
|
||||
if (kind == SearchResultKind.REFERENCE_IN_WITH_CLAUSE) {
|
||||
return MatchKind.REFERENCE_IN_WITH_CLAUSE;
|
||||
}
|
||||
if (kind == SearchResultKind.REFERENCE_IN_PATTERN_FIELD) {
|
||||
return MatchKind.REFERENCE_IN_PATTERN_FIELD;
|
||||
}
|
||||
return MatchKind.REFERENCE;
|
||||
return switch (kind) {
|
||||
SearchResultKind.READ => MatchKind.READ,
|
||||
SearchResultKind.READ_WRITE => MatchKind.READ_WRITE,
|
||||
SearchResultKind.WRITE => MatchKind.WRITE,
|
||||
SearchResultKind.INVOCATION => MatchKind.INVOCATION,
|
||||
SearchResultKind.DOT_SHORTHANDS_CONSTRUCTOR_TEAR_OFF =>
|
||||
MatchKind.DOT_SHORTHANDS_CONSTRUCTOR_TEAR_OFF,
|
||||
SearchResultKind.DOT_SHORTHANDS_CONSTRUCTOR_INVOCATION =>
|
||||
MatchKind.DOT_SHORTHANDS_CONSTRUCTOR_INVOCATION,
|
||||
SearchResultKind.REFERENCE_BY_NAMED_ARGUMENT =>
|
||||
MatchKind.REFERENCE_BY_NAMED_ARGUMENT,
|
||||
SearchResultKind.INVOCATION_BY_ENUM_CONSTANT_WITHOUT_ARGUMENTS =>
|
||||
MatchKind.INVOCATION_BY_ENUM_CONSTANT_WITHOUT_ARGUMENTS,
|
||||
SearchResultKind.REFERENCE_BY_CONSTRUCTOR_TEAR_OFF =>
|
||||
MatchKind.REFERENCE_BY_CONSTRUCTOR_TEAR_OFF,
|
||||
SearchResultKind.REFERENCE_IN_EXTENDS_CLAUSE =>
|
||||
MatchKind.REFERENCE_IN_EXTENDS_CLAUSE,
|
||||
SearchResultKind.REFERENCE_IN_IMPLEMENTS_CLAUSE =>
|
||||
MatchKind.REFERENCE_IN_IMPLEMENTS_CLAUSE,
|
||||
SearchResultKind.REFERENCE_IN_ON_CLAUSE =>
|
||||
MatchKind.REFERENCE_IN_ON_CLAUSE,
|
||||
SearchResultKind.REFERENCE_IN_WITH_CLAUSE =>
|
||||
MatchKind.REFERENCE_IN_WITH_CLAUSE,
|
||||
SearchResultKind.REFERENCE_IN_PATTERN_FIELD =>
|
||||
MatchKind.REFERENCE_IN_PATTERN_FIELD,
|
||||
_ => MatchKind.REFERENCE,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -276,6 +276,7 @@ class EnumTest {
|
||||
EnumTester<MatchKind, SearchResultKind>().run(
|
||||
newSearchResultKind_fromEngine,
|
||||
exceptions: {
|
||||
MatchKind.REFERENCE_BY_NAMED_ARGUMENT: SearchResultKind.REFERENCE,
|
||||
MatchKind.REFERENCE_IN_PATTERN_FIELD: SearchResultKind.REFERENCE,
|
||||
MatchKind.DOT_SHORTHANDS_CONSTRUCTOR_INVOCATION:
|
||||
SearchResultKind.INVOCATION,
|
||||
|
||||
+236
-5
@@ -13,6 +13,9 @@ import 'abstract_rename.dart';
|
||||
void main() {
|
||||
defineReflectiveSuite(() {
|
||||
defineReflectiveTests(RenameClassMemberClassTest);
|
||||
defineReflectiveTests(
|
||||
RenameClassMemberClassTest_WithoutPrivateNamedParameters,
|
||||
);
|
||||
defineReflectiveTests(RenameClassMemberEnumTest);
|
||||
defineReflectiveTests(RenameClassMemberExtensionTypeTest);
|
||||
});
|
||||
@@ -87,18 +90,18 @@ class B extends A {
|
||||
''');
|
||||
createRenameRefactoring();
|
||||
// check status
|
||||
refactoring.newName = '_foo';
|
||||
refactoring.newName = '_rename';
|
||||
var status = await refactoring.checkFinalConditions();
|
||||
assertRefactoringStatusOK(status);
|
||||
await assertSuccessfulRefactoring('''
|
||||
class A {
|
||||
final int _foo;
|
||||
final int _rename;
|
||||
|
||||
A({int foo = 0}) : _foo = foo;
|
||||
A({this._rename = 0});
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
B({super.foo});
|
||||
B({super.rename});
|
||||
}
|
||||
''');
|
||||
}
|
||||
@@ -148,6 +151,131 @@ class B extends A {
|
||||
''');
|
||||
}
|
||||
|
||||
Future<void> test_atConstructor_privateNamed() async {
|
||||
await indexTestUnit('''
|
||||
class C {
|
||||
int? _foo;
|
||||
C({this._foo}) : assert(_foo != null);
|
||||
}
|
||||
|
||||
void main() {
|
||||
var c = C(foo: 1);
|
||||
print(c._foo);
|
||||
}
|
||||
''');
|
||||
// configure refactoring
|
||||
createRenameRefactoringAtString('_foo})');
|
||||
expect(refactoring.refactoringName, 'Rename Field');
|
||||
expect(refactoring.elementKindName, 'field');
|
||||
refactoring.newName = '_renamed';
|
||||
// validate change
|
||||
return assertSuccessfulRefactoring('''
|
||||
class C {
|
||||
int? _renamed;
|
||||
C({this._renamed}) : assert(_renamed != null);
|
||||
}
|
||||
|
||||
void main() {
|
||||
var c = C(renamed: 1);
|
||||
print(c._renamed);
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
Future<void> test_atConstructor_privateNamed_fromPublicNamed() async {
|
||||
await indexTestUnit('''
|
||||
class C {
|
||||
int? foo;
|
||||
C({this.foo}) : assert(foo != null);
|
||||
}
|
||||
|
||||
void main() {
|
||||
var c = C(foo: 1);
|
||||
print(c.foo);
|
||||
}
|
||||
''');
|
||||
// configure refactoring
|
||||
createRenameRefactoringAtString('foo})');
|
||||
expect(refactoring.refactoringName, 'Rename Field');
|
||||
expect(refactoring.elementKindName, 'field');
|
||||
refactoring.newName = '_renamed';
|
||||
// validate change
|
||||
return assertSuccessfulRefactoring('''
|
||||
class C {
|
||||
int? _renamed;
|
||||
C({this._renamed}) : assert(_renamed != null);
|
||||
}
|
||||
|
||||
void main() {
|
||||
var c = C(renamed: 1);
|
||||
print(c._renamed);
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
Future<void>
|
||||
test_atConstructor_privateNamed_noCorrespondingPublicName() async {
|
||||
await indexTestUnit('''
|
||||
class C {
|
||||
int? _foo;
|
||||
C({this._foo}) : assert(_foo != null);
|
||||
}
|
||||
|
||||
void main() {
|
||||
var c = C(foo: 1);
|
||||
print(c._foo);
|
||||
}
|
||||
''');
|
||||
// configure refactoring
|
||||
createRenameRefactoringAtString('_foo})');
|
||||
expect(refactoring.refactoringName, 'Rename Field');
|
||||
expect(refactoring.elementKindName, 'field');
|
||||
refactoring.newName = '_if';
|
||||
// validate change
|
||||
return assertSuccessfulRefactoring('''
|
||||
class C {
|
||||
int? _if;
|
||||
C({this._if}) : assert(_if != null);
|
||||
}
|
||||
|
||||
void main() {
|
||||
var c = C(_if: 1);
|
||||
print(c._if);
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
Future<void> test_atConstructor_privateNamed_toPublicNamed() async {
|
||||
await indexTestUnit('''
|
||||
class C {
|
||||
int? _foo;
|
||||
C({this._foo}) : assert(_foo != null);
|
||||
}
|
||||
|
||||
void main() {
|
||||
var c = C(foo: 1);
|
||||
print(c._foo);
|
||||
}
|
||||
''');
|
||||
// configure refactoring
|
||||
createRenameRefactoringAtString('_foo})');
|
||||
expect(refactoring.refactoringName, 'Rename Field');
|
||||
expect(refactoring.elementKindName, 'field');
|
||||
refactoring.newName = 'renamed';
|
||||
// validate change
|
||||
return assertSuccessfulRefactoring('''
|
||||
class C {
|
||||
int? renamed;
|
||||
C({this.renamed}) : assert(renamed != null);
|
||||
}
|
||||
|
||||
void main() {
|
||||
var c = C(renamed: 1);
|
||||
print(c.renamed);
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
Future<void> test_checkFinalConditions_classNameConflict_sameClass() async {
|
||||
await indexTestUnit('''
|
||||
class NewName {
|
||||
@@ -1851,6 +1979,109 @@ class A {
|
||||
}
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class RenameClassMemberClassTest_WithoutPrivateNamedParameters
|
||||
extends RenameRefactoringTest {
|
||||
Future<void> test_atConstructor_named_subclasses_toPrivate() async {
|
||||
await indexTestUnit('''
|
||||
// @dart=3.9
|
||||
class A {
|
||||
final int foo;
|
||||
|
||||
A({this.f^oo = 0});
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
B({super.foo});
|
||||
}
|
||||
''');
|
||||
createRenameRefactoring();
|
||||
// check status
|
||||
refactoring.newName = '_rename';
|
||||
var status = await refactoring.checkFinalConditions();
|
||||
assertRefactoringStatusOK(status);
|
||||
await assertSuccessfulRefactoring('''
|
||||
// @dart=3.9
|
||||
class A {
|
||||
final int _rename;
|
||||
|
||||
A({int foo = 0}) : _rename = foo;
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
B({super.foo});
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
Future<void> test_atConstructor_toPrivateNamed() async {
|
||||
await indexTestUnit('''
|
||||
// @dart=3.9
|
||||
class C {
|
||||
int? foo;
|
||||
C({this.foo}) : assert(foo != null);
|
||||
}
|
||||
|
||||
void main() {
|
||||
var c = C(foo: 1);
|
||||
print(c.foo);
|
||||
}
|
||||
''');
|
||||
// configure refactoring
|
||||
createRenameRefactoringAtString('foo})');
|
||||
expect(refactoring.refactoringName, 'Rename Field');
|
||||
expect(refactoring.elementKindName, 'field');
|
||||
refactoring.newName = '_renamed';
|
||||
// validate change
|
||||
return assertSuccessfulRefactoring('''
|
||||
// @dart=3.9
|
||||
class C {
|
||||
int? _renamed;
|
||||
C({int? foo}) : _renamed = foo, assert(foo != null);
|
||||
}
|
||||
|
||||
void main() {
|
||||
var c = C(foo: 1);
|
||||
print(c._renamed);
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
Future<void> test_createChange_FieldElement_private_initializer() async {
|
||||
await indexTestUnit('''
|
||||
// @dart=3.9
|
||||
class C {
|
||||
int? field;
|
||||
int? other;
|
||||
C({this.field}) : other = field;
|
||||
}
|
||||
void f() {
|
||||
var c = C(field: 0);
|
||||
c.field = 1;
|
||||
}
|
||||
''');
|
||||
// configure refactoring
|
||||
var element = findElement2.field('field');
|
||||
createRenameRefactoringForElement2(element);
|
||||
expect(refactoring.refactoringName, 'Rename Field');
|
||||
expect(refactoring.oldName, 'field');
|
||||
refactoring.newName = '_field';
|
||||
// validate change
|
||||
return assertSuccessfulRefactoring('''
|
||||
// @dart=3.9
|
||||
class C {
|
||||
int? _field;
|
||||
int? other;
|
||||
C({int? field}) : _field = field, other = field;
|
||||
}
|
||||
void f() {
|
||||
var c = C(field: 0);
|
||||
c._field = 1;
|
||||
}
|
||||
''');
|
||||
}
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class RenameClassMemberEnumTest extends RenameRefactoringTest {
|
||||
Future<void> test_checkFinalConditions_classNameConflict_sameClass() async {
|
||||
@@ -2321,7 +2552,7 @@ void f() {
|
||||
class C {
|
||||
int? _field;
|
||||
int? other;
|
||||
C({int? field}) : _field = field, other = field;
|
||||
C({this._field}) : other = _field;
|
||||
}
|
||||
void f() {
|
||||
var c = C(field: 0);
|
||||
|
||||
@@ -544,7 +544,7 @@ class B extends A {
|
||||
matches,
|
||||
unorderedEquals([
|
||||
predicate((SearchMatch m) {
|
||||
return m.kind == MatchKind.REFERENCE &&
|
||||
return m.kind == MatchKind.REFERENCE_BY_NAMED_ARGUMENT &&
|
||||
identical(
|
||||
m.element,
|
||||
findElement2.unnamedConstructor('B').superFormalParameter('a'),
|
||||
@@ -612,7 +612,7 @@ void g() {
|
||||
matches,
|
||||
unorderedEquals([
|
||||
predicate((SearchMatch m) {
|
||||
return m.kind == MatchKind.REFERENCE &&
|
||||
return m.kind == MatchKind.REFERENCE_BY_NAMED_ARGUMENT &&
|
||||
identical(m.element, findElement2.topFunction('g')) &&
|
||||
m.sourceRange.offset == code.position.offset &&
|
||||
m.sourceRange.length == 'test'.length;
|
||||
|
||||
@@ -1183,13 +1183,16 @@ class _IndexContributor extends GeneralizingAstVisitor {
|
||||
if (element is FormalParameterElement && node.parent is! Label) {
|
||||
return;
|
||||
}
|
||||
|
||||
IndexRelationKind kind = IndexRelationKind.IS_REFERENCED_BY;
|
||||
if (element is FormalParameterElement && element.isNamed) {
|
||||
// Use a different kind for named arguments so that we can handle
|
||||
// refactoring private named parameters.
|
||||
kind = IndexRelationKind.IS_REFERENCED_BY_NAMED_ARGUMENT;
|
||||
}
|
||||
|
||||
// record specific relations
|
||||
recordRelation(
|
||||
element,
|
||||
IndexRelationKind.IS_REFERENCED_BY,
|
||||
node,
|
||||
isQualified,
|
||||
);
|
||||
recordRelation(element, kind, node, isQualified);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -1226,7 +1229,9 @@ class _IndexContributor extends GeneralizingAstVisitor {
|
||||
if (superParameter != null) {
|
||||
recordRelation(
|
||||
superParameter,
|
||||
IndexRelationKind.IS_REFERENCED_BY,
|
||||
node.isNamed
|
||||
? IndexRelationKind.IS_REFERENCED_BY_NAMED_ARGUMENT
|
||||
: IndexRelationKind.IS_REFERENCED_BY,
|
||||
node.name,
|
||||
true,
|
||||
);
|
||||
|
||||
@@ -726,6 +726,8 @@ class Search {
|
||||
) async {
|
||||
List<SearchResult> results = <SearchResult>[];
|
||||
await _addResults(results, element, searchedFiles, const {
|
||||
IndexRelationKind.IS_REFERENCED_BY_NAMED_ARGUMENT:
|
||||
SearchResultKind.REFERENCE_BY_NAMED_ARGUMENT,
|
||||
IndexRelationKind.IS_REFERENCED_BY: SearchResultKind.REFERENCE,
|
||||
});
|
||||
return results;
|
||||
@@ -1134,6 +1136,7 @@ enum SearchResultKind {
|
||||
DOT_SHORTHANDS_CONSTRUCTOR_INVOCATION,
|
||||
DOT_SHORTHANDS_CONSTRUCTOR_TEAR_OFF,
|
||||
REFERENCE,
|
||||
REFERENCE_BY_NAMED_ARGUMENT,
|
||||
REFERENCE_IN_PATTERN_FIELD,
|
||||
REFERENCE_BY_CONSTRUCTOR_TEAR_OFF,
|
||||
REFERENCE_IN_EXTENDS_CLAUSE,
|
||||
|
||||
@@ -73,6 +73,11 @@ enum IndexRelationKind : byte {
|
||||
/// Right: location.
|
||||
IS_REFERENCED_BY_DOT_SHORTHAND_CONSTRUCTOR_TEAR_OFF,
|
||||
|
||||
/// Left: a parameter.
|
||||
/// Is referenced by a named argument.
|
||||
/// Right: named argument.
|
||||
IS_REFERENCED_BY_NAMED_ARGUMENT,
|
||||
|
||||
/// Left: unresolved member name.
|
||||
/// Is read at.
|
||||
/// Right: location.
|
||||
|
||||
@@ -383,6 +383,11 @@ enum IndexRelationKind {
|
||||
/// Right: location.
|
||||
IS_REFERENCED_BY_DOT_SHORTHAND_CONSTRUCTOR_TEAR_OFF,
|
||||
|
||||
/// Left: a parameter.
|
||||
/// Is referenced by a named argument.
|
||||
/// Right: named argument.
|
||||
IS_REFERENCED_BY_NAMED_ARGUMENT,
|
||||
|
||||
/// Left: unresolved member name.
|
||||
/// Is read at.
|
||||
/// Right: location.
|
||||
|
||||
@@ -1776,22 +1776,6 @@ void f() {
|
||||
''');
|
||||
}
|
||||
|
||||
test_isReferencedBy_FieldElement_dotSorthandConstructorInvocation() async {
|
||||
await _indexTestUnit('''
|
||||
class A {
|
||||
A({this.field});
|
||||
var field;
|
||||
}
|
||||
void foo() {
|
||||
A _ = .new(field: 42);
|
||||
}
|
||||
''');
|
||||
var element = findElement2.fieldFormalParameter('field');
|
||||
assertElementIndexText(element, r'''
|
||||
70 6:14 |field| IS_REFERENCED_BY qualified
|
||||
''');
|
||||
}
|
||||
|
||||
test_isReferencedBy_FieldElement_enum() async {
|
||||
await _indexTestUnit('''
|
||||
enum E {
|
||||
@@ -2125,7 +2109,7 @@ void f() {
|
||||
''');
|
||||
var element = findElement2.parameter('p');
|
||||
assertElementIndexText(element, r'''
|
||||
33 3:7 |p| IS_REFERENCED_BY qualified
|
||||
33 3:7 |p| IS_REFERENCED_BY_NAMED_ARGUMENT qualified
|
||||
''');
|
||||
}
|
||||
|
||||
@@ -2140,7 +2124,23 @@ void foo() {
|
||||
''');
|
||||
var element = findElement2.parameter('p');
|
||||
assertElementIndexText(element, r'''
|
||||
48 5:14 |p| IS_REFERENCED_BY qualified
|
||||
48 5:14 |p| IS_REFERENCED_BY_NAMED_ARGUMENT qualified
|
||||
''');
|
||||
}
|
||||
|
||||
test_isReferencedBy_ParameterElement_dotSorthandConstructorInvocation_field() async {
|
||||
await _indexTestUnit('''
|
||||
class A {
|
||||
A({this.field});
|
||||
var field;
|
||||
}
|
||||
void foo() {
|
||||
A _ = .new(field: 42);
|
||||
}
|
||||
''');
|
||||
var element = findElement2.fieldFormalParameter('field');
|
||||
assertElementIndexText(element, r'''
|
||||
70 6:14 |field| IS_REFERENCED_BY_NAMED_ARGUMENT qualified
|
||||
''');
|
||||
}
|
||||
|
||||
@@ -2196,7 +2196,7 @@ class B extends A {
|
||||
''');
|
||||
var element = findElement2.unnamedConstructor('A').parameter('a');
|
||||
assertElementIndexText(element, r'''
|
||||
75 5:21 |a| IS_REFERENCED_BY qualified
|
||||
75 5:21 |a| IS_REFERENCED_BY_NAMED_ARGUMENT qualified
|
||||
''');
|
||||
}
|
||||
|
||||
@@ -2227,7 +2227,7 @@ void f() {
|
||||
''');
|
||||
var element = findElement2.parameter('test');
|
||||
assertElementIndexText(element, r'''
|
||||
47 6:5 |test| IS_REFERENCED_BY qualified
|
||||
47 6:5 |test| IS_REFERENCED_BY_NAMED_ARGUMENT qualified
|
||||
''');
|
||||
}
|
||||
|
||||
@@ -2243,7 +2243,7 @@ void f(A<int> a) {
|
||||
''');
|
||||
var element = findElement2.parameter('test');
|
||||
assertElementIndexText(element, r'''
|
||||
68 6:9 |test| IS_REFERENCED_BY qualified
|
||||
68 6:9 |test| IS_REFERENCED_BY_NAMED_ARGUMENT qualified
|
||||
''');
|
||||
}
|
||||
|
||||
@@ -2257,7 +2257,7 @@ void() {
|
||||
''');
|
||||
var element = findElement2.parameter('test');
|
||||
assertElementIndexText(element, r'''
|
||||
41 4:7 |test| IS_REFERENCED_BY qualified
|
||||
41 4:7 |test| IS_REFERENCED_BY_NAMED_ARGUMENT qualified
|
||||
''');
|
||||
}
|
||||
|
||||
@@ -2271,7 +2271,7 @@ void() {
|
||||
''');
|
||||
var element = findElement2.parameter('test');
|
||||
assertElementIndexText(element, r'''
|
||||
58 4:10 |test| IS_REFERENCED_BY qualified
|
||||
58 4:10 |test| IS_REFERENCED_BY_NAMED_ARGUMENT qualified
|
||||
''');
|
||||
}
|
||||
|
||||
@@ -2300,7 +2300,7 @@ void() {
|
||||
''');
|
||||
var element = findElement2.parameter('test');
|
||||
assertElementIndexText(element, r'''
|
||||
49 4:7 |test| IS_REFERENCED_BY qualified
|
||||
49 4:7 |test| IS_REFERENCED_BY_NAMED_ARGUMENT qualified
|
||||
''');
|
||||
}
|
||||
|
||||
|
||||
@@ -1457,7 +1457,7 @@ class A {
|
||||
var field = findElement2.fieldFormalParameter('x');
|
||||
await assertElementReferencesText(field, r'''
|
||||
package:test/other.dart x@52
|
||||
52 4:12 |x| REFERENCE qualified
|
||||
52 4:12 |x| REFERENCE_BY_NAMED_ARGUMENT qualified
|
||||
''');
|
||||
}
|
||||
|
||||
@@ -2227,8 +2227,8 @@ class B extends A<String> {}
|
||||
var element = findElement2.parameter('p');
|
||||
await assertElementReferencesText(element, r'''
|
||||
<testLibraryFragment> f@5
|
||||
19 2:9 |p| REFERENCE qualified
|
||||
42 3:9 |p| REFERENCE qualified
|
||||
19 2:9 |p| REFERENCE_BY_NAMED_ARGUMENT qualified
|
||||
42 3:9 |p| REFERENCE_BY_NAMED_ARGUMENT qualified
|
||||
''');
|
||||
}
|
||||
|
||||
@@ -2298,7 +2298,7 @@ class B extends A {
|
||||
var element = findElement2.unnamedConstructor('A').parameter('a');
|
||||
await assertElementReferencesText(element, r'''
|
||||
<testLibraryFragment> a@75
|
||||
75 5:21 |a| REFERENCE qualified
|
||||
75 5:21 |a| REFERENCE_BY_NAMED_ARGUMENT qualified
|
||||
''');
|
||||
}
|
||||
|
||||
@@ -2338,7 +2338,7 @@ main() {
|
||||
32 4:3 |p| READ
|
||||
37 5:3 |p| READ
|
||||
<testLibraryFragment> main@44
|
||||
59 8:7 |p| REFERENCE qualified
|
||||
59 8:7 |p| REFERENCE_BY_NAMED_ARGUMENT qualified
|
||||
''');
|
||||
}
|
||||
|
||||
@@ -2356,7 +2356,7 @@ main() {
|
||||
<testLibraryFragment> foo@0
|
||||
27 2:3 |p| READ
|
||||
<testLibraryFragment> main@32
|
||||
50 5:10 |p| REFERENCE qualified
|
||||
50 5:10 |p| REFERENCE_BY_NAMED_ARGUMENT qualified
|
||||
''');
|
||||
}
|
||||
|
||||
@@ -2404,7 +2404,7 @@ main() {
|
||||
45 4:3 |p| READ
|
||||
50 5:3 |p| READ
|
||||
<testLibraryFragment> main@57
|
||||
72 8:7 |p| REFERENCE qualified
|
||||
72 8:7 |p| REFERENCE_BY_NAMED_ARGUMENT qualified
|
||||
''');
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user