@shapeshift-labs/frontier-lang-compiler 0.2.29 → 0.2.30
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 +10 -2
- package/bench/smoke.mjs +2 -1
- package/dist/index.d.ts +33 -0
- package/dist/index.js +689 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -334,6 +334,7 @@ import {
|
|
|
334
334
|
createBabelNativeImporterAdapter,
|
|
335
335
|
createClangAstNativeImporterAdapter,
|
|
336
336
|
createGoAstNativeImporterAdapter,
|
|
337
|
+
createJavaAstNativeImporterAdapter,
|
|
337
338
|
createPythonAstNativeImporterAdapter,
|
|
338
339
|
createRustSynNativeImporterAdapter,
|
|
339
340
|
importNativeProject,
|
|
@@ -359,6 +360,11 @@ const goAstAdapter = createGoAstNativeImporterAdapter({
|
|
|
359
360
|
parserModule: hostGoAstParser,
|
|
360
361
|
goVersion: '1.22'
|
|
361
362
|
});
|
|
363
|
+
const javaAstAdapter = createJavaAstNativeImporterAdapter({
|
|
364
|
+
parserModule: hostJavaAstParser,
|
|
365
|
+
javaVersion: '21',
|
|
366
|
+
sourceLevel: '21'
|
|
367
|
+
});
|
|
362
368
|
|
|
363
369
|
const imported = await runNativeImporterAdapter(babelAdapter, {
|
|
364
370
|
sourcePath: 'src/todo.ts',
|
|
@@ -367,13 +373,14 @@ const imported = await runNativeImporterAdapter(babelAdapter, {
|
|
|
367
373
|
|
|
368
374
|
const project = await importNativeProject({
|
|
369
375
|
projectRoot: 'src',
|
|
370
|
-
adapters: [babelAdapter, pythonAstAdapter, rustSynAdapter, clangAstAdapter, goAstAdapter],
|
|
376
|
+
adapters: [babelAdapter, pythonAstAdapter, rustSynAdapter, clangAstAdapter, goAstAdapter, javaAstAdapter],
|
|
371
377
|
sources: [
|
|
372
378
|
{ language: 'typescript', adapter: babelAdapter.id, sourcePath: 'src/todo.ts', sourceText },
|
|
373
379
|
{ language: 'python', adapter: pythonAstAdapter.id, sourcePath: 'tools/todo.py', sourceText: pythonSource },
|
|
374
380
|
{ language: 'rust', adapter: rustSynAdapter.id, sourcePath: 'src/todo.rs', sourceText: rustSource },
|
|
375
381
|
{ language: 'c', adapter: clangAstAdapter.id, sourcePath: 'native/todo.c', sourceText: cSource },
|
|
376
|
-
{ language: 'go', adapter: goAstAdapter.id, sourcePath: 'cmd/todo/main.go', sourceText: goSource }
|
|
382
|
+
{ language: 'go', adapter: goAstAdapter.id, sourcePath: 'cmd/todo/main.go', sourceText: goSource },
|
|
383
|
+
{ language: 'java', adapter: javaAstAdapter.id, sourcePath: 'src/main/java/Todo.java', sourceText: javaSource }
|
|
377
384
|
]
|
|
378
385
|
});
|
|
379
386
|
|
|
@@ -396,6 +403,7 @@ The built-in adapter factories are dependency-light wrappers for caller-owned pa
|
|
|
396
403
|
- `createRustSynNativeImporterAdapter`
|
|
397
404
|
- `createClangAstNativeImporterAdapter`
|
|
398
405
|
- `createGoAstNativeImporterAdapter`
|
|
406
|
+
- `createJavaAstNativeImporterAdapter`
|
|
399
407
|
- `createTreeSitterNativeImporterAdapter`
|
|
400
408
|
|
|
401
409
|
Adapter summaries include a structured `coverage` record so merge queues can distinguish exact parser AST imports from declaration scans. The record declares exactness, parser token/trivia support, diagnostics support, source-range and generated-range support, and semantic coverage. Built-in wrappers normalize native AST/CST nodes and declaration-level semantic indexes; they do not claim resolved references, types, control flow, generated ranges, or token/trivia fidelity unless the host adapter supplies that evidence.
|
package/bench/smoke.mjs
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
createClangAstNativeImporterAdapter,
|
|
6
6
|
createEstreeNativeImporterAdapter,
|
|
7
7
|
createGoAstNativeImporterAdapter,
|
|
8
|
+
createJavaAstNativeImporterAdapter,
|
|
8
9
|
createNativeImportCoverageMatrix,
|
|
9
10
|
createNativeParserAstFormatMatrix,
|
|
10
11
|
createProjectionTargetLossMatrix,
|
|
@@ -81,7 +82,7 @@ const matrixDurationMs = performance.now() - matrixStart;
|
|
|
81
82
|
const parserFormatMatrixStart = performance.now();
|
|
82
83
|
const parserFormatMatrix = createNativeParserAstFormatMatrix({
|
|
83
84
|
imports: nativeImportResults,
|
|
84
|
-
adapters: [estreeAdapter, createPythonAstNativeImporterAdapter(), createRustSynNativeImporterAdapter(), createClangAstNativeImporterAdapter(), createGoAstNativeImporterAdapter()]
|
|
85
|
+
adapters: [estreeAdapter, createPythonAstNativeImporterAdapter(), createRustSynNativeImporterAdapter(), createClangAstNativeImporterAdapter(), createGoAstNativeImporterAdapter(), createJavaAstNativeImporterAdapter()]
|
|
85
86
|
});
|
|
86
87
|
const parserFormatMatrixDurationMs = performance.now() - parserFormatMatrixStart;
|
|
87
88
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1465,6 +1465,38 @@ export interface GoAstNativeImporterAdapterOptions {
|
|
|
1465
1465
|
readonly maxNodes?: number;
|
|
1466
1466
|
}
|
|
1467
1467
|
|
|
1468
|
+
export interface JavaAstNativeImporterAdapterOptions {
|
|
1469
|
+
readonly id?: string;
|
|
1470
|
+
readonly language?: FrontierSourceLanguage;
|
|
1471
|
+
readonly parser?: string;
|
|
1472
|
+
readonly version?: string;
|
|
1473
|
+
readonly capabilities?: readonly string[];
|
|
1474
|
+
readonly coverage?: NativeImporterAdapterCoverageInput;
|
|
1475
|
+
readonly supportedExtensions?: readonly string[];
|
|
1476
|
+
readonly diagnostics?: readonly NativeImporterAdapterDiagnostic[];
|
|
1477
|
+
readonly ast?: unknown;
|
|
1478
|
+
readonly compilationUnit?: unknown;
|
|
1479
|
+
readonly unit?: unknown;
|
|
1480
|
+
readonly sourceFile?: unknown;
|
|
1481
|
+
readonly parse?: (sourceText: string, options: Record<string, unknown>) => unknown;
|
|
1482
|
+
readonly parserModule?: { readonly parse: (sourceText: string, options: Record<string, unknown>) => unknown };
|
|
1483
|
+
readonly javac?: { readonly parse: (sourceText: string, options: Record<string, unknown>) => unknown };
|
|
1484
|
+
readonly jdt?: { readonly parse: (sourceText: string, options: Record<string, unknown>) => unknown };
|
|
1485
|
+
readonly javaParser?: { readonly parse: (sourceText: string, options: Record<string, unknown>) => unknown };
|
|
1486
|
+
readonly parserOptions?: Record<string, unknown>;
|
|
1487
|
+
readonly javaVersion?: string;
|
|
1488
|
+
readonly sourceLevel?: string;
|
|
1489
|
+
readonly classPath?: readonly string[] | string | unknown;
|
|
1490
|
+
readonly modulePath?: readonly string[] | string | unknown;
|
|
1491
|
+
readonly generated?: boolean;
|
|
1492
|
+
readonly annotationProcessing?: unknown;
|
|
1493
|
+
readonly bindingEvidence?: unknown;
|
|
1494
|
+
readonly positionResolver?: (position: unknown) => unknown;
|
|
1495
|
+
readonly lineMap?: unknown;
|
|
1496
|
+
readonly includeAnnotations?: boolean;
|
|
1497
|
+
readonly maxNodes?: number;
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1468
1500
|
export interface TreeSitterNativeImporterAdapterOptions {
|
|
1469
1501
|
readonly id?: string;
|
|
1470
1502
|
readonly language?: FrontierSourceLanguage;
|
|
@@ -1838,6 +1870,7 @@ export declare function createPythonAstNativeImporterAdapter(options?: PythonAst
|
|
|
1838
1870
|
export declare function createRustSynNativeImporterAdapter(options?: RustSynNativeImporterAdapterOptions): NativeImporterAdapter;
|
|
1839
1871
|
export declare function createClangAstNativeImporterAdapter(options?: ClangAstNativeImporterAdapterOptions): NativeImporterAdapter;
|
|
1840
1872
|
export declare function createGoAstNativeImporterAdapter(options?: GoAstNativeImporterAdapterOptions): NativeImporterAdapter;
|
|
1873
|
+
export declare function createJavaAstNativeImporterAdapter(options?: JavaAstNativeImporterAdapterOptions): NativeImporterAdapter;
|
|
1841
1874
|
export declare function createTreeSitterNativeImporterAdapter(options?: TreeSitterNativeImporterAdapterOptions): NativeImporterAdapter;
|
|
1842
1875
|
export declare function runNativeImporterAdapter(adapter: NativeImporterAdapter, input: RunNativeImporterAdapterOptions): Promise<NativeImporterAdapterImportResult>;
|
|
1843
1876
|
export declare function runNativeTargetProjectionAdapter(adapter: NativeTargetProjectionAdapter, input: NativeTargetProjectionAdapterInput): NativeTargetProjectionResult;
|
package/dist/index.js
CHANGED
|
@@ -427,6 +427,18 @@ export const NativeParserAstFormatProfiles = Object.freeze([
|
|
|
427
427
|
supportsErrorRecovery: true,
|
|
428
428
|
notes: ['Go go/ast trees expose parser syntax nodes and token positions; FileSet, build tags, generated-code classification, package loading, go/types, comments/trivia, and control-flow evidence remain host-owned.']
|
|
429
429
|
}),
|
|
430
|
+
nativeParserAstFormatProfile('java-ast', {
|
|
431
|
+
aliases: ['javac', 'javac-tree', 'jdt', 'eclipse-jdt', 'javaparser', 'java-parser'],
|
|
432
|
+
kind: 'compiler-ast',
|
|
433
|
+
languages: ['java'],
|
|
434
|
+
parserAdapters: ['javac', 'jdt', 'javaparser', 'java-ast'],
|
|
435
|
+
exactness: 'exact-parser-ast',
|
|
436
|
+
sourceRangeModel: 'java-source-range',
|
|
437
|
+
preservesTokens: false,
|
|
438
|
+
preservesTrivia: false,
|
|
439
|
+
supportsErrorRecovery: true,
|
|
440
|
+
notes: ['Java compiler/parser ASTs expose package/import/type/member declarations and source ranges; classpath/module-path, bindings, annotation processors, generated sources, Lombok expansion, comments/trivia, and control-flow evidence remain host-owned.']
|
|
441
|
+
}),
|
|
430
442
|
nativeParserAstFormatProfile('tree-sitter', {
|
|
431
443
|
kind: 'concrete-syntax-tree',
|
|
432
444
|
languages: ['mixed'],
|
|
@@ -2855,6 +2867,71 @@ export function createGoAstNativeImporterAdapter(options = {}) {
|
|
|
2855
2867
|
};
|
|
2856
2868
|
}
|
|
2857
2869
|
|
|
2870
|
+
export function createJavaAstNativeImporterAdapter(options = {}) {
|
|
2871
|
+
return {
|
|
2872
|
+
id: options.id ?? 'frontier.java-ast-native-importer',
|
|
2873
|
+
language: options.language ?? 'java',
|
|
2874
|
+
parser: options.parser ?? 'javac',
|
|
2875
|
+
version: options.version,
|
|
2876
|
+
capabilities: uniqueStrings(['nativeAst', 'semanticIndex', 'sourceMaps', 'diagnostics', ...(options.capabilities ?? [])]),
|
|
2877
|
+
coverage: nativeImporterAdapterCoverage({
|
|
2878
|
+
exactness: 'exact-parser-ast',
|
|
2879
|
+
exactAst: true,
|
|
2880
|
+
tokens: false,
|
|
2881
|
+
trivia: false,
|
|
2882
|
+
diagnostics: true,
|
|
2883
|
+
sourceRanges: true,
|
|
2884
|
+
generatedRanges: false,
|
|
2885
|
+
semanticCoverage: declarationSemanticCoverage(),
|
|
2886
|
+
notes: [
|
|
2887
|
+
'Normalizes caller-owned javac/JDT/JavaParser-shaped Java ASTs into native AST nodes and declaration-level semantic index records.',
|
|
2888
|
+
'Java AST imports do not resolve overloads, bindings, annotation processors, generated Lombok code, classpaths, modules, bytecode, comments/trivia, or control flow by themselves; attach host evidence for those claims.'
|
|
2889
|
+
]
|
|
2890
|
+
}, options.coverage),
|
|
2891
|
+
supportedExtensions: options.supportedExtensions ?? ['.java'],
|
|
2892
|
+
diagnostics: options.diagnostics,
|
|
2893
|
+
parse(input) {
|
|
2894
|
+
const parsed = input.options?.ast
|
|
2895
|
+
?? input.options?.nativeAst
|
|
2896
|
+
?? input.options?.compilationUnit
|
|
2897
|
+
?? input.options?.unit
|
|
2898
|
+
?? input.options?.sourceFile
|
|
2899
|
+
?? options.ast
|
|
2900
|
+
?? options.compilationUnit
|
|
2901
|
+
?? options.unit
|
|
2902
|
+
?? options.sourceFile
|
|
2903
|
+
?? parseJavaAstSource(input, options);
|
|
2904
|
+
const root = javaAstRoot(parsed);
|
|
2905
|
+
if (!root) {
|
|
2906
|
+
return missingInjectedParserResult(input, {
|
|
2907
|
+
parser: options.parser ?? 'javac',
|
|
2908
|
+
adapterId: options.id ?? 'frontier.java-ast-native-importer',
|
|
2909
|
+
message: 'createJavaAstNativeImporterAdapter requires an injected Java AST object, parserModule.parse function, parse function, or adapterOptions.ast.'
|
|
2910
|
+
});
|
|
2911
|
+
}
|
|
2912
|
+
const parseDiagnostics = normalizeParserErrors(parsed?.errors ?? parsed?.diagnostics ?? parsed?.problems, input, {
|
|
2913
|
+
parser: options.parser ?? 'javac'
|
|
2914
|
+
});
|
|
2915
|
+
return createNativeImportFromJavaAst(root, input, {
|
|
2916
|
+
parser: options.parser ?? 'javac',
|
|
2917
|
+
astFormat: 'java-ast',
|
|
2918
|
+
maxNodes: options.maxNodes,
|
|
2919
|
+
diagnostics: parseDiagnostics,
|
|
2920
|
+
javaVersion: options.javaVersion ?? input.options?.javaVersion ?? parsed?.javaVersion,
|
|
2921
|
+
sourceLevel: options.sourceLevel ?? input.options?.sourceLevel ?? parsed?.sourceLevel,
|
|
2922
|
+
classPath: input.options?.classPath ?? options.classPath ?? parsed?.classPath,
|
|
2923
|
+
modulePath: input.options?.modulePath ?? options.modulePath ?? parsed?.modulePath,
|
|
2924
|
+
generated: input.options?.generated ?? options.generated ?? parsed?.generated,
|
|
2925
|
+
annotationProcessing: input.options?.annotationProcessing ?? options.annotationProcessing ?? parsed?.annotationProcessing,
|
|
2926
|
+
bindingEvidence: input.options?.bindingEvidence ?? options.bindingEvidence ?? parsed?.bindingEvidence,
|
|
2927
|
+
positionResolver: input.options?.positionResolver ?? options.positionResolver,
|
|
2928
|
+
lineMap: input.options?.lineMap ?? options.lineMap ?? parsed?.lineMap,
|
|
2929
|
+
includeAnnotations: options.includeAnnotations ?? input.options?.includeAnnotations
|
|
2930
|
+
});
|
|
2931
|
+
}
|
|
2932
|
+
};
|
|
2933
|
+
}
|
|
2934
|
+
|
|
2858
2935
|
export function createTreeSitterNativeImporterAdapter(options = {}) {
|
|
2859
2936
|
return {
|
|
2860
2937
|
id: options.id ?? `frontier.tree-sitter-${idFragment(options.language ?? 'source')}-native-importer`,
|
|
@@ -7297,6 +7374,7 @@ function parserAstFormatIdForParser(parser) {
|
|
|
7297
7374
|
if (text.includes('rust-analyzer') || text.includes('rowan')) return 'rust-analyzer-rowan';
|
|
7298
7375
|
if (text.includes('clang') || text.includes('libclang')) return 'clang-ast-json';
|
|
7299
7376
|
if (text === 'go' || text.includes('go-parser') || text.includes('go-ast') || text.includes('go/parser') || text.includes('go/ast')) return 'go-ast';
|
|
7377
|
+
if (text === 'java' || text.includes('javac') || text.includes('jdt') || text.includes('javaparser') || text.includes('java-parser') || text.includes('java-ast')) return 'java-ast';
|
|
7300
7378
|
if (text.includes('tree-sitter') || text.includes('treesitter')) return 'tree-sitter';
|
|
7301
7379
|
if (text.includes('babel')) return 'babel';
|
|
7302
7380
|
if (text.includes('estree')) return 'estree';
|
|
@@ -8378,6 +8456,23 @@ function parseGoAstSource(input, options) {
|
|
|
8378
8456
|
return parse(input.sourceText, parserOptions);
|
|
8379
8457
|
}
|
|
8380
8458
|
|
|
8459
|
+
function parseJavaAstSource(input, options) {
|
|
8460
|
+
const parse = options.parse ?? options.parserModule?.parse ?? options.javac?.parse ?? options.jdt?.parse ?? options.javaParser?.parse;
|
|
8461
|
+
if (typeof parse !== 'function') return undefined;
|
|
8462
|
+
const parserOptions = {
|
|
8463
|
+
sourcePath: input.sourcePath,
|
|
8464
|
+
filename: input.sourcePath,
|
|
8465
|
+
javaVersion: options.javaVersion ?? input.options?.javaVersion,
|
|
8466
|
+
sourceLevel: options.sourceLevel ?? input.options?.sourceLevel,
|
|
8467
|
+
classPath: options.classPath ?? input.options?.classPath,
|
|
8468
|
+
modulePath: options.modulePath ?? input.options?.modulePath,
|
|
8469
|
+
includeAnnotations: options.includeAnnotations ?? input.options?.includeAnnotations,
|
|
8470
|
+
...(options.parserOptions ?? {}),
|
|
8471
|
+
...(input.options?.parserOptions ?? {})
|
|
8472
|
+
};
|
|
8473
|
+
return parse(input.sourceText, parserOptions);
|
|
8474
|
+
}
|
|
8475
|
+
|
|
8381
8476
|
function createNativeImportFromSyntaxAst(ast, input, options) {
|
|
8382
8477
|
const root = normalizeSyntaxAstRoot(ast, options.astFormat);
|
|
8383
8478
|
if (!root) {
|
|
@@ -8569,6 +8664,45 @@ function createNativeImportFromGoAst(root, input, options) {
|
|
|
8569
8664
|
};
|
|
8570
8665
|
}
|
|
8571
8666
|
|
|
8667
|
+
function createNativeImportFromJavaAst(root, input, options) {
|
|
8668
|
+
const context = createAstNormalizationContext(input, options);
|
|
8669
|
+
visitJavaAstNode(root, context, 'root');
|
|
8670
|
+
if (context.truncated) {
|
|
8671
|
+
context.losses.push(truncatedAstLoss(input, context, options));
|
|
8672
|
+
}
|
|
8673
|
+
if (options.generated && !context.losses.some((loss) => loss.kind === 'generatedCode')) {
|
|
8674
|
+
context.losses.push(javaGeneratedCodeLoss(input, context.rootId, undefined, options));
|
|
8675
|
+
}
|
|
8676
|
+
const semantic = semanticIndexFromNativeDeclarations(context.declarations, input, options);
|
|
8677
|
+
return {
|
|
8678
|
+
rootId: context.rootId,
|
|
8679
|
+
nodes: context.nodes,
|
|
8680
|
+
semanticIndex: semantic.semanticIndex,
|
|
8681
|
+
mappings: semantic.mappings,
|
|
8682
|
+
losses: mergeNativeLosses(context.losses, options.diagnostics?.map((diagnostic, index) => adapterDiagnosticToLoss(diagnostic, index, {
|
|
8683
|
+
id: input.adapterId,
|
|
8684
|
+
version: input.adapterVersion
|
|
8685
|
+
}, input)) ?? []),
|
|
8686
|
+
evidence: semantic.evidence,
|
|
8687
|
+
diagnostics: options.diagnostics,
|
|
8688
|
+
metadata: {
|
|
8689
|
+
astFormat: options.astFormat,
|
|
8690
|
+
parser: options.parser,
|
|
8691
|
+
javaVersion: options.javaVersion,
|
|
8692
|
+
sourceLevel: options.sourceLevel,
|
|
8693
|
+
classPathEvidence: javaPathEvidenceSummary(options.classPath),
|
|
8694
|
+
modulePathEvidence: javaPathEvidenceSummary(options.modulePath),
|
|
8695
|
+
annotationProcessing: javaAnnotationProcessingSummary(options.annotationProcessing),
|
|
8696
|
+
bindingEvidence: javaBindingEvidenceSummary(options.bindingEvidence),
|
|
8697
|
+
generated: options.generated,
|
|
8698
|
+
includeAnnotations: Boolean(options.includeAnnotations),
|
|
8699
|
+
normalizedNodeCount: Object.keys(context.nodes).length,
|
|
8700
|
+
declarationCount: context.declarations.length,
|
|
8701
|
+
truncated: context.truncated
|
|
8702
|
+
}
|
|
8703
|
+
};
|
|
8704
|
+
}
|
|
8705
|
+
|
|
8572
8706
|
function createNativeImportFromTreeSitter(root, input, options) {
|
|
8573
8707
|
const context = createAstNormalizationContext(input, options);
|
|
8574
8708
|
visitTreeSitterNode(root, context, 'root');
|
|
@@ -8972,6 +9106,78 @@ function visitGoAstNode(node, context, propertyPath) {
|
|
|
8972
9106
|
return id;
|
|
8973
9107
|
}
|
|
8974
9108
|
|
|
9109
|
+
function visitJavaAstNode(node, context, propertyPath) {
|
|
9110
|
+
if (!isJavaAstNode(node) || context.truncated) return undefined;
|
|
9111
|
+
if (context.objectIds.has(node)) return context.objectIds.get(node);
|
|
9112
|
+
if (context.counter >= context.maxNodes) {
|
|
9113
|
+
context.truncated = true;
|
|
9114
|
+
return undefined;
|
|
9115
|
+
}
|
|
9116
|
+
const kind = javaAstKind(node);
|
|
9117
|
+
const span = spanFromJavaAstNode(node, context.input, context.options);
|
|
9118
|
+
const id = nativeNodeId(context, kind, { start: { line: span?.startLine, column: span?.startColumn } }, propertyPath);
|
|
9119
|
+
context.objectIds.set(node, id);
|
|
9120
|
+
if (!context.rootId) context.rootId = id;
|
|
9121
|
+
const children = [];
|
|
9122
|
+
for (const [field, value] of javaAstChildEntries(node, kind)) {
|
|
9123
|
+
if (Array.isArray(value)) {
|
|
9124
|
+
value.forEach((entry, index) => {
|
|
9125
|
+
const childId = visitJavaAstNode(entry, context, `${propertyPath}.${field}[${index}]`);
|
|
9126
|
+
if (childId) children.push(childId);
|
|
9127
|
+
});
|
|
9128
|
+
} else {
|
|
9129
|
+
const childId = visitJavaAstNode(value, context, `${propertyPath}.${field}`);
|
|
9130
|
+
if (childId) children.push(childId);
|
|
9131
|
+
}
|
|
9132
|
+
}
|
|
9133
|
+
const declarations = javaAstDeclarations(node, kind, id, context.input);
|
|
9134
|
+
const declaration = declarations[0];
|
|
9135
|
+
const nativeNode = {
|
|
9136
|
+
id,
|
|
9137
|
+
kind,
|
|
9138
|
+
languageKind: `${context.input.language}.${kind}`,
|
|
9139
|
+
span,
|
|
9140
|
+
value: declaration?.name ?? javaAstNodeValue(node),
|
|
9141
|
+
fields: primitiveJavaAstFields(node, kind),
|
|
9142
|
+
children,
|
|
9143
|
+
metadata: {
|
|
9144
|
+
astFormat: context.options.astFormat,
|
|
9145
|
+
propertyPath,
|
|
9146
|
+
positionKind: javaAstPositionKind(node),
|
|
9147
|
+
parser: context.options.parser
|
|
9148
|
+
}
|
|
9149
|
+
};
|
|
9150
|
+
context.nodes[id] = nativeNode;
|
|
9151
|
+
for (const entry of declarations) {
|
|
9152
|
+
context.declarations.push({ ...entry, nativeNode });
|
|
9153
|
+
}
|
|
9154
|
+
if (javaRecoveredAstKind(kind) || javaProblemNode(node, kind)) {
|
|
9155
|
+
context.losses.push({
|
|
9156
|
+
id: `loss_${idFragment(id)}_java_recovered_node`,
|
|
9157
|
+
severity: 'error',
|
|
9158
|
+
phase: 'parse',
|
|
9159
|
+
sourceFormat: context.input.language,
|
|
9160
|
+
kind: 'unsupportedSyntax',
|
|
9161
|
+
message: 'Java parser reported a recovered, erroneous, malformed, or problem node; semantic import is partial until syntax errors are resolved.',
|
|
9162
|
+
span,
|
|
9163
|
+
nodeId: id,
|
|
9164
|
+
metadata: {
|
|
9165
|
+
parser: context.options.parser,
|
|
9166
|
+
astFormat: context.options.astFormat,
|
|
9167
|
+
nodeKind: kind
|
|
9168
|
+
}
|
|
9169
|
+
});
|
|
9170
|
+
}
|
|
9171
|
+
if (javaGeneratedCodeMarker(node, kind) || javaLombokAnnotationMarker(node, kind)) {
|
|
9172
|
+
context.losses.push(javaGeneratedCodeLoss(context.input, id, span, context.options, {
|
|
9173
|
+
nodeKind: kind,
|
|
9174
|
+
generatedMarker: javaGeneratedCodeMarker(node, kind),
|
|
9175
|
+
lombokMarker: javaLombokAnnotationMarker(node, kind)
|
|
9176
|
+
}));
|
|
9177
|
+
}
|
|
9178
|
+
return id;
|
|
9179
|
+
}
|
|
9180
|
+
|
|
8975
9181
|
function visitTreeSitterNode(node, context, propertyPath) {
|
|
8976
9182
|
if (!node || typeof node !== 'object' || context.truncated) return undefined;
|
|
8977
9183
|
if (context.objectIds.has(node)) return context.objectIds.get(node);
|
|
@@ -11207,6 +11413,489 @@ function goTypeEvidenceSummary(value) {
|
|
|
11207
11413
|
return Object.keys(summary).length ? summary : { present: true };
|
|
11208
11414
|
}
|
|
11209
11415
|
|
|
11416
|
+
function javaAstRoot(value) {
|
|
11417
|
+
if (!value || typeof value !== 'object') return undefined;
|
|
11418
|
+
if (isJavaAstNode(value)) return value;
|
|
11419
|
+
if (isJavaAstNode(value.ast)) return value.ast;
|
|
11420
|
+
if (isJavaAstNode(value.root)) return value.root;
|
|
11421
|
+
if (isJavaAstNode(value.compilationUnit)) return value.compilationUnit;
|
|
11422
|
+
if (isJavaAstNode(value.unit)) return value.unit;
|
|
11423
|
+
if (isJavaAstNode(value.sourceFile)) return value.sourceFile;
|
|
11424
|
+
if (Array.isArray(value.types) || Array.isArray(value.imports) || value.packageDeclaration || value.package) {
|
|
11425
|
+
return { kind: 'CompilationUnit', ...value };
|
|
11426
|
+
}
|
|
11427
|
+
return undefined;
|
|
11428
|
+
}
|
|
11429
|
+
|
|
11430
|
+
function isJavaAstNode(value) {
|
|
11431
|
+
return Boolean(value && typeof value === 'object' && typeof javaAstKind(value) === 'string');
|
|
11432
|
+
}
|
|
11433
|
+
|
|
11434
|
+
function javaAstKind(node) {
|
|
11435
|
+
if (!node || typeof node !== 'object') return undefined;
|
|
11436
|
+
const declared = node.kind ?? node._type ?? node.type ?? node.nodeType ?? node.astKind ?? node.treeKind ?? node.nodeKind;
|
|
11437
|
+
if (typeof declared === 'string') return normalizeJavaAstKind(declared);
|
|
11438
|
+
if (Array.isArray(node.imports) || Array.isArray(node.types) || node.packageDeclaration || node.package) return 'CompilationUnit';
|
|
11439
|
+
if (node.name && (node.members || node.bodyDeclarations || node.extends || node.implements || node.permittedTypes)) return 'ClassDeclaration';
|
|
11440
|
+
if (node.name && (node.returnType || node.parameters || node.body) && (node.modifiers || node.thrownExceptions || node.throws)) return 'MethodDeclaration';
|
|
11441
|
+
if (node.variables || node.fragments) return 'FieldDeclaration';
|
|
11442
|
+
if (node.name && node.type && (node.initializer !== undefined || node.extraDimensions !== undefined)) return 'VariableDeclarator';
|
|
11443
|
+
return undefined;
|
|
11444
|
+
}
|
|
11445
|
+
|
|
11446
|
+
function normalizeJavaAstKind(kind) {
|
|
11447
|
+
const text = String(kind).replace(/^(?:com\.sun\.source\.tree\.|org\.eclipse\.jdt\.core\.dom\.|com\.github\.javaparser\.ast\.)/, '');
|
|
11448
|
+
const compact = text.replace(/[_\s.-]+/g, '').replace(/Tree$/, '').toLowerCase();
|
|
11449
|
+
if (compact === 'compilationunit' || compact === 'compilationunitnode') return 'CompilationUnit';
|
|
11450
|
+
if (compact === 'package' || compact === 'packagedeclaration' || compact === 'packageclause') return 'PackageDeclaration';
|
|
11451
|
+
if (compact === 'import' || compact === 'importdeclaration') return 'ImportDeclaration';
|
|
11452
|
+
if (compact === 'class' || compact === 'classdeclaration' || compact === 'normalclassdeclaration' || compact === 'classorinterfacedeclaration') return 'ClassDeclaration';
|
|
11453
|
+
if (compact === 'interface' || compact === 'interfacedeclaration' || compact === 'normalinterfacedeclaration') return 'InterfaceDeclaration';
|
|
11454
|
+
if (compact === 'enum' || compact === 'enumdeclaration') return 'EnumDeclaration';
|
|
11455
|
+
if (compact === 'record' || compact === 'recorddeclaration') return 'RecordDeclaration';
|
|
11456
|
+
if (compact === 'annotation' || compact === 'annotationdeclaration' || compact === 'annotationtypedeclaration' || compact === 'annotationinterface') return 'AnnotationDeclaration';
|
|
11457
|
+
if (compact === 'method' || compact === 'methoddeclaration') return 'MethodDeclaration';
|
|
11458
|
+
if (compact === 'constructor' || compact === 'constructordeclaration') return 'ConstructorDeclaration';
|
|
11459
|
+
if (compact === 'variable' || compact === 'variabledeclaration' || compact === 'variabledeclarator' || compact === 'variabletree') return 'VariableDeclarator';
|
|
11460
|
+
if (compact === 'field' || compact === 'fielddeclaration') return 'FieldDeclaration';
|
|
11461
|
+
if (compact === 'enumconstant' || compact === 'enumconstantdeclaration') return 'EnumConstantDeclaration';
|
|
11462
|
+
if (compact === 'parameter' || compact === 'formalparameter' || compact === 'receiverparameter') return 'Parameter';
|
|
11463
|
+
if (compact === 'modifiers' || compact === 'modifier') return 'Modifiers';
|
|
11464
|
+
if (compact === 'markerannotationexpr' || compact === 'singlememberannotationexpr' || compact === 'normalannotationexpr' || compact === 'annotationexpr') return 'Annotation';
|
|
11465
|
+
if (compact === 'erroneous' || compact === 'erroneoustree' || compact === 'malformed' || compact === 'error' || compact === 'errornode' || compact === 'problem' || compact === 'problemtree' || compact === 'recovered') return 'Erroneous';
|
|
11466
|
+
if (/^[A-Z0-9_]+$/.test(text)) return text.toLowerCase().split('_').map(upperFirst).join('');
|
|
11467
|
+
return text;
|
|
11468
|
+
}
|
|
11469
|
+
|
|
11470
|
+
function ignoredJavaAstField(key) {
|
|
11471
|
+
return key === '_type'
|
|
11472
|
+
|| key === 'type'
|
|
11473
|
+
|| key === 'kind'
|
|
11474
|
+
|| key === 'nodeType'
|
|
11475
|
+
|| key === 'astKind'
|
|
11476
|
+
|| key === 'treeKind'
|
|
11477
|
+
|| key === 'nodeKind'
|
|
11478
|
+
|| key === 'parent'
|
|
11479
|
+
|| key === 'parentKind'
|
|
11480
|
+
|| key === 'parentField'
|
|
11481
|
+
|| key === 'binding'
|
|
11482
|
+
|| key === 'resolvedBinding'
|
|
11483
|
+
|| key === 'symbol'
|
|
11484
|
+
|| key === 'scope'
|
|
11485
|
+
|| key === 'range'
|
|
11486
|
+
|| key === 'loc'
|
|
11487
|
+
|| key === 'location'
|
|
11488
|
+
|| key === 'pos'
|
|
11489
|
+
|| key === 'end'
|
|
11490
|
+
|| key === 'start'
|
|
11491
|
+
|| key === 'endPosition'
|
|
11492
|
+
|| key === 'startPosition'
|
|
11493
|
+
|| key === 'length'
|
|
11494
|
+
|| key === 'name'
|
|
11495
|
+
|| key === 'identifier'
|
|
11496
|
+
|| key === 'simpleName'
|
|
11497
|
+
|| key === 'qualifiedName';
|
|
11498
|
+
}
|
|
11499
|
+
|
|
11500
|
+
function primitiveJavaAstFields(node, kind) {
|
|
11501
|
+
const fields = { kind };
|
|
11502
|
+
const name = javaAstDeclarationName(node);
|
|
11503
|
+
if (name) fields.name = name;
|
|
11504
|
+
const importPath = javaAstImportPath(node);
|
|
11505
|
+
if (importPath) fields.importPath = importPath;
|
|
11506
|
+
const type = javaAstTypeName(node.type ?? node.typeName ?? node.returnType ?? node.elementType);
|
|
11507
|
+
if (type) fields.type = type;
|
|
11508
|
+
const packageName = javaAstPackageName(node);
|
|
11509
|
+
if (packageName) fields.packageName = packageName;
|
|
11510
|
+
const modifiers = javaAstModifierNames(node);
|
|
11511
|
+
if (modifiers.length) fields.modifiers = modifiers.join(',');
|
|
11512
|
+
if (node.static === true || node.isStatic === true) fields.static = true;
|
|
11513
|
+
if (node.default === true || node.isDefault === true) fields.default = true;
|
|
11514
|
+
if (node.generated === true || node.Generated === true) fields.generated = true;
|
|
11515
|
+
if (typeof node.binaryName === 'string') fields.binaryName = node.binaryName;
|
|
11516
|
+
if (typeof node.qualifiedName === 'string') fields.qualifiedName = node.qualifiedName;
|
|
11517
|
+
if (Array.isArray(node.parameters)) fields.parameterCount = node.parameters.length;
|
|
11518
|
+
if (Array.isArray(node.throws ?? node.thrownExceptions)) fields.throwsCount = (node.throws ?? node.thrownExceptions).length;
|
|
11519
|
+
return fields;
|
|
11520
|
+
}
|
|
11521
|
+
|
|
11522
|
+
function spanFromJavaAstNode(node, input, options = {}) {
|
|
11523
|
+
const direct = spanFromJavaRange(node.range ?? node.loc ?? node.location, input)
|
|
11524
|
+
?? spanFromJavaLineFields(node, input);
|
|
11525
|
+
if (direct) return direct;
|
|
11526
|
+
const start = javaAstPosition(
|
|
11527
|
+
node.begin ?? node.start ?? node.pos ?? node.position ?? node.startPosition ?? node.name?.range?.begin ?? node.name?.loc?.start,
|
|
11528
|
+
options
|
|
11529
|
+
);
|
|
11530
|
+
const end = javaAstPosition(
|
|
11531
|
+
node.end ?? node.endPosition ?? node.stopPosition ?? node.finishPosition ?? node.name?.range?.end ?? node.name?.loc?.end,
|
|
11532
|
+
options
|
|
11533
|
+
);
|
|
11534
|
+
const sourceRange = node.sourceRange ?? node.rangeInfo;
|
|
11535
|
+
const sourceStart = javaAstPosition(
|
|
11536
|
+
sourceRange?.start ?? sourceRange?.offset ?? sourceRange?.startPosition,
|
|
11537
|
+
options
|
|
11538
|
+
);
|
|
11539
|
+
const sourceEnd = javaAstPosition(
|
|
11540
|
+
typeof sourceRange?.offset === 'number' && typeof sourceRange?.length === 'number'
|
|
11541
|
+
? sourceRange.offset + sourceRange.length
|
|
11542
|
+
: sourceRange?.end ?? sourceRange?.endPosition,
|
|
11543
|
+
options
|
|
11544
|
+
);
|
|
11545
|
+
const resolvedStart = start ?? sourceStart;
|
|
11546
|
+
const resolvedEnd = end ?? sourceEnd;
|
|
11547
|
+
if (!resolvedStart) return undefined;
|
|
11548
|
+
return {
|
|
11549
|
+
sourceId: input.sourceHash,
|
|
11550
|
+
path: resolvedStart.path ?? resolvedEnd?.path ?? input.sourcePath,
|
|
11551
|
+
startLine: resolvedStart.line,
|
|
11552
|
+
startColumn: resolvedStart.column,
|
|
11553
|
+
endLine: resolvedEnd?.line,
|
|
11554
|
+
endColumn: resolvedEnd?.column
|
|
11555
|
+
};
|
|
11556
|
+
}
|
|
11557
|
+
|
|
11558
|
+
function spanFromJavaRange(range, input) {
|
|
11559
|
+
if (!range || typeof range !== 'object') return undefined;
|
|
11560
|
+
const start = range.begin ?? range.start;
|
|
11561
|
+
const end = range.end ?? range.stop;
|
|
11562
|
+
if (start && typeof start === 'object') {
|
|
11563
|
+
const startLine = start.line ?? start.Line;
|
|
11564
|
+
const startColumn = start.column ?? start.col ?? start.Column ?? start.character;
|
|
11565
|
+
const endLine = end?.line ?? end?.Line;
|
|
11566
|
+
const endColumn = end?.column ?? end?.col ?? end?.Column ?? end?.character;
|
|
11567
|
+
if (typeof startLine === 'number') {
|
|
11568
|
+
return {
|
|
11569
|
+
sourceId: input.sourceHash,
|
|
11570
|
+
path: start.path ?? start.file ?? end?.path ?? end?.file ?? input.sourcePath,
|
|
11571
|
+
startLine,
|
|
11572
|
+
startColumn,
|
|
11573
|
+
endLine,
|
|
11574
|
+
endColumn
|
|
11575
|
+
};
|
|
11576
|
+
}
|
|
11577
|
+
}
|
|
11578
|
+
return undefined;
|
|
11579
|
+
}
|
|
11580
|
+
|
|
11581
|
+
function spanFromJavaLineFields(node, input) {
|
|
11582
|
+
const startLine = node.startLine ?? node.line ?? node.beginLine ?? node.lineno;
|
|
11583
|
+
if (typeof startLine !== 'number') return undefined;
|
|
11584
|
+
return {
|
|
11585
|
+
sourceId: input.sourceHash,
|
|
11586
|
+
path: node.path ?? node.file ?? node.filename ?? input.sourcePath,
|
|
11587
|
+
startLine,
|
|
11588
|
+
startColumn: node.startColumn ?? node.column ?? node.beginColumn ?? node.col,
|
|
11589
|
+
endLine: node.endLine ?? node.end_lineno,
|
|
11590
|
+
endColumn: node.endColumn ?? node.end_col_offset
|
|
11591
|
+
};
|
|
11592
|
+
}
|
|
11593
|
+
|
|
11594
|
+
function javaAstPosition(value, options = {}) {
|
|
11595
|
+
if (value === undefined || value === null) return undefined;
|
|
11596
|
+
if (typeof value === 'object') {
|
|
11597
|
+
const position = value.position ?? value.Position ?? value.pos ?? value.start ?? value;
|
|
11598
|
+
const line = position.line ?? position.Line ?? position.lineno;
|
|
11599
|
+
const column = position.column ?? position.Column ?? position.col ?? position.character;
|
|
11600
|
+
if (typeof line === 'number') {
|
|
11601
|
+
return {
|
|
11602
|
+
path: position.path ?? position.file ?? position.filename ?? position.Filename,
|
|
11603
|
+
line,
|
|
11604
|
+
column: typeof column === 'number' ? column : undefined
|
|
11605
|
+
};
|
|
11606
|
+
}
|
|
11607
|
+
}
|
|
11608
|
+
const resolver = typeof options.positionResolver === 'function'
|
|
11609
|
+
? options.positionResolver
|
|
11610
|
+
: typeof options.lineMap?.position === 'function'
|
|
11611
|
+
? options.lineMap.position.bind(options.lineMap)
|
|
11612
|
+
: typeof options.lineMap?.getPosition === 'function'
|
|
11613
|
+
? options.lineMap.getPosition.bind(options.lineMap)
|
|
11614
|
+
: typeof options.lineMap?.getLineNumber === 'function'
|
|
11615
|
+
? (offset) => ({
|
|
11616
|
+
line: options.lineMap.getLineNumber(offset),
|
|
11617
|
+
column: typeof options.lineMap.getColumnNumber === 'function' ? options.lineMap.getColumnNumber(offset) : undefined
|
|
11618
|
+
})
|
|
11619
|
+
: undefined;
|
|
11620
|
+
if (resolver) {
|
|
11621
|
+
const resolved = resolver(value);
|
|
11622
|
+
if (resolved !== value) return javaAstPosition(resolved, options);
|
|
11623
|
+
}
|
|
11624
|
+
return undefined;
|
|
11625
|
+
}
|
|
11626
|
+
|
|
11627
|
+
function javaAstPositionKind(node) {
|
|
11628
|
+
if (node.range?.begin || node.loc?.start) return 'line-column-range';
|
|
11629
|
+
if (typeof node.startLine === 'number' || typeof node.line === 'number') return 'line-column-fields';
|
|
11630
|
+
if (node.pos !== undefined || node.startPosition !== undefined) return 'offset-position';
|
|
11631
|
+
if (node.sourceRange) return 'source-range';
|
|
11632
|
+
return undefined;
|
|
11633
|
+
}
|
|
11634
|
+
|
|
11635
|
+
function javaAstDeclarations(node, kind, nativeNodeId, input) {
|
|
11636
|
+
if (kind === 'PackageDeclaration') {
|
|
11637
|
+
const name = javaAstPackageName(node) ?? javaAstDeclarationName(node);
|
|
11638
|
+
return name ? [declarationRecord(input, nativeNodeId, name, 'module', 'definition')] : [];
|
|
11639
|
+
}
|
|
11640
|
+
if (kind === 'ImportDeclaration') {
|
|
11641
|
+
const name = javaAstImportPath(node);
|
|
11642
|
+
return name ? [declarationRecord(input, nativeNodeId, name, 'module', 'import')] : [];
|
|
11643
|
+
}
|
|
11644
|
+
if (javaTypeDeclarationKind(kind)) {
|
|
11645
|
+
const name = javaAstDeclarationName(node);
|
|
11646
|
+
return name ? [declarationRecord(input, nativeNodeId, name, javaTypeDeclarationSymbolKind(kind), 'definition')] : [];
|
|
11647
|
+
}
|
|
11648
|
+
if (kind === 'MethodDeclaration' || kind === 'ConstructorDeclaration') {
|
|
11649
|
+
const name = javaAstDeclarationName(node);
|
|
11650
|
+
if (!name) return [];
|
|
11651
|
+
return [declarationRecord(input, nativeNodeId, name, 'method', javaAstHasBody(node) ? 'definition' : 'declaration')];
|
|
11652
|
+
}
|
|
11653
|
+
if (kind === 'FieldDeclaration') {
|
|
11654
|
+
return javaAstFieldNames(node).map((name) => declarationRecord(input, nativeNodeId, name, 'property', 'definition'));
|
|
11655
|
+
}
|
|
11656
|
+
if (kind === 'VariableDeclarator') {
|
|
11657
|
+
if (node.parentField === 'parameters' || node.parentKind === 'MethodDeclaration' || node.parentKind === 'ConstructorDeclaration') return [];
|
|
11658
|
+
const name = javaAstDeclarationName(node);
|
|
11659
|
+
if (!name) return [];
|
|
11660
|
+
const symbolKind = node.parentKind === 'FieldDeclaration' || javaTypeDeclarationKind(node.parentKind) ? 'property' : 'variable';
|
|
11661
|
+
return [declarationRecord(input, nativeNodeId, name, symbolKind, 'definition')];
|
|
11662
|
+
}
|
|
11663
|
+
if (kind === 'EnumConstantDeclaration') {
|
|
11664
|
+
const name = javaAstDeclarationName(node);
|
|
11665
|
+
return name ? [declarationRecord(input, nativeNodeId, name, 'enumMember', 'definition')] : [];
|
|
11666
|
+
}
|
|
11667
|
+
return [];
|
|
11668
|
+
}
|
|
11669
|
+
|
|
11670
|
+
function javaAstChildEntries(node, kind = javaAstKind(node)) {
|
|
11671
|
+
const fieldNames = Object.keys(node).filter((key) => !ignoredJavaAstField(key));
|
|
11672
|
+
const entries = [];
|
|
11673
|
+
for (const field of fieldNames) {
|
|
11674
|
+
const value = node[field];
|
|
11675
|
+
if (Array.isArray(value)) {
|
|
11676
|
+
entries.push([field, value.map((entry) => javaAstChildWithParent(entry, kind, field))]);
|
|
11677
|
+
continue;
|
|
11678
|
+
}
|
|
11679
|
+
if (value && typeof value === 'object') {
|
|
11680
|
+
entries.push([field, javaAstChildWithParent(value, kind, field)]);
|
|
11681
|
+
}
|
|
11682
|
+
}
|
|
11683
|
+
return entries.filter(([, value]) => Array.isArray(value)
|
|
11684
|
+
? value.some(isJavaAstNode)
|
|
11685
|
+
: isJavaAstNode(value));
|
|
11686
|
+
}
|
|
11687
|
+
|
|
11688
|
+
function javaAstChildWithParent(entry, parentKind, parentField) {
|
|
11689
|
+
if (!entry || typeof entry !== 'object' || Array.isArray(entry)) return entry;
|
|
11690
|
+
if (!isJavaAstNode(entry)) return entry;
|
|
11691
|
+
return { parentKind, parentField, ...entry };
|
|
11692
|
+
}
|
|
11693
|
+
|
|
11694
|
+
function javaAstNodeValue(node) {
|
|
11695
|
+
return javaAstDeclarationName(node)
|
|
11696
|
+
?? javaAstImportPath(node)
|
|
11697
|
+
?? javaAstPackageName(node)
|
|
11698
|
+
?? javaAstTypeName(node.type ?? node.returnType ?? node.elementType)
|
|
11699
|
+
?? javaAstLiteralValue(node);
|
|
11700
|
+
}
|
|
11701
|
+
|
|
11702
|
+
function javaAstDeclarationName(node) {
|
|
11703
|
+
if (!node || typeof node !== 'object') return undefined;
|
|
11704
|
+
for (const key of ['name', 'identifier', 'simpleName', 'qualifiedName', 'id']) {
|
|
11705
|
+
const value = node[key];
|
|
11706
|
+
const name = javaAstName(value);
|
|
11707
|
+
if (name) return name;
|
|
11708
|
+
}
|
|
11709
|
+
if (node.declaration && typeof node.declaration === 'object') return javaAstDeclarationName(node.declaration);
|
|
11710
|
+
return undefined;
|
|
11711
|
+
}
|
|
11712
|
+
|
|
11713
|
+
function javaAstName(value) {
|
|
11714
|
+
if (!value) return undefined;
|
|
11715
|
+
if (typeof value === 'string') return value;
|
|
11716
|
+
if (typeof value.identifier === 'string') return value.identifier;
|
|
11717
|
+
if (typeof value.name === 'string') return value.name;
|
|
11718
|
+
if (typeof value.simpleName === 'string') return value.simpleName;
|
|
11719
|
+
if (typeof value.qualifiedName === 'string') return value.qualifiedName;
|
|
11720
|
+
if (typeof value.fullyQualifiedName === 'string') return value.fullyQualifiedName;
|
|
11721
|
+
if (typeof value.id === 'string') return value.id;
|
|
11722
|
+
if (typeof value.value === 'string') return value.value;
|
|
11723
|
+
if (value.name && value.name !== value) return javaAstName(value.name);
|
|
11724
|
+
if (value.identifier && value.identifier !== value) return javaAstName(value.identifier);
|
|
11725
|
+
return undefined;
|
|
11726
|
+
}
|
|
11727
|
+
|
|
11728
|
+
function javaAstPackageName(node) {
|
|
11729
|
+
if (!node || typeof node !== 'object') return undefined;
|
|
11730
|
+
return javaAstName(node.packageName ?? node.packageDeclaration ?? node.package ?? node.name);
|
|
11731
|
+
}
|
|
11732
|
+
|
|
11733
|
+
function javaAstImportPath(node) {
|
|
11734
|
+
if (!node || typeof node !== 'object') return undefined;
|
|
11735
|
+
const candidate = node.qualifiedIdentifier ?? node.qualifiedName ?? node.path ?? node.name ?? node.identifier;
|
|
11736
|
+
const path = javaAstName(candidate);
|
|
11737
|
+
if (!path) return undefined;
|
|
11738
|
+
return node.asterisk || node.wildcard || node.onDemand || node.isAsterisk ? `${path.replace(/\.\*$/, '')}.*` : path;
|
|
11739
|
+
}
|
|
11740
|
+
|
|
11741
|
+
function javaAstFieldNames(node) {
|
|
11742
|
+
const fragments = node.variables ?? node.fragments ?? node.declarators ?? node.variableDeclarators;
|
|
11743
|
+
if (Array.isArray(fragments)) return fragments.map(javaAstDeclarationName).filter(Boolean);
|
|
11744
|
+
const name = javaAstDeclarationName(node);
|
|
11745
|
+
return name ? [name] : [];
|
|
11746
|
+
}
|
|
11747
|
+
|
|
11748
|
+
function javaAstTypeName(value) {
|
|
11749
|
+
if (!value) return undefined;
|
|
11750
|
+
if (typeof value === 'string') return value;
|
|
11751
|
+
if (typeof value.name === 'string') return value.name;
|
|
11752
|
+
if (typeof value.typeName === 'string') return value.typeName;
|
|
11753
|
+
if (typeof value.qualifiedName === 'string') return value.qualifiedName;
|
|
11754
|
+
if (value.elementType) {
|
|
11755
|
+
const inner = javaAstTypeName(value.elementType);
|
|
11756
|
+
return inner ? `${inner}[]` : '[]';
|
|
11757
|
+
}
|
|
11758
|
+
if (value.componentType) {
|
|
11759
|
+
const inner = javaAstTypeName(value.componentType);
|
|
11760
|
+
return inner ? `${inner}[]` : '[]';
|
|
11761
|
+
}
|
|
11762
|
+
if (Array.isArray(value.typeArguments)) {
|
|
11763
|
+
const base = javaAstName(value.name) ?? javaAstName(value);
|
|
11764
|
+
const args = value.typeArguments.map(javaAstTypeName).filter(Boolean);
|
|
11765
|
+
return base ? `${base}<${args.join(', ')}>` : undefined;
|
|
11766
|
+
}
|
|
11767
|
+
return javaAstName(value);
|
|
11768
|
+
}
|
|
11769
|
+
|
|
11770
|
+
function javaAstModifierNames(node) {
|
|
11771
|
+
const modifiers = node.modifiers ?? node.Modifiers ?? node.flags;
|
|
11772
|
+
if (!modifiers) return [];
|
|
11773
|
+
if (Array.isArray(modifiers)) {
|
|
11774
|
+
return uniqueStrings(modifiers.map((entry) => typeof entry === 'string' ? entry : javaAstName(entry) ?? entry.keyword ?? entry.kind).filter(Boolean));
|
|
11775
|
+
}
|
|
11776
|
+
if (typeof modifiers === 'string') return uniqueStrings(modifiers.split(/\s+/).filter(Boolean));
|
|
11777
|
+
if (typeof modifiers === 'object') {
|
|
11778
|
+
return uniqueStrings(Object.entries(modifiers)
|
|
11779
|
+
.filter(([, enabled]) => enabled === true)
|
|
11780
|
+
.map(([key]) => key));
|
|
11781
|
+
}
|
|
11782
|
+
return [];
|
|
11783
|
+
}
|
|
11784
|
+
|
|
11785
|
+
function javaTypeDeclarationKind(kind) {
|
|
11786
|
+
return kind === 'ClassDeclaration'
|
|
11787
|
+
|| kind === 'InterfaceDeclaration'
|
|
11788
|
+
|| kind === 'EnumDeclaration'
|
|
11789
|
+
|| kind === 'RecordDeclaration'
|
|
11790
|
+
|| kind === 'AnnotationDeclaration';
|
|
11791
|
+
}
|
|
11792
|
+
|
|
11793
|
+
function javaTypeDeclarationSymbolKind(kind) {
|
|
11794
|
+
if (kind === 'InterfaceDeclaration' || kind === 'AnnotationDeclaration') return 'interface';
|
|
11795
|
+
if (kind === 'ClassDeclaration') return 'class';
|
|
11796
|
+
return 'type';
|
|
11797
|
+
}
|
|
11798
|
+
|
|
11799
|
+
function javaAstHasBody(node) {
|
|
11800
|
+
return Boolean(node.body || node.block || node.statements || node.defaultValue || Array.isArray(node.bodyDeclarations));
|
|
11801
|
+
}
|
|
11802
|
+
|
|
11803
|
+
function javaAstLiteralValue(node) {
|
|
11804
|
+
const value = node.value ?? node.literal ?? node.token;
|
|
11805
|
+
if (value === null || typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') return value;
|
|
11806
|
+
return undefined;
|
|
11807
|
+
}
|
|
11808
|
+
|
|
11809
|
+
function javaRecoveredAstKind(kind) {
|
|
11810
|
+
return kind === 'Erroneous'
|
|
11811
|
+
|| /Error|Erroneous|Malformed|Recovered|Problem|Missing/.test(String(kind));
|
|
11812
|
+
}
|
|
11813
|
+
|
|
11814
|
+
function javaProblemNode(node, kind) {
|
|
11815
|
+
return Boolean(node.problem || node.error || node.malformed || node.recovered || node.hasError || node.hasErrors || kind === 'Erroneous');
|
|
11816
|
+
}
|
|
11817
|
+
|
|
11818
|
+
function javaGeneratedCodeMarker(node, kind) {
|
|
11819
|
+
if (node.generated || node.Generated || node.isGenerated) return true;
|
|
11820
|
+
if (kind === 'Annotation') {
|
|
11821
|
+
const name = javaAstDeclarationName(node);
|
|
11822
|
+
if (name && /(^|\.)(Generated|GeneratedValue)$/.test(name)) return true;
|
|
11823
|
+
}
|
|
11824
|
+
const annotations = node.annotations ?? node.modifiers?.annotations ?? node.modifiers;
|
|
11825
|
+
if (Array.isArray(annotations)) {
|
|
11826
|
+
return annotations.some((annotation) => {
|
|
11827
|
+
const name = javaAstDeclarationName(annotation) ?? javaAstName(annotation);
|
|
11828
|
+
return Boolean(name && /(^|\.)(Generated|GeneratedValue)$/.test(name));
|
|
11829
|
+
});
|
|
11830
|
+
}
|
|
11831
|
+
return false;
|
|
11832
|
+
}
|
|
11833
|
+
|
|
11834
|
+
function javaLombokAnnotationMarker(node, kind) {
|
|
11835
|
+
if (kind !== 'Annotation') return false;
|
|
11836
|
+
const name = javaAstDeclarationName(node);
|
|
11837
|
+
return Boolean(name && /^(lombok\.|Data$|Value$|Builder$|Getter$|Setter$|AllArgsConstructor$|NoArgsConstructor$|RequiredArgsConstructor$)/.test(name));
|
|
11838
|
+
}
|
|
11839
|
+
|
|
11840
|
+
function javaGeneratedCodeLoss(input, nodeId, span, options = {}, metadata = {}) {
|
|
11841
|
+
return {
|
|
11842
|
+
id: `loss_${idFragment(nodeId ?? input.sourcePath ?? 'java')}_java_generated_code`,
|
|
11843
|
+
severity: 'warning',
|
|
11844
|
+
phase: 'parse',
|
|
11845
|
+
sourceFormat: input.language,
|
|
11846
|
+
kind: 'generatedCode',
|
|
11847
|
+
message: 'Java generated-source, annotation-generated, or Lombok-derived code marker was imported; regenerated members and source ownership require host evidence.',
|
|
11848
|
+
span,
|
|
11849
|
+
nodeId,
|
|
11850
|
+
metadata: {
|
|
11851
|
+
parser: options.parser,
|
|
11852
|
+
astFormat: options.astFormat,
|
|
11853
|
+
annotationProcessing: javaAnnotationProcessingSummary(options.annotationProcessing),
|
|
11854
|
+
...metadata
|
|
11855
|
+
}
|
|
11856
|
+
};
|
|
11857
|
+
}
|
|
11858
|
+
|
|
11859
|
+
function javaPathEvidenceSummary(value) {
|
|
11860
|
+
if (!value) return undefined;
|
|
11861
|
+
if (Array.isArray(value)) return { entryCount: value.length };
|
|
11862
|
+
if (typeof value === 'string') return { entryCount: value.split(/[:;]/).filter(Boolean).length };
|
|
11863
|
+
if (typeof value === 'object') {
|
|
11864
|
+
const summary = {};
|
|
11865
|
+
if (typeof value.hash === 'string') summary.hash = value.hash;
|
|
11866
|
+
if (Array.isArray(value.entries)) summary.entryCount = value.entries.length;
|
|
11867
|
+
if (Array.isArray(value.roots)) summary.rootCount = value.roots.length;
|
|
11868
|
+
if (typeof value.source === 'string') summary.source = value.source;
|
|
11869
|
+
return Object.keys(summary).length ? summary : { present: true };
|
|
11870
|
+
}
|
|
11871
|
+
return { present: true };
|
|
11872
|
+
}
|
|
11873
|
+
|
|
11874
|
+
function javaAnnotationProcessingSummary(value) {
|
|
11875
|
+
if (!value) return undefined;
|
|
11876
|
+
if (Array.isArray(value)) return { processorCount: value.length };
|
|
11877
|
+
if (typeof value === 'object') {
|
|
11878
|
+
const summary = {};
|
|
11879
|
+
if (typeof value.hash === 'string') summary.hash = value.hash;
|
|
11880
|
+
if (typeof value.enabled === 'boolean') summary.enabled = value.enabled;
|
|
11881
|
+
if (Array.isArray(value.processors)) summary.processorCount = value.processors.length;
|
|
11882
|
+
if (Array.isArray(value.generatedSources)) summary.generatedSourceCount = value.generatedSources.length;
|
|
11883
|
+
return Object.keys(summary).length ? summary : { present: true };
|
|
11884
|
+
}
|
|
11885
|
+
return { present: Boolean(value) };
|
|
11886
|
+
}
|
|
11887
|
+
|
|
11888
|
+
function javaBindingEvidenceSummary(value) {
|
|
11889
|
+
if (!value || typeof value !== 'object') return undefined;
|
|
11890
|
+
const summary = {};
|
|
11891
|
+
if (typeof value.hash === 'string') summary.hash = value.hash;
|
|
11892
|
+
if (Array.isArray(value.bindings)) summary.bindingCount = value.bindings.length;
|
|
11893
|
+
if (Array.isArray(value.types)) summary.typeCount = value.types.length;
|
|
11894
|
+
if (Array.isArray(value.references)) summary.referenceCount = value.references.length;
|
|
11895
|
+
if (typeof value.solver === 'string') summary.solver = value.solver;
|
|
11896
|
+
return Object.keys(summary).length ? summary : { present: true };
|
|
11897
|
+
}
|
|
11898
|
+
|
|
11210
11899
|
function declarationRecord(input, nativeNodeId, name, symbolKind, role = 'definition') {
|
|
11211
11900
|
return {
|
|
11212
11901
|
name: String(name),
|
package/package.json
CHANGED