mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-02 01:25:39 -05:00
Merge from vscode 1ce89e2cb720d69c496c2815c4696ee4fd4429a6 (#6779)
* Merge from vscode 1ce89e2cb720d69c496c2815c4696ee4fd4429a6 * redisable accounts because of issues
This commit is contained in:
@@ -13,7 +13,7 @@ import { IPosition, Position } from 'vs/editor/common/core/position';
|
||||
import { IRange, Range } from 'vs/editor/common/core/range';
|
||||
import { Selection } from 'vs/editor/common/core/selection';
|
||||
import * as editorCommon from 'vs/editor/common/editorCommon';
|
||||
import { IIdentifiedSingleEditOperation, IModelDecoration, IModelDeltaDecoration, ITextModel } from 'vs/editor/common/model';
|
||||
import { IIdentifiedSingleEditOperation, IModelDecoration, IModelDeltaDecoration, ITextModel, ICursorStateComputer } from 'vs/editor/common/model';
|
||||
import { IModelContentChangedEvent, IModelDecorationsChangedEvent, IModelLanguageChangedEvent, IModelLanguageConfigurationChangedEvent, IModelOptionsChangedEvent } from 'vs/editor/common/model/textModelEvents';
|
||||
import { OverviewRulerZone } from 'vs/editor/common/view/overviewZoneManager';
|
||||
import { IEditorWhitespace } from 'vs/editor/common/viewLayout/whitespaceComputer';
|
||||
@@ -612,7 +612,7 @@ export interface ICodeEditor extends editorCommon.IEditor {
|
||||
* @param edits The edits to execute.
|
||||
* @param endCursorState Cursor state after the edits were applied.
|
||||
*/
|
||||
executeEdits(source: string, edits: IIdentifiedSingleEditOperation[], endCursorState?: Selection[]): boolean;
|
||||
executeEdits(source: string, edits: IIdentifiedSingleEditOperation[], endCursorState?: ICursorStateComputer | Selection[]): boolean;
|
||||
|
||||
/**
|
||||
* Execute multiple (concomitant) commands on the editor.
|
||||
|
||||
@@ -33,7 +33,7 @@ import { ISelection, Selection } from 'vs/editor/common/core/selection';
|
||||
import { InternalEditorAction } from 'vs/editor/common/editorAction';
|
||||
import * as editorCommon from 'vs/editor/common/editorCommon';
|
||||
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
|
||||
import { EndOfLinePreference, IIdentifiedSingleEditOperation, IModelDecoration, IModelDecorationOptions, IModelDecorationsChangeAccessor, IModelDeltaDecoration, ITextModel } from 'vs/editor/common/model';
|
||||
import { EndOfLinePreference, IIdentifiedSingleEditOperation, IModelDecoration, IModelDecorationOptions, IModelDecorationsChangeAccessor, IModelDeltaDecoration, ITextModel, ICursorStateComputer } from 'vs/editor/common/model';
|
||||
import { ClassName } from 'vs/editor/common/model/intervalTree';
|
||||
import { ModelDecorationOptions } from 'vs/editor/common/model/textModel';
|
||||
import { IModelContentChangedEvent, IModelDecorationsChangedEvent, IModelLanguageChangedEvent, IModelLanguageConfigurationChangedEvent, IModelOptionsChangedEvent } from 'vs/editor/common/model/textModelEvents';
|
||||
@@ -980,7 +980,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
|
||||
return true;
|
||||
}
|
||||
|
||||
public executeEdits(source: string, edits: IIdentifiedSingleEditOperation[], endCursorState?: Selection[]): boolean {
|
||||
public executeEdits(source: string, edits: IIdentifiedSingleEditOperation[], endCursorState?: ICursorStateComputer | Selection[]): boolean {
|
||||
if (!this._modelData) {
|
||||
return false;
|
||||
}
|
||||
@@ -989,14 +989,16 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
|
||||
return false;
|
||||
}
|
||||
|
||||
this._modelData.model.pushEditOperations(this._modelData.cursor.getSelections(), edits, () => {
|
||||
return endCursorState ? endCursorState : null;
|
||||
});
|
||||
|
||||
if (endCursorState) {
|
||||
this._modelData.cursor.setSelections(source, endCursorState);
|
||||
let cursorStateComputer: ICursorStateComputer;
|
||||
if (!endCursorState) {
|
||||
cursorStateComputer = () => null;
|
||||
} else if (Array.isArray(endCursorState)) {
|
||||
cursorStateComputer = () => endCursorState;
|
||||
} else {
|
||||
cursorStateComputer = endCursorState;
|
||||
}
|
||||
|
||||
this._modelData.cursor.executeEdits(source, edits, cursorStateComputer);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import { Position } from 'vs/editor/common/core/position';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { ISelection, Selection, SelectionDirection } from 'vs/editor/common/core/selection';
|
||||
import * as editorCommon from 'vs/editor/common/editorCommon';
|
||||
import { IIdentifiedSingleEditOperation, ITextModel, TrackedRangeStickiness, IModelDeltaDecoration } from 'vs/editor/common/model';
|
||||
import { IIdentifiedSingleEditOperation, ITextModel, TrackedRangeStickiness, IModelDeltaDecoration, ICursorStateComputer } from 'vs/editor/common/model';
|
||||
import { RawContentChangedType } from 'vs/editor/common/model/textModelEvents';
|
||||
import * as viewEvents from 'vs/editor/common/view/viewEvents';
|
||||
import { IViewModel } from 'vs/editor/common/viewModel/viewModel';
|
||||
@@ -429,6 +429,31 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors {
|
||||
|
||||
// ------ auxiliary handling logic
|
||||
|
||||
private _pushAutoClosedAction(autoClosedCharactersRanges: Range[], autoClosedEnclosingRanges: Range[]): void {
|
||||
let autoClosedCharactersDeltaDecorations: IModelDeltaDecoration[] = [];
|
||||
let autoClosedEnclosingDeltaDecorations: IModelDeltaDecoration[] = [];
|
||||
|
||||
for (let i = 0, len = autoClosedCharactersRanges.length; i < len; i++) {
|
||||
autoClosedCharactersDeltaDecorations.push({
|
||||
range: autoClosedCharactersRanges[i],
|
||||
options: {
|
||||
inlineClassName: 'auto-closed-character',
|
||||
stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges
|
||||
}
|
||||
});
|
||||
autoClosedEnclosingDeltaDecorations.push({
|
||||
range: autoClosedEnclosingRanges[i],
|
||||
options: {
|
||||
stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const autoClosedCharactersDecorations = this._model.deltaDecorations([], autoClosedCharactersDeltaDecorations);
|
||||
const autoClosedEnclosingDecorations = this._model.deltaDecorations([], autoClosedEnclosingDeltaDecorations);
|
||||
this._autoClosedActions.push(new AutoClosedAction(this._model, autoClosedCharactersDecorations, autoClosedEnclosingDecorations));
|
||||
}
|
||||
|
||||
private _executeEditOperation(opResult: EditOperationResult | null): void {
|
||||
|
||||
if (!opResult) {
|
||||
@@ -446,32 +471,19 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors {
|
||||
this._interpretCommandResult(result);
|
||||
|
||||
// Check for auto-closing closed characters
|
||||
let autoClosedCharactersRanges: IModelDeltaDecoration[] = [];
|
||||
let autoClosedEnclosingRanges: IModelDeltaDecoration[] = [];
|
||||
let autoClosedCharactersRanges: Range[] = [];
|
||||
let autoClosedEnclosingRanges: Range[] = [];
|
||||
|
||||
for (let i = 0; i < opResult.commands.length; i++) {
|
||||
const command = opResult.commands[i];
|
||||
if (command instanceof TypeWithAutoClosingCommand && command.enclosingRange && command.closeCharacterRange) {
|
||||
autoClosedCharactersRanges.push({
|
||||
range: command.closeCharacterRange,
|
||||
options: {
|
||||
inlineClassName: 'auto-closed-character',
|
||||
stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges
|
||||
}
|
||||
});
|
||||
autoClosedEnclosingRanges.push({
|
||||
range: command.enclosingRange,
|
||||
options: {
|
||||
stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges
|
||||
}
|
||||
});
|
||||
autoClosedCharactersRanges.push(command.closeCharacterRange);
|
||||
autoClosedEnclosingRanges.push(command.enclosingRange);
|
||||
}
|
||||
}
|
||||
|
||||
if (autoClosedCharactersRanges.length > 0) {
|
||||
const autoClosedCharactersDecorations = this._model.deltaDecorations([], autoClosedCharactersRanges);
|
||||
const autoClosedEnclosingDecorations = this._model.deltaDecorations([], autoClosedEnclosingRanges);
|
||||
this._autoClosedActions.push(new AutoClosedAction(this._model, autoClosedCharactersDecorations, autoClosedEnclosingDecorations));
|
||||
this._pushAutoClosedAction(autoClosedCharactersRanges, autoClosedEnclosingRanges);
|
||||
}
|
||||
|
||||
this._prevEditOperationType = opResult.type;
|
||||
@@ -563,6 +575,75 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors {
|
||||
// -----------------------------------------------------------------------------------------------------------
|
||||
// ----- handlers beyond this point
|
||||
|
||||
private _findAutoClosingPairs(edits: IIdentifiedSingleEditOperation[]): [number, number][] | null {
|
||||
if (!edits.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let indices: [number, number][] = [];
|
||||
for (let i = 0, len = edits.length; i < len; i++) {
|
||||
const edit = edits[i];
|
||||
if (!edit.text || edit.text.indexOf('\n') >= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const m = edit.text.match(/([)\]}>'"`])([^)\]}>'"`]*)$/);
|
||||
if (!m) {
|
||||
return null;
|
||||
}
|
||||
const closeChar = m[1];
|
||||
|
||||
const openChar = this.context.config.autoClosingPairsClose[closeChar];
|
||||
if (!openChar) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const closeCharIndex = edit.text.length - m[2].length - 1;
|
||||
const openCharIndex = edit.text.lastIndexOf(openChar, closeCharIndex - 1);
|
||||
if (openCharIndex === -1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
indices.push([openCharIndex, closeCharIndex]);
|
||||
}
|
||||
|
||||
return indices;
|
||||
}
|
||||
|
||||
public executeEdits(source: string, edits: IIdentifiedSingleEditOperation[], cursorStateComputer: ICursorStateComputer): void {
|
||||
let autoClosingIndices: [number, number][] | null = null;
|
||||
if (source === 'snippet') {
|
||||
autoClosingIndices = this._findAutoClosingPairs(edits);
|
||||
}
|
||||
|
||||
if (autoClosingIndices) {
|
||||
edits[0]._isTracked = true;
|
||||
}
|
||||
let autoClosedCharactersRanges: Range[] = [];
|
||||
let autoClosedEnclosingRanges: Range[] = [];
|
||||
const selections = this._model.pushEditOperations(this.getSelections(), edits, (undoEdits) => {
|
||||
if (autoClosingIndices) {
|
||||
for (let i = 0, len = autoClosingIndices.length; i < len; i++) {
|
||||
const [openCharInnerIndex, closeCharInnerIndex] = autoClosingIndices[i];
|
||||
const undoEdit = undoEdits[i];
|
||||
const lineNumber = undoEdit.range.startLineNumber;
|
||||
const openCharIndex = undoEdit.range.startColumn - 1 + openCharInnerIndex;
|
||||
const closeCharIndex = undoEdit.range.startColumn - 1 + closeCharInnerIndex;
|
||||
|
||||
autoClosedCharactersRanges.push(new Range(lineNumber, closeCharIndex + 1, lineNumber, closeCharIndex + 2));
|
||||
autoClosedEnclosingRanges.push(new Range(lineNumber, openCharIndex + 1, lineNumber, closeCharIndex + 2));
|
||||
}
|
||||
}
|
||||
return cursorStateComputer(undoEdits);
|
||||
});
|
||||
if (selections) {
|
||||
this.setSelections(source, selections);
|
||||
}
|
||||
if (autoClosedCharactersRanges.length > 0) {
|
||||
this._pushAutoClosedAction(autoClosedCharactersRanges, autoClosedEnclosingRanges);
|
||||
}
|
||||
}
|
||||
|
||||
public trigger(source: string, handlerId: string, payload: any): void {
|
||||
const H = editorCommon.Handler;
|
||||
|
||||
|
||||
@@ -489,21 +489,18 @@ export class SnippetSession {
|
||||
return;
|
||||
}
|
||||
|
||||
const model = this._editor.getModel();
|
||||
|
||||
// make insert edit and start with first selections
|
||||
const { edits, snippets } = SnippetSession.createEditsAndSnippets(this._editor, this._template, this._options.overwriteBefore, this._options.overwriteAfter, false, this._options.adjustWhitespace, this._options.clipboardText);
|
||||
this._snippets = snippets;
|
||||
|
||||
const selections = model.pushEditOperations(this._editor.getSelections(), edits, undoEdits => {
|
||||
this._editor.executeEdits('snippet', edits, undoEdits => {
|
||||
if (this._snippets[0].hasPlaceholder) {
|
||||
return this._move(true);
|
||||
} else {
|
||||
return undoEdits.map(edit => Selection.fromPositions(edit.range.getEndPosition()));
|
||||
}
|
||||
})!;
|
||||
this._editor.setSelections(selections);
|
||||
this._editor.revealRange(selections[0]);
|
||||
});
|
||||
this._editor.revealRange(this._editor.getSelections()[0]);
|
||||
}
|
||||
|
||||
merge(template: string, options: ISnippetSessionInsertOptions = _defaultOptions): void {
|
||||
@@ -513,8 +510,7 @@ export class SnippetSession {
|
||||
this._templateMerges.push([this._snippets[0]._nestingLevel, this._snippets[0]._placeholderGroupsIdx, template]);
|
||||
const { edits, snippets } = SnippetSession.createEditsAndSnippets(this._editor, template, options.overwriteBefore, options.overwriteAfter, true, options.adjustWhitespace, options.clipboardText);
|
||||
|
||||
this._editor.setSelections(this._editor.getModel().pushEditOperations(this._editor.getSelections(), edits, undoEdits => {
|
||||
|
||||
this._editor.executeEdits('snippet', edits, undoEdits => {
|
||||
for (const snippet of this._snippets) {
|
||||
snippet.merge(snippets);
|
||||
}
|
||||
@@ -525,7 +521,7 @@ export class SnippetSession {
|
||||
} else {
|
||||
return undoEdits.map(edit => Selection.fromPositions(edit.range.getEndPosition()));
|
||||
}
|
||||
})!);
|
||||
});
|
||||
}
|
||||
|
||||
next(): void {
|
||||
|
||||
@@ -4692,6 +4692,28 @@ suite('autoClosingPairs', () => {
|
||||
mode.dispose();
|
||||
});
|
||||
|
||||
test('issue #78975 - Parentheses swallowing does not work when parentheses are inserted by autocomplete', () => {
|
||||
let mode = new AutoClosingMode();
|
||||
usingCursor({
|
||||
text: [
|
||||
'<div id'
|
||||
],
|
||||
languageIdentifier: mode.getLanguageIdentifier()
|
||||
}, (model, cursor) => {
|
||||
cursor.setSelections('test', [new Selection(1, 8, 1, 8)]);
|
||||
|
||||
cursor.executeEdits('snippet', [{ range: new Range(1, 6, 1, 8), text: 'id=""' }], () => [new Selection(1, 10, 1, 10)]);
|
||||
assert.strictEqual(model.getLineContent(1), '<div id=""');
|
||||
|
||||
cursorCommand(cursor, H.Type, { text: 'a' }, 'keyboard');
|
||||
assert.strictEqual(model.getLineContent(1), '<div id="a"');
|
||||
|
||||
cursorCommand(cursor, H.Type, { text: '"' }, 'keyboard');
|
||||
assert.strictEqual(model.getLineContent(1), '<div id="a"');
|
||||
});
|
||||
mode.dispose();
|
||||
});
|
||||
|
||||
test('issue #15825: accents on mac US intl keyboard', () => {
|
||||
let mode = new AutoClosingMode();
|
||||
usingCursor({
|
||||
|
||||
Reference in New Issue
Block a user