Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix #3338 Format Document on save #3640

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions packages/editor/src/browser/editor-preferences.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,11 @@ export const editorPreferenceSchema: PreferenceSchema = {
'default': false,
'description': 'Enable auto indentation adjustment.'
},
'editor.formatOnSave': {
'type': 'boolean',
'default': false,
'description': 'Enable format on save when the autoSave preference is off.'
},
'editor.formatOnType': {
'type': 'boolean',
'default': false,
Expand Down Expand Up @@ -504,6 +509,7 @@ export interface EditorConfiguration {
'editor.autoClosingBrackets'?: boolean
'editor.autoIndent'?: boolean
'editor.formatOnType'?: boolean
'editor.formatOnSave'?: boolean
'editor.formatOnPaste'?: boolean
'editor.dragAndDrop'?: boolean
'editor.suggestOnTriggerCharacters'?: boolean
Expand Down
1 change: 1 addition & 0 deletions packages/editorconfig/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"dependencies": {
"@theia/core": "^0.3.16",
"@theia/editor": "^0.3.16",
"@theia/languages": "^0.3.16",
"@theia/monaco": "^0.3.16",
"editorconfig": "^0.15.0"
},
Expand Down
59 changes: 40 additions & 19 deletions packages/editorconfig/src/browser/editorconfig-document-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@
import { injectable, inject, postConstruct } from 'inversify';
import { MonacoEditor } from '@theia/monaco/lib/browser/monaco-editor';
import { TextDocumentSaveReason } from '@theia/languages/lib/browser';
import { EditorManager, EditorWidget, TextEditor } from '@theia/editor/lib/browser';
import { EditorManager, EditorWidget, TextEditor, EditorPreferences } from '@theia/editor/lib/browser';
import { EditorconfigService } from '../common/editorconfig-interface';
import { KnownProps } from 'editorconfig';
import { CommandService } from '@theia/core';

@injectable()
export class EditorconfigDocumentManager {
Expand All @@ -29,12 +30,18 @@ export class EditorconfigDocumentManager {
CRLF: '\r\n'
};

@inject(CommandService)
protected readonly commandService: CommandService;

@inject(EditorManager)
protected readonly editorManager: EditorManager;

@inject(EditorconfigService)
protected readonly editorconfigServer: EditorconfigService;

@inject(EditorPreferences)
protected readonly editorPreferences: EditorPreferences;

private properties: { [file: string]: KnownProps } = {};

@postConstruct()
Expand Down Expand Up @@ -62,24 +69,19 @@ export class EditorconfigDocumentManager {
const monacoEditor = MonacoEditor.get(editorWidget);
if (monacoEditor) {
monacoEditor.document.onWillSaveModel(event => {
event.waitUntil(new Promise<monaco.editor.IIdentifiedSingleEditOperation[]>(resolve => {
event.waitUntil(new Promise<monaco.editor.IIdentifiedSingleEditOperation[]>(async resolve => {
const edits: monaco.editor.IIdentifiedSingleEditOperation[] = [];
const uri = monacoEditor.uri.toString();
const properties = this.properties[uri];

const edits = [];
edits.push(...this.getEditsTrimmingTrailingWhitespaces(monacoEditor, properties, event.reason));
// actually format the document (doesn't return an operation)
await this.formatDocument(monacoEditor);

// gather operations
edits.push(...await this.getEditsTrimmingTrailingWhitespaces(monacoEditor, properties, event.reason));
const edit = this.getEditInsertingFinalNewLine(monacoEditor, properties);
if (edit) {
edits.push(edit);

// get current cursor position
const cursor = monacoEditor.cursor;

// and then restore it after resolving the promise
setTimeout(() => {
monacoEditor.cursor = cursor;
}, 0);
}

resolve(edits);
Expand Down Expand Up @@ -206,10 +208,11 @@ export class EditorconfigDocumentManager {
* preceding newline characters and false to ensure it doesn't.
*/
ensureTrimTrailingWhitespace(editor: MonacoEditor, properties: KnownProps): void {
const edits = this.getEditsTrimmingTrailingWhitespaces(editor, properties);
if (edits.length > 0) {
editor.document.textEditorModel.applyEdits(edits);
}
this.getEditsTrimmingTrailingWhitespaces(editor, properties).then(edits => {
if (edits.length > 0) {
editor.document.textEditorModel.applyEdits(edits);
}
});
}

/**
Expand All @@ -218,14 +221,16 @@ export class EditorconfigDocumentManager {
* @param editor editor
* @param properties editorconfig properties
*/
private getEditsTrimmingTrailingWhitespaces(editor: MonacoEditor, properties: KnownProps, saveReason?: TextDocumentSaveReason): monaco.editor.IIdentifiedSingleEditOperation[] {
private async getEditsTrimmingTrailingWhitespaces(
editor: MonacoEditor, properties: KnownProps, saveReason?: TextDocumentSaveReason
): Promise<monaco.editor.IIdentifiedSingleEditOperation[]> {
const edits = [];

if (MonacoEditor.get(this.editorManager.activeEditor) === editor) {
const trimReason = (saveReason !== TextDocumentSaveReason.Manual) ? 'auto-save' : undefined;
editor.commandService.executeCommand('editor.action.trimTrailingWhitespace', {
await new Promise((resolve, reject) => editor.commandService.executeCommand('editor.action.trimTrailingWhitespace', {
reason: trimReason
});
}).then(resolve, reject));
return [];
}

Expand Down Expand Up @@ -296,4 +301,20 @@ export class EditorconfigDocumentManager {
return undefined;
}

/**
* Format the document when the preference "editor.formatOnSave" is set and the
* "editor.autoSave" is set to "OFF". Only re-format when saving is done manually.
*
* @param editor editor
*/
private async formatDocument(editor: MonacoEditor): Promise<void> {
if (MonacoEditor.get(this.editorManager.activeEditor) === editor) {
if (this.editorPreferences['editor.formatOnSave'] && (this.editorPreferences['editor.autoSave']) === 'off') {
await new Promise((resolve, reject) => {
editor.commandService.executeCommand('editor.action.formatDocument').then(resolve, reject);
});
}
}
}

}