@adhisang/minecraft-modding-mcp 3.1.1 → 4.0.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 +49 -0
- package/README.md +37 -18
- package/dist/access-transformer-parser.d.ts +17 -0
- package/dist/access-transformer-parser.js +97 -0
- package/dist/cache-registry.d.ts +1 -1
- package/dist/cache-registry.js +10 -2
- package/dist/concurrency.d.ts +1 -0
- package/dist/concurrency.js +24 -0
- package/dist/config.d.ts +10 -1
- package/dist/config.js +52 -1
- package/dist/decompiler/vineflower.js +22 -21
- package/dist/entry-tools/analyze-mod-service.d.ts +4 -4
- package/dist/entry-tools/analyze-symbol-service.d.ts +22 -22
- package/dist/entry-tools/analyze-symbol-service.js +13 -2
- package/dist/entry-tools/inspect-minecraft-service.d.ts +168 -168
- package/dist/entry-tools/inspect-minecraft-service.js +8 -2
- package/dist/entry-tools/manage-cache-service.d.ts +4 -4
- package/dist/entry-tools/validate-project-service.d.ts +153 -16
- package/dist/entry-tools/validate-project-service.js +442 -25
- package/dist/gradle-paths.d.ts +4 -0
- package/dist/gradle-paths.js +57 -0
- package/dist/index.js +148 -30
- package/dist/lru-list.d.ts +31 -0
- package/dist/lru-list.js +102 -0
- package/dist/mapping-pipeline-service.d.ts +12 -1
- package/dist/mapping-pipeline-service.js +28 -1
- package/dist/mapping-service.d.ts +16 -0
- package/dist/mapping-service.js +405 -68
- package/dist/minecraft-explorer-service.d.ts +13 -0
- package/dist/minecraft-explorer-service.js +8 -4
- package/dist/mixin-validator.d.ts +33 -2
- package/dist/mixin-validator.js +218 -17
- package/dist/mod-analyzer.d.ts +1 -0
- package/dist/mod-analyzer.js +17 -1
- package/dist/mod-decompile-service.js +4 -4
- package/dist/mod-remap-service.js +1 -54
- package/dist/mod-search-service.d.ts +1 -0
- package/dist/mod-search-service.js +84 -51
- package/dist/observability.d.ts +18 -1
- package/dist/observability.js +44 -1
- package/dist/response-utils.d.ts +69 -0
- package/dist/response-utils.js +227 -0
- package/dist/source-jar-reader.d.ts +16 -0
- package/dist/source-jar-reader.js +103 -1
- package/dist/source-resolver.d.ts +9 -1
- package/dist/source-resolver.js +23 -16
- package/dist/source-service.d.ts +119 -3
- package/dist/source-service.js +1836 -218
- package/dist/storage/artifacts-repo.d.ts +4 -1
- package/dist/storage/artifacts-repo.js +33 -5
- package/dist/storage/files-repo.d.ts +0 -2
- package/dist/storage/files-repo.js +0 -11
- package/dist/storage/migrations.d.ts +1 -1
- package/dist/storage/migrations.js +10 -2
- package/dist/storage/schema.d.ts +2 -0
- package/dist/storage/schema.js +25 -0
- package/dist/tool-contract-manifest.js +8 -6
- package/dist/types.d.ts +20 -0
- package/dist/workspace-mapping-service.d.ts +13 -0
- package/dist/workspace-mapping-service.js +146 -14
- package/package.json +3 -1
|
@@ -9,7 +9,7 @@ function toErrorMessage(value) {
|
|
|
9
9
|
}
|
|
10
10
|
return String(value);
|
|
11
11
|
}
|
|
12
|
-
function hasJavaSourceExtension(entryPath) {
|
|
12
|
+
export function hasJavaSourceExtension(entryPath) {
|
|
13
13
|
const suffix = ".java";
|
|
14
14
|
if (entryPath.length < suffix.length) {
|
|
15
15
|
return false;
|
|
@@ -144,6 +144,22 @@ export async function listJavaEntries(jarPath) {
|
|
|
144
144
|
const entries = await listJarEntries(jarPath);
|
|
145
145
|
return entries.filter((entry) => hasJavaSourceExtension(entry) && isSecureJarEntryPath(entry));
|
|
146
146
|
}
|
|
147
|
+
export async function hasAnyJarEntry(jarPath, predicate) {
|
|
148
|
+
return withZipFile(jarPath, async (zipFile) => {
|
|
149
|
+
while (true) {
|
|
150
|
+
const entry = await readNextEntry(zipFile);
|
|
151
|
+
if (!entry) {
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
if (!isSecureJarEntryPath(entry.fileName)) {
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
if (predicate(entry.fileName)) {
|
|
158
|
+
return true;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
}
|
|
147
163
|
export async function readJarEntryAsUtf8(jarPath, entryPath) {
|
|
148
164
|
const contentBuffer = await readJarEntryAsBuffer(jarPath, entryPath);
|
|
149
165
|
return decodeUtf8OrThrow(contentBuffer, jarPath, entryPath);
|
|
@@ -177,6 +193,39 @@ export async function readJarEntryAsBuffer(jarPath, entryPath) {
|
|
|
177
193
|
}
|
|
178
194
|
});
|
|
179
195
|
}
|
|
196
|
+
export async function collectMatchedJarEntriesAsUtf8(jarPath, predicate, options = {}) {
|
|
197
|
+
return withZipFile(jarPath, async (zipFile) => {
|
|
198
|
+
const entries = [];
|
|
199
|
+
const maxEntries = options.maxEntries == null ? undefined : Math.max(1, Math.trunc(options.maxEntries));
|
|
200
|
+
while (true) {
|
|
201
|
+
const entry = await readNextEntry(zipFile);
|
|
202
|
+
if (!entry) {
|
|
203
|
+
return entries;
|
|
204
|
+
}
|
|
205
|
+
if (!isSecureJarEntryPath(entry.fileName)) {
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
if (!predicate(entry.fileName)) {
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
try {
|
|
212
|
+
const contentBuffer = await readEntryStream(zipFile, entry, jarPath, options.maxBytes);
|
|
213
|
+
entries.push({
|
|
214
|
+
filePath: entry.fileName,
|
|
215
|
+
content: decodeUtf8OrThrow(contentBuffer, jarPath, entry.fileName)
|
|
216
|
+
});
|
|
217
|
+
if (maxEntries != null && entries.length >= maxEntries) {
|
|
218
|
+
return entries;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
if (!options.continueOnError) {
|
|
223
|
+
throw error;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
}
|
|
180
229
|
export async function* iterateJavaEntriesAsUtf8(jarPath, maxBytes) {
|
|
181
230
|
const zipFile = await openZipFile(jarPath);
|
|
182
231
|
try {
|
|
@@ -227,4 +276,57 @@ export async function readAllJavaEntriesAsUtf8(jarPath, maxBytes) {
|
|
|
227
276
|
}
|
|
228
277
|
return entries;
|
|
229
278
|
}
|
|
279
|
+
function countMatches(input, pattern) {
|
|
280
|
+
const flags = pattern.flags.includes("g") ? pattern.flags : `${pattern.flags}g`;
|
|
281
|
+
const globalPattern = new RegExp(pattern.source, flags);
|
|
282
|
+
let count = 0;
|
|
283
|
+
while (globalPattern.exec(input)) {
|
|
284
|
+
count += 1;
|
|
285
|
+
}
|
|
286
|
+
return count;
|
|
287
|
+
}
|
|
288
|
+
export async function detectFabricLikeInputNamespace(inputJar) {
|
|
289
|
+
const warnings = [];
|
|
290
|
+
const classEntries = (await listJarEntries(inputJar))
|
|
291
|
+
.filter((entry) => entry.endsWith(".class"))
|
|
292
|
+
.slice(0, 24);
|
|
293
|
+
if (classEntries.length === 0) {
|
|
294
|
+
warnings.push("Could not inspect class entries to detect input mapping; assuming intermediary.");
|
|
295
|
+
return {
|
|
296
|
+
fromNamespace: "intermediary",
|
|
297
|
+
warnings
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
let mojangScore = 0;
|
|
301
|
+
let intermediaryScore = 0;
|
|
302
|
+
for (const entry of classEntries) {
|
|
303
|
+
let text = "";
|
|
304
|
+
try {
|
|
305
|
+
text = (await readJarEntryAsBuffer(inputJar, entry)).toString("latin1");
|
|
306
|
+
}
|
|
307
|
+
catch {
|
|
308
|
+
continue;
|
|
309
|
+
}
|
|
310
|
+
mojangScore += countMatches(text, /net\/minecraft\/(?:advancements|client|commands|core|data|gametest|nbt|network|recipe|resources|server|sounds|stats|tags|util|world)\//g) * 3;
|
|
311
|
+
intermediaryScore += countMatches(text, /net\/minecraft\/class_\d+/g) * 3;
|
|
312
|
+
intermediaryScore += countMatches(text, /\b(?:method|field)_\d+\b/g);
|
|
313
|
+
}
|
|
314
|
+
if (mojangScore > intermediaryScore && mojangScore > 0) {
|
|
315
|
+
return {
|
|
316
|
+
fromNamespace: "mojang",
|
|
317
|
+
warnings
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
if (intermediaryScore > mojangScore && intermediaryScore > 0) {
|
|
321
|
+
return {
|
|
322
|
+
fromNamespace: "intermediary",
|
|
323
|
+
warnings
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
warnings.push("Could not confidently detect whether the input jar uses intermediary or mojang names; assuming intermediary.");
|
|
327
|
+
return {
|
|
328
|
+
fromNamespace: "intermediary",
|
|
329
|
+
warnings
|
|
330
|
+
};
|
|
331
|
+
}
|
|
230
332
|
//# sourceMappingURL=source-jar-reader.js.map
|
|
@@ -1,8 +1,16 @@
|
|
|
1
|
-
import type { Config, ResolvedSourceArtifact, SourceTargetInput } from "./types.js";
|
|
1
|
+
import type { Config, MappingVariant, ResolvedSourceArtifact, SourceTargetInput } from "./types.js";
|
|
2
|
+
export type { MappingVariant } from "./types.js";
|
|
2
3
|
export interface ResolveSourceTargetOptions {
|
|
3
4
|
allowDecompile: boolean;
|
|
4
5
|
preferBinaryOnly?: boolean;
|
|
5
6
|
preferredRepos?: string[];
|
|
7
|
+
/**
|
|
8
|
+
* When set to "mojang-remapped", the artifactId hash gets a dedicated
|
|
9
|
+
* suffix so the mojang-remapped variant of an otherwise binary-only artifact
|
|
10
|
+
* occupies its own cache slot. Defaults to "pass" which preserves the
|
|
11
|
+
* legacy hash for obfuscated and source-backed artifacts.
|
|
12
|
+
*/
|
|
13
|
+
mappingVariant?: MappingVariant;
|
|
6
14
|
onRepoFailover?: (event: {
|
|
7
15
|
stage: "source" | "binary";
|
|
8
16
|
repoUrl: string;
|
package/dist/source-resolver.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { readdir } from "node:fs/promises";
|
|
2
2
|
import { basename, dirname, join, resolve as resolvePath } from "node:path";
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
4
|
import fastGlob from "fast-glob";
|
|
@@ -7,7 +7,7 @@ import { buildRemoteBinaryUrls, buildRemoteSourceUrls, hasExistingJar, parseCoor
|
|
|
7
7
|
import { defaultDownloadPath, downloadToCache } from "./repo-downloader.js";
|
|
8
8
|
import { artifactSignatureFromFile, normalizeJarPath } from "./path-resolver.js";
|
|
9
9
|
import { stableArtifactId } from "./config.js";
|
|
10
|
-
import {
|
|
10
|
+
import { hasAnyJarEntry, hasJavaSourceExtension } from "./source-jar-reader.js";
|
|
11
11
|
function readStatsSignature(filePath) {
|
|
12
12
|
const stats = artifactSignatureFromFile(filePath);
|
|
13
13
|
return stats.signature;
|
|
@@ -16,8 +16,7 @@ async function hasJavaSources(jarPath) {
|
|
|
16
16
|
if (!hasExistingJar(jarPath)) {
|
|
17
17
|
return false;
|
|
18
18
|
}
|
|
19
|
-
|
|
20
|
-
return entries.length > 0;
|
|
19
|
+
return hasAnyJarEntry(jarPath, hasJavaSourceExtension);
|
|
21
20
|
}
|
|
22
21
|
function resolveExactJarSourceCandidate(inputJarPath) {
|
|
23
22
|
const directory = dirname(inputJarPath);
|
|
@@ -35,12 +34,12 @@ function resolveSiblingBinaryJarCandidate(inputJarPath) {
|
|
|
35
34
|
const candidate = join(directory, binaryName);
|
|
36
35
|
return hasExistingJar(candidate) ? candidate : undefined;
|
|
37
36
|
}
|
|
38
|
-
function listAdjacentJarSourceCandidates(inputJarPath) {
|
|
37
|
+
async function listAdjacentJarSourceCandidates(inputJarPath) {
|
|
39
38
|
const directory = dirname(inputJarPath);
|
|
40
39
|
const exact = resolveExactJarSourceCandidate(inputJarPath);
|
|
41
40
|
const candidates = new Set();
|
|
42
41
|
try {
|
|
43
|
-
for (const file of
|
|
42
|
+
for (const file of await readdir(directory)) {
|
|
44
43
|
if (file.toLowerCase().endsWith("-sources.jar")) {
|
|
45
44
|
const candidate = join(directory, file);
|
|
46
45
|
if (candidate !== inputJarPath && candidate !== exact) {
|
|
@@ -90,7 +89,7 @@ function resolveGradleUserHome() {
|
|
|
90
89
|
}
|
|
91
90
|
return resolvePath(homedir(), ".gradle");
|
|
92
91
|
}
|
|
93
|
-
function resolveGradleCacheCoordinateCandidate(coordinate) {
|
|
92
|
+
async function resolveGradleCacheCoordinateCandidate(coordinate) {
|
|
94
93
|
const parsed = parseCoordinate(coordinate);
|
|
95
94
|
const baseDir = resolvePath(resolveGradleUserHome(), "caches", "modules-2", "files-2.1", parsed.groupId, parsed.artifactId, parsed.version);
|
|
96
95
|
const base = `${parsed.artifactId}-${parsed.version}`;
|
|
@@ -105,7 +104,7 @@ function resolveGradleCacheCoordinateCandidate(coordinate) {
|
|
|
105
104
|
];
|
|
106
105
|
let discoveredFiles = [];
|
|
107
106
|
try {
|
|
108
|
-
discoveredFiles = fastGlob.
|
|
107
|
+
discoveredFiles = await fastGlob.glob("*/*", {
|
|
109
108
|
cwd: baseDir,
|
|
110
109
|
absolute: true,
|
|
111
110
|
onlyFiles: true
|
|
@@ -134,11 +133,19 @@ function resolveGradleCacheCoordinateCandidate(coordinate) {
|
|
|
134
133
|
function resolveRemoteBinaryCandidate(coordinate, repos) {
|
|
135
134
|
return buildRemoteBinaryUrls(repos, coordinate);
|
|
136
135
|
}
|
|
137
|
-
function artifactIdForJar(inputKind, artifactPath, signature, suffix) {
|
|
138
|
-
|
|
136
|
+
function artifactIdForJar(inputKind, artifactPath, signature, suffix, mappingVariant = "pass") {
|
|
137
|
+
const parts = [inputKind, artifactPath, signature, suffix ?? "source"];
|
|
138
|
+
if (mappingVariant === "mojang-remapped") {
|
|
139
|
+
parts.push("mojang-remapped");
|
|
140
|
+
}
|
|
141
|
+
return stableArtifactId(parts);
|
|
139
142
|
}
|
|
140
|
-
function artifactIdForCoordinate(coordinate, source, signature) {
|
|
141
|
-
|
|
143
|
+
function artifactIdForCoordinate(coordinate, source, signature, mappingVariant = "pass") {
|
|
144
|
+
const parts = ["coord", coordinate, source, signature];
|
|
145
|
+
if (mappingVariant === "mojang-remapped") {
|
|
146
|
+
parts.push("mojang-remapped");
|
|
147
|
+
}
|
|
148
|
+
return stableArtifactId(parts);
|
|
142
149
|
}
|
|
143
150
|
function resolvedAtNow() {
|
|
144
151
|
return new Date().toISOString();
|
|
@@ -150,7 +157,7 @@ export async function resolveSourceTarget(input, options, explicitConfig) {
|
|
|
150
157
|
const resolvedJarPath = normalizeJarPath(input.value);
|
|
151
158
|
const binarySignature = readStatsSignature(resolvedJarPath);
|
|
152
159
|
const exactSourceJarPath = resolveExactJarSourceCandidate(resolvedJarPath);
|
|
153
|
-
const adjacentSourceCandidates = listAdjacentJarSourceCandidates(resolvedJarPath);
|
|
160
|
+
const adjacentSourceCandidates = await listAdjacentJarSourceCandidates(resolvedJarPath);
|
|
154
161
|
const maybeAdjacentSourceCandidates = adjacentSourceCandidates.length > 0 ? adjacentSourceCandidates : undefined;
|
|
155
162
|
const preferBinaryOnly = options.preferBinaryOnly ?? false;
|
|
156
163
|
if (await hasJavaSources(resolvedJarPath)) {
|
|
@@ -192,7 +199,7 @@ export async function resolveSourceTarget(input, options, explicitConfig) {
|
|
|
192
199
|
});
|
|
193
200
|
}
|
|
194
201
|
return {
|
|
195
|
-
artifactId: artifactIdForJar("jar", resolvedJarPath, `${binarySignature}:decompile
|
|
202
|
+
artifactId: artifactIdForJar("jar", resolvedJarPath, `${binarySignature}:decompile`, undefined, options.mappingVariant ?? "pass"),
|
|
196
203
|
artifactSignature: `${binarySignature}:decompile`,
|
|
197
204
|
origin: "decompiled",
|
|
198
205
|
binaryJarPath: resolvedJarPath,
|
|
@@ -225,7 +232,7 @@ export async function resolveSourceTarget(input, options, explicitConfig) {
|
|
|
225
232
|
};
|
|
226
233
|
}
|
|
227
234
|
}
|
|
228
|
-
const gradleCacheCandidate = resolveGradleCacheCoordinateCandidate(coordinate);
|
|
235
|
+
const gradleCacheCandidate = await resolveGradleCacheCoordinateCandidate(coordinate);
|
|
229
236
|
if (gradleCacheCandidate?.sourceJarPath && (await hasJavaSources(gradleCacheCandidate.sourceJarPath))) {
|
|
230
237
|
const signature = readStatsSignature(gradleCacheCandidate.sourceJarPath);
|
|
231
238
|
return {
|
|
@@ -327,7 +334,7 @@ export async function resolveSourceTarget(input, options, explicitConfig) {
|
|
|
327
334
|
}
|
|
328
335
|
const signature = readStatsSignature(downloaded.path);
|
|
329
336
|
return {
|
|
330
|
-
artifactId: artifactIdForCoordinate(coordinate, "decompiled", signature),
|
|
337
|
+
artifactId: artifactIdForCoordinate(coordinate, "decompiled", signature, options.mappingVariant ?? "pass"),
|
|
331
338
|
artifactSignature: signature,
|
|
332
339
|
origin: "decompiled",
|
|
333
340
|
binaryJarPath: downloaded.path,
|
package/dist/source-service.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { type ResponseContext as ExplorerResponseContext, type SignatureMember } from "./minecraft-explorer-service.js";
|
|
2
|
-
import { type MixinValidationResult, type MixinValidationProvenance, type MappingHealthReport, type AccessWidenerValidationResult } from "./mixin-validator.js";
|
|
2
|
+
import { type MixinValidationResult, type MixinValidationProvenance, type MappingHealthReport, type AccessWidenerValidationResult, type AccessTransformerValidationResult } from "./mixin-validator.js";
|
|
3
3
|
import { type ClassApiMatrixInput as MappingClassApiMatrixInput, type ClassApiMatrixOutput as MappingClassApiMatrixOutput, type FindMappingInput as MappingFindMappingInput, type FindMappingOutput as MappingFindMappingOutput, type ResolveMethodMappingExactInput as MappingResolveMethodMappingExactInput, type ResolveMethodMappingExactOutput as MappingResolveMethodMappingExactOutput, type SymbolResolutionOutput as MappingSymbolResolutionOutput, type SymbolExistenceInput as MappingSymbolExistenceInput, type SymbolExistenceOutput as MappingSymbolExistenceOutput } from "./mapping-service.js";
|
|
4
4
|
import { RuntimeMetrics, type RuntimeMetricSnapshot } from "./observability.js";
|
|
5
5
|
import { type WorkspaceCompileMappingOutput } from "./workspace-mapping-service.js";
|
|
6
|
-
import type { ArtifactProvenance, ArtifactRow, ArtifactScope, Config, MappingSourcePriority, ResolvedSourceArtifact, SourceMapping, SourceTargetInput } from "./types.js";
|
|
6
|
+
import type { AccessTransformerNamespace, ArtifactProvenance, ArtifactRow, ArtifactScope, Config, MappingSourcePriority, ResolvedSourceArtifact, SourceMapping, SourceTargetInput } from "./types.js";
|
|
7
7
|
import { type ListVersionsInput, type ListVersionsOutput } from "./version-service.js";
|
|
8
8
|
import { type GetRegistryDataInput, type GetRegistryDataOutput } from "./registry-service.js";
|
|
9
9
|
import { type CompareVersionsInput, type CompareVersionsOutput } from "./version-diff-service.js";
|
|
@@ -18,9 +18,11 @@ export type ResolveArtifactInput = {
|
|
|
18
18
|
scope?: ArtifactScope;
|
|
19
19
|
preferProjectVersion?: boolean;
|
|
20
20
|
strictVersion?: boolean;
|
|
21
|
+
compact?: boolean;
|
|
21
22
|
};
|
|
22
23
|
export type ResolveArtifactOutput = {
|
|
23
24
|
artifactId: string;
|
|
25
|
+
artifactAlias: string;
|
|
24
26
|
origin: "local-jar" | "local-m2" | "remote-repo" | "decompiled";
|
|
25
27
|
isDecompiled: boolean;
|
|
26
28
|
resolvedSourceJarPath?: string;
|
|
@@ -74,6 +76,8 @@ export type SearchClassSourceInput = {
|
|
|
74
76
|
queryMode?: QueryMode;
|
|
75
77
|
limit?: number;
|
|
76
78
|
cursor?: string;
|
|
79
|
+
queryNamespace?: SourceMapping;
|
|
80
|
+
sourcePriority?: MappingSourcePriority;
|
|
77
81
|
};
|
|
78
82
|
export type SearchClassSourceOutput = {
|
|
79
83
|
hits: SearchSourceHit[];
|
|
@@ -81,6 +85,13 @@ export type SearchClassSourceOutput = {
|
|
|
81
85
|
mappingApplied: SourceMapping;
|
|
82
86
|
returnedNamespace: SourceMapping;
|
|
83
87
|
artifactContents: ArtifactContentsSummary;
|
|
88
|
+
translatedQuery?: {
|
|
89
|
+
original: string;
|
|
90
|
+
translated: string;
|
|
91
|
+
fromNamespace: SourceMapping;
|
|
92
|
+
toNamespace: SourceMapping;
|
|
93
|
+
};
|
|
94
|
+
warnings?: string[];
|
|
84
95
|
};
|
|
85
96
|
export type GetArtifactFileInput = {
|
|
86
97
|
artifactId: string;
|
|
@@ -207,6 +218,17 @@ export type GetClassMembersInput = {
|
|
|
207
218
|
preferProjectVersion?: boolean;
|
|
208
219
|
strictVersion?: boolean;
|
|
209
220
|
};
|
|
221
|
+
export type DecompiledMember = {
|
|
222
|
+
name: string;
|
|
223
|
+
line: number;
|
|
224
|
+
kind: "constructor" | "field" | "method";
|
|
225
|
+
};
|
|
226
|
+
export type DecompiledFallback = {
|
|
227
|
+
constructors: DecompiledMember[];
|
|
228
|
+
fields: DecompiledMember[];
|
|
229
|
+
methods: DecompiledMember[];
|
|
230
|
+
origin: "source-extracted";
|
|
231
|
+
};
|
|
210
232
|
export type GetClassMembersOutput = {
|
|
211
233
|
className: string;
|
|
212
234
|
members: {
|
|
@@ -230,6 +252,13 @@ export type GetClassMembersOutput = {
|
|
|
230
252
|
provenance: ArtifactProvenance;
|
|
231
253
|
qualityFlags: string[];
|
|
232
254
|
artifactContents: ArtifactContentsSummary;
|
|
255
|
+
decompiledFallback?: DecompiledFallback;
|
|
256
|
+
decompiledMemberCounts?: {
|
|
257
|
+
constructors: number;
|
|
258
|
+
fields: number;
|
|
259
|
+
methods: number;
|
|
260
|
+
total: number;
|
|
261
|
+
};
|
|
233
262
|
warnings: string[];
|
|
234
263
|
};
|
|
235
264
|
export type TraceSymbolLifecycleInput = {
|
|
@@ -424,8 +453,21 @@ export type ValidateAccessWidenerInput = {
|
|
|
424
453
|
version: string;
|
|
425
454
|
mapping?: SourceMapping;
|
|
426
455
|
sourcePriority?: MappingSourcePriority;
|
|
456
|
+
projectPath?: string;
|
|
457
|
+
scope?: ArtifactScope;
|
|
458
|
+
preferProjectVersion?: boolean;
|
|
427
459
|
};
|
|
428
460
|
export type ValidateAccessWidenerOutput = AccessWidenerValidationResult;
|
|
461
|
+
export type ValidateAccessTransformerInput = {
|
|
462
|
+
content: string;
|
|
463
|
+
version: string;
|
|
464
|
+
atNamespace?: AccessTransformerNamespace;
|
|
465
|
+
sourcePriority?: MappingSourcePriority;
|
|
466
|
+
projectPath?: string;
|
|
467
|
+
scope?: ArtifactScope;
|
|
468
|
+
preferProjectVersion?: boolean;
|
|
469
|
+
};
|
|
470
|
+
export type ValidateAccessTransformerOutput = AccessTransformerValidationResult;
|
|
429
471
|
export declare class SourceService {
|
|
430
472
|
private readonly config;
|
|
431
473
|
private readonly db;
|
|
@@ -442,10 +484,33 @@ export declare class SourceService {
|
|
|
442
484
|
private readonly versionDiffService;
|
|
443
485
|
private readonly modDecompileService;
|
|
444
486
|
private readonly modSearchService;
|
|
445
|
-
private
|
|
487
|
+
private readonly lru;
|
|
488
|
+
private cacheTotalContentBytes;
|
|
489
|
+
private readonly remappedJarBytes;
|
|
490
|
+
/** In-flight binary-remap jobs keyed by remapped jar path so concurrent
|
|
491
|
+
* resolveArtifact calls for the same artifactId share a single tiny-remapper run. */
|
|
492
|
+
private readonly inflightRemaps;
|
|
446
493
|
constructor(explicitConfig?: Config, metrics?: RuntimeMetrics);
|
|
447
494
|
private discoverVersionSourceJar;
|
|
495
|
+
private discoverAccessWidenerRuntimeCandidates;
|
|
496
|
+
private discoverAccessTransformerRuntimeCandidates;
|
|
497
|
+
private resolveAccessWidenerRuntimeArtifact;
|
|
498
|
+
private resolveAccessTransformerNamespace;
|
|
499
|
+
private resolveAccessTransformerRuntimeArtifact;
|
|
448
500
|
private buildVersionSourceRecoveryCommand;
|
|
501
|
+
/**
|
|
502
|
+
* Decide whether the upcoming resolveArtifact call may transparently remap a
|
|
503
|
+
* binary-only artifact (obfuscated -> mojang) and decompile it. The gate
|
|
504
|
+
* succeeds only when:
|
|
505
|
+
* - the requested mapping is "mojang" on a still-obfuscated runtime
|
|
506
|
+
* - tiny-remapper jar is downloadable / available locally
|
|
507
|
+
* - the version's Mojang tiny mapping file can be produced
|
|
508
|
+
* - checkMappingHealth reports mojang mappings are usable
|
|
509
|
+
* On any failure the variant defaults to "pass" so the legacy
|
|
510
|
+
* MAPPING_NOT_APPLIED fallback (or the existing source-backed flow) keeps
|
|
511
|
+
* its existing artifactId hash.
|
|
512
|
+
*/
|
|
513
|
+
private computeBinaryRemapGate;
|
|
449
514
|
private buildArtifactContentsSummary;
|
|
450
515
|
private inferVersionFromContext;
|
|
451
516
|
private resolveVersionContext;
|
|
@@ -464,22 +529,28 @@ export declare class SourceService {
|
|
|
464
529
|
getClassApiMatrix(input: GetClassApiMatrixInput): Promise<GetClassApiMatrixOutput>;
|
|
465
530
|
checkSymbolExists(input: CheckSymbolExistsInput): Promise<CheckSymbolExistsOutput>;
|
|
466
531
|
resolveWorkspaceSymbol(input: ResolveWorkspaceSymbolInput): Promise<ResolveWorkspaceSymbolOutput>;
|
|
532
|
+
private checkSymbolExistsInUnobfuscatedRuntime;
|
|
467
533
|
traceSymbolLifecycle(input: TraceSymbolLifecycleInput): Promise<TraceSymbolLifecycleOutput>;
|
|
468
534
|
diffClassSignatures(input: DiffClassSignaturesInput): Promise<DiffClassSignaturesOutput>;
|
|
469
535
|
findClass(input: FindClassInput): FindClassOutput;
|
|
470
536
|
getClassSource(input: GetClassSourceInput): Promise<GetClassSourceOutput>;
|
|
471
537
|
getClassMembers(input: GetClassMembersInput): Promise<GetClassMembersOutput>;
|
|
538
|
+
private buildDecompiledFallback;
|
|
472
539
|
validateMixin(input: ValidateMixinInput): Promise<ValidateMixinOutput>;
|
|
540
|
+
private runValidateMixinDispatcher;
|
|
473
541
|
private createProjectValidateMixinConfigInput;
|
|
474
542
|
private shouldRetryValidateMixinWithMavenFirst;
|
|
475
543
|
private findValidateMixinClassMapping;
|
|
476
544
|
private validateMixinSingle;
|
|
545
|
+
private runValidateMixinPipeline;
|
|
477
546
|
private resolveMixinInputPath;
|
|
478
547
|
private resolveMixinConfigSources;
|
|
479
548
|
private validateMixinMany;
|
|
480
549
|
private applyValidateMixinOutputCompaction;
|
|
481
550
|
private buildValidateMixinOutput;
|
|
482
551
|
validateAccessWidener(input: ValidateAccessWidenerInput): Promise<ValidateAccessWidenerOutput>;
|
|
552
|
+
validateAccessTransformer(input: ValidateAccessTransformerInput): Promise<ValidateAccessTransformerOutput>;
|
|
553
|
+
recordToolCall(tool: string, durationMs: number): void;
|
|
483
554
|
getRuntimeMetrics(): RuntimeMetricSnapshot;
|
|
484
555
|
indexArtifact(input: IndexArtifactInput): Promise<IndexArtifactOutput>;
|
|
485
556
|
private searchSymbolIntent;
|
|
@@ -491,6 +562,11 @@ export declare class SourceService {
|
|
|
491
562
|
private indexedCandidateLimit;
|
|
492
563
|
private indexedCandidateLimitForMatch;
|
|
493
564
|
private extractClassMetadata;
|
|
565
|
+
private extractDecompiledMembers;
|
|
566
|
+
private computeLineBraceDepths;
|
|
567
|
+
private computeBraceRange;
|
|
568
|
+
private scanBraceRange;
|
|
569
|
+
private computeNestedTypeRanges;
|
|
494
570
|
private resolveClassFilePath;
|
|
495
571
|
private resolveBinaryFallbackArtifact;
|
|
496
572
|
private buildProvenance;
|
|
@@ -509,13 +585,53 @@ export declare class SourceService {
|
|
|
509
585
|
private buildRebuiltArtifactData;
|
|
510
586
|
getArtifact(artifactId: string): ArtifactRow;
|
|
511
587
|
private ingestIfNeeded;
|
|
588
|
+
/**
|
|
589
|
+
* If the resolved artifact's transformChain promised an "obf -> mojang"
|
|
590
|
+
* binary remap, run tiny-remapper now and return the remapped jar path.
|
|
591
|
+
* Otherwise return the original binaryJarPath unchanged.
|
|
592
|
+
*
|
|
593
|
+
* Cache safety: writes to a per-attempt temp file then atomic-renames into
|
|
594
|
+
* <cacheDir>/remapped/<artifactId>.jar. A per-target inflight Promise map
|
|
595
|
+
* collapses concurrent calls so two simultaneous resolveArtifact calls for
|
|
596
|
+
* the same artifactId share one tiny-remapper run instead of racing on the
|
|
597
|
+
* same output path.
|
|
598
|
+
*/
|
|
599
|
+
private maybeRemapBinaryForMojang;
|
|
600
|
+
private recordRemappedJarBytesFromDisk;
|
|
601
|
+
/**
|
|
602
|
+
* Best-effort structural check that `path` is a non-empty file beginning with
|
|
603
|
+
* the ZIP local-file-header magic (`50 4B 03 04`). Used to drop partial /
|
|
604
|
+
* corrupt remap-cache entries before they reach Vineflower. False positives
|
|
605
|
+
* are acceptable (Vineflower will surface a clearer error); false negatives
|
|
606
|
+
* are not (a corrupt cache hit must be evicted).
|
|
607
|
+
*/
|
|
608
|
+
private isUsableJarFile;
|
|
609
|
+
private runBinaryRemap;
|
|
512
610
|
private loadFromSourceJar;
|
|
513
611
|
private hasAnyFiles;
|
|
612
|
+
/**
|
|
613
|
+
* Best-effort cleanup of `<cacheDir>/remapped/<artifactId>.jar` written by
|
|
614
|
+
* `maybeRemapBinaryForMojang`. Called from cache-eviction paths so the
|
|
615
|
+
* Mojang-remapped binary jar does not outlive the artifact row that owns it.
|
|
616
|
+
* Also releases the jar's bytes from `cacheTotalContentBytes`. Errors are
|
|
617
|
+
* swallowed: orphaned jars remain visible to `manage-cache` under the
|
|
618
|
+
* `binary-remap` cache kind and can be reclaimed there.
|
|
619
|
+
*/
|
|
620
|
+
private unlinkRemappedJarForArtifact;
|
|
621
|
+
/**
|
|
622
|
+
* Add the remapped jar's on-disk size to `cacheTotalContentBytes` so the
|
|
623
|
+
* `enforceCacheLimits` byte gate sees the jar before deciding to evict.
|
|
624
|
+
* Without this, a Mojang-remapped client jar (tens of MB) can accumulate
|
|
625
|
+
* silently while the indexed-source byte total stays below `maxCacheBytes`.
|
|
626
|
+
*/
|
|
627
|
+
private recordRemappedJarBytes;
|
|
628
|
+
private releaseRemappedJarBytes;
|
|
514
629
|
private enforceCacheLimits;
|
|
515
630
|
private refreshCacheMetrics;
|
|
516
631
|
private touchCacheMetrics;
|
|
517
632
|
private upsertCacheMetrics;
|
|
518
633
|
private removeCacheMetrics;
|
|
519
634
|
private publishCacheMetrics;
|
|
635
|
+
private snapshotLruAccounting;
|
|
520
636
|
}
|
|
521
637
|
export {};
|