Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@
"contributes": {
"configuration": {
"properties": {
"python.ty.disableLanguageServices": {
"ty.disableLanguageServices": {
"default": false,
"markdownDescription": "Whether to disable all language services for ty like completions, hover, goto definition, etc.",
"scope": "window",
Expand Down
36 changes: 14 additions & 22 deletions src/common/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ import {
SERVER_SUBCOMMAND,
} from "./constants";
import { logger } from "./logger";
import { getExtensionSettings, getGlobalSettings, type ISettings } from "./settings";
import {
getInitializationOptions,
InitializationOptions,
type ExtensionSettings,
} from "./settings";
import { updateStatus } from "./status";
import { getDocumentSelector } from "./utilities";

Expand All @@ -28,11 +32,6 @@ import which = require("which");
import { createTyMiddleware } from "../client";
import { getPythonExtensionAPI } from "./python";

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

/**
* Check if shell mode is required for `execFile`.
*
Expand Down Expand Up @@ -76,7 +75,7 @@ function executeFile(file: string, args: string[] = []): Promise<string> {
* which checks the PATH environment variable.
* 5. If all else fails, return the bundled executable path.
*/
async function findBinaryPath(settings: ISettings): Promise<string> {
async function findBinaryPath(settings: ExtensionSettings): Promise<string> {
if (!vscode.workspace.isTrusted) {
logger.info(`Workspace is not trusted, using bundled executable: ${BUNDLED_EXECUTABLE}`);
return BUNDLED_EXECUTABLE;
Expand Down Expand Up @@ -136,12 +135,12 @@ async function findBinaryPath(settings: ISettings): Promise<string> {
}

async function createServer(
settings: ISettings,
settings: ExtensionSettings,
serverId: string,
serverName: string,
outputChannel: OutputChannel,
traceOutputChannel: OutputChannel,
initializationOptions: IInitializationOptions,
initializationOptions: InitializationOptions,
middleware?: Middleware,
): Promise<LanguageClient> {
const binaryPath = await findBinaryPath(settings);
Expand Down Expand Up @@ -172,34 +171,27 @@ async function createServer(
let _disposables: Disposable[] = [];

export async function startServer(
workspaceSettings: ISettings,
settings: ExtensionSettings,
serverId: string,
serverName: string,
outputChannel: OutputChannel,
traceOutputChannel: OutputChannel,
): Promise<LanguageClient | undefined> {
updateStatus(undefined, LanguageStatusSeverity.Information, true);

const extensionSettings = await getExtensionSettings(serverId);
for (const settings of extensionSettings) {
logger.info(`Workspace settings for ${settings.cwd}: ${JSON.stringify(settings, null, 4)}`);
}
const globalSettings = await getGlobalSettings(serverId);
logger.info(`Global settings: ${JSON.stringify(globalSettings, null, 4)}`);
const pythonExtension = await getPythonExtensionAPI();
const initializationOptions = getInitializationOptions(serverId);
logger.info(`Initialization options: ${JSON.stringify(initializationOptions, null, 4)}`);

const pythonExtension = await getPythonExtensionAPI();
const middleware = createTyMiddleware(pythonExtension);

const newLSClient = await createServer(
workspaceSettings,
settings,
serverId,
serverName,
outputChannel,
traceOutputChannel,
{
settings: extensionSettings,
globalSettings: globalSettings,
},
initializationOptions,
middleware,
);
logger.info("Server: Start requested.");
Expand Down
80 changes: 17 additions & 63 deletions src/common/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,32 +12,16 @@ type ImportStrategy = "fromEnvironment" | "useBundled";

type LogLevel = "error" | "warn" | "info" | "debug" | "trace";

type PythonSettings = {
ty?: {
disableLanguageServices?: boolean;
};
};

type DiagnosticMode = "openFilesOnly" | "workspace";
export interface InitializationOptions {
logLevel?: LogLevel;
logFile?: string;
}

export interface ISettings {
export interface ExtensionSettings {
cwd: string;
workspace: string;
path: string[];
interpreter: string[];
importStrategy: ImportStrategy;
diagnosticMode: DiagnosticMode;
logLevel?: LogLevel;
logFile?: string;
python?: PythonSettings;
}

export function getExtensionSettings(namespace: string): Promise<ISettings[]> {
return Promise.all(
getWorkspaceFolders().map((workspaceFolder) =>
getWorkspaceSettings(namespace, workspaceFolder),
),
);
}

function resolveVariables(value: string[], workspace?: WorkspaceFolder): string[];
Expand Down Expand Up @@ -80,29 +64,23 @@ function resolveVariables(
}
}

export function getInitializationOptions(namespace: string): InitializationOptions {
const config = getConfiguration(namespace);
return {
logLevel: getOptionalGlobalValue<LogLevel>(config, "logLevel"),
logFile: getOptionalGlobalValue<string>(config, "logFile"),
};
}

export function getInterpreterFromSetting(namespace: string, scope?: ConfigurationScope) {
const config = getConfiguration(namespace, scope);
return config.get<string[]>("interpreter");
}

function getPythonSettings(workspace?: WorkspaceFolder): PythonSettings | undefined {
const config = getConfiguration("python", workspace?.uri);
const disableLanguageServices = config.get<boolean>("ty.disableLanguageServices");
if (disableLanguageServices !== undefined) {
return {
ty: {
disableLanguageServices,
},
};
}

return undefined;
}

export async function getWorkspaceSettings(
export async function getExtensionSettings(
namespace: string,
workspace: WorkspaceFolder,
): Promise<ISettings> {
): Promise<ExtensionSettings> {
const config = getConfiguration(namespace, workspace.uri);

let interpreter: string[] = getInterpreterFromSetting(namespace, workspace) ?? [];
Expand All @@ -116,42 +94,17 @@ export async function getWorkspaceSettings(

return {
cwd: workspace.uri.fsPath,
workspace: workspace.uri.toString(),
path: resolveVariables(config.get<string[]>("path") ?? [], workspace),
interpreter,
importStrategy: config.get<ImportStrategy>("importStrategy") ?? "fromEnvironment",
diagnosticMode: config.get<DiagnosticMode>("diagnosticMode") ?? "openFilesOnly",
logLevel: config.get<LogLevel>("logLevel"),
logFile: config.get<string>("logFile"),
python: getPythonSettings(workspace),
};
}

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

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

export async function getGlobalSettings(namespace: string): Promise<ISettings> {
const config = getConfiguration(namespace);
return {
cwd: process.cwd(),
workspace: process.cwd(),
path: getGlobalValue<string[]>(config, "path", []),
interpreter: [],
importStrategy: getGlobalValue<ImportStrategy>(config, "importStrategy", "fromEnvironment"),
diagnosticMode: getGlobalValue<DiagnosticMode>(config, "diagnosticMode", "openFilesOnly"),
logLevel: getOptionalGlobalValue<LogLevel>(config, "logLevel"),
logFile: getOptionalGlobalValue<string>(config, "logFile"),
python: getPythonSettings(),
};
}

export function checkIfConfigurationChanged(
e: ConfigurationChangeEvent,
namespace: string,
Expand All @@ -162,8 +115,9 @@ export function checkIfConfigurationChanged(
`${namespace}.path`,
`${namespace}.logLevel`,
`${namespace}.logFile`,
// TODO: Remove these once `workspace/didChangeConfiguration` is supported in the server
`${namespace}.diagnosticMode`,
"python.ty.disableLanguageServices",
`${namespace}.disableLanguageServices`,
];
return settings.some((s) => e.affectsConfiguration(s));
}
14 changes: 7 additions & 7 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { startServer, stopServer } from "./common/server";
import {
checkIfConfigurationChanged,
getInterpreterFromSetting,
getWorkspaceSettings,
getExtensionSettings,
} from "./common/settings";
import { loadServerDefaults } from "./common/setup";
import { registerLanguageStatusItem, updateStatus } from "./common/status";
Expand Down Expand Up @@ -78,10 +78,10 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
}

const projectRoot = await getProjectRoot();
const workspaceSettings = await getWorkspaceSettings(serverId, projectRoot);
const settings = await getExtensionSettings(serverId, projectRoot);

if (vscode.workspace.isTrusted) {
if (workspaceSettings.interpreter.length === 0) {
if (settings.interpreter.length === 0) {
updateStatus(
vscode.l10n.t("Please select a Python interpreter."),
vscode.LanguageStatusSeverity.Error,
Expand All @@ -95,16 +95,16 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
return;
}

logger.info(`Using interpreter: ${workspaceSettings.interpreter.join(" ")}`);
const resolvedEnvironment = await resolveInterpreter(workspaceSettings.interpreter);
logger.info(`Using interpreter: ${settings.interpreter.join(" ")}`);
const resolvedEnvironment = await resolveInterpreter(settings.interpreter);
if (resolvedEnvironment === undefined) {
updateStatus(
vscode.l10n.t("Python interpreter not found."),
vscode.LanguageStatusSeverity.Error,
);
logger.error(
"Unable to find any Python environment for the interpreter path:",
workspaceSettings.interpreter.join(" "),
settings.interpreter.join(" "),
);
return;
}
Expand All @@ -115,7 +115,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
}

lsClient = await startServer(
workspaceSettings,
settings,
serverId,
serverName,
outputChannel,
Expand Down