| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 import 'dart:async'; | 5 import 'dart:async'; |
| 6 | 6 |
| 7 import 'package:analysis_server/src/protocol_server.dart' hide Element; | 7 import 'package:analysis_server/src/protocol_server.dart' |
| 8 hide Element, ElementKind; |
| 8 import 'package:analysis_server/src/services/correction/status.dart'; | 9 import 'package:analysis_server/src/services/correction/status.dart'; |
| 9 import 'package:analysis_server/src/services/correction/util.dart'; | 10 import 'package:analysis_server/src/services/correction/util.dart'; |
| 10 import 'package:analysis_server/src/services/refactoring/naming_conventions.dart
'; | 11 import 'package:analysis_server/src/services/refactoring/naming_conventions.dart
'; |
| 11 import 'package:analysis_server/src/services/refactoring/refactoring.dart'; | 12 import 'package:analysis_server/src/services/refactoring/refactoring.dart'; |
| 12 import 'package:analysis_server/src/services/refactoring/rename.dart'; | 13 import 'package:analysis_server/src/services/refactoring/rename.dart'; |
| 13 import 'package:analysis_server/src/services/search/hierarchy.dart'; | 14 import 'package:analysis_server/src/services/search/hierarchy.dart'; |
| 14 import 'package:analysis_server/src/services/search/search_engine.dart'; | 15 import 'package:analysis_server/src/services/search/search_engine.dart'; |
| 15 import 'package:analyzer/dart/ast/ast.dart'; | 16 import 'package:analyzer/dart/ast/ast.dart'; |
| 16 import 'package:analyzer/dart/ast/visitor.dart'; | 17 import 'package:analyzer/dart/ast/visitor.dart'; |
| 17 import 'package:analyzer/dart/element/element.dart'; | 18 import 'package:analyzer/dart/element/element.dart'; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 47 return "Rename Local Variable"; | 48 return "Rename Local Variable"; |
| 48 } | 49 } |
| 49 | 50 |
| 50 @override | 51 @override |
| 51 Future<RefactoringStatus> checkFinalConditions() async { | 52 Future<RefactoringStatus> checkFinalConditions() async { |
| 52 RefactoringStatus result = new RefactoringStatus(); | 53 RefactoringStatus result = new RefactoringStatus(); |
| 53 await _prepareElements(); | 54 await _prepareElements(); |
| 54 for (LocalElement element in elements) { | 55 for (LocalElement element in elements) { |
| 55 CompilationUnit unit = await unitCache.getUnit(element); | 56 CompilationUnit unit = await unitCache.getUnit(element); |
| 56 if (unit != null) { | 57 if (unit != null) { |
| 57 SourceRange elementRange = element.visibleRange; | 58 unit.accept(new _ConflictValidatorVisitor(result, newName, element)); |
| 58 unit.accept(new _ConflictValidatorVisitor(this, result, elementRange)); | |
| 59 } | 59 } |
| 60 } | 60 } |
| 61 return result; | 61 return result; |
| 62 } | 62 } |
| 63 | 63 |
| 64 @override | 64 @override |
| 65 RefactoringStatus checkNewName() { | 65 RefactoringStatus checkNewName() { |
| 66 RefactoringStatus result = super.checkNewName(); | 66 RefactoringStatus result = super.checkNewName(); |
| 67 if (element is LocalVariableElement) { | 67 if (element is LocalVariableElement) { |
| 68 result.addStatus(validateVariableName(newName)); | 68 result.addStatus(validateVariableName(newName)); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 } | 104 } |
| 105 } | 105 } |
| 106 } | 106 } |
| 107 } else { | 107 } else { |
| 108 elements = new Set.from([element]); | 108 elements = new Set.from([element]); |
| 109 } | 109 } |
| 110 } | 110 } |
| 111 } | 111 } |
| 112 | 112 |
| 113 class _ConflictValidatorVisitor extends RecursiveAstVisitor { | 113 class _ConflictValidatorVisitor extends RecursiveAstVisitor { |
| 114 final RenameLocalRefactoringImpl refactoring; | |
| 115 final RefactoringStatus result; | 114 final RefactoringStatus result; |
| 116 final SourceRange elementRange; | 115 final String newName; |
| 116 final LocalElement target; |
| 117 final Set<Element> conflictingLocals = new Set<Element>(); | 117 final Set<Element> conflictingLocals = new Set<Element>(); |
| 118 | 118 |
| 119 _ConflictValidatorVisitor(this.refactoring, this.result, this.elementRange); | 119 _ConflictValidatorVisitor(this.result, this.newName, this.target); |
| 120 | 120 |
| 121 @override | 121 @override |
| 122 visitSimpleIdentifier(SimpleIdentifier node) { | 122 visitSimpleIdentifier(SimpleIdentifier node) { |
| 123 Element nodeElement = node.bestElement; | 123 Element nodeElement = node.bestElement; |
| 124 String newName = refactoring.newName; | |
| 125 if (nodeElement != null && nodeElement.name == newName) { | 124 if (nodeElement != null && nodeElement.name == newName) { |
| 126 // duplicate declaration | 125 // Duplicate declaration. |
| 127 if (node.inDeclarationContext() && | 126 if (node.inDeclarationContext() && _isVisibleWithTarget(nodeElement)) { |
| 128 haveIntersectingRanges(refactoring.element, nodeElement)) { | |
| 129 conflictingLocals.add(nodeElement); | 127 conflictingLocals.add(nodeElement); |
| 130 String nodeKind = nodeElement.kind.displayName; | 128 String nodeKind = nodeElement.kind.displayName; |
| 131 String message = "Duplicate $nodeKind '$newName'."; | 129 String message = "Duplicate $nodeKind '$newName'."; |
| 132 result.addError(message, newLocation_fromElement(nodeElement)); | 130 result.addError(message, newLocation_fromElement(nodeElement)); |
| 133 return; | 131 return; |
| 134 } | 132 } |
| 135 if (conflictingLocals.contains(nodeElement)) { | 133 if (conflictingLocals.contains(nodeElement)) { |
| 136 return; | 134 return; |
| 137 } | 135 } |
| 138 // shadowing referenced element | 136 // Shadowing by the target element. |
| 139 if (elementRange != null && | 137 SourceRange targetRange = target.visibleRange; |
| 140 elementRange.contains(node.offset) && | 138 if (targetRange != null && |
| 139 targetRange.contains(node.offset) && |
| 141 !node.isQualified && | 140 !node.isQualified && |
| 142 !_isNamedExpressionName(node)) { | 141 !_isNamedExpressionName(node)) { |
| 143 nodeElement = getSyntheticAccessorVariable(nodeElement); | 142 nodeElement = getSyntheticAccessorVariable(nodeElement); |
| 144 String nodeKind = nodeElement.kind.displayName; | 143 String nodeKind = nodeElement.kind.displayName; |
| 145 String nodeName = getElementQualifiedName(nodeElement); | 144 String nodeName = getElementQualifiedName(nodeElement); |
| 146 String nameElementSourceName = nodeElement.source.shortName; | 145 String nameElementSourceName = nodeElement.source.shortName; |
| 147 String refKind = refactoring.element.kind.displayName; | 146 String refKind = target.kind.displayName; |
| 148 String message = 'Usage of $nodeKind "$nodeName" declared in ' | 147 String message = 'Usage of $nodeKind "$nodeName" declared in ' |
| 149 '"$nameElementSourceName" will be shadowed by renamed $refKind.'; | 148 '"$nameElementSourceName" will be shadowed by renamed $refKind.'; |
| 150 result.addError(message, newLocation_fromNode(node)); | 149 result.addError(message, newLocation_fromNode(node)); |
| 151 } | 150 } |
| 152 } | 151 } |
| 153 } | 152 } |
| 154 | 153 |
| 154 /** |
| 155 * Returns whether [element] and [target] are visible together. |
| 156 */ |
| 157 bool _isVisibleWithTarget(Element element) { |
| 158 if (element is LocalElement) { |
| 159 SourceRange targetRange = target.visibleRange; |
| 160 SourceRange elementRange = element.visibleRange; |
| 161 return targetRange != null && |
| 162 elementRange != null && |
| 163 elementRange.intersects(targetRange); |
| 164 } |
| 165 return false; |
| 166 } |
| 167 |
| 155 static bool _isNamedExpressionName(SimpleIdentifier node) { | 168 static bool _isNamedExpressionName(SimpleIdentifier node) { |
| 156 return node.parent is Label && node.parent.parent is NamedExpression; | 169 return node.parent is Label && node.parent.parent is NamedExpression; |
| 157 } | 170 } |
| 158 } | 171 } |
| OLD | NEW |