Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
4433be1fd5 | ||
|
65af5f4600 | ||
|
7f39455bd0 |
BIN
JavaTXcompiler-0.1-jar-with-dependencies.jar
Normal file
BIN
JavaTXcompiler-0.1-jar-with-dependencies.jar
Normal file
Binary file not shown.
BIN
TX-main.png
Normal file
BIN
TX-main.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 664 KiB |
@@ -37,7 +37,7 @@ exports.JavaMainCodeLensProvider = void 0;
|
||||
const vscode = __importStar(require("vscode"));
|
||||
class JavaMainCodeLensProvider {
|
||||
constructor() {
|
||||
this.regexMain = /public\s+static\s+void\s+main\s*\(\s*String\s*\[\]\s*\w*\s*\)/g;
|
||||
this.regexMain = /public\s+static\s+(?:void\s+)?main\s*\(\s*(?:String\s*\[\]\s*\w*|\w*)?\s*\)/g;
|
||||
}
|
||||
provideCodeLenses(document) {
|
||||
const text = document.getText();
|
||||
|
@@ -1 +1 @@
|
||||
{"version":3,"file":"codelensProvider.js","sourceRoot":"","sources":["../src/codelensProvider.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,+CAAiC;AACjC,MAAa,wBAAwB;IAArC;QACU,cAAS,GAAG,gEAAgE,CAAC;IAYvF,CAAC;IAXC,iBAAiB,CAAC,QAA6B;QAC7C,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,EAAE,CAAC;QAChC,MAAM,UAAU,GAAsB,EAAE,CAAC;QACzC,IAAI,CAAyB,CAAC;QAC9B,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YAChD,MAAM,GAAG,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YACzC,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACzC,UAAU,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,yBAAyB,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC;QAC3H,CAAC;QACD,OAAO,UAAU,CAAC;IACpB,CAAC;CACF;AAbD,4DAaC"}
|
||||
{"version":3,"file":"codelensProvider.js","sourceRoot":"","sources":["../src/codelensProvider.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,+CAAiC;AACjC,MAAa,wBAAwB;IAArC;QACU,cAAS,GAAE,8EAA8E,CAAA;IAYnG,CAAC;IAXC,iBAAiB,CAAC,QAA6B;QAC7C,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,EAAE,CAAC;QAChC,MAAM,UAAU,GAAsB,EAAE,CAAC;QACzC,IAAI,CAAyB,CAAC;QAC9B,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YAChD,MAAM,GAAG,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YACzC,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACzC,UAAU,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,yBAAyB,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC;QAC3H,CAAC;QACD,OAAO,UAAU,CAAC;IACpB,CAAC;CACF;AAbD,4DAaC"}
|
151
out/extension.js
151
out/extension.js
@@ -42,52 +42,33 @@ const path = __importStar(require("path"));
|
||||
const codelensProvider_1 = require("./codelensProvider");
|
||||
function getConfig(key, def) { const v = vscode.workspace.getConfiguration().get(key); return v === undefined ? def : v; }
|
||||
function getWorkspaceFolderUri(docUri) { return docUri ? vscode.workspace.getWorkspaceFolder(docUri)?.uri : vscode.workspace.workspaceFolders?.[0]?.uri; }
|
||||
function toAbs(folder, workspace) { return path.isAbsolute(folder) ? folder : (workspace ? path.join(workspace.fsPath, folder) : folder); }
|
||||
function buildClasspath(folders) { return folders.join(path.delimiter); }
|
||||
function readPackageName(text) { return text.match(/^\s*package\s+([\w\.]+)\s*;/m)?.[1]; }
|
||||
function fqcnFromDocument(doc) { const pkg = readPackageName(doc.getText()); const simple = path.basename(doc.fileName).replace(/\.java$/i, ""); return pkg ? `${pkg}.${simple}` : simple; }
|
||||
function execInTerminal(cmd, cwd, name = "Java Class Runner") { const t = vscode.window.terminals.find(tt => tt.name === name) || vscode.window.createTerminal({ name }); t.show(true); if (cwd)
|
||||
t.sendText(`cd "${cwd}"`); t.sendText(cmd); }
|
||||
function ensureDir(dir) { if (!fs.existsSync(dir))
|
||||
fs.mkdirSync(dir, { recursive: true }); }
|
||||
function psExec(cmdPath) { if (process.platform === "win32" && (cmdPath.includes("\\") || cmdPath.includes("/") || cmdPath.includes(" ")))
|
||||
return `& "${cmdPath}"`; return cmdPath; }
|
||||
function nearestOutFoldersFor(docPath, workspace) {
|
||||
const res = [];
|
||||
const fileDir = path.dirname(docPath);
|
||||
const add = (p) => { if (fs.existsSync(p) && !res.includes(p))
|
||||
res.push(p); };
|
||||
add(path.join(fileDir, "out"));
|
||||
if (workspace)
|
||||
add(path.join(workspace.fsPath, "out"));
|
||||
if (workspace) {
|
||||
let cur = fileDir;
|
||||
while (cur.startsWith(workspace.fsPath)) {
|
||||
add(path.join(cur, "out"));
|
||||
const parent = path.dirname(cur);
|
||||
if (parent === cur)
|
||||
break;
|
||||
cur = parent;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
async function compileJava(javaFile, outDir, classpath, javacPath) {
|
||||
async function compileJava(javaFile, outDir, classpath, ctxpath) {
|
||||
ensureDir(outDir);
|
||||
if (javaFile.includes(".java")) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const args = [javaFile, "-cp", classpath, "-d", outDir];
|
||||
const proc = cp.spawn("javac", args, { shell: process.platform === "win32" });
|
||||
let stderr = "";
|
||||
proc.stderr.on("data", d => stderr += d.toString());
|
||||
proc.on("close", code => code === 0 ? resolve() : reject(new Error(`javac exit code ${code}\n${stderr}`)));
|
||||
});
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
const args = ["-d", outDir];
|
||||
if (classpath.trim().length > 0) {
|
||||
args.push("-cp", classpath);
|
||||
}
|
||||
args.push(javaFile);
|
||||
const proc = cp.spawn(javacPath, args, { shell: process.platform === "win32" });
|
||||
const args = ["-jar", ctxpath + "/JavaTXcompiler-0.1-jar-with-dependencies.jar", javaFile, "-cp", classpath, "-d", outDir];
|
||||
const proc = cp.spawn("java", args, { shell: process.platform === "win32" });
|
||||
let stderr = "";
|
||||
proc.stderr.on("data", d => stderr += d.toString());
|
||||
proc.on("close", code => code === 0 ? resolve() : reject(new Error(`javac exit code ${code}\n${stderr}`)));
|
||||
});
|
||||
}
|
||||
function activate(ctx) {
|
||||
ctx.subscriptions.push(vscode.languages.registerCodeLensProvider({ language: "java" }, new codelensProvider_1.JavaMainCodeLensProvider()));
|
||||
ctx.subscriptions.push(vscode.languages.registerCodeLensProvider([{ language: "java" }, { pattern: "**/*.jav" }], new codelensProvider_1.JavaMainCodeLensProvider()));
|
||||
ctx.subscriptions.push(vscode.commands.registerCommand("javaClassRunner.runMain", async () => {
|
||||
const ed = vscode.window.activeTextEditor;
|
||||
if (!ed || ed.document.languageId !== "java") {
|
||||
@@ -95,86 +76,58 @@ function activate(ctx) {
|
||||
return;
|
||||
}
|
||||
const ws = getWorkspaceFolderUri(ed.document.uri);
|
||||
const cpFolders = getConfig("javaClassRunner.classpathFolders", ["classes"]).map(f => toAbs(f, ws)).filter(f => f && fs.existsSync(f));
|
||||
const outDirCfg = getConfig("javaClassRunner.compile.outDir", ".java-class-runner/out");
|
||||
const outDir = toAbs(outDirCfg, ws);
|
||||
const compileEnabled = getConfig("javaClassRunner.compile.enabled", true);
|
||||
const javaPath = getConfig("javaClassRunner.java.path", "java");
|
||||
const javacPath = getConfig("javaClassRunner.javac.path", "javac");
|
||||
const fileDir = path.dirname(ed.document.fileName);
|
||||
const outDir = path.join(fileDir, "out", "main");
|
||||
const cpFolders = [outDir, path.join(fileDir, "out")];
|
||||
ensureDir(outDir);
|
||||
if (fs.existsSync(outDir)) {
|
||||
for (const entry of fs.readdirSync(outDir)) {
|
||||
const fullPath = path.join(outDir, entry);
|
||||
if (fs.lstatSync(fullPath).isDirectory()) {
|
||||
fs.rmSync(fullPath, { recursive: true, force: true });
|
||||
}
|
||||
else {
|
||||
fs.unlinkSync(fullPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
const wdCfg = getConfig("javaClassRunner.run.workingDirectory", "${workspaceFolder}");
|
||||
const wd = wdCfg.replace("${workspaceFolder}", ws?.fsPath ?? process.cwd());
|
||||
const vmArgs = getConfig("javaClassRunner.run.vmArgs", []);
|
||||
const programArgs = getConfig("javaClassRunner.run.programArgs", []);
|
||||
const fqcn = fqcnFromDocument(ed.document);
|
||||
if (!fqcn) {
|
||||
vscode.window.showErrorMessage("Konnte FQCN nicht bestimmen.");
|
||||
return;
|
||||
}
|
||||
const detectedOuts = nearestOutFoldersFor(ed.document.fileName, ws);
|
||||
// compile: include detected outs so javac can resolve prebuilt dependencies (.class)
|
||||
if (compileEnabled) {
|
||||
try {
|
||||
await compileJava(ed.document.fileName, outDir, buildClasspath([...cpFolders, ...detectedOuts]), javacPath);
|
||||
}
|
||||
catch (err) {
|
||||
vscode.window.showErrorMessage(`Kompilierung fehlgeschlagen: ${err?.message || String(err)}`);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await compileJava(ed.document.fileName, outDir, `"${cpFolders.join(";")}"`, ctx.extensionPath);
|
||||
}
|
||||
// runtime cp: compile out + configured + detected outs
|
||||
const cpCombined = buildClasspath([outDir, ...cpFolders, ...detectedOuts].filter(Boolean));
|
||||
const cpArg = cpCombined.length ? `-cp "${cpCombined}"` : "";
|
||||
const cmd = `${psExec(javaPath)} ${cpArg} ${vmArgs.join(" ")} ${fqcn} ${programArgs.join(" ")}`.trim();
|
||||
execInTerminal(cmd, wd);
|
||||
}));
|
||||
ctx.subscriptions.push(vscode.commands.registerCommand("javaClassRunner.runFromClassesFolder", async () => {
|
||||
const ws = getWorkspaceFolderUri();
|
||||
const cpFolders = getConfig("javaClassRunner.classpathFolders", ["classes"]).map(f => toAbs(f, ws)).filter(f => f && fs.existsSync(f));
|
||||
if (cpFolders.length === 0) {
|
||||
vscode.window.showErrorMessage("Kein gültiger Klassen-Ordner gefunden. Prüfe 'javaClassRunner.classpathFolders'.");
|
||||
catch (err) {
|
||||
vscode.window.showErrorMessage(`Kompilierung fehlgeschlagen: ${err?.message || String(err)}`);
|
||||
return;
|
||||
}
|
||||
const javaPath = getConfig("javaClassRunner.java.path", "java");
|
||||
const wdCfg = getConfig("javaClassRunner.run.workingDirectory", "${workspaceFolder}");
|
||||
const wd = wdCfg.replace("${workspaceFolder}", ws?.fsPath ?? process.cwd());
|
||||
const vmArgs = getConfig("javaClassRunner.run.vmArgs", []);
|
||||
const programArgs = getConfig("javaClassRunner.run.programArgs", []);
|
||||
async function listMainClassesInFolder(root) {
|
||||
const out = [];
|
||||
const walk = async (dir) => {
|
||||
const entries = await fs.promises.readdir(dir, { withFileTypes: true });
|
||||
for (const e of entries) {
|
||||
const full = path.join(dir, e.name);
|
||||
if (e.isDirectory())
|
||||
await walk(full);
|
||||
else if (e.isFile() && e.name.endsWith(".class") && !e.name.includes("$")) {
|
||||
const rel = path.relative(root, full).replace(/\.class$/, "");
|
||||
const fqcn = rel.split(path.sep).join(".");
|
||||
out.push(fqcn);
|
||||
}
|
||||
// Find the first .class file in outDir (excluding inner classes with $)
|
||||
let mainClass;
|
||||
const walk = (dir) => {
|
||||
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
||||
for (const e of entries) {
|
||||
const full = path.join(dir, e.name);
|
||||
if (e.isDirectory())
|
||||
walk(full);
|
||||
else if (e.isFile() && e.name.endsWith(".class") && !e.name.includes("$") && !mainClass) {
|
||||
const rel = path.relative(outDir, full).replace(/\.class$/, "");
|
||||
mainClass = rel.split(path.sep).join(".");
|
||||
}
|
||||
};
|
||||
if (fs.existsSync(root))
|
||||
await walk(root);
|
||||
return out.sort();
|
||||
}
|
||||
const classes = [];
|
||||
for (const folder of cpFolders) {
|
||||
const list = await listMainClassesInFolder(folder);
|
||||
for (const c of list)
|
||||
if (!classes.includes(c))
|
||||
classes.push(c);
|
||||
}
|
||||
if (classes.length === 0) {
|
||||
vscode.window.showWarningMessage("Keine .class-Dateien gefunden (ohne $).");
|
||||
if (mainClass)
|
||||
break;
|
||||
}
|
||||
};
|
||||
if (fs.existsSync(outDir))
|
||||
walk(outDir);
|
||||
if (!mainClass) {
|
||||
vscode.window.showErrorMessage("Keine .class-Datei im Ausgabeverzeichnis gefunden.");
|
||||
return;
|
||||
}
|
||||
const picked = await vscode.window.showQuickPick(classes, { placeHolder: "Wähle eine Main-Klasse (FQCN)" });
|
||||
if (!picked)
|
||||
return;
|
||||
const cpCombined = buildClasspath(cpFolders);
|
||||
const cpArg = cpCombined.length ? `-cp "${cpCombined}"` : "";
|
||||
const cmd = `${psExec(javaPath)} ${cpArg} ${vmArgs.join(" ")} ${picked} ${programArgs.join(" ")}`.trim();
|
||||
const cmd = `java -cp "${cpFolders.join(";")}" ${mainClass}`.trim();
|
||||
execInTerminal(cmd, wd);
|
||||
}));
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
@@ -1,8 +1,9 @@
|
||||
{
|
||||
"name": "java-class-runner",
|
||||
"displayName": "Java Class Runner (Run Main from .java + classpath folder)",
|
||||
"description": "Führt Java Main-Methoden aus und nutzt .class-Ordner als Classpath. Fügt einen 'Run' CodeLens über main(...) hinzu.",
|
||||
"version": "1.0.2",
|
||||
"icon": "TX-main.png",
|
||||
"name": "java-tx-main-runner",
|
||||
"displayName": "Java-TX Main Runner",
|
||||
"description": "Führt Java und Java-TX Main-Methoden aus und nutzt den /out Ordner als Classpath. Fügt einen 'Run' CodeLens über main(...) hinzu.",
|
||||
"version": "0.0.2",
|
||||
"engines": {
|
||||
"vscode": "^1.85.0"
|
||||
},
|
||||
|
@@ -1,7 +1,7 @@
|
||||
|
||||
import * as vscode from "vscode";
|
||||
export class JavaMainCodeLensProvider implements vscode.CodeLensProvider {
|
||||
private regexMain = /public\s+static\s+void\s+main\s*\(\s*String\s*\[\]\s*\w*\s*\)/g;
|
||||
private regexMain =/public\s+static\s+(?:void\s+)?main\s*\(\s*(?:String\s*\[\]\s*\w*|\w*)?\s*\)/g
|
||||
provideCodeLenses(document: vscode.TextDocument): vscode.CodeLens[] {
|
||||
const text = document.getText();
|
||||
const codeLenses: vscode.CodeLens[] = [];
|
||||
|
150
src/extension.ts
150
src/extension.ts
@@ -7,120 +7,100 @@ import { JavaMainCodeLensProvider } from "./codelensProvider";
|
||||
|
||||
function getConfig<T>(key: string, def: T): T { const v = vscode.workspace.getConfiguration().get<T>(key); return v===undefined?def:v; }
|
||||
function getWorkspaceFolderUri(docUri?: vscode.Uri): vscode.Uri | undefined { return docUri ? vscode.workspace.getWorkspaceFolder(docUri)?.uri : vscode.workspace.workspaceFolders?.[0]?.uri; }
|
||||
function toAbs(folder: string, workspace?: vscode.Uri): string { return path.isAbsolute(folder) ? folder : (workspace ? path.join(workspace.fsPath, folder) : folder); }
|
||||
function buildClasspath(folders: string[]): string { return folders.join(path.delimiter); }
|
||||
function readPackageName(text: string): string | undefined { return text.match(/^\s*package\s+([\w\.]+)\s*;/m)?.[1]; }
|
||||
function fqcnFromDocument(doc: vscode.TextDocument): string | undefined { const pkg = readPackageName(doc.getText()); const simple = path.basename(doc.fileName).replace(/\.java$/i,""); return pkg ? `${pkg}.${simple}` : simple; }
|
||||
function execInTerminal(cmd: string, cwd?: string, name="Java Class Runner") { const t = vscode.window.terminals.find(tt=>tt.name===name) || vscode.window.createTerminal({name}); t.show(true); if (cwd) t.sendText(`cd "${cwd}"`); t.sendText(cmd); }
|
||||
function ensureDir(dir: string) { if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); }
|
||||
function psExec(cmdPath: string): string { if (process.platform==="win32" && (cmdPath.includes("\\")||cmdPath.includes("/")||cmdPath.includes(" "))) return `& "${cmdPath}"`; return cmdPath; }
|
||||
function nearestOutFoldersFor(docPath: string, workspace?: vscode.Uri): string[] {
|
||||
const res: string[] = [];
|
||||
const fileDir = path.dirname(docPath);
|
||||
const add = (p:string)=>{ if (fs.existsSync(p) && !res.includes(p)) res.push(p); };
|
||||
add(path.join(fileDir,"out"));
|
||||
if (workspace) add(path.join(workspace.fsPath,"out"));
|
||||
if (workspace) {
|
||||
let cur=fileDir;
|
||||
while (cur.startsWith(workspace.fsPath)) {
|
||||
add(path.join(cur,"out"));
|
||||
const parent = path.dirname(cur);
|
||||
if (parent===cur) break;
|
||||
cur = parent;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
async function compileJava(javaFile: string, outDir: string, classpath: string, javacPath: string): Promise<void> {
|
||||
|
||||
async function compileJava(javaFile: string, outDir: string, classpath: string, ctxpath : string): Promise<void> {
|
||||
ensureDir(outDir);
|
||||
if(javaFile.includes(".java")){
|
||||
return new Promise((resolve, reject) => {
|
||||
const args = [javaFile, "-cp", classpath, "-d", outDir];
|
||||
const proc = cp.spawn("javac", args, { shell: process.platform==="win32" });
|
||||
let stderr=""; proc.stderr.on("data", d=>stderr+=d.toString());
|
||||
proc.on("close", code=> code===0 ? resolve() : reject(new Error(`javac exit code ${code}\n${stderr}`)));
|
||||
});
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const args = ["-d", outDir];
|
||||
if (classpath.trim().length>0) { args.push("-cp", classpath); }
|
||||
args.push(javaFile);
|
||||
const proc = cp.spawn(javacPath, args, { shell: process.platform==="win32" });
|
||||
const args = ["-jar", ctxpath + "/JavaTXcompiler-0.1-jar-with-dependencies.jar", javaFile, "-cp", classpath, "-d", outDir];
|
||||
const proc = cp.spawn("java", args, { shell: process.platform==="win32" });
|
||||
let stderr=""; proc.stderr.on("data", d=>stderr+=d.toString());
|
||||
proc.on("close", code=> code===0 ? resolve() : reject(new Error(`javac exit code ${code}\n${stderr}`)));
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
export function activate(ctx: vscode.ExtensionContext) {
|
||||
ctx.subscriptions.push(vscode.languages.registerCodeLensProvider({ language: "java" }, new JavaMainCodeLensProvider()));
|
||||
ctx.subscriptions.push(
|
||||
vscode.languages.registerCodeLensProvider(
|
||||
[{ language: "java" }, { pattern: "**/*.jav" }],
|
||||
new JavaMainCodeLensProvider()
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
ctx.subscriptions.push(vscode.commands.registerCommand("javaClassRunner.runMain", async () => {
|
||||
|
||||
const ed = vscode.window.activeTextEditor;
|
||||
if (!ed || ed.document.languageId!=="java") { vscode.window.showErrorMessage("Öffne eine Java-Datei mit main(...)"); return; }
|
||||
|
||||
const ws = getWorkspaceFolderUri(ed.document.uri);
|
||||
const cpFolders = getConfig<string[]>("javaClassRunner.classpathFolders", ["classes"]).map(f=>toAbs(f, ws)).filter(f=>f && fs.existsSync(f));
|
||||
const outDirCfg = getConfig<string>("javaClassRunner.compile.outDir", ".java-class-runner/out");
|
||||
const outDir = toAbs(outDirCfg, ws);
|
||||
const compileEnabled = getConfig<boolean>("javaClassRunner.compile.enabled", true);
|
||||
const javaPath = getConfig<string>("javaClassRunner.java.path", "java");
|
||||
const javacPath = getConfig<string>("javaClassRunner.javac.path", "javac");
|
||||
const fileDir = path.dirname(ed.document.fileName);
|
||||
const outDir = path.join(fileDir, "out", "main");
|
||||
const cpFolders = [outDir, path.join(fileDir, "out")];
|
||||
ensureDir(outDir);
|
||||
|
||||
if (fs.existsSync(outDir)) {
|
||||
for (const entry of fs.readdirSync(outDir)) {
|
||||
const fullPath = path.join(outDir, entry);
|
||||
if (fs.lstatSync(fullPath).isDirectory()) {
|
||||
fs.rmSync(fullPath, { recursive: true, force: true });
|
||||
} else {
|
||||
fs.unlinkSync(fullPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const wdCfg = getConfig<string>("javaClassRunner.run.workingDirectory", "${workspaceFolder}");
|
||||
const wd = wdCfg.replace("${workspaceFolder}", ws?.fsPath ?? process.cwd());
|
||||
const vmArgs = getConfig<string[]>("javaClassRunner.run.vmArgs", []);
|
||||
const programArgs = getConfig<string[]>("javaClassRunner.run.programArgs", []);
|
||||
|
||||
const fqcn = fqcnFromDocument(ed.document);
|
||||
if (!fqcn) { vscode.window.showErrorMessage("Konnte FQCN nicht bestimmen."); return; }
|
||||
|
||||
const detectedOuts = nearestOutFoldersFor(ed.document.fileName, ws);
|
||||
// compile: include detected outs so javac can resolve prebuilt dependencies (.class)
|
||||
if (compileEnabled) {
|
||||
try { await compileJava(ed.document.fileName, outDir, buildClasspath([...cpFolders, ...detectedOuts]), javacPath); }
|
||||
catch (err:any) { vscode.window.showErrorMessage(`Kompilierung fehlgeschlagen: ${err?.message || String(err)}`); return; }
|
||||
try {
|
||||
await compileJava(ed.document.fileName, outDir, `"${cpFolders.join(";")}"`, ctx.extensionPath); }
|
||||
|
||||
catch (err:any) {
|
||||
vscode.window.showErrorMessage(`Kompilierung fehlgeschlagen: ${err?.message || String(err)}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// runtime cp: compile out + configured + detected outs
|
||||
const cpCombined = buildClasspath([outDir, ...cpFolders, ...detectedOuts].filter(Boolean));
|
||||
const cpArg = cpCombined.length ? `-cp "${cpCombined}"` : "";
|
||||
const cmd = `${psExec(javaPath)} ${cpArg} ${vmArgs.join(" ")} ${fqcn} ${programArgs.join(" ")}`.trim();
|
||||
execInTerminal(cmd, wd);
|
||||
}));
|
||||
|
||||
ctx.subscriptions.push(vscode.commands.registerCommand("javaClassRunner.runFromClassesFolder", async () => {
|
||||
const ws = getWorkspaceFolderUri();
|
||||
const cpFolders = getConfig<string[]>("javaClassRunner.classpathFolders", ["classes"]).map(f=>toAbs(f, ws)).filter(f=>f && fs.existsSync(f));
|
||||
if (cpFolders.length===0) { vscode.window.showErrorMessage("Kein gültiger Klassen-Ordner gefunden. Prüfe 'javaClassRunner.classpathFolders'."); return; }
|
||||
const javaPath = getConfig<string>("javaClassRunner.java.path", "java");
|
||||
const wdCfg = getConfig<string>("javaClassRunner.run.workingDirectory", "${workspaceFolder}");
|
||||
const wd = wdCfg.replace("${workspaceFolder}", ws?.fsPath ?? process.cwd());
|
||||
const vmArgs = getConfig<string[]>("javaClassRunner.run.vmArgs", []);
|
||||
const programArgs = getConfig<string[]>("javaClassRunner.run.programArgs", []);
|
||||
|
||||
async function listMainClassesInFolder(root: string): Promise<string[]> {
|
||||
const out: string[] = [];
|
||||
const walk = async (dir: string) => {
|
||||
const entries = await fs.promises.readdir(dir, { withFileTypes: true });
|
||||
for (const e of entries) {
|
||||
const full = path.join(dir, e.name);
|
||||
if (e.isDirectory()) await walk(full);
|
||||
else if (e.isFile() && e.name.endsWith(".class") && !e.name.includes("$")) {
|
||||
const rel = path.relative(root, full).replace(/\.class$/,"");
|
||||
const fqcn = rel.split(path.sep).join(".");
|
||||
out.push(fqcn);
|
||||
}
|
||||
|
||||
// Find the first .class file in outDir (excluding inner classes with $)
|
||||
let mainClass: string | undefined;
|
||||
const walk = (dir: string) => {
|
||||
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
||||
for (const e of entries) {
|
||||
const full = path.join(dir, e.name);
|
||||
if (e.isDirectory()) walk(full);
|
||||
else if (e.isFile() && e.name.endsWith(".class") && !e.name.includes("$") && !mainClass) {
|
||||
const rel = path.relative(outDir, full).replace(/\.class$/,"");
|
||||
mainClass = rel.split(path.sep).join(".");
|
||||
}
|
||||
};
|
||||
if (fs.existsSync(root)) await walk(root);
|
||||
return out.sort();
|
||||
if (mainClass) break;
|
||||
}
|
||||
};
|
||||
if (fs.existsSync(outDir)) walk(outDir);
|
||||
if (!mainClass) {
|
||||
vscode.window.showErrorMessage("Keine .class-Datei im Ausgabeverzeichnis gefunden.");
|
||||
return;
|
||||
}
|
||||
|
||||
const classes: string[] = [];
|
||||
for (const folder of cpFolders) {
|
||||
const list = await listMainClassesInFolder(folder);
|
||||
for (const c of list) if (!classes.includes(c)) classes.push(c);
|
||||
}
|
||||
if (classes.length===0) { vscode.window.showWarningMessage("Keine .class-Dateien gefunden (ohne $)."); return; }
|
||||
const picked = await vscode.window.showQuickPick(classes, { placeHolder: "Wähle eine Main-Klasse (FQCN)" });
|
||||
if (!picked) return;
|
||||
|
||||
const cpCombined = buildClasspath(cpFolders);
|
||||
const cpArg = cpCombined.length ? `-cp "${cpCombined}"` : "";
|
||||
const cmd = `${psExec(javaPath)} ${cpArg} ${vmArgs.join(" ")} ${picked} ${programArgs.join(" ")}`.trim();
|
||||
const cmd = `java -cp "${cpFolders.join(";")}" ${mainClass}`.trim();
|
||||
execInTerminal(cmd, wd);
|
||||
}));
|
||||
}
|
||||
|
||||
export function deactivate() {}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user