@shapeshift-labs/frontier-lang-compiler 0.2.27 → 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 +10 -2
- package/bench/smoke.mjs +2 -1
- package/dist/index.d.ts +26 -0
- package/dist/index.js +428 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -332,6 +332,7 @@ 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,
|
|
336
337
|
createRustSynNativeImporterAdapter,
|
|
337
338
|
importNativeProject,
|
|
@@ -348,6 +349,11 @@ const rustSynAdapter = createRustSynNativeImporterAdapter({
|
|
|
348
349
|
parserModule: hostRustSynParser,
|
|
349
350
|
rustEdition: '2021'
|
|
350
351
|
});
|
|
352
|
+
const clangAstAdapter = createClangAstNativeImporterAdapter({
|
|
353
|
+
parserModule: hostClangJsonParser,
|
|
354
|
+
cStandard: 'c11',
|
|
355
|
+
compileFlags: ['-std=c11']
|
|
356
|
+
});
|
|
351
357
|
|
|
352
358
|
const imported = await runNativeImporterAdapter(babelAdapter, {
|
|
353
359
|
sourcePath: 'src/todo.ts',
|
|
@@ -356,11 +362,12 @@ const imported = await runNativeImporterAdapter(babelAdapter, {
|
|
|
356
362
|
|
|
357
363
|
const project = await importNativeProject({
|
|
358
364
|
projectRoot: 'src',
|
|
359
|
-
adapters: [babelAdapter, pythonAstAdapter, rustSynAdapter],
|
|
365
|
+
adapters: [babelAdapter, pythonAstAdapter, rustSynAdapter, clangAstAdapter],
|
|
360
366
|
sources: [
|
|
361
367
|
{ language: 'typescript', adapter: babelAdapter.id, sourcePath: 'src/todo.ts', sourceText },
|
|
362
368
|
{ language: 'python', adapter: pythonAstAdapter.id, sourcePath: 'tools/todo.py', sourceText: pythonSource },
|
|
363
|
-
{ language: 'rust', adapter: rustSynAdapter.id, sourcePath: 'src/todo.rs', sourceText: rustSource }
|
|
369
|
+
{ language: 'rust', adapter: rustSynAdapter.id, sourcePath: 'src/todo.rs', sourceText: rustSource },
|
|
370
|
+
{ language: 'c', adapter: clangAstAdapter.id, sourcePath: 'native/todo.c', sourceText: cSource }
|
|
364
371
|
]
|
|
365
372
|
});
|
|
366
373
|
|
|
@@ -381,6 +388,7 @@ The built-in adapter factories are dependency-light wrappers for caller-owned pa
|
|
|
381
388
|
- `createTypeScriptCompilerNativeImporterAdapter`
|
|
382
389
|
- `createPythonAstNativeImporterAdapter`
|
|
383
390
|
- `createRustSynNativeImporterAdapter`
|
|
391
|
+
- `createClangAstNativeImporterAdapter`
|
|
384
392
|
- `createTreeSitterNativeImporterAdapter`
|
|
385
393
|
|
|
386
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,6 +2,7 @@ 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,
|
|
@@ -79,7 +80,7 @@ const matrixDurationMs = performance.now() - matrixStart;
|
|
|
79
80
|
const parserFormatMatrixStart = performance.now();
|
|
80
81
|
const parserFormatMatrix = createNativeParserAstFormatMatrix({
|
|
81
82
|
imports: nativeImportResults,
|
|
82
|
-
adapters: [estreeAdapter, createPythonAstNativeImporterAdapter(), createRustSynNativeImporterAdapter()]
|
|
83
|
+
adapters: [estreeAdapter, createPythonAstNativeImporterAdapter(), createRustSynNativeImporterAdapter(), createClangAstNativeImporterAdapter()]
|
|
83
84
|
});
|
|
84
85
|
const parserFormatMatrixDurationMs = performance.now() - parserFormatMatrixStart;
|
|
85
86
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1410,6 +1410,31 @@ 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
|
+
|
|
1413
1438
|
export interface TreeSitterNativeImporterAdapterOptions {
|
|
1414
1439
|
readonly id?: string;
|
|
1415
1440
|
readonly language?: FrontierSourceLanguage;
|
|
@@ -1781,6 +1806,7 @@ export declare function createBabelNativeImporterAdapter(options?: JavaScriptNat
|
|
|
1781
1806
|
export declare function createTypeScriptCompilerNativeImporterAdapter(options?: TypeScriptCompilerNativeImporterAdapterOptions): NativeImporterAdapter;
|
|
1782
1807
|
export declare function createPythonAstNativeImporterAdapter(options?: PythonAstNativeImporterAdapterOptions): NativeImporterAdapter;
|
|
1783
1808
|
export declare function createRustSynNativeImporterAdapter(options?: RustSynNativeImporterAdapterOptions): NativeImporterAdapter;
|
|
1809
|
+
export declare function createClangAstNativeImporterAdapter(options?: ClangAstNativeImporterAdapterOptions): NativeImporterAdapter;
|
|
1784
1810
|
export declare function createTreeSitterNativeImporterAdapter(options?: TreeSitterNativeImporterAdapterOptions): NativeImporterAdapter;
|
|
1785
1811
|
export declare function runNativeImporterAdapter(adapter: NativeImporterAdapter, input: RunNativeImporterAdapterOptions): Promise<NativeImporterAdapterImportResult>;
|
|
1786
1812
|
export declare function runNativeTargetProjectionAdapter(adapter: NativeTargetProjectionAdapter, input: NativeTargetProjectionAdapterInput): NativeTargetProjectionResult;
|
package/dist/index.js
CHANGED
|
@@ -403,6 +403,18 @@ 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
|
+
}),
|
|
406
418
|
nativeParserAstFormatProfile('tree-sitter', {
|
|
407
419
|
kind: 'concrete-syntax-tree',
|
|
408
420
|
languages: ['mixed'],
|
|
@@ -2711,6 +2723,64 @@ export function createRustSynNativeImporterAdapter(options = {}) {
|
|
|
2711
2723
|
};
|
|
2712
2724
|
}
|
|
2713
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
|
+
|
|
2714
2784
|
export function createTreeSitterNativeImporterAdapter(options = {}) {
|
|
2715
2785
|
return {
|
|
2716
2786
|
id: options.id ?? `frontier.tree-sitter-${idFragment(options.language ?? 'source')}-native-importer`,
|
|
@@ -7151,6 +7221,7 @@ function parserAstFormatIdForParser(parser) {
|
|
|
7151
7221
|
if (text.includes('python') && text.includes('ast')) return 'python-ast';
|
|
7152
7222
|
if (text === 'syn' || text.includes('rust-syn')) return 'rust-syn';
|
|
7153
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';
|
|
7154
7225
|
if (text.includes('tree-sitter') || text.includes('treesitter')) return 'tree-sitter';
|
|
7155
7226
|
if (text.includes('babel')) return 'babel';
|
|
7156
7227
|
if (text.includes('estree')) return 'estree';
|
|
@@ -8199,6 +8270,23 @@ function parseRustSynSource(input, options) {
|
|
|
8199
8270
|
return parse(input.sourceText, parserOptions);
|
|
8200
8271
|
}
|
|
8201
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
|
+
|
|
8202
8290
|
function createNativeImportFromSyntaxAst(ast, input, options) {
|
|
8203
8291
|
const root = normalizeSyntaxAstRoot(ast, options.astFormat);
|
|
8204
8292
|
if (!root) {
|
|
@@ -8319,6 +8407,42 @@ function createNativeImportFromRustSyn(root, input, options) {
|
|
|
8319
8407
|
};
|
|
8320
8408
|
}
|
|
8321
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
|
+
|
|
8322
8446
|
function createNativeImportFromTreeSitter(root, input, options) {
|
|
8323
8447
|
const context = createAstNormalizationContext(input, options);
|
|
8324
8448
|
visitTreeSitterNode(root, context, 'root');
|
|
@@ -8563,6 +8687,67 @@ function visitRustSynNode(node, context, propertyPath) {
|
|
|
8563
8687
|
return id;
|
|
8564
8688
|
}
|
|
8565
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
|
+
|
|
8566
8751
|
function visitTreeSitterNode(node, context, propertyPath) {
|
|
8567
8752
|
if (!node || typeof node !== 'object' || context.truncated) return undefined;
|
|
8568
8753
|
if (context.objectIds.has(node)) return context.objectIds.get(node);
|
|
@@ -10229,6 +10414,249 @@ function rustSynMacroKind(kind) {
|
|
|
10229
10414
|
return /Macro|MacroRules|MacroCall/.test(String(kind));
|
|
10230
10415
|
}
|
|
10231
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
|
+
|
|
10232
10660
|
function declarationRecord(input, nativeNodeId, name, symbolKind, role = 'definition') {
|
|
10233
10661
|
return {
|
|
10234
10662
|
name: String(name),
|
package/package.json
CHANGED