| Index: pkg/analysis_server/lib/src/services/refactoring/rename_local.dart
|
| diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_local.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_local.dart
|
| index ac9105150699600e0482b0f80b49f4da6c8c4d0b..85f86e4aa837d9f6bf0dc93f07ac659086f39baf 100644
|
| --- a/pkg/analysis_server/lib/src/services/refactoring/rename_local.dart
|
| +++ b/pkg/analysis_server/lib/src/services/refactoring/rename_local.dart
|
| @@ -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;
|
| }
|
|
|