@kaluchi/jdtbridge 1.1.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 ADDED
@@ -0,0 +1,102 @@
1
+ # @kaluchi/jdtbridge — CLI reference
2
+
3
+ CLI for [JDT Bridge](../README.md). Requires Eclipse running with the jdtbridge plugin installed.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ cd cli
9
+ npm install
10
+ npm link # registers `jdt` and `jdtbridge` global commands
11
+ ```
12
+
13
+ ## Plugin setup
14
+
15
+ ```bash
16
+ jdt setup # build + install into Eclipse
17
+ jdt setup --check # diagnostic: show status of all components
18
+ jdt setup --skip-build # reinstall last build
19
+ jdt setup --clean # clean build (mvn clean verify)
20
+ jdt setup --remove # uninstall plugin from Eclipse
21
+ jdt setup --eclipse <path> # specify Eclipse path (saved to config)
22
+ ```
23
+
24
+ If Eclipse is running, you will be prompted to stop it. After install, Eclipse restarts automatically with the same workspace.
25
+
26
+ ## Commands
27
+
28
+ Run `jdt help <command>` for detailed flags and examples. Most commands have short aliases.
29
+
30
+ ### Search & navigation
31
+
32
+ ```bash
33
+ jdt projects # list workspace projects
34
+ jdt project-info <name> [--lines N] # (alias: pi) project overview
35
+ jdt find <Name> [--source-only] # find type declarations (* wildcards)
36
+ jdt references <FQN> [method] [--field <name>] # (alias: refs) references to type/method/field
37
+ jdt subtypes <FQN> # (alias: subt) all subtypes/implementors
38
+ jdt hierarchy <FQN> # (alias: hier) supers + interfaces + subtypes
39
+ jdt implementors <FQN> <method> [--arity N] # (alias: impl) implementations of interface method
40
+ jdt type-info <FQN> # (alias: ti) class overview (fields, methods)
41
+ jdt source <FQN> [method] [--arity N] # (alias: src) source code (project + libraries)
42
+ ```
43
+
44
+ ### Testing & building
45
+
46
+ ```bash
47
+ jdt build [--project <name>] [--clean] # (alias: b) build project
48
+ jdt test <FQN> [method] [--timeout N] # run JUnit test class or method
49
+ jdt test --project <name> [--package <pkg>] # run tests in project/package
50
+ ```
51
+
52
+ All commands auto-refresh from disk. `build` is the only command that triggers explicit builds.
53
+
54
+ ### Diagnostics
55
+
56
+ ```bash
57
+ jdt errors [--project <name>] [--file <path>] # (alias: err) compilation errors
58
+ jdt errors --warnings --all # include warnings and all marker types
59
+ ```
60
+
61
+ File paths are workspace-relative: `my-app/src/main/java/.../Foo.java`.
62
+
63
+ ### Refactoring
64
+
65
+ ```bash
66
+ jdt organize-imports <file> # (alias: oi) organize imports
67
+ jdt format <file> # (alias: fmt) format code (Eclipse settings)
68
+ jdt rename <FQN> <newName> # rename type
69
+ jdt rename <FQN> <newName> --method <old> # rename method
70
+ jdt rename <FQN> <newName> --field <old> # rename field
71
+ jdt move <FQN> <target.package> # move type to another package
72
+ ```
73
+
74
+ ### Editor
75
+
76
+ ```bash
77
+ jdt active-editor # (alias: ae) current file and cursor line
78
+ jdt open <FQN> [method] [--arity N] # open in Eclipse editor
79
+ ```
80
+
81
+ ## Instance discovery
82
+
83
+ The CLI reads `~/.jdtbridge/instances/*.json` to find running Eclipse instances. Each file contains port, auth token, PID, and workspace path. Stale instances are filtered by PID liveness.
84
+
85
+ When multiple instances are running, use `--workspace <hint>` or the CLI picks the first live one.
86
+
87
+ Override the home directory with `JDTBRIDGE_HOME` environment variable.
88
+
89
+ ## Color output
90
+
91
+ Auto-detected from TTY. Override:
92
+
93
+ - `--color` / `--no-color` flags
94
+ - `FORCE_COLOR=1` / `NO_COLOR=1` env
95
+ - `JDTBRIDGE_COLOR=1` env
96
+
97
+ ## Development
98
+
99
+ ```bash
100
+ npm test # run tests
101
+ npm run test:watch # watch mode
102
+ ```
package/bin/jdt.mjs ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import { run } from "../src/cli.mjs";
3
+ run(process.argv.slice(2));
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@kaluchi/jdtbridge",
3
+ "version": "1.1.0",
4
+ "description": "CLI for Eclipse JDT Bridge — semantic Java analysis via Eclipse JDT SearchEngine",
5
+ "type": "module",
6
+ "bin": {
7
+ "jdt": "./bin/jdt.mjs",
8
+ "jdtbridge": "./bin/jdt.mjs"
9
+ },
10
+ "files": [
11
+ "bin/",
12
+ "src/"
13
+ ],
14
+ "scripts": {
15
+ "test": "vitest run",
16
+ "test:watch": "vitest"
17
+ },
18
+ "engines": {
19
+ "node": ">=20"
20
+ },
21
+ "keywords": [
22
+ "eclipse",
23
+ "jdt",
24
+ "java",
25
+ "refactoring",
26
+ "search"
27
+ ],
28
+ "license": "Apache-2.0",
29
+ "author": "kaluchi",
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "https://github.com/kaluchi/jdtbridge.git",
33
+ "directory": "cli"
34
+ },
35
+ "homepage": "https://github.com/kaluchi/jdtbridge/tree/master/cli",
36
+ "bugs": "https://github.com/kaluchi/jdtbridge/issues",
37
+ "devDependencies": {
38
+ "@vitest/coverage-v8": "^3.2.4",
39
+ "vitest": "^3.0.0"
40
+ },
41
+ "dependencies": {
42
+ "picocolors": "^1.1.0"
43
+ }
44
+ }
package/src/args.mjs ADDED
@@ -0,0 +1,37 @@
1
+ // CLI argument parsing utilities.
2
+
3
+ /**
4
+ * Parse --flag and --key value pairs from args array.
5
+ * Boolean flags (standalone --flag) get value `true`.
6
+ * Key-value pairs (--key value) get the string value.
7
+ */
8
+ export function parseFlags(args) {
9
+ const flags = {};
10
+ for (let i = 0; i < args.length; i++) {
11
+ if (args[i].startsWith("--")) {
12
+ const key = args[i].slice(2);
13
+ if (i + 1 < args.length && !args[i + 1].startsWith("--")) {
14
+ flags[key] = args[++i];
15
+ } else {
16
+ flags[key] = true;
17
+ }
18
+ }
19
+ }
20
+ return flags;
21
+ }
22
+
23
+ /**
24
+ * Extract positional arguments (non-flag values) from args array.
25
+ * Skips --flag and --key value pairs.
26
+ */
27
+ export function extractPositional(args) {
28
+ const result = [];
29
+ for (let i = 0; i < args.length; i++) {
30
+ if (args[i].startsWith("--")) {
31
+ if (i + 1 < args.length && !args[i + 1].startsWith("--")) i++;
32
+ } else {
33
+ result.push(args[i]);
34
+ }
35
+ }
36
+ return result;
37
+ }
package/src/cli.mjs ADDED
@@ -0,0 +1,174 @@
1
+ // Main CLI dispatcher.
2
+ // Maps command names to handler functions and provides help.
3
+
4
+ import { projects, help as projectsHelp } from "./commands/projects.mjs";
5
+ import { projectInfo, help as projectInfoHelp } from "./commands/project-info.mjs";
6
+ import { find, help as findHelp } from "./commands/find.mjs";
7
+ import { references, help as referencesHelp } from "./commands/references.mjs";
8
+ import { subtypes, help as subtypesHelp } from "./commands/subtypes.mjs";
9
+ import { hierarchy, help as hierarchyHelp } from "./commands/hierarchy.mjs";
10
+ import { implementors, help as implementorsHelp } from "./commands/implementors.mjs";
11
+ import { typeInfo, help as typeInfoHelp } from "./commands/type-info.mjs";
12
+ import { source, help as sourceHelp } from "./commands/source.mjs";
13
+ import { build, help as buildHelp } from "./commands/build.mjs";
14
+ import { test, help as testHelp } from "./commands/test.mjs";
15
+ import { errors, help as errorsHelp } from "./commands/errors.mjs";
16
+ import {
17
+ organizeImports,
18
+ format,
19
+ rename,
20
+ move,
21
+ organizeImportsHelp,
22
+ formatHelp,
23
+ renameHelp,
24
+ moveHelp,
25
+ } from "./commands/refactoring.mjs";
26
+ import {
27
+ activeEditor,
28
+ open,
29
+ activeEditorHelp,
30
+ openHelp,
31
+ } from "./commands/editor.mjs";
32
+ import { setup, help as setupHelp } from "./commands/setup.mjs";
33
+ import { isConnectionError } from "./client.mjs";
34
+ import { bold, red, dim } from "./color.mjs";
35
+
36
+ const commands = {
37
+ projects: { fn: projects, help: projectsHelp },
38
+ "project-info": { fn: projectInfo, help: projectInfoHelp },
39
+ find: { fn: find, help: findHelp },
40
+ references: { fn: references, help: referencesHelp },
41
+ subtypes: { fn: subtypes, help: subtypesHelp },
42
+ hierarchy: { fn: hierarchy, help: hierarchyHelp },
43
+ implementors: { fn: implementors, help: implementorsHelp },
44
+ "type-info": { fn: typeInfo, help: typeInfoHelp },
45
+ source: { fn: source, help: sourceHelp },
46
+ build: { fn: build, help: buildHelp },
47
+ test: { fn: test, help: testHelp },
48
+ errors: { fn: errors, help: errorsHelp },
49
+ "organize-imports": { fn: organizeImports, help: organizeImportsHelp },
50
+ format: { fn: format, help: formatHelp },
51
+ rename: { fn: rename, help: renameHelp },
52
+ move: { fn: move, help: moveHelp },
53
+ "active-editor": { fn: activeEditor, help: activeEditorHelp },
54
+ open: { fn: open, help: openHelp },
55
+ setup: { fn: setup, help: setupHelp },
56
+ };
57
+
58
+ /** Short aliases for frequently used commands. */
59
+ const aliases = {
60
+ refs: "references",
61
+ impl: "implementors",
62
+ subt: "subtypes",
63
+ hier: "hierarchy",
64
+ pi: "project-info",
65
+ ti: "type-info",
66
+ oi: "organize-imports",
67
+ ae: "active-editor",
68
+ src: "source",
69
+ b: "build",
70
+ err: "errors",
71
+ fmt: "format",
72
+ };
73
+
74
+ // Reverse map: command name → list of its aliases (for display).
75
+ const aliasesOf = {};
76
+ for (const [short, full] of Object.entries(aliases)) {
77
+ (aliasesOf[full] ||= []).push(short);
78
+ }
79
+
80
+ /** Resolve a command name or alias to its full name. */
81
+ function resolve(name) {
82
+ if (commands[name]) return name;
83
+ return aliases[name] || null;
84
+ }
85
+
86
+ function fmtAliases(name) {
87
+ const list = aliasesOf[name];
88
+ return list ? " " + dim("(" + list.join(", ") + ")") : "";
89
+ }
90
+
91
+ function printOverview() {
92
+ console.log(`Eclipse JDT Bridge — semantic Java analysis via Eclipse JDT SearchEngine.
93
+ Requires: Eclipse running with the jdtbridge plugin.
94
+
95
+ Search & navigation:
96
+ projects list workspace projects
97
+ project-info${fmtAliases("project-info")} <name> [--lines N] project overview (adaptive detail)
98
+ find <Name|*Pattern*> [--source-only] find type declarations
99
+ references${fmtAliases("references")} <FQN> [method] [--field <name>] references to type/method/field
100
+ subtypes${fmtAliases("subtypes")} <FQN> all subtypes/implementors
101
+ hierarchy${fmtAliases("hierarchy")} <FQN> full hierarchy (supers + interfaces + subtypes)
102
+ implementors${fmtAliases("implementors")} <FQN> <method> [--arity n] implementations of interface method
103
+ type-info${fmtAliases("type-info")} <FQN> class overview (fields, methods, line numbers)
104
+ source${fmtAliases("source")} <FQN> [method] [--arity n] type or method source code (project and libraries)
105
+
106
+ Testing & building:
107
+ build${fmtAliases("build")} [--project <name>] [--clean] build project (incremental or clean)
108
+ test <FQN> [method] run JUnit test class or method
109
+ test --project <name> [--package <pkg>] run tests in project/package
110
+
111
+ Diagnostics:
112
+ errors${fmtAliases("errors")} [--file <path>] [--project <name>] compilation errors
113
+
114
+ Refactoring:
115
+ organize-imports${fmtAliases("organize-imports")} <file> organize imports
116
+ format${fmtAliases("format")} <file> format with Eclipse project settings
117
+ rename <FQN> <newName> [--method|--field] rename type/method/field
118
+ move <FQN> <target.package> move type to another package
119
+
120
+ Editor:
121
+ active-editor${fmtAliases("active-editor")} current file and cursor line
122
+ open <FQN> [method] open in Eclipse editor
123
+
124
+ Setup:
125
+ setup [--check|--remove] install/check/remove Eclipse plugin
126
+
127
+ Use "jdt help <command>" for detailed usage of any command.`);
128
+ }
129
+
130
+ export async function run(argv) {
131
+ const [command, ...rest] = argv;
132
+
133
+ if (!command || command === "--help") {
134
+ printOverview();
135
+ return;
136
+ }
137
+
138
+ if (command === "help") {
139
+ const topic = rest[0];
140
+ const resolved = topic ? resolve(topic) : null;
141
+ if (resolved) {
142
+ console.log(commands[resolved].help);
143
+ } else if (topic) {
144
+ console.error(`Unknown command: ${topic}`);
145
+ console.log();
146
+ printOverview();
147
+ } else {
148
+ printOverview();
149
+ }
150
+ return;
151
+ }
152
+
153
+ const resolved = resolve(command);
154
+ if (!resolved) {
155
+ console.error(`Unknown command: ${command}`);
156
+ console.log();
157
+ printOverview();
158
+ process.exit(1);
159
+ }
160
+
161
+ try {
162
+ await commands[resolved].fn(rest);
163
+ } catch (e) {
164
+ if (isConnectionError(e)) {
165
+ console.error(
166
+ bold(red("Eclipse JDT Bridge not responding.")) +
167
+ "\nCheck that Eclipse is running with the jdtbridge plugin.\n",
168
+ );
169
+ } else {
170
+ console.error(e.message);
171
+ }
172
+ process.exit(1);
173
+ }
174
+ }
package/src/client.mjs ADDED
@@ -0,0 +1,168 @@
1
+ // HTTP client for JDT Bridge server.
2
+
3
+ import { request } from "node:http";
4
+ import { findInstance } from "./discovery.mjs";
5
+ import { red, bold } from "./color.mjs";
6
+
7
+ /** @type {import('./discovery.mjs').Instance|null} */
8
+ let _instance;
9
+
10
+ /**
11
+ * Ensure we have a connected instance. Call before any HTTP request.
12
+ * @param {string} [workspaceHint]
13
+ * @returns {import('./discovery.mjs').Instance}
14
+ */
15
+ export function connect(workspaceHint) {
16
+ if (_instance) return _instance;
17
+ _instance = findInstance(workspaceHint);
18
+ if (!_instance) {
19
+ console.error(
20
+ bold(red("Eclipse JDT Bridge not running.")) +
21
+ "\n\nNo live instances found. Check that:" +
22
+ "\n 1. Eclipse is running" +
23
+ "\n 2. The jdtbridge plugin is installed (io.github.kaluchi.jdtbridge)" +
24
+ "\n 3. Instance files exist in ~/.jdtbridge/instances/",
25
+ );
26
+ process.exit(1);
27
+ }
28
+ return _instance;
29
+ }
30
+
31
+ /** Reset cached instance (for testing). */
32
+ export function resetClient() {
33
+ _instance = null;
34
+ }
35
+
36
+ function authHeaders() {
37
+ const inst = _instance;
38
+ return inst && inst.token
39
+ ? { Authorization: `Bearer ${inst.token}` }
40
+ : {};
41
+ }
42
+
43
+ /**
44
+ * Parse JSON responses, tolerating non-finite numeric literals sometimes
45
+ * returned by the Eclipse bridge (for example `time: NaN` in test results).
46
+ * @param {string} data
47
+ * @returns {any}
48
+ */
49
+ function parseJson(data) {
50
+ try {
51
+ return JSON.parse(data);
52
+ } catch {
53
+ const sanitized = data
54
+ .replace(/:\s*NaN\b/g, ": null")
55
+ .replace(/:\s*Infinity\b/g, ": null")
56
+ .replace(/:\s*-Infinity\b/g, ": null");
57
+ if (sanitized !== data) {
58
+ return JSON.parse(sanitized);
59
+ }
60
+ throw new Error("Invalid JSON: " + data);
61
+ }
62
+ }
63
+
64
+ /**
65
+ * HTTP GET request, returns parsed JSON.
66
+ * @param {string} path - URL path with query string
67
+ * @param {number} [timeoutMs=10000]
68
+ * @returns {Promise<any>}
69
+ */
70
+ export function get(path, timeoutMs = 10_000) {
71
+ const inst = connect();
72
+ return new Promise((resolve, reject) => {
73
+ const req = request(
74
+ {
75
+ hostname: "127.0.0.1",
76
+ port: inst.port,
77
+ path,
78
+ method: "GET",
79
+ timeout: timeoutMs,
80
+ headers: authHeaders(),
81
+ },
82
+ (res) => {
83
+ let data = "";
84
+ res.on("data", (chunk) => (data += chunk));
85
+ res.on("end", () => {
86
+ if (res.statusCode !== 200) {
87
+ reject(new Error(`HTTP ${res.statusCode}: ${data}`));
88
+ return;
89
+ }
90
+ try {
91
+ resolve(parseJson(data));
92
+ } catch (e) {
93
+ reject(e);
94
+ }
95
+ });
96
+ },
97
+ );
98
+ req.on("timeout", () => {
99
+ req.destroy();
100
+ reject(new Error("Request timed out"));
101
+ });
102
+ req.on("error", reject);
103
+ req.end();
104
+ });
105
+ }
106
+
107
+ /**
108
+ * HTTP GET request, returns raw response with headers.
109
+ * Used for /source which returns text/plain.
110
+ * @param {string} path
111
+ * @param {number} [timeoutMs=10000]
112
+ * @returns {Promise<{headers: object, body: string}>}
113
+ */
114
+ export function getRaw(path, timeoutMs = 10_000) {
115
+ const inst = connect();
116
+ return new Promise((resolve, reject) => {
117
+ const req = request(
118
+ {
119
+ hostname: "127.0.0.1",
120
+ port: inst.port,
121
+ path,
122
+ method: "GET",
123
+ timeout: timeoutMs,
124
+ headers: authHeaders(),
125
+ },
126
+ (res) => {
127
+ let data = "";
128
+ res.on("data", (chunk) => (data += chunk));
129
+ res.on("end", () => {
130
+ if (res.statusCode !== 200) {
131
+ reject(new Error(`HTTP ${res.statusCode}: ${data}`));
132
+ return;
133
+ }
134
+ const contentType = res.headers["content-type"] || "";
135
+ if (contentType.startsWith("application/json")) {
136
+ try {
137
+ const json = parseJson(data);
138
+ if (json.error) {
139
+ reject(new Error(json.error));
140
+ } else {
141
+ resolve({ headers: res.headers, body: data });
142
+ }
143
+ } catch (e) {
144
+ reject(e);
145
+ }
146
+ } else {
147
+ resolve({ headers: res.headers, body: data });
148
+ }
149
+ });
150
+ },
151
+ );
152
+ req.on("timeout", () => {
153
+ req.destroy();
154
+ reject(new Error("Request timed out"));
155
+ });
156
+ req.on("error", reject);
157
+ req.end();
158
+ });
159
+ }
160
+
161
+ /**
162
+ * Check if error is a connection refused error.
163
+ * @param {Error} e
164
+ * @returns {boolean}
165
+ */
166
+ export function isConnectionError(e) {
167
+ return e.code === "ECONNREFUSED" || e.code === "ECONNRESET";
168
+ }
package/src/color.mjs ADDED
@@ -0,0 +1,40 @@
1
+ // Colored output with TTY auto-detection.
2
+ // Enable: --color flag, JDTBRIDGE_COLOR=1, or FORCE_COLOR=1
3
+ // Disable: --no-color flag, NO_COLOR=1
4
+
5
+ import pc from "picocolors";
6
+
7
+ let _enabled;
8
+
9
+ /** Check if color output is enabled. */
10
+ export function isColorEnabled() {
11
+ if (_enabled !== undefined) return _enabled;
12
+
13
+ if (process.env.NO_COLOR || process.argv.includes("--no-color")) {
14
+ _enabled = false;
15
+ } else if (
16
+ process.env.FORCE_COLOR ||
17
+ process.env.JDTBRIDGE_COLOR ||
18
+ process.argv.includes("--color")
19
+ ) {
20
+ _enabled = true;
21
+ } else {
22
+ _enabled = process.stdout.isTTY === true;
23
+ }
24
+ return _enabled;
25
+ }
26
+
27
+ /** Set color enabled/disabled explicitly. */
28
+ export function setColorEnabled(enabled) {
29
+ _enabled = enabled;
30
+ }
31
+
32
+ function wrap(fn) {
33
+ return (s) => (isColorEnabled() ? fn(s) : s);
34
+ }
35
+
36
+ export const red = wrap(pc.red);
37
+ export const green = wrap(pc.green);
38
+ export const yellow = wrap(pc.yellow);
39
+ export const bold = wrap(pc.bold);
40
+ export const dim = wrap(pc.dim);
@@ -0,0 +1,40 @@
1
+ import { get } from "../client.mjs";
2
+ import { parseFlags } from "../args.mjs";
3
+
4
+ export async function build(args) {
5
+ const flags = parseFlags(args);
6
+ const params = [];
7
+ if (flags.project) params.push(`project=${encodeURIComponent(flags.project)}`);
8
+ if (flags.clean) params.push("clean");
9
+
10
+ let url = "/build";
11
+ if (params.length > 0) url += "?" + params.join("&");
12
+ const result = await get(url, 180_000);
13
+ if (result.error) {
14
+ console.error(result.error);
15
+ process.exit(1);
16
+ }
17
+ const n = result.errors || 0;
18
+ if (n === 0) {
19
+ console.log("Build complete (0 errors)");
20
+ } else {
21
+ console.log(`Build complete (${n} errors)`);
22
+ process.exit(1);
23
+ }
24
+ }
25
+
26
+ export const help = `Build a project via Eclipse incremental or clean builder.
27
+
28
+ Usage: jdt build [--project <name>] [--clean]
29
+
30
+ Options:
31
+ --project <name> project to build (omit for workspace-wide incremental)
32
+ --clean clean + full rebuild (requires --project)
33
+
34
+ Always refreshes from disk before building.
35
+ Exit code: 0 if no compilation errors, 1 if errors found.
36
+
37
+ Examples:
38
+ jdt build --project m8-client
39
+ jdt build --project m8-client --clean
40
+ jdt build --project m8-client --clean && jdt test --project m8-client-gwt`;
@@ -0,0 +1,49 @@
1
+ import { get } from "../client.mjs";
2
+ import { extractPositional, parseFlags } from "../args.mjs";
3
+ import { stripProject } from "../paths.mjs";
4
+
5
+ export async function activeEditor() {
6
+ const result = await get("/active-editor");
7
+ if (result.error) {
8
+ console.error(result.error);
9
+ process.exit(1);
10
+ }
11
+ if (result.file === null) {
12
+ console.log("(no file open)");
13
+ } else {
14
+ console.log(`${stripProject(result.file)}:${result.line}`);
15
+ }
16
+ }
17
+
18
+ export async function open(args) {
19
+ const pos = extractPositional(args);
20
+ const flags = parseFlags(args);
21
+ const fqn = pos[0];
22
+ const method = pos[1];
23
+ if (!fqn) {
24
+ console.error("Usage: open <FQN> [method] [--arity n]");
25
+ process.exit(1);
26
+ }
27
+ let url = `/open?class=${encodeURIComponent(fqn)}`;
28
+ if (method) url += `&method=${encodeURIComponent(method)}`;
29
+ if (flags.arity !== undefined && flags.arity !== true)
30
+ url += `&arity=${flags.arity}`;
31
+ const result = await get(url);
32
+ if (result.error) {
33
+ console.error(result.error);
34
+ process.exit(1);
35
+ }
36
+ console.log("Opened");
37
+ }
38
+
39
+ export const activeEditorHelp = `Show the file and cursor line of the active Eclipse editor.
40
+
41
+ Usage: jdt active-editor`;
42
+
43
+ export const openHelp = `Open a type or method in the Eclipse editor.
44
+
45
+ Usage: jdt open <FQN> [method] [--arity n]
46
+
47
+ Examples:
48
+ jdt open app.m8.dao.StaffDaoImpl
49
+ jdt open app.m8.dao.StaffDaoImpl getStaff`;