提交 05c87e71 编写于 作者: A Alex Dima

Fixes #6862: Do not auto trim whitespace if edits are not near the cursors

上级 f22a2494
......@@ -97,46 +97,69 @@ export class EditableTextModel extends TextModelWithDecorations implements edito
};
});
for (let i = 0, len = this._trimAutoWhitespaceLines.length; i < len; i++) {
let trimLineNumber = this._trimAutoWhitespaceLines[i];
let maxLineColumn = this.getLineMaxColumn(trimLineNumber);
let allowTrimLine = true;
// Sometimes, auto-formatters change ranges automatically which can cause undesired auto whitespace trimming near the cursor
// We'll use the following heuristic: if the edits occur near the cursor, then it's ok to trim auto whitespace
let editsAreNearCursors = true;
for (let i = 0, len = beforeCursorState.length; i < len; i++) {
let sel = beforeCursorState[i];
let foundEditNearSel = false;
for (let j = 0, lenJ = incomingEdits.length; j < lenJ; j++) {
let editRange = incomingEdits[j].range;
let editText = incomingEdits[j].text;
if (trimLineNumber < editRange.startLineNumber || trimLineNumber > editRange.endLineNumber) {
// `trimLine` is completely outside this edit
continue;
let selIsAbove = editRange.startLineNumber > sel.endLineNumber;
let selIsBelow = sel.startLineNumber > editRange.endLineNumber;
if (!selIsAbove && !selIsBelow) {
foundEditNearSel = true;
break;
}
}
if (!foundEditNearSel) {
editsAreNearCursors = false;
break;
}
}
// At this point:
// editRange.startLineNumber <= trimLine <= editRange.endLineNumber
if (
trimLineNumber === editRange.startLineNumber && editRange.startColumn === maxLineColumn
&& editRange.isEmpty() && editText && editText.length > 0 && editText.charAt(0) === '\n'
) {
// This edit inserts a new line (and maybe other text) after `trimLine`
continue;
if (editsAreNearCursors) {
for (let i = 0, len = this._trimAutoWhitespaceLines.length; i < len; i++) {
let trimLineNumber = this._trimAutoWhitespaceLines[i];
let maxLineColumn = this.getLineMaxColumn(trimLineNumber);
let allowTrimLine = true;
for (let j = 0, lenJ = incomingEdits.length; j < lenJ; j++) {
let editRange = incomingEdits[j].range;
let editText = incomingEdits[j].text;
if (trimLineNumber < editRange.startLineNumber || trimLineNumber > editRange.endLineNumber) {
// `trimLine` is completely outside this edit
continue;
}
// At this point:
// editRange.startLineNumber <= trimLine <= editRange.endLineNumber
if (
trimLineNumber === editRange.startLineNumber && editRange.startColumn === maxLineColumn
&& editRange.isEmpty() && editText && editText.length > 0 && editText.charAt(0) === '\n'
) {
// This edit inserts a new line (and maybe other text) after `trimLine`
continue;
}
// Looks like we can't trim this line as it would interfere with an incoming edit
allowTrimLine = false;
break;
}
// Looks like we can't trim this line as it would interfere with an incoming edit
allowTrimLine = false;
break;
}
if (allowTrimLine) {
editOperations.push({
identifier: null,
range: new Range(trimLineNumber, 1, trimLineNumber, maxLineColumn),
text: null,
forceMoveMarkers: false,
isAutoWhitespaceEdit: false
});
}
if (allowTrimLine) {
editOperations.push({
identifier: null,
range: new Range(trimLineNumber, 1, trimLineNumber, maxLineColumn),
text: null,
forceMoveMarkers: false,
isAutoWhitespaceEdit: false
});
}
}
this._trimAutoWhitespaceLines = null;
......
......@@ -10,7 +10,11 @@ import {EditOperation} from 'vs/editor/common/core/editOperation';
import {Position} from 'vs/editor/common/core/position';
import {Range} from 'vs/editor/common/core/range';
import {Selection} from 'vs/editor/common/core/selection';
import {EndOfLinePreference, EventType, Handler, IPosition, ISelection, IEditorOptions, DefaultEndOfLine, ITextModelCreationOptions} from 'vs/editor/common/editorCommon';
import {
EndOfLinePreference, EventType, Handler, IPosition, ISelection, IEditorOptions,
DefaultEndOfLine, ITextModelCreationOptions, ICommand,
ITokenizedModel, IEditOperationBuilder, ICursorStateComputerData
} from 'vs/editor/common/editorCommon';
import {Model} from 'vs/editor/common/model/model';
import {IMode, IRichEditSupport, IndentAction} from 'vs/editor/common/modes';
import {RichEditSupport} from 'vs/editor/common/modes/supports/richEditSupport';
......@@ -2184,6 +2188,49 @@ suite('Editor Controller - Cursor Configuration', () => {
});
});
test('issue #6862: Editor removes auto inserted indentation when formatting on type', () => {
usingCursor({
text: [
'function foo (params: string) {}'
],
modelOpts: {
insertSpaces: true,
tabSize: 4,
detectIndentation: false,
defaultEOL: DefaultEndOfLine.LF,
trimAutoWhitespace: true
},
mode: new OnEnterMode(IndentAction.IndentOutdent),
}, (model, cursor) => {
moveTo(cursor, 1, 32);
cursorCommand(cursor, H.Type, { text: '\n' }, 'keyboard');
assert.equal(model.getLineContent(1), 'function foo (params: string) {');
assert.equal(model.getLineContent(2), ' ');
assert.equal(model.getLineContent(3), '}');
class TestCommand implements ICommand {
private _selectionId: string = null;
public getEditOperations(model: ITokenizedModel, builder: IEditOperationBuilder): void {
builder.addEditOperation(new Range(1, 13, 1, 14), '');
this._selectionId = builder.trackSelection(cursor.getSelection());
}
public computeCursorState(model: ITokenizedModel, helper: ICursorStateComputerData): Selection {
return helper.getTrackedSelection(this._selectionId);
}
}
cursor.trigger('autoFormat', Handler.ExecuteCommand, new TestCommand());
assert.equal(model.getLineContent(1), 'function foo(params: string) {');
assert.equal(model.getLineContent(2), ' ');
assert.equal(model.getLineContent(3), '}');
});
});
test('removeAutoWhitespace on: removes only whitespace the cursor added 2', () => {
usingCursor({
text: [
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册