@kaluchi/jdtbridge 1.2.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -8
- package/package.json +1 -1
- package/src/args.mjs +70 -0
- package/src/cli.mjs +82 -13
- package/src/client.mjs +38 -0
- package/src/commands/editor.mjs +25 -19
- package/src/commands/find.mjs +8 -5
- package/src/commands/implementors.mjs +11 -7
- package/src/commands/launch.mjs +308 -0
- package/src/commands/refactoring.mjs +11 -8
- package/src/commands/references.mjs +16 -13
- package/src/commands/source.mjs +11 -8
- package/src/commands/test.mjs +6 -5
package/README.md
CHANGED
|
@@ -32,20 +32,20 @@ Run `jdt help <command>` for detailed flags and examples. Most commands have sho
|
|
|
32
32
|
```bash
|
|
33
33
|
jdt projects # list workspace projects
|
|
34
34
|
jdt project-info <name> [--lines N] # (alias: pi) project overview
|
|
35
|
-
jdt find <Name> [--source-only]
|
|
36
|
-
jdt references <
|
|
35
|
+
jdt find <Name|package> [--source-only] # find types by name, wildcard, or package
|
|
36
|
+
jdt references <FQMN> [--field <name>] # (alias: refs) references to type/method/field
|
|
37
37
|
jdt subtypes <FQN> # (alias: subt) all subtypes/implementors
|
|
38
38
|
jdt hierarchy <FQN> # (alias: hier) supers + interfaces + subtypes
|
|
39
|
-
jdt implementors <
|
|
39
|
+
jdt implementors <FQMN> # (alias: impl) implementations of interface method
|
|
40
40
|
jdt type-info <FQN> # (alias: ti) class overview (fields, methods)
|
|
41
|
-
jdt source <
|
|
41
|
+
jdt source <FQMN> # (alias: src) source code (project + libraries)
|
|
42
42
|
```
|
|
43
43
|
|
|
44
44
|
### Testing & building
|
|
45
45
|
|
|
46
46
|
```bash
|
|
47
47
|
jdt build [--project <name>] [--clean] # (alias: b) build project
|
|
48
|
-
jdt test <
|
|
48
|
+
jdt test <FQMN> [--timeout N] # run JUnit test class or method
|
|
49
49
|
jdt test --project <name> [--package <pkg>] # run tests in project/package
|
|
50
50
|
```
|
|
51
51
|
|
|
@@ -66,16 +66,32 @@ File paths are workspace-relative: `my-app/src/main/java/.../Foo.java`.
|
|
|
66
66
|
jdt organize-imports <file> # (alias: oi) organize imports
|
|
67
67
|
jdt format <file> # (alias: fmt) format code (Eclipse settings)
|
|
68
68
|
jdt rename <FQN> <newName> # rename type
|
|
69
|
-
jdt rename <
|
|
69
|
+
jdt rename <FQMN> <newName> # rename method (FQMN includes method)
|
|
70
70
|
jdt rename <FQN> <newName> --field <old> # rename field
|
|
71
71
|
jdt move <FQN> <target.package> # move type to another package
|
|
72
72
|
```
|
|
73
73
|
|
|
74
|
+
### Launches
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
jdt launch list # list launches (running + terminated)
|
|
78
|
+
jdt launch configs # list saved launch configurations
|
|
79
|
+
jdt launch run <config> [-f] [-q] # launch a configuration
|
|
80
|
+
jdt launch debug <config> [-f] [-q] # launch in debug mode
|
|
81
|
+
jdt launch logs <name> [-f] [--tail N] # show console output
|
|
82
|
+
jdt launch stop <name> # stop a running launch
|
|
83
|
+
jdt launch clear [name] # remove terminated launches
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
`-f` streams output in real-time until the process terminates.
|
|
87
|
+
Without `-f`, `launch run` prints an onboarding guide with available commands (`-q` to suppress).
|
|
88
|
+
Console output persists in Eclipse and is available via `launch logs` at any time.
|
|
89
|
+
|
|
74
90
|
### Editor
|
|
75
91
|
|
|
76
92
|
```bash
|
|
77
|
-
jdt
|
|
78
|
-
jdt open <
|
|
93
|
+
jdt editors # (alias: ed) list all open editors (absolute paths)
|
|
94
|
+
jdt open <FQMN> # open in Eclipse editor
|
|
79
95
|
```
|
|
80
96
|
|
|
81
97
|
## Instance discovery
|
package/package.json
CHANGED
package/src/args.mjs
CHANGED
|
@@ -35,3 +35,73 @@ export function extractPositional(args) {
|
|
|
35
35
|
}
|
|
36
36
|
return result;
|
|
37
37
|
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Parse a Fully Qualified Method Name (FQMN) string.
|
|
41
|
+
*
|
|
42
|
+
* Supported formats:
|
|
43
|
+
* "pkg.Class#method(Type, Type)" — javadoc / surefire style
|
|
44
|
+
* "pkg.Class#method" — method without signature
|
|
45
|
+
* "pkg.Class.method(Type, Type)" — Eclipse Copy Qualified Name style
|
|
46
|
+
* "pkg.Class" — plain FQN (no method)
|
|
47
|
+
*
|
|
48
|
+
* Returns { className, method, paramTypes } where paramTypes is:
|
|
49
|
+
* null — no signature specified (any overload)
|
|
50
|
+
* [] — empty parens, i.e. zero-arg method
|
|
51
|
+
* ["String", "int[]", ...] — explicit parameter types
|
|
52
|
+
*/
|
|
53
|
+
export function parseFqmn(input) {
|
|
54
|
+
if (!input) return { className: null, method: null, paramTypes: null };
|
|
55
|
+
|
|
56
|
+
// Javadoc style: Class#method or Class#method(params)
|
|
57
|
+
const hashIdx = input.indexOf("#");
|
|
58
|
+
if (hashIdx >= 0) {
|
|
59
|
+
return parseMethodPart(input.substring(0, hashIdx), input.substring(hashIdx + 1));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Eclipse Copy Qualified Name: only when parentheses are present
|
|
63
|
+
const parenIdx = input.indexOf("(");
|
|
64
|
+
if (parenIdx >= 0) {
|
|
65
|
+
const dotIdx = input.lastIndexOf(".", parenIdx);
|
|
66
|
+
if (dotIdx >= 0) {
|
|
67
|
+
return parseMethodPart(input.substring(0, dotIdx), input.substring(dotIdx + 1));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Plain FQN — no method
|
|
72
|
+
return { className: input, method: null, paramTypes: null };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function parseMethodPart(className, rest) {
|
|
76
|
+
const parenIdx = rest.indexOf("(");
|
|
77
|
+
if (parenIdx < 0) {
|
|
78
|
+
return { className, method: rest || null, paramTypes: null };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const method = rest.substring(0, parenIdx);
|
|
82
|
+
const closeIdx = rest.lastIndexOf(")");
|
|
83
|
+
const paramsStr = rest.substring(parenIdx + 1, closeIdx >= 0 ? closeIdx : rest.length);
|
|
84
|
+
|
|
85
|
+
if (paramsStr.trim() === "") {
|
|
86
|
+
return { className, method, paramTypes: [] };
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return { className, method, paramTypes: splitParams(paramsStr) };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function splitParams(str) {
|
|
93
|
+
const params = [];
|
|
94
|
+
let depth = 0;
|
|
95
|
+
let start = 0;
|
|
96
|
+
for (let i = 0; i < str.length; i++) {
|
|
97
|
+
if (str[i] === "<") depth++;
|
|
98
|
+
else if (str[i] === ">") depth--;
|
|
99
|
+
else if (str[i] === "," && depth === 0) {
|
|
100
|
+
params.push(str.substring(start, i).trim());
|
|
101
|
+
start = i + 1;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
const last = str.substring(start).trim();
|
|
105
|
+
if (last) params.push(last);
|
|
106
|
+
return params;
|
|
107
|
+
}
|
package/src/cli.mjs
CHANGED
|
@@ -24,11 +24,29 @@ import {
|
|
|
24
24
|
moveHelp,
|
|
25
25
|
} from "./commands/refactoring.mjs";
|
|
26
26
|
import {
|
|
27
|
-
|
|
27
|
+
editors,
|
|
28
28
|
open,
|
|
29
|
-
|
|
29
|
+
editorsHelp,
|
|
30
30
|
openHelp,
|
|
31
31
|
} from "./commands/editor.mjs";
|
|
32
|
+
import {
|
|
33
|
+
launchList,
|
|
34
|
+
launchConfigs,
|
|
35
|
+
launchRun,
|
|
36
|
+
launchDebug,
|
|
37
|
+
launchStop,
|
|
38
|
+
launchClear,
|
|
39
|
+
launchLogs,
|
|
40
|
+
launchConsole,
|
|
41
|
+
launchListHelp,
|
|
42
|
+
launchConfigsHelp,
|
|
43
|
+
launchRunHelp,
|
|
44
|
+
launchDebugHelp,
|
|
45
|
+
launchStopHelp,
|
|
46
|
+
launchClearHelp,
|
|
47
|
+
launchLogsHelp,
|
|
48
|
+
launchConsoleHelp,
|
|
49
|
+
} from "./commands/launch.mjs";
|
|
32
50
|
import { setup, help as setupHelp } from "./commands/setup.mjs";
|
|
33
51
|
import { isConnectionError } from "./client.mjs";
|
|
34
52
|
import { bold, red, dim } from "./color.mjs";
|
|
@@ -36,6 +54,45 @@ import { createRequire } from "node:module";
|
|
|
36
54
|
|
|
37
55
|
const { version } = createRequire(import.meta.url)("../package.json");
|
|
38
56
|
|
|
57
|
+
const launchSubcommands = {
|
|
58
|
+
list: { fn: launchList, help: launchListHelp },
|
|
59
|
+
configs: { fn: launchConfigs, help: launchConfigsHelp },
|
|
60
|
+
run: { fn: launchRun, help: launchRunHelp },
|
|
61
|
+
debug: { fn: launchDebug, help: launchDebugHelp },
|
|
62
|
+
stop: { fn: launchStop, help: launchStopHelp },
|
|
63
|
+
clear: { fn: launchClear, help: launchClearHelp },
|
|
64
|
+
logs: { fn: launchLogs, help: launchLogsHelp },
|
|
65
|
+
console: { fn: launchConsole, help: launchConsoleHelp },
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const launchHelp = `Manage launches (running and terminated processes).
|
|
69
|
+
|
|
70
|
+
Subcommands:
|
|
71
|
+
jdt launch list list all launches
|
|
72
|
+
jdt launch configs list saved launch configurations
|
|
73
|
+
jdt launch run <config> [-f] [-q] launch a configuration
|
|
74
|
+
jdt launch debug <config> [-f] [-q] launch in debug mode
|
|
75
|
+
jdt launch logs <name> [-f] [--tail N] show console output
|
|
76
|
+
jdt launch stop <name> stop a running launch
|
|
77
|
+
jdt launch clear [name] remove terminated launches
|
|
78
|
+
|
|
79
|
+
Use "jdt help launch <subcommand>" for details.`;
|
|
80
|
+
|
|
81
|
+
async function launchDispatch(args) {
|
|
82
|
+
const [sub, ...rest] = args;
|
|
83
|
+
if (!sub || sub === "--help") {
|
|
84
|
+
console.log(launchHelp);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const cmd = launchSubcommands[sub];
|
|
88
|
+
if (!cmd) {
|
|
89
|
+
console.error(`Unknown launch subcommand: ${sub}`);
|
|
90
|
+
console.log(launchHelp);
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
await cmd.fn(rest);
|
|
94
|
+
}
|
|
95
|
+
|
|
39
96
|
const commands = {
|
|
40
97
|
projects: { fn: projects, help: projectsHelp },
|
|
41
98
|
"project-info": { fn: projectInfo, help: projectInfoHelp },
|
|
@@ -53,8 +110,9 @@ const commands = {
|
|
|
53
110
|
format: { fn: format, help: formatHelp },
|
|
54
111
|
rename: { fn: rename, help: renameHelp },
|
|
55
112
|
move: { fn: move, help: moveHelp },
|
|
56
|
-
|
|
113
|
+
editors: { fn: editors, help: editorsHelp },
|
|
57
114
|
open: { fn: open, help: openHelp },
|
|
115
|
+
launch: { fn: launchDispatch, help: launchHelp },
|
|
58
116
|
setup: { fn: setup, help: setupHelp },
|
|
59
117
|
};
|
|
60
118
|
|
|
@@ -67,7 +125,7 @@ const aliases = {
|
|
|
67
125
|
pi: "project-info",
|
|
68
126
|
ti: "type-info",
|
|
69
127
|
oi: "organize-imports",
|
|
70
|
-
|
|
128
|
+
ed: "editors",
|
|
71
129
|
src: "source",
|
|
72
130
|
b: "build",
|
|
73
131
|
err: "errors",
|
|
@@ -98,17 +156,17 @@ Requires: Eclipse running with the jdtbridge plugin.
|
|
|
98
156
|
Search & navigation:
|
|
99
157
|
projects list workspace projects
|
|
100
158
|
project-info${fmtAliases("project-info")} <name> [--lines N] project overview (adaptive detail)
|
|
101
|
-
find <Name|*Pattern
|
|
102
|
-
references${fmtAliases("references")} <
|
|
159
|
+
find <Name|*Pattern*|pkg> [--source-only] find types by name, wildcard, or package
|
|
160
|
+
references${fmtAliases("references")} <FQMN> [--field <name>] references to type/method/field
|
|
103
161
|
subtypes${fmtAliases("subtypes")} <FQN> all subtypes/implementors
|
|
104
162
|
hierarchy${fmtAliases("hierarchy")} <FQN> full hierarchy (supers + interfaces + subtypes)
|
|
105
|
-
implementors${fmtAliases("implementors")} <
|
|
163
|
+
implementors${fmtAliases("implementors")} <FQMN> implementations of interface method
|
|
106
164
|
type-info${fmtAliases("type-info")} <FQN> class overview (fields, methods, line numbers)
|
|
107
|
-
source${fmtAliases("source")} <
|
|
165
|
+
source${fmtAliases("source")} <FQMN> type or method source code (project and libraries)
|
|
108
166
|
|
|
109
167
|
Testing & building:
|
|
110
168
|
build${fmtAliases("build")} [--project <name>] [--clean] build project (incremental or clean)
|
|
111
|
-
test <
|
|
169
|
+
test <FQMN> run JUnit test class or method
|
|
112
170
|
test --project <name> [--package <pkg>] run tests in project/package
|
|
113
171
|
|
|
114
172
|
Diagnostics:
|
|
@@ -117,12 +175,21 @@ Diagnostics:
|
|
|
117
175
|
Refactoring:
|
|
118
176
|
organize-imports${fmtAliases("organize-imports")} <file> organize imports
|
|
119
177
|
format${fmtAliases("format")} <file> format with Eclipse project settings
|
|
120
|
-
rename <
|
|
178
|
+
rename <FQMN> <newName> [--field <old>] rename type/method/field
|
|
121
179
|
move <FQN> <target.package> move type to another package
|
|
122
180
|
|
|
181
|
+
Launches:
|
|
182
|
+
launch list list launches (running + terminated)
|
|
183
|
+
launch configs list saved launch configurations
|
|
184
|
+
launch run <config> [-f] [-q] launch a configuration
|
|
185
|
+
launch debug <config> [-f] [-q] launch in debug mode
|
|
186
|
+
launch logs <name> [-f] [--tail N] show console output
|
|
187
|
+
launch stop <name> stop a running launch
|
|
188
|
+
launch clear [name] remove terminated launches
|
|
189
|
+
|
|
123
190
|
Editor:
|
|
124
|
-
|
|
125
|
-
open <
|
|
191
|
+
editors${fmtAliases("editors")} list open editors (absolute paths)
|
|
192
|
+
open <FQMN> open in Eclipse editor
|
|
126
193
|
|
|
127
194
|
Setup:
|
|
128
195
|
setup [--check|--remove] install/check/remove Eclipse plugin
|
|
@@ -146,7 +213,9 @@ export async function run(argv) {
|
|
|
146
213
|
if (command === "help") {
|
|
147
214
|
const topic = rest[0];
|
|
148
215
|
const resolved = topic ? resolve(topic) : null;
|
|
149
|
-
if (resolved) {
|
|
216
|
+
if (resolved === "launch" && rest[1] && launchSubcommands[rest[1]]) {
|
|
217
|
+
console.log(launchSubcommands[rest[1]].help);
|
|
218
|
+
} else if (resolved) {
|
|
150
219
|
console.log(commands[resolved].help);
|
|
151
220
|
} else if (topic) {
|
|
152
221
|
console.error(`Unknown command: ${topic}`);
|
package/src/client.mjs
CHANGED
|
@@ -158,6 +158,44 @@ export function getRaw(path, timeoutMs = 10_000) {
|
|
|
158
158
|
});
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
+
/**
|
|
162
|
+
* HTTP GET with streaming response. Pipes text/plain chunks to
|
|
163
|
+
* the provided writable stream (typically process.stdout).
|
|
164
|
+
* Resolves when the server closes the connection.
|
|
165
|
+
* Rejects on non-200 status or connection error.
|
|
166
|
+
* @param {string} path
|
|
167
|
+
* @param {import('stream').Writable} dest
|
|
168
|
+
* @returns {Promise<void>}
|
|
169
|
+
*/
|
|
170
|
+
export function getStream(path, dest) {
|
|
171
|
+
const inst = connect();
|
|
172
|
+
return new Promise((resolve, reject) => {
|
|
173
|
+
const req = request(
|
|
174
|
+
{
|
|
175
|
+
hostname: "127.0.0.1",
|
|
176
|
+
port: inst.port,
|
|
177
|
+
path,
|
|
178
|
+
method: "GET",
|
|
179
|
+
timeout: 0, // no timeout for streaming
|
|
180
|
+
headers: authHeaders(),
|
|
181
|
+
},
|
|
182
|
+
(res) => {
|
|
183
|
+
if (res.statusCode !== 200) {
|
|
184
|
+
let data = "";
|
|
185
|
+
res.on("data", (chunk) => (data += chunk));
|
|
186
|
+
res.on("end", () => reject(new Error(data.trim())));
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
res.pipe(dest, { end: false });
|
|
190
|
+
res.on("end", resolve);
|
|
191
|
+
res.on("error", reject);
|
|
192
|
+
},
|
|
193
|
+
);
|
|
194
|
+
req.on("error", reject);
|
|
195
|
+
req.end();
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
|
|
161
199
|
/**
|
|
162
200
|
* Check if error is a connection refused error.
|
|
163
201
|
* @param {Error} e
|
package/src/commands/editor.mjs
CHANGED
|
@@ -1,33 +1,36 @@
|
|
|
1
1
|
import { get } from "../client.mjs";
|
|
2
|
-
import { extractPositional, parseFlags } from "../args.mjs";
|
|
3
|
-
import { stripProject } from "../paths.mjs";
|
|
2
|
+
import { extractPositional, parseFlags, parseFqmn } from "../args.mjs";
|
|
4
3
|
|
|
5
|
-
export async function
|
|
6
|
-
const
|
|
7
|
-
if (
|
|
8
|
-
console.error(
|
|
4
|
+
export async function editors() {
|
|
5
|
+
const results = await get("/editors");
|
|
6
|
+
if (results.error) {
|
|
7
|
+
console.error(results.error);
|
|
9
8
|
process.exit(1);
|
|
10
9
|
}
|
|
11
|
-
if (
|
|
12
|
-
console.log("(no
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
if (results.length === 0) {
|
|
11
|
+
console.log("(no open editors)");
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
for (const r of results) {
|
|
15
|
+
console.log(r.file);
|
|
15
16
|
}
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
export async function open(args) {
|
|
19
20
|
const pos = extractPositional(args);
|
|
20
21
|
const flags = parseFlags(args);
|
|
21
|
-
const
|
|
22
|
-
const
|
|
22
|
+
const parsed = parseFqmn(pos[0]);
|
|
23
|
+
const fqn = parsed.className;
|
|
24
|
+
const method = parsed.method || pos[1];
|
|
23
25
|
if (!fqn) {
|
|
24
|
-
console.error("Usage: open <FQN>
|
|
26
|
+
console.error("Usage: open <FQN>[#method[(param types)]]");
|
|
25
27
|
process.exit(1);
|
|
26
28
|
}
|
|
27
29
|
let url = `/open?class=${encodeURIComponent(fqn)}`;
|
|
28
30
|
if (method) url += `&method=${encodeURIComponent(method)}`;
|
|
29
|
-
if (
|
|
30
|
-
url += `&
|
|
31
|
+
if (parsed.paramTypes) {
|
|
32
|
+
url += `¶mTypes=${encodeURIComponent(parsed.paramTypes.join(","))}`;
|
|
33
|
+
}
|
|
31
34
|
const result = await get(url);
|
|
32
35
|
if (result.error) {
|
|
33
36
|
console.error(result.error);
|
|
@@ -36,14 +39,17 @@ export async function open(args) {
|
|
|
36
39
|
console.log("Opened");
|
|
37
40
|
}
|
|
38
41
|
|
|
39
|
-
export const
|
|
42
|
+
export const editorsHelp = `List all open editors in Eclipse. Active editor first.
|
|
43
|
+
|
|
44
|
+
Usage: jdt editors
|
|
40
45
|
|
|
41
|
-
|
|
46
|
+
Output: absolute file paths, one per line.`;
|
|
42
47
|
|
|
43
48
|
export const openHelp = `Open a type or method in the Eclipse editor.
|
|
44
49
|
|
|
45
|
-
Usage: jdt open <FQN>
|
|
50
|
+
Usage: jdt open <FQN>[#method[(param types)]]
|
|
46
51
|
|
|
47
52
|
Examples:
|
|
48
53
|
jdt open app.m8.dao.StaffDaoImpl
|
|
49
|
-
jdt open app.m8.dao.StaffDaoImpl
|
|
54
|
+
jdt open app.m8.dao.StaffDaoImpl#getStaff
|
|
55
|
+
jdt open "app.m8.dao.StaffDaoImpl#save(Order)"`;
|
package/src/commands/find.mjs
CHANGED
|
@@ -25,17 +25,20 @@ export async function find(args) {
|
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
export const help = `Find type declarations by name or
|
|
28
|
+
export const help = `Find type declarations by name, wildcard, or package.
|
|
29
29
|
|
|
30
|
-
Usage: jdt find <Name|*Pattern
|
|
30
|
+
Usage: jdt find <Name|*Pattern*|package.name> [--source-only]
|
|
31
31
|
|
|
32
32
|
Arguments:
|
|
33
|
-
Name
|
|
34
|
-
*Pattern*
|
|
33
|
+
Name exact type name (e.g. DataSourceUtils)
|
|
34
|
+
*Pattern* wildcard pattern (e.g. *Controller*, Find*)
|
|
35
|
+
package.name dotted package name — lists all types in the package
|
|
35
36
|
|
|
36
37
|
Flags:
|
|
37
38
|
--source-only exclude binary/library types, show only workspace sources
|
|
38
39
|
|
|
39
40
|
Examples:
|
|
40
41
|
jdt find DataSourceUtils
|
|
41
|
-
jdt find *Controller* --source-only
|
|
42
|
+
jdt find *Controller* --source-only
|
|
43
|
+
jdt find com.example.service
|
|
44
|
+
jdt find com.example.service.`;
|
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
import { get } from "../client.mjs";
|
|
2
|
-
import { extractPositional, parseFlags } from "../args.mjs";
|
|
2
|
+
import { extractPositional, parseFlags, parseFqmn } from "../args.mjs";
|
|
3
3
|
import { stripProject } from "../paths.mjs";
|
|
4
4
|
|
|
5
5
|
export async function implementors(args) {
|
|
6
6
|
const pos = extractPositional(args);
|
|
7
7
|
const flags = parseFlags(args);
|
|
8
|
-
const
|
|
8
|
+
const parsed = parseFqmn(pos[0]);
|
|
9
|
+
const fqn = parsed.className;
|
|
10
|
+
const method = parsed.method || pos[1];
|
|
9
11
|
if (!fqn || !method) {
|
|
10
|
-
console.error("Usage: implementors <FQN
|
|
12
|
+
console.error("Usage: implementors <FQN>#<method>[(param types)]");
|
|
11
13
|
process.exit(1);
|
|
12
14
|
}
|
|
13
15
|
let url = `/implementors?class=${encodeURIComponent(fqn)}&method=${encodeURIComponent(method)}`;
|
|
14
|
-
if (
|
|
15
|
-
url += `&
|
|
16
|
+
if (parsed.paramTypes) {
|
|
17
|
+
url += `¶mTypes=${encodeURIComponent(parsed.paramTypes.join(","))}`;
|
|
18
|
+
}
|
|
16
19
|
const results = await get(url, 30_000);
|
|
17
20
|
if (results.error) {
|
|
18
21
|
console.error(results.error);
|
|
@@ -29,6 +32,7 @@ export async function implementors(args) {
|
|
|
29
32
|
|
|
30
33
|
export const help = `Find implementations of an interface method across all implementing classes.
|
|
31
34
|
|
|
32
|
-
Usage: jdt implementors <FQN
|
|
35
|
+
Usage: jdt implementors <FQN>#<method>[(param types)]
|
|
33
36
|
|
|
34
|
-
|
|
37
|
+
Examples:
|
|
38
|
+
jdt implementors app.m8.web.shared.core.HasId#getId`;
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import { get, getStream } from "../client.mjs";
|
|
2
|
+
import { extractPositional, parseFlags } from "../args.mjs";
|
|
3
|
+
|
|
4
|
+
export async function launchList() {
|
|
5
|
+
const results = await get("/launch/list");
|
|
6
|
+
if (results.error) {
|
|
7
|
+
console.error(results.error);
|
|
8
|
+
process.exit(1);
|
|
9
|
+
}
|
|
10
|
+
if (results.length === 0) {
|
|
11
|
+
console.log("(no launches)");
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
for (const r of results) {
|
|
15
|
+
const status = r.terminated
|
|
16
|
+
? `terminated${r.exitCode !== undefined ? ` (${r.exitCode})` : ""}`
|
|
17
|
+
: "running";
|
|
18
|
+
const parts = [r.name, r.type, r.mode, status];
|
|
19
|
+
if (r.pid) parts.push(`pid:${r.pid}`);
|
|
20
|
+
console.log(parts.join(" "));
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export async function launchConfigs() {
|
|
25
|
+
const results = await get("/launch/configs");
|
|
26
|
+
if (results.error) {
|
|
27
|
+
console.error(results.error);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
if (results.length === 0) {
|
|
31
|
+
console.log("(no launch configurations)");
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
for (const r of results) {
|
|
35
|
+
console.log(`${r.name} ${r.type}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export async function launchClear(args) {
|
|
40
|
+
const pos = extractPositional(args);
|
|
41
|
+
let url = "/launch/clear";
|
|
42
|
+
if (pos[0]) url += `?name=${encodeURIComponent(pos[0])}`;
|
|
43
|
+
const result = await get(url);
|
|
44
|
+
if (result.error) {
|
|
45
|
+
console.error(result.error);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
console.log(`Removed ${result.removed} terminated launch${result.removed !== 1 ? "es" : ""}`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Launch a configuration. Without -f, prints onboarding guide.
|
|
53
|
+
* With -f, streams console output until termination.
|
|
54
|
+
*/
|
|
55
|
+
export async function launchRun(args) {
|
|
56
|
+
return launchWithMode(args, "run");
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Launch in debug mode. Same interface as run. */
|
|
60
|
+
export async function launchDebug(args) {
|
|
61
|
+
return launchWithMode(args, "debug");
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async function launchWithMode(args, mode) {
|
|
65
|
+
const pos = extractPositional(args);
|
|
66
|
+
const name = pos[0];
|
|
67
|
+
if (!name) {
|
|
68
|
+
console.error(`Usage: launch ${mode} <config-name> [-f] [-q]`);
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
let url = `/launch/run?name=${encodeURIComponent(name)}`;
|
|
73
|
+
if (mode === "debug") url += "&debug";
|
|
74
|
+
const result = await get(url, 30_000);
|
|
75
|
+
if (result.error) {
|
|
76
|
+
console.error(result.error);
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const follow = args.includes("-f") || args.includes("--follow");
|
|
81
|
+
if (follow) {
|
|
82
|
+
console.error(formatLaunched(result));
|
|
83
|
+
const exitCode = await followLogs(result.name, args);
|
|
84
|
+
process.exit(exitCode);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const quiet = args.includes("-q") || args.includes("--quiet");
|
|
88
|
+
const n = result.name;
|
|
89
|
+
console.log(formatLaunched(result));
|
|
90
|
+
|
|
91
|
+
if (!quiet) {
|
|
92
|
+
console.log(launchGuide(n));
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function formatLaunched(result) {
|
|
97
|
+
const parts = [`Launched ${result.name} (${result.mode})`];
|
|
98
|
+
if (result.type) parts[0] += ` [${result.type}]`;
|
|
99
|
+
if (result.pid) parts.push(` PID: ${result.pid}`);
|
|
100
|
+
if (result.workingDir) parts.push(` Working dir: ${result.workingDir}`);
|
|
101
|
+
if (result.cmdline) {
|
|
102
|
+
parts.push(` Command: ${result.cmdline}`);
|
|
103
|
+
}
|
|
104
|
+
return parts.join("\n");
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function launchGuide(name) {
|
|
108
|
+
return `
|
|
109
|
+
Console output is captured by Eclipse and remains available
|
|
110
|
+
after the process terminates. You can read it at any time,
|
|
111
|
+
filter with grep, or pipe through tail/head.
|
|
112
|
+
|
|
113
|
+
View logs:
|
|
114
|
+
jdt launch logs ${name}
|
|
115
|
+
jdt launch logs ${name} --tail 30
|
|
116
|
+
|
|
117
|
+
Wait for completion (blocks until process exits):
|
|
118
|
+
jdt launch logs ${name} -f | tail -20
|
|
119
|
+
jdt launch logs ${name} -f
|
|
120
|
+
|
|
121
|
+
Manage:
|
|
122
|
+
jdt launch list
|
|
123
|
+
jdt launch stop ${name}
|
|
124
|
+
jdt launch clear
|
|
125
|
+
|
|
126
|
+
Run modes:
|
|
127
|
+
jdt launch run <config> launch (this output)
|
|
128
|
+
jdt launch run <config> -f launch + stream output
|
|
129
|
+
jdt launch run <config> -f | tail launch + wait + bounded
|
|
130
|
+
jdt launch debug <config> launch with debugger
|
|
131
|
+
|
|
132
|
+
Add -q to suppress this guide.`;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export async function launchStop(args) {
|
|
136
|
+
const pos = extractPositional(args);
|
|
137
|
+
const name = pos[0];
|
|
138
|
+
if (!name) {
|
|
139
|
+
console.error("Usage: launch stop <name>");
|
|
140
|
+
process.exit(1);
|
|
141
|
+
}
|
|
142
|
+
const url = `/launch/stop?name=${encodeURIComponent(name)}`;
|
|
143
|
+
const result = await get(url);
|
|
144
|
+
if (result.error) {
|
|
145
|
+
console.error(result.error);
|
|
146
|
+
process.exit(1);
|
|
147
|
+
}
|
|
148
|
+
console.log(`Stopped ${result.name}`);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Show console output. "logs" is the primary name,
|
|
153
|
+
* "console" is kept as an alias.
|
|
154
|
+
*/
|
|
155
|
+
export async function launchLogs(args) {
|
|
156
|
+
const pos = extractPositional(args);
|
|
157
|
+
const flags = parseFlags(args);
|
|
158
|
+
const name = pos[0];
|
|
159
|
+
if (!name) {
|
|
160
|
+
console.error(
|
|
161
|
+
"Usage: launch logs <name> [-f|--follow] [--tail N]",
|
|
162
|
+
);
|
|
163
|
+
process.exit(1);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const follow = args.includes("-f") || args.includes("--follow");
|
|
167
|
+
if (follow) {
|
|
168
|
+
const exitCode = await followLogs(name, args);
|
|
169
|
+
process.exit(exitCode);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Snapshot mode
|
|
173
|
+
let url = `/launch/console?name=${encodeURIComponent(name)}`;
|
|
174
|
+
if (flags.tail !== undefined && flags.tail !== true)
|
|
175
|
+
url += `&tail=${flags.tail}`;
|
|
176
|
+
if (args.includes("--stderr")) url += "&stream=stderr";
|
|
177
|
+
else if (args.includes("--stdout")) url += "&stream=stdout";
|
|
178
|
+
const result = await get(url, 30_000);
|
|
179
|
+
if (result.error) {
|
|
180
|
+
console.error(result.error);
|
|
181
|
+
process.exit(1);
|
|
182
|
+
}
|
|
183
|
+
if (result.output) {
|
|
184
|
+
const text = result.output.endsWith("\n")
|
|
185
|
+
? result.output.slice(0, -1)
|
|
186
|
+
: result.output;
|
|
187
|
+
console.log(text);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/** Alias: console → logs */
|
|
192
|
+
export const launchConsole = launchLogs;
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Stream console output until process terminates or Ctrl+C.
|
|
196
|
+
* Returns the process exit code (0 on detach).
|
|
197
|
+
*/
|
|
198
|
+
async function followLogs(name, args) {
|
|
199
|
+
const flags = parseFlags(args);
|
|
200
|
+
let url = `/launch/console/stream?name=${encodeURIComponent(name)}`;
|
|
201
|
+
if (flags.tail !== undefined && flags.tail !== true)
|
|
202
|
+
url += `&tail=${flags.tail}`;
|
|
203
|
+
if (args.includes("--stderr")) url += "&stream=stderr";
|
|
204
|
+
else if (args.includes("--stdout")) url += "&stream=stdout";
|
|
205
|
+
|
|
206
|
+
// Ctrl+C = detach, not kill
|
|
207
|
+
let detached = false;
|
|
208
|
+
const onSigint = () => {
|
|
209
|
+
detached = true;
|
|
210
|
+
process.stdout.write("\n");
|
|
211
|
+
process.exit(0);
|
|
212
|
+
};
|
|
213
|
+
process.on("SIGINT", onSigint);
|
|
214
|
+
|
|
215
|
+
try {
|
|
216
|
+
await getStream(url, process.stdout);
|
|
217
|
+
} catch (e) {
|
|
218
|
+
if (!detached) {
|
|
219
|
+
console.error(e.message);
|
|
220
|
+
return 1;
|
|
221
|
+
}
|
|
222
|
+
return 0;
|
|
223
|
+
} finally {
|
|
224
|
+
process.removeListener("SIGINT", onSigint);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Stream ended — fetch exit code
|
|
228
|
+
try {
|
|
229
|
+
const list = await get("/launch/list");
|
|
230
|
+
const entry = Array.isArray(list)
|
|
231
|
+
? list.find((l) => l.name === name && l.terminated)
|
|
232
|
+
: null;
|
|
233
|
+
return entry?.exitCode ?? 0;
|
|
234
|
+
} catch {
|
|
235
|
+
return 0;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export const launchRunHelp = `Launch a saved configuration.
|
|
240
|
+
|
|
241
|
+
Usage: jdt launch run <config-name> [-f] [-q]
|
|
242
|
+
|
|
243
|
+
Without -f, launches and prints a guide with available commands.
|
|
244
|
+
With -f, launches and streams console output until the process terminates.
|
|
245
|
+
|
|
246
|
+
Flags:
|
|
247
|
+
-f, --follow stream output (Ctrl+C to detach, process keeps running)
|
|
248
|
+
-q, --quiet suppress onboarding guide
|
|
249
|
+
|
|
250
|
+
Examples:
|
|
251
|
+
jdt launch run m8-server run + show guide
|
|
252
|
+
jdt launch run m8-server -q run silently
|
|
253
|
+
jdt launch run jdtbridge-verify -f run + stream all output
|
|
254
|
+
jdt launch run m8-server -f | tail -20 run + wait + bounded output`;
|
|
255
|
+
|
|
256
|
+
export const launchDebugHelp = `Launch a configuration in debug mode.
|
|
257
|
+
|
|
258
|
+
Usage: jdt launch debug <config-name> [-f] [-q]
|
|
259
|
+
|
|
260
|
+
Same as "launch run" but attaches the Eclipse debugger.
|
|
261
|
+
|
|
262
|
+
Examples:
|
|
263
|
+
jdt launch debug m8-server
|
|
264
|
+
jdt launch debug m8-server -f`;
|
|
265
|
+
|
|
266
|
+
export const launchStopHelp = `Stop a running launch.
|
|
267
|
+
|
|
268
|
+
Usage: jdt launch stop <name>
|
|
269
|
+
|
|
270
|
+
Example: jdt launch stop m8-server`;
|
|
271
|
+
|
|
272
|
+
export const launchConfigsHelp = `List saved launch configurations (Run → Run Configurations).
|
|
273
|
+
|
|
274
|
+
Usage: jdt launch configs
|
|
275
|
+
|
|
276
|
+
Output: configuration name and type, one per line.`;
|
|
277
|
+
|
|
278
|
+
export const launchClearHelp = `Remove terminated launches and their console output.
|
|
279
|
+
|
|
280
|
+
Usage: jdt launch clear [name]
|
|
281
|
+
|
|
282
|
+
Without name, removes all terminated launches. With name, removes only that one.`;
|
|
283
|
+
|
|
284
|
+
export const launchListHelp = `List all launches (running and terminated).
|
|
285
|
+
|
|
286
|
+
Usage: jdt launch list
|
|
287
|
+
|
|
288
|
+
Output: name, type, mode, status — one launch per line.`;
|
|
289
|
+
|
|
290
|
+
export const launchLogsHelp = `Show console output of a launch.
|
|
291
|
+
|
|
292
|
+
Console output is captured by Eclipse and persists after the process
|
|
293
|
+
terminates. Without -f, returns a snapshot. With -f, streams in real-time.
|
|
294
|
+
|
|
295
|
+
Usage: jdt launch logs <name> [-f|--follow] [--tail N]
|
|
296
|
+
|
|
297
|
+
Flags:
|
|
298
|
+
-f, --follow stream until process terminates (Ctrl+C to detach)
|
|
299
|
+
--tail <N> last N lines only (snapshot), or start N lines back (follow)
|
|
300
|
+
|
|
301
|
+
Examples:
|
|
302
|
+
jdt launch logs m8-server full output snapshot
|
|
303
|
+
jdt launch logs m8-server --tail 30 last 30 lines
|
|
304
|
+
jdt launch logs m8-server -f stream live
|
|
305
|
+
jdt launch logs m8-server -f | tail -20 wait + bounded output`;
|
|
306
|
+
|
|
307
|
+
// Keep old name for backward compatibility
|
|
308
|
+
export const launchConsoleHelp = launchLogsHelp;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { get } from "../client.mjs";
|
|
2
|
-
import { extractPositional, parseFlags } from "../args.mjs";
|
|
2
|
+
import { extractPositional, parseFlags, parseFqmn } from "../args.mjs";
|
|
3
3
|
import { toWsPath } from "../paths.mjs";
|
|
4
4
|
import { green, yellow } from "../color.mjs";
|
|
5
5
|
|
|
@@ -46,19 +46,21 @@ export async function format(args) {
|
|
|
46
46
|
export async function rename(args) {
|
|
47
47
|
const pos = extractPositional(args);
|
|
48
48
|
const flags = parseFlags(args);
|
|
49
|
-
const
|
|
49
|
+
const parsed = parseFqmn(pos[0]);
|
|
50
|
+
const fqn = parsed.className;
|
|
50
51
|
const newName = pos[1];
|
|
51
52
|
if (!fqn || !newName) {
|
|
52
53
|
console.error(
|
|
53
|
-
"Usage: rename <FQN> <newName> [--field name]
|
|
54
|
+
"Usage: rename <FQN>[#method[(param types)]] <newName> [--field name]",
|
|
54
55
|
);
|
|
55
56
|
process.exit(1);
|
|
56
57
|
}
|
|
57
58
|
let url = `/rename?class=${encodeURIComponent(fqn)}&newName=${encodeURIComponent(newName)}`;
|
|
58
59
|
if (flags.field) url += `&field=${encodeURIComponent(flags.field)}`;
|
|
59
|
-
if (
|
|
60
|
-
if (
|
|
61
|
-
url += `&
|
|
60
|
+
if (parsed.method) url += `&method=${encodeURIComponent(parsed.method)}`;
|
|
61
|
+
if (parsed.paramTypes) {
|
|
62
|
+
url += `¶mTypes=${encodeURIComponent(parsed.paramTypes.join(","))}`;
|
|
63
|
+
}
|
|
62
64
|
const result = await get(url, 30_000);
|
|
63
65
|
if (result.error) {
|
|
64
66
|
console.error(result.error);
|
|
@@ -103,11 +105,12 @@ Example: jdt format m8-server/src/main/java/.../Foo.java`;
|
|
|
103
105
|
|
|
104
106
|
export const renameHelp = `Rename a type, method, or field (updates all references).
|
|
105
107
|
|
|
106
|
-
Usage: jdt rename <FQN>
|
|
108
|
+
Usage: jdt rename <FQN>[#method[(param types)]] <newName>
|
|
109
|
+
jdt rename <FQN> <newName> [--field <old>]
|
|
107
110
|
|
|
108
111
|
Examples:
|
|
109
112
|
jdt rename app.m8.dto.Foo Bar
|
|
110
|
-
jdt rename app.m8.dto.Foo getBar
|
|
113
|
+
jdt rename app.m8.dto.Foo#getFoo getBar`;
|
|
111
114
|
|
|
112
115
|
export const moveHelp = `Move a type to another package (updates all references).
|
|
113
116
|
|
|
@@ -1,24 +1,26 @@
|
|
|
1
1
|
import { get } from "../client.mjs";
|
|
2
|
-
import { extractPositional, parseFlags } from "../args.mjs";
|
|
2
|
+
import { extractPositional, parseFlags, parseFqmn } from "../args.mjs";
|
|
3
3
|
import { formatReferences } from "../format/references.mjs";
|
|
4
4
|
|
|
5
5
|
export async function references(args) {
|
|
6
6
|
const pos = extractPositional(args);
|
|
7
7
|
const flags = parseFlags(args);
|
|
8
|
-
const
|
|
8
|
+
const parsed = parseFqmn(pos[0]);
|
|
9
|
+
const fqn = parsed.className;
|
|
9
10
|
if (!fqn) {
|
|
10
|
-
console.error("Usage: references <FQN>
|
|
11
|
+
console.error("Usage: references <FQN>[#method[(param types)]] [--field name]");
|
|
11
12
|
process.exit(1);
|
|
12
13
|
}
|
|
13
14
|
let url = `/references?class=${encodeURIComponent(fqn)}`;
|
|
14
15
|
if (flags.field) {
|
|
15
16
|
url += `&field=${encodeURIComponent(flags.field)}`;
|
|
16
17
|
} else {
|
|
17
|
-
const method = pos[1];
|
|
18
|
+
const method = parsed.method || pos[1];
|
|
18
19
|
if (method) url += `&method=${encodeURIComponent(method)}`;
|
|
20
|
+
if (parsed.paramTypes) {
|
|
21
|
+
url += `¶mTypes=${encodeURIComponent(parsed.paramTypes.join(","))}`;
|
|
22
|
+
}
|
|
19
23
|
}
|
|
20
|
-
if (flags.arity !== undefined && flags.arity !== true)
|
|
21
|
-
url += `&arity=${flags.arity}`;
|
|
22
24
|
const results = await get(url, 30_000);
|
|
23
25
|
if (results.error) {
|
|
24
26
|
console.error(results.error);
|
|
@@ -33,19 +35,20 @@ export async function references(args) {
|
|
|
33
35
|
|
|
34
36
|
export const help = `Find all references to a type, method, or field across the workspace.
|
|
35
37
|
|
|
36
|
-
Usage: jdt references <FQN>
|
|
38
|
+
Usage: jdt references <FQN>[#method[(param types)]]
|
|
37
39
|
jdt references <FQN> --field <name>
|
|
38
|
-
jdt references <FQN> [method] --arity <n>
|
|
39
40
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
method
|
|
41
|
+
FQMN formats (Fully Qualified Method Name):
|
|
42
|
+
pkg.Class#method any overload
|
|
43
|
+
pkg.Class#method() zero-arg overload
|
|
44
|
+
pkg.Class#method(String) specific signature
|
|
45
|
+
pkg.Class.method(String) Eclipse Copy Qualified Name style
|
|
43
46
|
|
|
44
47
|
Flags:
|
|
45
48
|
--field <name> find references to a field
|
|
46
|
-
--arity <n> disambiguate overloaded methods by parameter count
|
|
47
49
|
|
|
48
50
|
Examples:
|
|
49
51
|
jdt references app.m8.dto.web.core.IdOrgRoot
|
|
50
|
-
jdt references app.m8.dao.StaffDaoImpl
|
|
52
|
+
jdt references app.m8.dao.StaffDaoImpl#getStaff
|
|
53
|
+
jdt references "app.m8.dao.StaffDaoImpl#save(Order)"
|
|
51
54
|
jdt references app.m8.dao.StaffDaoImpl --field staffCache`;
|
package/src/commands/source.mjs
CHANGED
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
import { getRaw } from "../client.mjs";
|
|
2
|
-
import { extractPositional, parseFlags } from "../args.mjs";
|
|
2
|
+
import { extractPositional, parseFlags, parseFqmn } from "../args.mjs";
|
|
3
3
|
import { stripProject } from "../paths.mjs";
|
|
4
4
|
|
|
5
5
|
export async function source(args) {
|
|
6
6
|
const pos = extractPositional(args);
|
|
7
7
|
const flags = parseFlags(args);
|
|
8
|
-
const
|
|
8
|
+
const parsed = parseFqmn(pos[0]);
|
|
9
|
+
const fqn = parsed.className;
|
|
9
10
|
if (!fqn) {
|
|
10
|
-
console.error("Usage: source <FQN>
|
|
11
|
+
console.error("Usage: source <FQN>[#method[(param types)]]");
|
|
11
12
|
process.exit(1);
|
|
12
13
|
}
|
|
14
|
+
const method = parsed.method || pos[1];
|
|
13
15
|
let url = `/source?class=${encodeURIComponent(fqn)}`;
|
|
14
16
|
if (method) url += `&method=${encodeURIComponent(method)}`;
|
|
15
|
-
if (
|
|
16
|
-
url += `&
|
|
17
|
+
if (parsed.paramTypes) {
|
|
18
|
+
url += `¶mTypes=${encodeURIComponent(parsed.paramTypes.join(","))}`;
|
|
19
|
+
}
|
|
17
20
|
const result = await getRaw(url, 30_000);
|
|
18
21
|
const file = result.headers["x-file"] || "?";
|
|
19
22
|
const startLine = result.headers["x-start-line"] || "?";
|
|
@@ -35,9 +38,9 @@ export async function source(args) {
|
|
|
35
38
|
|
|
36
39
|
export const help = `Print source code of a type or method.
|
|
37
40
|
|
|
38
|
-
Usage: jdt source <FQN>
|
|
41
|
+
Usage: jdt source <FQN>[#method[(param types)]]
|
|
39
42
|
|
|
40
43
|
Examples:
|
|
41
44
|
jdt source app.m8.dao.StaffDaoImpl
|
|
42
|
-
jdt source app.m8.dao.StaffDaoImpl
|
|
43
|
-
jdt source app.m8.dao.StaffDaoImpl
|
|
45
|
+
jdt source app.m8.dao.StaffDaoImpl#getStaff
|
|
46
|
+
jdt source "app.m8.dao.StaffDaoImpl#save(Order)"`;
|
package/src/commands/test.mjs
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { get } from "../client.mjs";
|
|
2
|
-
import { extractPositional, parseFlags } from "../args.mjs";
|
|
2
|
+
import { extractPositional, parseFlags, parseFqmn } from "../args.mjs";
|
|
3
3
|
import { formatTestResults } from "../format/test-results.mjs";
|
|
4
4
|
|
|
5
5
|
export async function test(args) {
|
|
6
6
|
const pos = extractPositional(args);
|
|
7
7
|
const flags = parseFlags(args);
|
|
8
8
|
let url = "/test?";
|
|
9
|
-
const
|
|
9
|
+
const parsed = parseFqmn(pos[0]);
|
|
10
|
+
const fqn = parsed.className;
|
|
10
11
|
if (fqn) {
|
|
11
12
|
url += `class=${encodeURIComponent(fqn)}`;
|
|
12
|
-
const method = pos[1];
|
|
13
|
+
const method = parsed.method || pos[1];
|
|
13
14
|
if (method) url += `&method=${encodeURIComponent(method)}`;
|
|
14
15
|
} else if (flags.project) {
|
|
15
16
|
url += `project=${encodeURIComponent(flags.project)}`;
|
|
@@ -33,7 +34,7 @@ export async function test(args) {
|
|
|
33
34
|
|
|
34
35
|
export const help = `Run JUnit tests via Eclipse's built-in test runner.
|
|
35
36
|
|
|
36
|
-
Usage: jdt test <FQN>
|
|
37
|
+
Usage: jdt test <FQN>[#method]
|
|
37
38
|
jdt test --project <name> [--package <pkg>]
|
|
38
39
|
|
|
39
40
|
Flags:
|
|
@@ -43,5 +44,5 @@ Flags:
|
|
|
43
44
|
|
|
44
45
|
Examples:
|
|
45
46
|
jdt test app.m8ws.utils.ObjectMapperTest
|
|
46
|
-
jdt test app.m8ws.utils.ObjectMapperTest
|
|
47
|
+
jdt test app.m8ws.utils.ObjectMapperTest#testSerialize
|
|
47
48
|
jdt test --project m8-server`;
|