Rework how we handle custom editors (#5696)

* update how we handle editors

* small edit

* handle changing languages

* implement generic language association

* implement notebook serializers

* fix tests

* formatting

* update how we handle editors

* small edit

* handle changing languages

* implement generic language association

* implement notebook serializers

* fix tests

* formatting

* fix broken

* fix compile

* fix tests

* add back in removed note book contributions

* fix layering

* fix compile errors

* fix workbench

* fix hanging promises

* idk why these changed

* fix change

* add comments to language change code

* fix a few bugs

* add query plan association
This commit is contained in:
Anthony Dresser
2019-11-24 19:22:11 -08:00
committed by GitHub
parent f3a6fc6f88
commit 43387f0d0b
50 changed files with 988 additions and 873 deletions

View File

@@ -0,0 +1,12 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { EditorReplacementContribution } from 'sql/workbench/common/editorReplacerContribution';
import { Registry } from 'vs/platform/registry/common/platform';
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
const workbenchContributionsRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);
workbenchContributionsRegistry.registerWorkbenchContribution(EditorReplacementContribution, LifecyclePhase.Starting);

View File

@@ -0,0 +1,83 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { IEditorService, IOpenEditorOverride } from 'vs/workbench/services/editor/common/editorService';
import { IEditorInput } from 'vs/workbench/common/editor';
import { IEditorOptions, ITextEditorOptions } from 'vs/platform/editor/common/editor';
import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService';
import { UntitledEditorInput } from 'vs/workbench/common/editor/untitledEditorInput';
import { IModeService } from 'vs/editor/common/services/modeService';
import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileEditorInput';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { Registry } from 'vs/platform/registry/common/platform';
import { ILanguageAssociationRegistry, Extensions as LanguageAssociationExtensions } from 'sql/workbench/common/languageAssociation';
const languageAssociationRegistry = Registry.as<ILanguageAssociationRegistry>(LanguageAssociationExtensions.LanguageAssociations);
export class EditorReplacementContribution implements IWorkbenchContribution {
private editorOpeningListener: IDisposable;
constructor(
@IEditorService private readonly editorService: IEditorService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IModeService private readonly modeService: IModeService
) {
this.editorOpeningListener = this.editorService.overrideOpenEditor((editor, options, group) => this.onEditorOpening(editor, options, group));
}
private onEditorOpening(editor: IEditorInput, options: IEditorOptions | ITextEditorOptions | undefined, group: IEditorGroup): IOpenEditorOverride | undefined {
// If the resource was already opened before in the group, do not prevent
// the opening of that resource. Otherwise we would have the same settings
// opened twice (https://github.com/Microsoft/vscode/issues/36447)
// if (group.isOpened(editor)) {
// return undefined;
// }
if (!(editor instanceof FileEditorInput) && !(editor instanceof UntitledEditorInput)) {
return undefined;
}
let language: string;
if (editor instanceof FileEditorInput) {
language = editor.getPreferredMode();
} else if (editor instanceof UntitledEditorInput) {
language = editor.getMode();
} else {
return undefined;
}
if (!language) { // in the case the input doesn't have a preferred mode set we will attempt to guess the mode from the file path
language = this.modeService.getModeIdByFilepathOrFirstLine(editor.getResource());
}
if (!language) {
const defaultInputCreator = languageAssociationRegistry.getAssociations().filter(e => e.isDefault)[0];
if (defaultInputCreator) {
editor.setMode(defaultInputCreator.language);
const newInput = this.instantiationService.invokeFunction(defaultInputCreator.creator, editor);
if (newInput) {
return { override: this.editorService.openEditor(newInput, options, group) };
}
}
} else {
const inputCreator = languageAssociationRegistry.getAssociations().filter(e => e.language === language)[0];
if (inputCreator) {
const newInput = this.instantiationService.invokeFunction(inputCreator.creator, editor);
if (newInput) {
return { override: this.editorService.openEditor(newInput, options, group) };
}
}
}
return undefined;
}
dispose(): void {
dispose(this.editorOpeningListener);
}
}

View File

@@ -0,0 +1,34 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Registry } from 'vs/platform/registry/common/platform';
import { IEditorInput } from 'vs/workbench/common/editor';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
export type InputCreator = (servicesAccessor: ServicesAccessor, activeEditor: IEditorInput) => IEditorInput | undefined;
export type BaseInputCreator = (activeEditor: IEditorInput) => IEditorInput;
export interface ILanguageAssociationRegistry {
registerLanguageAssociation(language: string, creator: InputCreator, baseInputCreator: BaseInputCreator, isDefault?: boolean): void;
getAssociations(): Array<{ language: string, creator: InputCreator, baseInputCreator: BaseInputCreator, isDefault: boolean }>;
}
class LanguageAssociationRegistry implements ILanguageAssociationRegistry {
private associations = new Array<{ language: string, creator: InputCreator, baseInputCreator: BaseInputCreator, isDefault: boolean }>();
registerLanguageAssociation(language: string, creator: InputCreator, baseInputCreator: BaseInputCreator, isDefault: boolean = false): void {
this.associations.push({ language, creator, baseInputCreator, isDefault });
}
getAssociations(): Array<{ language: string, creator: InputCreator, baseInputCreator: BaseInputCreator, isDefault: boolean }> {
return this.associations.slice();
}
}
export const Extensions = {
LanguageAssociations: 'workbench.contributions.editor.languageAssociation'
};
Registry.add(Extensions.LanguageAssociations, new LanguageAssociationRegistry());

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as ConnectionConstants from 'sql/platform/connection/common/constants';
import { QueryInput } from 'sql/workbench/contrib/query/common/queryInput';
import { QueryEditorInput } from 'sql/workbench/contrib/query/common/queryEditorInput';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { URI } from 'vs/base/common/uri';
@@ -26,11 +26,8 @@ export function getSqlConfigValue<T>(workspaceConfigService: IConfigurationServi
export function getEditorUri(input: IEditorInput): string {
let uri: URI;
if (input instanceof QueryInput) {
let queryCast: QueryInput = <QueryInput>input;
if (queryCast) {
uri = queryCast.getResource();
}
if (input instanceof QueryEditorInput) {
uri = input.getResource();
}
if (uri) {