@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 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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shapeshift-labs/frontier-lang-compiler",
3
- "version": "0.2.27",
3
+ "version": "0.2.29",
4
4
  "description": "Compiler facade for Frontier Lang source documents and language projection adapters.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",