-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Experiment: Viper integration #78
base: master
Are you sure you want to change the base?
Changes from 9 commits
0c99de9
e796c87
2b0ac87
5e67dd6
7ca8087
fe96390
1076303
50820c3
cbab556
8342646
3058bb3
3cfc5bc
e18a93d
f519db6
aa0cfec
f027fca
2a519f2
fab6719
5c2b5cf
494c2ab
ca5fd04
31720e0
b98d69e
3e5beed
4734df0
12a4ea9
be5321f
2a82fa2
0a490b3
ca64a28
36c88ef
09ab3a8
f3020e4
2b3a960
10d7fdf
6d38483
05863c4
95f22ca
4115385
4fab05b
dee8a27
ea81dab
cad3795
ca084b3
d7ee213
3ae85c4
35ffeeb
c67e11c
2a01b69
a514d30
6c82368
14f5805
867e624
f6f1bc2
fec8d16
f26d1a2
0eaea58
2b63a3c
82bc022
4445f11
1816b9e
d8e6e89
7f7441e
2062102
8ea25ba
b653fac
ecb80e0
80e48c4
b4a6caa
12b0854
7419e39
8779b86
b8548c4
dec28b3
008a6cd
c6b1eba
e187a16
aec67b0
015f176
b9d40af
0f1180e
ed04f5b
b21008f
5dcd477
62a59f8
acb9265
d6d0279
ccd6cc4
dd5dd5b
3c3b284
d04f8fd
21ef478
ba913e1
563e565
0e5c9fe
9639874
18e50a2
7f38803
9dbb92e
e45ff0d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,3 +2,5 @@ | |
/out/ | ||
result | ||
*.vsix | ||
|
||
/src/generated/**/* |
This file was deleted.
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,7 +2,7 @@ | |
"name": "vscode-motoko", | ||
"displayName": "Motoko", | ||
"description": "Motoko language support", | ||
"version": "0.5.3", | ||
"version": "0.5.3-viper", | ||
"publisher": "dfinity-foundation", | ||
"repository": "https://github.com/dfinity/vscode-motoko", | ||
"engines": { | ||
|
@@ -155,9 +155,14 @@ | |
"typescript": "^4.8.2", | ||
"vsce": "^2.11.0" | ||
}, | ||
"extensionDependencies": [ | ||
"viper-admin.viper" | ||
], | ||
"scripts": { | ||
"vscode:prepublish": "npm run compile", | ||
"compile": "rimraf ./out && tsc -p .", | ||
"vscode:prepublish": "npm run generate && npm run compile", | ||
"generate": "npm run download && cd ../motoko && nix-shell --command 'make -C src moc.js' && cp -vL src/moc.js ../vscode-motoko/src/generated", | ||
"download": "curl -L -o src/generated/viperserver.jar https://github.com/viperproject/viperserver/releases/download/v-2022-10-18-0728/viperserver.jar -C -", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good idea; now using the Nix environment for the stand-in portable build logic. |
||
"compile": "rimraf ./out && tsc -p . && cp -vr src/generated out/generated", | ||
"test": "jest", | ||
"lint": "tslint -p .", | ||
"package": "vsce package", | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import getMotoko from 'motoko/lib'; | ||
|
||
const mo = getMotoko(require('../generated/moc.js').Motoko as any); | ||
|
||
export default mo; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
// Load custom `moc.js` with Viper integration | ||
import { Span } from 'motoko/lib/ast'; | ||
import mo from './motoko'; | ||
import { spawn } from 'child_process'; | ||
import * as rpc from 'vscode-jsonrpc/node'; | ||
import { resolve } from 'path'; | ||
import { connect } from 'net'; | ||
|
||
const serverPort = 54816; // TODO: config | ||
|
||
let connection: rpc.MessageConnection | undefined; | ||
|
||
try { | ||
spawn('java', [ | ||
'-Xmx2048m', | ||
'-Xss16m', | ||
'-jar', | ||
resolve(__dirname, '../generated/viperserver.jar'), | ||
'--singleClient', | ||
'--serverMode', | ||
'LSP', | ||
'--port', | ||
String(serverPort), | ||
]).on('error', console.error); | ||
|
||
const socket = connect(serverPort); | ||
connection = rpc.createMessageConnection( | ||
new rpc.SocketMessageReader(socket), | ||
new rpc.SocketMessageWriter(socket), | ||
); | ||
connection.listen(); | ||
|
||
console.log('Listening to Viper LSP'); | ||
|
||
connection.sendNotification(new rpc.NotificationType('initialize')); | ||
} catch (err) { | ||
console.error(`Error while initializing Viper LSP: ${err}`); | ||
} | ||
|
||
type Range = { start: Span; end: Span }; | ||
type CompilerRange = [number, number, number, number]; | ||
export type Lookup = (pos: CompilerRange) => CompilerRange; | ||
|
||
// Viper -> Motoko source map cache | ||
const sourceLookupMap = new Map<string, Lookup>(); | ||
|
||
export function getMotokoSourceRange( | ||
virtualPath: string, | ||
{ start: [a, b], end: [c, d] }: Range, | ||
): Range | undefined { | ||
const lookup = sourceLookupMap.get(virtualPath); | ||
if (!lookup) { | ||
return; | ||
} | ||
const result = lookup([a, b, c, d]); | ||
if (!result) { | ||
return; | ||
} | ||
return { | ||
start: [result[0], result[1]], | ||
end: [result[2], result[3]], | ||
}; | ||
} | ||
|
||
export function compileViper(uri: string, virtualPath: string) { | ||
const result = mo.compiler.viper([virtualPath]); | ||
const lookup = result?.code?.[1]; | ||
if (lookup) { | ||
sourceLookupMap.set(virtualPath, lookup); | ||
} | ||
if (connection) { | ||
// TODO | ||
connection.sendNotification( | ||
new rpc.NotificationType('textDocument/didOpen'), | ||
{ | ||
textDocument: { languageId: 'viper', version: 0, uri }, | ||
}, | ||
); | ||
} | ||
|
||
return result; | ||
} | ||
|
||
export function invalidateViper(virtualPath: string) { | ||
sourceLookupMap.delete(virtualPath); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: there might be a conflict between the version of
viperserver
provided by theviper-admin.viper
extension and Nix. Maybe we don't need this for now and just assume thatviperserver.jar
is available in the system (e.g., under some env variable that Nix provides)?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
^ @ggreif
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
He already uses
$VIPER_SERVER
! But the ideal thing would be to frob the port number form theviper-ide
panel, and connect to the already running server.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would be ideal. The main challenge here is that VS Code loads extensions based on activation events, so it's currently required to manually open a
*.vpr
file to activate the Viper LS.Update: I just found a way to programmatically activate the Viper extension using the extensions API, so now we just need a way to reliably retrieve the port number.
Looking at the corresponding logic in viper-ide, one option is to modify the extension to expose the port in the ViperApi (which we can then access from our language client). This should be sufficiently decoupled from our use case to make this a reasonable standalone feature.