Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
8 changes: 8 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,14 @@
"configuration": {
"properties": {
"python.ty.disableLanguageServices": {
"default": false,
"markdownDescription": "Whether to disable all language services for ty like completions, hover, goto definition, etc.",
"markdownDeprecationMessage": "**Deprecated**: Please use `ty.disableLanguageServices` instead.",
"deprecationMessage": "Deprecated: Please use ty.disableLanguageServices instead.",
"scope": "window",
"type": "boolean"
},
"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