Skip to content

Commit

Permalink
Ensure global settings are passed to the server.
Browse files Browse the repository at this point in the history
  • Loading branch information
karthiknadig committed Feb 22, 2023
1 parent 4df14cb commit fea5067
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 20 deletions.
69 changes: 53 additions & 16 deletions bundled/tool/lsp_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ def update_sys_path(path_to_add: str, strategy: str) -> None:
from pygls import server, uris, workspace

WORKSPACE_SETTINGS = {}
GLOBAL_SETTINGS = {}
RUNNER = pathlib.Path(__file__).parent / "runner.py"

MAX_WORKERS = 5
Expand Down Expand Up @@ -343,6 +344,9 @@ def initialize(params: lsp.InitializeParams) -> None:
import_strategy = os.getenv("LS_IMPORT_STRATEGY", "useBundled")
update_sys_path(os.getcwd(), import_strategy)

global GLOBAL_SETTINGS
GLOBAL_SETTINGS = params.initialization_options.get("globalSettings", {})

settings = params.initialization_options["settings"]
_update_workspace_settings(settings)
log_to_output(
Expand Down Expand Up @@ -418,26 +422,35 @@ def _log_version_info() -> None:
# *****************************************************
# Internal functional and settings management APIs.
# *****************************************************
def _update_workspace_settings(settings):
if not settings:
key = os.getcwd()
WORKSPACE_SETTINGS[key] = {
"cwd": key,
"workspaceFS": key,
"workspace": uris.from_fs_path(key),
"path": [],
"interpreter": [sys.executable],
"args": [],
"severity": {
def _get_global_defaults():
return {
"path": GLOBAL_SETTINGS.get("path", []),
"interpreter": GLOBAL_SETTINGS.get("interpreter", [sys.executable]),
"args": GLOBAL_SETTINGS.get("args", []),
"severity": GLOBAL_SETTINGS.get(
"severity",
{
"convention": "Information",
"error": "Error",
"fatal": "Error",
"refactor": "Hint",
"warning": "Warning",
"info": "Information",
},
"importStrategy": "useBundled",
"showNotifications": "off",
),
"importStrategy": GLOBAL_SETTINGS.get("importStrategy", "useBundled"),
"showNotifications": GLOBAL_SETTINGS.get("showNotifications", "off"),
"extraPaths": GLOBAL_SETTINGS.get("extraPaths", []),
}

def _update_workspace_settings(settings):
if not settings:
key = os.getcwd()
WORKSPACE_SETTINGS[key] = {
"cwd": key,
"workspaceFS": key,
"workspace": uris.from_fs_path(key),
**_get_global_defaults(),
}
return

Expand All @@ -462,12 +475,36 @@ def _get_settings_by_path(file_path: pathlib.Path):
return setting_values[0]


def _get_document_key(document: workspace.Document):
if WORKSPACE_SETTINGS:
document_workspace = pathlib.Path(document.path)
workspaces = {s["workspaceFS"] for s in WORKSPACE_SETTINGS.values()}

# Find workspace settings for the given file.
while document_workspace != document_workspace.parent:
if str(document_workspace) in workspaces:
return str(document_workspace)
document_workspace = document_workspace.parent

return None


def _get_settings_by_document(document: workspace.Document | None):
if len(WORKSPACE_SETTINGS) == 1 or document is None or document.path is None:
if document is None or document.path is None:
return list(WORKSPACE_SETTINGS.values())[0]

document_workspace = pathlib.Path(document.path)
return _get_settings_by_path(document_workspace)
key = _get_document_key(document)
if key is None:
# This is either a non-workspace file or there is no workspace.
key = os.fspath(pathlib.Path(document.path).parent)
return {
"cwd": key,
"workspaceFS": key,
"workspace": uris.from_fs_path(key),
**_get_global_defaults(),
}

return WORKSPACE_SETTINGS[str(key)]


# *****************************************************
Expand Down
5 changes: 3 additions & 2 deletions src/common/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ import {
import { DEBUG_SERVER_SCRIPT_PATH, SERVER_SCRIPT_PATH } from './constants';
import { traceError, traceInfo, traceVerbose } from './log/logging';
import { getDebuggerPath } from './python';
import { getExtensionSettings, getWorkspaceSettings, ISettings } from './settings';
import { getExtensionSettings, getGlobalSettings, getWorkspaceSettings, ISettings } from './settings';
import { getLSClientTraceLevel, getProjectRoot } from './utilities';
import { isVirtualWorkspace } from './vscodeapi';

export type IInitOptions = { settings: ISettings[] };
export type IInitOptions = { settings: ISettings[]; globalSettings: ISettings };

async function createServer(
projectRoot: WorkspaceFolder,
Expand Down Expand Up @@ -109,6 +109,7 @@ export async function restartServer(
outputChannel,
{
settings: await getExtensionSettings(serverId, true),
globalSettings: await getGlobalSettings(serverId, false),
},
workspaceSetting,
);
Expand Down
32 changes: 31 additions & 1 deletion src/common/settings.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

import { ConfigurationChangeEvent, WorkspaceFolder } from 'vscode';
import { ConfigurationChangeEvent, WorkspaceConfiguration, WorkspaceFolder } from 'vscode';
import { traceLog } from './log/logging';
import { getInterpreterDetails } from './python';
import { getConfiguration, getWorkspaceFolders } from './vscodeapi';
Expand Down Expand Up @@ -136,6 +136,36 @@ export async function getWorkspaceSettings(
return workspaceSetting;
}

function getGlobalValue<T>(config: WorkspaceConfiguration, key: string, defaultValue: T): T {
const inspect = config.inspect<T>(key);
return inspect?.globalValue ?? inspect?.defaultValue ?? defaultValue;
}

export async function getGlobalSettings(namespace: string, includeInterpreter?: boolean): Promise<ISettings> {
const config = getConfiguration(namespace);

let interpreter: string[] | undefined = [];
if (includeInterpreter) {
interpreter = getGlobalValue<string[]>(config, 'interpreter', []);
if (interpreter === undefined || interpreter.length === 0) {
interpreter = (await getInterpreterDetails()).path;
}
}

const setting = {
cwd: process.cwd(),
workspace: process.cwd(),
args: getGlobalValue<string[]>(config, 'args', []),
severity: getGlobalValue<Record<string, string>>(config, 'severity', DEFAULT_SEVERITY),
path: getGlobalValue<string[]>(config, 'path', []),
interpreter: interpreter ?? [],
importStrategy: getGlobalValue<string>(config, 'importStrategy', 'fromEnvironment'),
showNotifications: getGlobalValue<string>(config, 'showNotifications', 'off'),
extraPaths: getGlobalValue<string[]>(config, 'extraPaths', []),
};
return setting;
}

export function checkIfConfigurationChanged(e: ConfigurationChangeEvent, namespace: string): boolean {
const settings = [
`${namespace}.args`,
Expand Down
2 changes: 1 addition & 1 deletion src/test/python_tests/lsp_test_client/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,4 @@ def get_initialization_options():
setting["cwd"] = str(PROJECT_ROOT)
setting["extraPaths"] = []

return {"settings": [setting]}
return {"settings": [setting], "globalSettings": setting}

0 comments on commit fea5067

Please sign in to comment.