Merge branch 'main' into local-quail

This commit is contained in:
Aiday Marlen Kyzy
2024-03-21 17:44:31 +01:00
5 changed files with 82 additions and 47 deletions
@@ -732,6 +732,8 @@ suite('`Full` Auto Indent On Type - TypeScript/JavaScript', () => {
// issue: Should indent after an equal sign is detected followed by whitespace characters.
// This should be outdented when a semi-colon is detected indicating the end of the assignment.
// TODO: requires exploring indent/outdent pairs instead
const model = createTextModel([
'const array ='
].join('\n'), languageId, {});
@@ -753,6 +755,8 @@ suite('`Full` Auto Indent On Type - TypeScript/JavaScript', () => {
// https://github.com/microsoft/vscode/issues/43244
// issue: When a dot is written, we should detect that this is a method call and indent accordingly
// TODO: requires exploring indent/outdent pairs instead
const model = createTextModel([
'const array = [1, 2, 3];',
'array.'
@@ -776,6 +780,8 @@ suite('`Full` Auto Indent On Type - TypeScript/JavaScript', () => {
// https://github.com/microsoft/vscode/issues/43244
// issue: When a dot is written, we should detect that this is a method call and indent accordingly
// TODO: requires exploring indent/outdent pairs instead
const model = createTextModel([
'const array = [1, 2, 3]',
].join('\n'), languageId, {});
@@ -798,6 +804,8 @@ suite('`Full` Auto Indent On Type - TypeScript/JavaScript', () => {
// https://github.com/microsoft/vscode/issues/43244
// Currently passes, but should pass with all the tests above too
// TODO: requires exploring indent/outdent pairs instead
const model = createTextModel([
'const array = [1, 2, 3]',
' .filter(() => true)'
@@ -816,10 +824,38 @@ suite('`Full` Auto Indent On Type - TypeScript/JavaScript', () => {
});
});
test.skip('issue #43244: keep indentation when chained methods called on object/array', () => {
// https://github.com/microsoft/vscode/issues/43244
// When the call chain is not finished yet, and we type a dot, we do not want to change the indentation
// TODO: requires exploring indent/outdent pairs instead
const model = createTextModel([
'const array = [1, 2, 3]',
' .filter(() => true)',
' '
].join('\n'), languageId, {});
disposables.add(model);
withTestCodeEditor(model, { autoIndent: "full" }, (editor, viewModel, instantiationService) => {
registerLanguage(instantiationService, languageId, Language.TypeScript, disposables);
editor.setSelection(new Selection(3, 5, 3, 5));
viewModel.type(".");
assert.strictEqual(model.getValue(), [
'const array = [1, 2, 3]',
' .filter(() => true)',
' .' // here we don't want to increase the indentation because we have chained methods
].join('\n'));
});
});
test.skip('issue #43244: outdent when a semi-color is detected indicating the end of the assignment', () => {
// https://github.com/microsoft/vscode/issues/43244
// TODO: requires exploring indent/outdent pairs instead
const model = createTextModel([
'const array = [1, 2, 3]',
' .filter(() => true);'
@@ -844,17 +880,17 @@ suite('`Full` Auto Indent On Type - TypeScript/JavaScript', () => {
const model = createTextModel([
'const array = [1, 2, 3, 4, 5];',
'array.map(v =>)'
'array.map(_)'
].join('\n'), languageId, {});
disposables.add(model);
withTestCodeEditor(model, { autoIndent: "full" }, (editor, viewModel, instantiationService) => {
registerLanguage(instantiationService, languageId, Language.TypeScript, disposables);
editor.setSelection(new Selection(2, 15, 2, 15));
editor.setSelection(new Selection(2, 12, 2, 12));
viewModel.type("\n", 'keyboard');
assert.strictEqual(model.getValue(), [
'const array = [1, 2, 3, 4, 5];',
'array.map(v =>',
'array.map(_',
' ',
')'
].join('\n'));
+25 -24
View File
@@ -38,7 +38,7 @@ import { INotificationService } from 'vs/platform/notification/common/notificati
import { IEditorProgressService } from 'vs/platform/progress/common/progress';
import { Registry } from 'vs/platform/registry/common/platform';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { CONTEXT_RENAME_INPUT_VISIBLE, NewNameSource, RenameInputFieldResult, RenameWidget } from './renameInputField';
import { CONTEXT_RENAME_INPUT_VISIBLE, NewNameSource, RenameWidget, RenameWidgetResult } from './renameWidget';
class RenameSkeleton {
@@ -138,7 +138,7 @@ class RenameController implements IEditorContribution {
return editor.getContribution<RenameController>(RenameController.ID);
}
private readonly _renameInputField: RenameWidget;
private readonly _renameWidget: RenameWidget;
private readonly _disposableStore = new DisposableStore();
private _cts: CancellationTokenSource = new CancellationTokenSource();
@@ -153,7 +153,7 @@ class RenameController implements IEditorContribution {
@ILanguageFeaturesService private readonly _languageFeaturesService: ILanguageFeaturesService,
@ITelemetryService private readonly _telemetryService: ITelemetryService,
) {
this._renameInputField = this._disposableStore.add(this._instaService.createInstance(RenameWidget, this.editor, ['acceptRenameInput', 'acceptRenameInputWithPreview']));
this._renameWidget = this._disposableStore.add(this._instaService.createInstance(RenameWidget, this.editor, ['acceptRenameInput', 'acceptRenameInputWithPreview']));
}
dispose(): void {
@@ -235,7 +235,7 @@ class RenameController implements IEditorContribution {
trace('creating rename input field and awaiting its result');
const supportPreview = this._bulkEditService.hasPreviewHandler() && this._configService.getValue<boolean>(this.editor.getModel().uri, 'editor.rename.enablePreview');
const inputFieldResult = await this._renameInputField.getInput(
const inputFieldResult = await this._renameWidget.getInput(
loc.range,
loc.text,
supportPreview,
@@ -321,22 +321,22 @@ class RenameController implements IEditorContribution {
}
acceptRenameInput(wantsPreview: boolean): void {
this._renameInputField.acceptInput(wantsPreview);
this._renameWidget.acceptInput(wantsPreview);
}
cancelRenameInput(): void {
this._renameInputField.cancelInput(true, 'cancelRenameInput command');
this._renameWidget.cancelInput(true, 'cancelRenameInput command');
}
focusNextRenameSuggestion(): void {
this._renameInputField.focusNextRenameSuggestion();
this._renameWidget.focusNextRenameSuggestion();
}
focusPreviousRenameSuggestion(): void {
this._renameInputField.focusPreviousRenameSuggestion();
this._renameWidget.focusPreviousRenameSuggestion();
}
private _reportTelemetry(nRenameSuggestionProviders: number, languageId: string, inputFieldResult: boolean | RenameInputFieldResult, inDebugMode?: 'inDebugMode') {
private _reportTelemetry(nRenameSuggestionProviders: number, languageId: string, inputFieldResult: boolean | RenameWidgetResult, inDebugMode?: 'inDebugMode') {
type RenameInvokedEvent =
{
kind: 'accepted' | 'cancelled';
@@ -367,22 +367,23 @@ class RenameController implements IEditorContribution {
wantsPreview?: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'If user wanted preview.'; isMeasurement: true };
};
const value: RenameInvokedEvent = typeof inputFieldResult === 'boolean'
? {
kind: 'cancelled',
languageId,
nRenameSuggestionProviders,
}
: {
kind: 'accepted',
languageId,
nRenameSuggestionProviders,
const value: RenameInvokedEvent =
typeof inputFieldResult === 'boolean'
? {
kind: 'cancelled',
languageId,
nRenameSuggestionProviders,
}
: {
kind: 'accepted',
languageId,
nRenameSuggestionProviders,
source: inputFieldResult.stats.source.k,
nRenameSuggestions: inputFieldResult.stats.nRenameSuggestions,
timeBeforeFirstInputFieldEdit: inputFieldResult.stats.timeBeforeFirstInputFieldEdit,
wantsPreview: inputFieldResult.wantsPreview,
};
source: inputFieldResult.stats.source.k,
nRenameSuggestions: inputFieldResult.stats.nRenameSuggestions,
timeBeforeFirstInputFieldEdit: inputFieldResult.stats.timeBeforeFirstInputFieldEdit,
wantsPreview: inputFieldResult.wantsPreview,
};
if (inDebugMode) {
this._telemetryService.publicLog2<RenameInvokedEvent, RenameInvokedClassification>('renameInvokedEventDebug', value);
@@ -16,7 +16,7 @@ import { Emitter } from 'vs/base/common/event';
import { DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { StopWatch } from 'vs/base/common/stopwatch';
import { assertType, isDefined } from 'vs/base/common/types';
import 'vs/css!./renameInputField';
import 'vs/css!./renameWidget';
import { applyFontInfo } from 'vs/editor/browser/config/domFontInfo';
import { ContentWidgetPositionPreference, ICodeEditor, IContentWidget, IContentWidgetPosition } from 'vs/editor/browser/editorBrowser';
import { EditorOption } from 'vs/editor/common/config/editorOptions';
@@ -66,24 +66,24 @@ export type NewNameSource =
/**
* Various statistics regarding rename input field
*/
export type RenameInputFieldStats = {
export type RenameWidgetStats = {
nRenameSuggestions: number;
source: NewNameSource;
timeBeforeFirstInputFieldEdit: number | undefined;
};
export type RenameInputFieldResult = {
export type RenameWidgetResult = {
/**
* The new name to be used
*/
newName: string;
wantsPreview?: boolean;
stats: RenameInputFieldStats;
stats: RenameWidgetStats;
};
interface IRenameInputField {
interface IRenameWidget {
/**
* @returns a `boolean` standing for `shouldFocusEditor`, if user didn't pick a new name, or a {@link RenameInputFieldResult}
* @returns a `boolean` standing for `shouldFocusEditor`, if user didn't pick a new name, or a {@link RenameWidgetResult}
*/
getInput(
where: IRange,
@@ -91,7 +91,7 @@ interface IRenameInputField {
supportPreview: boolean,
requestRenameSuggestions: (cts: CancellationToken) => ProviderResult<NewSymbolName[]>[],
cts: CancellationTokenSource
): Promise<RenameInputFieldResult | boolean>;
): Promise<RenameWidgetResult | boolean>;
acceptInput(wantsPreview: boolean): void;
cancelInput(focusEditor: boolean, caller: string): void;
@@ -100,7 +100,7 @@ interface IRenameInputField {
focusPreviousRenameSuggestion(): void;
}
export class RenameWidget implements IRenameInputField, IContentWidget, IDisposable {
export class RenameWidget implements IRenameWidget, IContentWidget, IDisposable {
// implement IContentWidget
readonly allowEditorOverflow: boolean = true;
@@ -243,7 +243,7 @@ export class RenameWidget implements IRenameInputField, IContentWidget, IDisposa
if (this._domNode === undefined) {
return;
}
assertType(this._label !== undefined, 'RenameInputField#_updateFont: _label must not be undefined given _domNode is defined');
assertType(this._label !== undefined, 'RenameWidget#_updateFont: _label must not be undefined given _domNode is defined');
this._editor.applyFontInfo(this._input.domNode);
@@ -361,14 +361,14 @@ export class RenameWidget implements IRenameInputField, IContentWidget, IDisposa
where: IRange,
currentName: string,
supportPreview: boolean,
requestRenameSuggestions: (cts: CancellationToken) => ProviderResult<NewSymbolName[]>[],
requestRenameCandidates: (cts: CancellationToken) => ProviderResult<NewSymbolName[]>[],
cts: CancellationTokenSource
): Promise<RenameInputFieldResult | boolean> {
): Promise<RenameWidgetResult | boolean> {
const { start: selectionStart, end: selectionEnd } = this._getSelection(where, currentName);
this._renameCandidateProvidersCts = new CancellationTokenSource();
const candidates = requestRenameSuggestions(this._renameCandidateProvidersCts.token);
const candidates = requestRenameCandidates(this._renameCandidateProvidersCts.token);
this._updateRenameCandidates(candidates, currentName, cts.token);
this._isEditingRenameCandidate = false;
@@ -395,7 +395,7 @@ export class RenameWidget implements IRenameInputField, IContentWidget, IDisposa
}
}));
const inputResult = new DeferredPromise<RenameInputFieldResult | boolean>();
const inputResult = new DeferredPromise<RenameWidgetResult | boolean>();
inputResult.p.finally(() => {
disposeOnDone.dispose();
@@ -547,7 +547,7 @@ export class RenameWidget implements IRenameInputField, IContentWidget, IDisposa
if (visibleRanges.length > 0) {
firstLineInViewport = visibleRanges[0].startLineNumber;
} else {
this._logService.warn('RenameInputField#_getTopForPosition: this should not happen - visibleRanges is empty');
this._logService.warn('RenameWidget#_getTopForPosition: this should not happen - visibleRanges is empty');
firstLineInViewport = Math.max(1, this._position!.lineNumber - 5); // @ulugbekna: fallback to current line minus 5
}
return this._editor.getTopForLineNumber(this._position!.lineNumber) - this._editor.getTopForLineNumber(firstLineInViewport);
@@ -190,7 +190,7 @@ suite('Auto-Reindentation - TypeScript/JavaScript', () => {
// explanation: if (, [, {, is followed by a forward slash then assume we are in a regex pattern, and do not indent
// increaseIndentPattern: /^((?!\/\/).)*(\{([^}"'`]*|(\t|[ ])*\/\/.*)|\([^)"'`]*|\[[^\]"'`]*)$/ -> /^((?!\/\/).)*(\{([^}"'`/]*|(\t|[ ])*\/\/.*)|\([^)"'`/]*|\[[^\]"'`/]*)$/
// -> Final current increase indent pattern
// -> Final current increase indent pattern at of writing
const fileContents = [
'const r = /{/;',
@@ -214,7 +214,7 @@ suite('Auto-Reindentation - TypeScript/JavaScript', () => {
// fix: https://github.com/microsoft/vscode/commit/7910b3d7bab8a721aae98dc05af0b5e1ea9d9782
// decreaseIndentPattern: /^(.*\*\/)?\s*[\}\]\)].*$/ -> /^((?!.*?\/\*).*\*\/)?\s*[\}\]\)].*$/
// -> Final current decrease indent pattern
// -> Final current decrease indent pattern at the time of writing
// explanation: Positive lookahead: (?= «pattern») matches if pattern matches what comes after the current location in the input string.
// Negative lookahead: (?! «pattern») matches if pattern does not match what comes after the current location in the input string
@@ -282,10 +282,8 @@ suite('Auto-Reindentation - TypeScript/JavaScript', () => {
// related: https://github.com/microsoft/vscode/issues/43244
// explanation: When you have an arrow function, you don't have { or }, but you would expect indentation to still be done in that way
/*
Notes: Currently the reindent edit operations does not call the onEnter rules
The reindent should also call the onEnter rules to get the correct indentation
*/
// TODO: requires exploring indent/outdent pairs instead
const fileContents = [
'const add1 = (n) =>',
' n + 1;',