Skip to content
Open
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
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@
"type": "object",
"description": "List of detectors which are hidden in the explorer",
"default": []
},
"slither.slitherLspPath": {
"type":"string",
"markdownDescription": "Path to the `slither-lsp` executable",
"default": "slither-lsp"
}
}
}
Expand Down
72 changes: 71 additions & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { SettingsViewProvider } from "./views/settings/settingsViewProvider";
import * as state from "./state";
import { Configuration } from "./types/configTypes";
import { isDebuggingExtension } from "./utils/common";
import * as cp from "child_process"

// Properties
export let analysis_key: number | null = null;
Expand All @@ -14,6 +15,40 @@ export let finishedActivation: boolean = false;

let slitherSettingsProvider: SettingsViewProvider;

const slitherLspRegex = /^\s*usage:\s+slither-lsp/gm;

function checkSlitherLsp(path: string): Promise<void> {
return new Promise<void>((resolve, reject) => {
const data: Buffer[] = [];

const child = cp.spawn(path, ["--help"]);
child.stdout.on("data", chunk => {
data.push(chunk)
})

child.on("error", err => {
reject(err);
})

child.on("close", code => {
const stdout = Buffer.concat(data).toString("utf-8").trim();

if (code) {
reject(`Invalid \`slither-lsp\` executable. Process terminated with code ${code}`);
Logger.error(`slither-lsp output: ${stdout}`);
return;
}

if (!slitherLspRegex.test(stdout)) {
reject(`The specified executable was not recognized as a valid \`slither-lsp\` executable`);
return;
}

resolve();
});
});
}

// Functions
export async function activate(context: vscode.ExtensionContext) {
// Set our slither panel to visible
Expand Down Expand Up @@ -58,8 +93,43 @@ export async function activate(context: vscode.ExtensionContext) {
Logger.debug("Started in console mode");
}

const slitherLspPath = vscode.workspace.getConfiguration("slither").get("slitherLspPath", "slither-lsp");

vscode.workspace.onDidChangeConfiguration(async event => {
let affected = event.affectsConfiguration("slither.slitherLspPath");
if (!affected) {
return;
}

const action = await vscode.window
.showInformationMessage(
`Reload window in order for changes in the configuration of Contract Explorer to take effect.`,
"Reload"
);
if (action === "Reload") {
await vscode.commands.executeCommand('workbench.action.reloadWindow');
}
});

try {
await checkSlitherLsp(slitherLspPath);
} catch (err) {
let msg = "";
if (typeof (err) === "string") {
msg = err;
} else if (err instanceof Error) {
msg = err.toString();
}
const action = await vscode.window.showErrorMessage(msg, "Edit path");

if (action === "Edit path") {
await vscode.commands.executeCommand("workbench.action.openSettings", "slither.slitherLspPath");
}
return;
}

// Initialize the language server
let slitherLanguageClient = new SlitherLanguageClient(port);
let slitherLanguageClient = new SlitherLanguageClient(slitherLspPath, port);

// When the language server is ready, we'll want to start fetching some state variables.
slitherLanguageClient.start(async () => {
Expand Down
9 changes: 3 additions & 6 deletions src/slitherLanguageClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,23 @@ import {
} from "./types/languageServerTypes";
import { AnalysisRequestParams } from "./types/analysisTypes";

// The name of the language server executable
const lsp_executable_name = "slither-lsp";

export class SlitherLanguageClient {
public languageClient: LanguageClient;
private socket: Socket | null = null;

constructor(port: integer | null) {
constructor(slitherLspPath: string, port: integer | null) {
// Define server options.
let serverOptions: ServerOptions;
if (port == null) {
// If we weren't given a port, we use stdio. We keep the process attached so when we exit, it exits.
serverOptions = {
run: {
command: lsp_executable_name,
command: slitherLspPath,
args: [],
options: { detached: false },
},
debug: {
command: lsp_executable_name,
command: slitherLspPath,
args: [],
options: { detached: false },
},
Expand Down