Register additional editor overrides when adding new notebook file types (#17708)

* Also standardized file extension contributions to always start with a period, and to always do lower case string comparisons for file extensions.
This commit is contained in:
Cory Rivera
2021-11-19 09:14:41 -08:00
committed by GitHub
parent 09666bc4e8
commit 8e04d3992a
8 changed files with 64 additions and 50 deletions

View File

@@ -53,7 +53,7 @@ import { ImageMimeTypes, TextCellEditModes } from 'sql/workbench/services/notebo
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { NotebookInput } from 'sql/workbench/contrib/notebook/browser/models/notebookInput';
import { INotebookModel } from 'sql/workbench/services/notebook/browser/models/modelInterfaces';
import { IExecuteManager } from 'sql/workbench/services/notebook/browser/notebookService';
import { DEFAULT_NOTEBOOK_FILETYPE, IExecuteManager, SQL_NOTEBOOK_PROVIDER } from 'sql/workbench/services/notebook/browser/notebookService';
import { NotebookExplorerViewletViewsContribution } from 'sql/workbench/contrib/notebook/browser/notebookExplorer/notebookExplorerViewlet';
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { ContributedEditorPriority, IEditorOverrideService } from 'vs/workbench/services/editor/common/editorOverrideService';
@@ -62,7 +62,8 @@ import { IModeService } from 'vs/editor/common/services/modeService';
import { ILogService } from 'vs/platform/log/common/log';
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
import { useNewMarkdownRendererKey } from 'sql/workbench/contrib/notebook/common/notebookCommon';
import { JUPYTER_PROVIDER_ID } from 'sql/workbench/common/constants';
import { JUPYTER_PROVIDER_ID, NotebookLanguage } from 'sql/workbench/common/constants';
import { INotebookProviderRegistry, NotebookProviderRegistryId } from 'sql/workbench/services/notebook/common/notebookRegistry';
Registry.as<IEditorInputFactoryRegistry>(EditorExtensions.EditorInputFactories)
.registerEditorInputSerializer(FileNotebookInput.ID, FileNoteBookEditorInputSerializer);
@@ -687,10 +688,12 @@ configurationRegistry.registerConfiguration({
});
const languageAssociationRegistry = Registry.as<ILanguageAssociationRegistry>(LanguageAssociationExtensions.LanguageAssociations);
const notebookRegistry = Registry.as<INotebookProviderRegistry>(NotebookProviderRegistryId);
export class NotebookEditorOverrideContribution extends Disposable implements IWorkbenchContribution {
private _registeredOverrides = new DisposableStore();
private _newFileExtensions: string[] = [];
constructor(
@ILogService private _logService: ILogService,
@@ -705,47 +708,59 @@ export class NotebookEditorOverrideContribution extends Disposable implements IW
this._modeService.onLanguagesMaybeChanged(() => {
this.registerEditorOverrides();
});
notebookRegistry.onNewDescriptionRegistration(({ id, registration }) => {
if (id !== JUPYTER_PROVIDER_ID && id !== SQL_NOTEBOOK_PROVIDER && registration?.fileExtensions?.length > 0) {
let extensions = registration.fileExtensions
.filter(ext => ext?.length > 0 && ext.toLowerCase() !== DEFAULT_NOTEBOOK_FILETYPE);
this._newFileExtensions = this._newFileExtensions.concat(extensions);
this.registerEditorOverrides();
}
});
}
private registerEditorOverrides(): void {
this._registeredOverrides.clear();
// List of language IDs to associate the query editor for. These are case sensitive.
NotebookEditorInputAssociation.languages.map(lang => {
let allExtensions: string[] = [];
// List of built-in language IDs to associate the query editor for. These are case sensitive.
NotebookEditorInputAssociation.languages.forEach(lang => {
const langExtensions = this._modeService.getExtensions(lang);
if (langExtensions.length === 0) {
return;
}
// Create the selector from the list of all the language extensions we want to associate with the
// notebook editor (filtering out any languages which didn't have any extensions registered yet)
const selector = `*{${langExtensions.join(',')}}`;
this._registeredOverrides.add(this._editorOverrideService.registerEditor(
selector,
{
id: NotebookEditor.ID,
label: NotebookEditor.LABEL,
describes: (currentEditor) => currentEditor instanceof FileNotebookInput,
priority: ContributedEditorPriority.builtin
},
{},
(resource, options, group) => {
const fileInput = this._editorService.createEditorInput({
resource: resource
}) as FileEditorInput;
// Try to convert the input, falling back to just a plain file input if we're unable to
const newInput = this.tryConvertInput(fileInput, lang) ?? fileInput;
return { editor: newInput, options: options, group: group };
},
(diffEditorInput, options, group) => {
// Try to convert the input, falling back to the original input if we're unable to
const newInput = this.tryConvertInput(diffEditorInput, lang) ?? diffEditorInput;
return { editor: newInput, options: options, group: group };
}
));
allExtensions = allExtensions.concat(langExtensions);
});
// Add newly registered file extensions
allExtensions = allExtensions.concat(this._newFileExtensions);
// Create the selector from the list of all the language extensions we want to associate with the
// notebook editor
const selector = `*{${allExtensions.join(',')}}`;
this._registeredOverrides.add(this._editorOverrideService.registerEditor(
selector,
{
id: NotebookEditor.ID,
label: NotebookEditor.LABEL,
describes: (currentEditor) => currentEditor instanceof FileNotebookInput,
priority: ContributedEditorPriority.builtin
},
{},
(resource, options, group) => {
const fileInput = this._editorService.createEditorInput({
resource: resource
}) as FileEditorInput;
// Try to convert the input, falling back to just a plain file input if we're unable to
const newInput = this.tryConvertInput(fileInput) ?? fileInput;
return { editor: newInput, options: options, group: group };
},
(diffEditorInput, options, group) => {
// Try to convert the input, falling back to the original input if we're unable to
const newInput = this.tryConvertInput(diffEditorInput) ?? diffEditorInput;
return { editor: newInput, options: options, group: group };
}
));
}
private tryConvertInput(input: IEditorInput, lang: string): IEditorInput | undefined {
const langAssociation = languageAssociationRegistry.getAssociationForLanguage(lang);
private tryConvertInput(input: IEditorInput): IEditorInput | undefined {
const langAssociation = languageAssociationRegistry.getAssociationForLanguage(NotebookLanguage.Ipynb);
const notebookEditorInput = langAssociation?.syncConvertInput?.(input);
if (!notebookEditorInput) {
this._logService.warn('Unable to create input for overriding editor ', input instanceof DiffEditorInput ? `${input.primary.resource.toString()} <-> ${input.secondary.resource.toString()}` : input.resource.toString());