Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(37)

Side by Side Diff: pkg/analysis_server/lib/src/services/refactoring/move_file.dart

Issue 2983783003: Remove the 'Move File' refactoring. (Closed)
Patch Set: Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 import 'dart:async';
6 import 'dart:core';
7
8 import 'package:analysis_server/src/protocol_server.dart' hide Element;
9 import 'package:analysis_server/src/services/correction/status.dart';
10 import 'package:analysis_server/src/services/refactoring/refactoring.dart';
11 import 'package:analysis_server/src/services/refactoring/refactoring_internal.da rt';
12 import 'package:analysis_server/src/services/search/search_engine.dart';
13 import 'package:analyzer/dart/element/element.dart';
14 import 'package:analyzer/file_system/file_system.dart';
15 import 'package:analyzer/src/generated/engine.dart';
16 import 'package:analyzer/src/generated/source.dart';
17 import 'package:path/path.dart' as pathos;
18 import 'package:source_span/src/span.dart';
19 import 'package:yaml/yaml.dart';
20
21 /**
22 * [ExtractLocalRefactoring] implementation.
23 */
24 class MoveFileRefactoringImpl extends RefactoringImpl
25 implements MoveFileRefactoring {
26 final ResourceProvider resourceProvider;
27 final pathos.Context pathContext;
28 final SearchEngine searchEngine;
29 final AnalysisContext context;
30 final Source source;
31
32 String oldFile;
33 String newFile;
34
35 SourceChange change;
36 LibraryElement library;
37 String oldLibraryDir;
38 String newLibraryDir;
39
40 MoveFileRefactoringImpl(ResourceProvider resourceProvider, this.searchEngine,
41 this.context, this.source, this.oldFile)
42 : resourceProvider = resourceProvider,
43 pathContext = resourceProvider.pathContext {
44 if (source != null) {
45 oldFile = source.fullName;
46 }
47 }
48
49 @override
50 String get refactoringName => 'Move File';
51
52 @override
53 Future<RefactoringStatus> checkFinalConditions() {
54 RefactoringStatus result = new RefactoringStatus();
55 return new Future.value(result);
56 }
57
58 @override
59 Future<RefactoringStatus> checkInitialConditions() {
60 RefactoringStatus result = new RefactoringStatus();
61 return new Future.value(result);
62 }
63
64 @override
65 Future<SourceChange> createChange() async {
66 // move file
67 if (source != null) {
68 return _createFileChange();
69 }
70 // rename project
71 if (oldFile != null) {
72 Resource projectFolder = resourceProvider.getResource(oldFile);
73 if (projectFolder is Folder && projectFolder.exists) {
74 Resource pubspecFile = projectFolder.getChild('pubspec.yaml');
75 if (pubspecFile is File && pubspecFile.exists) {
76 return _createProjectChange(projectFolder, pubspecFile);
77 }
78 }
79 }
80 // no change
81 return null;
82 }
83
84 @override
85 bool requiresPreview() => false;
86
87 /**
88 * Computes the URI to use to reference [newFile] from [reference].
89 */
90 String _computeNewUri(SourceReference reference) {
91 String refDir = pathContext.dirname(reference.file);
92 // try to keep package: URI
93 if (_isPackageReference(reference)) {
94 Source newSource = new NonExistingSource(
95 newFile, pathos.toUri(newFile), UriKind.FILE_URI);
96 Uri restoredUri = context.sourceFactory.restoreUri(newSource);
97 if (restoredUri != null) {
98 return restoredUri.toString();
99 }
100 }
101 // if no package: URI, prepare relative
102 return _getRelativeUri(newFile, refDir);
103 }
104
105 Future<SourceChange> _createFileChange() async {
106 change = new SourceChange('Update File References');
107 List<Source> librarySources = context.getLibrariesContaining(source);
108 await Future.forEach(librarySources, (Source librarySource) async {
109 CompilationUnitElement unitElement =
110 context.getCompilationUnitElement(source, librarySource);
111 if (unitElement != null) {
112 // if a defining unit, update outgoing references
113 library = unitElement.library;
114 if (library.definingCompilationUnit == unitElement) {
115 oldLibraryDir = pathContext.dirname(oldFile);
116 newLibraryDir = pathContext.dirname(newFile);
117 _updateUriReferences(library.imports);
118 _updateUriReferences(library.exports);
119 _updateUriReferences(library.parts);
120 }
121 // update reference to the unit
122 List<SearchMatch> matches =
123 await searchEngine.searchReferences(unitElement);
124 List<SourceReference> references = getSourceReferences(matches);
125 for (SourceReference reference in references) {
126 String newUri = _computeNewUri(reference);
127 reference.addEdit(change, "'$newUri'");
128 }
129 }
130 });
131 return change;
132 }
133
134 Future<SourceChange> _createProjectChange(
135 Folder project, File pubspecFile) async {
136 change = new SourceChange('Rename project');
137 String oldPackageName = pathContext.basename(oldFile);
138 String newPackageName = pathContext.basename(newFile);
139 // add pubspec.yaml change
140 {
141 // prepare "name" field value location
142 SourceSpan nameSpan;
143 {
144 String pubspecString = pubspecFile.readAsStringSync();
145 YamlMap pubspecNode = loadYamlNode(pubspecString);
146 YamlNode nameNode = pubspecNode.nodes['name'];
147 nameSpan = nameNode.span;
148 }
149 int nameOffset = nameSpan.start.offset;
150 int nameLength = nameSpan.length;
151 // add edit
152 change.addEdit(pubspecFile.path, pubspecFile.modificationStamp,
153 new SourceEdit(nameOffset, nameLength, newPackageName));
154 }
155 // check all local libraries
156 for (Source librarySource in context.librarySources) {
157 // should be a local library
158 if (!project.contains(librarySource.fullName)) {
159 continue;
160 }
161 // we need LibraryElement
162 LibraryElement library = context.getLibraryElement(librarySource);
163 if (library == null) {
164 continue;
165 }
166 // update all imports
167 updateUriElements(List<UriReferencedElement> uriElements) {
168 for (UriReferencedElement element in uriElements) {
169 String uri = element.uri;
170 if (uri != null) {
171 String oldPrefix = 'package:$oldPackageName/';
172 if (uri.startsWith(oldPrefix)) {
173 doSourceChange_addElementEdit(
174 change,
175 library,
176 new SourceEdit(element.uriOffset + 1, oldPrefix.length,
177 'package:$newPackageName/'));
178 }
179 }
180 }
181 }
182
183 updateUriElements(library.imports);
184 updateUriElements(library.exports);
185 }
186 // done
187 return change;
188 }
189
190 String _getRelativeUri(String path, String from) {
191 String uri = pathContext.relative(path, from: from);
192 List<String> parts = pathContext.split(uri);
193 return pathos.posix.joinAll(parts);
194 }
195
196 bool _isPackageReference(SourceReference reference) {
197 Source source = reference.element.source;
198 int offset = reference.range.offset + "'".length;
199 String content = context.getContents(source).data;
200 return content.startsWith('package:', offset);
201 }
202
203 /**
204 * Checks if the given [path] represents a relative URI.
205 *
206 * The following URI's are not relative:
207 * `/absolute/path/file.dart`
208 * `dart:math`
209 */
210 bool _isRelativeUri(String path) {
211 // absolute URI
212 if (Uri.parse(path).isAbsolute) {
213 return false;
214 }
215 // absolute path
216 if (pathContext.isAbsolute(path)) {
217 return false;
218 }
219 // OK
220 return true;
221 }
222
223 void _updateUriReference(UriReferencedElement element) {
224 if (!element.isSynthetic) {
225 String elementUri = element.uri;
226 if (_isRelativeUri(elementUri)) {
227 String elementPath = pathContext.join(oldLibraryDir, elementUri);
228 String newUri = _getRelativeUri(elementPath, newLibraryDir);
229 int uriOffset = element.uriOffset;
230 int uriLength = element.uriEnd - uriOffset;
231 doSourceChange_addElementEdit(
232 change, library, new SourceEdit(uriOffset, uriLength, "'$newUri'"));
233 }
234 }
235 }
236
237 void _updateUriReferences(List<UriReferencedElement> elements) {
238 for (UriReferencedElement element in elements) {
239 _updateUriReference(element);
240 }
241 }
242 }
OLDNEW
« no previous file with comments | « pkg/analysis_server/lib/src/edit/edit_domain.dart ('k') | pkg/analysis_server/lib/src/services/refactoring/refactoring.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698