Query editor input titles (#9512)

* address untitled editor file name differences; remove feature for updating title for untitled to content

* add tests for new methods

* fix tests

* fix up tests

* remove unncessary await

* revert changes to title for content
This commit is contained in:
Anthony Dresser
2020-03-11 12:42:13 -07:00
committed by GitHub
parent edd396f0fe
commit dbc20c1f67
9 changed files with 156 additions and 24 deletions

View File

@@ -16,6 +16,7 @@ import * as path from 'vs/base/common/path';
import { ILanguageAssociationRegistry, Extensions as LanguageAssociationExtensions } from 'sql/workbench/services/languageAssociation/common/languageAssociation';
import { UntitledTextEditorInput } from 'vs/workbench/services/untitled/common/untitledTextEditorInput';
import { isThenable } from 'vs/base/common/async';
const languageAssociationRegistry = Registry.as<ILanguageAssociationRegistry>(LanguageAssociationExtensions.LanguageAssociations);
@@ -63,7 +64,7 @@ export class EditorReplacementContribution implements IWorkbenchContribution {
editor.setMode(defaultInputCreator[0]);
const newInput = defaultInputCreator[1].convertInput(editor);
if (newInput) {
return { override: this.editorService.openEditor(newInput, options, group) };
return { override: isThenable(newInput) ? newInput.then(input => this.editorService.openEditor(input, options, group)) : this.editorService.openEditor(newInput, options, group) };
}
}
} else {
@@ -71,7 +72,7 @@ export class EditorReplacementContribution implements IWorkbenchContribution {
if (inputCreator) {
const newInput = inputCreator.convertInput(editor);
if (newInput) {
return { override: this.editorService.openEditor(newInput, options, group) };
return { override: isThenable(newInput) ? newInput.then(input => this.editorService.openEditor(input, options, group)) : this.editorService.openEditor(newInput, options, group) };
}
}
}

View File

@@ -13,7 +13,7 @@ import { URI } from 'vs/base/common/uri';
import { IOpenEditorOverrideHandler, IOpenEditorOverride, IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IDisposable, toDisposable, dispose } from 'vs/base/common/lifecycle';
import { isUndefinedOrNull } from 'vs/base/common/types';
import { IEditorInput, EditorInput } from 'vs/workbench/common/editor';
import { IEditorInput, EditorInput, IUntitledTextResourceInput } from 'vs/workbench/common/editor';
import { ITextEditorOptions, IEditorOptions } from 'vs/platform/editor/common/editor';
import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService';
import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileEditorInput';
@@ -29,9 +29,13 @@ import { UntitledQueryEditorInput } from 'sql/workbench/common/editor/query/unti
import { INotebookService } from 'sql/workbench/services/notebook/browser/notebookService';
import { NotebookServiceStub } from 'sql/workbench/contrib/notebook/test/stubs';
import { IUntitledTextEditorService } from 'vs/workbench/services/untitled/common/untitledTextEditorService';
import { IQueryEditorService } from 'sql/workbench/services/queryEditor/common/queryEditorService';
import { TestQueryEditorService } from 'sql/workbench/services/queryEditor/test/common/testQueryEditorService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
const languageAssociations = Registry.as<ILanguageAssociationRegistry>(LanguageAssociationExtensions.LanguageAssociations);
suite('Editor Replacer Contribution', () => {
let disposables: IDisposable[] = [];
@@ -40,6 +44,9 @@ suite('Editor Replacer Contribution', () => {
disposables.push(languageAssociations.registerLanguageAssociation(NotebookEditorInputAssociation.languages, NotebookEditorInputAssociation));
const instantiationService = workbenchInstantiationService();
instantiationService.stub(INotebookService, new NotebookServiceStub());
const editorService = new MockEditorService(instantiationService);
instantiationService.stub(IEditorService, editorService);
instantiationService.stub(IQueryEditorService, instantiationService.createInstance(TestQueryEditorService));
instantiationService.invokeFunction(accessor => {
languageAssociations.start(accessor);
});
@@ -50,7 +57,8 @@ suite('Editor Replacer Contribution', () => {
});
test('does proper lifecycle', () => {
const editorService = new MockEditorService();
const instantiationService = workbenchInstantiationService();
const editorService = new MockEditorService(instantiationService);
const modeService = new TestModeService();
const contrib = new EditorReplacementContribution(editorService, modeService);
assert.equal(editorService.overridenOpens.length, 1);
@@ -59,8 +67,8 @@ suite('Editor Replacer Contribution', () => {
});
test('does replace sql file input from uri (no mode service)', async () => {
const editorService = new MockEditorService();
const instantiationService = workbenchInstantiationService();
const editorService = new MockEditorService(instantiationService);
instantiationService.stub(IEditorService, editorService);
const contrib = instantiationService.createInstance(EditorReplacementContribution);
const input = instantiationService.createInstance(FileEditorInput, URI.file('/test/file.sql'), undefined, undefined);
@@ -74,8 +82,8 @@ suite('Editor Replacer Contribution', () => {
});
test('does replace sql file input using input mode', async () => {
const editorService = new MockEditorService();
const instantiationService = workbenchInstantiationService();
const editorService = new MockEditorService(instantiationService);
instantiationService.stub(IEditorService, editorService);
const contrib = instantiationService.createInstance(EditorReplacementContribution);
const input = instantiationService.createInstance(FileEditorInput, URI.file('/test/file.other'), undefined, 'sql');
@@ -88,9 +96,9 @@ suite('Editor Replacer Contribution', () => {
contrib.dispose();
});
test('does replace notebook file input using input mode', async () => {
const editorService = new MockEditorService();
test('does replace notebook file input using input extension notebook', async () => {
const instantiationService = workbenchInstantiationService();
const editorService = new MockEditorService(instantiationService);
instantiationService.stub(IEditorService, editorService);
const contrib = instantiationService.createInstance(EditorReplacementContribution);
const input = instantiationService.createInstance(FileEditorInput, URI.file('/test/file.notebook'), undefined, undefined);
@@ -103,9 +111,9 @@ suite('Editor Replacer Contribution', () => {
contrib.dispose();
});
test('does replace notebook file input using input mode', async () => {
const editorService = new MockEditorService();
test('does replace notebook file input using input extension iynb', async () => {
const instantiationService = workbenchInstantiationService();
const editorService = new MockEditorService(instantiationService);
instantiationService.stub(IEditorService, editorService);
const contrib = instantiationService.createInstance(EditorReplacementContribution);
const input = instantiationService.createInstance(FileEditorInput, URI.file('/test/file.iynb'), undefined, 'notebook');
@@ -118,9 +126,9 @@ suite('Editor Replacer Contribution', () => {
contrib.dispose();
});
test('does replace notebook file input using input mode', async () => {
const editorService = new MockEditorService();
test('does replace file input using default mode', async function () {
const instantiationService = workbenchInstantiationService();
const editorService = new MockEditorService(instantiationService);
instantiationService.stub(IEditorService, editorService);
const contrib = instantiationService.createInstance(EditorReplacementContribution);
const accessor = instantiationService.createInstance(ServiceAccessor);
@@ -137,8 +145,8 @@ suite('Editor Replacer Contribution', () => {
});
test('does not replace editors that it shouldnt', async () => {
const editorService = new MockEditorService();
const instantiationService = workbenchInstantiationService();
const editorService = new MockEditorService(instantiationService);
instantiationService.stub(IEditorService, editorService);
const contrib = instantiationService.createInstance(EditorReplacementContribution);
const accessor = instantiationService.createInstance(ServiceAccessor);
@@ -152,8 +160,8 @@ suite('Editor Replacer Contribution', () => {
});
test('does not replace editors if it doesnt have a replacer', async () => {
const editorService = new MockEditorService();
const instantiationService = workbenchInstantiationService();
const editorService = new MockEditorService(instantiationService);
instantiationService.stub(IEditorService, editorService);
const contrib = instantiationService.createInstance(EditorReplacementContribution);
const accessor = instantiationService.createInstance(ServiceAccessor);
@@ -167,6 +175,10 @@ suite('Editor Replacer Contribution', () => {
});
class MockEditorService extends TestEditorService {
constructor(private readonly instantiationService: IInstantiationService) {
super();
}
readonly overridenOpens: IOpenEditorOverrideHandler[] = [];
overrideOpenEditor(_handler: IOpenEditorOverrideHandler): IDisposable {
@@ -192,6 +204,12 @@ class MockEditorService extends TestEditorService {
openEditor(_editor: any, _options?: any, _group?: any): Promise<any> {
return Promise.resolve(_editor);
}
createInput(_input: IUntitledTextResourceInput): EditorInput {
const accessor = this.instantiationService.createInstance(ServiceAccessor);
const service = accessor.untitledTextEditorService;
return this.instantiationService.createInstance(UntitledTextEditorInput, service.create());
}
}
class TestModeService implements IModeService {

View File

@@ -21,6 +21,7 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic
import { onUnexpectedError } from 'vs/base/common/errors';
import { IFileService } from 'vs/platform/files/common/files';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IQueryEditorService } from 'sql/workbench/services/queryEditor/common/queryEditorService';
const editorInputFactoryRegistry = Registry.as<IEditorInputFactoryRegistry>(EditorInputExtensions.EditorInputFactories);
@@ -31,9 +32,37 @@ export class QueryEditorLanguageAssociation implements ILanguageAssociation {
constructor(@IInstantiationService private readonly instantiationService: IInstantiationService,
@IObjectExplorerService private readonly objectExplorerService: IObjectExplorerService,
@IConnectionManagementService private readonly connectionManagementService: IConnectionManagementService,
@IEditorService private readonly editorService: IEditorService) { }
@IEditorService private readonly editorService: IEditorService,
@IQueryEditorService private readonly queryEditorService: IQueryEditorService) { }
convertInput(activeEditor: IEditorInput): QueryEditorInput | undefined {
async convertInput(activeEditor: IEditorInput): Promise<QueryEditorInput | undefined> {
const queryResultsInput = this.instantiationService.createInstance(QueryResultsInput, activeEditor.resource.toString(true));
let queryEditorInput: QueryEditorInput;
if (activeEditor instanceof FileEditorInput) {
queryEditorInput = this.instantiationService.createInstance(FileQueryEditorInput, '', activeEditor, queryResultsInput);
} else if (activeEditor instanceof UntitledTextEditorInput) {
const content = (await activeEditor.resolve()).textEditorModel.getValue();
queryEditorInput = (this.queryEditorService.newSqlEditor(content) as any) as UntitledQueryEditorInput;
} else {
return undefined;
}
const profile = getCurrentGlobalConnection(this.objectExplorerService, this.connectionManagementService, this.editorService);
if (profile) {
const options: IConnectionCompletionOptions = {
params: { connectionType: ConnectionType.editor, runQueryOnCompletion: undefined, input: queryEditorInput },
saveTheConnection: false,
showDashboard: false,
showConnectionDialogOnError: true,
showFirewallRuleOnError: true
};
this.connectionManagementService.connect(profile, queryEditorInput.uri, options).catch(err => onUnexpectedError(err));
}
return queryEditorInput;
}
syncConvertinput(activeEditor: IEditorInput): QueryEditorInput | undefined {
const queryResultsInput = this.instantiationService.createInstance(QueryResultsInput, activeEditor.resource.toString(true));
let queryEditorInput: QueryEditorInput;
if (activeEditor instanceof FileEditorInput) {

View File

@@ -21,10 +21,11 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
import { UntitledQueryEditorInput } from 'sql/workbench/common/editor/query/untitledQueryEditorInput';
import { UntitledTextEditorInput } from 'vs/workbench/services/untitled/common/untitledTextEditorInput';
import { IUntitledTextEditorService } from 'vs/workbench/services/untitled/common/untitledTextEditorService';
import { isThenable } from 'vs/base/common/async';
suite('Query Input Factory', () => {
test('query editor input is connected if global connection exists (OE)', () => {
test('sync query editor input is connected if global connection exists (OE)', () => {
const editorService = new MockEditorService();
const instantiationService = workbenchInstantiationService();
const connectionManagementService = new MockConnectionManagementService();
@@ -37,7 +38,22 @@ suite('Query Input Factory', () => {
assert(connectionManagementService.numberConnects === 1, 'Convert input should have called connect when active OE connection exists');
});
test('query editor input is connected if global connection exists (Editor)', () => {
test('query editor input is connected if global connection exists (OE)', async () => {
const editorService = new MockEditorService();
const instantiationService = workbenchInstantiationService();
const connectionManagementService = new MockConnectionManagementService();
instantiationService.stub(IObjectExplorerService, new MockObjectExplorerService());
instantiationService.stub(IConnectionManagementService, connectionManagementService);
instantiationService.stub(IEditorService, editorService);
const queryEditorLanguageAssociation = instantiationService.createInstance(QueryEditorLanguageAssociation);
const input = instantiationService.createInstance(FileEditorInput, URI.file('/test/file.sql'), undefined, undefined);
const response = queryEditorLanguageAssociation.convertInput(input);
assert(isThenable(response));
await response;
assert(connectionManagementService.numberConnects === 1, 'Convert input should have called connect when active OE connection exists');
});
test('sync query editor input is connected if global connection exists (Editor)', () => {
const instantiationService = workbenchInstantiationService();
const editorService = new MockEditorService(instantiationService);
const connectionManagementService = new MockConnectionManagementService();
@@ -50,7 +66,22 @@ suite('Query Input Factory', () => {
assert(connectionManagementService.numberConnects === 1, 'Convert input should have called connect when active editor connection exists');
});
test('query editor input is not connected if no global connection exists', () => {
test('query editor input is connected if global connection exists (Editor)', async () => {
const instantiationService = workbenchInstantiationService();
const editorService = new MockEditorService(instantiationService);
const connectionManagementService = new MockConnectionManagementService();
instantiationService.stub(IObjectExplorerService, new MockObjectExplorerService());
instantiationService.stub(IConnectionManagementService, connectionManagementService);
instantiationService.stub(IEditorService, editorService);
const queryEditorLanguageAssociation = instantiationService.createInstance(QueryEditorLanguageAssociation);
const input = instantiationService.createInstance(FileEditorInput, URI.file('/test/file.sql'), undefined, undefined);
const response = queryEditorLanguageAssociation.convertInput(input);
assert(isThenable(response));
await response;
assert(connectionManagementService.numberConnects === 1, 'Convert input should have called connect when active editor connection exists');
});
test('sync query editor input is not connected if no global connection exists', () => {
const instantiationService = workbenchInstantiationService();
const editorService = new MockEditorService();
const connectionManagementService = new MockConnectionManagementService();
@@ -58,7 +89,21 @@ suite('Query Input Factory', () => {
instantiationService.stub(IEditorService, editorService);
const queryEditorLanguageAssociation = instantiationService.createInstance(QueryEditorLanguageAssociation);
const input = instantiationService.createInstance(FileEditorInput, URI.file('/test/file.sql'), undefined, undefined);
queryEditorLanguageAssociation.convertInput(input);
queryEditorLanguageAssociation.syncConvertinput(input);
assert(connectionManagementService.numberConnects === 0, 'Convert input should not have been called connect when no global connections exist');
});
test('async query editor input is not connected if no global connection exists', async () => {
const instantiationService = workbenchInstantiationService();
const editorService = new MockEditorService();
const connectionManagementService = new MockConnectionManagementService();
instantiationService.stub(IConnectionManagementService, connectionManagementService);
instantiationService.stub(IEditorService, editorService);
const queryEditorLanguageAssociation = instantiationService.createInstance(QueryEditorLanguageAssociation);
const input = instantiationService.createInstance(FileEditorInput, URI.file('/test/file.sql'), undefined, undefined);
const response = queryEditorLanguageAssociation.convertInput(input);
assert(isThenable(response));
await response;
assert(connectionManagementService.numberConnects === 0, 'Convert input should not have been called connect when no global connections exist');
});