| Index: pkg/analysis_services/lib/src/refactoring/rename_local.dart
|
| diff --git a/pkg/analysis_services/lib/src/refactoring/rename_local.dart b/pkg/analysis_services/lib/src/refactoring/rename_local.dart
|
| index ebe6288eaaf38959910888f9c8ce082517945931..56194289a5d6367b0cad387d6163b7eb7ce7c33a 100644
|
| --- a/pkg/analysis_services/lib/src/refactoring/rename_local.dart
|
| +++ b/pkg/analysis_services/lib/src/refactoring/rename_local.dart
|
| @@ -7,12 +7,18 @@
|
|
|
| library services.src.refactoring.rename_local;
|
|
|
| +import 'dart:async';
|
| +
|
| import 'package:analysis_services/correction/change.dart';
|
| import 'package:analysis_services/correction/status.dart';
|
| import 'package:analysis_services/refactoring/refactoring.dart';
|
| +import 'package:analysis_services/search/hierarchy.dart';
|
| import 'package:analysis_services/search/search_engine.dart';
|
| +import 'package:analysis_services/src/correction/util.dart';
|
| import 'package:analysis_services/src/refactoring/rename.dart';
|
| +import 'package:analyzer/src/generated/ast.dart';
|
| import 'package:analyzer/src/generated/element.dart';
|
| +import 'package:analyzer/src/generated/source.dart';
|
|
|
|
|
| /**
|
| @@ -39,18 +45,84 @@ class RenameLocalRefactoringImpl extends RenameRefactoringImpl {
|
| }
|
|
|
| @override
|
| - RefactoringStatus checkFinalConditions() {
|
| - // TODO: implement checkFinalConditions
|
| + Future<RefactoringStatus> checkFinalConditions() {
|
| + RefactoringStatus result = new RefactoringStatus();
|
| + // checks the resolved CompilationUnit(s)
|
| + Source unitSource = element.source;
|
| + List<Source> librarySources = context.getLibrariesContaining(unitSource);
|
| + for (Source librarySource in librarySources) {
|
| + _analyzePossibleConflicts_inLibrary(result, unitSource, librarySource);
|
| + }
|
| + return new Future.value(result);
|
| }
|
|
|
| - // TODO: implement refactoringName
|
| @override
|
| - Change createChange() {
|
| - // TODO: implement createChange
|
| + Future<Change> createChange() {
|
| + Change change = new Change(refactoringName);
|
| + // update declaration
|
| + addDeclarationEdit(change, element);
|
| + // update references
|
| + return searchEngine.searchReferences(element).then((refMatches) {
|
| + List<SourceReference> references = getSourceReferences(refMatches);
|
| + for (SourceReference reference in references) {
|
| + addReferenceEdit(change, reference);
|
| + }
|
| + return change;
|
| + });
|
| }
|
|
|
| + void _analyzePossibleConflicts_inLibrary(RefactoringStatus result,
|
| + Source unitSource, Source librarySource) {
|
| + // prepare resolved unit
|
| + CompilationUnit unit = null;
|
| + try {
|
| + unit = context.resolveCompilationUnit2(unitSource, librarySource);
|
| + } catch (e) {
|
| + }
|
| + if (unit == null) {
|
| + return;
|
| + }
|
| + // check for conflicts in the unit
|
| + SourceRange elementRange = element.visibleRange;
|
| + unit.accept(new _ConflictValidatorVisitor(this, result, elementRange));
|
| + }
|
| +}
|
| +
|
| +
|
| +class _ConflictValidatorVisitor extends RecursiveAstVisitor<Object> {
|
| + final RenameLocalRefactoringImpl refactoring;
|
| + final RefactoringStatus result;
|
| + final SourceRange elementRange;
|
| +
|
| + _ConflictValidatorVisitor(this.refactoring, this.result, this.elementRange);
|
| +
|
| @override
|
| - bool requiresPreview() {
|
| - // TODO: implement requiresPreview
|
| + Object visitSimpleIdentifier(SimpleIdentifier node) {
|
| + Element nodeElement = node.bestElement;
|
| + String newName = refactoring.newName;
|
| + if (nodeElement != null && nodeElement.name == newName) {
|
| + // duplicate declaration
|
| + if (haveIntersectingRanges(refactoring.element, nodeElement)) {
|
| + String nodeKind = nodeElement.kind.displayName;
|
| + String message = "Duplicate ${nodeKind} '$newName'.";
|
| + result.addError(
|
| + message,
|
| + new RefactoringStatusContext.forElement(nodeElement));
|
| + return null;
|
| + }
|
| + // shadowing referenced element
|
| + if (elementRange.contains(node.offset) && !node.isQualified) {
|
| + nodeElement = getSyntheticAccessorVariable(nodeElement);
|
| + String nodeKind = nodeElement.kind.displayName;
|
| + String nodeName = getElementQualifiedName(nodeElement);
|
| + String nameElementSourceName = nodeElement.source.shortName;
|
| + String refKind = refactoring.element.kind.displayName;
|
| + String message =
|
| + 'Usage of $nodeKind "$nodeName" declared in '
|
| + '"$nameElementSourceName" will be shadowed by renamed $refKind.';
|
| + result.addError(message, new RefactoringStatusContext.forNode(node));
|
| + }
|
| + }
|
| + return null;
|
| }
|
| }
|
|
|