Skip to content
Draft
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
27 changes: 24 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,17 @@
"configuration": {
"title": "Meson build configuration",
"properties": {
"mesonbuild.trace.server": {
"type": "string",
"default": "off",
"scope": "window",
"enum": [
"off",
"messages",
"verbose"
],
"description": "Traces the communication between VS Code and the current Meson language server."
},
"mesonbuild.selectRootDir": {
"type": "boolean",
"default": true,
Expand Down Expand Up @@ -172,12 +183,18 @@
"description": "Specify the list of options used for running benchmarks. --benchmark is implicit."
},
"mesonbuild.mesonPath": {
"type": "string",
"type": [
"string",
"array"
],
"default": "meson",
"description": "Specify the meson executable to use"
},
"mesonbuild.muonPath": {
"type": "string",
"type": [
"string",
"array"
],
"default": "muon",
"description": "Specify the muon executable to use"
},
Expand Down Expand Up @@ -255,12 +272,16 @@
"enum": [
"Swift-MesonLSP",
"mesonlsp",
"muon",
null
],
"description": "Select which language server to use. Swift-MesonLSP is a legacy alias for mesonlsp."
},
"mesonbuild.languageServerPath": {
"type": "string",
"type": [
"string",
"array"
],
"description": "Binary name or path to language server",
"default": ""
},
Expand Down
15 changes: 5 additions & 10 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,14 +239,11 @@ export async function activate(ctx: vscode.ExtensionContext) {
await regenerateTests(controller);
}

const server = extensionConfiguration(SettingsKey.languageServer);
let client = await createLanguageServerClient(server, await askShouldDownloadLanguageServer(), ctx);
// Basically every server supports formatting...
const serverSupportsFormatting = server == "mesonlsp" || server == "Swift-MesonLSP";
if (client !== null && serverSupportsFormatting) {
let client = await createLanguageServerClient(await askShouldDownloadLanguageServer(), ctx);
if (client !== null) {
ctx.subscriptions.push(
vscode.workspace.onDidChangeConfiguration((e) => {
if (e.affectsConfiguration(`mesonbuild.${server}`)) {
if (e.affectsConfiguration(`mesonbuild.${client!.server}`)) {
client?.reloadConfig();
}
}),
Expand All @@ -257,9 +254,7 @@ export async function activate(ctx: vscode.ExtensionContext) {
client.start();
await client.reloadConfig();

getOutputChannel().appendLine(
"Not enabling the muon linter/formatter because a language server supporting formatting is active.",
);
getOutputChannel().appendLine("Linters and formatters disabled because a language server is active.");
} else {
activateLinters(sourceDir, ctx);
activateFormatters(sourceDir, ctx);
Expand All @@ -268,7 +263,7 @@ export async function activate(ctx: vscode.ExtensionContext) {
ctx.subscriptions.push(
vscode.commands.registerCommand("mesonbuild.restartLanguageServer", async () => {
if (client === null) {
client = await createLanguageServerClient(server, await askShouldDownloadLanguageServer(), ctx);
client = await createLanguageServerClient(await askShouldDownloadLanguageServer(), ctx);
if (client !== null) {
ctx.subscriptions.push(client);
client.start();
Expand Down
13 changes: 9 additions & 4 deletions src/lsp/common.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,29 @@
import * as vscode from "vscode";
import { LanguageServerClient } from ".";
import { LanguageServer } from "../types";
import { LanguageServer, SettingsKey } from "../types";
import { MesonLSPLanguageClient } from "./mesonlsp";
import { MuonLanguageClient } from "./muon";
import { Uri } from "vscode";
import { extensionConfiguration } from "../utils";

export function serverToClass(server: LanguageServer): any {
switch (server) {
case "Swift-MesonLSP":
case "mesonlsp":
return MesonLSPLanguageClient;
case "muon":
return MuonLanguageClient;
default:
return null;
}
}

export async function createLanguageServerClient(
server: LanguageServer,
download: boolean,
context: vscode.ExtensionContext,
): Promise<LanguageServerClient | null> {
const server = extensionConfiguration(SettingsKey.languageServer);

const klass = serverToClass(server);
if (klass == null) {
return null;
Expand All @@ -28,7 +33,7 @@ export async function createLanguageServerClient(
return null;
}

let languageServerPath = LanguageServerClient.resolveLanguageServerPath(server, context);
let [languageServerPath, args] = LanguageServerClient.resolveLanguageServerPath(server, context);
if (languageServerPath === null) {
if (klass.artifact() == null) {
enum Options {
Expand All @@ -55,5 +60,5 @@ export async function createLanguageServerClient(
}
}

return new klass(languageServerPath, context, klass.version);
return new klass(languageServerPath, args, context, klass.version);
}
38 changes: 23 additions & 15 deletions src/lsp/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ import {
TransportKind,
} from "vscode-languageclient/node";
import * as storage from "../storage";
import { LanguageServer } from "../types";
import { ExtensionConfiguration, LanguageServer } from "../types";
import { serverToClass } from "./common";
import { extensionConfiguration, resolveCommandAndArgs } from "../utils";

export abstract class LanguageServerClient {
private static readonly clientOptions: LanguageClientOptions = {
Expand All @@ -27,6 +28,7 @@ export abstract class LanguageServerClient {
private readonly context: vscode.ExtensionContext;

protected languageServerPath: vscode.Uri | null;
protected extraArgs: string[];
protected referenceVersion: string;
readonly server: LanguageServer;

Expand All @@ -40,11 +42,13 @@ export abstract class LanguageServerClient {
protected constructor(
server: LanguageServer,
languageServerPath: vscode.Uri,
extraArgs: string[],
context: vscode.ExtensionContext,
referenceVersion: string,
) {
this.server = server;
this.languageServerPath = languageServerPath;
this.extraArgs = extraArgs;
this.context = context;
this.referenceVersion = referenceVersion;
}
Expand Down Expand Up @@ -146,25 +150,26 @@ export abstract class LanguageServerClient {
return uri;
}

static resolveLanguageServerPath(server: LanguageServer, context: vscode.ExtensionContext): vscode.Uri | null {
const config = vscode.workspace.getConfiguration("mesonbuild");

const configLanguageServerPath = config["languageServerPath"];
if (configLanguageServerPath !== null && configLanguageServerPath != "") {
static resolveLanguageServerPath(
server: LanguageServer,
context: vscode.ExtensionContext,
): [vscode.Uri | null, string[]] {
const [configLanguageServerPath, args] = resolveCommandAndArgs(extensionConfiguration("languageServerPath"));
if (configLanguageServerPath !== null && configLanguageServerPath !== "") {
if (!path.isAbsolute(configLanguageServerPath)) {
const binary = which.sync(configLanguageServerPath, { nothrow: true });
if (binary !== null) return vscode.Uri.from({ scheme: "file", path: binary });
if (binary !== null) return [vscode.Uri.from({ scheme: "file", path: binary }), args];
}
return vscode.Uri.from({ scheme: "file", path: configLanguageServerPath });
return [vscode.Uri.from({ scheme: "file", path: configLanguageServerPath }), args];
}

const cached = LanguageServerClient.cachedLanguageServer(server, context);
if (cached !== null) return cached;
if (cached !== null) return [cached, args];

const binary = which.sync(server!, { nothrow: true });
if (binary !== null) return vscode.Uri.from({ scheme: "file", path: binary });
if (binary !== null) return [vscode.Uri.from({ scheme: "file", path: binary }), args];

return null;
return [null, args];
}

protected static supportsSystem(): boolean {
Expand All @@ -184,7 +189,10 @@ export abstract class LanguageServerClient {

async restart(): Promise<void> {
await this.dispose();
this.languageServerPath = LanguageServerClient.resolveLanguageServerPath(this.server, this.context);
[this.languageServerPath, this.extraArgs] = LanguageServerClient.resolveLanguageServerPath(
this.server,
this.context,
);
if (this.languageServerPath === null) {
vscode.window.showErrorMessage(
"Failed to restart the language server because a binary was not found and could not be downloaded",
Expand All @@ -201,9 +209,9 @@ export abstract class LanguageServerClient {
transport: TransportKind.stdio,
};
const options = LanguageServerClient.clientOptions;
options.initializationOptions = vscode.workspace.getConfiguration(`mesonbuild.${this.server}`);
options.initializationOptions = extensionConfiguration(`mesonbuild.${this.server}` as keyof ExtensionConfiguration);
this.ls = new LanguageClient(
this.server!,
"mesonbuild",
`Meson Language Server (${this.server})`,
serverOptions,
LanguageServerClient.clientOptions,
Expand All @@ -213,7 +221,7 @@ export abstract class LanguageServerClient {
}

async reloadConfig(): Promise<void> {
const config = vscode.workspace.getConfiguration(`mesonbuild.${this.server}`);
const config = extensionConfiguration(`mesonbuild.${this.server}` as keyof ExtensionConfiguration);
const params: DidChangeConfigurationParams = {
settings: config,
};
Expand Down
13 changes: 9 additions & 4 deletions src/lsp/mesonlsp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,24 @@ export class MesonLSPLanguageClient extends LanguageServerClient {
get runExe(): Executable {
return {
command: this.languageServerPath!.fsPath,
args: ["--lsp"],
args: [...this.extraArgs, "--lsp"],
};
}

get debugExe(): Executable {
return {
command: this.languageServerPath!.fsPath,
args: ["--lsp"],
args: [...this.extraArgs, "--lsp"],
};
}

constructor(languageServerPath: vscode.Uri, context: vscode.ExtensionContext, referenceVersion: string) {
super("mesonlsp", languageServerPath, context, referenceVersion);
constructor(
languageServerPath: vscode.Uri,
extraArgs: string[],
context: vscode.ExtensionContext,
referenceVersion: string,
) {
super("mesonlsp", languageServerPath, extraArgs, context, referenceVersion);
}

static override artifact(): { url: string; hash: string } | null {
Expand Down
29 changes: 29 additions & 0 deletions src/lsp/muon.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import * as vscode from "vscode";

import type { Executable } from "vscode-languageclient/node";
import { LanguageServerClient } from "../lsp";

export class MuonLanguageClient extends LanguageServerClient {
get runExe(): Executable {
return {
command: this.languageServerPath!.fsPath,
args: [...this.extraArgs, "analyze", "lsp"],
};
}

get debugExe(): Executable {
return {
command: this.languageServerPath!.fsPath,
args: [...this.extraArgs, "analyze", "lsp"],
};
}

constructor(
languageServerPath: vscode.Uri,
extraArgs: string[],
context: vscode.ExtensionContext,
referenceVersion: string,
) {
super("muon", languageServerPath, extraArgs, context, referenceVersion);
}
}
Loading
Loading