Skip to content

Commit

Permalink
redhat-developer#327 use 'workspace/configuration' to fetch settings
Browse files Browse the repository at this point in the history
Signed-off-by: Yevhen Vydolob <[email protected]>
  • Loading branch information
evidolob committed May 27, 2021
1 parent 38aad39 commit 5d23b73
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 21 deletions.
39 changes: 28 additions & 11 deletions src/languageserver/handlers/settingsHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { xhr, configure as configureHttpRequests } from 'request-light';
import { DidChangeConfigurationParams, DocumentFormattingRequest, Connection } from 'vscode-languageserver';
import { DocumentFormattingRequest, Connection, DidChangeConfigurationNotification } from 'vscode-languageserver';
import { isRelativePath, relativeToAbsolutePath } from '../../languageservice/utils/paths';
import { checkSchemaURI, JSON_SCHEMASTORE_URL, KUBERNETES_SCHEMA_URL } from '../../languageservice/utils/schemaUrls';
import { LanguageService, LanguageSettings, SchemaPriority } from '../../languageservice/yamlLanguageService';
Expand All @@ -21,16 +21,35 @@ export class SettingsHandler {
) {}

public registerHandlers(): void {
this.connection.onDidChangeConfiguration((change) => this.configurationChangeHandler(change));
if (this.yamlSettings.hasConfigurationCapability) {
// Register for all configuration changes.
this.connection.client.register(DidChangeConfigurationNotification.type, undefined);
}
this.connection.onDidChangeConfiguration(() => this.pullConfiguration());
}

/**
* Run when the editor configuration is changed
* The client syncs the 'yaml', 'http.proxy', 'http.proxyStrictSSL' settings sections
* Update relevant settings with fallback to defaults if needed
* The server pull the 'yaml', 'http.proxy', 'http.proxyStrictSSL', '[yaml]' settings sections
*/
private configurationChangeHandler(change: DidChangeConfigurationParams): void {
const settings = change.settings as Settings;
async pullConfiguration(): Promise<void> {
const config = await this.connection.workspace.getConfiguration([
{ section: 'yaml' },
{ section: 'http.proxy' },
{ section: 'http.proxyStrictSSL' },
{ section: '[yaml]' },
]);
const settings: Settings = {
yaml: config[0],
http: {
proxy: config[1],
proxyStrictSSL: config[2],
},
yamlEditor: config[3],
};
this.setConfiguration(settings);
}

setConfiguration(settings: Settings): void {
configureHttpRequests(settings.http && settings.http.proxy, settings.http && settings.http.proxyStrictSSL);

this.yamlSettings.specificValidatorPaths = [];
Expand Down Expand Up @@ -81,10 +100,8 @@ export class SettingsHandler {

this.yamlSettings.schemaConfigurationSettings = [];

if (settings['[yaml]'] && settings['[yaml]']['editor.tabSize']) {
this.yamlSettings.indentation = ' '.repeat(settings['[yaml]']['editor.tabSize']);
} else if (settings.editor?.tabSize) {
this.yamlSettings.indentation = ' '.repeat(settings.editor.tabSize);
if (settings.yamlEditor && settings.yamlEditor['editor.tabSize']) {
this.yamlSettings.indentation = ' '.repeat(settings.yamlEditor['editor.tabSize']);
}

for (const uri in this.yamlSettings.yamlConfigurationSettings) {
Expand Down
13 changes: 10 additions & 3 deletions src/yamlServerInit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export class YAMLServerInit {
languageService: LanguageService;
languageHandler: LanguageHandlers;
validationHandler: ValidationHandler;
settingsHandler: SettingsHandler;

private telemetry: Telemetry;
constructor(
Expand All @@ -48,6 +49,9 @@ export class YAMLServerInit {
this.yamlSettings.workspaceFolders = workspaceFoldersChanged(this.yamlSettings.workspaceFolders, changedFolders);
});
}
// need to call this after connection initialized
this.settingsHandler.registerHandlers();
this.settingsHandler.pullConfiguration();
});
}

Expand Down Expand Up @@ -81,6 +85,9 @@ export class YAMLServerInit {
this.yamlSettings.hasWorkspaceFolderCapability =
this.yamlSettings.capabilities.workspace && !!this.yamlSettings.capabilities.workspace.workspaceFolders;

this.yamlSettings.hasConfigurationCapability = !!(
this.yamlSettings.capabilities.workspace && !!this.yamlSettings.capabilities.workspace.configuration
);
this.registerHandlers();

return {
Expand Down Expand Up @@ -117,17 +124,17 @@ export class YAMLServerInit {
private registerHandlers(): void {
// Register all features that the language server has
this.validationHandler = new ValidationHandler(this.connection, this.languageService, this.yamlSettings);
const settingsHandler = new SettingsHandler(
this.settingsHandler = new SettingsHandler(
this.connection,
this.languageService,
this.yamlSettings,
this.validationHandler,
this.telemetry
);
settingsHandler.registerHandlers();
// this.settingsHandler.registerHandlers();
this.languageHandler = new LanguageHandlers(this.connection, this.languageService, this.yamlSettings, this.validationHandler);
this.languageHandler.registerHandlers();
new NotificationHandlers(this.connection, this.languageService, this.yamlSettings, settingsHandler).registerHandlers();
new NotificationHandlers(this.connection, this.languageService, this.yamlSettings, this.settingsHandler).registerHandlers();
new RequestHandlers(this.connection, this.languageService).registerHandlers();
new WorkspaceHandlers(this.connection, commandExecutor).registerHandlers();
}
Expand Down
7 changes: 5 additions & 2 deletions src/yamlSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@ export interface Settings {
proxy: string;
proxyStrictSSL: boolean;
};
editor: {
tabSize: number;
yamlEditor: {
'editor.tabSize': number;
'editor.insertSpaces': boolean;
'editor.formatOnType': boolean;
};
}

Expand Down Expand Up @@ -77,6 +79,7 @@ export class SettingsState {
clientDynamicRegisterSupport = false;
hierarchicalDocumentSymbolSupport = false;
hasWorkspaceFolderCapability = false;
hasConfigurationCapability = false;
useVSCodeContentRequest = false;
}

Expand Down
38 changes: 33 additions & 5 deletions test/settingsHandlers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,30 @@ import { SettingsHandler } from '../src/languageserver/handlers/settingsHandlers
import * as sinon from 'sinon';
import * as chai from 'chai';
import * as sinonChai from 'sinon-chai';
import { Connection } from 'vscode-languageserver';
import { Connection, RemoteWorkspace } from 'vscode-languageserver';
import { SettingsState } from '../src/yamlSettings';
import { ValidationHandler } from '../src/languageserver/handlers/validationHandlers';
import { LanguageService, LanguageSettings, SchemaConfiguration, SchemaPriority } from '../src';
import * as request from 'request-light';
import { setupLanguageService } from './utils/testHelper';
import { Telemetry } from '../src/languageserver/telemetry';
import { TestWorkspace } from './utils/testsTypes';

const expect = chai.expect;
chai.use(sinonChai);

describe('Settings Handlers Tests', () => {
const sandbox = sinon.createSandbox();
let connectionStub: sinon.SinonMockStatic;
const connection: Connection = {} as Connection;
let workspaceStub: sinon.SinonStubbedInstance<RemoteWorkspace>;
let languageService: sinon.SinonMockStatic;
let settingsState: SettingsState;
let validationHandler: sinon.SinonMock;
let xhrStub: sinon.SinonStub;

beforeEach(() => {
connectionStub = sandbox.mock();
workspaceStub = sandbox.createStubInstance(TestWorkspace);
connection.workspace = (workspaceStub as unknown) as RemoteWorkspace;
languageService = sandbox.mock();
settingsState = new SettingsState();
validationHandler = sandbox.mock(ValidationHandler);
Expand All @@ -51,7 +54,7 @@ describe('Settings Handlers Tests', () => {
}]}`,
});
const settingsHandler = new SettingsHandler(
(connectionStub as unknown) as Connection,
connection,
(languageService as unknown) as LanguageService,
settingsState,
(validationHandler as unknown) as ValidationHandler,
Expand All @@ -78,7 +81,7 @@ describe('Settings Handlers Tests', () => {

const languageService = languageServerSetup.languageService;
const settingsHandler = new SettingsHandler(
(connectionStub as unknown) as Connection,
connection,
languageService,
settingsState,
(validationHandler as unknown) as ValidationHandler,
Expand Down Expand Up @@ -143,4 +146,29 @@ describe('Settings Handlers Tests', () => {
});
});
});

describe('Settings fetch', () => {
it('should fetch preferences', async () => {
const settingsHandler = new SettingsHandler(
connection,
(languageService as unknown) as LanguageService,
settingsState,
(validationHandler as unknown) as ValidationHandler,
{} as Telemetry
);
workspaceStub.getConfiguration.resolves([{}, {}, {}, {}]);
const setConfigurationStub = sandbox.stub(settingsHandler, 'setConfiguration');

await settingsHandler.pullConfiguration();

expect(workspaceStub.getConfiguration).calledOnceWith([
{ section: 'yaml' },
{ section: 'http.proxy' },
{ section: 'http.proxyStrictSSL' },
{ section: '[yaml]' },
]);

expect(setConfigurationStub).calledOnce;
});
});
});
57 changes: 57 additions & 0 deletions test/utils/testsTypes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Red Hat. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { Event, NotificationHandler, RequestHandler } from 'vscode-jsonrpc';
import {
ApplyWorkspaceEditParams,
WorkspaceEdit,
ApplyWorkspaceEditResponse,
ConfigurationItem,
WorkspaceFolder,
WorkspaceFoldersChangeEvent,
CreateFilesParams,
RenameFilesParams,
DeleteFilesParams,
} from 'vscode-languageserver-protocol';
import { Connection, RemoteWorkspace } from 'vscode-languageserver/lib/common/server';

/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
export class TestWorkspace implements RemoteWorkspace {
connection: Connection;
applyEdit(paramOrEdit: ApplyWorkspaceEditParams | WorkspaceEdit): Promise<ApplyWorkspaceEditResponse> {
throw new Error('Method not implemented.');
}
getConfiguration(): Promise<any>;
getConfiguration(section: string): Promise<any>;
getConfiguration(item: ConfigurationItem): Promise<any>;
getConfiguration(items: ConfigurationItem[]): Promise<any[]>;
getConfiguration(items?: any): Promise<any | any[]> {
throw new Error('Method not implemented.');
}
getWorkspaceFolders(): Promise<WorkspaceFolder[]> {
throw new Error('Method not implemented.');
}
onDidChangeWorkspaceFolders: Event<WorkspaceFoldersChangeEvent>;
onDidCreateFiles(handler: NotificationHandler<CreateFilesParams>): void {
throw new Error('Method not implemented.');
}
onDidRenameFiles(handler: NotificationHandler<RenameFilesParams>): void {
throw new Error('Method not implemented.');
}
onDidDeleteFiles(handler: NotificationHandler<DeleteFilesParams>): void {
throw new Error('Method not implemented.');
}
onWillCreateFiles(handler: RequestHandler<CreateFilesParams, WorkspaceEdit, never>): void {
throw new Error('Method not implemented.');
}
onWillRenameFiles(handler: RequestHandler<RenameFilesParams, WorkspaceEdit, never>): void {
throw new Error('Method not implemented.');
}
onWillDeleteFiles(handler: RequestHandler<DeleteFilesParams, WorkspaceEdit, never>): void {
throw new Error('Method not implemented.');
}
}

0 comments on commit 5d23b73

Please sign in to comment.