@shapeshift-labs/frontier-lang-compiler 0.2.28 → 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 +17 -2
- package/bench/smoke.mjs +3 -1
- package/dist/index.d.ts +64 -0
- package/dist/index.js +1318 -79
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -415,6 +415,30 @@ export const NativeParserAstFormatProfiles = Object.freeze([
|
|
|
415
415
|
supportsErrorRecovery: false,
|
|
416
416
|
notes: ['Clang JSON AST dumps expose compiler AST declarations and source ranges after preprocessing; compile commands, macros, inactive branches, type checking, and lossless formatting remain host-owned evidence.']
|
|
417
417
|
}),
|
|
418
|
+
nativeParserAstFormatProfile('go-ast', {
|
|
419
|
+
aliases: ['go/parser', 'goast', 'golang-ast'],
|
|
420
|
+
kind: 'compiler-ast',
|
|
421
|
+
languages: ['go'],
|
|
422
|
+
parserAdapters: ['go/ast', 'go/parser', 'go-ast'],
|
|
423
|
+
exactness: 'exact-parser-ast',
|
|
424
|
+
sourceRangeModel: 'token-position',
|
|
425
|
+
preservesTokens: false,
|
|
426
|
+
preservesTrivia: false,
|
|
427
|
+
supportsErrorRecovery: true,
|
|
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
|
+
}),
|
|
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
|
+
}),
|
|
418
442
|
nativeParserAstFormatProfile('tree-sitter', {
|
|
419
443
|
kind: 'concrete-syntax-tree',
|
|
420
444
|
languages: ['mixed'],
|
|
@@ -2781,6 +2805,133 @@ export function createClangAstNativeImporterAdapter(options = {}) {
|
|
|
2781
2805
|
};
|
|
2782
2806
|
}
|
|
2783
2807
|
|
|
2808
|
+
export function createGoAstNativeImporterAdapter(options = {}) {
|
|
2809
|
+
return {
|
|
2810
|
+
id: options.id ?? 'frontier.go-ast-native-importer',
|
|
2811
|
+
language: options.language ?? 'go',
|
|
2812
|
+
parser: options.parser ?? 'go/parser',
|
|
2813
|
+
version: options.version,
|
|
2814
|
+
capabilities: uniqueStrings(['nativeAst', 'semanticIndex', 'sourceMaps', 'diagnostics', ...(options.capabilities ?? [])]),
|
|
2815
|
+
coverage: nativeImporterAdapterCoverage({
|
|
2816
|
+
exactness: 'exact-parser-ast',
|
|
2817
|
+
exactAst: true,
|
|
2818
|
+
tokens: false,
|
|
2819
|
+
trivia: false,
|
|
2820
|
+
diagnostics: true,
|
|
2821
|
+
sourceRanges: true,
|
|
2822
|
+
generatedRanges: false,
|
|
2823
|
+
semanticCoverage: declarationSemanticCoverage(),
|
|
2824
|
+
notes: [
|
|
2825
|
+
'Normalizes caller-owned Go go/ast-shaped File or Package trees into native AST nodes and declaration-level semantic index records.',
|
|
2826
|
+
'Go AST imports do not resolve types, imports, build tags, generated code, or control flow by themselves; attach FileSet, go/types, go/packages, and build context evidence for those claims.'
|
|
2827
|
+
]
|
|
2828
|
+
}, options.coverage),
|
|
2829
|
+
supportedExtensions: options.supportedExtensions ?? ['.go'],
|
|
2830
|
+
diagnostics: options.diagnostics,
|
|
2831
|
+
parse(input) {
|
|
2832
|
+
const parsed = input.options?.ast
|
|
2833
|
+
?? input.options?.nativeAst
|
|
2834
|
+
?? input.options?.file
|
|
2835
|
+
?? input.options?.sourceFile
|
|
2836
|
+
?? input.options?.package
|
|
2837
|
+
?? options.ast
|
|
2838
|
+
?? options.file
|
|
2839
|
+
?? options.sourceFile
|
|
2840
|
+
?? options.package
|
|
2841
|
+
?? parseGoAstSource(input, options);
|
|
2842
|
+
const root = goAstRoot(parsed);
|
|
2843
|
+
if (!root) {
|
|
2844
|
+
return missingInjectedParserResult(input, {
|
|
2845
|
+
parser: options.parser ?? 'go/parser',
|
|
2846
|
+
adapterId: options.id ?? 'frontier.go-ast-native-importer',
|
|
2847
|
+
message: 'createGoAstNativeImporterAdapter requires an injected Go ast.File/Package-shaped object, parserModule.parse function, parse function, or adapterOptions.ast.'
|
|
2848
|
+
});
|
|
2849
|
+
}
|
|
2850
|
+
const parseDiagnostics = normalizeParserErrors(parsed?.errors ?? parsed?.diagnostics, input, {
|
|
2851
|
+
parser: options.parser ?? 'go/parser'
|
|
2852
|
+
});
|
|
2853
|
+
return createNativeImportFromGoAst(root, input, {
|
|
2854
|
+
parser: options.parser ?? 'go/parser',
|
|
2855
|
+
astFormat: 'go-ast',
|
|
2856
|
+
maxNodes: options.maxNodes,
|
|
2857
|
+
diagnostics: parseDiagnostics,
|
|
2858
|
+
goVersion: options.goVersion ?? input.options?.goVersion ?? parsed?.goVersion,
|
|
2859
|
+
packageName: options.packageName ?? input.options?.packageName ?? parsed?.packageName ?? root?.Name?.Name ?? root?.Name,
|
|
2860
|
+
fileSet: input.options?.fileSet ?? input.options?.fset ?? options.fileSet ?? options.fset ?? parsed?.fileSet ?? parsed?.fset,
|
|
2861
|
+
includeComments: options.includeComments ?? input.options?.includeComments,
|
|
2862
|
+
buildTags: input.options?.buildTags ?? options.buildTags ?? parsed?.buildTags,
|
|
2863
|
+
generated: input.options?.generated ?? options.generated ?? parsed?.generated,
|
|
2864
|
+
typeEvidence: input.options?.typeEvidence ?? options.typeEvidence ?? parsed?.typeEvidence
|
|
2865
|
+
});
|
|
2866
|
+
}
|
|
2867
|
+
};
|
|
2868
|
+
}
|
|
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
|
+
|
|
2784
2935
|
export function createTreeSitterNativeImporterAdapter(options = {}) {
|
|
2785
2936
|
return {
|
|
2786
2937
|
id: options.id ?? `frontier.tree-sitter-${idFragment(options.language ?? 'source')}-native-importer`,
|
|
@@ -7222,6 +7373,8 @@ function parserAstFormatIdForParser(parser) {
|
|
|
7222
7373
|
if (text === 'syn' || text.includes('rust-syn')) return 'rust-syn';
|
|
7223
7374
|
if (text.includes('rust-analyzer') || text.includes('rowan')) return 'rust-analyzer-rowan';
|
|
7224
7375
|
if (text.includes('clang') || text.includes('libclang')) return 'clang-ast-json';
|
|
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';
|
|
7225
7378
|
if (text.includes('tree-sitter') || text.includes('treesitter')) return 'tree-sitter';
|
|
7226
7379
|
if (text.includes('babel')) return 'babel';
|
|
7227
7380
|
if (text.includes('estree')) return 'estree';
|
|
@@ -8287,6 +8440,39 @@ function parseClangAstSource(input, options) {
|
|
|
8287
8440
|
return parse(input.sourceText, parserOptions);
|
|
8288
8441
|
}
|
|
8289
8442
|
|
|
8443
|
+
function parseGoAstSource(input, options) {
|
|
8444
|
+
const parse = options.parse ?? options.parserModule?.parse ?? options.goAst?.parse ?? options.goParser?.parse;
|
|
8445
|
+
if (typeof parse !== 'function') return undefined;
|
|
8446
|
+
const parserOptions = {
|
|
8447
|
+
sourcePath: input.sourcePath,
|
|
8448
|
+
filename: input.sourcePath,
|
|
8449
|
+
mode: options.mode ?? input.options?.mode ?? 'ParseComments',
|
|
8450
|
+
goVersion: options.goVersion ?? input.options?.goVersion,
|
|
8451
|
+
packageName: options.packageName ?? input.options?.packageName,
|
|
8452
|
+
includeComments: options.includeComments ?? input.options?.includeComments,
|
|
8453
|
+
...(options.parserOptions ?? {}),
|
|
8454
|
+
...(input.options?.parserOptions ?? {})
|
|
8455
|
+
};
|
|
8456
|
+
return parse(input.sourceText, parserOptions);
|
|
8457
|
+
}
|
|
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
|
+
|
|
8290
8476
|
function createNativeImportFromSyntaxAst(ast, input, options) {
|
|
8291
8477
|
const root = normalizeSyntaxAstRoot(ast, options.astFormat);
|
|
8292
8478
|
if (!root) {
|
|
@@ -8443,6 +8629,80 @@ function createNativeImportFromClangAst(root, input, options) {
|
|
|
8443
8629
|
};
|
|
8444
8630
|
}
|
|
8445
8631
|
|
|
8632
|
+
function createNativeImportFromGoAst(root, input, options) {
|
|
8633
|
+
const context = createAstNormalizationContext(input, options);
|
|
8634
|
+
visitGoAstNode(root, context, 'root');
|
|
8635
|
+
if (context.truncated) {
|
|
8636
|
+
context.losses.push(truncatedAstLoss(input, context, options));
|
|
8637
|
+
}
|
|
8638
|
+
const semantic = semanticIndexFromNativeDeclarations(context.declarations, input, options);
|
|
8639
|
+
return {
|
|
8640
|
+
rootId: context.rootId,
|
|
8641
|
+
nodes: context.nodes,
|
|
8642
|
+
semanticIndex: semantic.semanticIndex,
|
|
8643
|
+
mappings: semantic.mappings,
|
|
8644
|
+
losses: mergeNativeLosses(context.losses, options.diagnostics?.map((diagnostic, index) => adapterDiagnosticToLoss(diagnostic, index, {
|
|
8645
|
+
id: input.adapterId,
|
|
8646
|
+
version: input.adapterVersion
|
|
8647
|
+
}, input)) ?? []),
|
|
8648
|
+
evidence: semantic.evidence,
|
|
8649
|
+
diagnostics: options.diagnostics,
|
|
8650
|
+
metadata: {
|
|
8651
|
+
astFormat: options.astFormat,
|
|
8652
|
+
parser: options.parser,
|
|
8653
|
+
goVersion: options.goVersion,
|
|
8654
|
+
packageName: options.packageName,
|
|
8655
|
+
includeComments: Boolean(options.includeComments),
|
|
8656
|
+
buildTags: Array.isArray(options.buildTags) ? options.buildTags.slice() : options.buildTags,
|
|
8657
|
+
generated: options.generated,
|
|
8658
|
+
fileSetEvidence: Boolean(options.fileSet),
|
|
8659
|
+
typeEvidence: goTypeEvidenceSummary(options.typeEvidence),
|
|
8660
|
+
normalizedNodeCount: Object.keys(context.nodes).length,
|
|
8661
|
+
declarationCount: context.declarations.length,
|
|
8662
|
+
truncated: context.truncated
|
|
8663
|
+
}
|
|
8664
|
+
};
|
|
8665
|
+
}
|
|
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
|
+
|
|
8446
8706
|
function createNativeImportFromTreeSitter(root, input, options) {
|
|
8447
8707
|
const context = createAstNormalizationContext(input, options);
|
|
8448
8708
|
visitTreeSitterNode(root, context, 'root');
|
|
@@ -8748,117 +9008,287 @@ function visitClangAstNode(node, context, propertyPath) {
|
|
|
8748
9008
|
return id;
|
|
8749
9009
|
}
|
|
8750
9010
|
|
|
8751
|
-
function
|
|
8752
|
-
if (!node ||
|
|
9011
|
+
function visitGoAstNode(node, context, propertyPath) {
|
|
9012
|
+
if (!isGoAstNode(node) || context.truncated) return undefined;
|
|
8753
9013
|
if (context.objectIds.has(node)) return context.objectIds.get(node);
|
|
8754
9014
|
if (context.counter >= context.maxNodes) {
|
|
8755
9015
|
context.truncated = true;
|
|
8756
9016
|
return undefined;
|
|
8757
9017
|
}
|
|
8758
|
-
const kind =
|
|
8759
|
-
const span =
|
|
9018
|
+
const kind = goAstKind(node);
|
|
9019
|
+
const span = spanFromGoAstNode(node, context.input, context.options);
|
|
8760
9020
|
const id = nativeNodeId(context, kind, { start: { line: span?.startLine, column: span?.startColumn } }, propertyPath);
|
|
8761
9021
|
context.objectIds.set(node, id);
|
|
8762
9022
|
if (!context.rootId) context.rootId = id;
|
|
8763
9023
|
const children = [];
|
|
8764
|
-
const
|
|
8765
|
-
|
|
8766
|
-
|
|
8767
|
-
|
|
8768
|
-
|
|
8769
|
-
|
|
8770
|
-
|
|
8771
|
-
|
|
8772
|
-
|
|
8773
|
-
|
|
9024
|
+
for (const [field, value] of goAstChildEntries(node)) {
|
|
9025
|
+
if (Array.isArray(value)) {
|
|
9026
|
+
value.forEach((entry, index) => {
|
|
9027
|
+
const childId = visitGoAstNode(entry, context, `${propertyPath}.${field}[${index}]`);
|
|
9028
|
+
if (childId) children.push(childId);
|
|
9029
|
+
});
|
|
9030
|
+
} else {
|
|
9031
|
+
const childId = visitGoAstNode(value, context, `${propertyPath}.${field}`);
|
|
9032
|
+
if (childId) children.push(childId);
|
|
9033
|
+
}
|
|
9034
|
+
}
|
|
9035
|
+
const declarations = goAstDeclarations(node, kind, id, context.input);
|
|
9036
|
+
const declaration = declarations[0];
|
|
8774
9037
|
const nativeNode = {
|
|
8775
9038
|
id,
|
|
8776
9039
|
kind,
|
|
8777
9040
|
languageKind: `${context.input.language}.${kind}`,
|
|
8778
9041
|
span,
|
|
8779
|
-
value: declaration?.name ??
|
|
8780
|
-
fields:
|
|
8781
|
-
named: Boolean(node.isNamed ?? node.named),
|
|
8782
|
-
missing: Boolean(node.isMissing),
|
|
8783
|
-
error: Boolean(node.hasError || kind === 'ERROR')
|
|
8784
|
-
},
|
|
9042
|
+
value: declaration?.name ?? goAstNodeValue(node),
|
|
9043
|
+
fields: primitiveGoAstFields(node, kind),
|
|
8785
9044
|
children,
|
|
8786
9045
|
metadata: {
|
|
8787
9046
|
astFormat: context.options.astFormat,
|
|
8788
9047
|
propertyPath,
|
|
8789
|
-
|
|
8790
|
-
|
|
9048
|
+
positionKind: goAstPositionKind(node),
|
|
9049
|
+
packageName: context.options.packageName
|
|
8791
9050
|
}
|
|
8792
9051
|
};
|
|
8793
9052
|
context.nodes[id] = nativeNode;
|
|
8794
|
-
|
|
8795
|
-
|
|
9053
|
+
for (const entry of declarations) {
|
|
9054
|
+
context.declarations.push({ ...entry, nativeNode });
|
|
9055
|
+
}
|
|
9056
|
+
if (goBadAstKind(kind)) {
|
|
8796
9057
|
context.losses.push({
|
|
8797
|
-
id: `loss_${idFragment(id)}
|
|
9058
|
+
id: `loss_${idFragment(id)}_go_bad_node`,
|
|
8798
9059
|
severity: 'error',
|
|
8799
9060
|
phase: 'parse',
|
|
8800
9061
|
sourceFormat: context.input.language,
|
|
8801
9062
|
kind: 'unsupportedSyntax',
|
|
8802
|
-
message: '
|
|
9063
|
+
message: 'Go parser recovered a BadDecl/BadExpr/BadStmt node; semantic import is partial until syntax errors are resolved.',
|
|
8803
9064
|
span,
|
|
8804
|
-
nodeId: id
|
|
9065
|
+
nodeId: id,
|
|
9066
|
+
metadata: {
|
|
9067
|
+
parser: context.options.parser,
|
|
9068
|
+
astFormat: context.options.astFormat,
|
|
9069
|
+
nodeKind: kind
|
|
9070
|
+
}
|
|
8805
9071
|
});
|
|
8806
9072
|
}
|
|
8807
|
-
|
|
8808
|
-
|
|
8809
|
-
|
|
8810
|
-
|
|
8811
|
-
|
|
8812
|
-
|
|
8813
|
-
|
|
8814
|
-
|
|
8815
|
-
|
|
8816
|
-
|
|
8817
|
-
const mappings = [];
|
|
8818
|
-
for (const declaration of declarations) {
|
|
8819
|
-
const symbolId = declaration.symbolId ?? `symbol:${input.language}:${declaration.role === 'import' ? 'import:' : ''}${idFragment(declaration.name)}`;
|
|
8820
|
-
const occurrenceId = `occ_${idFragment(declaration.nativeNode.id)}_${declaration.role ?? 'definition'}`;
|
|
8821
|
-
const ownershipRegion = semanticOwnershipRegionForDeclaration(input, {
|
|
8822
|
-
...declaration,
|
|
8823
|
-
nodeId: declaration.nativeNode.id,
|
|
8824
|
-
kind: declaration.nativeNode.kind,
|
|
8825
|
-
languageKind: declaration.nativeNode.languageKind,
|
|
8826
|
-
span: declaration.nativeNode.span,
|
|
8827
|
-
symbolId
|
|
8828
|
-
}, documentId);
|
|
8829
|
-
declaration.nativeNode.metadata = {
|
|
8830
|
-
...declaration.nativeNode.metadata,
|
|
8831
|
-
ownershipRegionId: ownershipRegion.id,
|
|
8832
|
-
ownershipRegionKey: ownershipRegion.key,
|
|
8833
|
-
ownershipRegionKind: ownershipRegion.regionKind
|
|
8834
|
-
};
|
|
8835
|
-
symbols.push({
|
|
8836
|
-
id: symbolId,
|
|
8837
|
-
scheme: 'frontier',
|
|
8838
|
-
name: declaration.name,
|
|
8839
|
-
kind: declaration.symbolKind,
|
|
8840
|
-
language: input.language,
|
|
8841
|
-
nativeAstNodeId: declaration.nativeNode.id,
|
|
8842
|
-
signatureHash: hashSemanticValue([input.language, declaration.nativeNode.kind, declaration.name, declaration.nativeNode.fields ?? {}]),
|
|
8843
|
-
definitionSpan: declaration.nativeNode.span,
|
|
9073
|
+
if (kind === 'FuncDecl' && goReceiverFieldCount(node) > 1) {
|
|
9074
|
+
context.losses.push({
|
|
9075
|
+
id: `loss_${idFragment(id)}_go_multiple_receivers`,
|
|
9076
|
+
severity: 'warning',
|
|
9077
|
+
phase: 'parse',
|
|
9078
|
+
sourceFormat: context.input.language,
|
|
9079
|
+
kind: 'unsupportedSyntax',
|
|
9080
|
+
message: 'Go parser accepted multiple receiver fields; valid method ownership requires a single receiver.',
|
|
9081
|
+
span,
|
|
9082
|
+
nodeId: id,
|
|
8844
9083
|
metadata: {
|
|
8845
|
-
|
|
8846
|
-
|
|
8847
|
-
|
|
9084
|
+
parser: context.options.parser,
|
|
9085
|
+
astFormat: context.options.astFormat,
|
|
9086
|
+
receiverFieldCount: goReceiverFieldCount(node)
|
|
8848
9087
|
}
|
|
8849
9088
|
});
|
|
8850
|
-
|
|
8851
|
-
|
|
8852
|
-
|
|
8853
|
-
|
|
8854
|
-
|
|
8855
|
-
|
|
8856
|
-
|
|
8857
|
-
|
|
8858
|
-
|
|
8859
|
-
|
|
8860
|
-
|
|
8861
|
-
|
|
9089
|
+
}
|
|
9090
|
+
if (goGeneratedCodeMarker(node, kind)) {
|
|
9091
|
+
context.losses.push({
|
|
9092
|
+
id: `loss_${idFragment(id)}_go_generated_code`,
|
|
9093
|
+
severity: 'warning',
|
|
9094
|
+
phase: 'parse',
|
|
9095
|
+
sourceFormat: context.input.language,
|
|
9096
|
+
kind: 'generatedCode',
|
|
9097
|
+
message: 'Go generated-code marker was imported; regeneration provenance and source ownership require host evidence.',
|
|
9098
|
+
span,
|
|
9099
|
+
nodeId: id,
|
|
9100
|
+
metadata: {
|
|
9101
|
+
parser: context.options.parser,
|
|
9102
|
+
astFormat: context.options.astFormat
|
|
9103
|
+
}
|
|
9104
|
+
});
|
|
9105
|
+
}
|
|
9106
|
+
return id;
|
|
9107
|
+
}
|
|
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
|
+
|
|
9181
|
+
function visitTreeSitterNode(node, context, propertyPath) {
|
|
9182
|
+
if (!node || typeof node !== 'object' || context.truncated) return undefined;
|
|
9183
|
+
if (context.objectIds.has(node)) return context.objectIds.get(node);
|
|
9184
|
+
if (context.counter >= context.maxNodes) {
|
|
9185
|
+
context.truncated = true;
|
|
9186
|
+
return undefined;
|
|
9187
|
+
}
|
|
9188
|
+
const kind = String(node.type ?? node.kind ?? 'node');
|
|
9189
|
+
const span = spanFromTreeSitterNode(node, context.input);
|
|
9190
|
+
const id = nativeNodeId(context, kind, { start: { line: span?.startLine, column: span?.startColumn } }, propertyPath);
|
|
9191
|
+
context.objectIds.set(node, id);
|
|
9192
|
+
if (!context.rootId) context.rootId = id;
|
|
9193
|
+
const children = [];
|
|
9194
|
+
const rawChildren = Array.isArray(node.namedChildren)
|
|
9195
|
+
? node.namedChildren
|
|
9196
|
+
: Array.isArray(node.children)
|
|
9197
|
+
? node.children
|
|
9198
|
+
: [];
|
|
9199
|
+
rawChildren.forEach((child, index) => {
|
|
9200
|
+
const childId = visitTreeSitterNode(child, context, `${propertyPath}.children[${index}]`);
|
|
9201
|
+
if (childId) children.push(childId);
|
|
9202
|
+
});
|
|
9203
|
+
const declaration = treeSitterDeclaration(node, kind, id, context.input, context.options);
|
|
9204
|
+
const nativeNode = {
|
|
9205
|
+
id,
|
|
9206
|
+
kind,
|
|
9207
|
+
languageKind: `${context.input.language}.${kind}`,
|
|
9208
|
+
span,
|
|
9209
|
+
value: declaration?.name ?? shortNodeText(node),
|
|
9210
|
+
fields: {
|
|
9211
|
+
named: Boolean(node.isNamed ?? node.named),
|
|
9212
|
+
missing: Boolean(node.isMissing),
|
|
9213
|
+
error: Boolean(node.hasError || kind === 'ERROR')
|
|
9214
|
+
},
|
|
9215
|
+
children,
|
|
9216
|
+
metadata: {
|
|
9217
|
+
astFormat: context.options.astFormat,
|
|
9218
|
+
propertyPath,
|
|
9219
|
+
startIndex: numberOrUndefined(node.startIndex),
|
|
9220
|
+
endIndex: numberOrUndefined(node.endIndex)
|
|
9221
|
+
}
|
|
9222
|
+
};
|
|
9223
|
+
context.nodes[id] = nativeNode;
|
|
9224
|
+
if (declaration) context.declarations.push({ ...declaration, nativeNode });
|
|
9225
|
+
if (node.hasError || kind === 'ERROR') {
|
|
9226
|
+
context.losses.push({
|
|
9227
|
+
id: `loss_${idFragment(id)}_tree_sitter_error`,
|
|
9228
|
+
severity: 'error',
|
|
9229
|
+
phase: 'parse',
|
|
9230
|
+
sourceFormat: context.input.language,
|
|
9231
|
+
kind: 'unsupportedSyntax',
|
|
9232
|
+
message: 'Tree-sitter reported a parse error node.',
|
|
9233
|
+
span,
|
|
9234
|
+
nodeId: id
|
|
9235
|
+
});
|
|
9236
|
+
}
|
|
9237
|
+
return id;
|
|
9238
|
+
}
|
|
9239
|
+
|
|
9240
|
+
function semanticIndexFromNativeDeclarations(declarations, input, options) {
|
|
9241
|
+
const documentId = `doc_${idFragment(input.sourcePath ?? input.language)}_${idFragment(input.sourceHash)}`;
|
|
9242
|
+
const evidenceId = `evidence_${idFragment(input.sourcePath ?? input.language)}_${idFragment(options.astFormat ?? options.parser)}_import`;
|
|
9243
|
+
const symbols = [];
|
|
9244
|
+
const occurrences = [];
|
|
9245
|
+
const relations = [];
|
|
9246
|
+
const facts = [];
|
|
9247
|
+
const mappings = [];
|
|
9248
|
+
for (const declaration of declarations) {
|
|
9249
|
+
const symbolId = declaration.symbolId ?? `symbol:${input.language}:${declaration.role === 'import' ? 'import:' : ''}${idFragment(declaration.name)}`;
|
|
9250
|
+
const occurrenceId = `occ_${idFragment(declaration.nativeNode.id)}_${declaration.role ?? 'definition'}`;
|
|
9251
|
+
const ownershipRegion = semanticOwnershipRegionForDeclaration(input, {
|
|
9252
|
+
...declaration,
|
|
9253
|
+
nodeId: declaration.nativeNode.id,
|
|
9254
|
+
kind: declaration.nativeNode.kind,
|
|
9255
|
+
languageKind: declaration.nativeNode.languageKind,
|
|
9256
|
+
span: declaration.nativeNode.span,
|
|
9257
|
+
symbolId
|
|
9258
|
+
}, documentId);
|
|
9259
|
+
declaration.nativeNode.metadata = {
|
|
9260
|
+
...declaration.nativeNode.metadata,
|
|
9261
|
+
ownershipRegionId: ownershipRegion.id,
|
|
9262
|
+
ownershipRegionKey: ownershipRegion.key,
|
|
9263
|
+
ownershipRegionKind: ownershipRegion.regionKind
|
|
9264
|
+
};
|
|
9265
|
+
symbols.push({
|
|
9266
|
+
id: symbolId,
|
|
9267
|
+
scheme: 'frontier',
|
|
9268
|
+
name: declaration.name,
|
|
9269
|
+
kind: declaration.symbolKind,
|
|
9270
|
+
language: input.language,
|
|
9271
|
+
nativeAstNodeId: declaration.nativeNode.id,
|
|
9272
|
+
signatureHash: hashSemanticValue([input.language, declaration.nativeNode.kind, declaration.name, declaration.nativeNode.fields ?? {}]),
|
|
9273
|
+
definitionSpan: declaration.nativeNode.span,
|
|
9274
|
+
metadata: {
|
|
9275
|
+
ownershipRegionId: ownershipRegion.id,
|
|
9276
|
+
ownershipRegionKey: ownershipRegion.key,
|
|
9277
|
+
ownershipRegionKind: ownershipRegion.regionKind
|
|
9278
|
+
}
|
|
9279
|
+
});
|
|
9280
|
+
occurrences.push({
|
|
9281
|
+
id: occurrenceId,
|
|
9282
|
+
documentId,
|
|
9283
|
+
symbolId,
|
|
9284
|
+
role: declaration.role ?? 'definition',
|
|
9285
|
+
span: declaration.nativeNode.span,
|
|
9286
|
+
nativeAstNodeId: declaration.nativeNode.id
|
|
9287
|
+
});
|
|
9288
|
+
relations.push({
|
|
9289
|
+
id: `rel_${idFragment(documentId)}_${idFragment(declaration.nativeNode.id)}`,
|
|
9290
|
+
sourceId: documentId,
|
|
9291
|
+
predicate: relationPredicateForDeclaration(declaration),
|
|
8862
9292
|
targetId: symbolId
|
|
8863
9293
|
});
|
|
8864
9294
|
facts.push({
|
|
@@ -10657,6 +11087,815 @@ function serializableIncludeGraphSummary(value) {
|
|
|
10657
11087
|
return Object.keys(summary).length ? summary : { present: true };
|
|
10658
11088
|
}
|
|
10659
11089
|
|
|
11090
|
+
function goAstRoot(value) {
|
|
11091
|
+
if (!value || typeof value !== 'object') return undefined;
|
|
11092
|
+
if (isGoAstNode(value)) return value;
|
|
11093
|
+
if (isGoAstNode(value.ast)) return value.ast;
|
|
11094
|
+
if (isGoAstNode(value.file)) return value.file;
|
|
11095
|
+
if (isGoAstNode(value.sourceFile)) return value.sourceFile;
|
|
11096
|
+
if (isGoAstNode(value.root)) return value.root;
|
|
11097
|
+
if (isGoAstNode(value.package)) return value.package;
|
|
11098
|
+
if (value.files && typeof value.files === 'object') return { kind: 'Package', Name: value.name ?? value.packageName, Files: value.files };
|
|
11099
|
+
return undefined;
|
|
11100
|
+
}
|
|
11101
|
+
|
|
11102
|
+
function isGoAstNode(value) {
|
|
11103
|
+
return Boolean(value && typeof value === 'object' && typeof goAstKind(value) === 'string');
|
|
11104
|
+
}
|
|
11105
|
+
|
|
11106
|
+
function goAstKind(node) {
|
|
11107
|
+
if (!node || typeof node !== 'object') return undefined;
|
|
11108
|
+
const declared = node.kind ?? node._type ?? node.type ?? node.nodeType ?? node.astKind;
|
|
11109
|
+
if (typeof declared === 'string') return normalizeGoAstKind(declared);
|
|
11110
|
+
if (Array.isArray(node.Decls) || Array.isArray(node.decls)) return 'File';
|
|
11111
|
+
if (node.Files || node.files) return 'Package';
|
|
11112
|
+
if (node.Name && node.Type && (node.Body || node.Recv !== undefined || node.recv !== undefined)) return 'FuncDecl';
|
|
11113
|
+
if (node.Tok && (node.Specs || node.specs)) return 'GenDecl';
|
|
11114
|
+
if (node.Path && (node.Name !== undefined || node.EndPos !== undefined)) return 'ImportSpec';
|
|
11115
|
+
if (node.Names && node.Type !== undefined) return 'ValueSpec';
|
|
11116
|
+
if (node.Name && node.Type !== undefined) return 'TypeSpec';
|
|
11117
|
+
if (node.List && (node.Opening !== undefined || node.Closing !== undefined)) return 'FieldList';
|
|
11118
|
+
return undefined;
|
|
11119
|
+
}
|
|
11120
|
+
|
|
11121
|
+
function normalizeGoAstKind(kind) {
|
|
11122
|
+
const text = String(kind).replace(/^(?:ast\.)?\*/, '').replace(/^(?:go\/ast\.)/, '');
|
|
11123
|
+
if (/^file$/i.test(text)) return 'File';
|
|
11124
|
+
if (/^package$/i.test(text)) return 'Package';
|
|
11125
|
+
if (/^funcdecl$/i.test(text) || /^func_decl$/i.test(text)) return 'FuncDecl';
|
|
11126
|
+
if (/^gendecl$/i.test(text) || /^gen_decl$/i.test(text)) return 'GenDecl';
|
|
11127
|
+
if (/^importspec$/i.test(text) || /^import_spec$/i.test(text)) return 'ImportSpec';
|
|
11128
|
+
if (/^typespec$/i.test(text) || /^type_spec$/i.test(text)) return 'TypeSpec';
|
|
11129
|
+
if (/^valuespec$/i.test(text) || /^value_spec$/i.test(text)) return 'ValueSpec';
|
|
11130
|
+
if (/^structtype$/i.test(text) || /^struct_type$/i.test(text)) return 'StructType';
|
|
11131
|
+
if (/^interfacetype$/i.test(text) || /^interface_type$/i.test(text)) return 'InterfaceType';
|
|
11132
|
+
if (/^fieldlist$/i.test(text) || /^field_list$/i.test(text)) return 'FieldList';
|
|
11133
|
+
return text;
|
|
11134
|
+
}
|
|
11135
|
+
|
|
11136
|
+
function ignoredGoAstField(key) {
|
|
11137
|
+
return key === '_type'
|
|
11138
|
+
|| key === 'type'
|
|
11139
|
+
|| key === 'kind'
|
|
11140
|
+
|| key === 'nodeType'
|
|
11141
|
+
|| key === 'astKind'
|
|
11142
|
+
|| key === 'parent'
|
|
11143
|
+
|| key === 'Obj'
|
|
11144
|
+
|| key === 'object'
|
|
11145
|
+
|| key === 'Scope'
|
|
11146
|
+
|| key === 'scope'
|
|
11147
|
+
|| key === 'Unresolved'
|
|
11148
|
+
|| key === 'unresolved'
|
|
11149
|
+
|| key === 'FileStart'
|
|
11150
|
+
|| key === 'FileEnd'
|
|
11151
|
+
|| key === 'Package'
|
|
11152
|
+
|| key === 'Name'
|
|
11153
|
+
|| key === 'Path'
|
|
11154
|
+
|| key === 'Pos'
|
|
11155
|
+
|| key === 'End'
|
|
11156
|
+
|| key === 'pos'
|
|
11157
|
+
|| key === 'end';
|
|
11158
|
+
}
|
|
11159
|
+
|
|
11160
|
+
function primitiveGoAstFields(node, kind) {
|
|
11161
|
+
const fields = { kind };
|
|
11162
|
+
const name = goAstDeclarationName(node);
|
|
11163
|
+
if (name) fields.name = name;
|
|
11164
|
+
const type = goAstTypeName(node.Type ?? node.type);
|
|
11165
|
+
if (type) fields.type = type;
|
|
11166
|
+
const tok = goAstTokenName(node.Tok ?? node.tok);
|
|
11167
|
+
if (tok) fields.token = tok;
|
|
11168
|
+
const importPath = goAstImportPath(node);
|
|
11169
|
+
if (importPath) fields.importPath = importPath;
|
|
11170
|
+
const receiver = goAstReceiverName(node);
|
|
11171
|
+
if (receiver) fields.receiver = receiver;
|
|
11172
|
+
for (const key of ['Incomplete', 'Doc', 'Comment']) {
|
|
11173
|
+
const value = node[key] ?? node[key[0].toLowerCase() + key.slice(1)];
|
|
11174
|
+
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean' || value === null) fields[key[0].toLowerCase() + key.slice(1)] = value;
|
|
11175
|
+
}
|
|
11176
|
+
if (Array.isArray(node.Names ?? node.names)) {
|
|
11177
|
+
fields.names = (node.Names ?? node.names).map(goAstIdentName).filter(Boolean).join(',');
|
|
11178
|
+
}
|
|
11179
|
+
return fields;
|
|
11180
|
+
}
|
|
11181
|
+
|
|
11182
|
+
function spanFromGoAstNode(node, input, options = {}) {
|
|
11183
|
+
const start = goAstPosition(node.Pos ?? node.pos ?? node.Name?.NamePos ?? node.name?.namePos ?? node.Package, options);
|
|
11184
|
+
const end = goAstPosition(node.End ?? node.end ?? node.EndPos ?? node.endPos, options);
|
|
11185
|
+
if (!start) return undefined;
|
|
11186
|
+
return {
|
|
11187
|
+
sourceId: input.sourceHash,
|
|
11188
|
+
path: start.path ?? end?.path ?? input.sourcePath,
|
|
11189
|
+
startLine: start.line,
|
|
11190
|
+
startColumn: start.column,
|
|
11191
|
+
endLine: end?.line,
|
|
11192
|
+
endColumn: end?.column
|
|
11193
|
+
};
|
|
11194
|
+
}
|
|
11195
|
+
|
|
11196
|
+
function goAstPosition(value, options = {}) {
|
|
11197
|
+
if (!value) return undefined;
|
|
11198
|
+
if (typeof value === 'object') {
|
|
11199
|
+
const position = value.position ?? value.Position ?? value.pos ?? value.Pos ?? value;
|
|
11200
|
+
const line = position.Line ?? position.line;
|
|
11201
|
+
const column = position.Column ?? position.column ?? position.Col ?? position.col;
|
|
11202
|
+
if (typeof line === 'number') {
|
|
11203
|
+
return {
|
|
11204
|
+
path: position.Filename ?? position.filename ?? position.file ?? position.path,
|
|
11205
|
+
line,
|
|
11206
|
+
column: typeof column === 'number' ? column : undefined
|
|
11207
|
+
};
|
|
11208
|
+
}
|
|
11209
|
+
}
|
|
11210
|
+
const fileSet = options.fileSet ?? options.fset;
|
|
11211
|
+
const positionFor = typeof fileSet?.PositionFor === 'function'
|
|
11212
|
+
? fileSet.PositionFor.bind(fileSet)
|
|
11213
|
+
: typeof fileSet?.positionFor === 'function'
|
|
11214
|
+
? fileSet.positionFor.bind(fileSet)
|
|
11215
|
+
: typeof fileSet?.Position === 'function'
|
|
11216
|
+
? fileSet.Position.bind(fileSet)
|
|
11217
|
+
: typeof fileSet?.position === 'function'
|
|
11218
|
+
? fileSet.position.bind(fileSet)
|
|
11219
|
+
: undefined;
|
|
11220
|
+
if (positionFor) {
|
|
11221
|
+
const resolved = positionFor(value, true);
|
|
11222
|
+
return goAstPosition(resolved, options);
|
|
11223
|
+
}
|
|
11224
|
+
return undefined;
|
|
11225
|
+
}
|
|
11226
|
+
|
|
11227
|
+
function goAstPositionKind(node) {
|
|
11228
|
+
const pos = node.Pos ?? node.pos ?? node.Name?.NamePos ?? node.name?.namePos;
|
|
11229
|
+
if (!pos) return undefined;
|
|
11230
|
+
if (typeof pos === 'object') return 'token.Position';
|
|
11231
|
+
return 'token.Pos';
|
|
11232
|
+
}
|
|
11233
|
+
|
|
11234
|
+
function goAstDeclarations(node, kind, nativeNodeId, input) {
|
|
11235
|
+
if (kind === 'ImportSpec') {
|
|
11236
|
+
const name = goAstImportPath(node);
|
|
11237
|
+
return name ? [declarationRecord(input, nativeNodeId, name, 'module', 'import')] : [];
|
|
11238
|
+
}
|
|
11239
|
+
if (kind === 'FuncDecl') {
|
|
11240
|
+
const name = goAstDeclarationName(node);
|
|
11241
|
+
if (!name) return [];
|
|
11242
|
+
const receiver = goAstReceiverName(node);
|
|
11243
|
+
return [declarationRecord(input, nativeNodeId, receiver ? `${receiver}.${name}` : name, receiver ? 'method' : 'function', node.Body || node.body ? 'definition' : 'declaration')];
|
|
11244
|
+
}
|
|
11245
|
+
if (kind === 'TypeSpec') {
|
|
11246
|
+
const name = goAstDeclarationName(node);
|
|
11247
|
+
return name ? [declarationRecord(input, nativeNodeId, name, goAstTypeSpecSymbolKind(node), 'definition')] : [];
|
|
11248
|
+
}
|
|
11249
|
+
if (kind === 'ValueSpec') {
|
|
11250
|
+
const names = goAstValueSpecNames(node);
|
|
11251
|
+
const token = goAstTokenName(node.parentTok ?? node.Tok ?? node.tok);
|
|
11252
|
+
return names.map((name) => declarationRecord(input, nativeNodeId, name, token === 'CONST' || token === 'const' ? 'constant' : 'variable', 'definition'));
|
|
11253
|
+
}
|
|
11254
|
+
if (kind === 'Field') {
|
|
11255
|
+
return goAstValueSpecNames(node).map((name) => declarationRecord(input, nativeNodeId, name, 'property', 'definition'));
|
|
11256
|
+
}
|
|
11257
|
+
if (kind === 'Package' || kind === 'File') {
|
|
11258
|
+
const name = goAstPackageName(node);
|
|
11259
|
+
return name ? [declarationRecord(input, nativeNodeId, name, 'module', 'definition')] : [];
|
|
11260
|
+
}
|
|
11261
|
+
return [];
|
|
11262
|
+
}
|
|
11263
|
+
|
|
11264
|
+
function goAstChildEntries(node) {
|
|
11265
|
+
const fieldNames = Object.keys(node).filter((key) => !ignoredGoAstField(key));
|
|
11266
|
+
const entries = [];
|
|
11267
|
+
for (const field of fieldNames) {
|
|
11268
|
+
const value = node[field];
|
|
11269
|
+
if (field === 'Files' || field === 'files') {
|
|
11270
|
+
if (value && typeof value === 'object') entries.push([field, Array.isArray(value) ? value : Object.values(value)]);
|
|
11271
|
+
continue;
|
|
11272
|
+
}
|
|
11273
|
+
if (field === 'Specs' || field === 'specs') {
|
|
11274
|
+
const token = goAstTokenName(node.Tok ?? node.tok);
|
|
11275
|
+
entries.push([field, Array.isArray(value)
|
|
11276
|
+
? value.map((entry) => entry && typeof entry === 'object' ? { parentTok: token, ...entry } : entry)
|
|
11277
|
+
: value]);
|
|
11278
|
+
continue;
|
|
11279
|
+
}
|
|
11280
|
+
entries.push([field, value]);
|
|
11281
|
+
}
|
|
11282
|
+
return entries.filter(([, value]) => Array.isArray(value)
|
|
11283
|
+
? value.some(isGoAstNode)
|
|
11284
|
+
: isGoAstNode(value));
|
|
11285
|
+
}
|
|
11286
|
+
|
|
11287
|
+
function goAstNodeValue(node) {
|
|
11288
|
+
return goAstDeclarationName(node)
|
|
11289
|
+
?? goAstImportPath(node)
|
|
11290
|
+
?? goAstTypeName(node.Type ?? node.type)
|
|
11291
|
+
?? goAstLiteralValue(node);
|
|
11292
|
+
}
|
|
11293
|
+
|
|
11294
|
+
function goAstDeclarationName(node) {
|
|
11295
|
+
if (!node || typeof node !== 'object') return undefined;
|
|
11296
|
+
return goAstIdentName(node.Name ?? node.name)
|
|
11297
|
+
?? goAstIdentName(node.Ident ?? node.ident)
|
|
11298
|
+
?? goAstIdentName(node.Sel ?? node.sel)
|
|
11299
|
+
?? (typeof node.Name === 'string' ? node.Name : undefined)
|
|
11300
|
+
?? (typeof node.name === 'string' ? node.name : undefined);
|
|
11301
|
+
}
|
|
11302
|
+
|
|
11303
|
+
function goAstPackageName(node) {
|
|
11304
|
+
if (!node || typeof node !== 'object') return undefined;
|
|
11305
|
+
return goAstIdentName(node.Name ?? node.name) ?? node.PackageName ?? node.packageName;
|
|
11306
|
+
}
|
|
11307
|
+
|
|
11308
|
+
function goAstIdentName(value) {
|
|
11309
|
+
if (!value) return undefined;
|
|
11310
|
+
if (typeof value === 'string') return value;
|
|
11311
|
+
return value.Name ?? value.name ?? value.Value ?? value.value;
|
|
11312
|
+
}
|
|
11313
|
+
|
|
11314
|
+
function goAstImportPath(node) {
|
|
11315
|
+
if (!node || typeof node !== 'object') return undefined;
|
|
11316
|
+
const path = node.Path ?? node.path;
|
|
11317
|
+
const raw = typeof path === 'string' ? path : path?.Value ?? path?.value ?? path?.Kind;
|
|
11318
|
+
if (typeof raw !== 'string') return undefined;
|
|
11319
|
+
return raw.replace(/^"|"$/g, '').replace(/^`|`$/g, '');
|
|
11320
|
+
}
|
|
11321
|
+
|
|
11322
|
+
function goAstReceiverName(node) {
|
|
11323
|
+
const recv = node?.Recv ?? node?.recv;
|
|
11324
|
+
const list = recv?.List ?? recv?.list;
|
|
11325
|
+
if (!Array.isArray(list) || !list.length) return undefined;
|
|
11326
|
+
const first = list[0];
|
|
11327
|
+
return goAstTypeName(first?.Type ?? first?.type);
|
|
11328
|
+
}
|
|
11329
|
+
|
|
11330
|
+
function goAstValueSpecName(node) {
|
|
11331
|
+
return goAstValueSpecNames(node)[0];
|
|
11332
|
+
}
|
|
11333
|
+
|
|
11334
|
+
function goAstValueSpecNames(node) {
|
|
11335
|
+
const names = node.Names ?? node.names;
|
|
11336
|
+
if (Array.isArray(names)) return names.map(goAstIdentName).filter(Boolean);
|
|
11337
|
+
const name = goAstDeclarationName(node);
|
|
11338
|
+
return name ? [name] : [];
|
|
11339
|
+
}
|
|
11340
|
+
|
|
11341
|
+
function goAstTypeSpecSymbolKind(node) {
|
|
11342
|
+
const type = node.Type ?? node.type;
|
|
11343
|
+
const kind = goAstKind(type);
|
|
11344
|
+
if (kind === 'InterfaceType') return 'interface';
|
|
11345
|
+
if (kind === 'StructType') return 'class';
|
|
11346
|
+
return 'type';
|
|
11347
|
+
}
|
|
11348
|
+
|
|
11349
|
+
function goAstTypeName(value) {
|
|
11350
|
+
if (!value) return undefined;
|
|
11351
|
+
if (typeof value === 'string') return value;
|
|
11352
|
+
const kind = goAstKind(value);
|
|
11353
|
+
if (kind === 'Ident') return goAstIdentName(value);
|
|
11354
|
+
if (kind === 'StarExpr') {
|
|
11355
|
+
const inner = goAstTypeName(value.X ?? value.x);
|
|
11356
|
+
return inner ? `*${inner}` : '*';
|
|
11357
|
+
}
|
|
11358
|
+
if (kind === 'SelectorExpr') {
|
|
11359
|
+
const left = goAstTypeName(value.X ?? value.x);
|
|
11360
|
+
const right = goAstIdentName(value.Sel ?? value.sel);
|
|
11361
|
+
return [left, right].filter(Boolean).join('.');
|
|
11362
|
+
}
|
|
11363
|
+
if (kind === 'ArrayType') {
|
|
11364
|
+
const inner = goAstTypeName(value.Elt ?? value.elt);
|
|
11365
|
+
return `[]${inner ?? 'unknown'}`;
|
|
11366
|
+
}
|
|
11367
|
+
if (kind === 'MapType') {
|
|
11368
|
+
return `map[${goAstTypeName(value.Key ?? value.key) ?? 'unknown'}]${goAstTypeName(value.Value ?? value.value) ?? 'unknown'}`;
|
|
11369
|
+
}
|
|
11370
|
+
if (kind === 'StructType') return 'struct';
|
|
11371
|
+
if (kind === 'InterfaceType') return 'interface';
|
|
11372
|
+
if (kind === 'FuncType') return 'func';
|
|
11373
|
+
return goAstDeclarationName(value);
|
|
11374
|
+
}
|
|
11375
|
+
|
|
11376
|
+
function goAstTokenName(value) {
|
|
11377
|
+
if (!value) return undefined;
|
|
11378
|
+
if (typeof value === 'string') return value;
|
|
11379
|
+
if (typeof value === 'number') return String(value);
|
|
11380
|
+
return value.String ?? value.string ?? value.Name ?? value.name;
|
|
11381
|
+
}
|
|
11382
|
+
|
|
11383
|
+
function goAstLiteralValue(node) {
|
|
11384
|
+
const value = node.Value ?? node.value;
|
|
11385
|
+
if (value === null || typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') return value;
|
|
11386
|
+
return undefined;
|
|
11387
|
+
}
|
|
11388
|
+
|
|
11389
|
+
function goGeneratedCodeMarker(node, kind) {
|
|
11390
|
+
if (kind !== 'File') return false;
|
|
11391
|
+
if (node.Generated || node.generated) return true;
|
|
11392
|
+
const comments = node.Comments ?? node.comments;
|
|
11393
|
+
if (!Array.isArray(comments)) return false;
|
|
11394
|
+
return comments.some((group) => JSON.stringify(group).includes('Code generated') && JSON.stringify(group).includes('DO NOT EDIT'));
|
|
11395
|
+
}
|
|
11396
|
+
|
|
11397
|
+
function goBadAstKind(kind) {
|
|
11398
|
+
return kind === 'BadDecl' || kind === 'BadExpr' || kind === 'BadStmt';
|
|
11399
|
+
}
|
|
11400
|
+
|
|
11401
|
+
function goReceiverFieldCount(node) {
|
|
11402
|
+
const list = (node?.Recv ?? node?.recv)?.List ?? (node?.Recv ?? node?.recv)?.list;
|
|
11403
|
+
return Array.isArray(list) ? list.length : 0;
|
|
11404
|
+
}
|
|
11405
|
+
|
|
11406
|
+
function goTypeEvidenceSummary(value) {
|
|
11407
|
+
if (!value || typeof value !== 'object') return undefined;
|
|
11408
|
+
const summary = {};
|
|
11409
|
+
if (typeof value.packagePath === 'string') summary.packagePath = value.packagePath;
|
|
11410
|
+
if (typeof value.hash === 'string') summary.hash = value.hash;
|
|
11411
|
+
if (Array.isArray(value.types)) summary.typeCount = value.types.length;
|
|
11412
|
+
if (Array.isArray(value.references)) summary.referenceCount = value.references.length;
|
|
11413
|
+
return Object.keys(summary).length ? summary : { present: true };
|
|
11414
|
+
}
|
|
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
|
+
|
|
10660
11899
|
function declarationRecord(input, nativeNodeId, name, symbolKind, role = 'definition') {
|
|
10661
11900
|
return {
|
|
10662
11901
|
name: String(name),
|