@shapeshift-labs/frontier-lang-compiler 0.2.26 → 0.2.28
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 +49 -0
- package/dist/index.js +900 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -332,7 +332,9 @@ Use injected parser adapters when a real language parser is available but should
|
|
|
332
332
|
```js
|
|
333
333
|
import {
|
|
334
334
|
createBabelNativeImporterAdapter,
|
|
335
|
+
createClangAstNativeImporterAdapter,
|
|
335
336
|
createPythonAstNativeImporterAdapter,
|
|
337
|
+
createRustSynNativeImporterAdapter,
|
|
336
338
|
importNativeProject,
|
|
337
339
|
runNativeImporterAdapter
|
|
338
340
|
} from '@shapeshift-labs/frontier-lang-compiler';
|
|
@@ -343,6 +345,15 @@ const babelAdapter = createBabelNativeImporterAdapter({
|
|
|
343
345
|
const pythonAstAdapter = createPythonAstNativeImporterAdapter({
|
|
344
346
|
parserModule: hostPythonAstParser
|
|
345
347
|
});
|
|
348
|
+
const rustSynAdapter = createRustSynNativeImporterAdapter({
|
|
349
|
+
parserModule: hostRustSynParser,
|
|
350
|
+
rustEdition: '2021'
|
|
351
|
+
});
|
|
352
|
+
const clangAstAdapter = createClangAstNativeImporterAdapter({
|
|
353
|
+
parserModule: hostClangJsonParser,
|
|
354
|
+
cStandard: 'c11',
|
|
355
|
+
compileFlags: ['-std=c11']
|
|
356
|
+
});
|
|
346
357
|
|
|
347
358
|
const imported = await runNativeImporterAdapter(babelAdapter, {
|
|
348
359
|
sourcePath: 'src/todo.ts',
|
|
@@ -351,10 +362,12 @@ const imported = await runNativeImporterAdapter(babelAdapter, {
|
|
|
351
362
|
|
|
352
363
|
const project = await importNativeProject({
|
|
353
364
|
projectRoot: 'src',
|
|
354
|
-
adapters: [babelAdapter, pythonAstAdapter],
|
|
365
|
+
adapters: [babelAdapter, pythonAstAdapter, rustSynAdapter, clangAstAdapter],
|
|
355
366
|
sources: [
|
|
356
367
|
{ language: 'typescript', adapter: babelAdapter.id, sourcePath: 'src/todo.ts', sourceText },
|
|
357
|
-
{ language: 'python', adapter: pythonAstAdapter.id, sourcePath: 'tools/todo.py', sourceText: pythonSource }
|
|
368
|
+
{ language: 'python', adapter: pythonAstAdapter.id, sourcePath: 'tools/todo.py', sourceText: pythonSource },
|
|
369
|
+
{ language: 'rust', adapter: rustSynAdapter.id, sourcePath: 'src/todo.rs', sourceText: rustSource },
|
|
370
|
+
{ language: 'c', adapter: clangAstAdapter.id, sourcePath: 'native/todo.c', sourceText: cSource }
|
|
358
371
|
]
|
|
359
372
|
});
|
|
360
373
|
|
|
@@ -374,6 +387,8 @@ The built-in adapter factories are dependency-light wrappers for caller-owned pa
|
|
|
374
387
|
- `createBabelNativeImporterAdapter`
|
|
375
388
|
- `createTypeScriptCompilerNativeImporterAdapter`
|
|
376
389
|
- `createPythonAstNativeImporterAdapter`
|
|
390
|
+
- `createRustSynNativeImporterAdapter`
|
|
391
|
+
- `createClangAstNativeImporterAdapter`
|
|
377
392
|
- `createTreeSitterNativeImporterAdapter`
|
|
378
393
|
|
|
379
394
|
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,12 +2,14 @@ import { performance } from 'node:perf_hooks';
|
|
|
2
2
|
import {
|
|
3
3
|
compileNativeSource,
|
|
4
4
|
compileFrontierSource,
|
|
5
|
+
createClangAstNativeImporterAdapter,
|
|
5
6
|
createEstreeNativeImporterAdapter,
|
|
6
7
|
createNativeImportCoverageMatrix,
|
|
7
8
|
createNativeParserAstFormatMatrix,
|
|
8
9
|
createProjectionTargetLossMatrix,
|
|
9
10
|
createNativeSourcePreservation,
|
|
10
11
|
createPythonAstNativeImporterAdapter,
|
|
12
|
+
createRustSynNativeImporterAdapter,
|
|
11
13
|
createSemanticImportSidecar,
|
|
12
14
|
diffNativeSources,
|
|
13
15
|
importExternalSemanticIndex,
|
|
@@ -78,7 +80,7 @@ const matrixDurationMs = performance.now() - matrixStart;
|
|
|
78
80
|
const parserFormatMatrixStart = performance.now();
|
|
79
81
|
const parserFormatMatrix = createNativeParserAstFormatMatrix({
|
|
80
82
|
imports: nativeImportResults,
|
|
81
|
-
adapters: [estreeAdapter, createPythonAstNativeImporterAdapter()]
|
|
83
|
+
adapters: [estreeAdapter, createPythonAstNativeImporterAdapter(), createRustSynNativeImporterAdapter(), createClangAstNativeImporterAdapter()]
|
|
82
84
|
});
|
|
83
85
|
const parserFormatMatrixDurationMs = performance.now() - parserFormatMatrixStart;
|
|
84
86
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1388,6 +1388,53 @@ export interface PythonAstNativeImporterAdapterOptions {
|
|
|
1388
1388
|
readonly maxNodes?: number;
|
|
1389
1389
|
}
|
|
1390
1390
|
|
|
1391
|
+
export interface RustSynNativeImporterAdapterOptions {
|
|
1392
|
+
readonly id?: string;
|
|
1393
|
+
readonly language?: FrontierSourceLanguage;
|
|
1394
|
+
readonly parser?: string;
|
|
1395
|
+
readonly version?: string;
|
|
1396
|
+
readonly capabilities?: readonly string[];
|
|
1397
|
+
readonly coverage?: NativeImporterAdapterCoverageInput;
|
|
1398
|
+
readonly supportedExtensions?: readonly string[];
|
|
1399
|
+
readonly diagnostics?: readonly NativeImporterAdapterDiagnostic[];
|
|
1400
|
+
readonly ast?: unknown;
|
|
1401
|
+
readonly file?: unknown;
|
|
1402
|
+
readonly sourceFile?: unknown;
|
|
1403
|
+
readonly parse?: (sourceText: string, options: Record<string, unknown>) => unknown;
|
|
1404
|
+
readonly parserModule?: { readonly parse: (sourceText: string, options: Record<string, unknown>) => unknown };
|
|
1405
|
+
readonly rustSyn?: { readonly parse: (sourceText: string, options: Record<string, unknown>) => unknown };
|
|
1406
|
+
readonly syn?: { readonly parse: (sourceText: string, options: Record<string, unknown>) => unknown };
|
|
1407
|
+
readonly parserOptions?: Record<string, unknown>;
|
|
1408
|
+
readonly rustEdition?: '2015' | '2018' | '2021' | '2024' | string;
|
|
1409
|
+
readonly includeAttributes?: boolean;
|
|
1410
|
+
readonly maxNodes?: number;
|
|
1411
|
+
}
|
|
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
|
+
|
|
1391
1438
|
export interface TreeSitterNativeImporterAdapterOptions {
|
|
1392
1439
|
readonly id?: string;
|
|
1393
1440
|
readonly language?: FrontierSourceLanguage;
|
|
@@ -1758,6 +1805,8 @@ export declare function createEstreeNativeImporterAdapter(options?: JavaScriptNa
|
|
|
1758
1805
|
export declare function createBabelNativeImporterAdapter(options?: JavaScriptNativeImporterAdapterOptions): NativeImporterAdapter;
|
|
1759
1806
|
export declare function createTypeScriptCompilerNativeImporterAdapter(options?: TypeScriptCompilerNativeImporterAdapterOptions): NativeImporterAdapter;
|
|
1760
1807
|
export declare function createPythonAstNativeImporterAdapter(options?: PythonAstNativeImporterAdapterOptions): NativeImporterAdapter;
|
|
1808
|
+
export declare function createRustSynNativeImporterAdapter(options?: RustSynNativeImporterAdapterOptions): NativeImporterAdapter;
|
|
1809
|
+
export declare function createClangAstNativeImporterAdapter(options?: ClangAstNativeImporterAdapterOptions): NativeImporterAdapter;
|
|
1761
1810
|
export declare function createTreeSitterNativeImporterAdapter(options?: TreeSitterNativeImporterAdapterOptions): NativeImporterAdapter;
|
|
1762
1811
|
export declare function runNativeImporterAdapter(adapter: NativeImporterAdapter, input: RunNativeImporterAdapterOptions): Promise<NativeImporterAdapterImportResult>;
|
|
1763
1812
|
export declare function runNativeTargetProjectionAdapter(adapter: NativeTargetProjectionAdapter, input: NativeTargetProjectionAdapterInput): NativeTargetProjectionResult;
|
package/dist/index.js
CHANGED
|
@@ -378,6 +378,43 @@ export const NativeParserAstFormatProfiles = Object.freeze([
|
|
|
378
378
|
supportsErrorRecovery: false,
|
|
379
379
|
notes: ['Python stdlib AST exposes versioned abstract grammar and source locations, but not formatting trivia.']
|
|
380
380
|
}),
|
|
381
|
+
nativeParserAstFormatProfile('rust-syn', {
|
|
382
|
+
aliases: ['syn'],
|
|
383
|
+
kind: 'abstract-ast',
|
|
384
|
+
languages: ['rust'],
|
|
385
|
+
parserAdapters: ['syn', 'rust-syn'],
|
|
386
|
+
exactness: 'exact-parser-ast',
|
|
387
|
+
sourceRangeModel: 'proc-macro2-span',
|
|
388
|
+
preservesTokens: false,
|
|
389
|
+
preservesTrivia: false,
|
|
390
|
+
supportsErrorRecovery: false,
|
|
391
|
+
notes: ['syn parses Rust token streams into an abstract syntax tree; macro expansion, name resolution, type checking, and lossless trivia remain host-owned evidence.']
|
|
392
|
+
}),
|
|
393
|
+
nativeParserAstFormatProfile('rust-analyzer-rowan', {
|
|
394
|
+
aliases: ['rowan', 'rust-analyzer'],
|
|
395
|
+
kind: 'concrete-syntax-tree',
|
|
396
|
+
languages: ['rust'],
|
|
397
|
+
parserAdapters: ['rust-analyzer-rowan'],
|
|
398
|
+
exactness: 'parser-tree',
|
|
399
|
+
sourceRangeModel: 'text-range',
|
|
400
|
+
preservesTokens: true,
|
|
401
|
+
preservesTrivia: true,
|
|
402
|
+
supportsIncremental: true,
|
|
403
|
+
supportsErrorRecovery: true,
|
|
404
|
+
notes: ['rust-analyzer uses rowan-backed concrete syntax trees with AST wrappers; semantic richness still depends on host analysis evidence.']
|
|
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
|
+
}),
|
|
381
418
|
nativeParserAstFormatProfile('tree-sitter', {
|
|
382
419
|
kind: 'concrete-syntax-tree',
|
|
383
420
|
languages: ['mixed'],
|
|
@@ -2631,6 +2668,119 @@ export function createPythonAstNativeImporterAdapter(options = {}) {
|
|
|
2631
2668
|
};
|
|
2632
2669
|
}
|
|
2633
2670
|
|
|
2671
|
+
export function createRustSynNativeImporterAdapter(options = {}) {
|
|
2672
|
+
return {
|
|
2673
|
+
id: options.id ?? 'frontier.rust-syn-native-importer',
|
|
2674
|
+
language: options.language ?? 'rust',
|
|
2675
|
+
parser: options.parser ?? 'syn',
|
|
2676
|
+
version: options.version,
|
|
2677
|
+
capabilities: uniqueStrings(['nativeAst', 'semanticIndex', 'sourceMaps', 'diagnostics', ...(options.capabilities ?? [])]),
|
|
2678
|
+
coverage: nativeImporterAdapterCoverage({
|
|
2679
|
+
exactness: 'exact-parser-ast',
|
|
2680
|
+
exactAst: true,
|
|
2681
|
+
tokens: false,
|
|
2682
|
+
trivia: false,
|
|
2683
|
+
diagnostics: true,
|
|
2684
|
+
sourceRanges: false,
|
|
2685
|
+
generatedRanges: false,
|
|
2686
|
+
semanticCoverage: declarationSemanticCoverage(),
|
|
2687
|
+
notes: [
|
|
2688
|
+
'Normalizes caller-owned syn-shaped Rust ASTs into native AST nodes and declaration-level semantic index records.',
|
|
2689
|
+
'syn does not expand macros, resolve names, type-check, or preserve full concrete syntax/trivia; attach rust-analyzer/rustc evidence for those claims.'
|
|
2690
|
+
]
|
|
2691
|
+
}, options.coverage),
|
|
2692
|
+
supportedExtensions: options.supportedExtensions ?? ['.rs'],
|
|
2693
|
+
diagnostics: options.diagnostics,
|
|
2694
|
+
parse(input) {
|
|
2695
|
+
const parsed = input.options?.ast
|
|
2696
|
+
?? input.options?.nativeAst
|
|
2697
|
+
?? input.options?.file
|
|
2698
|
+
?? input.options?.sourceFile
|
|
2699
|
+
?? options.ast
|
|
2700
|
+
?? options.file
|
|
2701
|
+
?? options.sourceFile
|
|
2702
|
+
?? parseRustSynSource(input, options);
|
|
2703
|
+
const root = rustSynAstRoot(parsed);
|
|
2704
|
+
if (!root) {
|
|
2705
|
+
return missingInjectedParserResult(input, {
|
|
2706
|
+
parser: options.parser ?? 'syn',
|
|
2707
|
+
adapterId: options.id ?? 'frontier.rust-syn-native-importer',
|
|
2708
|
+
message: 'createRustSynNativeImporterAdapter requires an injected syn-shaped AST object, parserModule.parse function, parse function, or adapterOptions.ast.'
|
|
2709
|
+
});
|
|
2710
|
+
}
|
|
2711
|
+
const parseDiagnostics = normalizeParserErrors(parsed?.errors ?? parsed?.diagnostics, input, {
|
|
2712
|
+
parser: options.parser ?? 'syn'
|
|
2713
|
+
});
|
|
2714
|
+
return createNativeImportFromRustSyn(root, input, {
|
|
2715
|
+
parser: options.parser ?? 'syn',
|
|
2716
|
+
astFormat: 'rust-syn',
|
|
2717
|
+
maxNodes: options.maxNodes,
|
|
2718
|
+
diagnostics: parseDiagnostics,
|
|
2719
|
+
rustEdition: options.rustEdition ?? input.options?.rustEdition ?? parsed?.rustEdition,
|
|
2720
|
+
includeAttributes: options.includeAttributes ?? input.options?.includeAttributes
|
|
2721
|
+
});
|
|
2722
|
+
}
|
|
2723
|
+
};
|
|
2724
|
+
}
|
|
2725
|
+
|
|
2726
|
+
export function createClangAstNativeImporterAdapter(options = {}) {
|
|
2727
|
+
return {
|
|
2728
|
+
id: options.id ?? 'frontier.clang-ast-native-importer',
|
|
2729
|
+
language: options.language ?? 'c',
|
|
2730
|
+
parser: options.parser ?? 'clang',
|
|
2731
|
+
version: options.version,
|
|
2732
|
+
capabilities: uniqueStrings(['nativeAst', 'semanticIndex', 'sourceMaps', 'diagnostics', ...(options.capabilities ?? [])]),
|
|
2733
|
+
coverage: nativeImporterAdapterCoverage({
|
|
2734
|
+
exactness: 'exact-parser-ast',
|
|
2735
|
+
exactAst: true,
|
|
2736
|
+
tokens: false,
|
|
2737
|
+
trivia: false,
|
|
2738
|
+
diagnostics: true,
|
|
2739
|
+
sourceRanges: true,
|
|
2740
|
+
generatedRanges: false,
|
|
2741
|
+
semanticCoverage: declarationSemanticCoverage(),
|
|
2742
|
+
notes: [
|
|
2743
|
+
'Normalizes caller-owned Clang -ast-dump=json shaped ASTs into native AST nodes and declaration-level semantic index records.',
|
|
2744
|
+
'Clang JSON ASTs reflect a preprocessed compiler view; compile commands, macros, inactive preprocessor branches, comments/trivia, and full type/reference analysis require host evidence.'
|
|
2745
|
+
]
|
|
2746
|
+
}, options.coverage),
|
|
2747
|
+
supportedExtensions: options.supportedExtensions ?? ['.c', '.h', '.cc', '.cpp', '.cxx', '.hpp', '.hh'],
|
|
2748
|
+
diagnostics: options.diagnostics,
|
|
2749
|
+
parse(input) {
|
|
2750
|
+
const parsed = input.options?.ast
|
|
2751
|
+
?? input.options?.nativeAst
|
|
2752
|
+
?? input.options?.translationUnit
|
|
2753
|
+
?? input.options?.tu
|
|
2754
|
+
?? options.ast
|
|
2755
|
+
?? options.translationUnit
|
|
2756
|
+
?? options.tu
|
|
2757
|
+
?? parseClangAstSource(input, options);
|
|
2758
|
+
const root = clangAstRoot(parsed);
|
|
2759
|
+
if (!root) {
|
|
2760
|
+
return missingInjectedParserResult(input, {
|
|
2761
|
+
parser: options.parser ?? 'clang',
|
|
2762
|
+
adapterId: options.id ?? 'frontier.clang-ast-native-importer',
|
|
2763
|
+
message: 'createClangAstNativeImporterAdapter requires an injected Clang JSON AST object, parserModule.parse function, parse function, or adapterOptions.ast.'
|
|
2764
|
+
});
|
|
2765
|
+
}
|
|
2766
|
+
const parseDiagnostics = normalizeParserErrors(parsed?.errors ?? parsed?.diagnostics, input, {
|
|
2767
|
+
parser: options.parser ?? 'clang'
|
|
2768
|
+
});
|
|
2769
|
+
return createNativeImportFromClangAst(root, input, {
|
|
2770
|
+
parser: options.parser ?? 'clang',
|
|
2771
|
+
astFormat: 'clang-ast-json',
|
|
2772
|
+
maxNodes: options.maxNodes,
|
|
2773
|
+
diagnostics: parseDiagnostics,
|
|
2774
|
+
cStandard: options.cStandard ?? input.options?.cStandard ?? parsed?.cStandard,
|
|
2775
|
+
compileFlags: options.compileFlags ?? input.options?.compileFlags ?? parsed?.compileFlags,
|
|
2776
|
+
includeSystemHeaders: options.includeSystemHeaders ?? input.options?.includeSystemHeaders,
|
|
2777
|
+
preprocessorRecords: input.options?.preprocessorRecords ?? options.preprocessorRecords ?? parsed?.preprocessorRecords,
|
|
2778
|
+
includeGraph: input.options?.includeGraph ?? options.includeGraph ?? parsed?.includeGraph
|
|
2779
|
+
});
|
|
2780
|
+
}
|
|
2781
|
+
};
|
|
2782
|
+
}
|
|
2783
|
+
|
|
2634
2784
|
export function createTreeSitterNativeImporterAdapter(options = {}) {
|
|
2635
2785
|
return {
|
|
2636
2786
|
id: options.id ?? `frontier.tree-sitter-${idFragment(options.language ?? 'source')}-native-importer`,
|
|
@@ -7069,6 +7219,9 @@ function parserAstFormatIdForParser(parser) {
|
|
|
7069
7219
|
const text = normalizeParserAstFormatId(parser);
|
|
7070
7220
|
if (text.includes('typescript')) return 'typescript-compiler-api';
|
|
7071
7221
|
if (text.includes('python') && text.includes('ast')) return 'python-ast';
|
|
7222
|
+
if (text === 'syn' || text.includes('rust-syn')) return 'rust-syn';
|
|
7223
|
+
if (text.includes('rust-analyzer') || text.includes('rowan')) return 'rust-analyzer-rowan';
|
|
7224
|
+
if (text.includes('clang') || text.includes('libclang')) return 'clang-ast-json';
|
|
7072
7225
|
if (text.includes('tree-sitter') || text.includes('treesitter')) return 'tree-sitter';
|
|
7073
7226
|
if (text.includes('babel')) return 'babel';
|
|
7074
7227
|
if (text.includes('estree')) return 'estree';
|
|
@@ -8103,6 +8256,37 @@ function parsePythonAstSource(input, options) {
|
|
|
8103
8256
|
return parse(input.sourceText, parserOptions);
|
|
8104
8257
|
}
|
|
8105
8258
|
|
|
8259
|
+
function parseRustSynSource(input, options) {
|
|
8260
|
+
const parse = options.parse ?? options.parserModule?.parse ?? options.rustSyn?.parse ?? options.syn?.parse;
|
|
8261
|
+
if (typeof parse !== 'function') return undefined;
|
|
8262
|
+
const parserOptions = {
|
|
8263
|
+
sourcePath: input.sourcePath,
|
|
8264
|
+
filename: input.sourcePath,
|
|
8265
|
+
edition: options.rustEdition ?? input.options?.rustEdition ?? '2021',
|
|
8266
|
+
includeAttributes: options.includeAttributes ?? input.options?.includeAttributes,
|
|
8267
|
+
...(options.parserOptions ?? {}),
|
|
8268
|
+
...(input.options?.parserOptions ?? {})
|
|
8269
|
+
};
|
|
8270
|
+
return parse(input.sourceText, parserOptions);
|
|
8271
|
+
}
|
|
8272
|
+
|
|
8273
|
+
function parseClangAstSource(input, options) {
|
|
8274
|
+
const parse = options.parse ?? options.parserModule?.parse ?? options.clang?.parse ?? options.libclang?.parse;
|
|
8275
|
+
if (typeof parse !== 'function') return undefined;
|
|
8276
|
+
const parserOptions = {
|
|
8277
|
+
sourcePath: input.sourcePath,
|
|
8278
|
+
filename: input.sourcePath,
|
|
8279
|
+
language: options.language ?? input.language,
|
|
8280
|
+
standard: options.cStandard ?? input.options?.cStandard,
|
|
8281
|
+
compileFlags: options.compileFlags ?? input.options?.compileFlags,
|
|
8282
|
+
includeSystemHeaders: options.includeSystemHeaders ?? input.options?.includeSystemHeaders,
|
|
8283
|
+
astDumpFormat: 'json',
|
|
8284
|
+
...(options.parserOptions ?? {}),
|
|
8285
|
+
...(input.options?.parserOptions ?? {})
|
|
8286
|
+
};
|
|
8287
|
+
return parse(input.sourceText, parserOptions);
|
|
8288
|
+
}
|
|
8289
|
+
|
|
8106
8290
|
function createNativeImportFromSyntaxAst(ast, input, options) {
|
|
8107
8291
|
const root = normalizeSyntaxAstRoot(ast, options.astFormat);
|
|
8108
8292
|
if (!root) {
|
|
@@ -8193,6 +8377,72 @@ function createNativeImportFromPythonAst(root, input, options) {
|
|
|
8193
8377
|
};
|
|
8194
8378
|
}
|
|
8195
8379
|
|
|
8380
|
+
function createNativeImportFromRustSyn(root, input, options) {
|
|
8381
|
+
const context = createAstNormalizationContext(input, options);
|
|
8382
|
+
visitRustSynNode(root, context, 'root');
|
|
8383
|
+
if (context.truncated) {
|
|
8384
|
+
context.losses.push(truncatedAstLoss(input, context, options));
|
|
8385
|
+
}
|
|
8386
|
+
const semantic = semanticIndexFromNativeDeclarations(context.declarations, input, options);
|
|
8387
|
+
return {
|
|
8388
|
+
rootId: context.rootId,
|
|
8389
|
+
nodes: context.nodes,
|
|
8390
|
+
semanticIndex: semantic.semanticIndex,
|
|
8391
|
+
mappings: semantic.mappings,
|
|
8392
|
+
losses: mergeNativeLosses(context.losses, options.diagnostics?.map((diagnostic, index) => adapterDiagnosticToLoss(diagnostic, index, {
|
|
8393
|
+
id: input.adapterId,
|
|
8394
|
+
version: input.adapterVersion
|
|
8395
|
+
}, input)) ?? []),
|
|
8396
|
+
evidence: semantic.evidence,
|
|
8397
|
+
diagnostics: options.diagnostics,
|
|
8398
|
+
metadata: {
|
|
8399
|
+
astFormat: options.astFormat,
|
|
8400
|
+
parser: options.parser,
|
|
8401
|
+
rustEdition: options.rustEdition,
|
|
8402
|
+
includeAttributes: Boolean(options.includeAttributes),
|
|
8403
|
+
normalizedNodeCount: Object.keys(context.nodes).length,
|
|
8404
|
+
declarationCount: context.declarations.length,
|
|
8405
|
+
truncated: context.truncated
|
|
8406
|
+
}
|
|
8407
|
+
};
|
|
8408
|
+
}
|
|
8409
|
+
|
|
8410
|
+
function createNativeImportFromClangAst(root, input, options) {
|
|
8411
|
+
const context = createAstNormalizationContext(input, options);
|
|
8412
|
+
visitClangAstNode(root, context, 'root');
|
|
8413
|
+
for (const [index, record] of clangPreprocessorRecords(options.preprocessorRecords).entries()) {
|
|
8414
|
+
visitClangAstNode(record, context, `preprocessorRecords[${index}]`);
|
|
8415
|
+
}
|
|
8416
|
+
if (context.truncated) {
|
|
8417
|
+
context.losses.push(truncatedAstLoss(input, context, options));
|
|
8418
|
+
}
|
|
8419
|
+
const semantic = semanticIndexFromNativeDeclarations(context.declarations, input, options);
|
|
8420
|
+
return {
|
|
8421
|
+
rootId: context.rootId,
|
|
8422
|
+
nodes: context.nodes,
|
|
8423
|
+
semanticIndex: semantic.semanticIndex,
|
|
8424
|
+
mappings: semantic.mappings,
|
|
8425
|
+
losses: mergeNativeLosses(context.losses, options.diagnostics?.map((diagnostic, index) => adapterDiagnosticToLoss(diagnostic, index, {
|
|
8426
|
+
id: input.adapterId,
|
|
8427
|
+
version: input.adapterVersion
|
|
8428
|
+
}, input)) ?? []),
|
|
8429
|
+
evidence: semantic.evidence,
|
|
8430
|
+
diagnostics: options.diagnostics,
|
|
8431
|
+
metadata: {
|
|
8432
|
+
astFormat: options.astFormat,
|
|
8433
|
+
parser: options.parser,
|
|
8434
|
+
cStandard: options.cStandard,
|
|
8435
|
+
compileFlags: Array.isArray(options.compileFlags) ? options.compileFlags.slice() : options.compileFlags,
|
|
8436
|
+
includeSystemHeaders: Boolean(options.includeSystemHeaders),
|
|
8437
|
+
preprocessorRecordCount: clangPreprocessorRecords(options.preprocessorRecords).length,
|
|
8438
|
+
includeGraph: serializableIncludeGraphSummary(options.includeGraph),
|
|
8439
|
+
normalizedNodeCount: Object.keys(context.nodes).length,
|
|
8440
|
+
declarationCount: context.declarations.length,
|
|
8441
|
+
truncated: context.truncated
|
|
8442
|
+
}
|
|
8443
|
+
};
|
|
8444
|
+
}
|
|
8445
|
+
|
|
8196
8446
|
function createNativeImportFromTreeSitter(root, input, options) {
|
|
8197
8447
|
const context = createAstNormalizationContext(input, options);
|
|
8198
8448
|
visitTreeSitterNode(root, context, 'root');
|
|
@@ -8376,6 +8626,128 @@ function visitPythonAstNode(node, context, propertyPath) {
|
|
|
8376
8626
|
return id;
|
|
8377
8627
|
}
|
|
8378
8628
|
|
|
8629
|
+
function visitRustSynNode(node, context, propertyPath) {
|
|
8630
|
+
if (!isRustSynAstNode(node) || context.truncated) return undefined;
|
|
8631
|
+
if (context.objectIds.has(node)) return context.objectIds.get(node);
|
|
8632
|
+
if (context.counter >= context.maxNodes) {
|
|
8633
|
+
context.truncated = true;
|
|
8634
|
+
return undefined;
|
|
8635
|
+
}
|
|
8636
|
+
const kind = rustSynKind(node);
|
|
8637
|
+
const payload = rustSynPayload(node);
|
|
8638
|
+
const span = spanFromRustSynNode(payload, context.input);
|
|
8639
|
+
const id = nativeNodeId(context, kind, { start: { line: span?.startLine, column: span?.startColumn } }, propertyPath);
|
|
8640
|
+
context.objectIds.set(node, id);
|
|
8641
|
+
if (!context.rootId) context.rootId = id;
|
|
8642
|
+
const children = [];
|
|
8643
|
+
for (const [field, value] of rustSynChildEntries(node)) {
|
|
8644
|
+
if (Array.isArray(value)) {
|
|
8645
|
+
value.forEach((entry, index) => {
|
|
8646
|
+
const childId = visitRustSynNode(entry, context, `${propertyPath}.${field}[${index}]`);
|
|
8647
|
+
if (childId) children.push(childId);
|
|
8648
|
+
});
|
|
8649
|
+
} else {
|
|
8650
|
+
const childId = visitRustSynNode(value, context, `${propertyPath}.${field}`);
|
|
8651
|
+
if (childId) children.push(childId);
|
|
8652
|
+
}
|
|
8653
|
+
}
|
|
8654
|
+
const declaration = rustSynDeclaration(payload, kind, id, context.input);
|
|
8655
|
+
const nativeNode = {
|
|
8656
|
+
id,
|
|
8657
|
+
kind,
|
|
8658
|
+
languageKind: `${context.input.language}.${kind}`,
|
|
8659
|
+
span,
|
|
8660
|
+
value: declaration?.name ?? rustSynNodeValue(payload),
|
|
8661
|
+
fields: primitiveRustSynFields(payload, kind),
|
|
8662
|
+
children,
|
|
8663
|
+
metadata: {
|
|
8664
|
+
astFormat: context.options.astFormat,
|
|
8665
|
+
propertyPath,
|
|
8666
|
+
spanKind: rustSynSpanKind(payload)
|
|
8667
|
+
}
|
|
8668
|
+
};
|
|
8669
|
+
context.nodes[id] = nativeNode;
|
|
8670
|
+
if (declaration) context.declarations.push({ ...declaration, nativeNode });
|
|
8671
|
+
if (rustSynMacroKind(kind)) {
|
|
8672
|
+
context.losses.push({
|
|
8673
|
+
id: `loss_${idFragment(id)}_rust_macro_expansion`,
|
|
8674
|
+
severity: 'warning',
|
|
8675
|
+
phase: 'parse',
|
|
8676
|
+
sourceFormat: context.input.language,
|
|
8677
|
+
kind: 'macroExpansion',
|
|
8678
|
+
message: 'Rust macro syntax was parsed but macro expansion and generated items require host compiler evidence.',
|
|
8679
|
+
span,
|
|
8680
|
+
nodeId: id,
|
|
8681
|
+
metadata: {
|
|
8682
|
+
parser: context.options.parser,
|
|
8683
|
+
astFormat: context.options.astFormat
|
|
8684
|
+
}
|
|
8685
|
+
});
|
|
8686
|
+
}
|
|
8687
|
+
return id;
|
|
8688
|
+
}
|
|
8689
|
+
|
|
8690
|
+
function visitClangAstNode(node, context, propertyPath) {
|
|
8691
|
+
if (!isClangAstNode(node) || context.truncated) return undefined;
|
|
8692
|
+
if (context.objectIds.has(node)) return context.objectIds.get(node);
|
|
8693
|
+
if (context.counter >= context.maxNodes) {
|
|
8694
|
+
context.truncated = true;
|
|
8695
|
+
return undefined;
|
|
8696
|
+
}
|
|
8697
|
+
const kind = clangAstKind(node);
|
|
8698
|
+
const span = spanFromClangAstNode(node, context.input);
|
|
8699
|
+
const id = nativeNodeId(context, kind, { start: { line: span?.startLine, column: span?.startColumn } }, propertyPath);
|
|
8700
|
+
context.objectIds.set(node, id);
|
|
8701
|
+
if (!context.rootId) context.rootId = id;
|
|
8702
|
+
const children = [];
|
|
8703
|
+
for (const [field, value] of clangAstChildEntries(node)) {
|
|
8704
|
+
if (Array.isArray(value)) {
|
|
8705
|
+
value.forEach((entry, index) => {
|
|
8706
|
+
const childId = visitClangAstNode(entry, context, `${propertyPath}.${field}[${index}]`);
|
|
8707
|
+
if (childId) children.push(childId);
|
|
8708
|
+
});
|
|
8709
|
+
} else {
|
|
8710
|
+
const childId = visitClangAstNode(value, context, `${propertyPath}.${field}`);
|
|
8711
|
+
if (childId) children.push(childId);
|
|
8712
|
+
}
|
|
8713
|
+
}
|
|
8714
|
+
const declaration = clangAstDeclaration(node, kind, id, context.input);
|
|
8715
|
+
const nativeNode = {
|
|
8716
|
+
id,
|
|
8717
|
+
kind,
|
|
8718
|
+
languageKind: `${context.input.language}.${kind}`,
|
|
8719
|
+
span,
|
|
8720
|
+
value: declaration?.name ?? clangAstNodeValue(node),
|
|
8721
|
+
fields: primitiveClangAstFields(node, kind),
|
|
8722
|
+
children,
|
|
8723
|
+
metadata: {
|
|
8724
|
+
astFormat: context.options.astFormat,
|
|
8725
|
+
propertyPath,
|
|
8726
|
+
clangId: typeof node.id === 'string' || typeof node.id === 'number' ? String(node.id) : undefined,
|
|
8727
|
+
locationKind: clangLocationKind(node)
|
|
8728
|
+
}
|
|
8729
|
+
};
|
|
8730
|
+
context.nodes[id] = nativeNode;
|
|
8731
|
+
if (declaration) context.declarations.push({ ...declaration, nativeNode });
|
|
8732
|
+
if (clangPreprocessorKind(kind)) {
|
|
8733
|
+
context.losses.push({
|
|
8734
|
+
id: `loss_${idFragment(id)}_clang_preprocessor`,
|
|
8735
|
+
severity: 'warning',
|
|
8736
|
+
phase: 'parse',
|
|
8737
|
+
sourceFormat: context.input.language,
|
|
8738
|
+
kind: 'preprocessor',
|
|
8739
|
+
message: 'Clang AST preprocessor records were imported, but macro expansion, inactive branches, and compile-command provenance require host evidence.',
|
|
8740
|
+
span,
|
|
8741
|
+
nodeId: id,
|
|
8742
|
+
metadata: {
|
|
8743
|
+
parser: context.options.parser,
|
|
8744
|
+
astFormat: context.options.astFormat
|
|
8745
|
+
}
|
|
8746
|
+
});
|
|
8747
|
+
}
|
|
8748
|
+
return id;
|
|
8749
|
+
}
|
|
8750
|
+
|
|
8379
8751
|
function visitTreeSitterNode(node, context, propertyPath) {
|
|
8380
8752
|
if (!node || typeof node !== 'object' || context.truncated) return undefined;
|
|
8381
8753
|
if (context.objectIds.has(node)) return context.objectIds.get(node);
|
|
@@ -9530,6 +9902,87 @@ function pythonAstKind(node) {
|
|
|
9530
9902
|
return node?._type ?? node?.type ?? node?.kind ?? node?.nodeType;
|
|
9531
9903
|
}
|
|
9532
9904
|
|
|
9905
|
+
function rustSynAstRoot(value) {
|
|
9906
|
+
if (!value || typeof value !== 'object') return undefined;
|
|
9907
|
+
if (isRustSynAstNode(value)) return value;
|
|
9908
|
+
if (isRustSynAstNode(value.ast)) return value.ast;
|
|
9909
|
+
if (isRustSynAstNode(value.file)) return value.file;
|
|
9910
|
+
if (isRustSynAstNode(value.root)) return value.root;
|
|
9911
|
+
if (isRustSynAstNode(value.module)) return value.module;
|
|
9912
|
+
if (isRustSynAstNode(value.sourceFile)) return value.sourceFile;
|
|
9913
|
+
return undefined;
|
|
9914
|
+
}
|
|
9915
|
+
|
|
9916
|
+
function isRustSynAstNode(value) {
|
|
9917
|
+
return Boolean(value && typeof value === 'object' && typeof rustSynKind(value) === 'string');
|
|
9918
|
+
}
|
|
9919
|
+
|
|
9920
|
+
function rustSynKind(node) {
|
|
9921
|
+
const declared = node?._type ?? node?.type ?? node?.kind ?? node?.nodeType ?? node?.synKind;
|
|
9922
|
+
if (typeof declared === 'string') return normalizeRustSynKind(declared);
|
|
9923
|
+
const wrapper = rustSynWrapperKind(node);
|
|
9924
|
+
if (wrapper) return normalizeRustSynKind(wrapper);
|
|
9925
|
+
if (Array.isArray(node?.items)) return 'File';
|
|
9926
|
+
if (node?.sig && node?.block) return 'ItemFn';
|
|
9927
|
+
if (node?.ident && node?.fields && Array.isArray(node?.variants)) return 'ItemEnum';
|
|
9928
|
+
if (node?.ident && node?.fields) return 'ItemStruct';
|
|
9929
|
+
if (node?.ident && Array.isArray(node?.items)) return 'ItemMod';
|
|
9930
|
+
if (node?.trait_ || node?.self_ty || node?.selfType) return 'ItemImpl';
|
|
9931
|
+
if (node?.path && (node?.tree || node?.trees)) return 'ItemUse';
|
|
9932
|
+
return undefined;
|
|
9933
|
+
}
|
|
9934
|
+
|
|
9935
|
+
function rustSynPayload(node) {
|
|
9936
|
+
if (!node || typeof node !== 'object') return node;
|
|
9937
|
+
const wrapper = rustSynWrapperKind(node);
|
|
9938
|
+
return wrapper ? node[wrapper] : node;
|
|
9939
|
+
}
|
|
9940
|
+
|
|
9941
|
+
function rustSynWrapperKind(node) {
|
|
9942
|
+
if (!node || typeof node !== 'object') return undefined;
|
|
9943
|
+
const keys = Object.keys(node).filter((key) => !ignoredRustSynField(key));
|
|
9944
|
+
if (keys.length !== 1) return undefined;
|
|
9945
|
+
const key = keys[0];
|
|
9946
|
+
const value = node[key];
|
|
9947
|
+
if (!value || typeof value !== 'object') return undefined;
|
|
9948
|
+
if (/^(?:Fn|Struct|Enum|Trait|Impl|Use|Mod|Type|Const|Static|Union|Macro)$/.test(key)) return key;
|
|
9949
|
+
if (/^(?:Item|ImplItem|TraitItem|ForeignItem)/.test(key)) return key;
|
|
9950
|
+
return undefined;
|
|
9951
|
+
}
|
|
9952
|
+
|
|
9953
|
+
function normalizeRustSynKind(kind) {
|
|
9954
|
+
const text = String(kind);
|
|
9955
|
+
const compact = text.replace(/^(?:syn::)?/, '').replace(/^Item::/, 'Item').replace(/^ImplItem::/, 'ImplItem').replace(/^TraitItem::/, 'TraitItem');
|
|
9956
|
+
if (/^fn$/i.test(compact)) return 'ItemFn';
|
|
9957
|
+
if (/^struct$/i.test(compact)) return 'ItemStruct';
|
|
9958
|
+
if (/^enum$/i.test(compact)) return 'ItemEnum';
|
|
9959
|
+
if (/^trait$/i.test(compact)) return 'ItemTrait';
|
|
9960
|
+
if (/^impl$/i.test(compact)) return 'ItemImpl';
|
|
9961
|
+
if (/^use$/i.test(compact)) return 'ItemUse';
|
|
9962
|
+
if (/^mod$/i.test(compact)) return 'ItemMod';
|
|
9963
|
+
if (/^type$/i.test(compact)) return 'ItemType';
|
|
9964
|
+
if (/^const$/i.test(compact)) return 'ItemConst';
|
|
9965
|
+
if (/^static$/i.test(compact)) return 'ItemStatic';
|
|
9966
|
+
if (/^union$/i.test(compact)) return 'ItemUnion';
|
|
9967
|
+
if (/^item_fn$/i.test(compact)) return 'ItemFn';
|
|
9968
|
+
if (/^item_struct$/i.test(compact)) return 'ItemStruct';
|
|
9969
|
+
if (/^item_enum$/i.test(compact)) return 'ItemEnum';
|
|
9970
|
+
if (/^item_trait$/i.test(compact)) return 'ItemTrait';
|
|
9971
|
+
if (/^item_impl$/i.test(compact)) return 'ItemImpl';
|
|
9972
|
+
if (/^item_use$/i.test(compact)) return 'ItemUse';
|
|
9973
|
+
if (/^item_mod$/i.test(compact)) return 'ItemMod';
|
|
9974
|
+
if (/^item_type$/i.test(compact)) return 'ItemType';
|
|
9975
|
+
if (/^item_const$/i.test(compact)) return 'ItemConst';
|
|
9976
|
+
if (/^item_static$/i.test(compact)) return 'ItemStatic';
|
|
9977
|
+
if (/^item_union$/i.test(compact)) return 'ItemUnion';
|
|
9978
|
+
if (/^item_macro$/i.test(compact)) return 'ItemMacro';
|
|
9979
|
+
if (/^macro$/i.test(compact)) return 'Macro';
|
|
9980
|
+
if (/^impl_item_fn$/i.test(compact)) return 'ImplItemFn';
|
|
9981
|
+
if (/^trait_item_fn$/i.test(compact)) return 'TraitItemFn';
|
|
9982
|
+
if (/^foreign_item_fn$/i.test(compact)) return 'ForeignItemFn';
|
|
9983
|
+
return compact;
|
|
9984
|
+
}
|
|
9985
|
+
|
|
9533
9986
|
function ignoredSyntaxField(key) {
|
|
9534
9987
|
return key === 'type'
|
|
9535
9988
|
|| key === 'kind'
|
|
@@ -9564,6 +10017,18 @@ function ignoredPythonAstField(key) {
|
|
|
9564
10017
|
|| key === 'parent';
|
|
9565
10018
|
}
|
|
9566
10019
|
|
|
10020
|
+
function ignoredRustSynField(key) {
|
|
10021
|
+
return key === '_type'
|
|
10022
|
+
|| key === 'type'
|
|
10023
|
+
|| key === 'kind'
|
|
10024
|
+
|| key === 'nodeType'
|
|
10025
|
+
|| key === 'synKind'
|
|
10026
|
+
|| key === 'span'
|
|
10027
|
+
|| key === 'tokens'
|
|
10028
|
+
|| key === 'tokenStream'
|
|
10029
|
+
|| key === 'parent';
|
|
10030
|
+
}
|
|
10031
|
+
|
|
9567
10032
|
function primitiveSyntaxFields(node) {
|
|
9568
10033
|
const fields = {};
|
|
9569
10034
|
for (const key of ['name', 'operator', 'sourceType', 'async', 'generator', 'computed', 'static', 'exportKind', 'importKind', 'optional']) {
|
|
@@ -9595,6 +10060,22 @@ function primitivePythonAstFields(node, kind) {
|
|
|
9595
10060
|
return fields;
|
|
9596
10061
|
}
|
|
9597
10062
|
|
|
10063
|
+
function primitiveRustSynFields(node, kind) {
|
|
10064
|
+
const fields = { kind };
|
|
10065
|
+
const ident = rustSynIdentName(node.ident ?? node.name ?? node.sig?.ident);
|
|
10066
|
+
if (ident) fields.ident = ident;
|
|
10067
|
+
const path = rustSynPathName(node.path ?? node.trait_ ?? node.self_ty ?? node.selfType ?? node.ty);
|
|
10068
|
+
if (path) fields.path = path;
|
|
10069
|
+
const visibility = rustSynVisibility(node.vis ?? node.visibility);
|
|
10070
|
+
if (visibility) fields.visibility = visibility;
|
|
10071
|
+
for (const key of ['mutability', 'defaultness', 'constness', 'asyncness', 'unsafety', 'abi']) {
|
|
10072
|
+
const value = node[key];
|
|
10073
|
+
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean' || value === null) fields[key] = value;
|
|
10074
|
+
}
|
|
10075
|
+
if (Array.isArray(node.attrs) && node.attrs.length) fields.attributeCount = node.attrs.length;
|
|
10076
|
+
return fields;
|
|
10077
|
+
}
|
|
10078
|
+
|
|
9598
10079
|
function literalSyntaxValue(node) {
|
|
9599
10080
|
if (node.value === null || typeof node.value === 'string' || typeof node.value === 'number' || typeof node.value === 'boolean') return node.value;
|
|
9600
10081
|
return undefined;
|
|
@@ -9635,6 +10116,36 @@ function spanFromPythonAstNode(node, input) {
|
|
|
9635
10116
|
};
|
|
9636
10117
|
}
|
|
9637
10118
|
|
|
10119
|
+
function spanFromRustSynNode(node, input) {
|
|
10120
|
+
const span = node.span ?? node.ident?.span ?? node.sig?.ident?.span ?? node.name?.span;
|
|
10121
|
+
if (!span || typeof span !== 'object') return undefined;
|
|
10122
|
+
const start = span.start ?? span.lo ?? span.begin;
|
|
10123
|
+
const end = span.end ?? span.hi;
|
|
10124
|
+
const startLine = span.startLine ?? span.line ?? start?.line;
|
|
10125
|
+
const startColumn = span.startColumn ?? span.column ?? start?.column;
|
|
10126
|
+
const endLine = span.endLine ?? end?.line;
|
|
10127
|
+
const endColumn = span.endColumn ?? end?.column;
|
|
10128
|
+
if (typeof startLine !== 'number') return undefined;
|
|
10129
|
+
return {
|
|
10130
|
+
sourceId: input.sourceHash,
|
|
10131
|
+
path: input.sourcePath,
|
|
10132
|
+
startLine,
|
|
10133
|
+
startColumn: typeof startColumn === 'number' ? rustSynColumnToOneBased(startColumn, span) : undefined,
|
|
10134
|
+
endLine: typeof endLine === 'number' ? endLine : undefined,
|
|
10135
|
+
endColumn: typeof endColumn === 'number' ? rustSynColumnToOneBased(endColumn, span) : undefined
|
|
10136
|
+
};
|
|
10137
|
+
}
|
|
10138
|
+
|
|
10139
|
+
function rustSynColumnToOneBased(column, span) {
|
|
10140
|
+
return span.columnBase === 1 || span.columnsOneBased ? column : column + 1;
|
|
10141
|
+
}
|
|
10142
|
+
|
|
10143
|
+
function rustSynSpanKind(node) {
|
|
10144
|
+
const span = node.span ?? node.ident?.span ?? node.sig?.ident?.span ?? node.name?.span;
|
|
10145
|
+
if (!span || typeof span !== 'object') return undefined;
|
|
10146
|
+
return span.kind ?? span.source ?? 'host-span';
|
|
10147
|
+
}
|
|
10148
|
+
|
|
9638
10149
|
function syntaxDeclaration(node, nativeNodeId, input) {
|
|
9639
10150
|
const kind = String(node.type ?? node.kind ?? '');
|
|
9640
10151
|
if (kind === 'ImportDeclaration') {
|
|
@@ -9671,6 +10182,46 @@ function pythonAstDeclaration(node, kind, nativeNodeId, input) {
|
|
|
9671
10182
|
return undefined;
|
|
9672
10183
|
}
|
|
9673
10184
|
|
|
10185
|
+
function rustSynDeclaration(node, kind, nativeNodeId, input) {
|
|
10186
|
+
if (kind === 'ItemUse' || kind === 'UseTree' || kind === 'UsePath' || kind === 'UseName') {
|
|
10187
|
+
const name = rustSynUseName(node);
|
|
10188
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'module', 'import');
|
|
10189
|
+
}
|
|
10190
|
+
if (kind === 'ItemFn' || kind === 'ForeignItemFn') {
|
|
10191
|
+
const name = rustSynIdentName(node.sig?.ident ?? node.ident ?? node.name);
|
|
10192
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'function', 'definition');
|
|
10193
|
+
}
|
|
10194
|
+
if (kind === 'ImplItemFn' || kind === 'TraitItemFn') {
|
|
10195
|
+
const name = rustSynIdentName(node.sig?.ident ?? node.ident ?? node.name);
|
|
10196
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'method', 'definition');
|
|
10197
|
+
}
|
|
10198
|
+
if (kind === 'ItemStruct' || kind === 'ItemUnion') {
|
|
10199
|
+
const name = rustSynIdentName(node.ident ?? node.name);
|
|
10200
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'class', 'definition');
|
|
10201
|
+
}
|
|
10202
|
+
if (kind === 'ItemEnum' || kind === 'ItemTrait' || kind === 'ItemType') {
|
|
10203
|
+
const name = rustSynIdentName(node.ident ?? node.name);
|
|
10204
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'type', 'definition');
|
|
10205
|
+
}
|
|
10206
|
+
if (kind === 'ItemMod') {
|
|
10207
|
+
const name = rustSynIdentName(node.ident ?? node.name);
|
|
10208
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'module', 'definition');
|
|
10209
|
+
}
|
|
10210
|
+
if (kind === 'ItemConst' || kind === 'ItemStatic') {
|
|
10211
|
+
const name = rustSynIdentName(node.ident ?? node.name);
|
|
10212
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'variable', 'definition');
|
|
10213
|
+
}
|
|
10214
|
+
if (kind === 'ItemImpl') {
|
|
10215
|
+
const name = rustSynImplName(node);
|
|
10216
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'type', 'definition');
|
|
10217
|
+
}
|
|
10218
|
+
if (rustSynMacroKind(kind)) {
|
|
10219
|
+
const name = rustSynIdentName(node.ident ?? node.mac?.path ?? node.path);
|
|
10220
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'macro', 'definition');
|
|
10221
|
+
}
|
|
10222
|
+
return undefined;
|
|
10223
|
+
}
|
|
10224
|
+
|
|
9674
10225
|
function typeScriptDeclaration(node, kind, nativeNodeId, input) {
|
|
9675
10226
|
if (kind === 'ImportDeclaration' || kind === 'ImportEqualsDeclaration') {
|
|
9676
10227
|
const name = stringFromTsExpression(node.moduleSpecifier) ?? stringFromTsExpression(node.externalModuleReference?.expression);
|
|
@@ -9725,10 +10276,26 @@ function pythonAstChildEntries(node) {
|
|
|
9725
10276
|
: isPythonAstNode(value));
|
|
9726
10277
|
}
|
|
9727
10278
|
|
|
10279
|
+
function rustSynChildEntries(node) {
|
|
10280
|
+
const payload = rustSynPayload(node);
|
|
10281
|
+
const fieldNames = Object.keys(payload).filter((key) => !ignoredRustSynField(key));
|
|
10282
|
+
return fieldNames
|
|
10283
|
+
.map((field) => [field, payload[field]])
|
|
10284
|
+
.filter(([, value]) => Array.isArray(value)
|
|
10285
|
+
? value.some(isRustSynAstNode)
|
|
10286
|
+
: isRustSynAstNode(value));
|
|
10287
|
+
}
|
|
10288
|
+
|
|
9728
10289
|
function pythonAstNodeValue(node) {
|
|
9729
10290
|
return node.name ?? node.id ?? node.arg ?? node.module ?? pythonAstLiteralValue(node);
|
|
9730
10291
|
}
|
|
9731
10292
|
|
|
10293
|
+
function rustSynNodeValue(node) {
|
|
10294
|
+
return rustSynIdentName(node.ident ?? node.name ?? node.sig?.ident)
|
|
10295
|
+
?? rustSynPathName(node.path ?? node.trait_ ?? node.self_ty ?? node.selfType ?? node.ty)
|
|
10296
|
+
?? rustSynLiteralValue(node);
|
|
10297
|
+
}
|
|
10298
|
+
|
|
9732
10299
|
function pythonAliasName(alias) {
|
|
9733
10300
|
if (!alias) return undefined;
|
|
9734
10301
|
if (typeof alias === 'string') return alias;
|
|
@@ -9757,6 +10324,339 @@ function pythonTargetName(target) {
|
|
|
9757
10324
|
return undefined;
|
|
9758
10325
|
}
|
|
9759
10326
|
|
|
10327
|
+
function rustSynIdentName(value) {
|
|
10328
|
+
if (!value) return undefined;
|
|
10329
|
+
if (typeof value === 'string') return value;
|
|
10330
|
+
if (typeof value.ident === 'string') return value.ident;
|
|
10331
|
+
if (typeof value.name === 'string') return value.name;
|
|
10332
|
+
if (typeof value.text === 'string') return value.text;
|
|
10333
|
+
if (typeof value.sym === 'string') return value.sym;
|
|
10334
|
+
if (typeof value.value === 'string') return value.value;
|
|
10335
|
+
if (typeof value.path === 'string') return value.path;
|
|
10336
|
+
return rustSynPathName(value.path ?? value);
|
|
10337
|
+
}
|
|
10338
|
+
|
|
10339
|
+
function rustSynPathName(value) {
|
|
10340
|
+
if (!value) return undefined;
|
|
10341
|
+
if (typeof value === 'string') return value;
|
|
10342
|
+
if (typeof value.ident === 'string') return value.ident;
|
|
10343
|
+
if (typeof value.name === 'string') return value.name;
|
|
10344
|
+
if (typeof value.path === 'string') return value.path;
|
|
10345
|
+
if (value.path && typeof value.path === 'object') return rustSynPathName(value.path);
|
|
10346
|
+
if (Array.isArray(value.segments)) {
|
|
10347
|
+
const names = value.segments
|
|
10348
|
+
.map((segment) => rustSynIdentName(segment.ident ?? segment))
|
|
10349
|
+
.filter(Boolean);
|
|
10350
|
+
return names.length ? names.join('::') : undefined;
|
|
10351
|
+
}
|
|
10352
|
+
if (Array.isArray(value.qself)) return value.qself.map(rustSynPathName).filter(Boolean).join('::');
|
|
10353
|
+
if (value.leading_colon && value.segments) {
|
|
10354
|
+
const name = rustSynPathName({ segments: value.segments });
|
|
10355
|
+
return name ? `::${name}` : undefined;
|
|
10356
|
+
}
|
|
10357
|
+
return undefined;
|
|
10358
|
+
}
|
|
10359
|
+
|
|
10360
|
+
function rustSynUseName(node) {
|
|
10361
|
+
if (!node) return undefined;
|
|
10362
|
+
if (node.prefix && node.tree) {
|
|
10363
|
+
const prefix = rustSynPathName(node.prefix);
|
|
10364
|
+
const child = rustSynUseName(node.tree);
|
|
10365
|
+
return [prefix, child].filter(Boolean).join('::') || undefined;
|
|
10366
|
+
}
|
|
10367
|
+
if (node.ident && node.tree) {
|
|
10368
|
+
const prefix = rustSynIdentName(node.ident);
|
|
10369
|
+
const child = rustSynUseName(node.tree);
|
|
10370
|
+
return [prefix, child].filter(Boolean).join('::') || undefined;
|
|
10371
|
+
}
|
|
10372
|
+
if (node.path && node.tree) {
|
|
10373
|
+
const prefix = rustSynPathName(node.path);
|
|
10374
|
+
const child = rustSynUseName(node.tree);
|
|
10375
|
+
return [prefix, child].filter(Boolean).join('::') || undefined;
|
|
10376
|
+
}
|
|
10377
|
+
if (Array.isArray(node.trees)) return node.trees.map(rustSynUseName).find(Boolean);
|
|
10378
|
+
if (node.tree) return rustSynUseName(node.tree);
|
|
10379
|
+
if (node.path) return rustSynPathName(node.path);
|
|
10380
|
+
if (node.name) return rustSynIdentName(node.name);
|
|
10381
|
+
if (node.ident) return rustSynIdentName(node.ident);
|
|
10382
|
+
if (node.rename) return rustSynIdentName(node.rename);
|
|
10383
|
+
return undefined;
|
|
10384
|
+
}
|
|
10385
|
+
|
|
10386
|
+
function rustSynImplName(node) {
|
|
10387
|
+
const selfType = rustSynPathName(node.self_ty ?? node.selfType ?? node.ty);
|
|
10388
|
+
const traitPath = Array.isArray(node.trait_)
|
|
10389
|
+
? rustSynPathName(node.trait_[1] ?? node.trait_[0])
|
|
10390
|
+
: rustSynPathName(node.trait_);
|
|
10391
|
+
if (selfType && traitPath) return `${selfType}.${traitPath}.impl`;
|
|
10392
|
+
if (selfType) return `${selfType}.impl`;
|
|
10393
|
+
if (traitPath) return `${traitPath}.impl`;
|
|
10394
|
+
return undefined;
|
|
10395
|
+
}
|
|
10396
|
+
|
|
10397
|
+
function rustSynVisibility(value) {
|
|
10398
|
+
if (!value) return undefined;
|
|
10399
|
+
if (typeof value === 'string') return value;
|
|
10400
|
+
if (typeof value.kind === 'string') return value.kind;
|
|
10401
|
+
if (typeof value.type === 'string') return value.type;
|
|
10402
|
+
if (value.pub || value.Public) return 'pub';
|
|
10403
|
+
if (value.restricted || value.Restricted) return 'restricted';
|
|
10404
|
+
return undefined;
|
|
10405
|
+
}
|
|
10406
|
+
|
|
10407
|
+
function rustSynLiteralValue(node) {
|
|
10408
|
+
const value = node.value ?? node.lit?.value ?? node.lit;
|
|
10409
|
+
if (value === null || typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') return value;
|
|
10410
|
+
return undefined;
|
|
10411
|
+
}
|
|
10412
|
+
|
|
10413
|
+
function rustSynMacroKind(kind) {
|
|
10414
|
+
return /Macro|MacroRules|MacroCall/.test(String(kind));
|
|
10415
|
+
}
|
|
10416
|
+
|
|
10417
|
+
function clangAstRoot(value) {
|
|
10418
|
+
if (!value || typeof value !== 'object') return undefined;
|
|
10419
|
+
if (Array.isArray(value)) return { kind: 'TranslationUnitDecl', inner: value };
|
|
10420
|
+
if (isClangAstNode(value)) return value;
|
|
10421
|
+
if (Array.isArray(value.ast)) return { kind: 'TranslationUnitDecl', inner: value.ast };
|
|
10422
|
+
if (isClangAstNode(value.ast)) return value.ast;
|
|
10423
|
+
if (isClangAstNode(value.root)) return value.root;
|
|
10424
|
+
if (isClangAstNode(value.translationUnit)) return value.translationUnit;
|
|
10425
|
+
if (isClangAstNode(value.tu)) return value.tu;
|
|
10426
|
+
if (isClangAstNode(value.file)) return value.file;
|
|
10427
|
+
if (isClangAstNode(value.sourceFile)) return value.sourceFile;
|
|
10428
|
+
return undefined;
|
|
10429
|
+
}
|
|
10430
|
+
|
|
10431
|
+
function isClangAstNode(value) {
|
|
10432
|
+
return Boolean(value && typeof value === 'object' && typeof clangAstKind(value) === 'string');
|
|
10433
|
+
}
|
|
10434
|
+
|
|
10435
|
+
function clangAstKind(node) {
|
|
10436
|
+
if (!node || typeof node !== 'object') return undefined;
|
|
10437
|
+
const declared = node.kind ?? node._type ?? node.type ?? node.nodeType ?? node.declKind ?? node.stmtKind;
|
|
10438
|
+
if (typeof declared === 'string') return declared;
|
|
10439
|
+
if (Array.isArray(node.inner) || Array.isArray(node.children) || Array.isArray(node.decls)) return 'TranslationUnitDecl';
|
|
10440
|
+
return undefined;
|
|
10441
|
+
}
|
|
10442
|
+
|
|
10443
|
+
function ignoredClangAstField(key) {
|
|
10444
|
+
return key === '_type'
|
|
10445
|
+
|| key === 'type'
|
|
10446
|
+
|| key === 'kind'
|
|
10447
|
+
|| key === 'nodeType'
|
|
10448
|
+
|| key === 'declKind'
|
|
10449
|
+
|| key === 'stmtKind'
|
|
10450
|
+
|| key === 'id'
|
|
10451
|
+
|| key === 'loc'
|
|
10452
|
+
|| key === 'range'
|
|
10453
|
+
|| key === 'name'
|
|
10454
|
+
|| key === 'displayName'
|
|
10455
|
+
|| key === 'qualifiedName'
|
|
10456
|
+
|| key === 'mangledName'
|
|
10457
|
+
|| key === 'parent'
|
|
10458
|
+
|| key === 'parentDeclContextId'
|
|
10459
|
+
|| key === 'previousDecl'
|
|
10460
|
+
|| key === 'referencedDecl';
|
|
10461
|
+
}
|
|
10462
|
+
|
|
10463
|
+
function primitiveClangAstFields(node, kind) {
|
|
10464
|
+
const fields = { kind };
|
|
10465
|
+
const name = clangDeclarationName(node);
|
|
10466
|
+
if (name) fields.name = name;
|
|
10467
|
+
const type = clangTypeName(node.type ?? node.qualType);
|
|
10468
|
+
if (type) fields.type = type;
|
|
10469
|
+
for (const key of [
|
|
10470
|
+
'mangledName',
|
|
10471
|
+
'storageClass',
|
|
10472
|
+
'tagUsed',
|
|
10473
|
+
'completeDefinition',
|
|
10474
|
+
'isThisDeclarationADefinition',
|
|
10475
|
+
'inline',
|
|
10476
|
+
'isUsed',
|
|
10477
|
+
'isReferenced',
|
|
10478
|
+
'valueCategory',
|
|
10479
|
+
'opcode',
|
|
10480
|
+
'castKind'
|
|
10481
|
+
]) {
|
|
10482
|
+
const value = node[key];
|
|
10483
|
+
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean' || value === null) fields[key] = value;
|
|
10484
|
+
}
|
|
10485
|
+
const includePath = clangIncludePath(node);
|
|
10486
|
+
if (includePath) fields.includePath = includePath;
|
|
10487
|
+
const literal = clangLiteralValue(node);
|
|
10488
|
+
if (literal !== undefined) fields.literal = literal;
|
|
10489
|
+
const referenced = clangDeclarationName(node.referencedDecl);
|
|
10490
|
+
if (referenced) fields.referenced = referenced;
|
|
10491
|
+
return fields;
|
|
10492
|
+
}
|
|
10493
|
+
|
|
10494
|
+
function spanFromClangAstNode(node, input) {
|
|
10495
|
+
const range = node.range ?? {};
|
|
10496
|
+
const begin = range.begin ?? node.loc ?? node.spellingLoc ?? node.expansionLoc;
|
|
10497
|
+
const end = range.end ?? node.end;
|
|
10498
|
+
const start = clangLocPosition(begin);
|
|
10499
|
+
if (!start) return undefined;
|
|
10500
|
+
const finish = clangLocPosition(end);
|
|
10501
|
+
return {
|
|
10502
|
+
sourceId: input.sourceHash,
|
|
10503
|
+
path: start.path ?? finish?.path ?? input.sourcePath,
|
|
10504
|
+
startLine: start.line,
|
|
10505
|
+
startColumn: start.column,
|
|
10506
|
+
endLine: finish?.line,
|
|
10507
|
+
endColumn: finish?.column
|
|
10508
|
+
};
|
|
10509
|
+
}
|
|
10510
|
+
|
|
10511
|
+
function clangLocPosition(loc) {
|
|
10512
|
+
if (!loc || typeof loc !== 'object') return undefined;
|
|
10513
|
+
const expanded = loc.expansionLoc ?? loc.spellingLoc ?? loc;
|
|
10514
|
+
const line = expanded.line ?? expanded.startLine ?? expanded.begin?.line;
|
|
10515
|
+
const column = expanded.col ?? expanded.column ?? expanded.startColumn ?? expanded.begin?.col ?? expanded.begin?.column;
|
|
10516
|
+
if (typeof line !== 'number') return undefined;
|
|
10517
|
+
return {
|
|
10518
|
+
path: expanded.file ?? expanded.filename ?? expanded.path,
|
|
10519
|
+
line,
|
|
10520
|
+
column: typeof column === 'number' ? column : undefined
|
|
10521
|
+
};
|
|
10522
|
+
}
|
|
10523
|
+
|
|
10524
|
+
function clangLocationKind(node) {
|
|
10525
|
+
const loc = node.loc ?? node.range?.begin;
|
|
10526
|
+
if (!loc || typeof loc !== 'object') return undefined;
|
|
10527
|
+
if (loc.expansionLoc) return 'expansionLoc';
|
|
10528
|
+
if (loc.spellingLoc) return 'spellingLoc';
|
|
10529
|
+
if (loc.includedFrom) return 'includedFrom';
|
|
10530
|
+
return 'clang-loc';
|
|
10531
|
+
}
|
|
10532
|
+
|
|
10533
|
+
function clangAstDeclaration(node, kind, nativeNodeId, input) {
|
|
10534
|
+
if (kind === 'FunctionDecl' || kind === 'CXXMethodDecl' || kind === 'FunctionTemplateDecl') {
|
|
10535
|
+
const name = clangDeclarationName(node);
|
|
10536
|
+
if (name) return declarationRecord(input, nativeNodeId, name, kind === 'CXXMethodDecl' ? 'method' : 'function', clangDeclarationAction(node));
|
|
10537
|
+
}
|
|
10538
|
+
if (kind === 'ParmVarDecl') {
|
|
10539
|
+
const name = clangDeclarationName(node);
|
|
10540
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'parameter', 'definition');
|
|
10541
|
+
}
|
|
10542
|
+
if (kind === 'RecordDecl' || kind === 'CXXRecordDecl' || kind === 'ClassTemplateDecl') {
|
|
10543
|
+
const name = clangDeclarationName(node);
|
|
10544
|
+
if (name) return declarationRecord(input, nativeNodeId, name, kind === 'CXXRecordDecl' ? 'class' : 'type', clangDeclarationAction(node));
|
|
10545
|
+
}
|
|
10546
|
+
if (kind === 'FieldDecl') {
|
|
10547
|
+
const name = clangDeclarationName(node);
|
|
10548
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'property', 'definition');
|
|
10549
|
+
}
|
|
10550
|
+
if (kind === 'TypedefDecl' || kind === 'TypeAliasDecl' || kind === 'TypeAliasTemplateDecl') {
|
|
10551
|
+
const name = clangDeclarationName(node);
|
|
10552
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'type', 'definition');
|
|
10553
|
+
}
|
|
10554
|
+
if (kind === 'EnumDecl') {
|
|
10555
|
+
const name = clangDeclarationName(node);
|
|
10556
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'type', clangDeclarationAction(node));
|
|
10557
|
+
}
|
|
10558
|
+
if (kind === 'EnumConstantDecl') {
|
|
10559
|
+
const name = clangDeclarationName(node);
|
|
10560
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'enumMember', 'definition');
|
|
10561
|
+
}
|
|
10562
|
+
if (kind === 'VarDecl') {
|
|
10563
|
+
const name = clangDeclarationName(node);
|
|
10564
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'variable', clangDeclarationAction(node));
|
|
10565
|
+
}
|
|
10566
|
+
if (/IncludeDirective|InclusionDirective/.test(kind)) {
|
|
10567
|
+
const name = clangIncludePath(node);
|
|
10568
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'module', 'import');
|
|
10569
|
+
}
|
|
10570
|
+
if (/MacroDefinition|MacroExpansion|MacroInstantiation/.test(kind)) {
|
|
10571
|
+
const name = clangDeclarationName(node) ?? clangIncludePath(node);
|
|
10572
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'macro', 'definition');
|
|
10573
|
+
}
|
|
10574
|
+
return undefined;
|
|
10575
|
+
}
|
|
10576
|
+
|
|
10577
|
+
function clangDeclarationAction(node) {
|
|
10578
|
+
if (node.isThisDeclarationADefinition === false) return 'declaration';
|
|
10579
|
+
if (node.isThisDeclarationADefinition === true) return 'definition';
|
|
10580
|
+
if (Array.isArray(node.inner) && node.inner.some((entry) => ['CompoundStmt', 'FieldDecl', 'EnumConstantDecl'].includes(clangAstKind(entry)))) return 'definition';
|
|
10581
|
+
return 'declaration';
|
|
10582
|
+
}
|
|
10583
|
+
|
|
10584
|
+
function clangAstChildEntries(node) {
|
|
10585
|
+
const fieldNames = Object.keys(node).filter((key) => !ignoredClangAstField(key));
|
|
10586
|
+
return fieldNames
|
|
10587
|
+
.map((field) => [field, node[field]])
|
|
10588
|
+
.filter(([, value]) => Array.isArray(value)
|
|
10589
|
+
? value.some(isClangAstNode)
|
|
10590
|
+
: isClangAstNode(value));
|
|
10591
|
+
}
|
|
10592
|
+
|
|
10593
|
+
function clangAstNodeValue(node) {
|
|
10594
|
+
return clangDeclarationName(node)
|
|
10595
|
+
?? clangIncludePath(node)
|
|
10596
|
+
?? clangTypeName(node.type ?? node.qualType)
|
|
10597
|
+
?? clangLiteralValue(node);
|
|
10598
|
+
}
|
|
10599
|
+
|
|
10600
|
+
function clangDeclarationName(node) {
|
|
10601
|
+
if (!node || typeof node !== 'object') return undefined;
|
|
10602
|
+
for (const key of ['qualifiedName', 'displayName', 'name', 'mangledName']) {
|
|
10603
|
+
if (typeof node[key] === 'string' && node[key]) return node[key];
|
|
10604
|
+
}
|
|
10605
|
+
if (node.name && typeof node.name === 'object') return clangDeclarationName(node.name);
|
|
10606
|
+
if (node.referencedDecl && typeof node.referencedDecl === 'object') return clangDeclarationName(node.referencedDecl);
|
|
10607
|
+
if (node.decl && typeof node.decl === 'object') return clangDeclarationName(node.decl);
|
|
10608
|
+
return undefined;
|
|
10609
|
+
}
|
|
10610
|
+
|
|
10611
|
+
function clangIncludePath(node) {
|
|
10612
|
+
if (!node || typeof node !== 'object') return undefined;
|
|
10613
|
+
for (const key of ['file', 'filename', 'path', 'spelling', 'source']) {
|
|
10614
|
+
if (typeof node[key] === 'string' && node[key]) return node[key];
|
|
10615
|
+
}
|
|
10616
|
+
if (node.include && typeof node.include === 'object') return clangIncludePath(node.include);
|
|
10617
|
+
return undefined;
|
|
10618
|
+
}
|
|
10619
|
+
|
|
10620
|
+
function clangTypeName(value) {
|
|
10621
|
+
if (!value) return undefined;
|
|
10622
|
+
if (typeof value === 'string') return value;
|
|
10623
|
+
if (typeof value.qualType === 'string') return value.qualType;
|
|
10624
|
+
if (typeof value.desugaredQualType === 'string') return value.desugaredQualType;
|
|
10625
|
+
if (typeof value.name === 'string') return value.name;
|
|
10626
|
+
if (value.type && typeof value.type === 'object') return clangTypeName(value.type);
|
|
10627
|
+
return undefined;
|
|
10628
|
+
}
|
|
10629
|
+
|
|
10630
|
+
function clangLiteralValue(node) {
|
|
10631
|
+
const value = node.value ?? node.val ?? node.literal;
|
|
10632
|
+
if (value === null || typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') return value;
|
|
10633
|
+
if (typeof node.valueAsString === 'string') return node.valueAsString;
|
|
10634
|
+
return undefined;
|
|
10635
|
+
}
|
|
10636
|
+
|
|
10637
|
+
function clangPreprocessorKind(kind) {
|
|
10638
|
+
return /Macro|Preprocess|Preprocessor|IfDirective|IfdefDirective|IfndefDirective|ElifDirective|ElseDirective|EndifDirective/.test(String(kind));
|
|
10639
|
+
}
|
|
10640
|
+
|
|
10641
|
+
function clangPreprocessorRecords(value) {
|
|
10642
|
+
if (!value) return [];
|
|
10643
|
+
if (Array.isArray(value)) return value.filter(isClangAstNode);
|
|
10644
|
+
if (typeof value === 'object' && Array.isArray(value.records)) return value.records.filter(isClangAstNode);
|
|
10645
|
+
if (isClangAstNode(value)) return [value];
|
|
10646
|
+
return [];
|
|
10647
|
+
}
|
|
10648
|
+
|
|
10649
|
+
function serializableIncludeGraphSummary(value) {
|
|
10650
|
+
if (!value || typeof value !== 'object') return undefined;
|
|
10651
|
+
if (Array.isArray(value)) return { edgeCount: value.length };
|
|
10652
|
+
const summary = {};
|
|
10653
|
+
if (typeof value.hash === 'string') summary.hash = value.hash;
|
|
10654
|
+
if (typeof value.root === 'string') summary.root = value.root;
|
|
10655
|
+
if (Array.isArray(value.edges)) summary.edgeCount = value.edges.length;
|
|
10656
|
+
if (Array.isArray(value.includes)) summary.includeCount = value.includes.length;
|
|
10657
|
+
return Object.keys(summary).length ? summary : { present: true };
|
|
10658
|
+
}
|
|
10659
|
+
|
|
9760
10660
|
function declarationRecord(input, nativeNodeId, name, symbolKind, role = 'definition') {
|
|
9761
10661
|
return {
|
|
9762
10662
|
name: String(name),
|
package/package.json
CHANGED