@kaluchi/jdtbridge 1.5.0 → 1.6.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/package.json +1 -1
- package/src/args.mjs +13 -1
- package/src/commands/hierarchy.mjs +11 -22
- package/src/commands/source.mjs +54 -20
- package/src/format/hierarchy.mjs +47 -0
package/package.json
CHANGED
package/src/args.mjs
CHANGED
|
@@ -103,5 +103,17 @@ function splitParams(str) {
|
|
|
103
103
|
}
|
|
104
104
|
const last = str.substring(start).trim();
|
|
105
105
|
if (last) params.push(last);
|
|
106
|
-
return params;
|
|
106
|
+
return params.map(eraseGenerics);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** Strip generics: Map<String,Integer> → Map, List<String>[] → List[] */
|
|
110
|
+
function eraseGenerics(type) {
|
|
111
|
+
let result = "";
|
|
112
|
+
let depth = 0;
|
|
113
|
+
for (const ch of type) {
|
|
114
|
+
if (ch === "<") depth++;
|
|
115
|
+
else if (ch === ">") depth--;
|
|
116
|
+
else if (depth === 0) result += ch;
|
|
117
|
+
}
|
|
118
|
+
return result;
|
|
107
119
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { get } from "../client.mjs";
|
|
2
2
|
import { extractPositional } from "../args.mjs";
|
|
3
|
-
import {
|
|
4
|
-
import { bold } from "../color.mjs";
|
|
3
|
+
import { formatHierarchy } from "../format/hierarchy.mjs";
|
|
5
4
|
|
|
6
5
|
export async function hierarchy(args) {
|
|
7
6
|
const pos = extractPositional(args);
|
|
@@ -18,26 +17,16 @@ export async function hierarchy(args) {
|
|
|
18
17
|
console.error(result.error);
|
|
19
18
|
process.exit(1);
|
|
20
19
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const loc = s.binary ? "(binary)" : stripProject(s.file);
|
|
32
|
-
console.log(` ${s.fqn} ${loc}`);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
if (result.subtypes.length > 0) {
|
|
36
|
-
console.log(bold("Subtypes:"));
|
|
37
|
-
for (const s of result.subtypes) {
|
|
38
|
-
const loc = s.binary ? "(binary)" : stripProject(s.file);
|
|
39
|
-
console.log(` ${s.fqn} ${loc}`);
|
|
40
|
-
}
|
|
20
|
+
|
|
21
|
+
const lines = [];
|
|
22
|
+
lines.push(`#### ${result.fqn || fqn}`);
|
|
23
|
+
lines.push("");
|
|
24
|
+
lines.push(...formatHierarchy(result));
|
|
25
|
+
|
|
26
|
+
if (lines.length > 2) {
|
|
27
|
+
console.log(lines.join("\n"));
|
|
28
|
+
} else {
|
|
29
|
+
console.log("No hierarchy found.");
|
|
41
30
|
}
|
|
42
31
|
}
|
|
43
32
|
|
package/src/commands/source.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { get } from "../client.mjs";
|
|
2
2
|
import { extractPositional, parseFqmn } from "../args.mjs";
|
|
3
|
+
import { formatHierEntry } from "../format/hierarchy.mjs";
|
|
3
4
|
|
|
4
5
|
export async function source(args) {
|
|
5
6
|
const jsonFlag = args.includes("--json");
|
|
@@ -91,8 +92,8 @@ function formatMemberRef(ref) {
|
|
|
91
92
|
if (ref.inherited) annotations.push("inherited");
|
|
92
93
|
if (annotations.length > 0) line += ` (${annotations.join(", ")})`;
|
|
93
94
|
|
|
94
|
-
// Line number
|
|
95
|
-
|
|
95
|
+
// Line number: server sends it but we don't render for incoming —
|
|
96
|
+
// callers are navigable by FQMN, line numbers just add noise
|
|
96
97
|
|
|
97
98
|
// Javadoc inline after —
|
|
98
99
|
if (ref.doc) line += ` — ${ref.doc}`;
|
|
@@ -126,19 +127,31 @@ function groupByDeclaringType(refs) {
|
|
|
126
127
|
return groups;
|
|
127
128
|
}
|
|
128
129
|
|
|
129
|
-
function formatRefGroup({ typeFqn, group }, implIndex) {
|
|
130
|
+
function formatRefGroup({ typeFqn, group }, implIndex, viewScope) {
|
|
130
131
|
const lines = [];
|
|
131
|
-
|
|
132
|
+
// Type header: only show for standalone type refs (no members).
|
|
133
|
+
// When members exist, the type is already visible in their FQMNs.
|
|
134
|
+
const standalone = group.members.length === 0;
|
|
135
|
+
if (standalone && group.typeRef) {
|
|
132
136
|
lines.push(formatTypeHeader(group.typeRef));
|
|
133
|
-
|
|
134
|
-
const
|
|
135
|
-
|
|
137
|
+
// Show type implementations (domain-scoped)
|
|
138
|
+
const impls = implIndex[group.typeRef.fqmn];
|
|
139
|
+
if (impls && !(viewScope === "project" && group.typeRef.scope === "dependency")) {
|
|
140
|
+
for (const impl of impls) {
|
|
141
|
+
let implLine = ` ${badge(impl)} \`${impl.fqmn}\``;
|
|
142
|
+
if (impl.anonymous && impl.enclosingFqmn) {
|
|
143
|
+
implLine += ` — in \`${impl.enclosingFqmn}\``;
|
|
144
|
+
}
|
|
145
|
+
lines.push(implLine);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
136
148
|
}
|
|
137
149
|
for (const ref of group.members) {
|
|
138
150
|
lines.push(formatMemberRef(ref));
|
|
139
|
-
// Show implementations
|
|
151
|
+
// Show implementations — skip dependency interface impls
|
|
152
|
+
// when viewing project source (domain scoping)
|
|
140
153
|
const impls = implIndex[ref.fqmn];
|
|
141
|
-
if (impls) {
|
|
154
|
+
if (impls && !(viewScope === "project" && ref.scope === "dependency")) {
|
|
142
155
|
for (const impl of impls) {
|
|
143
156
|
lines.push(` → ${badge(impl)} \`${impl.fqmn}\``);
|
|
144
157
|
}
|
|
@@ -159,21 +172,20 @@ function buildImplIndex(refs) {
|
|
|
159
172
|
return index;
|
|
160
173
|
}
|
|
161
174
|
|
|
175
|
+
|
|
162
176
|
// ---- Hierarchy (type-level) ----
|
|
163
177
|
|
|
164
|
-
function
|
|
178
|
+
function formatHierarchySection(lines, result) {
|
|
165
179
|
const supers = result.supertypes || [];
|
|
166
180
|
const subs = result.subtypes || [];
|
|
167
181
|
if (supers.length > 0 || subs.length > 0) {
|
|
168
182
|
lines.push("");
|
|
169
183
|
lines.push("#### Hierarchy:");
|
|
170
184
|
for (const s of supers) {
|
|
171
|
-
|
|
172
|
-
lines.push(`↑ ${b} \`${s.fqn}\``);
|
|
185
|
+
lines.push(...formatHierEntry("↑", s));
|
|
173
186
|
}
|
|
174
187
|
for (const s of subs) {
|
|
175
|
-
|
|
176
|
-
lines.push(`↓ ${b} \`${s.fqn}\``);
|
|
188
|
+
lines.push(...formatHierEntry("", s));
|
|
177
189
|
}
|
|
178
190
|
}
|
|
179
191
|
if (result.enclosingType) {
|
|
@@ -182,7 +194,7 @@ function formatHierarchy(lines, result) {
|
|
|
182
194
|
const et = result.enclosingType;
|
|
183
195
|
const fqn = typeof et === "string" ? et : et.fqn;
|
|
184
196
|
const kind = typeof et === "string" ? "class" : (et.kind || "class");
|
|
185
|
-
lines.push(
|
|
197
|
+
lines.push(...formatHierEntry("", { fqn, kind, ...et }));
|
|
186
198
|
}
|
|
187
199
|
}
|
|
188
200
|
|
|
@@ -212,7 +224,7 @@ function formatMarkdown(result) {
|
|
|
212
224
|
|
|
213
225
|
// Type-level: hierarchy instead of refs
|
|
214
226
|
if (result.supertypes || result.subtypes) {
|
|
215
|
-
|
|
227
|
+
formatHierarchySection(lines, result);
|
|
216
228
|
return lines.join("\n");
|
|
217
229
|
}
|
|
218
230
|
|
|
@@ -220,10 +232,32 @@ function formatMarkdown(result) {
|
|
|
220
232
|
return lines.join("\n");
|
|
221
233
|
}
|
|
222
234
|
|
|
223
|
-
//
|
|
224
|
-
const
|
|
235
|
+
// Self-reference: the viewed member's declaring type
|
|
236
|
+
const selfFqn = result.fqmn.includes("#")
|
|
237
|
+
? result.fqmn.split("#")[0] : null;
|
|
238
|
+
|
|
239
|
+
// Split by direction, filter self-reference type refs
|
|
240
|
+
const outgoing = result.refs.filter((r) =>
|
|
241
|
+
r.direction !== "incoming"
|
|
242
|
+
&& !(r.kind === "type" && r.fqmn === selfFqn));
|
|
225
243
|
const incoming = result.refs.filter((r) => r.direction === "incoming");
|
|
226
244
|
|
|
245
|
+
const viewScope = result.viewScope;
|
|
246
|
+
|
|
247
|
+
// Implementations section (interface/abstract methods)
|
|
248
|
+
const impls = result.implementations || [];
|
|
249
|
+
if (impls.length > 0) {
|
|
250
|
+
lines.push("");
|
|
251
|
+
lines.push("#### Implementations:");
|
|
252
|
+
for (const impl of impls) {
|
|
253
|
+
let line = `[M] \`${impl.fqmn}\``;
|
|
254
|
+
if (impl.anonymous && impl.enclosingFqmn) {
|
|
255
|
+
line += ` — in \`${impl.enclosingFqmn}\``;
|
|
256
|
+
}
|
|
257
|
+
lines.push(line);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
227
261
|
if (outgoing.length > 0) {
|
|
228
262
|
const implIndex = buildImplIndex(outgoing);
|
|
229
263
|
const mainRefs = outgoing.filter((r) => !r.implementationOf);
|
|
@@ -231,7 +265,7 @@ function formatMarkdown(result) {
|
|
|
231
265
|
lines.push("#### Outgoing Calls:");
|
|
232
266
|
const groups = groupByDeclaringType(mainRefs);
|
|
233
267
|
for (const g of groups) {
|
|
234
|
-
lines.push(formatRefGroup(g, implIndex));
|
|
268
|
+
lines.push(formatRefGroup(g, implIndex, viewScope));
|
|
235
269
|
}
|
|
236
270
|
}
|
|
237
271
|
|
|
@@ -242,7 +276,7 @@ function formatMarkdown(result) {
|
|
|
242
276
|
lines.push("#### Incoming Calls:");
|
|
243
277
|
const groups = groupByDeclaringType(mainRefs);
|
|
244
278
|
for (const g of groups) {
|
|
245
|
-
lines.push(formatRefGroup(g, implIndex));
|
|
279
|
+
lines.push(formatRefGroup(g, implIndex, viewScope));
|
|
246
280
|
}
|
|
247
281
|
}
|
|
248
282
|
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
const TYPE_KIND_BADGE = {
|
|
2
|
+
class: "[C]",
|
|
3
|
+
interface: "[I]",
|
|
4
|
+
enum: "[E]",
|
|
5
|
+
annotation: "[A]",
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export function formatHierEntry(arrow, s) {
|
|
9
|
+
const depth = s.depth || 0;
|
|
10
|
+
const indent = " ".repeat(depth);
|
|
11
|
+
const b = TYPE_KIND_BADGE[s.kind] || "[C]";
|
|
12
|
+
const prefix = arrow ? `${arrow} ` : "";
|
|
13
|
+
let line = `${indent}- ${prefix}${b} \`${s.fqn}\``;
|
|
14
|
+
if (s.anonymous && s.enclosingFqmn) {
|
|
15
|
+
line += ` — in \`${s.enclosingFqmn}\``;
|
|
16
|
+
}
|
|
17
|
+
const lines = [line];
|
|
18
|
+
if (s.file) {
|
|
19
|
+
let loc = s.file;
|
|
20
|
+
if (s.line) {
|
|
21
|
+
loc += `:${s.line}`;
|
|
22
|
+
if (s.endLine && s.endLine !== s.line) loc += `-${s.endLine}`;
|
|
23
|
+
}
|
|
24
|
+
lines.push(`${indent} \`${loc}\``);
|
|
25
|
+
}
|
|
26
|
+
return lines;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function formatHierarchy(result) {
|
|
30
|
+
const lines = [];
|
|
31
|
+
const supers = result.supertypes || [];
|
|
32
|
+
const subs = result.subtypes || [];
|
|
33
|
+
if (supers.length > 0) {
|
|
34
|
+
lines.push("#### Supertypes:");
|
|
35
|
+
for (const s of supers) {
|
|
36
|
+
lines.push(...formatHierEntry("↑", s));
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (subs.length > 0) {
|
|
40
|
+
if (lines.length > 0) lines.push("");
|
|
41
|
+
lines.push("#### Subtypes:");
|
|
42
|
+
for (const s of subs) {
|
|
43
|
+
lines.push(...formatHierEntry("", s));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return lines;
|
|
47
|
+
}
|