Use offset/length of the import prefix, or empty. Same for constructor names.

R=brianwilkerson@google.com

Bug: https://github.com/dart-lang/sdk/issues/32685
Change-Id: I40b7f9c679b04725db19dad661e3a88a4a982f1c
Reviewed-on: https://dart-review.googlesource.com/48682
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Konstantin Shcheglov 2018-03-28 18:19:09 +00:00 committed by commit-bot@chromium.org
parent 85b4c604c5
commit 44dbba2b80
6 changed files with 142 additions and 38 deletions

View file

@ -4797,7 +4797,7 @@ a:focus, a:hover {
<p>
The offset to the beginning of the name selected to be
renamed.
renamed, or -1 if the name does not exist yet.
</p>
</dd><dt class="field"><b>length: int</b></dt><dd>

View file

@ -14330,12 +14330,14 @@ class RenameFeedback extends RefactoringFeedback {
String _oldName;
/**
* The offset to the beginning of the name selected to be renamed.
* The offset to the beginning of the name selected to be renamed, or -1 if
* the name does not exist yet.
*/
int get offset => _offset;
/**
* The offset to the beginning of the name selected to be renamed.
* The offset to the beginning of the name selected to be renamed, or -1 if
* the name does not exist yet.
*/
void set offset(int value) {
assert(value != null);

View file

@ -939,20 +939,44 @@ class _RefactoringManager {
AstNode node = await server.getNodeAtOffset(file, offset);
Element element = server.getElementOfNode(node);
if (node != null && element != null) {
int feedbackOffset = node.offset;
int feedbackLength = node.length;
if (element is FieldFormalParameterElement) {
element = (element as FieldFormalParameterElement).field;
}
// climb from "Class" in "new Class.named()" to "Class.named"
if (node.parent is TypeName && node.parent.parent is ConstructorName) {
ConstructorName constructor = node.parent.parent;
node = constructor;
element = constructor.staticElement;
// Use the prefix offset/length when renaming an import directive.
if (node is ImportDirective && element is ImportElement) {
if (node.prefix != null) {
feedbackOffset = node.prefix.offset;
feedbackLength = node.prefix.length;
} else {
feedbackOffset = -1;
feedbackLength = 0;
}
}
// Canonicalize to ConstructorName.
var constructorName = _canonicalizeToConstructorName(node);
if (constructorName != null) {
node = constructorName;
element = constructorName.staticElement;
// Use the constructor name offset/length.
if (constructorName.name != null) {
feedbackOffset = constructorName.name.offset;
feedbackLength = constructorName.name.length;
} else {
feedbackOffset = -1;
feedbackLength = 0;
}
}
// do create the refactoring
refactoring = new RenameRefactoring(
searchEngine, server.getAstProvider(file), element);
feedback =
new RenameFeedback(node.offset, node.length, 'kind', 'oldName');
feedback = new RenameFeedback(
feedbackOffset, feedbackLength, 'kind', 'oldName');
}
}
if (refactoring == null) {
@ -1087,6 +1111,32 @@ class _RefactoringManager {
}
return new RefactoringStatus();
}
/**
* If the [node] is a constructor reference, return the corresponding
* [ConstructorName], or `null` otherwise.
*/
static ConstructorName _canonicalizeToConstructorName(AstNode node) {
var parent = node.parent;
var parent2 = parent?.parent;
// "named" in "Class.named".
if (parent is ConstructorName) {
return parent;
}
// "Class" in "Class.named".
if (parent is TypeName && parent2 is ConstructorName) {
return parent2;
}
// Canonicalize "new Class.named()" to "Class.named".
if (node is InstanceCreationExpression) {
return node.constructorName;
}
return null;
}
}
/**

View file

@ -1562,16 +1562,24 @@ class B {
B() {}
}
''');
return assertSuccessfulRefactoring(() {
return sendRenameRequest('B;', 'newName');
}, '''
return assertSuccessfulRefactoring(
() {
return sendRenameRequest('B;', 'newName');
},
'''
class A {
A() = B.newName;
}
class B {
B.newName() {}
}
''');
''',
feedbackValidator: (feedback) {
RenameFeedback renameFeedback = feedback;
expect(renameFeedback.offset, -1);
expect(renameFeedback.length, 0);
},
);
}
test_constructor_fromInstanceCreation() {
@ -1583,16 +1591,24 @@ main() {
new A.test();
}
''');
return assertSuccessfulRefactoring(() {
return sendRenameRequest('test();', 'newName');
}, '''
return assertSuccessfulRefactoring(
() {
return sendRenameRequest('test();', 'newName');
},
'''
class A {
A.newName() {}
}
main() {
new A.newName();
}
''');
''',
feedbackValidator: (feedback) {
RenameFeedback renameFeedback = feedback;
expect(renameFeedback.offset, 43);
expect(renameFeedback.length, 4);
},
);
}
test_constructor_fromInstanceCreation_default_onClassName() {
@ -1604,16 +1620,24 @@ main() {
new A();
}
''');
return assertSuccessfulRefactoring(() {
return sendRenameRequest('A();', 'newName');
}, '''
return assertSuccessfulRefactoring(
() {
return sendRenameRequest('A();', 'newName');
},
'''
class A {
A.newName() {}
}
main() {
new A.newName();
}
''');
''',
feedbackValidator: (feedback) {
RenameFeedback renameFeedback = feedback;
expect(renameFeedback.offset, -1);
expect(renameFeedback.length, 0);
},
);
}
test_constructor_fromInstanceCreation_default_onNew() {
@ -1625,16 +1649,24 @@ main() {
new A();
}
''');
return assertSuccessfulRefactoring(() {
return sendRenameRequest('new A();', 'newName');
}, '''
return assertSuccessfulRefactoring(
() {
return sendRenameRequest('new A();', 'newName');
},
'''
class A {
A.newName() {}
}
main() {
new A.newName();
}
''');
''',
feedbackValidator: (feedback) {
RenameFeedback renameFeedback = feedback;
expect(renameFeedback.offset, -1);
expect(renameFeedback.length, 0);
},
);
}
test_feedback() {
@ -1682,16 +1714,23 @@ main() {
Future f;
}
''');
return assertSuccessfulRefactoring(() {
return sendRenameRequest("import 'dart:async';", 'new_name');
}, '''
return assertSuccessfulRefactoring(
() {
return sendRenameRequest("import 'dart:async';", 'new_name');
},
'''
import 'dart:math';
import 'dart:async' as new_name;
main() {
Random r;
new_name.Future f;
}
''');
''',
feedbackValidator: (feedback) {
RenameFeedback renameFeedback = feedback;
expect(renameFeedback.offset, -1);
expect(renameFeedback.length, 0);
});
}
test_importPrefix_remove() {
@ -1703,16 +1742,23 @@ main() {
test.Future f;
}
''');
return assertSuccessfulRefactoring(() {
return sendRenameRequest("import 'dart:async' as test;", '');
}, '''
return assertSuccessfulRefactoring(
() {
return sendRenameRequest("import 'dart:async' as test;", '');
},
'''
import 'dart:math' as test;
import 'dart:async';
main() {
test.Random r;
Future f;
}
''');
''',
feedbackValidator: (feedback) {
RenameFeedback renameFeedback = feedback;
expect(renameFeedback.offset, 51);
expect(renameFeedback.length, 4);
});
}
test_init_fatalError_noElement() {
@ -1970,9 +2016,13 @@ class _AbstractGetRefactoring_Test extends AbstractAnalysisTest {
}
Future assertSuccessfulRefactoring(
Future<Response> requestSender(), String expectedCode) async {
Future<Response> requestSender(), String expectedCode,
{void Function(RefactoringFeedback) feedbackValidator}) async {
EditGetRefactoringResult result = await getRefactoringResult(requestSender);
assertResultProblemsOK(result);
if (feedbackValidator != null) {
feedbackValidator(result.feedback);
}
assertTestRefactoringResult(result, expectedCode);
}

View file

@ -34,7 +34,8 @@ public class RenameFeedback extends RefactoringFeedback {
public static final List<RenameFeedback> EMPTY_LIST = Lists.newArrayList();
/**
* The offset to the beginning of the name selected to be renamed.
* The offset to the beginning of the name selected to be renamed, or -1 if the name does not exist
* yet.
*/
private final int offset;
@ -113,7 +114,8 @@ public class RenameFeedback extends RefactoringFeedback {
}
/**
* The offset to the beginning of the name selected to be renamed.
* The offset to the beginning of the name selected to be renamed, or -1 if the name does not exist
* yet.
*/
public int getOffset() {
return offset;

View file

@ -4382,7 +4382,7 @@
<ref>int</ref>
<p>
The offset to the beginning of the name selected to be
renamed.
renamed, or -1 if the name does not exist yet.
</p>
</field>
<field name="length">