add bare bones for a lsp
This commit is contained in:
parent
6b60fa9d33
commit
52211ea02c
3
prometeu-lsp/prometeu-lsp-api/build.gradle.kts
Normal file
3
prometeu-lsp/prometeu-lsp-api/build.gradle.kts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
plugins {
|
||||||
|
id("gradle.java-library-conventions")
|
||||||
|
}
|
||||||
9
prometeu-lsp/prometeu-lsp-v1/build.gradle.kts
Normal file
9
prometeu-lsp/prometeu-lsp-v1/build.gradle.kts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
plugins {
|
||||||
|
id("gradle.java-library-conventions")
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(project(":prometeu-infra"))
|
||||||
|
|
||||||
|
implementation("org.eclipse.lsp4j:org.eclipse.lsp4j:1.0.0")
|
||||||
|
}
|
||||||
@ -0,0 +1,271 @@
|
|||||||
|
package p.studio.lsp;
|
||||||
|
|
||||||
|
import org.eclipse.lsp4j.*;
|
||||||
|
import org.eclipse.lsp4j.jsonrpc.Launcher;
|
||||||
|
import org.eclipse.lsp4j.launch.LSPLauncher;
|
||||||
|
import org.eclipse.lsp4j.services.*;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.ServerSocket;
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
public final class PrometeuStudioLspMain {
|
||||||
|
|
||||||
|
private static final String HOST = "127.0.0.1";
|
||||||
|
private static final int PORT = 7777;
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
InetAddress bindAddress = InetAddress.getByName(HOST);
|
||||||
|
|
||||||
|
try (ServerSocket serverSocket = new ServerSocket(PORT, 50, bindAddress)) {
|
||||||
|
System.out.println("Prometeu Studio LSP listening on " + HOST + ":" + PORT);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
Socket socket = serverSocket.accept();
|
||||||
|
|
||||||
|
Thread clientThread = new Thread(() -> handleClient(socket));
|
||||||
|
clientThread.setName("prometeu-lsp-client");
|
||||||
|
clientThread.setDaemon(true);
|
||||||
|
clientThread.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void handleClient(Socket socket) {
|
||||||
|
try {
|
||||||
|
System.out.println("VS Code connected: " + socket.getRemoteSocketAddress());
|
||||||
|
|
||||||
|
InputStream input = socket.getInputStream();
|
||||||
|
OutputStream output = socket.getOutputStream();
|
||||||
|
|
||||||
|
PrometeuLanguageServer server = new PrometeuLanguageServer();
|
||||||
|
|
||||||
|
Launcher<LanguageClient> launcher =
|
||||||
|
LSPLauncher.createServerLauncher(server, input, output);
|
||||||
|
|
||||||
|
LanguageClient client = launcher.getRemoteProxy();
|
||||||
|
server.connect(client);
|
||||||
|
|
||||||
|
launcher.startListening();
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("LSP client failed: " + e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class PrometeuLanguageServer implements LanguageServer, LanguageClientAware {
|
||||||
|
|
||||||
|
private LanguageClient client;
|
||||||
|
private final TextDocumentService textDocumentService = new PrometeuTextDocumentService(this);
|
||||||
|
private final WorkspaceService workspaceService = new PrometeuWorkspaceService();
|
||||||
|
|
||||||
|
private boolean shutdownRequested = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void connect(LanguageClient client) {
|
||||||
|
this.client = client;
|
||||||
|
|
||||||
|
if (textDocumentService instanceof PrometeuTextDocumentService service) {
|
||||||
|
service.connect(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public LanguageClient client() {
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<InitializeResult> initialize(InitializeParams params) {
|
||||||
|
ServerCapabilities capabilities = new ServerCapabilities();
|
||||||
|
|
||||||
|
TextDocumentSyncOptions syncOptions = new TextDocumentSyncOptions();
|
||||||
|
syncOptions.setOpenClose(true);
|
||||||
|
syncOptions.setChange(TextDocumentSyncKind.Full);
|
||||||
|
|
||||||
|
SaveOptions saveOptions = new SaveOptions();
|
||||||
|
saveOptions.setIncludeText(true);
|
||||||
|
syncOptions.setSave(saveOptions);
|
||||||
|
|
||||||
|
capabilities.setTextDocumentSync(syncOptions);
|
||||||
|
capabilities.setHoverProvider(true);
|
||||||
|
|
||||||
|
InitializeResult result = new InitializeResult(capabilities);
|
||||||
|
|
||||||
|
ServerInfo serverInfo = new ServerInfo();
|
||||||
|
serverInfo.setName("Prometeu Studio LSP");
|
||||||
|
serverInfo.setVersion("0.1.0");
|
||||||
|
result.setServerInfo(serverInfo);
|
||||||
|
|
||||||
|
return CompletableFuture.completedFuture(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialized(InitializedParams params) {
|
||||||
|
if (client != null) {
|
||||||
|
client.logMessage(new MessageParams(
|
||||||
|
MessageType.Info,
|
||||||
|
"Hello from Prometeu Studio LSP"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<Object> shutdown() {
|
||||||
|
shutdownRequested = true;
|
||||||
|
return CompletableFuture.completedFuture(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exit() {
|
||||||
|
System.out.println("LSP client requested exit. shutdownRequested=" + shutdownRequested);
|
||||||
|
|
||||||
|
// Importantíssimo:
|
||||||
|
// Como isso está dentro do Studio, NÃO use System.exit().
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TextDocumentService getTextDocumentService() {
|
||||||
|
return textDocumentService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WorkspaceService getWorkspaceService() {
|
||||||
|
return workspaceService;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class PrometeuTextDocumentService implements TextDocumentService {
|
||||||
|
|
||||||
|
private final PrometeuLanguageServer server;
|
||||||
|
private LanguageClient client;
|
||||||
|
|
||||||
|
private PrometeuTextDocumentService(PrometeuLanguageServer server) {
|
||||||
|
this.server = server;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void connect(LanguageClient client) {
|
||||||
|
this.client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void didOpen(DidOpenTextDocumentParams params) {
|
||||||
|
String uri = params.getTextDocument().getUri();
|
||||||
|
String text = params.getTextDocument().getText();
|
||||||
|
|
||||||
|
System.out.println("didOpen: " + uri);
|
||||||
|
|
||||||
|
publishHelloDiagnostic(uri, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void didChange(DidChangeTextDocumentParams params) {
|
||||||
|
String uri = params.getTextDocument().getUri();
|
||||||
|
|
||||||
|
String text = "";
|
||||||
|
if (!params.getContentChanges().isEmpty()) {
|
||||||
|
text = params.getContentChanges().get(0).getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("didChange: " + uri);
|
||||||
|
|
||||||
|
publishHelloDiagnostic(uri, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void didClose(DidCloseTextDocumentParams params) {
|
||||||
|
String uri = params.getTextDocument().getUri();
|
||||||
|
|
||||||
|
System.out.println("didClose: " + uri);
|
||||||
|
|
||||||
|
if (client != null) {
|
||||||
|
client.publishDiagnostics(new PublishDiagnosticsParams(uri, List.of()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void didSave(DidSaveTextDocumentParams params) {
|
||||||
|
String uri = params.getTextDocument().getUri();
|
||||||
|
|
||||||
|
System.out.println("didSave: " + uri);
|
||||||
|
|
||||||
|
if (client != null) {
|
||||||
|
client.logMessage(new MessageParams(
|
||||||
|
MessageType.Info,
|
||||||
|
"Prometeu Studio saw save: " + uri
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<Hover> hover(HoverParams params) {
|
||||||
|
MarkupContent content = new MarkupContent();
|
||||||
|
content.setKind(MarkupKind.MARKDOWN);
|
||||||
|
content.setValue("""
|
||||||
|
**Prometeu Studio LSP**
|
||||||
|
|
||||||
|
Hello from Java + LSP4J.
|
||||||
|
|
||||||
|
This hover came from the Studio process.
|
||||||
|
""");
|
||||||
|
|
||||||
|
Hover hover = new Hover();
|
||||||
|
hover.setContents(content);
|
||||||
|
|
||||||
|
return CompletableFuture.completedFuture(hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void publishHelloDiagnostic(String uri, String text) {
|
||||||
|
if (client == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Diagnostic diagnostic = new Diagnostic();
|
||||||
|
|
||||||
|
diagnostic.setRange(new Range(
|
||||||
|
new Position(0, 0),
|
||||||
|
new Position(0, Math.max(1, firstLineLength(text)))
|
||||||
|
));
|
||||||
|
|
||||||
|
diagnostic.setSeverity(DiagnosticSeverity.Information);
|
||||||
|
diagnostic.setSource("Prometeu Studio");
|
||||||
|
diagnostic.setMessage("Hello from Prometeu Studio LSP");
|
||||||
|
|
||||||
|
client.publishDiagnostics(new PublishDiagnosticsParams(
|
||||||
|
uri,
|
||||||
|
List.of(diagnostic)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
private int firstLineLength(String text) {
|
||||||
|
if (text == null || text.isEmpty()) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int newline = text.indexOf('\n');
|
||||||
|
|
||||||
|
if (newline < 0) {
|
||||||
|
return text.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
return newline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class PrometeuWorkspaceService implements WorkspaceService {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void didChangeConfiguration(DidChangeConfigurationParams params) {
|
||||||
|
System.out.println("didChangeConfiguration");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void didChangeWatchedFiles(DidChangeWatchedFilesParams params) {
|
||||||
|
System.out.println("didChangeWatchedFiles: " + params.getChanges().size() + " changes");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,9 +5,13 @@ plugins {
|
|||||||
rootProject.name = "prometeu-studio"
|
rootProject.name = "prometeu-studio"
|
||||||
|
|
||||||
include("prometeu-infra")
|
include("prometeu-infra")
|
||||||
|
|
||||||
include("prometeu-packer:prometeu-packer-api")
|
include("prometeu-packer:prometeu-packer-api")
|
||||||
include("prometeu-packer:prometeu-packer-v1")
|
include("prometeu-packer:prometeu-packer-v1")
|
||||||
|
|
||||||
|
include("prometeu-lsp:prometeu-lsp-api")
|
||||||
|
include("prometeu-lsp:prometeu-lsp-v1")
|
||||||
|
|
||||||
include("prometeu-compiler:frontends:prometeu-frontend-pbs")
|
include("prometeu-compiler:frontends:prometeu-frontend-pbs")
|
||||||
include("prometeu-compiler:prometeu-compiler-core")
|
include("prometeu-compiler:prometeu-compiler-core")
|
||||||
include("prometeu-compiler:prometeu-build-pipeline")
|
include("prometeu-compiler:prometeu-build-pipeline")
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
35
tools/vscode-extension/.gitignore
vendored
Normal file
35
tools/vscode-extension/.gitignore
vendored
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
# Dependencies
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Build output
|
||||||
|
out/
|
||||||
|
dist/
|
||||||
|
|
||||||
|
# VS Code package output
|
||||||
|
*.vsix
|
||||||
|
|
||||||
|
# TypeScript
|
||||||
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
|
||||||
|
# Test / coverage
|
||||||
|
coverage/
|
||||||
|
.vscode-test/
|
||||||
|
|
||||||
|
# Environment / local config
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
!.env.example
|
||||||
|
|
||||||
|
# OS files
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Editor local state
|
||||||
|
.vscode/settings.json
|
||||||
|
.vscode/*.log
|
||||||
17
tools/vscode-extension/.vscode/launch.json
vendored
Normal file
17
tools/vscode-extension/.vscode/launch.json
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Run Prometeu VS Code Extension",
|
||||||
|
"type": "extensionHost",
|
||||||
|
"request": "launch",
|
||||||
|
"args": [
|
||||||
|
"--extensionDevelopmentPath=${workspaceFolder}"
|
||||||
|
],
|
||||||
|
"outFiles": [
|
||||||
|
"${workspaceFolder}/out/**/*.js"
|
||||||
|
],
|
||||||
|
"preLaunchTask": "npm: compile"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
12
tools/vscode-extension/.vscode/tasks.json
vendored
Normal file
12
tools/vscode-extension/.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"type": "npm",
|
||||||
|
"script": "compile",
|
||||||
|
"group": "build",
|
||||||
|
"problemMatcher": "$tsc",
|
||||||
|
"label": "npm: compile"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
139
tools/vscode-extension/package-lock.json
generated
Normal file
139
tools/vscode-extension/package-lock.json
generated
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
{
|
||||||
|
"name": "prometeu-vscode-extension",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "prometeu-vscode-extension",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"dependencies": {
|
||||||
|
"vscode-languageclient": "^9.0.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^20.0.0",
|
||||||
|
"@types/vscode": "^1.90.0",
|
||||||
|
"typescript": "^5.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"vscode": "^1.90.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/node": {
|
||||||
|
"version": "20.19.39",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.39.tgz",
|
||||||
|
"integrity": "sha512-orrrD74MBUyK8jOAD/r0+lfa1I2MO6I+vAkmAWzMYbCcgrN4lCrmK52gRFQq/JRxfYPfonkr4b0jcY7Olqdqbw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"undici-types": "~6.21.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/vscode": {
|
||||||
|
"version": "1.118.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.118.0.tgz",
|
||||||
|
"integrity": "sha512-Ah6eTlqDcwIMELEVwQMO++rJAFBRz/oLluLD/vWdYrH1KuI9kfpaM+7pg0OvvascgcJy+ghLCERAYouM4QbzGw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/balanced-match": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/brace-expansion": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"balanced-match": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/minimatch": {
|
||||||
|
"version": "5.1.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz",
|
||||||
|
"integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"brace-expansion": "^2.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/semver": {
|
||||||
|
"version": "7.7.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
|
||||||
|
"integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
|
||||||
|
"license": "ISC",
|
||||||
|
"bin": {
|
||||||
|
"semver": "bin/semver.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/typescript": {
|
||||||
|
"version": "5.9.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
|
||||||
|
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"bin": {
|
||||||
|
"tsc": "bin/tsc",
|
||||||
|
"tsserver": "bin/tsserver"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.17"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/undici-types": {
|
||||||
|
"version": "6.21.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
|
||||||
|
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/vscode-jsonrpc": {
|
||||||
|
"version": "8.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz",
|
||||||
|
"integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/vscode-languageclient": {
|
||||||
|
"version": "9.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-9.0.1.tgz",
|
||||||
|
"integrity": "sha512-JZiimVdvimEuHh5olxhxkht09m3JzUGwggb5eRUkzzJhZ2KjCN0nh55VfiED9oez9DyF8/fz1g1iBV3h+0Z2EA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"minimatch": "^5.1.0",
|
||||||
|
"semver": "^7.3.7",
|
||||||
|
"vscode-languageserver-protocol": "3.17.5"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"vscode": "^1.82.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/vscode-languageserver-protocol": {
|
||||||
|
"version": "3.17.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz",
|
||||||
|
"integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"vscode-jsonrpc": "8.2.0",
|
||||||
|
"vscode-languageserver-types": "3.17.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/vscode-languageserver-types": {
|
||||||
|
"version": "3.17.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz",
|
||||||
|
"integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==",
|
||||||
|
"license": "MIT"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
69
tools/vscode-extension/package.json
Normal file
69
tools/vscode-extension/package.json
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
{
|
||||||
|
"name": "prometeu-vscode-extension",
|
||||||
|
"displayName": "Prometeu VS Code Extension",
|
||||||
|
"description": "VS Code bridge for Prometeu Studio.",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"engines": {
|
||||||
|
"vscode": "^1.90.0"
|
||||||
|
},
|
||||||
|
"categories": [
|
||||||
|
"Programming Languages"
|
||||||
|
],
|
||||||
|
"activationEvents": [
|
||||||
|
"onLanguage:pbs"
|
||||||
|
],
|
||||||
|
"main": "./out/extension.js",
|
||||||
|
"contributes": {
|
||||||
|
"languages": [
|
||||||
|
{
|
||||||
|
"id": "pbs",
|
||||||
|
"aliases": [
|
||||||
|
"PBS",
|
||||||
|
"Prometeu Base Script"
|
||||||
|
],
|
||||||
|
"extensions": [
|
||||||
|
".pbs",
|
||||||
|
".barrel"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"commands": [
|
||||||
|
{
|
||||||
|
"command": "prometeu.connectStudioLsp",
|
||||||
|
"title": "Prometeu: Connect to Studio LSP"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "prometeu.restartStudioLsp",
|
||||||
|
"title": "Prometeu: Restart Studio LSP"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"configuration": {
|
||||||
|
"title": "Prometeu",
|
||||||
|
"properties": {
|
||||||
|
"prometeu.studio.host": {
|
||||||
|
"type": "string",
|
||||||
|
"default": "127.0.0.1",
|
||||||
|
"description": "Prometeu Studio LSP host."
|
||||||
|
},
|
||||||
|
"prometeu.studio.port": {
|
||||||
|
"type": "number",
|
||||||
|
"default": 7777,
|
||||||
|
"description": "Prometeu Studio LSP TCP port."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"compile": "tsc -p ./",
|
||||||
|
"watch": "tsc -watch -p ./"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"vscode-languageclient": "^9.0.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^20.0.0",
|
||||||
|
"@types/vscode": "^1.90.0",
|
||||||
|
"typescript": "^5.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
159
tools/vscode-extension/src/extension.ts
Normal file
159
tools/vscode-extension/src/extension.ts
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
import * as net from "node:net";
|
||||||
|
import * as vscode from "vscode";
|
||||||
|
|
||||||
|
import {
|
||||||
|
LanguageClient,
|
||||||
|
LanguageClientOptions,
|
||||||
|
ServerOptions,
|
||||||
|
StreamInfo
|
||||||
|
} from "vscode-languageclient/node";
|
||||||
|
|
||||||
|
let client: LanguageClient | undefined;
|
||||||
|
let output: vscode.OutputChannel;
|
||||||
|
|
||||||
|
export function activate(context: vscode.ExtensionContext): void {
|
||||||
|
output = vscode.window.createOutputChannel("Prometeu LSP");
|
||||||
|
output.appendLine("Prometeu VS Code extension activated.");
|
||||||
|
|
||||||
|
const connectCommand = vscode.commands.registerCommand(
|
||||||
|
"prometeu.connectStudioLsp",
|
||||||
|
async () => {
|
||||||
|
await startClient(context);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const restartCommand = vscode.commands.registerCommand(
|
||||||
|
"prometeu.restartStudioLsp",
|
||||||
|
async () => {
|
||||||
|
await stopClient();
|
||||||
|
await startClient(context);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
context.subscriptions.push(output, connectCommand, restartCommand);
|
||||||
|
|
||||||
|
void startClient(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function deactivate(): Promise<void> {
|
||||||
|
await stopClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function startClient(context: vscode.ExtensionContext): Promise<void> {
|
||||||
|
if (client) {
|
||||||
|
output.appendLine("Prometeu LSP client is already running.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const config = vscode.workspace.getConfiguration("prometeu.studio");
|
||||||
|
|
||||||
|
const host = config.get<string>("host", "127.0.0.1");
|
||||||
|
const port = config.get<number>("port", 7777);
|
||||||
|
|
||||||
|
output.show(true);
|
||||||
|
output.appendLine(`Connecting to Prometeu Studio LSP at ${host}:${port}...`);
|
||||||
|
|
||||||
|
const serverOptions: ServerOptions = async (): Promise<StreamInfo> => {
|
||||||
|
return new Promise<StreamInfo>((resolve, reject) => {
|
||||||
|
const socket = net.createConnection({ host, port });
|
||||||
|
|
||||||
|
let settled = false;
|
||||||
|
|
||||||
|
const connectTimeout = setTimeout(() => {
|
||||||
|
if (settled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
settled = true;
|
||||||
|
socket.destroy();
|
||||||
|
reject(new Error("Connection timed out."));
|
||||||
|
}, 3000);
|
||||||
|
|
||||||
|
socket.once("connect", () => {
|
||||||
|
if (settled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
settled = true;
|
||||||
|
clearTimeout(connectTimeout);
|
||||||
|
|
||||||
|
output.appendLine("TCP connection established with Prometeu Studio.");
|
||||||
|
|
||||||
|
resolve({
|
||||||
|
reader: socket,
|
||||||
|
writer: socket
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.once("error", (error) => {
|
||||||
|
if (settled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
settled = true;
|
||||||
|
clearTimeout(connectTimeout);
|
||||||
|
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const clientOptions: LanguageClientOptions = {
|
||||||
|
documentSelector: [
|
||||||
|
{
|
||||||
|
scheme: "file",
|
||||||
|
language: "pbs"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
synchronize: {
|
||||||
|
fileEvents: [
|
||||||
|
vscode.workspace.createFileSystemWatcher("**/*.pbs")
|
||||||
|
]
|
||||||
|
},
|
||||||
|
initializationOptions: {
|
||||||
|
clientKind: "vscode",
|
||||||
|
prometeuClientVersion: context.extension.packageJSON.version
|
||||||
|
},
|
||||||
|
outputChannel: output
|
||||||
|
};
|
||||||
|
|
||||||
|
client = new LanguageClient(
|
||||||
|
"prometeuStudioLsp",
|
||||||
|
"Prometeu Studio LSP",
|
||||||
|
serverOptions,
|
||||||
|
clientOptions
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await client.start();
|
||||||
|
|
||||||
|
output.appendLine("Prometeu Studio LSP client started.");
|
||||||
|
vscode.window.showInformationMessage("Connected to Prometeu Studio LSP.");
|
||||||
|
} catch (error) {
|
||||||
|
client = undefined;
|
||||||
|
|
||||||
|
const message = error instanceof Error ? error.message : String(error);
|
||||||
|
|
||||||
|
output.appendLine(`Failed to start Prometeu LSP client: ${message}`);
|
||||||
|
vscode.window.showErrorMessage(`Could not connect to Prometeu Studio LSP: ${message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function stopClient(): Promise<void> {
|
||||||
|
if (!client) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentClient = client;
|
||||||
|
client = undefined;
|
||||||
|
|
||||||
|
output.appendLine("Stopping Prometeu Studio LSP client...");
|
||||||
|
|
||||||
|
try {
|
||||||
|
await currentClient.stop();
|
||||||
|
output.appendLine("Prometeu Studio LSP client stopped.");
|
||||||
|
} catch (error) {
|
||||||
|
const message = error instanceof Error ? error.message : String(error);
|
||||||
|
output.appendLine(`Failed to stop Prometeu LSP client cleanly: ${message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
20
tools/vscode-extension/tsconfig.json
Normal file
20
tools/vscode-extension/tsconfig.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"module": "Node16",
|
||||||
|
"target": "ES2022",
|
||||||
|
"lib": [
|
||||||
|
"ES2022"
|
||||||
|
],
|
||||||
|
"outDir": "out",
|
||||||
|
"rootDir": "src",
|
||||||
|
"sourceMap": true,
|
||||||
|
"strict": true,
|
||||||
|
"moduleResolution": "Node16",
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"skipLibCheck": true
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"node_modules",
|
||||||
|
".vscode-test"
|
||||||
|
]
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user