mirror of
https://github.com/microsoft/vscode.git
synced 2026-08-19 22:42:35 +01:00
fix #54829
This commit is contained in:
@@ -9,7 +9,7 @@ import { Range } from 'vs/editor/common/core/range';
|
||||
import { Selection } from 'vs/editor/common/core/selection';
|
||||
import { ICommand, ICursorStateComputerData, IEditOperationBuilder } from 'vs/editor/common/editorCommon';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
import { IndentAction } from 'vs/editor/common/modes/languageConfiguration';
|
||||
import { CompleteEnterAction, IndentAction } from 'vs/editor/common/modes/languageConfiguration';
|
||||
import { IIndentConverter, LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
|
||||
import { IndentConsts } from 'vs/editor/common/modes/supports/indentRules';
|
||||
import * as indentUtils from 'vs/editor/contrib/indentation/indentUtils';
|
||||
@@ -135,7 +135,8 @@ export class MoveLinesCommand implements ICommand {
|
||||
// to s.startLineNumber
|
||||
builder.addEditOperation(new Range(s.startLineNumber, 1, s.startLineNumber, 1), insertingText + '\n');
|
||||
|
||||
let ret = this.matchEnterRule(model, indentConverter, tabSize, s.startLineNumber, s.startLineNumber, insertingText);
|
||||
let ret = this.matchEnterRuleMovingDown(model, indentConverter, tabSize, s.startLineNumber, movingLineNumber, insertingText);
|
||||
|
||||
// check if the line being moved before matches onEnter rules, if so let's adjust the indentation by onEnter rules.
|
||||
if (ret !== null) {
|
||||
if (ret !== 0) {
|
||||
@@ -229,31 +230,7 @@ export class MoveLinesCommand implements ICommand {
|
||||
};
|
||||
}
|
||||
|
||||
private matchEnterRule(model: ITextModel, indentConverter: IIndentConverter, tabSize: number, line: number, oneLineAbove: number, oneLineAboveText?: string) {
|
||||
let validPrecedingLine = oneLineAbove;
|
||||
while (validPrecedingLine >= 1) {
|
||||
// ship empty lines as empty lines just inherit indentation
|
||||
let lineContent;
|
||||
if (validPrecedingLine === oneLineAbove && oneLineAboveText !== undefined) {
|
||||
lineContent = oneLineAboveText;
|
||||
} else {
|
||||
lineContent = model.getLineContent(validPrecedingLine);
|
||||
}
|
||||
|
||||
let nonWhitespaceIdx = strings.lastNonWhitespaceIndex(lineContent);
|
||||
if (nonWhitespaceIdx >= 0) {
|
||||
break;
|
||||
}
|
||||
validPrecedingLine--;
|
||||
}
|
||||
|
||||
if (validPrecedingLine < 1 || line > model.getLineCount()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let maxColumn = model.getLineMaxColumn(validPrecedingLine);
|
||||
let enter = LanguageConfigurationRegistry.getEnterAction(this._autoIndent, model, new Range(validPrecedingLine, maxColumn, validPrecedingLine, maxColumn));
|
||||
|
||||
private parseEnterResult(model: ITextModel, indentConverter: IIndentConverter, tabSize: number, line: number, enter: CompleteEnterAction | null) {
|
||||
if (enter) {
|
||||
let enterPrefix = enter.indentation;
|
||||
|
||||
@@ -283,6 +260,72 @@ export class MoveLinesCommand implements ICommand {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param model
|
||||
* @param indentConverter
|
||||
* @param tabSize
|
||||
* @param line the line moving down
|
||||
* @param futureAboveLineNumber the line which will be at the `line` position
|
||||
* @param futureAboveLineText
|
||||
*/
|
||||
private matchEnterRuleMovingDown(model: ITextModel, indentConverter: IIndentConverter, tabSize: number, line: number, futureAboveLineNumber: number, futureAboveLineText: string) {
|
||||
if (strings.lastNonWhitespaceIndex(futureAboveLineText) >= 0) {
|
||||
// break
|
||||
let maxColumn = model.getLineMaxColumn(futureAboveLineNumber);
|
||||
let enter = LanguageConfigurationRegistry.getEnterAction(this._autoIndent, model, new Range(futureAboveLineNumber, maxColumn, futureAboveLineNumber, maxColumn));
|
||||
return this.parseEnterResult(model, indentConverter, tabSize, line, enter);
|
||||
} else {
|
||||
// go upwards, starting from `line - 1`
|
||||
let validPrecedingLine = line - 1;
|
||||
while (validPrecedingLine >= 1) {
|
||||
let lineContent = model.getLineContent(validPrecedingLine);
|
||||
let nonWhitespaceIdx = strings.lastNonWhitespaceIndex(lineContent);
|
||||
|
||||
if (nonWhitespaceIdx >= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
validPrecedingLine--;
|
||||
}
|
||||
|
||||
if (validPrecedingLine < 1 || line > model.getLineCount()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let maxColumn = model.getLineMaxColumn(validPrecedingLine);
|
||||
let enter = LanguageConfigurationRegistry.getEnterAction(this._autoIndent, model, new Range(validPrecedingLine, maxColumn, validPrecedingLine, maxColumn));
|
||||
return this.parseEnterResult(model, indentConverter, tabSize, line, enter);
|
||||
}
|
||||
}
|
||||
|
||||
private matchEnterRule(model: ITextModel, indentConverter: IIndentConverter, tabSize: number, line: number, oneLineAbove: number, oneLineAboveText?: string) {
|
||||
let validPrecedingLine = oneLineAbove;
|
||||
while (validPrecedingLine >= 1) {
|
||||
// ship empty lines as empty lines just inherit indentation
|
||||
let lineContent;
|
||||
if (validPrecedingLine === oneLineAbove && oneLineAboveText !== undefined) {
|
||||
lineContent = oneLineAboveText;
|
||||
} else {
|
||||
lineContent = model.getLineContent(validPrecedingLine);
|
||||
}
|
||||
|
||||
let nonWhitespaceIdx = strings.lastNonWhitespaceIndex(lineContent);
|
||||
if (nonWhitespaceIdx >= 0) {
|
||||
break;
|
||||
}
|
||||
validPrecedingLine--;
|
||||
}
|
||||
|
||||
if (validPrecedingLine < 1 || line > model.getLineCount()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let maxColumn = model.getLineMaxColumn(validPrecedingLine);
|
||||
let enter = LanguageConfigurationRegistry.getEnterAction(this._autoIndent, model, new Range(validPrecedingLine, maxColumn, validPrecedingLine, maxColumn));
|
||||
return this.parseEnterResult(model, indentConverter, tabSize, line, enter);
|
||||
}
|
||||
|
||||
private trimLeft(str: string) {
|
||||
return str.replace(/^\s+/, '');
|
||||
}
|
||||
|
||||
@@ -329,6 +329,7 @@ suite('Editor contrib - Move Lines Command honors Indentation Rules', () => {
|
||||
mode.dispose();
|
||||
});
|
||||
|
||||
|
||||
test('move line should still work as before if there is no indentation rules', () => {
|
||||
testMoveLinesUpWithIndentCommand(
|
||||
null!,
|
||||
@@ -351,3 +352,55 @@ suite('Editor contrib - Move Lines Command honors Indentation Rules', () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
class EnterRulesMode extends MockMode {
|
||||
private static readonly _id = new LanguageIdentifier('moveLinesEnterMode', 8);
|
||||
constructor() {
|
||||
super(EnterRulesMode._id);
|
||||
this._register(LanguageConfigurationRegistry.register(this.getLanguageIdentifier(), {
|
||||
indentationRules: {
|
||||
decreaseIndentPattern: /^\s*\[$/,
|
||||
increaseIndentPattern: /^\s*\]$/,
|
||||
},
|
||||
brackets: [
|
||||
['{', '}']
|
||||
]
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
suite('Editor - contrib - Move Lines Command honors onEnter Rules', () => {
|
||||
|
||||
test('issue #54829. move block across block', () => {
|
||||
let mode = new EnterRulesMode();
|
||||
|
||||
testMoveLinesDownWithIndentCommand(
|
||||
mode.getLanguageIdentifier(),
|
||||
|
||||
[
|
||||
'if (true) {',
|
||||
' if (false) {',
|
||||
' if (1) {',
|
||||
' console.log(\'b\');',
|
||||
' }',
|
||||
' console.log(\'a\');',
|
||||
' }',
|
||||
'}'
|
||||
],
|
||||
new Selection(3, 9, 5, 10),
|
||||
[
|
||||
'if (true) {',
|
||||
' if (false) {',
|
||||
' console.log(\'a\');',
|
||||
' if (1) {',
|
||||
' console.log(\'b\');',
|
||||
' }',
|
||||
' }',
|
||||
'}'
|
||||
],
|
||||
new Selection(4, 9, 6, 10),
|
||||
);
|
||||
|
||||
mode.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user