@shapeshift-labs/frontier-lang-compiler 0.2.27 → 0.2.29
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 +57 -0
- package/dist/index.js +978 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -332,6 +332,8 @@ Use injected parser adapters when a real language parser is available but should
|
|
|
332
332
|
```js
|
|
333
333
|
import {
|
|
334
334
|
createBabelNativeImporterAdapter,
|
|
335
|
+
createClangAstNativeImporterAdapter,
|
|
336
|
+
createGoAstNativeImporterAdapter,
|
|
335
337
|
createPythonAstNativeImporterAdapter,
|
|
336
338
|
createRustSynNativeImporterAdapter,
|
|
337
339
|
importNativeProject,
|
|
@@ -348,6 +350,15 @@ const rustSynAdapter = createRustSynNativeImporterAdapter({
|
|
|
348
350
|
parserModule: hostRustSynParser,
|
|
349
351
|
rustEdition: '2021'
|
|
350
352
|
});
|
|
353
|
+
const clangAstAdapter = createClangAstNativeImporterAdapter({
|
|
354
|
+
parserModule: hostClangJsonParser,
|
|
355
|
+
cStandard: 'c11',
|
|
356
|
+
compileFlags: ['-std=c11']
|
|
357
|
+
});
|
|
358
|
+
const goAstAdapter = createGoAstNativeImporterAdapter({
|
|
359
|
+
parserModule: hostGoAstParser,
|
|
360
|
+
goVersion: '1.22'
|
|
361
|
+
});
|
|
351
362
|
|
|
352
363
|
const imported = await runNativeImporterAdapter(babelAdapter, {
|
|
353
364
|
sourcePath: 'src/todo.ts',
|
|
@@ -356,11 +367,13 @@ const imported = await runNativeImporterAdapter(babelAdapter, {
|
|
|
356
367
|
|
|
357
368
|
const project = await importNativeProject({
|
|
358
369
|
projectRoot: 'src',
|
|
359
|
-
adapters: [babelAdapter, pythonAstAdapter, rustSynAdapter],
|
|
370
|
+
adapters: [babelAdapter, pythonAstAdapter, rustSynAdapter, clangAstAdapter, goAstAdapter],
|
|
360
371
|
sources: [
|
|
361
372
|
{ language: 'typescript', adapter: babelAdapter.id, sourcePath: 'src/todo.ts', sourceText },
|
|
362
373
|
{ language: 'python', adapter: pythonAstAdapter.id, sourcePath: 'tools/todo.py', sourceText: pythonSource },
|
|
363
|
-
{ language: 'rust', adapter: rustSynAdapter.id, sourcePath: 'src/todo.rs', sourceText: rustSource }
|
|
374
|
+
{ language: 'rust', adapter: rustSynAdapter.id, sourcePath: 'src/todo.rs', sourceText: rustSource },
|
|
375
|
+
{ language: 'c', adapter: clangAstAdapter.id, sourcePath: 'native/todo.c', sourceText: cSource },
|
|
376
|
+
{ language: 'go', adapter: goAstAdapter.id, sourcePath: 'cmd/todo/main.go', sourceText: goSource }
|
|
364
377
|
]
|
|
365
378
|
});
|
|
366
379
|
|
|
@@ -381,6 +394,8 @@ The built-in adapter factories are dependency-light wrappers for caller-owned pa
|
|
|
381
394
|
- `createTypeScriptCompilerNativeImporterAdapter`
|
|
382
395
|
- `createPythonAstNativeImporterAdapter`
|
|
383
396
|
- `createRustSynNativeImporterAdapter`
|
|
397
|
+
- `createClangAstNativeImporterAdapter`
|
|
398
|
+
- `createGoAstNativeImporterAdapter`
|
|
384
399
|
- `createTreeSitterNativeImporterAdapter`
|
|
385
400
|
|
|
386
401
|
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
|
@@ -2,7 +2,9 @@ import { performance } from 'node:perf_hooks';
|
|
|
2
2
|
import {
|
|
3
3
|
compileNativeSource,
|
|
4
4
|
compileFrontierSource,
|
|
5
|
+
createClangAstNativeImporterAdapter,
|
|
5
6
|
createEstreeNativeImporterAdapter,
|
|
7
|
+
createGoAstNativeImporterAdapter,
|
|
6
8
|
createNativeImportCoverageMatrix,
|
|
7
9
|
createNativeParserAstFormatMatrix,
|
|
8
10
|
createProjectionTargetLossMatrix,
|
|
@@ -79,7 +81,7 @@ const matrixDurationMs = performance.now() - matrixStart;
|
|
|
79
81
|
const parserFormatMatrixStart = performance.now();
|
|
80
82
|
const parserFormatMatrix = createNativeParserAstFormatMatrix({
|
|
81
83
|
imports: nativeImportResults,
|
|
82
|
-
adapters: [estreeAdapter, createPythonAstNativeImporterAdapter(), createRustSynNativeImporterAdapter()]
|
|
84
|
+
adapters: [estreeAdapter, createPythonAstNativeImporterAdapter(), createRustSynNativeImporterAdapter(), createClangAstNativeImporterAdapter(), createGoAstNativeImporterAdapter()]
|
|
83
85
|
});
|
|
84
86
|
const parserFormatMatrixDurationMs = performance.now() - parserFormatMatrixStart;
|
|
85
87
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1410,6 +1410,61 @@ export interface RustSynNativeImporterAdapterOptions {
|
|
|
1410
1410
|
readonly maxNodes?: number;
|
|
1411
1411
|
}
|
|
1412
1412
|
|
|
1413
|
+
export interface ClangAstNativeImporterAdapterOptions {
|
|
1414
|
+
readonly id?: string;
|
|
1415
|
+
readonly language?: FrontierSourceLanguage;
|
|
1416
|
+
readonly parser?: string;
|
|
1417
|
+
readonly version?: string;
|
|
1418
|
+
readonly capabilities?: readonly string[];
|
|
1419
|
+
readonly coverage?: NativeImporterAdapterCoverageInput;
|
|
1420
|
+
readonly supportedExtensions?: readonly string[];
|
|
1421
|
+
readonly diagnostics?: readonly NativeImporterAdapterDiagnostic[];
|
|
1422
|
+
readonly ast?: unknown;
|
|
1423
|
+
readonly translationUnit?: unknown;
|
|
1424
|
+
readonly tu?: unknown;
|
|
1425
|
+
readonly parse?: (sourceText: string, options: Record<string, unknown>) => unknown;
|
|
1426
|
+
readonly parserModule?: { readonly parse: (sourceText: string, options: Record<string, unknown>) => unknown };
|
|
1427
|
+
readonly clang?: { readonly parse: (sourceText: string, options: Record<string, unknown>) => unknown };
|
|
1428
|
+
readonly libclang?: { readonly parse: (sourceText: string, options: Record<string, unknown>) => unknown };
|
|
1429
|
+
readonly parserOptions?: Record<string, unknown>;
|
|
1430
|
+
readonly cStandard?: 'c89' | 'c99' | 'c11' | 'c17' | 'c23' | 'gnu11' | 'gnu17' | 'gnu23' | string;
|
|
1431
|
+
readonly compileFlags?: readonly string[];
|
|
1432
|
+
readonly includeSystemHeaders?: boolean;
|
|
1433
|
+
readonly preprocessorRecords?: readonly unknown[] | { readonly records?: readonly unknown[] };
|
|
1434
|
+
readonly includeGraph?: unknown;
|
|
1435
|
+
readonly maxNodes?: number;
|
|
1436
|
+
}
|
|
1437
|
+
|
|
1438
|
+
export interface GoAstNativeImporterAdapterOptions {
|
|
1439
|
+
readonly id?: string;
|
|
1440
|
+
readonly language?: FrontierSourceLanguage;
|
|
1441
|
+
readonly parser?: string;
|
|
1442
|
+
readonly version?: string;
|
|
1443
|
+
readonly capabilities?: readonly string[];
|
|
1444
|
+
readonly coverage?: NativeImporterAdapterCoverageInput;
|
|
1445
|
+
readonly supportedExtensions?: readonly string[];
|
|
1446
|
+
readonly diagnostics?: readonly NativeImporterAdapterDiagnostic[];
|
|
1447
|
+
readonly ast?: unknown;
|
|
1448
|
+
readonly file?: unknown;
|
|
1449
|
+
readonly sourceFile?: unknown;
|
|
1450
|
+
readonly package?: unknown;
|
|
1451
|
+
readonly parse?: (sourceText: string, options: Record<string, unknown>) => unknown;
|
|
1452
|
+
readonly parserModule?: { readonly parse: (sourceText: string, options: Record<string, unknown>) => unknown };
|
|
1453
|
+
readonly goAst?: { readonly parse: (sourceText: string, options: Record<string, unknown>) => unknown };
|
|
1454
|
+
readonly goParser?: { readonly parse: (sourceText: string, options: Record<string, unknown>) => unknown };
|
|
1455
|
+
readonly parserOptions?: Record<string, unknown>;
|
|
1456
|
+
readonly mode?: string | number;
|
|
1457
|
+
readonly goVersion?: string;
|
|
1458
|
+
readonly packageName?: string;
|
|
1459
|
+
readonly fileSet?: unknown;
|
|
1460
|
+
readonly fset?: unknown;
|
|
1461
|
+
readonly includeComments?: boolean;
|
|
1462
|
+
readonly buildTags?: readonly string[];
|
|
1463
|
+
readonly generated?: boolean;
|
|
1464
|
+
readonly typeEvidence?: unknown;
|
|
1465
|
+
readonly maxNodes?: number;
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1413
1468
|
export interface TreeSitterNativeImporterAdapterOptions {
|
|
1414
1469
|
readonly id?: string;
|
|
1415
1470
|
readonly language?: FrontierSourceLanguage;
|
|
@@ -1781,6 +1836,8 @@ export declare function createBabelNativeImporterAdapter(options?: JavaScriptNat
|
|
|
1781
1836
|
export declare function createTypeScriptCompilerNativeImporterAdapter(options?: TypeScriptCompilerNativeImporterAdapterOptions): NativeImporterAdapter;
|
|
1782
1837
|
export declare function createPythonAstNativeImporterAdapter(options?: PythonAstNativeImporterAdapterOptions): NativeImporterAdapter;
|
|
1783
1838
|
export declare function createRustSynNativeImporterAdapter(options?: RustSynNativeImporterAdapterOptions): NativeImporterAdapter;
|
|
1839
|
+
export declare function createClangAstNativeImporterAdapter(options?: ClangAstNativeImporterAdapterOptions): NativeImporterAdapter;
|
|
1840
|
+
export declare function createGoAstNativeImporterAdapter(options?: GoAstNativeImporterAdapterOptions): NativeImporterAdapter;
|
|
1784
1841
|
export declare function createTreeSitterNativeImporterAdapter(options?: TreeSitterNativeImporterAdapterOptions): NativeImporterAdapter;
|
|
1785
1842
|
export declare function runNativeImporterAdapter(adapter: NativeImporterAdapter, input: RunNativeImporterAdapterOptions): Promise<NativeImporterAdapterImportResult>;
|
|
1786
1843
|
export declare function runNativeTargetProjectionAdapter(adapter: NativeTargetProjectionAdapter, input: NativeTargetProjectionAdapterInput): NativeTargetProjectionResult;
|
package/dist/index.js
CHANGED
|
@@ -403,6 +403,30 @@ export const NativeParserAstFormatProfiles = Object.freeze([
|
|
|
403
403
|
supportsErrorRecovery: true,
|
|
404
404
|
notes: ['rust-analyzer uses rowan-backed concrete syntax trees with AST wrappers; semantic richness still depends on host analysis evidence.']
|
|
405
405
|
}),
|
|
406
|
+
nativeParserAstFormatProfile('clang-ast-json', {
|
|
407
|
+
aliases: ['clang', 'libclang', 'clang-json', 'clang-ast-dump-json'],
|
|
408
|
+
kind: 'compiler-ast',
|
|
409
|
+
languages: ['c', 'cpp'],
|
|
410
|
+
parserAdapters: ['clang', 'libclang', 'clang-ast-json'],
|
|
411
|
+
exactness: 'exact-parser-ast',
|
|
412
|
+
sourceRangeModel: 'clang-loc-range',
|
|
413
|
+
preservesTokens: false,
|
|
414
|
+
preservesTrivia: false,
|
|
415
|
+
supportsErrorRecovery: false,
|
|
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
|
+
}),
|
|
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
|
+
}),
|
|
406
430
|
nativeParserAstFormatProfile('tree-sitter', {
|
|
407
431
|
kind: 'concrete-syntax-tree',
|
|
408
432
|
languages: ['mixed'],
|
|
@@ -2711,6 +2735,126 @@ export function createRustSynNativeImporterAdapter(options = {}) {
|
|
|
2711
2735
|
};
|
|
2712
2736
|
}
|
|
2713
2737
|
|
|
2738
|
+
export function createClangAstNativeImporterAdapter(options = {}) {
|
|
2739
|
+
return {
|
|
2740
|
+
id: options.id ?? 'frontier.clang-ast-native-importer',
|
|
2741
|
+
language: options.language ?? 'c',
|
|
2742
|
+
parser: options.parser ?? 'clang',
|
|
2743
|
+
version: options.version,
|
|
2744
|
+
capabilities: uniqueStrings(['nativeAst', 'semanticIndex', 'sourceMaps', 'diagnostics', ...(options.capabilities ?? [])]),
|
|
2745
|
+
coverage: nativeImporterAdapterCoverage({
|
|
2746
|
+
exactness: 'exact-parser-ast',
|
|
2747
|
+
exactAst: true,
|
|
2748
|
+
tokens: false,
|
|
2749
|
+
trivia: false,
|
|
2750
|
+
diagnostics: true,
|
|
2751
|
+
sourceRanges: true,
|
|
2752
|
+
generatedRanges: false,
|
|
2753
|
+
semanticCoverage: declarationSemanticCoverage(),
|
|
2754
|
+
notes: [
|
|
2755
|
+
'Normalizes caller-owned Clang -ast-dump=json shaped ASTs into native AST nodes and declaration-level semantic index records.',
|
|
2756
|
+
'Clang JSON ASTs reflect a preprocessed compiler view; compile commands, macros, inactive preprocessor branches, comments/trivia, and full type/reference analysis require host evidence.'
|
|
2757
|
+
]
|
|
2758
|
+
}, options.coverage),
|
|
2759
|
+
supportedExtensions: options.supportedExtensions ?? ['.c', '.h', '.cc', '.cpp', '.cxx', '.hpp', '.hh'],
|
|
2760
|
+
diagnostics: options.diagnostics,
|
|
2761
|
+
parse(input) {
|
|
2762
|
+
const parsed = input.options?.ast
|
|
2763
|
+
?? input.options?.nativeAst
|
|
2764
|
+
?? input.options?.translationUnit
|
|
2765
|
+
?? input.options?.tu
|
|
2766
|
+
?? options.ast
|
|
2767
|
+
?? options.translationUnit
|
|
2768
|
+
?? options.tu
|
|
2769
|
+
?? parseClangAstSource(input, options);
|
|
2770
|
+
const root = clangAstRoot(parsed);
|
|
2771
|
+
if (!root) {
|
|
2772
|
+
return missingInjectedParserResult(input, {
|
|
2773
|
+
parser: options.parser ?? 'clang',
|
|
2774
|
+
adapterId: options.id ?? 'frontier.clang-ast-native-importer',
|
|
2775
|
+
message: 'createClangAstNativeImporterAdapter requires an injected Clang JSON AST object, parserModule.parse function, parse function, or adapterOptions.ast.'
|
|
2776
|
+
});
|
|
2777
|
+
}
|
|
2778
|
+
const parseDiagnostics = normalizeParserErrors(parsed?.errors ?? parsed?.diagnostics, input, {
|
|
2779
|
+
parser: options.parser ?? 'clang'
|
|
2780
|
+
});
|
|
2781
|
+
return createNativeImportFromClangAst(root, input, {
|
|
2782
|
+
parser: options.parser ?? 'clang',
|
|
2783
|
+
astFormat: 'clang-ast-json',
|
|
2784
|
+
maxNodes: options.maxNodes,
|
|
2785
|
+
diagnostics: parseDiagnostics,
|
|
2786
|
+
cStandard: options.cStandard ?? input.options?.cStandard ?? parsed?.cStandard,
|
|
2787
|
+
compileFlags: options.compileFlags ?? input.options?.compileFlags ?? parsed?.compileFlags,
|
|
2788
|
+
includeSystemHeaders: options.includeSystemHeaders ?? input.options?.includeSystemHeaders,
|
|
2789
|
+
preprocessorRecords: input.options?.preprocessorRecords ?? options.preprocessorRecords ?? parsed?.preprocessorRecords,
|
|
2790
|
+
includeGraph: input.options?.includeGraph ?? options.includeGraph ?? parsed?.includeGraph
|
|
2791
|
+
});
|
|
2792
|
+
}
|
|
2793
|
+
};
|
|
2794
|
+
}
|
|
2795
|
+
|
|
2796
|
+
export function createGoAstNativeImporterAdapter(options = {}) {
|
|
2797
|
+
return {
|
|
2798
|
+
id: options.id ?? 'frontier.go-ast-native-importer',
|
|
2799
|
+
language: options.language ?? 'go',
|
|
2800
|
+
parser: options.parser ?? 'go/parser',
|
|
2801
|
+
version: options.version,
|
|
2802
|
+
capabilities: uniqueStrings(['nativeAst', 'semanticIndex', 'sourceMaps', 'diagnostics', ...(options.capabilities ?? [])]),
|
|
2803
|
+
coverage: nativeImporterAdapterCoverage({
|
|
2804
|
+
exactness: 'exact-parser-ast',
|
|
2805
|
+
exactAst: true,
|
|
2806
|
+
tokens: false,
|
|
2807
|
+
trivia: false,
|
|
2808
|
+
diagnostics: true,
|
|
2809
|
+
sourceRanges: true,
|
|
2810
|
+
generatedRanges: false,
|
|
2811
|
+
semanticCoverage: declarationSemanticCoverage(),
|
|
2812
|
+
notes: [
|
|
2813
|
+
'Normalizes caller-owned Go go/ast-shaped File or Package trees into native AST nodes and declaration-level semantic index records.',
|
|
2814
|
+
'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.'
|
|
2815
|
+
]
|
|
2816
|
+
}, options.coverage),
|
|
2817
|
+
supportedExtensions: options.supportedExtensions ?? ['.go'],
|
|
2818
|
+
diagnostics: options.diagnostics,
|
|
2819
|
+
parse(input) {
|
|
2820
|
+
const parsed = input.options?.ast
|
|
2821
|
+
?? input.options?.nativeAst
|
|
2822
|
+
?? input.options?.file
|
|
2823
|
+
?? input.options?.sourceFile
|
|
2824
|
+
?? input.options?.package
|
|
2825
|
+
?? options.ast
|
|
2826
|
+
?? options.file
|
|
2827
|
+
?? options.sourceFile
|
|
2828
|
+
?? options.package
|
|
2829
|
+
?? parseGoAstSource(input, options);
|
|
2830
|
+
const root = goAstRoot(parsed);
|
|
2831
|
+
if (!root) {
|
|
2832
|
+
return missingInjectedParserResult(input, {
|
|
2833
|
+
parser: options.parser ?? 'go/parser',
|
|
2834
|
+
adapterId: options.id ?? 'frontier.go-ast-native-importer',
|
|
2835
|
+
message: 'createGoAstNativeImporterAdapter requires an injected Go ast.File/Package-shaped object, parserModule.parse function, parse function, or adapterOptions.ast.'
|
|
2836
|
+
});
|
|
2837
|
+
}
|
|
2838
|
+
const parseDiagnostics = normalizeParserErrors(parsed?.errors ?? parsed?.diagnostics, input, {
|
|
2839
|
+
parser: options.parser ?? 'go/parser'
|
|
2840
|
+
});
|
|
2841
|
+
return createNativeImportFromGoAst(root, input, {
|
|
2842
|
+
parser: options.parser ?? 'go/parser',
|
|
2843
|
+
astFormat: 'go-ast',
|
|
2844
|
+
maxNodes: options.maxNodes,
|
|
2845
|
+
diagnostics: parseDiagnostics,
|
|
2846
|
+
goVersion: options.goVersion ?? input.options?.goVersion ?? parsed?.goVersion,
|
|
2847
|
+
packageName: options.packageName ?? input.options?.packageName ?? parsed?.packageName ?? root?.Name?.Name ?? root?.Name,
|
|
2848
|
+
fileSet: input.options?.fileSet ?? input.options?.fset ?? options.fileSet ?? options.fset ?? parsed?.fileSet ?? parsed?.fset,
|
|
2849
|
+
includeComments: options.includeComments ?? input.options?.includeComments,
|
|
2850
|
+
buildTags: input.options?.buildTags ?? options.buildTags ?? parsed?.buildTags,
|
|
2851
|
+
generated: input.options?.generated ?? options.generated ?? parsed?.generated,
|
|
2852
|
+
typeEvidence: input.options?.typeEvidence ?? options.typeEvidence ?? parsed?.typeEvidence
|
|
2853
|
+
});
|
|
2854
|
+
}
|
|
2855
|
+
};
|
|
2856
|
+
}
|
|
2857
|
+
|
|
2714
2858
|
export function createTreeSitterNativeImporterAdapter(options = {}) {
|
|
2715
2859
|
return {
|
|
2716
2860
|
id: options.id ?? `frontier.tree-sitter-${idFragment(options.language ?? 'source')}-native-importer`,
|
|
@@ -7151,6 +7295,8 @@ function parserAstFormatIdForParser(parser) {
|
|
|
7151
7295
|
if (text.includes('python') && text.includes('ast')) return 'python-ast';
|
|
7152
7296
|
if (text === 'syn' || text.includes('rust-syn')) return 'rust-syn';
|
|
7153
7297
|
if (text.includes('rust-analyzer') || text.includes('rowan')) return 'rust-analyzer-rowan';
|
|
7298
|
+
if (text.includes('clang') || text.includes('libclang')) return 'clang-ast-json';
|
|
7299
|
+
if (text === 'go' || text.includes('go-parser') || text.includes('go-ast') || text.includes('go/parser') || text.includes('go/ast')) return 'go-ast';
|
|
7154
7300
|
if (text.includes('tree-sitter') || text.includes('treesitter')) return 'tree-sitter';
|
|
7155
7301
|
if (text.includes('babel')) return 'babel';
|
|
7156
7302
|
if (text.includes('estree')) return 'estree';
|
|
@@ -8199,6 +8345,39 @@ function parseRustSynSource(input, options) {
|
|
|
8199
8345
|
return parse(input.sourceText, parserOptions);
|
|
8200
8346
|
}
|
|
8201
8347
|
|
|
8348
|
+
function parseClangAstSource(input, options) {
|
|
8349
|
+
const parse = options.parse ?? options.parserModule?.parse ?? options.clang?.parse ?? options.libclang?.parse;
|
|
8350
|
+
if (typeof parse !== 'function') return undefined;
|
|
8351
|
+
const parserOptions = {
|
|
8352
|
+
sourcePath: input.sourcePath,
|
|
8353
|
+
filename: input.sourcePath,
|
|
8354
|
+
language: options.language ?? input.language,
|
|
8355
|
+
standard: options.cStandard ?? input.options?.cStandard,
|
|
8356
|
+
compileFlags: options.compileFlags ?? input.options?.compileFlags,
|
|
8357
|
+
includeSystemHeaders: options.includeSystemHeaders ?? input.options?.includeSystemHeaders,
|
|
8358
|
+
astDumpFormat: 'json',
|
|
8359
|
+
...(options.parserOptions ?? {}),
|
|
8360
|
+
...(input.options?.parserOptions ?? {})
|
|
8361
|
+
};
|
|
8362
|
+
return parse(input.sourceText, parserOptions);
|
|
8363
|
+
}
|
|
8364
|
+
|
|
8365
|
+
function parseGoAstSource(input, options) {
|
|
8366
|
+
const parse = options.parse ?? options.parserModule?.parse ?? options.goAst?.parse ?? options.goParser?.parse;
|
|
8367
|
+
if (typeof parse !== 'function') return undefined;
|
|
8368
|
+
const parserOptions = {
|
|
8369
|
+
sourcePath: input.sourcePath,
|
|
8370
|
+
filename: input.sourcePath,
|
|
8371
|
+
mode: options.mode ?? input.options?.mode ?? 'ParseComments',
|
|
8372
|
+
goVersion: options.goVersion ?? input.options?.goVersion,
|
|
8373
|
+
packageName: options.packageName ?? input.options?.packageName,
|
|
8374
|
+
includeComments: options.includeComments ?? input.options?.includeComments,
|
|
8375
|
+
...(options.parserOptions ?? {}),
|
|
8376
|
+
...(input.options?.parserOptions ?? {})
|
|
8377
|
+
};
|
|
8378
|
+
return parse(input.sourceText, parserOptions);
|
|
8379
|
+
}
|
|
8380
|
+
|
|
8202
8381
|
function createNativeImportFromSyntaxAst(ast, input, options) {
|
|
8203
8382
|
const root = normalizeSyntaxAstRoot(ast, options.astFormat);
|
|
8204
8383
|
if (!root) {
|
|
@@ -8319,6 +8498,77 @@ function createNativeImportFromRustSyn(root, input, options) {
|
|
|
8319
8498
|
};
|
|
8320
8499
|
}
|
|
8321
8500
|
|
|
8501
|
+
function createNativeImportFromClangAst(root, input, options) {
|
|
8502
|
+
const context = createAstNormalizationContext(input, options);
|
|
8503
|
+
visitClangAstNode(root, context, 'root');
|
|
8504
|
+
for (const [index, record] of clangPreprocessorRecords(options.preprocessorRecords).entries()) {
|
|
8505
|
+
visitClangAstNode(record, context, `preprocessorRecords[${index}]`);
|
|
8506
|
+
}
|
|
8507
|
+
if (context.truncated) {
|
|
8508
|
+
context.losses.push(truncatedAstLoss(input, context, options));
|
|
8509
|
+
}
|
|
8510
|
+
const semantic = semanticIndexFromNativeDeclarations(context.declarations, input, options);
|
|
8511
|
+
return {
|
|
8512
|
+
rootId: context.rootId,
|
|
8513
|
+
nodes: context.nodes,
|
|
8514
|
+
semanticIndex: semantic.semanticIndex,
|
|
8515
|
+
mappings: semantic.mappings,
|
|
8516
|
+
losses: mergeNativeLosses(context.losses, options.diagnostics?.map((diagnostic, index) => adapterDiagnosticToLoss(diagnostic, index, {
|
|
8517
|
+
id: input.adapterId,
|
|
8518
|
+
version: input.adapterVersion
|
|
8519
|
+
}, input)) ?? []),
|
|
8520
|
+
evidence: semantic.evidence,
|
|
8521
|
+
diagnostics: options.diagnostics,
|
|
8522
|
+
metadata: {
|
|
8523
|
+
astFormat: options.astFormat,
|
|
8524
|
+
parser: options.parser,
|
|
8525
|
+
cStandard: options.cStandard,
|
|
8526
|
+
compileFlags: Array.isArray(options.compileFlags) ? options.compileFlags.slice() : options.compileFlags,
|
|
8527
|
+
includeSystemHeaders: Boolean(options.includeSystemHeaders),
|
|
8528
|
+
preprocessorRecordCount: clangPreprocessorRecords(options.preprocessorRecords).length,
|
|
8529
|
+
includeGraph: serializableIncludeGraphSummary(options.includeGraph),
|
|
8530
|
+
normalizedNodeCount: Object.keys(context.nodes).length,
|
|
8531
|
+
declarationCount: context.declarations.length,
|
|
8532
|
+
truncated: context.truncated
|
|
8533
|
+
}
|
|
8534
|
+
};
|
|
8535
|
+
}
|
|
8536
|
+
|
|
8537
|
+
function createNativeImportFromGoAst(root, input, options) {
|
|
8538
|
+
const context = createAstNormalizationContext(input, options);
|
|
8539
|
+
visitGoAstNode(root, context, 'root');
|
|
8540
|
+
if (context.truncated) {
|
|
8541
|
+
context.losses.push(truncatedAstLoss(input, context, options));
|
|
8542
|
+
}
|
|
8543
|
+
const semantic = semanticIndexFromNativeDeclarations(context.declarations, input, options);
|
|
8544
|
+
return {
|
|
8545
|
+
rootId: context.rootId,
|
|
8546
|
+
nodes: context.nodes,
|
|
8547
|
+
semanticIndex: semantic.semanticIndex,
|
|
8548
|
+
mappings: semantic.mappings,
|
|
8549
|
+
losses: mergeNativeLosses(context.losses, options.diagnostics?.map((diagnostic, index) => adapterDiagnosticToLoss(diagnostic, index, {
|
|
8550
|
+
id: input.adapterId,
|
|
8551
|
+
version: input.adapterVersion
|
|
8552
|
+
}, input)) ?? []),
|
|
8553
|
+
evidence: semantic.evidence,
|
|
8554
|
+
diagnostics: options.diagnostics,
|
|
8555
|
+
metadata: {
|
|
8556
|
+
astFormat: options.astFormat,
|
|
8557
|
+
parser: options.parser,
|
|
8558
|
+
goVersion: options.goVersion,
|
|
8559
|
+
packageName: options.packageName,
|
|
8560
|
+
includeComments: Boolean(options.includeComments),
|
|
8561
|
+
buildTags: Array.isArray(options.buildTags) ? options.buildTags.slice() : options.buildTags,
|
|
8562
|
+
generated: options.generated,
|
|
8563
|
+
fileSetEvidence: Boolean(options.fileSet),
|
|
8564
|
+
typeEvidence: goTypeEvidenceSummary(options.typeEvidence),
|
|
8565
|
+
normalizedNodeCount: Object.keys(context.nodes).length,
|
|
8566
|
+
declarationCount: context.declarations.length,
|
|
8567
|
+
truncated: context.truncated
|
|
8568
|
+
}
|
|
8569
|
+
};
|
|
8570
|
+
}
|
|
8571
|
+
|
|
8322
8572
|
function createNativeImportFromTreeSitter(root, input, options) {
|
|
8323
8573
|
const context = createAstNormalizationContext(input, options);
|
|
8324
8574
|
visitTreeSitterNode(root, context, 'root');
|
|
@@ -8563,6 +8813,165 @@ function visitRustSynNode(node, context, propertyPath) {
|
|
|
8563
8813
|
return id;
|
|
8564
8814
|
}
|
|
8565
8815
|
|
|
8816
|
+
function visitClangAstNode(node, context, propertyPath) {
|
|
8817
|
+
if (!isClangAstNode(node) || context.truncated) return undefined;
|
|
8818
|
+
if (context.objectIds.has(node)) return context.objectIds.get(node);
|
|
8819
|
+
if (context.counter >= context.maxNodes) {
|
|
8820
|
+
context.truncated = true;
|
|
8821
|
+
return undefined;
|
|
8822
|
+
}
|
|
8823
|
+
const kind = clangAstKind(node);
|
|
8824
|
+
const span = spanFromClangAstNode(node, context.input);
|
|
8825
|
+
const id = nativeNodeId(context, kind, { start: { line: span?.startLine, column: span?.startColumn } }, propertyPath);
|
|
8826
|
+
context.objectIds.set(node, id);
|
|
8827
|
+
if (!context.rootId) context.rootId = id;
|
|
8828
|
+
const children = [];
|
|
8829
|
+
for (const [field, value] of clangAstChildEntries(node)) {
|
|
8830
|
+
if (Array.isArray(value)) {
|
|
8831
|
+
value.forEach((entry, index) => {
|
|
8832
|
+
const childId = visitClangAstNode(entry, context, `${propertyPath}.${field}[${index}]`);
|
|
8833
|
+
if (childId) children.push(childId);
|
|
8834
|
+
});
|
|
8835
|
+
} else {
|
|
8836
|
+
const childId = visitClangAstNode(value, context, `${propertyPath}.${field}`);
|
|
8837
|
+
if (childId) children.push(childId);
|
|
8838
|
+
}
|
|
8839
|
+
}
|
|
8840
|
+
const declaration = clangAstDeclaration(node, kind, id, context.input);
|
|
8841
|
+
const nativeNode = {
|
|
8842
|
+
id,
|
|
8843
|
+
kind,
|
|
8844
|
+
languageKind: `${context.input.language}.${kind}`,
|
|
8845
|
+
span,
|
|
8846
|
+
value: declaration?.name ?? clangAstNodeValue(node),
|
|
8847
|
+
fields: primitiveClangAstFields(node, kind),
|
|
8848
|
+
children,
|
|
8849
|
+
metadata: {
|
|
8850
|
+
astFormat: context.options.astFormat,
|
|
8851
|
+
propertyPath,
|
|
8852
|
+
clangId: typeof node.id === 'string' || typeof node.id === 'number' ? String(node.id) : undefined,
|
|
8853
|
+
locationKind: clangLocationKind(node)
|
|
8854
|
+
}
|
|
8855
|
+
};
|
|
8856
|
+
context.nodes[id] = nativeNode;
|
|
8857
|
+
if (declaration) context.declarations.push({ ...declaration, nativeNode });
|
|
8858
|
+
if (clangPreprocessorKind(kind)) {
|
|
8859
|
+
context.losses.push({
|
|
8860
|
+
id: `loss_${idFragment(id)}_clang_preprocessor`,
|
|
8861
|
+
severity: 'warning',
|
|
8862
|
+
phase: 'parse',
|
|
8863
|
+
sourceFormat: context.input.language,
|
|
8864
|
+
kind: 'preprocessor',
|
|
8865
|
+
message: 'Clang AST preprocessor records were imported, but macro expansion, inactive branches, and compile-command provenance require host evidence.',
|
|
8866
|
+
span,
|
|
8867
|
+
nodeId: id,
|
|
8868
|
+
metadata: {
|
|
8869
|
+
parser: context.options.parser,
|
|
8870
|
+
astFormat: context.options.astFormat
|
|
8871
|
+
}
|
|
8872
|
+
});
|
|
8873
|
+
}
|
|
8874
|
+
return id;
|
|
8875
|
+
}
|
|
8876
|
+
|
|
8877
|
+
function visitGoAstNode(node, context, propertyPath) {
|
|
8878
|
+
if (!isGoAstNode(node) || context.truncated) return undefined;
|
|
8879
|
+
if (context.objectIds.has(node)) return context.objectIds.get(node);
|
|
8880
|
+
if (context.counter >= context.maxNodes) {
|
|
8881
|
+
context.truncated = true;
|
|
8882
|
+
return undefined;
|
|
8883
|
+
}
|
|
8884
|
+
const kind = goAstKind(node);
|
|
8885
|
+
const span = spanFromGoAstNode(node, context.input, context.options);
|
|
8886
|
+
const id = nativeNodeId(context, kind, { start: { line: span?.startLine, column: span?.startColumn } }, propertyPath);
|
|
8887
|
+
context.objectIds.set(node, id);
|
|
8888
|
+
if (!context.rootId) context.rootId = id;
|
|
8889
|
+
const children = [];
|
|
8890
|
+
for (const [field, value] of goAstChildEntries(node)) {
|
|
8891
|
+
if (Array.isArray(value)) {
|
|
8892
|
+
value.forEach((entry, index) => {
|
|
8893
|
+
const childId = visitGoAstNode(entry, context, `${propertyPath}.${field}[${index}]`);
|
|
8894
|
+
if (childId) children.push(childId);
|
|
8895
|
+
});
|
|
8896
|
+
} else {
|
|
8897
|
+
const childId = visitGoAstNode(value, context, `${propertyPath}.${field}`);
|
|
8898
|
+
if (childId) children.push(childId);
|
|
8899
|
+
}
|
|
8900
|
+
}
|
|
8901
|
+
const declarations = goAstDeclarations(node, kind, id, context.input);
|
|
8902
|
+
const declaration = declarations[0];
|
|
8903
|
+
const nativeNode = {
|
|
8904
|
+
id,
|
|
8905
|
+
kind,
|
|
8906
|
+
languageKind: `${context.input.language}.${kind}`,
|
|
8907
|
+
span,
|
|
8908
|
+
value: declaration?.name ?? goAstNodeValue(node),
|
|
8909
|
+
fields: primitiveGoAstFields(node, kind),
|
|
8910
|
+
children,
|
|
8911
|
+
metadata: {
|
|
8912
|
+
astFormat: context.options.astFormat,
|
|
8913
|
+
propertyPath,
|
|
8914
|
+
positionKind: goAstPositionKind(node),
|
|
8915
|
+
packageName: context.options.packageName
|
|
8916
|
+
}
|
|
8917
|
+
};
|
|
8918
|
+
context.nodes[id] = nativeNode;
|
|
8919
|
+
for (const entry of declarations) {
|
|
8920
|
+
context.declarations.push({ ...entry, nativeNode });
|
|
8921
|
+
}
|
|
8922
|
+
if (goBadAstKind(kind)) {
|
|
8923
|
+
context.losses.push({
|
|
8924
|
+
id: `loss_${idFragment(id)}_go_bad_node`,
|
|
8925
|
+
severity: 'error',
|
|
8926
|
+
phase: 'parse',
|
|
8927
|
+
sourceFormat: context.input.language,
|
|
8928
|
+
kind: 'unsupportedSyntax',
|
|
8929
|
+
message: 'Go parser recovered a BadDecl/BadExpr/BadStmt node; semantic import is partial until syntax errors are resolved.',
|
|
8930
|
+
span,
|
|
8931
|
+
nodeId: id,
|
|
8932
|
+
metadata: {
|
|
8933
|
+
parser: context.options.parser,
|
|
8934
|
+
astFormat: context.options.astFormat,
|
|
8935
|
+
nodeKind: kind
|
|
8936
|
+
}
|
|
8937
|
+
});
|
|
8938
|
+
}
|
|
8939
|
+
if (kind === 'FuncDecl' && goReceiverFieldCount(node) > 1) {
|
|
8940
|
+
context.losses.push({
|
|
8941
|
+
id: `loss_${idFragment(id)}_go_multiple_receivers`,
|
|
8942
|
+
severity: 'warning',
|
|
8943
|
+
phase: 'parse',
|
|
8944
|
+
sourceFormat: context.input.language,
|
|
8945
|
+
kind: 'unsupportedSyntax',
|
|
8946
|
+
message: 'Go parser accepted multiple receiver fields; valid method ownership requires a single receiver.',
|
|
8947
|
+
span,
|
|
8948
|
+
nodeId: id,
|
|
8949
|
+
metadata: {
|
|
8950
|
+
parser: context.options.parser,
|
|
8951
|
+
astFormat: context.options.astFormat,
|
|
8952
|
+
receiverFieldCount: goReceiverFieldCount(node)
|
|
8953
|
+
}
|
|
8954
|
+
});
|
|
8955
|
+
}
|
|
8956
|
+
if (goGeneratedCodeMarker(node, kind)) {
|
|
8957
|
+
context.losses.push({
|
|
8958
|
+
id: `loss_${idFragment(id)}_go_generated_code`,
|
|
8959
|
+
severity: 'warning',
|
|
8960
|
+
phase: 'parse',
|
|
8961
|
+
sourceFormat: context.input.language,
|
|
8962
|
+
kind: 'generatedCode',
|
|
8963
|
+
message: 'Go generated-code marker was imported; regeneration provenance and source ownership require host evidence.',
|
|
8964
|
+
span,
|
|
8965
|
+
nodeId: id,
|
|
8966
|
+
metadata: {
|
|
8967
|
+
parser: context.options.parser,
|
|
8968
|
+
astFormat: context.options.astFormat
|
|
8969
|
+
}
|
|
8970
|
+
});
|
|
8971
|
+
}
|
|
8972
|
+
return id;
|
|
8973
|
+
}
|
|
8974
|
+
|
|
8566
8975
|
function visitTreeSitterNode(node, context, propertyPath) {
|
|
8567
8976
|
if (!node || typeof node !== 'object' || context.truncated) return undefined;
|
|
8568
8977
|
if (context.objectIds.has(node)) return context.objectIds.get(node);
|
|
@@ -10229,6 +10638,575 @@ function rustSynMacroKind(kind) {
|
|
|
10229
10638
|
return /Macro|MacroRules|MacroCall/.test(String(kind));
|
|
10230
10639
|
}
|
|
10231
10640
|
|
|
10641
|
+
function clangAstRoot(value) {
|
|
10642
|
+
if (!value || typeof value !== 'object') return undefined;
|
|
10643
|
+
if (Array.isArray(value)) return { kind: 'TranslationUnitDecl', inner: value };
|
|
10644
|
+
if (isClangAstNode(value)) return value;
|
|
10645
|
+
if (Array.isArray(value.ast)) return { kind: 'TranslationUnitDecl', inner: value.ast };
|
|
10646
|
+
if (isClangAstNode(value.ast)) return value.ast;
|
|
10647
|
+
if (isClangAstNode(value.root)) return value.root;
|
|
10648
|
+
if (isClangAstNode(value.translationUnit)) return value.translationUnit;
|
|
10649
|
+
if (isClangAstNode(value.tu)) return value.tu;
|
|
10650
|
+
if (isClangAstNode(value.file)) return value.file;
|
|
10651
|
+
if (isClangAstNode(value.sourceFile)) return value.sourceFile;
|
|
10652
|
+
return undefined;
|
|
10653
|
+
}
|
|
10654
|
+
|
|
10655
|
+
function isClangAstNode(value) {
|
|
10656
|
+
return Boolean(value && typeof value === 'object' && typeof clangAstKind(value) === 'string');
|
|
10657
|
+
}
|
|
10658
|
+
|
|
10659
|
+
function clangAstKind(node) {
|
|
10660
|
+
if (!node || typeof node !== 'object') return undefined;
|
|
10661
|
+
const declared = node.kind ?? node._type ?? node.type ?? node.nodeType ?? node.declKind ?? node.stmtKind;
|
|
10662
|
+
if (typeof declared === 'string') return declared;
|
|
10663
|
+
if (Array.isArray(node.inner) || Array.isArray(node.children) || Array.isArray(node.decls)) return 'TranslationUnitDecl';
|
|
10664
|
+
return undefined;
|
|
10665
|
+
}
|
|
10666
|
+
|
|
10667
|
+
function ignoredClangAstField(key) {
|
|
10668
|
+
return key === '_type'
|
|
10669
|
+
|| key === 'type'
|
|
10670
|
+
|| key === 'kind'
|
|
10671
|
+
|| key === 'nodeType'
|
|
10672
|
+
|| key === 'declKind'
|
|
10673
|
+
|| key === 'stmtKind'
|
|
10674
|
+
|| key === 'id'
|
|
10675
|
+
|| key === 'loc'
|
|
10676
|
+
|| key === 'range'
|
|
10677
|
+
|| key === 'name'
|
|
10678
|
+
|| key === 'displayName'
|
|
10679
|
+
|| key === 'qualifiedName'
|
|
10680
|
+
|| key === 'mangledName'
|
|
10681
|
+
|| key === 'parent'
|
|
10682
|
+
|| key === 'parentDeclContextId'
|
|
10683
|
+
|| key === 'previousDecl'
|
|
10684
|
+
|| key === 'referencedDecl';
|
|
10685
|
+
}
|
|
10686
|
+
|
|
10687
|
+
function primitiveClangAstFields(node, kind) {
|
|
10688
|
+
const fields = { kind };
|
|
10689
|
+
const name = clangDeclarationName(node);
|
|
10690
|
+
if (name) fields.name = name;
|
|
10691
|
+
const type = clangTypeName(node.type ?? node.qualType);
|
|
10692
|
+
if (type) fields.type = type;
|
|
10693
|
+
for (const key of [
|
|
10694
|
+
'mangledName',
|
|
10695
|
+
'storageClass',
|
|
10696
|
+
'tagUsed',
|
|
10697
|
+
'completeDefinition',
|
|
10698
|
+
'isThisDeclarationADefinition',
|
|
10699
|
+
'inline',
|
|
10700
|
+
'isUsed',
|
|
10701
|
+
'isReferenced',
|
|
10702
|
+
'valueCategory',
|
|
10703
|
+
'opcode',
|
|
10704
|
+
'castKind'
|
|
10705
|
+
]) {
|
|
10706
|
+
const value = node[key];
|
|
10707
|
+
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean' || value === null) fields[key] = value;
|
|
10708
|
+
}
|
|
10709
|
+
const includePath = clangIncludePath(node);
|
|
10710
|
+
if (includePath) fields.includePath = includePath;
|
|
10711
|
+
const literal = clangLiteralValue(node);
|
|
10712
|
+
if (literal !== undefined) fields.literal = literal;
|
|
10713
|
+
const referenced = clangDeclarationName(node.referencedDecl);
|
|
10714
|
+
if (referenced) fields.referenced = referenced;
|
|
10715
|
+
return fields;
|
|
10716
|
+
}
|
|
10717
|
+
|
|
10718
|
+
function spanFromClangAstNode(node, input) {
|
|
10719
|
+
const range = node.range ?? {};
|
|
10720
|
+
const begin = range.begin ?? node.loc ?? node.spellingLoc ?? node.expansionLoc;
|
|
10721
|
+
const end = range.end ?? node.end;
|
|
10722
|
+
const start = clangLocPosition(begin);
|
|
10723
|
+
if (!start) return undefined;
|
|
10724
|
+
const finish = clangLocPosition(end);
|
|
10725
|
+
return {
|
|
10726
|
+
sourceId: input.sourceHash,
|
|
10727
|
+
path: start.path ?? finish?.path ?? input.sourcePath,
|
|
10728
|
+
startLine: start.line,
|
|
10729
|
+
startColumn: start.column,
|
|
10730
|
+
endLine: finish?.line,
|
|
10731
|
+
endColumn: finish?.column
|
|
10732
|
+
};
|
|
10733
|
+
}
|
|
10734
|
+
|
|
10735
|
+
function clangLocPosition(loc) {
|
|
10736
|
+
if (!loc || typeof loc !== 'object') return undefined;
|
|
10737
|
+
const expanded = loc.expansionLoc ?? loc.spellingLoc ?? loc;
|
|
10738
|
+
const line = expanded.line ?? expanded.startLine ?? expanded.begin?.line;
|
|
10739
|
+
const column = expanded.col ?? expanded.column ?? expanded.startColumn ?? expanded.begin?.col ?? expanded.begin?.column;
|
|
10740
|
+
if (typeof line !== 'number') return undefined;
|
|
10741
|
+
return {
|
|
10742
|
+
path: expanded.file ?? expanded.filename ?? expanded.path,
|
|
10743
|
+
line,
|
|
10744
|
+
column: typeof column === 'number' ? column : undefined
|
|
10745
|
+
};
|
|
10746
|
+
}
|
|
10747
|
+
|
|
10748
|
+
function clangLocationKind(node) {
|
|
10749
|
+
const loc = node.loc ?? node.range?.begin;
|
|
10750
|
+
if (!loc || typeof loc !== 'object') return undefined;
|
|
10751
|
+
if (loc.expansionLoc) return 'expansionLoc';
|
|
10752
|
+
if (loc.spellingLoc) return 'spellingLoc';
|
|
10753
|
+
if (loc.includedFrom) return 'includedFrom';
|
|
10754
|
+
return 'clang-loc';
|
|
10755
|
+
}
|
|
10756
|
+
|
|
10757
|
+
function clangAstDeclaration(node, kind, nativeNodeId, input) {
|
|
10758
|
+
if (kind === 'FunctionDecl' || kind === 'CXXMethodDecl' || kind === 'FunctionTemplateDecl') {
|
|
10759
|
+
const name = clangDeclarationName(node);
|
|
10760
|
+
if (name) return declarationRecord(input, nativeNodeId, name, kind === 'CXXMethodDecl' ? 'method' : 'function', clangDeclarationAction(node));
|
|
10761
|
+
}
|
|
10762
|
+
if (kind === 'ParmVarDecl') {
|
|
10763
|
+
const name = clangDeclarationName(node);
|
|
10764
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'parameter', 'definition');
|
|
10765
|
+
}
|
|
10766
|
+
if (kind === 'RecordDecl' || kind === 'CXXRecordDecl' || kind === 'ClassTemplateDecl') {
|
|
10767
|
+
const name = clangDeclarationName(node);
|
|
10768
|
+
if (name) return declarationRecord(input, nativeNodeId, name, kind === 'CXXRecordDecl' ? 'class' : 'type', clangDeclarationAction(node));
|
|
10769
|
+
}
|
|
10770
|
+
if (kind === 'FieldDecl') {
|
|
10771
|
+
const name = clangDeclarationName(node);
|
|
10772
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'property', 'definition');
|
|
10773
|
+
}
|
|
10774
|
+
if (kind === 'TypedefDecl' || kind === 'TypeAliasDecl' || kind === 'TypeAliasTemplateDecl') {
|
|
10775
|
+
const name = clangDeclarationName(node);
|
|
10776
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'type', 'definition');
|
|
10777
|
+
}
|
|
10778
|
+
if (kind === 'EnumDecl') {
|
|
10779
|
+
const name = clangDeclarationName(node);
|
|
10780
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'type', clangDeclarationAction(node));
|
|
10781
|
+
}
|
|
10782
|
+
if (kind === 'EnumConstantDecl') {
|
|
10783
|
+
const name = clangDeclarationName(node);
|
|
10784
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'enumMember', 'definition');
|
|
10785
|
+
}
|
|
10786
|
+
if (kind === 'VarDecl') {
|
|
10787
|
+
const name = clangDeclarationName(node);
|
|
10788
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'variable', clangDeclarationAction(node));
|
|
10789
|
+
}
|
|
10790
|
+
if (/IncludeDirective|InclusionDirective/.test(kind)) {
|
|
10791
|
+
const name = clangIncludePath(node);
|
|
10792
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'module', 'import');
|
|
10793
|
+
}
|
|
10794
|
+
if (/MacroDefinition|MacroExpansion|MacroInstantiation/.test(kind)) {
|
|
10795
|
+
const name = clangDeclarationName(node) ?? clangIncludePath(node);
|
|
10796
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'macro', 'definition');
|
|
10797
|
+
}
|
|
10798
|
+
return undefined;
|
|
10799
|
+
}
|
|
10800
|
+
|
|
10801
|
+
function clangDeclarationAction(node) {
|
|
10802
|
+
if (node.isThisDeclarationADefinition === false) return 'declaration';
|
|
10803
|
+
if (node.isThisDeclarationADefinition === true) return 'definition';
|
|
10804
|
+
if (Array.isArray(node.inner) && node.inner.some((entry) => ['CompoundStmt', 'FieldDecl', 'EnumConstantDecl'].includes(clangAstKind(entry)))) return 'definition';
|
|
10805
|
+
return 'declaration';
|
|
10806
|
+
}
|
|
10807
|
+
|
|
10808
|
+
function clangAstChildEntries(node) {
|
|
10809
|
+
const fieldNames = Object.keys(node).filter((key) => !ignoredClangAstField(key));
|
|
10810
|
+
return fieldNames
|
|
10811
|
+
.map((field) => [field, node[field]])
|
|
10812
|
+
.filter(([, value]) => Array.isArray(value)
|
|
10813
|
+
? value.some(isClangAstNode)
|
|
10814
|
+
: isClangAstNode(value));
|
|
10815
|
+
}
|
|
10816
|
+
|
|
10817
|
+
function clangAstNodeValue(node) {
|
|
10818
|
+
return clangDeclarationName(node)
|
|
10819
|
+
?? clangIncludePath(node)
|
|
10820
|
+
?? clangTypeName(node.type ?? node.qualType)
|
|
10821
|
+
?? clangLiteralValue(node);
|
|
10822
|
+
}
|
|
10823
|
+
|
|
10824
|
+
function clangDeclarationName(node) {
|
|
10825
|
+
if (!node || typeof node !== 'object') return undefined;
|
|
10826
|
+
for (const key of ['qualifiedName', 'displayName', 'name', 'mangledName']) {
|
|
10827
|
+
if (typeof node[key] === 'string' && node[key]) return node[key];
|
|
10828
|
+
}
|
|
10829
|
+
if (node.name && typeof node.name === 'object') return clangDeclarationName(node.name);
|
|
10830
|
+
if (node.referencedDecl && typeof node.referencedDecl === 'object') return clangDeclarationName(node.referencedDecl);
|
|
10831
|
+
if (node.decl && typeof node.decl === 'object') return clangDeclarationName(node.decl);
|
|
10832
|
+
return undefined;
|
|
10833
|
+
}
|
|
10834
|
+
|
|
10835
|
+
function clangIncludePath(node) {
|
|
10836
|
+
if (!node || typeof node !== 'object') return undefined;
|
|
10837
|
+
for (const key of ['file', 'filename', 'path', 'spelling', 'source']) {
|
|
10838
|
+
if (typeof node[key] === 'string' && node[key]) return node[key];
|
|
10839
|
+
}
|
|
10840
|
+
if (node.include && typeof node.include === 'object') return clangIncludePath(node.include);
|
|
10841
|
+
return undefined;
|
|
10842
|
+
}
|
|
10843
|
+
|
|
10844
|
+
function clangTypeName(value) {
|
|
10845
|
+
if (!value) return undefined;
|
|
10846
|
+
if (typeof value === 'string') return value;
|
|
10847
|
+
if (typeof value.qualType === 'string') return value.qualType;
|
|
10848
|
+
if (typeof value.desugaredQualType === 'string') return value.desugaredQualType;
|
|
10849
|
+
if (typeof value.name === 'string') return value.name;
|
|
10850
|
+
if (value.type && typeof value.type === 'object') return clangTypeName(value.type);
|
|
10851
|
+
return undefined;
|
|
10852
|
+
}
|
|
10853
|
+
|
|
10854
|
+
function clangLiteralValue(node) {
|
|
10855
|
+
const value = node.value ?? node.val ?? node.literal;
|
|
10856
|
+
if (value === null || typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') return value;
|
|
10857
|
+
if (typeof node.valueAsString === 'string') return node.valueAsString;
|
|
10858
|
+
return undefined;
|
|
10859
|
+
}
|
|
10860
|
+
|
|
10861
|
+
function clangPreprocessorKind(kind) {
|
|
10862
|
+
return /Macro|Preprocess|Preprocessor|IfDirective|IfdefDirective|IfndefDirective|ElifDirective|ElseDirective|EndifDirective/.test(String(kind));
|
|
10863
|
+
}
|
|
10864
|
+
|
|
10865
|
+
function clangPreprocessorRecords(value) {
|
|
10866
|
+
if (!value) return [];
|
|
10867
|
+
if (Array.isArray(value)) return value.filter(isClangAstNode);
|
|
10868
|
+
if (typeof value === 'object' && Array.isArray(value.records)) return value.records.filter(isClangAstNode);
|
|
10869
|
+
if (isClangAstNode(value)) return [value];
|
|
10870
|
+
return [];
|
|
10871
|
+
}
|
|
10872
|
+
|
|
10873
|
+
function serializableIncludeGraphSummary(value) {
|
|
10874
|
+
if (!value || typeof value !== 'object') return undefined;
|
|
10875
|
+
if (Array.isArray(value)) return { edgeCount: value.length };
|
|
10876
|
+
const summary = {};
|
|
10877
|
+
if (typeof value.hash === 'string') summary.hash = value.hash;
|
|
10878
|
+
if (typeof value.root === 'string') summary.root = value.root;
|
|
10879
|
+
if (Array.isArray(value.edges)) summary.edgeCount = value.edges.length;
|
|
10880
|
+
if (Array.isArray(value.includes)) summary.includeCount = value.includes.length;
|
|
10881
|
+
return Object.keys(summary).length ? summary : { present: true };
|
|
10882
|
+
}
|
|
10883
|
+
|
|
10884
|
+
function goAstRoot(value) {
|
|
10885
|
+
if (!value || typeof value !== 'object') return undefined;
|
|
10886
|
+
if (isGoAstNode(value)) return value;
|
|
10887
|
+
if (isGoAstNode(value.ast)) return value.ast;
|
|
10888
|
+
if (isGoAstNode(value.file)) return value.file;
|
|
10889
|
+
if (isGoAstNode(value.sourceFile)) return value.sourceFile;
|
|
10890
|
+
if (isGoAstNode(value.root)) return value.root;
|
|
10891
|
+
if (isGoAstNode(value.package)) return value.package;
|
|
10892
|
+
if (value.files && typeof value.files === 'object') return { kind: 'Package', Name: value.name ?? value.packageName, Files: value.files };
|
|
10893
|
+
return undefined;
|
|
10894
|
+
}
|
|
10895
|
+
|
|
10896
|
+
function isGoAstNode(value) {
|
|
10897
|
+
return Boolean(value && typeof value === 'object' && typeof goAstKind(value) === 'string');
|
|
10898
|
+
}
|
|
10899
|
+
|
|
10900
|
+
function goAstKind(node) {
|
|
10901
|
+
if (!node || typeof node !== 'object') return undefined;
|
|
10902
|
+
const declared = node.kind ?? node._type ?? node.type ?? node.nodeType ?? node.astKind;
|
|
10903
|
+
if (typeof declared === 'string') return normalizeGoAstKind(declared);
|
|
10904
|
+
if (Array.isArray(node.Decls) || Array.isArray(node.decls)) return 'File';
|
|
10905
|
+
if (node.Files || node.files) return 'Package';
|
|
10906
|
+
if (node.Name && node.Type && (node.Body || node.Recv !== undefined || node.recv !== undefined)) return 'FuncDecl';
|
|
10907
|
+
if (node.Tok && (node.Specs || node.specs)) return 'GenDecl';
|
|
10908
|
+
if (node.Path && (node.Name !== undefined || node.EndPos !== undefined)) return 'ImportSpec';
|
|
10909
|
+
if (node.Names && node.Type !== undefined) return 'ValueSpec';
|
|
10910
|
+
if (node.Name && node.Type !== undefined) return 'TypeSpec';
|
|
10911
|
+
if (node.List && (node.Opening !== undefined || node.Closing !== undefined)) return 'FieldList';
|
|
10912
|
+
return undefined;
|
|
10913
|
+
}
|
|
10914
|
+
|
|
10915
|
+
function normalizeGoAstKind(kind) {
|
|
10916
|
+
const text = String(kind).replace(/^(?:ast\.)?\*/, '').replace(/^(?:go\/ast\.)/, '');
|
|
10917
|
+
if (/^file$/i.test(text)) return 'File';
|
|
10918
|
+
if (/^package$/i.test(text)) return 'Package';
|
|
10919
|
+
if (/^funcdecl$/i.test(text) || /^func_decl$/i.test(text)) return 'FuncDecl';
|
|
10920
|
+
if (/^gendecl$/i.test(text) || /^gen_decl$/i.test(text)) return 'GenDecl';
|
|
10921
|
+
if (/^importspec$/i.test(text) || /^import_spec$/i.test(text)) return 'ImportSpec';
|
|
10922
|
+
if (/^typespec$/i.test(text) || /^type_spec$/i.test(text)) return 'TypeSpec';
|
|
10923
|
+
if (/^valuespec$/i.test(text) || /^value_spec$/i.test(text)) return 'ValueSpec';
|
|
10924
|
+
if (/^structtype$/i.test(text) || /^struct_type$/i.test(text)) return 'StructType';
|
|
10925
|
+
if (/^interfacetype$/i.test(text) || /^interface_type$/i.test(text)) return 'InterfaceType';
|
|
10926
|
+
if (/^fieldlist$/i.test(text) || /^field_list$/i.test(text)) return 'FieldList';
|
|
10927
|
+
return text;
|
|
10928
|
+
}
|
|
10929
|
+
|
|
10930
|
+
function ignoredGoAstField(key) {
|
|
10931
|
+
return key === '_type'
|
|
10932
|
+
|| key === 'type'
|
|
10933
|
+
|| key === 'kind'
|
|
10934
|
+
|| key === 'nodeType'
|
|
10935
|
+
|| key === 'astKind'
|
|
10936
|
+
|| key === 'parent'
|
|
10937
|
+
|| key === 'Obj'
|
|
10938
|
+
|| key === 'object'
|
|
10939
|
+
|| key === 'Scope'
|
|
10940
|
+
|| key === 'scope'
|
|
10941
|
+
|| key === 'Unresolved'
|
|
10942
|
+
|| key === 'unresolved'
|
|
10943
|
+
|| key === 'FileStart'
|
|
10944
|
+
|| key === 'FileEnd'
|
|
10945
|
+
|| key === 'Package'
|
|
10946
|
+
|| key === 'Name'
|
|
10947
|
+
|| key === 'Path'
|
|
10948
|
+
|| key === 'Pos'
|
|
10949
|
+
|| key === 'End'
|
|
10950
|
+
|| key === 'pos'
|
|
10951
|
+
|| key === 'end';
|
|
10952
|
+
}
|
|
10953
|
+
|
|
10954
|
+
function primitiveGoAstFields(node, kind) {
|
|
10955
|
+
const fields = { kind };
|
|
10956
|
+
const name = goAstDeclarationName(node);
|
|
10957
|
+
if (name) fields.name = name;
|
|
10958
|
+
const type = goAstTypeName(node.Type ?? node.type);
|
|
10959
|
+
if (type) fields.type = type;
|
|
10960
|
+
const tok = goAstTokenName(node.Tok ?? node.tok);
|
|
10961
|
+
if (tok) fields.token = tok;
|
|
10962
|
+
const importPath = goAstImportPath(node);
|
|
10963
|
+
if (importPath) fields.importPath = importPath;
|
|
10964
|
+
const receiver = goAstReceiverName(node);
|
|
10965
|
+
if (receiver) fields.receiver = receiver;
|
|
10966
|
+
for (const key of ['Incomplete', 'Doc', 'Comment']) {
|
|
10967
|
+
const value = node[key] ?? node[key[0].toLowerCase() + key.slice(1)];
|
|
10968
|
+
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean' || value === null) fields[key[0].toLowerCase() + key.slice(1)] = value;
|
|
10969
|
+
}
|
|
10970
|
+
if (Array.isArray(node.Names ?? node.names)) {
|
|
10971
|
+
fields.names = (node.Names ?? node.names).map(goAstIdentName).filter(Boolean).join(',');
|
|
10972
|
+
}
|
|
10973
|
+
return fields;
|
|
10974
|
+
}
|
|
10975
|
+
|
|
10976
|
+
function spanFromGoAstNode(node, input, options = {}) {
|
|
10977
|
+
const start = goAstPosition(node.Pos ?? node.pos ?? node.Name?.NamePos ?? node.name?.namePos ?? node.Package, options);
|
|
10978
|
+
const end = goAstPosition(node.End ?? node.end ?? node.EndPos ?? node.endPos, options);
|
|
10979
|
+
if (!start) return undefined;
|
|
10980
|
+
return {
|
|
10981
|
+
sourceId: input.sourceHash,
|
|
10982
|
+
path: start.path ?? end?.path ?? input.sourcePath,
|
|
10983
|
+
startLine: start.line,
|
|
10984
|
+
startColumn: start.column,
|
|
10985
|
+
endLine: end?.line,
|
|
10986
|
+
endColumn: end?.column
|
|
10987
|
+
};
|
|
10988
|
+
}
|
|
10989
|
+
|
|
10990
|
+
function goAstPosition(value, options = {}) {
|
|
10991
|
+
if (!value) return undefined;
|
|
10992
|
+
if (typeof value === 'object') {
|
|
10993
|
+
const position = value.position ?? value.Position ?? value.pos ?? value.Pos ?? value;
|
|
10994
|
+
const line = position.Line ?? position.line;
|
|
10995
|
+
const column = position.Column ?? position.column ?? position.Col ?? position.col;
|
|
10996
|
+
if (typeof line === 'number') {
|
|
10997
|
+
return {
|
|
10998
|
+
path: position.Filename ?? position.filename ?? position.file ?? position.path,
|
|
10999
|
+
line,
|
|
11000
|
+
column: typeof column === 'number' ? column : undefined
|
|
11001
|
+
};
|
|
11002
|
+
}
|
|
11003
|
+
}
|
|
11004
|
+
const fileSet = options.fileSet ?? options.fset;
|
|
11005
|
+
const positionFor = typeof fileSet?.PositionFor === 'function'
|
|
11006
|
+
? fileSet.PositionFor.bind(fileSet)
|
|
11007
|
+
: typeof fileSet?.positionFor === 'function'
|
|
11008
|
+
? fileSet.positionFor.bind(fileSet)
|
|
11009
|
+
: typeof fileSet?.Position === 'function'
|
|
11010
|
+
? fileSet.Position.bind(fileSet)
|
|
11011
|
+
: typeof fileSet?.position === 'function'
|
|
11012
|
+
? fileSet.position.bind(fileSet)
|
|
11013
|
+
: undefined;
|
|
11014
|
+
if (positionFor) {
|
|
11015
|
+
const resolved = positionFor(value, true);
|
|
11016
|
+
return goAstPosition(resolved, options);
|
|
11017
|
+
}
|
|
11018
|
+
return undefined;
|
|
11019
|
+
}
|
|
11020
|
+
|
|
11021
|
+
function goAstPositionKind(node) {
|
|
11022
|
+
const pos = node.Pos ?? node.pos ?? node.Name?.NamePos ?? node.name?.namePos;
|
|
11023
|
+
if (!pos) return undefined;
|
|
11024
|
+
if (typeof pos === 'object') return 'token.Position';
|
|
11025
|
+
return 'token.Pos';
|
|
11026
|
+
}
|
|
11027
|
+
|
|
11028
|
+
function goAstDeclarations(node, kind, nativeNodeId, input) {
|
|
11029
|
+
if (kind === 'ImportSpec') {
|
|
11030
|
+
const name = goAstImportPath(node);
|
|
11031
|
+
return name ? [declarationRecord(input, nativeNodeId, name, 'module', 'import')] : [];
|
|
11032
|
+
}
|
|
11033
|
+
if (kind === 'FuncDecl') {
|
|
11034
|
+
const name = goAstDeclarationName(node);
|
|
11035
|
+
if (!name) return [];
|
|
11036
|
+
const receiver = goAstReceiverName(node);
|
|
11037
|
+
return [declarationRecord(input, nativeNodeId, receiver ? `${receiver}.${name}` : name, receiver ? 'method' : 'function', node.Body || node.body ? 'definition' : 'declaration')];
|
|
11038
|
+
}
|
|
11039
|
+
if (kind === 'TypeSpec') {
|
|
11040
|
+
const name = goAstDeclarationName(node);
|
|
11041
|
+
return name ? [declarationRecord(input, nativeNodeId, name, goAstTypeSpecSymbolKind(node), 'definition')] : [];
|
|
11042
|
+
}
|
|
11043
|
+
if (kind === 'ValueSpec') {
|
|
11044
|
+
const names = goAstValueSpecNames(node);
|
|
11045
|
+
const token = goAstTokenName(node.parentTok ?? node.Tok ?? node.tok);
|
|
11046
|
+
return names.map((name) => declarationRecord(input, nativeNodeId, name, token === 'CONST' || token === 'const' ? 'constant' : 'variable', 'definition'));
|
|
11047
|
+
}
|
|
11048
|
+
if (kind === 'Field') {
|
|
11049
|
+
return goAstValueSpecNames(node).map((name) => declarationRecord(input, nativeNodeId, name, 'property', 'definition'));
|
|
11050
|
+
}
|
|
11051
|
+
if (kind === 'Package' || kind === 'File') {
|
|
11052
|
+
const name = goAstPackageName(node);
|
|
11053
|
+
return name ? [declarationRecord(input, nativeNodeId, name, 'module', 'definition')] : [];
|
|
11054
|
+
}
|
|
11055
|
+
return [];
|
|
11056
|
+
}
|
|
11057
|
+
|
|
11058
|
+
function goAstChildEntries(node) {
|
|
11059
|
+
const fieldNames = Object.keys(node).filter((key) => !ignoredGoAstField(key));
|
|
11060
|
+
const entries = [];
|
|
11061
|
+
for (const field of fieldNames) {
|
|
11062
|
+
const value = node[field];
|
|
11063
|
+
if (field === 'Files' || field === 'files') {
|
|
11064
|
+
if (value && typeof value === 'object') entries.push([field, Array.isArray(value) ? value : Object.values(value)]);
|
|
11065
|
+
continue;
|
|
11066
|
+
}
|
|
11067
|
+
if (field === 'Specs' || field === 'specs') {
|
|
11068
|
+
const token = goAstTokenName(node.Tok ?? node.tok);
|
|
11069
|
+
entries.push([field, Array.isArray(value)
|
|
11070
|
+
? value.map((entry) => entry && typeof entry === 'object' ? { parentTok: token, ...entry } : entry)
|
|
11071
|
+
: value]);
|
|
11072
|
+
continue;
|
|
11073
|
+
}
|
|
11074
|
+
entries.push([field, value]);
|
|
11075
|
+
}
|
|
11076
|
+
return entries.filter(([, value]) => Array.isArray(value)
|
|
11077
|
+
? value.some(isGoAstNode)
|
|
11078
|
+
: isGoAstNode(value));
|
|
11079
|
+
}
|
|
11080
|
+
|
|
11081
|
+
function goAstNodeValue(node) {
|
|
11082
|
+
return goAstDeclarationName(node)
|
|
11083
|
+
?? goAstImportPath(node)
|
|
11084
|
+
?? goAstTypeName(node.Type ?? node.type)
|
|
11085
|
+
?? goAstLiteralValue(node);
|
|
11086
|
+
}
|
|
11087
|
+
|
|
11088
|
+
function goAstDeclarationName(node) {
|
|
11089
|
+
if (!node || typeof node !== 'object') return undefined;
|
|
11090
|
+
return goAstIdentName(node.Name ?? node.name)
|
|
11091
|
+
?? goAstIdentName(node.Ident ?? node.ident)
|
|
11092
|
+
?? goAstIdentName(node.Sel ?? node.sel)
|
|
11093
|
+
?? (typeof node.Name === 'string' ? node.Name : undefined)
|
|
11094
|
+
?? (typeof node.name === 'string' ? node.name : undefined);
|
|
11095
|
+
}
|
|
11096
|
+
|
|
11097
|
+
function goAstPackageName(node) {
|
|
11098
|
+
if (!node || typeof node !== 'object') return undefined;
|
|
11099
|
+
return goAstIdentName(node.Name ?? node.name) ?? node.PackageName ?? node.packageName;
|
|
11100
|
+
}
|
|
11101
|
+
|
|
11102
|
+
function goAstIdentName(value) {
|
|
11103
|
+
if (!value) return undefined;
|
|
11104
|
+
if (typeof value === 'string') return value;
|
|
11105
|
+
return value.Name ?? value.name ?? value.Value ?? value.value;
|
|
11106
|
+
}
|
|
11107
|
+
|
|
11108
|
+
function goAstImportPath(node) {
|
|
11109
|
+
if (!node || typeof node !== 'object') return undefined;
|
|
11110
|
+
const path = node.Path ?? node.path;
|
|
11111
|
+
const raw = typeof path === 'string' ? path : path?.Value ?? path?.value ?? path?.Kind;
|
|
11112
|
+
if (typeof raw !== 'string') return undefined;
|
|
11113
|
+
return raw.replace(/^"|"$/g, '').replace(/^`|`$/g, '');
|
|
11114
|
+
}
|
|
11115
|
+
|
|
11116
|
+
function goAstReceiverName(node) {
|
|
11117
|
+
const recv = node?.Recv ?? node?.recv;
|
|
11118
|
+
const list = recv?.List ?? recv?.list;
|
|
11119
|
+
if (!Array.isArray(list) || !list.length) return undefined;
|
|
11120
|
+
const first = list[0];
|
|
11121
|
+
return goAstTypeName(first?.Type ?? first?.type);
|
|
11122
|
+
}
|
|
11123
|
+
|
|
11124
|
+
function goAstValueSpecName(node) {
|
|
11125
|
+
return goAstValueSpecNames(node)[0];
|
|
11126
|
+
}
|
|
11127
|
+
|
|
11128
|
+
function goAstValueSpecNames(node) {
|
|
11129
|
+
const names = node.Names ?? node.names;
|
|
11130
|
+
if (Array.isArray(names)) return names.map(goAstIdentName).filter(Boolean);
|
|
11131
|
+
const name = goAstDeclarationName(node);
|
|
11132
|
+
return name ? [name] : [];
|
|
11133
|
+
}
|
|
11134
|
+
|
|
11135
|
+
function goAstTypeSpecSymbolKind(node) {
|
|
11136
|
+
const type = node.Type ?? node.type;
|
|
11137
|
+
const kind = goAstKind(type);
|
|
11138
|
+
if (kind === 'InterfaceType') return 'interface';
|
|
11139
|
+
if (kind === 'StructType') return 'class';
|
|
11140
|
+
return 'type';
|
|
11141
|
+
}
|
|
11142
|
+
|
|
11143
|
+
function goAstTypeName(value) {
|
|
11144
|
+
if (!value) return undefined;
|
|
11145
|
+
if (typeof value === 'string') return value;
|
|
11146
|
+
const kind = goAstKind(value);
|
|
11147
|
+
if (kind === 'Ident') return goAstIdentName(value);
|
|
11148
|
+
if (kind === 'StarExpr') {
|
|
11149
|
+
const inner = goAstTypeName(value.X ?? value.x);
|
|
11150
|
+
return inner ? `*${inner}` : '*';
|
|
11151
|
+
}
|
|
11152
|
+
if (kind === 'SelectorExpr') {
|
|
11153
|
+
const left = goAstTypeName(value.X ?? value.x);
|
|
11154
|
+
const right = goAstIdentName(value.Sel ?? value.sel);
|
|
11155
|
+
return [left, right].filter(Boolean).join('.');
|
|
11156
|
+
}
|
|
11157
|
+
if (kind === 'ArrayType') {
|
|
11158
|
+
const inner = goAstTypeName(value.Elt ?? value.elt);
|
|
11159
|
+
return `[]${inner ?? 'unknown'}`;
|
|
11160
|
+
}
|
|
11161
|
+
if (kind === 'MapType') {
|
|
11162
|
+
return `map[${goAstTypeName(value.Key ?? value.key) ?? 'unknown'}]${goAstTypeName(value.Value ?? value.value) ?? 'unknown'}`;
|
|
11163
|
+
}
|
|
11164
|
+
if (kind === 'StructType') return 'struct';
|
|
11165
|
+
if (kind === 'InterfaceType') return 'interface';
|
|
11166
|
+
if (kind === 'FuncType') return 'func';
|
|
11167
|
+
return goAstDeclarationName(value);
|
|
11168
|
+
}
|
|
11169
|
+
|
|
11170
|
+
function goAstTokenName(value) {
|
|
11171
|
+
if (!value) return undefined;
|
|
11172
|
+
if (typeof value === 'string') return value;
|
|
11173
|
+
if (typeof value === 'number') return String(value);
|
|
11174
|
+
return value.String ?? value.string ?? value.Name ?? value.name;
|
|
11175
|
+
}
|
|
11176
|
+
|
|
11177
|
+
function goAstLiteralValue(node) {
|
|
11178
|
+
const value = node.Value ?? node.value;
|
|
11179
|
+
if (value === null || typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') return value;
|
|
11180
|
+
return undefined;
|
|
11181
|
+
}
|
|
11182
|
+
|
|
11183
|
+
function goGeneratedCodeMarker(node, kind) {
|
|
11184
|
+
if (kind !== 'File') return false;
|
|
11185
|
+
if (node.Generated || node.generated) return true;
|
|
11186
|
+
const comments = node.Comments ?? node.comments;
|
|
11187
|
+
if (!Array.isArray(comments)) return false;
|
|
11188
|
+
return comments.some((group) => JSON.stringify(group).includes('Code generated') && JSON.stringify(group).includes('DO NOT EDIT'));
|
|
11189
|
+
}
|
|
11190
|
+
|
|
11191
|
+
function goBadAstKind(kind) {
|
|
11192
|
+
return kind === 'BadDecl' || kind === 'BadExpr' || kind === 'BadStmt';
|
|
11193
|
+
}
|
|
11194
|
+
|
|
11195
|
+
function goReceiverFieldCount(node) {
|
|
11196
|
+
const list = (node?.Recv ?? node?.recv)?.List ?? (node?.Recv ?? node?.recv)?.list;
|
|
11197
|
+
return Array.isArray(list) ? list.length : 0;
|
|
11198
|
+
}
|
|
11199
|
+
|
|
11200
|
+
function goTypeEvidenceSummary(value) {
|
|
11201
|
+
if (!value || typeof value !== 'object') return undefined;
|
|
11202
|
+
const summary = {};
|
|
11203
|
+
if (typeof value.packagePath === 'string') summary.packagePath = value.packagePath;
|
|
11204
|
+
if (typeof value.hash === 'string') summary.hash = value.hash;
|
|
11205
|
+
if (Array.isArray(value.types)) summary.typeCount = value.types.length;
|
|
11206
|
+
if (Array.isArray(value.references)) summary.referenceCount = value.references.length;
|
|
11207
|
+
return Object.keys(summary).length ? summary : { present: true };
|
|
11208
|
+
}
|
|
11209
|
+
|
|
10232
11210
|
function declarationRecord(input, nativeNodeId, name, symbolKind, role = 'definition') {
|
|
10233
11211
|
return {
|
|
10234
11212
|
name: String(name),
|
package/package.json
CHANGED