mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
Merge from vscode f5044f0910e4aa7e7e06cb509781f3d56e729959 (#4759)
This commit is contained in:
@@ -23,8 +23,8 @@ import { FormattingEdit } from 'vs/editor/contrib/format/formattingEdit';
|
|||||||
import * as nls from 'vs/nls';
|
import * as nls from 'vs/nls';
|
||||||
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
import { IStatusbarService } from 'vs/platform/statusbar/common/statusbar';
|
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||||
import { ILabelService } from 'vs/platform/label/common/label';
|
import { LinkedList } from 'vs/base/common/linkedList';
|
||||||
|
|
||||||
export function alertFormattingEdits(edits: ISingleEditOperation[]): void {
|
export function alertFormattingEdits(edits: ISingleEditOperation[]): void {
|
||||||
|
|
||||||
@@ -86,30 +86,51 @@ export function getRealAndSyntheticDocumentFormattersOrdered(model: ITextModel):
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function formatDocumentRangeWithFirstProvider(
|
export const enum FormattingMode {
|
||||||
|
Explicit = 1,
|
||||||
|
Silent = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IFormattingEditProviderSelector {
|
||||||
|
<T extends (DocumentFormattingEditProvider | DocumentRangeFormattingEditProvider)>(formatter: T[], document: ITextModel, mode: FormattingMode): Promise<T | undefined>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export abstract class FormattingConflicts {
|
||||||
|
|
||||||
|
private static readonly _selectors = new LinkedList<IFormattingEditProviderSelector>();
|
||||||
|
|
||||||
|
static setFormatterSelector(selector: IFormattingEditProviderSelector): IDisposable {
|
||||||
|
const remove = FormattingConflicts._selectors.unshift(selector);
|
||||||
|
return { dispose: remove };
|
||||||
|
}
|
||||||
|
|
||||||
|
static async select<T extends (DocumentFormattingEditProvider | DocumentRangeFormattingEditProvider)>(formatter: T[], document: ITextModel, mode: FormattingMode): Promise<T | undefined> {
|
||||||
|
if (formatter.length === 0) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const { value: selector } = FormattingConflicts._selectors.iterator().next();
|
||||||
|
if (selector) {
|
||||||
|
return await selector(formatter, document, mode);
|
||||||
|
}
|
||||||
|
return formatter[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function formatDocumentRangeWithSelectedProvider(
|
||||||
accessor: ServicesAccessor,
|
accessor: ServicesAccessor,
|
||||||
editorOrModel: ITextModel | IActiveCodeEditor,
|
editorOrModel: ITextModel | IActiveCodeEditor,
|
||||||
range: Range,
|
range: Range,
|
||||||
|
mode: FormattingMode,
|
||||||
token: CancellationToken
|
token: CancellationToken
|
||||||
): Promise<boolean> {
|
): Promise<void> {
|
||||||
|
|
||||||
const instaService = accessor.get(IInstantiationService);
|
const instaService = accessor.get(IInstantiationService);
|
||||||
const statusBarService = accessor.get(IStatusbarService);
|
|
||||||
const labelService = accessor.get(ILabelService);
|
|
||||||
|
|
||||||
const model = isCodeEditor(editorOrModel) ? editorOrModel.getModel() : editorOrModel;
|
const model = isCodeEditor(editorOrModel) ? editorOrModel.getModel() : editorOrModel;
|
||||||
const [best, ...rest] = DocumentRangeFormattingEditProviderRegistry.ordered(model);
|
const provider = DocumentRangeFormattingEditProviderRegistry.ordered(model);
|
||||||
if (!best) {
|
const selected = await FormattingConflicts.select(provider, model, mode);
|
||||||
return false;
|
if (selected) {
|
||||||
|
await instaService.invokeFunction(formatDocumentRangeWithProvider, selected, editorOrModel, range, token);
|
||||||
}
|
}
|
||||||
const ret = await instaService.invokeFunction(formatDocumentRangeWithProvider, best, editorOrModel, range, token);
|
|
||||||
if (rest.length > 0) {
|
|
||||||
statusBarService.setStatusMessage(
|
|
||||||
nls.localize('random.pick', "$(tasklist) Formatted '{0}' with '{1}'", labelService.getUriLabel(model.uri, { relative: true }), best.displayName),
|
|
||||||
5 * 1000
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function formatDocumentRangeWithProvider(
|
export async function formatDocumentRangeWithProvider(
|
||||||
@@ -181,29 +202,20 @@ export async function formatDocumentRangeWithProvider(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function formatDocumentWithFirstProvider(
|
export async function formatDocumentWithSelectedProvider(
|
||||||
accessor: ServicesAccessor,
|
accessor: ServicesAccessor,
|
||||||
editorOrModel: ITextModel | IActiveCodeEditor,
|
editorOrModel: ITextModel | IActiveCodeEditor,
|
||||||
|
mode: FormattingMode,
|
||||||
token: CancellationToken
|
token: CancellationToken
|
||||||
): Promise<boolean> {
|
): Promise<void> {
|
||||||
|
|
||||||
const instaService = accessor.get(IInstantiationService);
|
const instaService = accessor.get(IInstantiationService);
|
||||||
const statusBarService = accessor.get(IStatusbarService);
|
|
||||||
const labelService = accessor.get(ILabelService);
|
|
||||||
|
|
||||||
const model = isCodeEditor(editorOrModel) ? editorOrModel.getModel() : editorOrModel;
|
const model = isCodeEditor(editorOrModel) ? editorOrModel.getModel() : editorOrModel;
|
||||||
const [best, ...rest] = getRealAndSyntheticDocumentFormattersOrdered(model);
|
const provider = getRealAndSyntheticDocumentFormattersOrdered(model);
|
||||||
if (!best) {
|
const selected = await FormattingConflicts.select(provider, model, mode);
|
||||||
return false;
|
if (selected) {
|
||||||
|
await instaService.invokeFunction(formatDocumentWithProvider, selected, editorOrModel, token);
|
||||||
}
|
}
|
||||||
const ret = await instaService.invokeFunction(formatDocumentWithProvider, best, editorOrModel, token);
|
|
||||||
if (rest.length > 0) {
|
|
||||||
statusBarService.setStatusMessage(
|
|
||||||
nls.localize('random.pick', "$(tasklist) Formatted '{0}' with '{1}'", labelService.getUriLabel(model.uri, { relative: true }), best.displayName),
|
|
||||||
5 * 1000
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function formatDocumentWithProvider(
|
export async function formatDocumentWithProvider(
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import * as editorCommon from 'vs/editor/common/editorCommon';
|
|||||||
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
|
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
|
||||||
import { DocumentRangeFormattingEditProviderRegistry, OnTypeFormattingEditProviderRegistry } from 'vs/editor/common/modes';
|
import { DocumentRangeFormattingEditProviderRegistry, OnTypeFormattingEditProviderRegistry } from 'vs/editor/common/modes';
|
||||||
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService';
|
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService';
|
||||||
import { getOnTypeFormattingEdits, alertFormattingEdits, formatDocumentRangeWithFirstProvider, formatDocumentWithFirstProvider } from 'vs/editor/contrib/format/format';
|
import { getOnTypeFormattingEdits, alertFormattingEdits, formatDocumentRangeWithSelectedProvider, formatDocumentWithSelectedProvider, FormattingMode } from 'vs/editor/contrib/format/format';
|
||||||
import { FormattingEdit } from 'vs/editor/contrib/format/formattingEdit';
|
import { FormattingEdit } from 'vs/editor/contrib/format/formattingEdit';
|
||||||
import * as nls from 'vs/nls';
|
import * as nls from 'vs/nls';
|
||||||
import { CommandsRegistry, ICommandService } from 'vs/platform/commands/common/commands';
|
import { CommandsRegistry, ICommandService } from 'vs/platform/commands/common/commands';
|
||||||
@@ -211,7 +211,7 @@ class FormatOnPaste implements editorCommon.IEditorContribution {
|
|||||||
if (this.editor.getSelections().length > 1) {
|
if (this.editor.getSelections().length > 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._instantiationService.invokeFunction(formatDocumentRangeWithFirstProvider, this.editor, range, CancellationToken.None).catch(onUnexpectedError);
|
this._instantiationService.invokeFunction(formatDocumentRangeWithSelectedProvider, this.editor, range, FormattingMode.Silent, CancellationToken.None).catch(onUnexpectedError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -240,7 +240,7 @@ class FormatDocumentAction extends EditorAction {
|
|||||||
async run(accessor: ServicesAccessor, editor: ICodeEditor): Promise<void> {
|
async run(accessor: ServicesAccessor, editor: ICodeEditor): Promise<void> {
|
||||||
if (editor.hasModel()) {
|
if (editor.hasModel()) {
|
||||||
const instaService = accessor.get(IInstantiationService);
|
const instaService = accessor.get(IInstantiationService);
|
||||||
await instaService.invokeFunction(formatDocumentWithFirstProvider, editor, CancellationToken.None);
|
await instaService.invokeFunction(formatDocumentWithSelectedProvider, editor, FormattingMode.Explicit, CancellationToken.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -276,7 +276,7 @@ class FormatSelectionAction extends EditorAction {
|
|||||||
if (range.isEmpty()) {
|
if (range.isEmpty()) {
|
||||||
range = new Range(range.startLineNumber, 1, range.startLineNumber, model.getLineMaxColumn(range.startLineNumber));
|
range = new Range(range.startLineNumber, 1, range.startLineNumber, model.getLineMaxColumn(range.startLineNumber));
|
||||||
}
|
}
|
||||||
await instaService.invokeFunction(formatDocumentRangeWithFirstProvider, editor, range, CancellationToken.None);
|
await instaService.invokeFunction(formatDocumentRangeWithSelectedProvider, editor, range, FormattingMode.Explicit, CancellationToken.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ Registry.as<IConfigurationRegistry>(Extensions.Configuration)
|
|||||||
'http.systemCertificates': {
|
'http.systemCertificates': {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
default: true,
|
default: true,
|
||||||
description: localize('systemCertificates', "Controls whether CA certificates should be loaded from the OS. (On Windows and Mac a reload of the window is required after turning this off.)")
|
description: localize('systemCertificates', "Controls whether CA certificates should be loaded from the OS. (On Windows and macOS a reload of the window is required after turning this off.)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -28,6 +28,6 @@ export class WorkspacesService implements IWorkspacesService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getWorkspaceIdentifier(configPath: URI): Promise<IWorkspaceIdentifier> {
|
getWorkspaceIdentifier(configPath: URI): Promise<IWorkspaceIdentifier> {
|
||||||
return this.channel.call('getWorkspaceIdentifier', configPath);
|
return this.channel.call('getWorkspaceIdentifier', configPath).then(reviveWorkspaceIdentifier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ export class MainThreadExtensionService implements MainThreadExtensionServiceSha
|
|||||||
if (missingInstalledDependency.enablementState === EnablementState.Enabled || missingInstalledDependency.enablementState === EnablementState.WorkspaceEnabled) {
|
if (missingInstalledDependency.enablementState === EnablementState.Enabled || missingInstalledDependency.enablementState === EnablementState.WorkspaceEnabled) {
|
||||||
this._notificationService.notify({
|
this._notificationService.notify({
|
||||||
severity: Severity.Error,
|
severity: Severity.Error,
|
||||||
message: localize('reload window', "Cannot activate extension '{0}' because it depends on extension '{1}', which is not loaded. Would you like to reload the window to load the extension?", extName, missingInstalledDependency.displayName),
|
message: localize('reload window', "Cannot activate the '{0}' extension because it depends on the '{1}' extension, which is not loaded. Would you like to reload the window to load the extension?", extName, missingInstalledDependency.displayName),
|
||||||
actions: {
|
actions: {
|
||||||
primary: [new Action('reload', localize('reload', "Reload Window"), '', true, () => this._windowService.reloadWindow())]
|
primary: [new Action('reload', localize('reload', "Reload Window"), '', true, () => this._windowService.reloadWindow())]
|
||||||
}
|
}
|
||||||
@@ -94,7 +94,7 @@ export class MainThreadExtensionService implements MainThreadExtensionServiceSha
|
|||||||
} else {
|
} else {
|
||||||
this._notificationService.notify({
|
this._notificationService.notify({
|
||||||
severity: Severity.Error,
|
severity: Severity.Error,
|
||||||
message: localize('disabledDep', "Cannot activate extension '{0}' because it depends on extension '{1}', which is disabled. Would you like to enable the extension and reload the window?", extName, missingInstalledDependency.displayName),
|
message: localize('disabledDep', "Cannot activate the '{0}' extension because it depends on the '{1}' extension, which is disabled. Would you like to enable the extension and reload the window?", extName, missingInstalledDependency.displayName),
|
||||||
actions: {
|
actions: {
|
||||||
primary: [new Action('enable', localize('enable dep', "Enable and Reload"), '', true,
|
primary: [new Action('enable', localize('enable dep', "Enable and Reload"), '', true,
|
||||||
() => this._extensionsWorkbenchService.setEnablement([missingInstalledDependency], missingInstalledDependency.enablementState === EnablementState.Disabled ? EnablementState.Enabled : EnablementState.WorkspaceEnabled)
|
() => this._extensionsWorkbenchService.setEnablement([missingInstalledDependency], missingInstalledDependency.enablementState === EnablementState.Disabled ? EnablementState.Enabled : EnablementState.WorkspaceEnabled)
|
||||||
@@ -110,7 +110,7 @@ export class MainThreadExtensionService implements MainThreadExtensionServiceSha
|
|||||||
if (dependencyExtension) {
|
if (dependencyExtension) {
|
||||||
this._notificationService.notify({
|
this._notificationService.notify({
|
||||||
severity: Severity.Error,
|
severity: Severity.Error,
|
||||||
message: localize('uninstalledDep', "Cannot activate extension '{0}' because it depends on extension '{1}', which is not installed. Would you like to install the extension and reload the window?", extName, dependencyExtension.displayName),
|
message: localize('uninstalledDep', "Cannot activate the '{0}' extension because it depends on the '{1}' extension, which is not installed. Would you like to install the extension and reload the window?", extName, dependencyExtension.displayName),
|
||||||
actions: {
|
actions: {
|
||||||
primary: [new Action('install', localize('install missing dep', "Install and Reload"), '', true,
|
primary: [new Action('install', localize('install missing dep', "Install and Reload"), '', true,
|
||||||
() => this._extensionsWorkbenchService.install(dependencyExtension)
|
() => this._extensionsWorkbenchService.install(dependencyExtension)
|
||||||
@@ -118,7 +118,7 @@ export class MainThreadExtensionService implements MainThreadExtensionServiceSha
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this._notificationService.error(localize('unknownDep', "Cannot activate extension '{0}' because it depends on an unknown extension '{1}'.", extName, missingDependency));
|
this._notificationService.error(localize('unknownDep', "Cannot activate the '{0}' extension because it depends on an unknown '{1}' extension .", extName, missingDependency));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import { shouldSynchronizeModel } from 'vs/editor/common/services/modelService';
|
|||||||
import { getCodeActions } from 'vs/editor/contrib/codeAction/codeAction';
|
import { getCodeActions } from 'vs/editor/contrib/codeAction/codeAction';
|
||||||
import { applyCodeAction } from 'vs/editor/contrib/codeAction/codeActionCommands';
|
import { applyCodeAction } from 'vs/editor/contrib/codeAction/codeActionCommands';
|
||||||
import { CodeActionKind } from 'vs/editor/contrib/codeAction/codeActionTrigger';
|
import { CodeActionKind } from 'vs/editor/contrib/codeAction/codeActionTrigger';
|
||||||
import { formatDocumentWithFirstProvider } from 'vs/editor/contrib/format/format';
|
import { formatDocumentWithSelectedProvider, FormattingMode } from 'vs/editor/contrib/format/format';
|
||||||
import { SnippetController2 } from 'vs/editor/contrib/snippet/snippetController2';
|
import { SnippetController2 } from 'vs/editor/contrib/snippet/snippetController2';
|
||||||
import { localize } from 'vs/nls';
|
import { localize } from 'vs/nls';
|
||||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||||
@@ -257,7 +257,7 @@ class FormatOnSaveParticipant implements ISaveParticipantParticipant {
|
|||||||
return new Promise<any>((resolve, reject) => {
|
return new Promise<any>((resolve, reject) => {
|
||||||
const source = new CancellationTokenSource();
|
const source = new CancellationTokenSource();
|
||||||
const timeout = this._configurationService.getValue<number>('editor.formatOnSaveTimeout', overrides);
|
const timeout = this._configurationService.getValue<number>('editor.formatOnSaveTimeout', overrides);
|
||||||
const request = this._instantiationService.invokeFunction(formatDocumentWithFirstProvider, model, source.token);
|
const request = this._instantiationService.invokeFunction(formatDocumentWithSelectedProvider, model, FormattingMode.Silent, source.token);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
reject(localize('timeout.formatOnSave', "Aborted format on save after {0}ms", timeout));
|
reject(localize('timeout.formatOnSave', "Aborted format on save after {0}ms", timeout));
|
||||||
|
|||||||
@@ -250,7 +250,7 @@ export class MainThreadWebviews extends Disposable implements MainThreadWebviews
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this._proxy.$deserializeWebviewPanel(handle, viewType, webview.getTitle(), state, editorGroupToViewColumn(this._editorGroupService, webview.group || ACTIVE_GROUP), webview.options);
|
await this._proxy.$deserializeWebviewPanel(handle, viewType, webview.getTitle(), state, editorGroupToViewColumn(this._editorGroupService, webview.group || 0), webview.options);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
onUnexpectedError(error);
|
onUnexpectedError(error);
|
||||||
webview.html = MainThreadWebviews.getDeserializationFailedContents(viewType);
|
webview.html = MainThreadWebviews.getDeserializationFailedContents(viewType);
|
||||||
@@ -312,7 +312,7 @@ export class MainThreadWebviews extends Disposable implements MainThreadWebviews
|
|||||||
this._proxy.$onDidChangeWebviewPanelViewState(newActiveWebview.handle, {
|
this._proxy.$onDidChangeWebviewPanelViewState(newActiveWebview.handle, {
|
||||||
active: true,
|
active: true,
|
||||||
visible: true,
|
visible: true,
|
||||||
position: editorGroupToViewColumn(this._editorGroupService, newActiveWebview.input.group || ACTIVE_GROUP)
|
position: editorGroupToViewColumn(this._editorGroupService, newActiveWebview.input.group || 0)
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -324,7 +324,7 @@ export class MainThreadWebviews extends Disposable implements MainThreadWebviews
|
|||||||
this._proxy.$onDidChangeWebviewPanelViewState(this._activeWebview, {
|
this._proxy.$onDidChangeWebviewPanelViewState(this._activeWebview, {
|
||||||
active: false,
|
active: false,
|
||||||
visible: this._editorService.visibleControls.some(editor => !!editor.input && editor.input.matches(oldActiveWebview)),
|
visible: this._editorService.visibleControls.some(editor => !!editor.input && editor.input.matches(oldActiveWebview)),
|
||||||
position: editorGroupToViewColumn(this._editorGroupService, oldActiveWebview.group || ACTIVE_GROUP),
|
position: editorGroupToViewColumn(this._editorGroupService, oldActiveWebview.group || 0),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ export interface ITextEditOperation {
|
|||||||
export interface IEditData {
|
export interface IEditData {
|
||||||
documentVersionId: number;
|
documentVersionId: number;
|
||||||
edits: ITextEditOperation[];
|
edits: ITextEditOperation[];
|
||||||
setEndOfLine: EndOfLine;
|
setEndOfLine: EndOfLine | undefined;
|
||||||
undoStopBefore: boolean;
|
undoStopBefore: boolean;
|
||||||
undoStopAfter: boolean;
|
undoStopAfter: boolean;
|
||||||
}
|
}
|
||||||
@@ -52,7 +52,7 @@ export class TextEditorEdit {
|
|||||||
private readonly _document: vscode.TextDocument;
|
private readonly _document: vscode.TextDocument;
|
||||||
private readonly _documentVersionId: number;
|
private readonly _documentVersionId: number;
|
||||||
private _collectedEdits: ITextEditOperation[];
|
private _collectedEdits: ITextEditOperation[];
|
||||||
private _setEndOfLine: EndOfLine;
|
private _setEndOfLine: EndOfLine | undefined;
|
||||||
private readonly _undoStopBefore: boolean;
|
private readonly _undoStopBefore: boolean;
|
||||||
private readonly _undoStopAfter: boolean;
|
private readonly _undoStopAfter: boolean;
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ export class TextEditorEdit {
|
|||||||
this._document = document;
|
this._document = document;
|
||||||
this._documentVersionId = document.version;
|
this._documentVersionId = document.version;
|
||||||
this._collectedEdits = [];
|
this._collectedEdits = [];
|
||||||
this._setEndOfLine = 0;
|
this._setEndOfLine = undefined;
|
||||||
this._undoStopBefore = options.undoStopBefore;
|
this._undoStopBefore = options.undoStopBefore;
|
||||||
this._undoStopAfter = options.undoStopAfter;
|
this._undoStopAfter = options.undoStopAfter;
|
||||||
}
|
}
|
||||||
@@ -607,7 +607,7 @@ export class ExtHostTextEditor implements vscode.TextEditor {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return this._proxy.$tryApplyEdits(this._id, editData.documentVersionId, edits, {
|
return this._proxy.$tryApplyEdits(this._id, editData.documentVersionId, edits, {
|
||||||
setEndOfLine: editData.setEndOfLine && TypeConverters.EndOfLine.from(editData.setEndOfLine),
|
setEndOfLine: typeof editData.setEndOfLine === 'number' ? TypeConverters.EndOfLine.from(editData.setEndOfLine) : undefined,
|
||||||
undoStopBefore: editData.undoStopBefore,
|
undoStopBefore: editData.undoStopBefore,
|
||||||
undoStopAfter: editData.undoStopAfter
|
undoStopAfter: editData.undoStopAfter
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ import { hash } from 'vs/base/common/hash';
|
|||||||
export class Call {
|
export class Call {
|
||||||
constructor(
|
constructor(
|
||||||
readonly item: CallHierarchyItem,
|
readonly item: CallHierarchyItem,
|
||||||
readonly locations: Location[]
|
readonly locations: Location[],
|
||||||
|
readonly parent: Call | undefined
|
||||||
) { }
|
) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,20 +40,20 @@ export class SingleDirectionDataSource implements IAsyncDataSource<CallHierarchy
|
|||||||
if (!calls) {
|
if (!calls) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
return calls.map(([item, locations]) => new Call(item, locations));
|
return calls.map(([item, locations]) => new Call(item, locations, element));
|
||||||
} catch {
|
} catch {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 'root'
|
// 'root'
|
||||||
return [new Call(element, [{ uri: element.uri, range: Range.lift(element.range).collapseToStart() }])];
|
return [new Call(element, [{ uri: element.uri, range: Range.lift(element.range).collapseToStart() }], undefined)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class IdentityProvider implements IIdentityProvider<Call> {
|
export class IdentityProvider implements IIdentityProvider<Call> {
|
||||||
getId(element: Call): { toString(): string; } {
|
getId(element: Call): { toString(): string; } {
|
||||||
return hash(element.item.uri.toString(), hash(JSON.stringify(element.item.range)));
|
return hash(element.item.uri.toString(), hash(JSON.stringify(element.item.range))).toString() + (element.parent ? this.getId(element.parent) : '');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,9 +13,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.monaco-workbench .call-hierarchy[data-state="message"] .message {
|
.monaco-workbench .call-hierarchy[data-state="message"] .message {
|
||||||
display: inherit;
|
display: flex;
|
||||||
text-align: center;
|
align-items: center;
|
||||||
padding-top: 3em;
|
justify-content: center;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -839,6 +839,11 @@ registerEditorAction(AcceptReplInputAction);
|
|||||||
registerEditorAction(ReplCopyAllAction);
|
registerEditorAction(ReplCopyAllAction);
|
||||||
|
|
||||||
class SelectReplActionItem extends FocusSessionActionItem {
|
class SelectReplActionItem extends FocusSessionActionItem {
|
||||||
|
|
||||||
|
protected getActionContext(_: string, index: number): any {
|
||||||
|
return this.debugService.getModel().getSessions(true)[index];
|
||||||
|
}
|
||||||
|
|
||||||
protected getSessions(): ReadonlyArray<IDebugSession> {
|
protected getSessions(): ReadonlyArray<IDebugSession> {
|
||||||
return this.debugService.getModel().getSessions(true).filter(s => !sessionsToIgnore.has(s));
|
return this.debugService.getModel().getSessions(true).filter(s => !sessionsToIgnore.has(s));
|
||||||
}
|
}
|
||||||
@@ -856,8 +861,7 @@ class SelectReplAction extends Action {
|
|||||||
super(id, label);
|
super(id, label);
|
||||||
}
|
}
|
||||||
|
|
||||||
run(sessionName: string): Promise<any> {
|
run(session: IDebugSession): Promise<any> {
|
||||||
const session = this.debugService.getModel().getSessions(true).filter(p => p.getLabel() === sessionName).pop();
|
|
||||||
// If session is already the focused session we need to manualy update the tree since view model will not send a focused change event
|
// If session is already the focused session we need to manualy update the tree since view model will not send a focused change event
|
||||||
if (session && session.state !== State.Inactive && session !== this.debugService.getViewModel().focusedSession) {
|
if (session && session.state !== State.Inactive && session !== this.debugService.getViewModel().focusedSession) {
|
||||||
this.debugService.focusStackFrame(undefined, undefined, session, true);
|
this.debugService.focusStackFrame(undefined, undefined, session, true);
|
||||||
|
|||||||
@@ -601,8 +601,8 @@ class Launch extends AbstractLaunch implements ILaunch {
|
|||||||
revealIfVisible: true
|
revealIfVisible: true
|
||||||
},
|
},
|
||||||
}, sideBySide ? SIDE_GROUP : ACTIVE_GROUP).then(editor => ({ editor, created })));
|
}, sideBySide ? SIDE_GROUP : ACTIVE_GROUP).then(editor => ({ editor, created })));
|
||||||
}, (error) => {
|
}, (error: Error) => {
|
||||||
throw new Error(nls.localize('DebugConfig.failed', "Unable to create 'launch.json' file inside the '.vscode' folder ({0}).", error));
|
throw new Error(nls.localize('DebugConfig.failed', "Unable to create 'launch.json' file inside the '.vscode' folder ({0}).", error.message));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { isObject } from 'vs/base/common/types';
|
|||||||
import { TelemetryAppenderClient } from 'vs/platform/telemetry/node/telemetryIpc';
|
import { TelemetryAppenderClient } from 'vs/platform/telemetry/node/telemetryIpc';
|
||||||
import { IJSONSchema, IJSONSchemaSnippet } from 'vs/base/common/jsonSchema';
|
import { IJSONSchema, IJSONSchemaSnippet } from 'vs/base/common/jsonSchema';
|
||||||
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||||
import { IConfig, IDebuggerContribution, IDebugAdapterExecutable, INTERNAL_CONSOLE_OPTIONS_SCHEMA, IConfigurationManager, IDebugAdapter, ITerminalSettings, IDebugger, IDebugSession, IAdapterDescriptor, IDebugAdapterServer, IDebugConfiguration } from 'vs/workbench/contrib/debug/common/debug';
|
import { IConfig, IDebuggerContribution, IDebugAdapterExecutable, INTERNAL_CONSOLE_OPTIONS_SCHEMA, IConfigurationManager, IDebugAdapter, ITerminalSettings, IDebugger, IDebugSession, IAdapterDescriptor, IDebugAdapterServer } from 'vs/workbench/contrib/debug/common/debug';
|
||||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||||
import { IOutputService } from 'vs/workbench/contrib/output/common/output';
|
import { IOutputService } from 'vs/workbench/contrib/output/common/output';
|
||||||
@@ -187,15 +187,6 @@ export class Debugger implements IDebugger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private inExtHost(): boolean {
|
private inExtHost(): boolean {
|
||||||
const debugConfigs = this.configurationService.getValue<IDebugConfiguration>('debug');
|
|
||||||
if (typeof debugConfigs.extensionHostDebugAdapter === 'boolean') {
|
|
||||||
return debugConfigs.extensionHostDebugAdapter;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
return !!debugConfigs.extensionHostDebugAdapter
|
|
||||||
|| this.configurationManager.needsToRunInExtHost(this.type)
|
|
||||||
|| (!!this.mainExtensionDescription && this.mainExtensionDescription.extensionLocation.scheme !== 'file');
|
|
||||||
*/
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,5 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import 'vs/css!./media/format.contribution';
|
|
||||||
import './formatActionsMultiple';
|
import './formatActionsMultiple';
|
||||||
import './formatActionsNone';
|
import './formatActionsNone';
|
||||||
|
|||||||
@@ -6,28 +6,165 @@
|
|||||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||||
import { EditorAction, registerEditorAction, ServicesAccessor } from 'vs/editor/browser/editorExtensions';
|
import { EditorAction, registerEditorAction, ServicesAccessor } from 'vs/editor/browser/editorExtensions';
|
||||||
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
|
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
|
||||||
import { DocumentRangeFormattingEditProviderRegistry } from 'vs/editor/common/modes';
|
import { DocumentRangeFormattingEditProviderRegistry, DocumentFormattingEditProvider, DocumentRangeFormattingEditProvider } from 'vs/editor/common/modes';
|
||||||
import * as nls from 'vs/nls';
|
import * as nls from 'vs/nls';
|
||||||
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||||
import { IQuickInputService, IQuickPickItem, IQuickInputButton } from 'vs/platform/quickinput/common/quickInput';
|
import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
|
||||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
import { formatDocumentRangeWithProvider, formatDocumentWithProvider, getRealAndSyntheticDocumentFormattersOrdered } from 'vs/editor/contrib/format/format';
|
import { formatDocumentRangeWithProvider, formatDocumentWithProvider, getRealAndSyntheticDocumentFormattersOrdered, FormattingConflicts, FormattingMode } from 'vs/editor/contrib/format/format';
|
||||||
import { Range } from 'vs/editor/common/core/range';
|
import { Range } from 'vs/editor/common/core/range';
|
||||||
import { showExtensionQuery } from 'vs/workbench/contrib/format/browser/showExtensionQuery';
|
|
||||||
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
|
||||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||||
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||||
|
import { Registry } from 'vs/platform/registry/common/platform';
|
||||||
|
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
|
||||||
|
import { Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry, IWorkbenchContribution } from 'vs/workbench/common/contributions';
|
||||||
|
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
|
||||||
|
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||||
|
import { Disposable } from 'vs/base/common/lifecycle';
|
||||||
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
|
import { ITextModel } from 'vs/editor/common/model';
|
||||||
|
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
|
||||||
|
import { IModeService } from 'vs/editor/common/services/modeService';
|
||||||
|
import { IStatusbarService } from 'vs/platform/statusbar/common/statusbar';
|
||||||
|
import { ILabelService } from 'vs/platform/label/common/label';
|
||||||
|
|
||||||
|
type FormattingEditProvider = DocumentFormattingEditProvider | DocumentRangeFormattingEditProvider;
|
||||||
|
|
||||||
|
class DefaultFormatter extends Disposable implements IWorkbenchContribution {
|
||||||
|
|
||||||
|
static configName = 'editor.defaultFormatter';
|
||||||
|
|
||||||
|
static extensionIds: string[] = [];
|
||||||
|
static extensionDescriptions: string[] = [];
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
@IExtensionService private readonly _extensionService: IExtensionService,
|
||||||
|
@IConfigurationService private readonly _configService: IConfigurationService,
|
||||||
|
@INotificationService private readonly _notificationService: INotificationService,
|
||||||
|
@IQuickInputService private readonly _quickInputService: IQuickInputService,
|
||||||
|
@IModeService private readonly _modeService: IModeService,
|
||||||
|
@IStatusbarService private readonly _statusbarService: IStatusbarService,
|
||||||
|
@ILabelService private readonly _labelService: ILabelService,
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
this._register(this._extensionService.onDidChangeExtensions(this._updateConfigValues, this));
|
||||||
|
this._register(FormattingConflicts.setFormatterSelector((formatter, document, mode) => this._selectFormatter(formatter, document, mode)));
|
||||||
|
this._updateConfigValues();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _updateConfigValues(): Promise<void> {
|
||||||
|
const extensions = await this._extensionService.getExtensions();
|
||||||
|
|
||||||
|
DefaultFormatter.extensionIds.length = 0;
|
||||||
|
DefaultFormatter.extensionDescriptions.length = 0;
|
||||||
|
for (const extension of extensions) {
|
||||||
|
if (extension.main) {
|
||||||
|
DefaultFormatter.extensionIds.push(extension.identifier.value);
|
||||||
|
DefaultFormatter.extensionDescriptions.push(extension.description || '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static _maybeQuotes(s: string): string {
|
||||||
|
return s.match(/\s/) ? `'${s}'` : s;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _selectFormatter<T extends FormattingEditProvider>(formatter: T[], document: ITextModel, mode: FormattingMode): Promise<T | undefined> {
|
||||||
|
|
||||||
|
const defaultFormatterId = this._configService.getValue<string>(DefaultFormatter.configName, {
|
||||||
|
resource: document.uri,
|
||||||
|
overrideIdentifier: document.getModeId()
|
||||||
|
});
|
||||||
|
|
||||||
|
if (defaultFormatterId) {
|
||||||
|
// good -> formatter configured
|
||||||
|
const [defaultFormatter] = formatter.filter(formatter => ExtensionIdentifier.equals(formatter.extensionId, defaultFormatterId));
|
||||||
|
if (defaultFormatter) {
|
||||||
|
// formatter available
|
||||||
|
return defaultFormatter;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// formatter gone
|
||||||
|
const extension = await this._extensionService.getExtension(defaultFormatterId);
|
||||||
|
const label = this._labelService.getUriLabel(document.uri, { relative: true });
|
||||||
|
const message = extension
|
||||||
|
? nls.localize('miss', "Extension '{0}' cannot format '{1}'", extension.displayName || extension.name, label)
|
||||||
|
: nls.localize('gone', "Extension '{0}' is configured as formatter but not available", defaultFormatterId);
|
||||||
|
this._statusbarService.setStatusMessage(message, 4000);
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (formatter.length === 1) {
|
||||||
|
// ok -> nothing configured but only one formatter available
|
||||||
|
return formatter[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
const langName = this._modeService.getLanguageName(document.getModeId()) || document.getModeId();
|
||||||
|
const silent = mode === FormattingMode.Silent;
|
||||||
|
const message = nls.localize('config.needed', "There are multiple formatters for {0}-files. Select a default formatter to continue.", DefaultFormatter._maybeQuotes(langName));
|
||||||
|
|
||||||
|
return new Promise<T | undefined>((resolve, reject) => {
|
||||||
|
this._notificationService.prompt(
|
||||||
|
Severity.Info,
|
||||||
|
message,
|
||||||
|
[{ label: nls.localize('do.config', "Configure..."), run: () => this._pickAndPersistDefaultFormatter(formatter, document).then(resolve, reject) }],
|
||||||
|
{ silent, onCancel: resolve }
|
||||||
|
);
|
||||||
|
|
||||||
|
if (silent) {
|
||||||
|
// don't wait when formatting happens without interaction
|
||||||
|
// but pick some formatter...
|
||||||
|
resolve(formatter[0]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _pickAndPersistDefaultFormatter<T extends FormattingEditProvider>(formatter: T[], document: ITextModel): Promise<T | undefined> {
|
||||||
|
const picks = formatter.map((formatter, index) => {
|
||||||
|
return <IIndexedPick>{
|
||||||
|
index,
|
||||||
|
label: formatter.displayName || formatter.extensionId || '?'
|
||||||
|
};
|
||||||
|
});
|
||||||
|
const langName = this._modeService.getLanguageName(document.getModeId()) || document.getModeId();
|
||||||
|
const pick = await this._quickInputService.pick(picks, { placeHolder: nls.localize('select', "Select a default formatter for {0}-files", DefaultFormatter._maybeQuotes(langName)) });
|
||||||
|
if (!pick || !formatter[pick.index].extensionId) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
this._configService.updateValue(DefaultFormatter.configName, formatter[pick.index].extensionId!.value, {
|
||||||
|
resource: document.uri,
|
||||||
|
overrideIdentifier: document.getModeId()
|
||||||
|
});
|
||||||
|
return formatter[pick.index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(
|
||||||
|
DefaultFormatter,
|
||||||
|
LifecyclePhase.Restored
|
||||||
|
);
|
||||||
|
|
||||||
|
Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration).registerConfiguration({
|
||||||
|
id: 'editor',
|
||||||
|
order: 5,
|
||||||
|
type: 'object',
|
||||||
|
overridable: true,
|
||||||
|
properties: {
|
||||||
|
[DefaultFormatter.configName]: {
|
||||||
|
description: nls.localize('formatter.default', "Defines a default formatter which takes precedence over all other formatter settings. Must be the identifier of an extension contributing a formatter."),
|
||||||
|
type: 'string',
|
||||||
|
default: null,
|
||||||
|
enum: DefaultFormatter.extensionIds,
|
||||||
|
markdownEnumDescriptions: DefaultFormatter.extensionDescriptions
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
interface IIndexedPick extends IQuickPickItem {
|
interface IIndexedPick extends IQuickPickItem {
|
||||||
index: number;
|
index: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const openExtensionAction: IQuickInputButton = {
|
|
||||||
tooltip: nls.localize('show.ext', "Show extension..."),
|
|
||||||
iconClass: 'format-show-extension'
|
|
||||||
};
|
|
||||||
|
|
||||||
function logFormatterTelemetry<T extends { extensionId?: ExtensionIdentifier }>(telemetryService: ITelemetryService, mode: 'document' | 'range', options: T[], pick?: T) {
|
function logFormatterTelemetry<T extends { extensionId?: ExtensionIdentifier }>(telemetryService: ITelemetryService, mode: 'document' | 'range', options: T[], pick?: T) {
|
||||||
|
|
||||||
function extKey(obj: T): string {
|
function extKey(obj: T): string {
|
||||||
@@ -48,6 +185,47 @@ function logFormatterTelemetry<T extends { extensionId?: ExtensionIdentifier }>(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function showFormatterPick(accessor: ServicesAccessor, model: ITextModel, formatters: FormattingEditProvider[]): Promise<number | undefined> {
|
||||||
|
const quickPickService = accessor.get(IQuickInputService);
|
||||||
|
const configService = accessor.get(IConfigurationService);
|
||||||
|
const modeService = accessor.get(IModeService);
|
||||||
|
|
||||||
|
const overrides = { resource: model.uri, overrideIdentifier: model.getModeId() };
|
||||||
|
const defaultFormatter = configService.getValue<string>(DefaultFormatter.configName, overrides);
|
||||||
|
|
||||||
|
const picks = formatters.map((provider, index) => {
|
||||||
|
return <IIndexedPick>{
|
||||||
|
index,
|
||||||
|
label: provider.displayName || '',
|
||||||
|
description: ExtensionIdentifier.equals(provider.extensionId, defaultFormatter) ? nls.localize('def', "(default)") : undefined,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const configurePick: IQuickPickItem = {
|
||||||
|
label: nls.localize('config', "Configure Default Formatter...")
|
||||||
|
};
|
||||||
|
|
||||||
|
const pick = await quickPickService.pick([...picks, { type: 'separator' }, configurePick], { placeHolder: nls.localize('format.placeHolder', "Select a formatter") });
|
||||||
|
if (!pick) {
|
||||||
|
// dismissed
|
||||||
|
return undefined;
|
||||||
|
|
||||||
|
} else if (pick === configurePick) {
|
||||||
|
// config default
|
||||||
|
const langName = modeService.getLanguageName(model.getModeId()) || model.getModeId();
|
||||||
|
const pick = await quickPickService.pick(picks, { placeHolder: nls.localize('select', "Select a default formatter for {0}-files", DefaultFormatter._maybeQuotes(langName)) });
|
||||||
|
if (pick && formatters[pick.index].extensionId) {
|
||||||
|
configService.updateValue(DefaultFormatter.configName, formatters[pick.index].extensionId!.value, overrides);
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// picked one
|
||||||
|
return (<IIndexedPick>pick).index;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
registerEditorAction(class FormatDocumentMultipleAction extends EditorAction {
|
registerEditorAction(class FormatDocumentMultipleAction extends EditorAction {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -68,32 +246,14 @@ registerEditorAction(class FormatDocumentMultipleAction extends EditorAction {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const instaService = accessor.get(IInstantiationService);
|
const instaService = accessor.get(IInstantiationService);
|
||||||
const quickPickService = accessor.get(IQuickInputService);
|
|
||||||
const viewletService = accessor.get(IViewletService);
|
|
||||||
const telemetryService = accessor.get(ITelemetryService);
|
const telemetryService = accessor.get(ITelemetryService);
|
||||||
const model = editor.getModel();
|
const model = editor.getModel();
|
||||||
|
|
||||||
const provider = getRealAndSyntheticDocumentFormattersOrdered(model);
|
const provider = getRealAndSyntheticDocumentFormattersOrdered(model);
|
||||||
const picks = provider.map((provider, index) => {
|
const pick = await instaService.invokeFunction(showFormatterPick, model, provider);
|
||||||
return <IIndexedPick>{
|
|
||||||
index,
|
|
||||||
label: provider.displayName || '',
|
|
||||||
buttons: [openExtensionAction]
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const pick = await quickPickService.pick(picks, {
|
|
||||||
placeHolder: nls.localize('format.placeHolder', "Select a formatter"),
|
|
||||||
onDidTriggerItemButton: (e) => {
|
|
||||||
const { extensionId } = provider[e.item.index];
|
|
||||||
return showExtensionQuery(viewletService, `@id:${extensionId!.value}`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (pick) {
|
if (pick) {
|
||||||
await instaService.invokeFunction(formatDocumentWithProvider, provider[pick.index], editor, CancellationToken.None);
|
await instaService.invokeFunction(formatDocumentWithProvider, provider[pick], editor, CancellationToken.None);
|
||||||
}
|
}
|
||||||
|
logFormatterTelemetry(telemetryService, 'document', provider, typeof pick === 'number' && provider[pick] || undefined);
|
||||||
logFormatterTelemetry(telemetryService, 'document', provider, pick && provider[pick.index]);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -118,36 +278,20 @@ registerEditorAction(class FormatSelectionMultipleAction extends EditorAction {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const instaService = accessor.get(IInstantiationService);
|
const instaService = accessor.get(IInstantiationService);
|
||||||
const quickPickService = accessor.get(IQuickInputService);
|
|
||||||
const viewletService = accessor.get(IViewletService);
|
|
||||||
const telemetryService = accessor.get(ITelemetryService);
|
const telemetryService = accessor.get(ITelemetryService);
|
||||||
const model = editor.getModel();
|
|
||||||
|
|
||||||
|
const model = editor.getModel();
|
||||||
let range: Range = editor.getSelection();
|
let range: Range = editor.getSelection();
|
||||||
if (range.isEmpty()) {
|
if (range.isEmpty()) {
|
||||||
range = new Range(range.startLineNumber, 1, range.startLineNumber, model.getLineMaxColumn(range.startLineNumber));
|
range = new Range(range.startLineNumber, 1, range.startLineNumber, model.getLineMaxColumn(range.startLineNumber));
|
||||||
}
|
}
|
||||||
|
|
||||||
const provider = DocumentRangeFormattingEditProviderRegistry.ordered(model);
|
const provider = DocumentRangeFormattingEditProviderRegistry.ordered(model);
|
||||||
const picks = provider.map((provider, index) => {
|
const pick = await instaService.invokeFunction(showFormatterPick, model, provider);
|
||||||
return <IIndexedPick>{
|
|
||||||
index,
|
|
||||||
label: provider.displayName || '',
|
|
||||||
buttons: [openExtensionAction]
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const pick = await quickPickService.pick(picks, {
|
|
||||||
placeHolder: nls.localize('format.placeHolder', "Select a formatter"),
|
|
||||||
onDidTriggerItemButton: (e) => {
|
|
||||||
const { extensionId } = provider[e.item.index];
|
|
||||||
return showExtensionQuery(viewletService, `@id:${extensionId!.value}`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (pick) {
|
if (pick) {
|
||||||
await instaService.invokeFunction(formatDocumentRangeWithProvider, provider[pick.index], editor, range, CancellationToken.None);
|
await instaService.invokeFunction(formatDocumentRangeWithProvider, provider[pick], editor, range, CancellationToken.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
logFormatterTelemetry(telemetryService, 'range', provider, pick && provider[pick.index]);
|
logFormatterTelemetry(telemetryService, 'range', provider, typeof pick === 'number' && provider[pick] || undefined);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><g fill="#C5C5C5"><path d="M12.714 9.603c-.07.207-.15.407-.246.601l1.017 2.139c-.335.424-.718.807-1.142 1.143l-2.14-1.018c-.193.097-.394.176-.601.247l-.795 2.235c-.265.03-.534.05-.807.05-.272 0-.541-.02-.806-.05l-.795-2.235c-.207-.071-.408-.15-.602-.247l-2.14 1.017c-.424-.336-.807-.719-1.143-1.143l1.017-2.139c-.094-.193-.175-.393-.245-.6l-2.236-.796c-.03-.265-.05-.534-.05-.807s.02-.542.05-.807l2.236-.795c.07-.207.15-.407.246-.601l-1.016-2.139c.336-.423.719-.807 1.143-1.142l2.14 1.017c.193-.096.394-.176.602-.247l.793-2.236c.265-.03.534-.05.806-.05.273 0 .542.02.808.05l.795 2.236c.207.07.407.15.601.246l2.14-1.017c.424.335.807.719 1.142 1.142l-1.017 2.139c.096.194.176.394.246.601l2.236.795c.029.266.049.535.049.808s-.02.542-.05.807l-2.236.796zm-4.714-4.603c-1.657 0-3 1.343-3 3s1.343 3 3 3 3-1.343 3-3-1.343-3-3-3z"/><circle cx="8" cy="8" r="1.5"/></g></svg>
|
|
||||||
|
Before Width: | Height: | Size: 927 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><g fill="#424242"><path d="M12.714 9.603c-.07.207-.15.407-.246.601l1.017 2.139c-.335.424-.718.807-1.142 1.143l-2.14-1.018c-.193.097-.394.176-.601.247l-.795 2.235c-.265.03-.534.05-.807.05-.272 0-.541-.02-.806-.05l-.795-2.235c-.207-.071-.408-.15-.602-.247l-2.14 1.017c-.424-.336-.807-.719-1.143-1.143l1.017-2.139c-.094-.193-.175-.393-.245-.6l-2.236-.796c-.03-.265-.05-.534-.05-.807s.02-.542.05-.807l2.236-.795c.07-.207.15-.407.246-.601l-1.016-2.139c.336-.423.719-.807 1.143-1.142l2.14 1.017c.193-.096.394-.176.602-.247l.793-2.236c.265-.03.534-.05.806-.05.273 0 .542.02.808.05l.795 2.236c.207.07.407.15.601.246l2.14-1.017c.424.335.807.719 1.142 1.142l-1.017 2.139c.096.194.176.394.246.601l2.236.795c.029.266.049.535.049.808s-.02.542-.05.807l-2.236.796zm-4.714-4.603c-1.657 0-3 1.343-3 3s1.343 3 3 3 3-1.343 3-3-1.343-3-3-3z"/><circle cx="8" cy="8" r="1.5"/></g></svg>
|
|
||||||
|
Before Width: | Height: | Size: 927 B |
@@ -1,13 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------------------------
|
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
|
||||||
*--------------------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
.monaco-workbench .format-show-extension {
|
|
||||||
background-image: url('configure.svg');
|
|
||||||
}
|
|
||||||
|
|
||||||
.vs-dark .monaco-workbench .format-show-extension,
|
|
||||||
.hc-black .monaco-workbench .format-show-extension {
|
|
||||||
background-image: url('configure-inverse.svg');
|
|
||||||
}
|
|
||||||
@@ -1181,6 +1181,10 @@ export class SCMViewlet extends ViewContainerViewlet implements IViewModel {
|
|||||||
this.viewsModel.setVisible(MainPanel.ID, false);
|
this.viewsModel.setVisible(MainPanel.ID, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (repositoryCount === 1) {
|
||||||
|
this.viewsModel.setVisible(this.viewDescriptors[0].id, true);
|
||||||
|
}
|
||||||
|
|
||||||
toggleClass(this.el, 'empty', repositoryCount === 0);
|
toggleClass(this.el, 'empty', repositoryCount === 0);
|
||||||
this.repositoryCount = repositoryCount;
|
this.repositoryCount = repositoryCount;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -230,7 +230,7 @@ export class QueryBuilder {
|
|||||||
parseSearchPaths(pattern: string): ISearchPathsInfo {
|
parseSearchPaths(pattern: string): ISearchPathsInfo {
|
||||||
const isSearchPath = (segment: string) => {
|
const isSearchPath = (segment: string) => {
|
||||||
// A segment is a search path if it is an absolute path or starts with ./, ../, .\, or ..\
|
// A segment is a search path if it is an absolute path or starts with ./, ../, .\, or ..\
|
||||||
return path.isAbsolute(segment) || /^\.\.?[\/\\]/.test(segment);
|
return path.isAbsolute(segment) || /^\.\.?([\/\\]|$)/.test(segment);
|
||||||
};
|
};
|
||||||
|
|
||||||
const segments = splitGlobPattern(pattern)
|
const segments = splitGlobPattern(pattern)
|
||||||
@@ -339,7 +339,7 @@ export class QueryBuilder {
|
|||||||
const workspaceUri = this.workspaceContextService.getWorkspace().folders[0].uri;
|
const workspaceUri = this.workspaceContextService.getWorkspace().folders[0].uri;
|
||||||
|
|
||||||
searchPath = normalizeSlashes(searchPath);
|
searchPath = normalizeSlashes(searchPath);
|
||||||
if (strings.startsWith(searchPath, '../')) {
|
if (strings.startsWith(searchPath, '../') || searchPath === '..') {
|
||||||
const resolvedPath = path.posix.resolve(workspaceUri.path, searchPath);
|
const resolvedPath = path.posix.resolve(workspaceUri.path, searchPath);
|
||||||
return [{
|
return [{
|
||||||
searchPath: workspaceUri.with({ path: resolvedPath })
|
searchPath: workspaceUri.with({ path: resolvedPath })
|
||||||
|
|||||||
@@ -667,6 +667,14 @@ suite('QueryBuilder', () => {
|
|||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'..',
|
||||||
|
{
|
||||||
|
searchPaths: [{
|
||||||
|
searchPath: getUri('/foo')
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
],
|
||||||
[
|
[
|
||||||
'..\\bar',
|
'..\\bar',
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -458,7 +458,7 @@ export class TerminalTaskSystem implements ITaskSystem {
|
|||||||
const resolvedVariables = this.resolveVariablesFromSet(this.currentTask.systemInfo, this.currentTask.workspaceFolder!, task, variables);
|
const resolvedVariables = this.resolveVariablesFromSet(this.currentTask.systemInfo, this.currentTask.workspaceFolder!, task, variables);
|
||||||
|
|
||||||
return resolvedVariables.then((resolvedVariables) => {
|
return resolvedVariables.then((resolvedVariables) => {
|
||||||
if (resolvedVariables) {
|
if (resolvedVariables && task.command && task.command.runtime) {
|
||||||
this.currentTask.resolvedVariables = resolvedVariables;
|
this.currentTask.resolvedVariables = resolvedVariables;
|
||||||
return this.executeInTerminal(task, trigger, new VariableResolver(this.currentTask.workspaceFolder!, this.currentTask.systemInfo, resolvedVariables.variables, this.configurationResolverService));
|
return this.executeInTerminal(task, trigger, new VariableResolver(this.currentTask.workspaceFolder!, this.currentTask.systemInfo, resolvedVariables.variables, this.configurationResolverService));
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -325,15 +325,15 @@ export class BulkEdit {
|
|||||||
|
|
||||||
} else if (!edit.newUri && edit.oldUri) {
|
} else if (!edit.newUri && edit.oldUri) {
|
||||||
// delete file
|
// delete file
|
||||||
if (!options.ignoreIfNotExists || await this._fileService.existsFile(edit.oldUri)) {
|
if (await this._fileService.existsFile(edit.oldUri)) {
|
||||||
let useTrash = this._configurationService.getValue<boolean>('files.enableTrash');
|
let useTrash = this._configurationService.getValue<boolean>('files.enableTrash');
|
||||||
if (useTrash && !(await this._fileService.hasCapability(edit.oldUri, FileSystemProviderCapabilities.Trash))) {
|
if (useTrash && !(await this._fileService.hasCapability(edit.oldUri, FileSystemProviderCapabilities.Trash))) {
|
||||||
useTrash = false; // not supported by provider
|
useTrash = false; // not supported by provider
|
||||||
}
|
}
|
||||||
|
|
||||||
await this._textFileService.delete(edit.oldUri, { useTrash, recursive: options.recursive });
|
await this._textFileService.delete(edit.oldUri, { useTrash, recursive: options.recursive });
|
||||||
|
} else if (!options.ignoreIfNotExists) {
|
||||||
|
throw new Error(`${edit.oldUri} does not exist and can not be deleted`);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (edit.newUri && !edit.oldUri) {
|
} else if (edit.newUri && !edit.oldUri) {
|
||||||
// create file
|
// create file
|
||||||
if (options.overwrite === undefined && options.ignoreIfExists && await this._fileService.existsFile(edit.newUri)) {
|
if (options.overwrite === undefined && options.ignoreIfExists && await this._fileService.existsFile(edit.newUri)) {
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ export function setup() {
|
|||||||
|
|
||||||
await app.workbench.extensions.installExtension(extensionName);
|
await app.workbench.extensions.installExtension(extensionName);
|
||||||
|
|
||||||
await app.reload();
|
|
||||||
await app.workbench.extensions.waitForExtensionsViewlet();
|
await app.workbench.extensions.waitForExtensionsViewlet();
|
||||||
await app.workbench.quickopen.runCommand('Smoke Test Check');
|
await app.workbench.quickopen.runCommand('Smoke Test Check');
|
||||||
await app.workbench.statusbar.waitForStatusbarText('smoke test', 'VS Code Smoke Test Check');
|
await app.workbench.statusbar.waitForStatusbarText('smoke test', 'VS Code Smoke Test Check');
|
||||||
|
|||||||
@@ -113,7 +113,6 @@ export async function spawn(options: SpawnOptions): Promise<Code> {
|
|||||||
'--skip-release-notes',
|
'--skip-release-notes',
|
||||||
'--sticky-quickopen',
|
'--sticky-quickopen',
|
||||||
'--disable-telemetry',
|
'--disable-telemetry',
|
||||||
'--disable-extensions',
|
|
||||||
'--disable-updates',
|
'--disable-updates',
|
||||||
'--disable-crash-reporter',
|
'--disable-crash-reporter',
|
||||||
`--extensions-dir=${options.extensionsPath}`,
|
`--extensions-dir=${options.extensionsPath}`,
|
||||||
|
|||||||
Reference in New Issue
Block a user