| 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.move_file; | 5 library services.src.refactoring.move_file; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 | 8 |
| 9 import 'package:analysis_server/src/protocol_server.dart' hide Element; | 9 import 'package:analysis_server/src/protocol_server.dart' hide Element; |
| 10 import 'package:analysis_server/src/services/correction/status.dart'; | 10 import 'package:analysis_server/src/services/correction/status.dart'; |
| 11 import 'package:analysis_server/src/services/refactoring/refactoring.dart'; | 11 import 'package:analysis_server/src/services/refactoring/refactoring.dart'; |
| 12 import 'package:analysis_server/src/services/refactoring/refactoring_internal.da
rt'; | 12 import 'package:analysis_server/src/services/refactoring/refactoring_internal.da
rt'; |
| 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/file_system/file_system.dart'; |
| 14 import 'package:analyzer/src/generated/element.dart'; | 15 import 'package:analyzer/src/generated/element.dart'; |
| 15 import 'package:analyzer/src/generated/engine.dart'; | 16 import 'package:analyzer/src/generated/engine.dart'; |
| 16 import 'package:analyzer/src/generated/source.dart'; | 17 import 'package:analyzer/src/generated/source.dart'; |
| 17 import 'package:path/path.dart' as pathos; | 18 import 'package:path/path.dart' as pathos; |
| 19 import 'package:source_span/src/span.dart'; |
| 20 import 'package:yaml/yaml.dart'; |
| 18 | 21 |
| 19 /** | 22 /** |
| 20 * [ExtractLocalRefactoring] implementation. | 23 * [ExtractLocalRefactoring] implementation. |
| 21 */ | 24 */ |
| 22 class MoveFileRefactoringImpl extends RefactoringImpl | 25 class MoveFileRefactoringImpl extends RefactoringImpl |
| 23 implements MoveFileRefactoring { | 26 implements MoveFileRefactoring { |
| 27 final ResourceProvider resourceProvider; |
| 24 final pathos.Context pathContext; | 28 final pathos.Context pathContext; |
| 25 final SearchEngine searchEngine; | 29 final SearchEngine searchEngine; |
| 26 final AnalysisContext context; | 30 final AnalysisContext context; |
| 27 final Source source; | 31 final Source source; |
| 28 | 32 |
| 29 String oldFile; | 33 String oldFile; |
| 30 String newFile; | 34 String newFile; |
| 31 | 35 |
| 32 SourceChange change; | 36 SourceChange change; |
| 33 LibraryElement library; | 37 LibraryElement library; |
| 34 String oldLibraryDir; | 38 String oldLibraryDir; |
| 35 String newLibraryDir; | 39 String newLibraryDir; |
| 36 | 40 |
| 37 MoveFileRefactoringImpl( | 41 MoveFileRefactoringImpl(ResourceProvider resourceProvider, this.searchEngine, |
| 38 this.pathContext, this.searchEngine, this.context, this.source) { | 42 this.context, this.source, this.oldFile) |
| 39 oldFile = source.fullName; | 43 : resourceProvider = resourceProvider, |
| 44 pathContext = resourceProvider.pathContext { |
| 45 if (source != null) { |
| 46 oldFile = source.fullName; |
| 47 } |
| 40 } | 48 } |
| 41 | 49 |
| 42 @override | 50 @override |
| 43 String get refactoringName => 'Move File'; | 51 String get refactoringName => 'Move File'; |
| 44 | 52 |
| 45 @override | 53 @override |
| 46 Future<RefactoringStatus> checkFinalConditions() { | 54 Future<RefactoringStatus> checkFinalConditions() { |
| 47 RefactoringStatus result = new RefactoringStatus(); | 55 RefactoringStatus result = new RefactoringStatus(); |
| 48 return new Future.value(result); | 56 return new Future.value(result); |
| 49 } | 57 } |
| 50 | 58 |
| 51 @override | 59 @override |
| 52 Future<RefactoringStatus> checkInitialConditions() { | 60 Future<RefactoringStatus> checkInitialConditions() { |
| 53 RefactoringStatus result = new RefactoringStatus(); | 61 RefactoringStatus result = new RefactoringStatus(); |
| 54 return new Future.value(result); | 62 return new Future.value(result); |
| 55 } | 63 } |
| 56 | 64 |
| 57 @override | 65 @override |
| 58 Future<SourceChange> createChange() async { | 66 Future<SourceChange> createChange() async { |
| 67 // move file |
| 68 if (source != null) { |
| 69 return _createFileChange(); |
| 70 } |
| 71 // rename project |
| 72 if (oldFile != null) { |
| 73 Resource projectFolder = resourceProvider.getResource(oldFile); |
| 74 if (projectFolder is Folder && projectFolder.exists) { |
| 75 Resource pubspecFile = projectFolder.getChild('pubspec.yaml'); |
| 76 if (pubspecFile is File && pubspecFile.exists) { |
| 77 return _createProjectChange(projectFolder, pubspecFile); |
| 78 } |
| 79 } |
| 80 } |
| 81 // no change |
| 82 return null; |
| 83 } |
| 84 |
| 85 @override |
| 86 bool requiresPreview() => false; |
| 87 |
| 88 /** |
| 89 * Computes the URI to use to reference [newFile] from [reference]. |
| 90 */ |
| 91 String _computeNewUri(SourceReference reference) { |
| 92 String refDir = pathContext.dirname(reference.file); |
| 93 // try to keep package: URI |
| 94 if (_isPackageReference(reference)) { |
| 95 Source newSource = new NonExistingSource(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 { |
| 59 change = new SourceChange('Update File References'); | 106 change = new SourceChange('Update File References'); |
| 60 List<Source> librarySources = context.getLibrariesContaining(source); | 107 List<Source> librarySources = context.getLibrariesContaining(source); |
| 61 await Future.forEach(librarySources, (Source librarySource) async { | 108 await Future.forEach(librarySources, (Source librarySource) async { |
| 62 CompilationUnitElement unitElement = | 109 CompilationUnitElement unitElement = |
| 63 context.getCompilationUnitElement(source, librarySource); | 110 context.getCompilationUnitElement(source, librarySource); |
| 64 if (unitElement != null) { | 111 if (unitElement != null) { |
| 65 // if a defining unit, update outgoing references | 112 // if a defining unit, update outgoing references |
| 66 library = unitElement.library; | 113 library = unitElement.library; |
| 67 if (library.definingCompilationUnit == unitElement) { | 114 if (library.definingCompilationUnit == unitElement) { |
| 68 oldLibraryDir = pathContext.dirname(oldFile); | 115 oldLibraryDir = pathContext.dirname(oldFile); |
| 69 newLibraryDir = pathContext.dirname(newFile); | 116 newLibraryDir = pathContext.dirname(newFile); |
| 70 _updateUriReferences(library.imports); | 117 _updateUriReferences(library.imports); |
| 71 _updateUriReferences(library.exports); | 118 _updateUriReferences(library.exports); |
| 72 _updateUriReferences(library.parts); | 119 _updateUriReferences(library.parts); |
| 73 } | 120 } |
| 74 // update reference to the unit | 121 // update reference to the unit |
| 75 List<SearchMatch> matches = | 122 List<SearchMatch> matches = |
| 76 await searchEngine.searchReferences(unitElement); | 123 await searchEngine.searchReferences(unitElement); |
| 77 List<SourceReference> references = getSourceReferences(matches); | 124 List<SourceReference> references = getSourceReferences(matches); |
| 78 for (SourceReference reference in references) { | 125 for (SourceReference reference in references) { |
| 79 String newUri = _computeNewUri(reference); | 126 String newUri = _computeNewUri(reference); |
| 80 reference.addEdit(change, "'$newUri'"); | 127 reference.addEdit(change, "'$newUri'"); |
| 81 } | 128 } |
| 82 } | 129 } |
| 83 }); | 130 }); |
| 84 return change; | 131 return change; |
| 85 } | 132 } |
| 86 | 133 |
| 87 @override | 134 Future<SourceChange> _createProjectChange( |
| 88 bool requiresPreview() => false; | 135 Folder project, File pubspecFile) async { |
| 89 | 136 // prepare "name" field value location |
| 90 /** | 137 SourceSpan nameSpan; |
| 91 * Computes the URI to use to reference [newFile] from [reference]. | 138 { |
| 92 */ | 139 String pubspecString = pubspecFile.readAsStringSync(); |
| 93 String _computeNewUri(SourceReference reference) { | 140 YamlMap pubspecNode = loadYamlNode(pubspecString); |
| 94 String refDir = pathContext.dirname(reference.file); | 141 YamlNode nameNode = pubspecNode.nodes['name']; |
| 95 // try to keep package: URI | 142 nameSpan = nameNode.span; |
| 96 if (_isPackageReference(reference)) { | |
| 97 Source newSource = new NonExistingSource(newFile, UriKind.FILE_URI); | |
| 98 Uri restoredUri = context.sourceFactory.restoreUri(newSource); | |
| 99 if (restoredUri != null) { | |
| 100 return restoredUri.toString(); | |
| 101 } | |
| 102 } | 143 } |
| 103 // if no package: URI, prepare relative | 144 int nameOffset = nameSpan.start.offset; |
| 104 return _getRelativeUri(newFile, refDir); | 145 int nameLength = nameSpan.length; |
| 146 // create Change |
| 147 change = new SourceChange('Rename project'); |
| 148 String newPackageName = pathContext.basename(newFile); |
| 149 change.addEdit(pubspecFile.path, pubspecFile.modificationStamp, |
| 150 new SourceEdit(nameOffset, nameLength, newPackageName)); |
| 151 return change; |
| 105 } | 152 } |
| 106 | 153 |
| 107 String _getRelativeUri(String path, String from) { | 154 String _getRelativeUri(String path, String from) { |
| 108 String uri = pathContext.relative(path, from: from); | 155 String uri = pathContext.relative(path, from: from); |
| 109 List<String> parts = pathContext.split(uri); | 156 List<String> parts = pathContext.split(uri); |
| 110 return pathos.posix.joinAll(parts); | 157 return pathos.posix.joinAll(parts); |
| 111 } | 158 } |
| 112 | 159 |
| 113 bool _isPackageReference(SourceReference reference) { | 160 bool _isPackageReference(SourceReference reference) { |
| 114 Source source = reference.element.source; | 161 Source source = reference.element.source; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 } | 197 } |
| 151 } | 198 } |
| 152 } | 199 } |
| 153 | 200 |
| 154 void _updateUriReferences(List<UriReferencedElement> elements) { | 201 void _updateUriReferences(List<UriReferencedElement> elements) { |
| 155 for (UriReferencedElement element in elements) { | 202 for (UriReferencedElement element in elements) { |
| 156 _updateUriReference(element); | 203 _updateUriReference(element); |
| 157 } | 204 } |
| 158 } | 205 } |
| 159 } | 206 } |
| OLD | NEW |