@adhisang/minecraft-modding-mcp 6.1.1 → 6.3.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/CHANGELOG.md +40 -1
- package/README.md +12 -4
- package/dist/cache-registry.d.ts +1 -1
- package/dist/cache-registry.js +3 -0
- package/dist/entry-tools/analyze-mod-service.d.ts +12 -6
- package/dist/entry-tools/analyze-mod-service.js +37 -3
- package/dist/entry-tools/analyze-symbol-service.d.ts +6 -4
- package/dist/entry-tools/analyze-symbol-service.js +37 -2
- package/dist/entry-tools/inspect-minecraft/internal.d.ts +7 -3
- package/dist/entry-tools/inspect-minecraft/internal.js +43 -15
- package/dist/entry-tools/inspect-minecraft-service.d.ts +12 -12
- package/dist/entry-tools/inspect-minecraft-service.js +1 -1
- package/dist/entry-tools/manage-cache-service.d.ts +4 -4
- package/dist/error-mapping.d.ts +13 -0
- package/dist/error-mapping.js +35 -2
- package/dist/errors.d.ts +2 -0
- package/dist/errors.js +2 -0
- package/dist/index.js +39 -20
- package/dist/mapping/internal-types.d.ts +7 -0
- package/dist/mapping/types.d.ts +18 -0
- package/dist/mapping-service.js +16 -3
- package/dist/minecraft-explorer-service.d.ts +4 -0
- package/dist/minecraft-explorer-service.js +156 -17
- package/dist/mod-analyzer.d.ts +7 -0
- package/dist/mod-analyzer.js +28 -7
- package/dist/source/artifact-resolver.d.ts +2 -0
- package/dist/source/artifact-resolver.js +24 -1
- package/dist/source/class-source/members-builder.d.ts +4 -0
- package/dist/source/class-source/members-builder.js +3 -1
- package/dist/source/class-source.d.ts +3 -1
- package/dist/source/class-source.js +192 -19
- package/dist/source/did-you-mean.d.ts +14 -0
- package/dist/source/did-you-mean.js +79 -0
- package/dist/source/file-access.js +159 -3
- package/dist/source/indexer.js +72 -2
- package/dist/source/lifecycle/runtime-check.js +9 -5
- package/dist/source/nested-jars.d.ts +78 -0
- package/dist/source/nested-jars.js +267 -0
- package/dist/source/workspace-target.js +5 -2
- package/dist/source-jar-reader.d.ts +16 -0
- package/dist/source-jar-reader.js +82 -0
- package/dist/source-service.d.ts +37 -0
- package/dist/source-service.js +52 -6
- package/dist/stage-emitter.js +24 -8
- package/dist/stdio-supervisor.d.ts +92 -9
- package/dist/stdio-supervisor.js +915 -103
- package/dist/tool-contract-manifest.js +2 -2
- package/dist/tool-guidance.js +115 -7
- package/dist/tool-schemas.d.ts +1343 -149
- package/dist/tool-schemas.js +39 -7
- package/dist/types.d.ts +23 -0
- package/dist/workspace-mapping-service.d.ts +1 -0
- package/dist/workspace-mapping-service.js +120 -8
- package/docs/README-ja.md +4 -0
- package/docs/tool-reference.md +92 -6
- package/package.json +5 -5
|
@@ -3,6 +3,7 @@ import { loadConfig } from "./config.js";
|
|
|
3
3
|
import { artifactSignatureFromFile, normalizeJarPath } from "./path-resolver.js";
|
|
4
4
|
import { createJarEntryReader } from "./source-jar-reader.js";
|
|
5
5
|
import { matchesMemberPattern } from "./source/member-pattern.js";
|
|
6
|
+
import { isUnobfuscatedVersion } from "./version-service.js";
|
|
6
7
|
const CLASSFILE_MAGIC = 0xcafebabe;
|
|
7
8
|
const MAX_INHERITANCE_DEPTH = 64;
|
|
8
9
|
const ACC_PUBLIC = 0x0001;
|
|
@@ -173,6 +174,21 @@ function toInternalName(fqn) {
|
|
|
173
174
|
function extractVersionFromPath(inputPath) {
|
|
174
175
|
return inputPath.match(/(\d+\.\d+(?:\.\d+)?)/)?.[1];
|
|
175
176
|
}
|
|
177
|
+
// Super classes/interfaces from these packages are never inside a Minecraft
|
|
178
|
+
// jar, so failing to resolve them during inherited-member expansion is
|
|
179
|
+
// expected, not a signal. Suppression is allowlist-only and per-prefix
|
|
180
|
+
// verified: JDK packages by definition, com.mojang.serialization because the
|
|
181
|
+
// DataFixerUpper serialization library ships as its own dependency jar
|
|
182
|
+
// (checked against 26.x client-only/common and 1.21.10 client jars). A broad
|
|
183
|
+
// com.mojang.* entry would be wrong — com.mojang.blaze3d.* IS client-jar
|
|
184
|
+
// content and its resolution failures must stay visible.
|
|
185
|
+
const KNOWN_ABSENT_PLATFORM_PREFIXES = [
|
|
186
|
+
"java/",
|
|
187
|
+
"javax/",
|
|
188
|
+
"jdk/",
|
|
189
|
+
"sun/",
|
|
190
|
+
"com/mojang/serialization/"
|
|
191
|
+
];
|
|
176
192
|
class SignatureCacheStore {
|
|
177
193
|
maxEntries;
|
|
178
194
|
nodes = new Map();
|
|
@@ -305,16 +321,111 @@ function readOptionalClassName(cp, index) {
|
|
|
305
321
|
}
|
|
306
322
|
return readClassName(cp, index);
|
|
307
323
|
}
|
|
324
|
+
function descriptorToClassName(descriptor) {
|
|
325
|
+
if (descriptor.startsWith("L") && descriptor.endsWith(";")) {
|
|
326
|
+
return descriptor.slice(1, -1).replace(/\//g, ".");
|
|
327
|
+
}
|
|
328
|
+
return descriptor;
|
|
329
|
+
}
|
|
330
|
+
function readNumericConstant(cp, index) {
|
|
331
|
+
const entry = cp[index];
|
|
332
|
+
if (entry && (entry.tag === 3 || entry.tag === 4 || entry.tag === 5 || entry.tag === 6)) {
|
|
333
|
+
return String(entry.numericValue);
|
|
334
|
+
}
|
|
335
|
+
return "<unknown-constant>";
|
|
336
|
+
}
|
|
337
|
+
// JVMS 4.7.16.1 element_value, rendered as compact Java-ish text. Every
|
|
338
|
+
// branch reads exactly its encoded bytes so nested/array values stay aligned.
|
|
339
|
+
function readElementValue(reader, cp) {
|
|
340
|
+
const tag = String.fromCharCode(reader.readU1());
|
|
341
|
+
switch (tag) {
|
|
342
|
+
case "B":
|
|
343
|
+
case "I":
|
|
344
|
+
case "S":
|
|
345
|
+
case "D":
|
|
346
|
+
case "F":
|
|
347
|
+
case "J":
|
|
348
|
+
return readNumericConstant(cp, reader.readU2());
|
|
349
|
+
case "C": {
|
|
350
|
+
const raw = readNumericConstant(cp, reader.readU2());
|
|
351
|
+
const code = Number(raw);
|
|
352
|
+
return Number.isFinite(code) ? `'${String.fromCharCode(code)}'` : raw;
|
|
353
|
+
}
|
|
354
|
+
case "Z": {
|
|
355
|
+
const raw = readNumericConstant(cp, reader.readU2());
|
|
356
|
+
return raw === "1" ? "true" : raw === "0" ? "false" : raw;
|
|
357
|
+
}
|
|
358
|
+
case "s":
|
|
359
|
+
return JSON.stringify(readUtf8(cp, reader.readU2()));
|
|
360
|
+
case "e": {
|
|
361
|
+
const typeDescriptor = readUtf8(cp, reader.readU2());
|
|
362
|
+
const constantName = readUtf8(cp, reader.readU2());
|
|
363
|
+
return `${descriptorToClassName(typeDescriptor)}.${constantName}`;
|
|
364
|
+
}
|
|
365
|
+
case "c":
|
|
366
|
+
return `${descriptorToClassName(readUtf8(cp, reader.readU2()))}.class`;
|
|
367
|
+
case "@":
|
|
368
|
+
return readAnnotationText(reader, cp);
|
|
369
|
+
case "[": {
|
|
370
|
+
const count = reader.readU2();
|
|
371
|
+
const parts = [];
|
|
372
|
+
for (let index = 0; index < count; index += 1) {
|
|
373
|
+
parts.push(readElementValue(reader, cp));
|
|
374
|
+
}
|
|
375
|
+
return `{${parts.join(", ")}}`;
|
|
376
|
+
}
|
|
377
|
+
default:
|
|
378
|
+
return "<unsupported-element-value>";
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
function readAnnotationText(reader, cp) {
|
|
382
|
+
const typeDescriptor = readUtf8(cp, reader.readU2());
|
|
383
|
+
const pairCount = reader.readU2();
|
|
384
|
+
const pairs = [];
|
|
385
|
+
for (let index = 0; index < pairCount; index += 1) {
|
|
386
|
+
const name = readUtf8(cp, reader.readU2());
|
|
387
|
+
pairs.push(`${name} = ${readElementValue(reader, cp)}`);
|
|
388
|
+
}
|
|
389
|
+
return `@${descriptorToClassName(typeDescriptor)}${pairs.length > 0 ? `(${pairs.join(", ")})` : ""}`;
|
|
390
|
+
}
|
|
308
391
|
function readAttributes(reader, cp, count) {
|
|
309
392
|
const names = [];
|
|
393
|
+
let annotationDefault;
|
|
394
|
+
let annotations;
|
|
310
395
|
for (let index = 0; index < count; index += 1) {
|
|
311
396
|
const nameIndex = reader.readU2();
|
|
312
397
|
const length = reader.readU4();
|
|
313
398
|
const attributeName = readUtf8(cp, nameIndex);
|
|
314
399
|
names.push(attributeName);
|
|
315
|
-
reader.
|
|
400
|
+
const body = reader.readBytes(length);
|
|
401
|
+
// Malformed attribute bodies must never fail the whole class parse; the
|
|
402
|
+
// rendered value is best-effort metadata, not a structural field.
|
|
403
|
+
if (attributeName === "AnnotationDefault") {
|
|
404
|
+
try {
|
|
405
|
+
annotationDefault = readElementValue(new ByteReader(body), cp);
|
|
406
|
+
}
|
|
407
|
+
catch {
|
|
408
|
+
annotationDefault = undefined;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
else if (attributeName === "RuntimeVisibleAnnotations") {
|
|
412
|
+
try {
|
|
413
|
+
const bodyReader = new ByteReader(body);
|
|
414
|
+
const annotationCount = bodyReader.readU2();
|
|
415
|
+
const rendered = [];
|
|
416
|
+
for (let a = 0; a < annotationCount; a += 1) {
|
|
417
|
+
rendered.push(readAnnotationText(bodyReader, cp));
|
|
418
|
+
}
|
|
419
|
+
if (rendered.length > 0) {
|
|
420
|
+
annotations = rendered;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
catch {
|
|
424
|
+
annotations = undefined;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
316
427
|
}
|
|
317
|
-
return names;
|
|
428
|
+
return { names, annotationDefault, annotations };
|
|
318
429
|
}
|
|
319
430
|
function parseClassFile(buffer) {
|
|
320
431
|
const reader = new ByteReader(buffer);
|
|
@@ -336,17 +447,28 @@ function parseClassFile(buffer) {
|
|
|
336
447
|
cp[index] = { tag: 1, value: reader.readBytes(length).toString("utf8") };
|
|
337
448
|
break;
|
|
338
449
|
}
|
|
339
|
-
case 3:
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
450
|
+
case 3: {
|
|
451
|
+
const bytes = reader.readBytes(4);
|
|
452
|
+
cp[index] = { tag, numericValue: bytes.readInt32BE(0) };
|
|
453
|
+
break;
|
|
454
|
+
}
|
|
455
|
+
case 4: {
|
|
456
|
+
const bytes = reader.readBytes(4);
|
|
457
|
+
cp[index] = { tag, numericValue: bytes.readFloatBE(0) };
|
|
343
458
|
break;
|
|
344
|
-
|
|
345
|
-
case
|
|
346
|
-
reader.
|
|
347
|
-
cp[index] = { tag };
|
|
459
|
+
}
|
|
460
|
+
case 5: {
|
|
461
|
+
const bytes = reader.readBytes(8);
|
|
462
|
+
cp[index] = { tag, numericValue: bytes.readBigInt64BE(0).toString() };
|
|
348
463
|
index += 1;
|
|
349
464
|
break;
|
|
465
|
+
}
|
|
466
|
+
case 6: {
|
|
467
|
+
const bytes = reader.readBytes(8);
|
|
468
|
+
cp[index] = { tag, numericValue: bytes.readDoubleBE(0) };
|
|
469
|
+
index += 1;
|
|
470
|
+
break;
|
|
471
|
+
}
|
|
350
472
|
case 7:
|
|
351
473
|
case 8:
|
|
352
474
|
case 16:
|
|
@@ -389,13 +511,17 @@ function parseClassFile(buffer) {
|
|
|
389
511
|
const nameIndex = reader.readU2();
|
|
390
512
|
const descriptorIndex = reader.readU2();
|
|
391
513
|
const attributesCount = reader.readU2();
|
|
392
|
-
const
|
|
514
|
+
const attributeResult = readAttributes(reader, cp, attributesCount);
|
|
393
515
|
members.push({
|
|
394
516
|
name: readUtf8(cp, nameIndex),
|
|
395
517
|
descriptor: readUtf8(cp, descriptorIndex),
|
|
396
518
|
accessFlags,
|
|
397
519
|
isSynthetic: (accessFlags & ACC_SYNTHETIC) !== 0 ||
|
|
398
|
-
|
|
520
|
+
attributeResult.names.some((attributeName) => attributeName === "Synthetic"),
|
|
521
|
+
...(attributeResult.annotationDefault !== undefined
|
|
522
|
+
? { annotationDefault: attributeResult.annotationDefault }
|
|
523
|
+
: {}),
|
|
524
|
+
...(attributeResult.annotations ? { annotations: attributeResult.annotations } : {})
|
|
399
525
|
});
|
|
400
526
|
}
|
|
401
527
|
return members;
|
|
@@ -478,6 +604,9 @@ export class MinecraftExplorerService {
|
|
|
478
604
|
const parsedClassCache = new Map([[parsed.internalName, parsed]]);
|
|
479
605
|
const warnings = [];
|
|
480
606
|
const warnMissingInheritedClass = (internalName, relation) => {
|
|
607
|
+
if (KNOWN_ABSENT_PLATFORM_PREFIXES.some((prefix) => internalName.startsWith(prefix))) {
|
|
608
|
+
return;
|
|
609
|
+
}
|
|
481
610
|
warnings.push(`Could not resolve ${relation} class "${internalName.replace(/\//g, ".")}" while expanding inherited members.`);
|
|
482
611
|
};
|
|
483
612
|
const readParsedClassByInternalName = async (internalName, relation) => {
|
|
@@ -572,7 +701,9 @@ export class MinecraftExplorerService {
|
|
|
572
701
|
javaSignature: `${modifiers ? `${modifiers} ` : ""}${fieldType} ${member.name}`.trim(),
|
|
573
702
|
jvmDescriptor: member.descriptor,
|
|
574
703
|
accessFlags: member.accessFlags,
|
|
575
|
-
isSynthetic: member.isSynthetic
|
|
704
|
+
isSynthetic: member.isSynthetic,
|
|
705
|
+
...(member.annotationDefault !== undefined ? { annotationDefault: member.annotationDefault } : {}),
|
|
706
|
+
...(member.annotations ? { annotations: member.annotations } : {})
|
|
576
707
|
};
|
|
577
708
|
}
|
|
578
709
|
const parsedMethod = parseMethodDescriptor(member.descriptor);
|
|
@@ -585,7 +716,9 @@ export class MinecraftExplorerService {
|
|
|
585
716
|
javaSignature: `${modifiers ? `${modifiers} ` : ""}${ownerSimpleClassName}(${args})`.trim(),
|
|
586
717
|
jvmDescriptor: member.descriptor,
|
|
587
718
|
accessFlags: member.accessFlags,
|
|
588
|
-
isSynthetic: member.isSynthetic
|
|
719
|
+
isSynthetic: member.isSynthetic,
|
|
720
|
+
...(member.annotationDefault !== undefined ? { annotationDefault: member.annotationDefault } : {}),
|
|
721
|
+
...(member.annotations ? { annotations: member.annotations } : {})
|
|
589
722
|
};
|
|
590
723
|
}
|
|
591
724
|
return {
|
|
@@ -594,7 +727,9 @@ export class MinecraftExplorerService {
|
|
|
594
727
|
javaSignature: `${modifiers ? `${modifiers} ` : ""}${parsedMethod.returnType} ${member.name}(${args})`.trim(),
|
|
595
728
|
jvmDescriptor: member.descriptor,
|
|
596
729
|
accessFlags: member.accessFlags,
|
|
597
|
-
isSynthetic: member.isSynthetic
|
|
730
|
+
isSynthetic: member.isSynthetic,
|
|
731
|
+
...(member.annotationDefault !== undefined ? { annotationDefault: member.annotationDefault } : {}),
|
|
732
|
+
...(member.annotations ? { annotations: member.annotations } : {})
|
|
598
733
|
};
|
|
599
734
|
};
|
|
600
735
|
const shouldIncludeMember = (member) => {
|
|
@@ -652,10 +787,14 @@ export class MinecraftExplorerService {
|
|
|
652
787
|
};
|
|
653
788
|
}
|
|
654
789
|
contextForJar(jarPath) {
|
|
790
|
+
const minecraftVersion = extractVersionFromPath(jarPath);
|
|
655
791
|
return {
|
|
656
|
-
minecraftVersion:
|
|
792
|
+
minecraftVersion: minecraftVersion ?? "unknown",
|
|
657
793
|
mappingType: "unknown",
|
|
658
|
-
|
|
794
|
+
// Unobfuscated releases ship mojang names in their bytecode; claiming
|
|
795
|
+
// "obfuscated" for them misled namespace reconciliation downstream.
|
|
796
|
+
// With no derivable version the conservative "obfuscated" stands.
|
|
797
|
+
mappingNamespace: minecraftVersion && isUnobfuscatedVersion(minecraftVersion) ? "mojang" : "obfuscated",
|
|
659
798
|
jarHash: artifactSignatureFromFile(jarPath).sourceArtifactId,
|
|
660
799
|
generatedAt: new Date().toISOString()
|
|
661
800
|
};
|
package/dist/mod-analyzer.d.ts
CHANGED
|
@@ -19,8 +19,15 @@ export interface ModAnalysisResult {
|
|
|
19
19
|
dependencies?: ModDependency[];
|
|
20
20
|
classCount: number;
|
|
21
21
|
classes?: string[];
|
|
22
|
+
/**
|
|
23
|
+
* In-archive paths of bundled Jar-in-Jar nested jars (META-INF/jars scan
|
|
24
|
+
* plus present-and-safe fabric.mod.json "jars" declarations). Absent when
|
|
25
|
+
* the mod bundles none.
|
|
26
|
+
*/
|
|
27
|
+
nestedJars?: string[];
|
|
22
28
|
}
|
|
23
29
|
export interface AnalyzeModOptions {
|
|
24
30
|
includeClasses?: boolean;
|
|
25
31
|
}
|
|
32
|
+
export declare function collectNestedJars(entries: string[], declared: string[] | undefined): string[];
|
|
26
33
|
export declare function analyzeModJar(jarPath: string, options?: AnalyzeModOptions): Promise<ModAnalysisResult>;
|
package/dist/mod-analyzer.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { parse as parseToml } from "smol-toml";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { AppError, ERROR_CODES } from "./errors.js";
|
|
4
|
-
import { normalizeJarPath } from "./path-resolver.js";
|
|
4
|
+
import { isSecureJarEntryPath, normalizeJarPath } from "./path-resolver.js";
|
|
5
5
|
import { listJarEntries, readJarEntryAsUtf8 } from "./source-jar-reader.js";
|
|
6
6
|
function toErrorMessage(value) {
|
|
7
7
|
if (value instanceof Error) {
|
|
@@ -32,7 +32,8 @@ const fabricModJsonSchema = z
|
|
|
32
32
|
depends: z.record(z.union([z.string(), z.array(z.string())])).optional(),
|
|
33
33
|
recommends: z.record(z.union([z.string(), z.array(z.string())])).optional(),
|
|
34
34
|
conflicts: z.record(z.union([z.string(), z.array(z.string())])).optional(),
|
|
35
|
-
suggests: z.record(z.union([z.string(), z.array(z.string())])).optional()
|
|
35
|
+
suggests: z.record(z.union([z.string(), z.array(z.string())])).optional(),
|
|
36
|
+
jars: z.array(z.object({ file: z.string() }).passthrough()).optional()
|
|
36
37
|
})
|
|
37
38
|
.passthrough();
|
|
38
39
|
const quiltModJsonSchema = z
|
|
@@ -120,6 +121,7 @@ function parseFabricMod(content) {
|
|
|
120
121
|
...collectFabricDeps(mod.conflicts, "conflicts"),
|
|
121
122
|
...collectFabricDeps(mod.suggests, "optional")
|
|
122
123
|
];
|
|
124
|
+
const declaredNestedJars = mod.jars?.map((entry) => entry.file);
|
|
123
125
|
return {
|
|
124
126
|
modId: mod.id,
|
|
125
127
|
modName: mod.name,
|
|
@@ -128,9 +130,25 @@ function parseFabricMod(content) {
|
|
|
128
130
|
entrypoints,
|
|
129
131
|
mixinConfigs,
|
|
130
132
|
accessWidener: mod.accessWidener,
|
|
131
|
-
dependencies: dependencies.length > 0 ? dependencies : undefined
|
|
133
|
+
dependencies: dependencies.length > 0 ? dependencies : undefined,
|
|
134
|
+
...(declaredNestedJars && declaredNestedJars.length > 0 ? { declaredNestedJars } : {})
|
|
132
135
|
};
|
|
133
136
|
}
|
|
137
|
+
// Nested-jar inventory: every real `.jar` entry directly under META-INF/jars/
|
|
138
|
+
// plus declared fabric.mod.json "jars" files that actually exist in the
|
|
139
|
+
// archive under a safe (non-escaping) path. Declared-but-absent or escaping
|
|
140
|
+
// paths are dropped — the inventory never names content the archive cannot
|
|
141
|
+
// safely serve.
|
|
142
|
+
export function collectNestedJars(entries, declared) {
|
|
143
|
+
const present = new Set(entries);
|
|
144
|
+
const collected = new Set(entries.filter((entry) => /^META-INF\/jars\/[^/]+\.jar$/.test(entry)));
|
|
145
|
+
for (const file of declared ?? []) {
|
|
146
|
+
if (isSecureJarEntryPath(file) && present.has(file) && file.endsWith(".jar")) {
|
|
147
|
+
collected.add(file);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return [...collected].sort((left, right) => left.localeCompare(right));
|
|
151
|
+
}
|
|
134
152
|
// ---------------------------------------------------------------------------
|
|
135
153
|
// Parser: Quilt
|
|
136
154
|
// ---------------------------------------------------------------------------
|
|
@@ -350,20 +368,23 @@ export async function analyzeModJar(jarPath, options) {
|
|
|
350
368
|
// graceful fallback
|
|
351
369
|
}
|
|
352
370
|
}
|
|
371
|
+
const { declaredNestedJars, ...metadataRest } = metadata;
|
|
372
|
+
const nestedJars = collectNestedJars(entries, declaredNestedJars);
|
|
353
373
|
return {
|
|
354
374
|
loader,
|
|
355
375
|
jarKind,
|
|
356
|
-
...
|
|
357
|
-
...(packagedAccessTransformers.length > 0 ||
|
|
376
|
+
...metadataRest,
|
|
377
|
+
...(packagedAccessTransformers.length > 0 || metadataRest.accessTransformers
|
|
358
378
|
? {
|
|
359
379
|
accessTransformers: [...new Set([
|
|
360
|
-
...(
|
|
380
|
+
...(metadataRest.accessTransformers ?? []),
|
|
361
381
|
...packagedAccessTransformers
|
|
362
382
|
])]
|
|
363
383
|
}
|
|
364
384
|
: {}),
|
|
365
385
|
classCount,
|
|
366
|
-
...(classes !== undefined ? { classes } : {})
|
|
386
|
+
...(classes !== undefined ? { classes } : {}),
|
|
387
|
+
...(nestedJars.length > 0 ? { nestedJars } : {})
|
|
367
388
|
};
|
|
368
389
|
}
|
|
369
390
|
//# sourceMappingURL=mod-analyzer.js.map
|
|
@@ -7,6 +7,8 @@ export type VersionSourceDiscovery = {
|
|
|
7
7
|
candidateArtifacts: string[];
|
|
8
8
|
selectedSourceJarPath?: string;
|
|
9
9
|
selectedHasMinecraftNamespace?: boolean;
|
|
10
|
+
/** The other half of a Loom split-source pair (common/clientOnly), when present. */
|
|
11
|
+
companionSourceJarPaths?: string[];
|
|
10
12
|
};
|
|
11
13
|
type RuntimeJarCandidate = {
|
|
12
14
|
jarPath: string;
|
|
@@ -206,13 +206,32 @@ export async function discoverVersionSourceJar(_svc, input) {
|
|
|
206
206
|
const candidateArtifacts = candidates
|
|
207
207
|
.slice(0, 20)
|
|
208
208
|
.map((candidate) => `${candidate.jarPath}#java=${candidate.javaEntryCount}#net_minecraft=${candidate.hasMinecraftNamespace ? 1 : 0}`);
|
|
209
|
+
// Loom split-source workspaces publish the version as a common/clientOnly
|
|
210
|
+
// PAIR with no merged jar; selecting one loses the other half's classes
|
|
211
|
+
// (e.g. net.minecraft.client.* when common wins). Surface the best-scored
|
|
212
|
+
// jar of the other half so ingestion can index both.
|
|
213
|
+
const selectedHalf = selected ? splitSourceHalf(selected.jarPath) : undefined;
|
|
214
|
+
const companion = selectedHalf
|
|
215
|
+
? candidates.find((candidate) => candidate !== selected &&
|
|
216
|
+
candidate.looksLikeMinecraftArtifact &&
|
|
217
|
+
splitSourceHalf(candidate.jarPath) !== undefined &&
|
|
218
|
+
splitSourceHalf(candidate.jarPath) !== selectedHalf &&
|
|
219
|
+
// Version affinity: a leftover other-half jar from a different
|
|
220
|
+
// version must never be spliced into this version's index.
|
|
221
|
+
hasExactVersionToken(candidate.jarPath, input.version))
|
|
222
|
+
: undefined;
|
|
209
223
|
return {
|
|
210
224
|
searchedPaths,
|
|
211
225
|
candidateArtifacts,
|
|
212
226
|
selectedSourceJarPath: selected?.jarPath,
|
|
213
|
-
selectedHasMinecraftNamespace: selected?.hasMinecraftNamespace
|
|
227
|
+
selectedHasMinecraftNamespace: selected?.hasMinecraftNamespace,
|
|
228
|
+
...(companion ? { companionSourceJarPaths: [companion.jarPath] } : {})
|
|
214
229
|
};
|
|
215
230
|
}
|
|
231
|
+
function splitSourceHalf(jarPath) {
|
|
232
|
+
const match = /minecraft-(common|clientonly)/i.exec(jarPath);
|
|
233
|
+
return match ? match[1].toLowerCase() : undefined;
|
|
234
|
+
}
|
|
216
235
|
export async function probeMinecraftArtifact(svc, input) {
|
|
217
236
|
let value = input.target.value.trim();
|
|
218
237
|
const warnings = [];
|
|
@@ -1171,6 +1190,10 @@ export async function resolveArtifact(svc, input) {
|
|
|
1171
1190
|
if (dependencyProvenance) {
|
|
1172
1191
|
provenance.dependencyResolution = dependencyProvenance;
|
|
1173
1192
|
}
|
|
1193
|
+
if (versionSourceDiscovery?.companionSourceJarPaths?.length &&
|
|
1194
|
+
resolved.sourceJarPath === versionSourceDiscovery.selectedSourceJarPath) {
|
|
1195
|
+
provenance.companionSourceJars = versionSourceDiscovery.companionSourceJarPaths;
|
|
1196
|
+
}
|
|
1174
1197
|
if (dependencyOrigin && dependencyRequestedMapping && dependencyRequestedMapping !== "obfuscated") {
|
|
1175
1198
|
const coord = resolved.coordinate ?? value;
|
|
1176
1199
|
warnings.push(`Dependency artifact ${coord} mapping "${dependencyRequestedMapping}" is not enforced (binary remap is disabled for non-vanilla artifacts); the JAR is returned in its native namespace and mappingApplied is reported as "obfuscated" with qualityFlag "dependency-mapping-unverified". Caller must validate symbol availability.`);
|
|
@@ -50,6 +50,10 @@ export type WireMember = {
|
|
|
50
50
|
ownerFqn?: string;
|
|
51
51
|
/** Present only when true. */
|
|
52
52
|
isSynthetic?: boolean;
|
|
53
|
+
/** Rendered default value of an annotation-type member. */
|
|
54
|
+
annotationDefault?: string;
|
|
55
|
+
/** Runtime-visible annotations; present only under the opt-in projection. */
|
|
56
|
+
annotations?: string[];
|
|
53
57
|
};
|
|
54
58
|
export type WireMembersBlock = {
|
|
55
59
|
/** Hoisted owner when every member shares one owner (the common, non-inherited case). */
|
|
@@ -82,7 +82,9 @@ export function projectMembersForWire(slice, includeInherited, keepFieldDescript
|
|
|
82
82
|
javaSignature: m.javaSignature,
|
|
83
83
|
...(keepDescriptor ? { jvmDescriptor: m.jvmDescriptor } : {}),
|
|
84
84
|
...(hoistOwner ? {} : { ownerFqn: m.ownerFqn }),
|
|
85
|
-
...(m.isSynthetic ? { isSynthetic: true } : {})
|
|
85
|
+
...(m.isSynthetic ? { isSynthetic: true } : {}),
|
|
86
|
+
...(m.annotationDefault !== undefined ? { annotationDefault: m.annotationDefault } : {}),
|
|
87
|
+
...(m.annotations?.length ? { annotations: m.annotations } : {})
|
|
86
88
|
});
|
|
87
89
|
return {
|
|
88
90
|
...(hoistOwner ? { ownerFqn: [...owners][0] } : {}),
|
|
@@ -37,7 +37,7 @@ export declare function buildFallbackProvenance(svc: SourceService, input: {
|
|
|
37
37
|
requestedMapping: SourceMapping;
|
|
38
38
|
mappingApplied: SourceMapping;
|
|
39
39
|
}): ArtifactProvenance;
|
|
40
|
-
export declare function buildClassSourceNotFoundError(
|
|
40
|
+
export declare function buildClassSourceNotFoundError(svc: SourceService, input: {
|
|
41
41
|
className: string;
|
|
42
42
|
lookupClassName: string;
|
|
43
43
|
artifactId: string;
|
|
@@ -51,6 +51,7 @@ export declare function buildClassSourceNotFoundError(_svc: SourceService, input
|
|
|
51
51
|
scope?: ArtifactScope;
|
|
52
52
|
projectPath?: string;
|
|
53
53
|
version?: string;
|
|
54
|
+
nestedJars?: string[];
|
|
54
55
|
}): AppError;
|
|
55
56
|
export declare function buildDecompiledFallback(svc: SourceService, artifactId: string, lookupClassName: string, memberPattern: string | undefined, maxMembers: number): {
|
|
56
57
|
fallback: DecompiledFallback;
|
|
@@ -58,5 +59,6 @@ export declare function buildDecompiledFallback(svc: SourceService, artifactId:
|
|
|
58
59
|
truncated: boolean;
|
|
59
60
|
} | undefined;
|
|
60
61
|
export declare function findClass(svc: SourceService, input: FindClassInput): FindClassOutput;
|
|
62
|
+
export declare function findClassIncludingNested(svc: SourceService, input: FindClassInput): Promise<FindClassOutput>;
|
|
61
63
|
export declare function getClassSource(svc: SourceService, input: GetClassSourceInput): Promise<GetClassSourceOutput>;
|
|
62
64
|
export declare function getClassMembers(svc: SourceService, input: GetClassMembersInput): Promise<GetClassMembersOutput>;
|