Skip to content
Merged
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
4 changes: 2 additions & 2 deletions client/liquid-java-0.0.15.vsix
Git LFS file not shown
Binary file removed client/server/language-server-liquidjava.jar
Binary file not shown.
19 changes: 19 additions & 0 deletions client/src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export const API_JAR_GLOB = "lib/liquidjava-api*.jar";
export const SERVER_JAR_FILENAME = "vscode-liquidjava.jar";
export const DEBUG_MODE = false;
export const DEBUG_PORT = 50000;
export const LIQUIDJAVA_SCOPES = [
"source.liquidjava keyword.other.liquidjava",
"source.liquidjava entity.name.function.liquidjava",
"source.liquidjava storage.type.primitive.liquidjava",
"source.liquidjava entity.name.type.liquidjava",
"source.liquidjava entity.name.type.class.liquidjava",
"source.liquidjava entity.name.type.externalref.liquidjava",
"source.liquidjava variable.other.liquidjava",
"source.liquidjava keyword.operator.liquidjava",
"source.liquidjava constant.language.boolean.liquidjava",
"source.liquidjava constant.numeric.liquidjava",
"keyword.operator.liquidjava",
"constant.language.boolean.liquidjava",
"constant.numeric.liquidjava",
];
17 changes: 1 addition & 16 deletions client/src/decorators.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,11 @@
import * as vscode from "vscode";
import { LIQUIDJAVA_SCOPES } from "./constants";

type TMRule = {
scope: string | string[];
settings: { fontStyle?: string; foreground?: string }
};

const LIQUIDJAVA_SCOPES = [
"source.liquidjava keyword.other.liquidjava",
"source.liquidjava entity.name.function.liquidjava",
"source.liquidjava storage.type.primitive.liquidjava",
"source.liquidjava entity.name.type.liquidjava",
"source.liquidjava entity.name.type.class.liquidjava",
"source.liquidjava entity.name.type.externalref.liquidjava",
"source.liquidjava variable.other.liquidjava",
"source.liquidjava keyword.operator.liquidjava",
"source.liquidjava constant.language.boolean.liquidjava",
"source.liquidjava constant.numeric.liquidjava",
"keyword.operator.liquidjava",
"constant.language.boolean.liquidjava",
"constant.numeric.liquidjava",
];

/**
* Apply italic fontStyle to LiquidJava TextMate scopes
* This preserves the active theme's colors and only adds italic style to injected tokens
Expand Down
144 changes: 4 additions & 140 deletions client/src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
import * as vscode from "vscode";
import * as fs from "fs";
import * as path from "path";
import * as net from "net";
import * as child_process from "child_process";
import { Trace } from "vscode-jsonrpc";
import { LanguageClient, LanguageClientOptions, StreamInfo, ServerOptions, State } from "vscode-languageclient";
import { LiquidJavaLogger, createLogger } from "./logging";
import { applyItalicOverlay } from "./decorators";

const SERVER_JAR_FILENAME = "language-server-liquidjava.jar";
const API_JAR_GLOB= "lib/liquidjava-api*.jar";
const DEBUG = false;
const DEBUG_PORT = 50000;
import { connectToPort, findJavaExecutable, getAvailablePort, isJarPresent, killProcess } from "./utils";
import { SERVER_JAR_FILENAME, DEBUG_MODE, DEBUG_PORT } from "./constants";

let serverProcess: child_process.ChildProcess;
let client: LanguageClient;
Expand Down Expand Up @@ -68,15 +63,6 @@ export async function deactivate() {
await stopExtension("Extension was deactivated");
}

/**
* Checks if the extension can be activated by looking for the LiquidJava API jar in the workspace
* @returns true if the extension can be activated, false otherwise
*/
async function isJarPresent(): Promise<boolean> {
const uris = await vscode.workspace.findFiles(API_JAR_GLOB);
return uris.length > 0;
}

/**
* Initializes logging for the extension with an output channel
* @param context The extension context
Expand Down Expand Up @@ -125,8 +111,8 @@ function updateStatusBar(state: "loading" | "stopped" | "passed" | "failed") {
* @returns A promise to the port number the server is running on
*/
async function runLanguageServer(context: vscode.ExtensionContext, javaExecutablePath: string): Promise<number> {
const port = DEBUG ? DEBUG_PORT : await getAvailablePort();
if (DEBUG) {
const port = DEBUG_MODE ? DEBUG_PORT : await getAvailablePort();
if (DEBUG_MODE) {
logger.client.info("DEBUG MODE: Using fixed port " + port);
return port;
}
Expand Down Expand Up @@ -187,8 +173,6 @@ async function runClient(context: vscode.ExtensionContext, port: number) {
documentSelector: [{ language: "java" }],
};
client = new LanguageClient("liquidJavaServer", "LiquidJava Server", serverOptions, clientOptions);
client.trace = Trace.Verbose; // for debugging

client.onDidChangeState((e) => {
if (e.newState === State.Stopped) {
stopExtension("Extension stopped");
Expand Down Expand Up @@ -221,93 +205,6 @@ async function runClient(context: vscode.ExtensionContext, port: number) {
);
}

/**
* Finds the Java executable in the system, either in JAVA_HOME or in PATH
* MIT Licensed code from: https://github.com/georgewfraser/vscode-javac
*/
function findJavaExecutable(binname: string): string | null {
binname = process.platform === "win32" ? `${binname}.exe` : binname;

// First search each JAVA_HOME bin folder
if (process.env["JAVA_HOME"]) {
for (const workspace of process.env["JAVA_HOME"].split(path.delimiter)) {
const binpath = path.join(workspace, "bin", binname);
if (fs.existsSync(binpath)) return binpath;
}
}
// Then search PATH parts
if (process.env["PATH"]) {
for (const part of process.env["PATH"].split(path.delimiter)) {
const binpath = path.join(part, binname);
if (fs.existsSync(binpath)) return binpath;
}
}
// Else return null
return null;
}

/**
* Gets an available port in the OS
* @returns A promise to the available port number
*/
async function getAvailablePort(): Promise<number> {
return new Promise((resolve, reject) => {
const server = net.createServer();
server.listen(0, "localhost", () => {
const port = (server.address() as net.AddressInfo).port;
server.close();
resolve(port);
});
server.on("error", reject);
});
}

/**
* Connects to the process on the given port, retrying until timeout
* @param port The port to connect to
* @param timeout The timeout duration in milliseconds
* @param attemptInterval The interval between connection attempts in milliseconds
* @param connectionTimeout The timeout for each individual connection attempt in milliseconds
* @returns A promise to the connected socket
*/
async function connectToPort(
port: number,
timeout = 10000,
attemptInterval = 500,
connectionTimeout = 500
): Promise<net.Socket> {
const deadline = Date.now() + timeout;
while (Date.now() < deadline) {
try {
return await new Promise((resolve, reject) => {
const s = net.connect({ port });

// connection timeout
const t = setTimeout(() => {
s.destroy(new Error("connection timeout"));
reject(new Error("connection timeout"));
}, connectionTimeout);

// success
s.once("connect", () => {
clearTimeout(t);
resolve(s);
});

// failure
s.once("error", (e) => {
clearTimeout(t);
reject(e);
});
});
} catch {
// wait and retry
await new Promise((r) => setTimeout(r, attemptInterval));
}
}
throw new Error(`Server not reachable on port ${port} within ${timeout}ms`);
}

/**
* Stops the LiquidJava extension
* @param reason The reason for stopping the extension
Expand Down Expand Up @@ -342,36 +239,3 @@ async function stopExtension(reason: string) {
await killProcess(serverProcess);
serverProcess = undefined;
}

/**
* Kills the given process if it is running
* @param proc The process to kill
* @returns A promise that resolves when the process has been killed
*/
async function killProcess(proc?: child_process.ChildProcess) {
return new Promise<void>((resolve, reject) => {
if (!proc || proc.killed) {
// already killed
resolve();
return;
}
if (process.platform === "win32") {
// Windows
child_process.exec(`taskkill /pid ${proc.pid} /T /F`, (err) => {
if (err) {
reject(err);
} else {
resolve();
}
});
} else {
// Unix
try {
process.kill(proc.pid, "SIGKILL");
resolve();
} catch (err) {
reject(err);
}
}
});
}
111 changes: 0 additions & 111 deletions client/src/extension_debug.ts

This file was deleted.

Loading