diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_will_rename_files.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_will_rename_files.dart index ee8a2a4001b..2091ecf4153 100644 --- a/pkg/analysis_server/lib/src/lsp/handlers/handler_will_rename_files.dart +++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_will_rename_files.dart @@ -21,11 +21,10 @@ class WillRenameFilesHandler Future> handle(RenameFilesParams params, MessageInfo message, CancellationToken token) async { final files = params.files; - // Only single-file rename/moves are currently supported. - // TODO(dantup): Tweak this when VS Code can correctly pass us cancellation - // requests to not check for .dart to also support folders (although we - // may still only support a single entry initially). - if (files.length > 1 || files.any((f) => !f.oldUri.endsWith('.dart'))) { + // Although we support folders, currently only a single item in the list + // is supported (eg. although you can rename a folder, you can't drag + // multiple files between folders). + if (files.length > 1) { return success(null); } diff --git a/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart b/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart index e2dd87886c9..a3255c5aa88 100644 --- a/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart +++ b/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart @@ -127,6 +127,13 @@ class ServerCapabilitiesComputer { glob: '**/*.dart', matches: FileOperationPatternKind.file, ), + ), + FileOperationFilter( + scheme: 'file', + pattern: FileOperationPattern( + glob: '**/', + matches: FileOperationPatternKind.folder, + ), ) ], ); diff --git a/pkg/analysis_server/test/lsp/will_rename_files_test.dart b/pkg/analysis_server/test/lsp/will_rename_files_test.dart index ea16d07ab69..c549c2fd8ac 100644 --- a/pkg/analysis_server/test/lsp/will_rename_files_test.dart +++ b/pkg/analysis_server/test/lsp/will_rename_files_test.dart @@ -86,7 +86,7 @@ class WillRenameFilesTest extends AbstractLspAnalysisServerTest { ); } - Future test_rename_updatesImports() async { + Future test_renameFile_updatesImports() async { final otherFilePath = join(projectFolderPath, 'lib', 'other.dart'); final otherFileUri = Uri.file(otherFilePath); final otherFileNewPath = join(projectFolderPath, 'lib', 'other_new.dart'); @@ -125,4 +125,44 @@ final a = A(); applyChanges(contents, edit.changes!); expect(contents[mainFilePath], equals(expectedMainContent)); } + + Future test_renameFolder_updatesImports() async { + final oldFolderPath = join(projectFolderPath, 'lib', 'folder'); + final newFolderPath = join(projectFolderPath, 'lib', 'folder_new'); + final otherFilePath = join(oldFolderPath, 'other.dart'); + final otherFileUri = Uri.file(otherFilePath); + + final mainContent = ''' +import 'folder/other.dart'; + +final a = A(); +'''; + + final otherContent = ''' +class A {} +'''; + + final expectedMainContent = ''' +import 'folder_new/other.dart'; + +final a = A(); +'''; + + await initialize(); + await openFile(mainFileUri, mainContent); + await openFile(otherFileUri, otherContent); + final edit = await onWillRename([ + FileRename( + oldUri: Uri.file(oldFolderPath).toString(), + newUri: Uri.file(newFolderPath).toString(), + ), + ]); + + // Ensure applying the edit will give us the expected content. + final contents = { + mainFilePath: withoutMarkers(mainContent), + }; + applyChanges(contents, edit.changes!); + expect(contents[mainFilePath], equals(expectedMainContent)); + } }