Skip to content

Commit e1e0dd7

Browse files
author
Kapil Borle
committed
Provide code formatting of selection
1 parent 7291539 commit e1e0dd7

File tree

1 file changed

+71
-30
lines changed

1 file changed

+71
-30
lines changed

src/features/DocumentFormatter.ts

Lines changed: 71 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
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';
312
import { LanguageClient, RequestType, NotificationType } from 'vscode-languageclient';
413
import Window = vscode.window;
514
import { 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

216252
export 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

Comments
 (0)