1
1
import type * as atomIde from "atom-ide-base"
2
2
import Convert from "../convert"
3
- import { LanguageClientConnection , ApplyWorkspaceEditParams , ApplyWorkspaceEditResponse } from "../languageclient"
3
+ import {
4
+ LanguageClientConnection ,
5
+ ApplyWorkspaceEditParams ,
6
+ ApplyWorkspaceEditResponse ,
7
+ WorkspaceEdit ,
8
+ TextDocumentEdit ,
9
+ CreateFile ,
10
+ RenameFile ,
11
+ DeleteFile ,
12
+ DocumentUri
13
+ } from "../languageclient"
4
14
import { TextBuffer , TextEditor } from "atom"
15
+ import * as fs from 'fs' ;
5
16
6
17
/** Public: Adapts workspace/applyEdit commands to editors. */
7
18
export default class ApplyEditAdapter {
@@ -33,33 +44,28 @@ export default class ApplyEditAdapter {
33
44
}
34
45
35
46
public static async onApplyEdit ( params : ApplyWorkspaceEditParams ) : Promise < ApplyWorkspaceEditResponse > {
36
- let changes = params . edit . changes || { }
37
-
38
- if ( params . edit . documentChanges ) {
39
- changes = { }
40
- params . edit . documentChanges . forEach ( ( change ) => {
41
- if ( change && "textDocument" in change && change . textDocument ) {
42
- changes [ change . textDocument . uri ] = change . edits
43
- }
44
- } )
45
- }
46
-
47
- const uris = Object . keys ( changes )
47
+ return ApplyEditAdapter . apply ( params . edit )
48
+ }
48
49
50
+ public static async apply ( workspaceEdit : WorkspaceEdit ) : Promise < ApplyWorkspaceEditResponse > {
51
+ ApplyEditAdapter . normalize ( workspaceEdit )
52
+
49
53
// Keep checkpoints from all successful buffer edits
50
54
const checkpoints : Array < { buffer : TextBuffer ; checkpoint : number } > = [ ]
51
55
52
- const promises = uris . map ( async ( uri ) => {
53
- const path = Convert . uriToPath ( uri )
56
+ const promises = ( workspaceEdit . documentChanges || [ ] ) . map ( async ( edit ) : Promise < void > => {
57
+ if ( ! ApplyEditAdapter . isTextDocumentEdit ( edit ) ) {
58
+ return ApplyEditAdapter . handleResourceOperation ( edit )
59
+ }
60
+ const path = Convert . uriToPath ( edit . textDocument . uri )
54
61
const editor = ( await atom . workspace . open ( path , {
55
62
searchAllPanes : true ,
56
63
// Open new editors in the background.
57
64
activatePane : false ,
58
65
activateItem : false ,
59
66
} ) ) as TextEditor
60
67
const buffer = editor . getBuffer ( )
61
- // Get an existing editor for the file, or open a new one if it doesn't exist.
62
- const edits = Convert . convertLsTextEdits ( changes [ uri ] )
68
+ const edits = Convert . convertLsTextEdits ( edit . edits )
63
69
const checkpoint = ApplyEditAdapter . applyEdits ( buffer , edits )
64
70
checkpoints . push ( { buffer, checkpoint } )
65
71
} )
@@ -81,6 +87,39 @@ export default class ApplyEditAdapter {
81
87
return { applied }
82
88
}
83
89
90
+ private static async handleResourceOperation ( edit : ( CreateFile | RenameFile | DeleteFile ) ) : Promise < void >
91
+ {
92
+ if ( edit . kind === 'delete' ) {
93
+ return fs . promises . unlink ( Convert . uriToPath ( edit . uri ) )
94
+ } else if ( edit . kind === 'rename' ) {
95
+ return fs . promises . rename ( Convert . uriToPath ( edit . oldUri ) , Convert . uriToPath ( edit . newUri ) )
96
+ } else if ( edit . kind === 'create' ) {
97
+ return fs . promises . writeFile ( edit . uri , '' )
98
+ }
99
+ }
100
+
101
+ private static normalize ( workspaceEdit : WorkspaceEdit ) : void {
102
+ const documentChanges = workspaceEdit . documentChanges || [ ]
103
+
104
+ if ( ! workspaceEdit . hasOwnProperty ( 'documentChanges' ) && workspaceEdit . hasOwnProperty ( 'changes' ) ) {
105
+ Object . keys ( workspaceEdit . changes || [ ] ) . forEach ( ( uri : DocumentUri ) => {
106
+ documentChanges . push ( {
107
+ textDocument : {
108
+ version : null ,
109
+ uri : uri
110
+ } ,
111
+ edits : workspaceEdit . changes ! [ uri ]
112
+ } )
113
+ } )
114
+ }
115
+
116
+ workspaceEdit . documentChanges = documentChanges
117
+ }
118
+
119
+ private static isTextDocumentEdit ( edit : ( TextDocumentEdit | CreateFile | RenameFile | DeleteFile ) ) : edit is TextDocumentEdit {
120
+ return ( < TextDocumentEdit > edit ) . edits !== undefined ;
121
+ }
122
+
84
123
/** Private: Do some basic sanity checking on the edit ranges. */
85
124
private static validateEdit ( buffer : TextBuffer , edit : atomIde . TextEdit , prevEdit : atomIde . TextEdit | null ) : void {
86
125
const path = buffer . getPath ( ) || ""
0 commit comments