Skip to content

Commit a9eb397

Browse files
authored
feat: Dafny Plugins support (#122)
1 parent 50a0f76 commit a9eb397

File tree

5 files changed

+35
-3
lines changed

5 files changed

+35
-3
lines changed

.eslintrc.json

+1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
"func-call-spacing": "off",
6969
"@typescript-eslint/func-call-spacing": "warn",
7070
"keyword-spacing": "off",
71+
"curly": "warn",
7172
"@typescript-eslint/keyword-spacing": [
7273
"warn",
7374
{

package.json

+8
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,14 @@
155155
"default": "true",
156156
"description": "Mark ghost statements in the code (requires restart and Dafny 3.4.0+)"
157157
},
158+
"dafny.dafnyPlugins": {
159+
"type": "array",
160+
"items": {
161+
"type": "string"
162+
},
163+
"default": [],
164+
"description": "Absolute paths to assemblies to be used as plugins (requires restart and Dafny 3.4.0+).\nExample 1: /user/home/dafnyplugin.dll\nExample 2: /user/home/dafnyplugin.dll,oneArgument\nExample 3: /user/home/dafnyplugin.dll,\"argument with space and \\\" escaped quote\" secondArgument"
165+
},
158166
"dafny.languageServerLaunchArgs": {
159167
"type": "array",
160168
"items": {

src/constants.ts

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export namespace ConfigurationConstants {
2323
export const VerificationVirtualCores = 'verificationVirtualCores';
2424
export const VerificationCachingPolicy = 'verificationCachingPolicy';
2525
export const MarkGhostStatements = 'markGhostStatements';
26+
export const DafnyPlugins = 'dafnyPlugins';
2627
}
2728

2829
export namespace Compiler {

src/extension.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ class ExtensionRuntime {
5858

5959
private async initializeClient(): Promise<void> {
6060
this.statusOutput.appendLine(`starting Dafny from ${getLanguageServerRuntimePath(this.context)}`);
61-
this.client = await DafnyLanguageClient.create(this.context);
61+
this.client = await DafnyLanguageClient.create(this.context, this.statusOutput);
6262
this.client.start();
6363
await this.client.onReady();
6464
this.languageServerVersion = await this.getLanguageServerVersionAfterStartup();

src/language/dafnyLanguageClient.ts

+24-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ExtensionContext, Disposable } from 'vscode';
1+
import { ExtensionContext, Disposable, OutputChannel } from 'vscode';
22
import { LanguageClient, LanguageClientOptions, ServerOptions } from 'vscode-languageclient/node';
33

44
import Configuration from '../configuration';
@@ -21,6 +21,7 @@ function getLanguageServerLaunchArgs(): string[] {
2121
getVerifierCachingPolicy(),
2222
getVerifierVirtualCoresArgument(),
2323
getMarkGhostStatementsArgument(),
24+
...getDafnyPluginsArgument(),
2425
...launchArgs
2526
];
2627
}
@@ -51,6 +52,18 @@ function getMarkGhostStatementsArgument(): string {
5152
return `--ghost:markStatements=${Configuration.get<string>(ConfigurationConstants.LanguageServer.MarkGhostStatements)}`;
5253
}
5354

55+
function getDafnyPluginsArgument(): string[] {
56+
const plugins = Configuration.get<string[]>(ConfigurationConstants.LanguageServer.DafnyPlugins);
57+
if(plugins === null || !Array.isArray(plugins)) {
58+
return [];
59+
}
60+
return (
61+
plugins
62+
.filter(plugin => plugin !== null && plugin !== '')
63+
.map((plugin, i) => `--dafny:plugins:${i}=${plugin}`)
64+
);
65+
}
66+
5467
export class DafnyLanguageClient extends LanguageClient {
5568
// eslint-disable-next-line max-params
5669
private constructor(id: string, name: string, serverOptions: ServerOptions, clientOptions: LanguageClientOptions, forceDebug?: boolean) {
@@ -61,9 +74,18 @@ export class DafnyLanguageClient extends LanguageClient {
6174
return this.sendRequest<ICounterExampleItem[]>('dafny/counterExample', param);
6275
}
6376

64-
public static async create(context: ExtensionContext): Promise<DafnyLanguageClient> {
77+
public static argumentsToCommandLine(launchArguments: string[]): string {
78+
return launchArguments.map(oneArgument =>
79+
(/\s|"|\\/.exec(oneArgument))
80+
? '"' + oneArgument.replace(/\\/g, '\\\\').replace(/"/g, '\\"') + '"'
81+
: oneArgument
82+
).join(' ');
83+
}
84+
85+
public static async create(context: ExtensionContext, statusOutput: OutputChannel): Promise<DafnyLanguageClient> {
6586
const dotnetExecutable = await getDotnetExecutablePath();
6687
const launchArguments = [ getLanguageServerRuntimePath(context), ...getLanguageServerLaunchArgs() ];
88+
statusOutput.appendLine(`Language server arguments: ${DafnyLanguageClient.argumentsToCommandLine(launchArguments)}`);
6789
const serverOptions: ServerOptions = {
6890
run: { command: dotnetExecutable, args: launchArguments },
6991
debug: { command: dotnetExecutable, args: launchArguments }

0 commit comments

Comments
 (0)