Skip to content

Commit 7626d52

Browse files
committed
restore extension specific formatOnSave #421
1 parent 7f3d38d commit 7626d52

5 files changed

Lines changed: 84 additions & 17 deletions

File tree

package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,11 @@
690690
"type": "string"
691691
}
692692
},
693+
"python.formatting.formatOnSave": {
694+
"type": "boolean",
695+
"default": false,
696+
"description": "Format the document upon saving."
697+
},
693698
"python.formatting.outputWindow": {
694699
"type": "string",
695700
"default": "Python",
@@ -838,4 +843,4 @@
838843
"vscode": "^1.0.0",
839844
"webpack": "^1.13.2"
840845
}
841-
}
846+
}

src/client/common/configSettings.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ export interface IFormattingSettings {
6565
autopep8Args: string[];
6666
yapfPath: string;
6767
yapfArgs: string[];
68+
formatOnSave: boolean;
6869
outputWindow: string;
6970
}
7071
export interface IAutoCompeteSettings {
@@ -152,7 +153,8 @@ export class PythonSettings extends EventEmitter implements IPythonSettings {
152153
autopep8Args: [], autopep8Path: 'autopep8',
153154
outputWindow: 'python',
154155
provider: 'autopep8',
155-
yapfArgs: [], yapfPath: 'yapf'
156+
yapfArgs: [], yapfPath: 'yapf',
157+
formatOnSave: false
156158
};
157159
this.formatting.autopep8Path = getAbsolutePath(this.formatting.autopep8Path, workspaceRoot);
158160
this.formatting.yapfPath = getAbsolutePath(this.formatting.yapfPath, workspaceRoot);

src/client/extension.ts

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import * as tests from './unittests/main';
2222
import * as jup from './jupyter/main';
2323
import { HelpProvider } from './helpProvider';
2424
import { Documentation } from './common/constants';
25+
import {activateFormatOnSaveProvider} from './providers/formatOnSaveProvider';
2526

2627
const PYTHON: vscode.DocumentFilter = { language: 'python', scheme: 'file' };
2728
let unitTestOutChannel: vscode.OutputChannel;
@@ -50,6 +51,7 @@ export function activate(context: vscode.ExtensionContext) {
5051
context.subscriptions.push(activateSetInterpreterProvider());
5152
context.subscriptions.push(...activateExecInTerminalProvider());
5253
activateSimplePythonRefactorProvider(context, formatOutChannel);
54+
context.subscriptions.push(activateFormatOnSaveProvider(PYTHON, settings.PythonSettings.getInstance(), formatOutChannel, vscode.workspace.rootPath));
5355

5456
// Enable indentAction
5557
vscode.languages.setLanguageConfiguration(PYTHON.language, {
@@ -92,16 +94,6 @@ export function activate(context: vscode.ExtensionContext) {
9294

9395
const hepProvider = new HelpProvider();
9496
context.subscriptions.push(hepProvider);
95-
96-
// Check for old outdated settings
97-
const pySettings = vscode.workspace.getConfiguration('python');
98-
if (pySettings.get('formatting.formatOnSave') === true) {
99-
vscode.window.showInformationMessage(`'python.formatting.formatOnSave' has been deprecated. Please use 'editor.formatOnSave' instead`, 'Help').then(item => {
100-
if (item === 'Help') {
101-
vscode.commands.executeCommand('python.displayHelp', Documentation.Formatting.FormatOnSave);
102-
}
103-
});
104-
}
10597
}
10698

10799
function disableOtherDocumentSymbolsProvider() {
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
"use strict";
2+
3+
// Solution for auto-formatting borrowed from the "go" language VSCode extension.
4+
5+
import * as vscode from "vscode";
6+
import { BaseFormatter } from "./../formatters/baseFormatter";
7+
import { YapfFormatter } from "./../formatters/yapfFormatter";
8+
import { AutoPep8Formatter } from "./../formatters/autoPep8Formatter";
9+
import * as settings from "./../common/configSettings";
10+
import * as telemetryHelper from "../common/telemetry";
11+
import * as telemetryContracts from "../common/telemetryContracts";
12+
13+
export function activateFormatOnSaveProvider(languageFilter: vscode.DocumentFilter, settings: settings.IPythonSettings, outputChannel: vscode.OutputChannel, workspaceRootPath: string): vscode.Disposable {
14+
let formatters = new Map<string, BaseFormatter>();
15+
let pythonSettings = settings;
16+
17+
let yapfFormatter = new YapfFormatter(outputChannel, settings, workspaceRootPath);
18+
let autoPep8 = new AutoPep8Formatter(outputChannel, settings, workspaceRootPath);
19+
20+
formatters.set(yapfFormatter.Id, yapfFormatter);
21+
formatters.set(autoPep8.Id, autoPep8);
22+
23+
return vscode.workspace.onWillSaveTextDocument(e => {
24+
const document = e.document;
25+
if (document.languageId !== languageFilter.language) {
26+
return;
27+
}
28+
let textEditor = vscode.window.activeTextEditor;
29+
let editorConfig = vscode.workspace.getConfiguration('editor');
30+
const globalEditorFormatOnSave = editorConfig && editorConfig.has('formatOnSave') && editorConfig.get('formatOnSave') === true;
31+
if ((pythonSettings.formatting.formatOnSave || globalEditorFormatOnSave) && textEditor.document === document) {
32+
let formatter = formatters.get(pythonSettings.formatting.provider);
33+
telemetryHelper.sendTelemetryEvent(telemetryContracts.IDE.Format, { Format_Provider: formatter.Id, Format_OnSave: "true" });
34+
e.waitUntil(formatter.formatDocument(document, null, null));
35+
}
36+
}, null, null);
37+
}

src/test/extension.format.test.ts

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ import * as assert from 'assert';
1111
// You can import and use all API from the 'vscode' module
1212
// as well as import your extension to test it
1313
import * as vscode from 'vscode';
14-
import {AutoPep8Formatter} from '../client/formatters/autoPep8Formatter';
15-
import {YapfFormatter} from '../client/formatters/yapfFormatter';
14+
import { AutoPep8Formatter } from '../client/formatters/autoPep8Formatter';
15+
import { YapfFormatter } from '../client/formatters/yapfFormatter';
1616
import * as path from 'path';
1717
import * as settings from '../client/common/configSettings';
1818
import * as fs from 'fs-extra';
19-
import {execPythonFile} from '../client/common/utils';
19+
import { execPythonFile } from '../client/common/utils';
2020

2121
let pythonSettings = settings.PythonSettings.getInstance();
2222
let ch = vscode.window.createOutputChannel('Tests');
@@ -46,7 +46,7 @@ suiteSetup(done => {
4646
formattedAutoPep8 = formattedResults[1];
4747
}).then(() => {
4848
done();
49-
}, reason=>{
49+
}, reason => {
5050
console.error(reason);
5151
console.error('Failed to initialize format tests');
5252
done();
@@ -81,7 +81,7 @@ suite('Formatting', () => {
8181
});
8282
}).then(edited => {
8383
assert.equal(textEditor.document.getText(), formattedContents, 'Formatted text is not the same');
84-
}, reason=>{
84+
}, reason => {
8585
assert.fail(reason, undefined, 'Formatting failed', '');
8686
});
8787
}
@@ -92,4 +92,35 @@ suite('Formatting', () => {
9292
test('Yapf', done => {
9393
testFormatting(new YapfFormatter(ch, pythonSettings, pythoFilesPath), formattedYapf, yapfFileToFormat).then(done, done);
9494
});
95+
96+
function testAutoFormatting(formatter: string, formattedContents: string, fileToFormat: string): PromiseLike<void> {
97+
let textDocument: vscode.TextDocument;
98+
pythonSettings.formatting.formatOnSave = true;
99+
pythonSettings.formatting.provider = formatter;
100+
return vscode.workspace.openTextDocument(fileToFormat).then(document => {
101+
textDocument = document;
102+
return vscode.window.showTextDocument(textDocument);
103+
}).then(editor => {
104+
return editor.edit(editBuilder => {
105+
editBuilder.insert(new vscode.Position(0, 0), '#\n');
106+
});
107+
}).then(edited => {
108+
return textDocument.save();
109+
}).then(saved => {
110+
return new Promise<any>((resolve, reject) => {
111+
setTimeout(() => {
112+
resolve();
113+
}, 4000);
114+
});
115+
}).then(() => {
116+
assert.equal(textDocument.getText(), formattedContents, 'Formatted contents are not the same');
117+
});
118+
}
119+
test('AutoPep8 autoformat on save', done => {
120+
testAutoFormatting('autopep8', '#\n' + formattedAutoPep8, autoPep8FileToAutoFormat).then(done, done);
121+
});
122+
123+
test('Yapf autoformat on save', done => {
124+
testAutoFormatting('yapf', '#\n' + formattedYapf, yapfFileToAutoFormat).then(done, done);
125+
});
95126
});

0 commit comments

Comments
 (0)