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 library services.src.refactoring; | 5 library services.src.refactoring; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:collection'; | 8 import 'dart:collection'; |
9 | 9 |
10 import 'package:analysis_server/src/protocol_server.dart' hide Element; | 10 import 'package:analysis_server/src/protocol_server.dart' hide Element; |
11 import 'package:analysis_server/src/services/correction/status.dart'; | 11 import 'package:analysis_server/src/services/correction/status.dart'; |
12 import 'package:analysis_server/src/services/refactoring/refactoring.dart'; | 12 import 'package:analysis_server/src/services/refactoring/refactoring.dart'; |
13 import 'package:analysis_server/src/services/search/search_engine.dart'; | 13 import 'package:analysis_server/src/services/search/search_engine.dart'; |
14 import 'package:analyzer/dart/element/element.dart'; | 14 import 'package:analyzer/dart/element/element.dart'; |
| 15 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext; |
15 import 'package:analyzer/src/generated/source.dart'; | 16 import 'package:analyzer/src/generated/source.dart'; |
16 | 17 |
17 /** | 18 /** |
| 19 * Return a new [SourceReference] instance for the given [match]. |
| 20 */ |
| 21 SourceReference getSourceReference(SearchMatch match) { |
| 22 return new SourceReference(match); |
| 23 } |
| 24 |
| 25 /** |
18 * When a [Source] (a file) is used in more than one context, [SearchEngine] | 26 * When a [Source] (a file) is used in more than one context, [SearchEngine] |
19 * will return separate [SearchMatch]s for each context. But in rename | 27 * will return separate [SearchMatch]s for each context. But in rename |
20 * refactorings we want to update each [Source] only once. | 28 * refactorings we want to update each [Source] only once. |
21 */ | 29 */ |
22 List<SourceReference> getSourceReferences(List<SearchMatch> matches) { | 30 List<SourceReference> getSourceReferences(List<SearchMatch> matches) { |
23 var uniqueReferences = new HashMap<SourceReference, SourceReference>(); | 31 var uniqueReferences = new HashMap<SourceReference, SourceReference>(); |
24 for (SearchMatch match in matches) { | 32 for (SearchMatch match in matches) { |
25 Element element = match.element; | 33 SourceReference newReference = getSourceReference(match); |
26 String file = element.source.fullName; | |
27 SourceRange range = match.sourceRange; | |
28 SourceReference newReference = new SourceReference( | |
29 file, range, element, match.isResolved, match.isQualified); | |
30 SourceReference oldReference = uniqueReferences[newReference]; | 34 SourceReference oldReference = uniqueReferences[newReference]; |
31 if (oldReference == null) { | 35 if (oldReference == null) { |
32 uniqueReferences[newReference] = newReference; | 36 uniqueReferences[newReference] = newReference; |
33 oldReference = newReference; | 37 oldReference = newReference; |
34 } | 38 } |
35 } | 39 } |
36 return uniqueReferences.keys.toList(); | 40 return uniqueReferences.keys.toList(); |
37 } | 41 } |
38 | 42 |
39 /** | 43 /** |
40 * Abstract implementation of [Refactoring]. | 44 * Abstract implementation of [Refactoring]. |
41 */ | 45 */ |
42 abstract class RefactoringImpl implements Refactoring { | 46 abstract class RefactoringImpl implements Refactoring { |
43 final List<String> potentialEditIds = <String>[]; | 47 final List<String> potentialEditIds = <String>[]; |
44 | 48 |
45 @override | 49 @override |
46 Future<RefactoringStatus> checkAllConditions() async { | 50 Future<RefactoringStatus> checkAllConditions() async { |
47 RefactoringStatus result = new RefactoringStatus(); | 51 RefactoringStatus result = new RefactoringStatus(); |
48 result.addStatus(await checkInitialConditions()); | 52 result.addStatus(await checkInitialConditions()); |
49 if (result.hasFatalError) { | 53 if (result.hasFatalError) { |
50 return result; | 54 return result; |
51 } | 55 } |
52 result.addStatus(await checkFinalConditions()); | 56 result.addStatus(await checkFinalConditions()); |
53 return result; | 57 return result; |
54 } | 58 } |
55 } | 59 } |
56 | 60 |
57 /** | 61 /** |
58 * The [SourceRange] in some [Source]. | 62 * The [SourceRange] in some [Source]. |
| 63 * |
| 64 * TODO(scheglov) inline this class as SearchMatch |
59 */ | 65 */ |
60 class SourceReference { | 66 class SourceReference { |
61 final String file; | 67 final SearchMatch _match; |
62 final SourceRange range; | |
63 final Element element; | |
64 final bool isResolved; | |
65 final bool isQualified; | |
66 | 68 |
67 SourceReference( | 69 SourceReference(this._match); |
68 this.file, this.range, this.element, this.isResolved, this.isQualified); | 70 |
| 71 AnalysisContext get context => _match.context; |
| 72 |
| 73 Element get element => _match.element; |
| 74 |
| 75 /** |
| 76 * The full path of the file containing the match. |
| 77 */ |
| 78 String get file => _match.file; |
69 | 79 |
70 @override | 80 @override |
71 int get hashCode { | 81 int get hashCode { |
72 int hash = file.hashCode; | 82 int hash = file.hashCode; |
73 hash = ((hash << 16) & 0xFFFFFFFF) + range.hashCode; | 83 hash = ((hash << 16) & 0xFFFFFFFF) + range.hashCode; |
74 return hash; | 84 return hash; |
75 } | 85 } |
76 | 86 |
| 87 bool get isResolved => _match.isResolved; |
| 88 |
| 89 SourceRange get range => _match.sourceRange; |
| 90 |
| 91 Source get unitSource => _match.unitSource; |
| 92 |
77 @override | 93 @override |
78 bool operator ==(Object other) { | 94 bool operator ==(Object other) { |
79 if (identical(other, this)) { | 95 if (identical(other, this)) { |
80 return true; | 96 return true; |
81 } | 97 } |
82 if (other is SourceReference) { | 98 if (other is SourceReference) { |
83 return other.file == file && other.range == range; | 99 return other.file == file && other.range == range; |
84 } | 100 } |
85 return false; | 101 return false; |
86 } | 102 } |
87 | 103 |
88 /** | 104 /** |
89 * Adds the [SourceEdit] to replace this reference. | 105 * Adds the [SourceEdit] to replace this reference. |
90 */ | 106 */ |
91 void addEdit(SourceChange change, String newText, {String id}) { | 107 void addEdit(SourceChange change, String newText, {String id}) { |
92 SourceEdit edit = createEdit(newText, id: id); | 108 SourceEdit edit = createEdit(newText, id: id); |
93 doSourceChange_addElementEdit(change, element, edit); | 109 doSourceChange_addSourceEdit(change, context, unitSource, edit); |
94 } | 110 } |
95 | 111 |
96 /** | 112 /** |
97 * Returns the [SourceEdit] to replace this reference. | 113 * Returns the [SourceEdit] to replace this reference. |
98 */ | 114 */ |
99 SourceEdit createEdit(String newText, {String id}) { | 115 SourceEdit createEdit(String newText, {String id}) { |
100 return newSourceEdit_range(range, newText, id: id); | 116 return newSourceEdit_range(range, newText, id: id); |
101 } | 117 } |
102 | 118 |
103 @override | 119 @override |
104 String toString() => '$file@$range'; | 120 String toString() => '$file@$range'; |
105 } | 121 } |
OLD | NEW |