1
1
import vscode = require( 'vscode' ) ;
2
- import { languages , TextDocument , TextEdit , FormattingOptions , CancellationToken } from 'vscode'
2
+ import {
3
+ languages ,
4
+ TextDocument ,
5
+ TextEdit ,
6
+ FormattingOptions ,
7
+ CancellationToken ,
8
+ DocumentFormattingEditProvider ,
9
+ DocumentRangeFormattingEditProvider ,
10
+ Range ,
11
+ } from 'vscode' ;
3
12
import { LanguageClient , RequestType , NotificationType } from 'vscode-languageclient' ;
4
13
import Window = vscode . window ;
5
14
import { IFeature } from '../feature' ;
@@ -67,7 +76,7 @@ function editComparer(leftOperand: ScriptRegion, rightOperand: ScriptRegion): nu
67
76
}
68
77
}
69
78
70
- class PSDocumentFormattingEditProvider implements vscode . DocumentFormattingEditProvider {
79
+ class PSDocumentFormattingEditProvider implements DocumentFormattingEditProvider , DocumentRangeFormattingEditProvider {
71
80
private languageClient : LanguageClient ;
72
81
73
82
// The order in which the rules will be executed starting from the first element.
@@ -88,16 +97,20 @@ class PSDocumentFormattingEditProvider implements vscode.DocumentFormattingEditP
88
97
document : TextDocument ,
89
98
options : FormattingOptions ,
90
99
token : CancellationToken ) : TextEdit [ ] | Thenable < TextEdit [ ] > {
100
+ return this . provideDocumentRangeFormattingEdits ( document , null , options , token ) ;
101
+ }
91
102
92
- // we need to order the edits such that edit i should not invalidate
93
- // the edits in edit j s.t i < j (seems like a hard problem)
94
- // or
95
- // peform edits ourself and return an empty textedit array
96
- return this . executeRulesInOrder ( document , options , 0 ) ;
103
+ provideDocumentRangeFormattingEdits (
104
+ document : TextDocument ,
105
+ range : Range ,
106
+ options : FormattingOptions ,
107
+ token : CancellationToken ) : TextEdit [ ] | Thenable < TextEdit [ ] > {
108
+ return this . executeRulesInOrder ( document , range , options , 0 ) ;
97
109
}
98
110
99
111
executeRulesInOrder (
100
112
document : TextDocument ,
113
+ range : Range ,
101
114
options : FormattingOptions ,
102
115
index : number ) : Thenable < TextEdit [ ] > | TextEdit [ ] {
103
116
if ( this . languageClient !== null && index < this . ruleOrder . length ) {
@@ -130,48 +143,71 @@ class PSDocumentFormattingEditProvider implements vscode.DocumentFormattingEditP
130
143
}
131
144
}
132
145
146
+ // we need to update the range as the edits might
147
+ // have changed the original layout
148
+ if ( range !== null ) {
149
+ let tempRange : Range = this . getSelectionRange ( document ) ;
150
+ if ( tempRange !== null ) {
151
+ range = tempRange ;
152
+ }
153
+ }
154
+
133
155
// we do not return a valid array because our text edits
134
156
// need to be executed in a particular order and it is
135
157
// easier if we perform the edits ourselves
136
- return this . applyEdit ( uniqueEdits , 0 , index ) ;
158
+ return this . applyEdit ( uniqueEdits , range , 0 , index ) ;
137
159
} )
138
160
. then ( ( ) => {
139
-
140
161
// execute the same rule again if we left out violations
141
162
// on the same line
142
163
if ( uniqueEdits . length !== edits . length ) {
143
- return this . executeRulesInOrder ( document , options , index ) ;
164
+ return this . executeRulesInOrder ( document , range , options , index ) ;
144
165
}
145
- return this . executeRulesInOrder ( document , options , index + 1 ) ;
166
+ return this . executeRulesInOrder ( document , range , options , index + 1 ) ;
146
167
} ) ;
147
168
} else {
148
169
return TextEdit [ 0 ] ;
149
170
}
150
171
}
151
172
152
- applyEdit ( edits : ScriptRegion [ ] , markerIndex : number , ruleIndex : number ) : Thenable < void > {
173
+ applyEdit ( edits : ScriptRegion [ ] , range : Range , markerIndex : number , ruleIndex : number ) : Thenable < void > {
153
174
if ( markerIndex >= edits . length ) {
154
175
return ;
155
176
}
156
177
157
178
let undoStopAfter = ! this . aggregateUndoStop || ( ruleIndex === this . ruleOrder . length - 1 && markerIndex === edits . length - 1 ) ;
158
179
let undoStopBefore = ! this . aggregateUndoStop || ( ruleIndex === 0 && markerIndex === 0 ) ;
159
180
let edit : ScriptRegion = edits [ markerIndex ] ;
160
- return Window . activeTextEditor . edit ( ( editBuilder ) => {
161
- editBuilder . replace (
162
- new vscode . Range (
163
- edit . startLineNumber - 1 ,
164
- edit . startColumnNumber - 1 ,
165
- edit . endLineNumber - 1 ,
166
- edit . endColumnNumber - 1 ) ,
167
- edit . text ) ;
168
- } ,
169
- {
170
- undoStopAfter : undoStopAfter ,
171
- undoStopBefore : undoStopBefore
172
- } ) . then ( ( isEditApplied ) => {
173
- return this . applyEdit ( edits , markerIndex + 1 , ruleIndex ) ;
174
- } ) ; // TODO handle rejection
181
+ let editRange : Range = new vscode . Range (
182
+ edit . startLineNumber - 1 ,
183
+ edit . startColumnNumber - 1 ,
184
+ edit . endLineNumber - 1 ,
185
+ edit . endColumnNumber - 1 ) ;
186
+ if ( range === null || range . contains ( editRange ) ) {
187
+ return Window . activeTextEditor . edit ( ( editBuilder ) => {
188
+ editBuilder . replace (
189
+ editRange ,
190
+ edit . text ) ;
191
+ } ,
192
+ {
193
+ undoStopAfter : undoStopAfter ,
194
+ undoStopBefore : undoStopBefore
195
+ } ) . then ( ( isEditApplied ) => {
196
+ return this . applyEdit ( edits , range , markerIndex + 1 , ruleIndex ) ;
197
+ } ) ; // TODO handle rejection
198
+ }
199
+ else {
200
+ return this . applyEdit ( edits , range , markerIndex + 1 , ruleIndex ) ;
201
+ }
202
+ }
203
+
204
+ getSelectionRange ( document : TextDocument ) : Range {
205
+ let editor = vscode . window . visibleTextEditors . find ( editor => editor . document === document ) ;
206
+ if ( editor !== undefined ) {
207
+ return editor . selection as Range ;
208
+ }
209
+
210
+ return null ;
175
211
}
176
212
177
213
setLanguageClient ( languageClient : LanguageClient ) : void {
@@ -214,13 +250,17 @@ class PSDocumentFormattingEditProvider implements vscode.DocumentFormattingEditP
214
250
}
215
251
216
252
export class DocumentFormatterFeature implements IFeature {
217
- private disposable : vscode . Disposable ;
253
+ private formattingEditProvider : vscode . Disposable ;
254
+ private rangeFormattingEditProvider : vscode . Disposable ;
218
255
private languageClient : LanguageClient ;
219
256
private documentFormattingEditProvider : PSDocumentFormattingEditProvider ;
220
257
221
258
constructor ( ) {
222
259
this . documentFormattingEditProvider = new PSDocumentFormattingEditProvider ( true ) ;
223
- this . disposable = vscode . languages . registerDocumentFormattingEditProvider (
260
+ this . formattingEditProvider = vscode . languages . registerDocumentFormattingEditProvider (
261
+ "powershell" ,
262
+ this . documentFormattingEditProvider ) ;
263
+ this . rangeFormattingEditProvider = vscode . languages . registerDocumentRangeFormattingEditProvider (
224
264
"powershell" ,
225
265
this . documentFormattingEditProvider ) ;
226
266
}
@@ -231,6 +271,7 @@ export class DocumentFormatterFeature implements IFeature {
231
271
}
232
272
233
273
public dispose ( ) : any {
234
- this . disposable . dispose ( ) ;
274
+ this . formattingEditProvider . dispose ( ) ;
275
+ this . rangeFormattingEditProvider . dispose ( ) ;
235
276
}
236
277
}
0 commit comments