11import 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' ;
312import { LanguageClient , RequestType , NotificationType } from 'vscode-languageclient' ;
413import Window = vscode . window ;
514import { IFeature } from '../feature' ;
@@ -67,7 +76,7 @@ function editComparer(leftOperand: ScriptRegion, rightOperand: ScriptRegion): nu
6776 }
6877}
6978
70- class PSDocumentFormattingEditProvider implements vscode . DocumentFormattingEditProvider {
79+ class PSDocumentFormattingEditProvider implements DocumentFormattingEditProvider , DocumentRangeFormattingEditProvider {
7180 private languageClient : LanguageClient ;
7281
7382 // The order in which the rules will be executed starting from the first element.
@@ -88,16 +97,20 @@ class PSDocumentFormattingEditProvider implements vscode.DocumentFormattingEditP
8897 document : TextDocument ,
8998 options : FormattingOptions ,
9099 token : CancellationToken ) : TextEdit [ ] | Thenable < TextEdit [ ] > {
100+ return this . provideDocumentRangeFormattingEdits ( document , null , options , token ) ;
101+ }
91102
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 ) ;
97109 }
98110
99111 executeRulesInOrder (
100112 document : TextDocument ,
113+ range : Range ,
101114 options : FormattingOptions ,
102115 index : number ) : Thenable < TextEdit [ ] > | TextEdit [ ] {
103116 if ( this . languageClient !== null && index < this . ruleOrder . length ) {
@@ -130,48 +143,71 @@ class PSDocumentFormattingEditProvider implements vscode.DocumentFormattingEditP
130143 }
131144 }
132145
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+
133155 // we do not return a valid array because our text edits
134156 // need to be executed in a particular order and it is
135157 // easier if we perform the edits ourselves
136- return this . applyEdit ( uniqueEdits , 0 , index ) ;
158+ return this . applyEdit ( uniqueEdits , range , 0 , index ) ;
137159 } )
138160 . then ( ( ) => {
139-
140161 // execute the same rule again if we left out violations
141162 // on the same line
142163 if ( uniqueEdits . length !== edits . length ) {
143- return this . executeRulesInOrder ( document , options , index ) ;
164+ return this . executeRulesInOrder ( document , range , options , index ) ;
144165 }
145- return this . executeRulesInOrder ( document , options , index + 1 ) ;
166+ return this . executeRulesInOrder ( document , range , options , index + 1 ) ;
146167 } ) ;
147168 } else {
148169 return TextEdit [ 0 ] ;
149170 }
150171 }
151172
152- applyEdit ( edits : ScriptRegion [ ] , markerIndex : number , ruleIndex : number ) : Thenable < void > {
173+ applyEdit ( edits : ScriptRegion [ ] , range : Range , markerIndex : number , ruleIndex : number ) : Thenable < void > {
153174 if ( markerIndex >= edits . length ) {
154175 return ;
155176 }
156177
157178 let undoStopAfter = ! this . aggregateUndoStop || ( ruleIndex === this . ruleOrder . length - 1 && markerIndex === edits . length - 1 ) ;
158179 let undoStopBefore = ! this . aggregateUndoStop || ( ruleIndex === 0 && markerIndex === 0 ) ;
159180 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 ;
175211 }
176212
177213 setLanguageClient ( languageClient : LanguageClient ) : void {
@@ -214,13 +250,17 @@ class PSDocumentFormattingEditProvider implements vscode.DocumentFormattingEditP
214250}
215251
216252export class DocumentFormatterFeature implements IFeature {
217- private disposable : vscode . Disposable ;
253+ private formattingEditProvider : vscode . Disposable ;
254+ private rangeFormattingEditProvider : vscode . Disposable ;
218255 private languageClient : LanguageClient ;
219256 private documentFormattingEditProvider : PSDocumentFormattingEditProvider ;
220257
221258 constructor ( ) {
222259 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 (
224264 "powershell" ,
225265 this . documentFormattingEditProvider ) ;
226266 }
@@ -231,6 +271,7 @@ export class DocumentFormatterFeature implements IFeature {
231271 }
232272
233273 public dispose ( ) : any {
234- this . disposable . dispose ( ) ;
274+ this . formattingEditProvider . dispose ( ) ;
275+ this . rangeFormattingEditProvider . dispose ( ) ;
235276 }
236277}
0 commit comments