mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 01:59:38 +00:00
Pass target elements being renamed into validator.
R=brianwilkerson@google.com BUG= Review-Url: https://codereview.chromium.org/2963173002 .
This commit is contained in:
parent
501688de4c
commit
f6b7fd307a
|
@ -17,25 +17,6 @@ import 'package:analyzer/src/generated/source.dart';
|
|||
import 'package:analyzer_plugin/utilities/range_factory.dart';
|
||||
import 'package:path/path.dart' as pathos;
|
||||
|
||||
/**
|
||||
* Returns `true` if two given [Element]s are [LocalElement]s and have
|
||||
* intersecting with visibility ranges.
|
||||
*/
|
||||
bool haveIntersectingRanges(LocalElement localElement, Element element) {
|
||||
if (element is! LocalElement) {
|
||||
return false;
|
||||
}
|
||||
LocalElement localElement2 = element as LocalElement;
|
||||
Source localSource = localElement.source;
|
||||
Source localSource2 = localElement2.source;
|
||||
SourceRange localRange = localElement.visibleRange;
|
||||
SourceRange localRange2 = localElement2.visibleRange;
|
||||
return localSource2 == localSource &&
|
||||
localRange != null &&
|
||||
localRange2 != null &&
|
||||
localRange2.intersects(localRange);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if [element] is defined in the library containing [source].
|
||||
*/
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:analysis_server/src/protocol_server.dart' hide Element;
|
||||
import 'package:analysis_server/src/protocol_server.dart'
|
||||
hide Element, ElementKind;
|
||||
import 'package:analysis_server/src/services/correction/status.dart';
|
||||
import 'package:analysis_server/src/services/correction/util.dart';
|
||||
import 'package:analysis_server/src/services/refactoring/naming_conventions.dart';
|
||||
|
@ -54,8 +55,7 @@ class RenameLocalRefactoringImpl extends RenameRefactoringImpl {
|
|||
for (LocalElement element in elements) {
|
||||
CompilationUnit unit = await unitCache.getUnit(element);
|
||||
if (unit != null) {
|
||||
SourceRange elementRange = element.visibleRange;
|
||||
unit.accept(new _ConflictValidatorVisitor(this, result, elementRange));
|
||||
unit.accept(new _ConflictValidatorVisitor(result, newName, element));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -111,21 +111,19 @@ class RenameLocalRefactoringImpl extends RenameRefactoringImpl {
|
|||
}
|
||||
|
||||
class _ConflictValidatorVisitor extends RecursiveAstVisitor {
|
||||
final RenameLocalRefactoringImpl refactoring;
|
||||
final RefactoringStatus result;
|
||||
final SourceRange elementRange;
|
||||
final String newName;
|
||||
final LocalElement target;
|
||||
final Set<Element> conflictingLocals = new Set<Element>();
|
||||
|
||||
_ConflictValidatorVisitor(this.refactoring, this.result, this.elementRange);
|
||||
_ConflictValidatorVisitor(this.result, this.newName, this.target);
|
||||
|
||||
@override
|
||||
visitSimpleIdentifier(SimpleIdentifier node) {
|
||||
Element nodeElement = node.bestElement;
|
||||
String newName = refactoring.newName;
|
||||
if (nodeElement != null && nodeElement.name == newName) {
|
||||
// duplicate declaration
|
||||
if (node.inDeclarationContext() &&
|
||||
haveIntersectingRanges(refactoring.element, nodeElement)) {
|
||||
// Duplicate declaration.
|
||||
if (node.inDeclarationContext() && _isVisibleWithTarget(nodeElement)) {
|
||||
conflictingLocals.add(nodeElement);
|
||||
String nodeKind = nodeElement.kind.displayName;
|
||||
String message = "Duplicate $nodeKind '$newName'.";
|
||||
|
@ -135,16 +133,17 @@ class _ConflictValidatorVisitor extends RecursiveAstVisitor {
|
|||
if (conflictingLocals.contains(nodeElement)) {
|
||||
return;
|
||||
}
|
||||
// shadowing referenced element
|
||||
if (elementRange != null &&
|
||||
elementRange.contains(node.offset) &&
|
||||
// Shadowing by the target element.
|
||||
SourceRange targetRange = target.visibleRange;
|
||||
if (targetRange != null &&
|
||||
targetRange.contains(node.offset) &&
|
||||
!node.isQualified &&
|
||||
!_isNamedExpressionName(node)) {
|
||||
nodeElement = getSyntheticAccessorVariable(nodeElement);
|
||||
String nodeKind = nodeElement.kind.displayName;
|
||||
String nodeName = getElementQualifiedName(nodeElement);
|
||||
String nameElementSourceName = nodeElement.source.shortName;
|
||||
String refKind = refactoring.element.kind.displayName;
|
||||
String refKind = target.kind.displayName;
|
||||
String message = 'Usage of $nodeKind "$nodeName" declared in '
|
||||
'"$nameElementSourceName" will be shadowed by renamed $refKind.';
|
||||
result.addError(message, newLocation_fromNode(node));
|
||||
|
@ -152,6 +151,20 @@ class _ConflictValidatorVisitor extends RecursiveAstVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether [element] and [target] are visible together.
|
||||
*/
|
||||
bool _isVisibleWithTarget(Element element) {
|
||||
if (element is LocalElement) {
|
||||
SourceRange targetRange = target.visibleRange;
|
||||
SourceRange elementRange = element.visibleRange;
|
||||
return targetRange != null &&
|
||||
elementRange != null &&
|
||||
elementRange.intersects(targetRange);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool _isNamedExpressionName(SimpleIdentifier node) {
|
||||
return node.parent is Label && node.parent.parent is NamedExpression;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue