@shapeshift-labs/frontier-lang-compiler 0.2.25 → 0.2.27
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 +18 -2
- package/bench/smoke.mjs +14 -0
- package/dist/index.d.ts +133 -0
- package/dist/index.js +1033 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -333,6 +333,125 @@ export const NativeImportLanguageProfiles = Object.freeze([
|
|
|
333
333
|
nativeImportLanguageProfile('r', { aliases: ['R'], extensions: ['.r', '.R'], parserAdapters: ['r-parser', 'tree-sitter'], lossKinds: ['declarationOnlyCoverage', 'opaqueNative', 'dynamicRuntime', 'sourceMapApproximation', 'sourcePreservation'] })
|
|
334
334
|
]);
|
|
335
335
|
|
|
336
|
+
export const NativeParserAstFormatProfiles = Object.freeze([
|
|
337
|
+
nativeParserAstFormatProfile('estree', {
|
|
338
|
+
kind: 'abstract-ast',
|
|
339
|
+
languages: ['javascript'],
|
|
340
|
+
parserAdapters: ['estree'],
|
|
341
|
+
exactness: 'exact-parser-ast',
|
|
342
|
+
sourceRangeModel: 'loc-range',
|
|
343
|
+
preservesTokens: false,
|
|
344
|
+
preservesTrivia: false,
|
|
345
|
+
supportsErrorRecovery: false,
|
|
346
|
+
notes: ['Community JavaScript AST shape used by many JS tooling parsers.']
|
|
347
|
+
}),
|
|
348
|
+
nativeParserAstFormatProfile('babel', {
|
|
349
|
+
kind: 'abstract-ast',
|
|
350
|
+
languages: ['javascript', 'typescript'],
|
|
351
|
+
parserAdapters: ['babel'],
|
|
352
|
+
exactness: 'exact-parser-ast',
|
|
353
|
+
sourceRangeModel: 'loc-range',
|
|
354
|
+
preservesTokens: false,
|
|
355
|
+
preservesTrivia: false,
|
|
356
|
+
supportsErrorRecovery: true,
|
|
357
|
+
notes: ['Babel-compatible ESTree-like ASTs can report parser errors when error recovery is enabled.']
|
|
358
|
+
}),
|
|
359
|
+
nativeParserAstFormatProfile('typescript-compiler-api', {
|
|
360
|
+
kind: 'compiler-ast',
|
|
361
|
+
languages: ['typescript', 'javascript'],
|
|
362
|
+
parserAdapters: ['typescript-compiler-api'],
|
|
363
|
+
exactness: 'exact-parser-ast',
|
|
364
|
+
sourceRangeModel: 'pos-end',
|
|
365
|
+
preservesTokens: false,
|
|
366
|
+
preservesTrivia: false,
|
|
367
|
+
supportsErrorRecovery: true,
|
|
368
|
+
notes: ['TypeScript SourceFile trees can be parsed without a full Program; richer type/checker evidence remains host-owned.']
|
|
369
|
+
}),
|
|
370
|
+
nativeParserAstFormatProfile('python-ast', {
|
|
371
|
+
kind: 'abstract-ast',
|
|
372
|
+
languages: ['python'],
|
|
373
|
+
parserAdapters: ['python-ast'],
|
|
374
|
+
exactness: 'exact-parser-ast',
|
|
375
|
+
sourceRangeModel: 'lineno-col-offset',
|
|
376
|
+
preservesTokens: false,
|
|
377
|
+
preservesTrivia: false,
|
|
378
|
+
supportsErrorRecovery: false,
|
|
379
|
+
notes: ['Python stdlib AST exposes versioned abstract grammar and source locations, but not formatting trivia.']
|
|
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('tree-sitter', {
|
|
407
|
+
kind: 'concrete-syntax-tree',
|
|
408
|
+
languages: ['mixed'],
|
|
409
|
+
parserAdapters: ['tree-sitter'],
|
|
410
|
+
exactness: 'parser-tree',
|
|
411
|
+
sourceRangeModel: 'row-column',
|
|
412
|
+
preservesTokens: false,
|
|
413
|
+
preservesTrivia: false,
|
|
414
|
+
supportsIncremental: true,
|
|
415
|
+
supportsErrorRecovery: true,
|
|
416
|
+
notes: ['Tree-sitter provides cross-language concrete syntax trees; language-specific queries still decide semantic richness.']
|
|
417
|
+
}),
|
|
418
|
+
nativeParserAstFormatProfile('libcst', {
|
|
419
|
+
kind: 'concrete-syntax-tree',
|
|
420
|
+
languages: ['python'],
|
|
421
|
+
parserAdapters: ['libcst'],
|
|
422
|
+
exactness: 'parser-tree',
|
|
423
|
+
sourceRangeModel: 'metadata-position-provider',
|
|
424
|
+
preservesTokens: true,
|
|
425
|
+
preservesTrivia: true,
|
|
426
|
+
supportsErrorRecovery: false,
|
|
427
|
+
notes: ['LibCST-style trees preserve formatting and are best treated as host-owned evidence until normalized explicitly.']
|
|
428
|
+
}),
|
|
429
|
+
nativeParserAstFormatProfile('scip', {
|
|
430
|
+
kind: 'semantic-index',
|
|
431
|
+
languages: ['mixed'],
|
|
432
|
+
parserAdapters: ['scip'],
|
|
433
|
+
exactness: 'loss-aware-native-ast',
|
|
434
|
+
sourceRangeModel: 'range-tuples',
|
|
435
|
+
preservesTokens: false,
|
|
436
|
+
preservesTrivia: false,
|
|
437
|
+
supportsErrorRecovery: false,
|
|
438
|
+
notes: ['SCIP is semantic index evidence rather than a full parser AST; it is useful for symbols/references and source maps.']
|
|
439
|
+
}),
|
|
440
|
+
nativeParserAstFormatProfile('lsif', {
|
|
441
|
+
kind: 'semantic-index',
|
|
442
|
+
languages: ['mixed'],
|
|
443
|
+
parserAdapters: ['lsif'],
|
|
444
|
+
exactness: 'loss-aware-native-ast',
|
|
445
|
+
sourceRangeModel: 'lsp-ranges',
|
|
446
|
+
preservesTokens: false,
|
|
447
|
+
preservesTrivia: false,
|
|
448
|
+
supportsErrorRecovery: false,
|
|
449
|
+
notes: ['LSIF graph dumps are semantic/source-map evidence, not complete native ASTs.']
|
|
450
|
+
})
|
|
451
|
+
]);
|
|
452
|
+
|
|
453
|
+
export const NativeParserAstFormats = Object.freeze(NativeParserAstFormatProfiles.map((profile) => profile.id));
|
|
454
|
+
|
|
336
455
|
export const ExternalSemanticIndexFormats = Object.freeze([
|
|
337
456
|
'frontier-semantic-index',
|
|
338
457
|
'scip',
|
|
@@ -2125,6 +2244,57 @@ export function createNativeImportCoverageMatrix(input = {}) {
|
|
|
2125
2244
|
};
|
|
2126
2245
|
}
|
|
2127
2246
|
|
|
2247
|
+
export function getNativeParserAstFormatProfile(format) {
|
|
2248
|
+
const normalized = normalizeParserAstFormatId(format);
|
|
2249
|
+
return NativeParserAstFormatProfiles.find((profile) => profile.id === normalized || profile.aliases.includes(normalized));
|
|
2250
|
+
}
|
|
2251
|
+
|
|
2252
|
+
export function createNativeParserAstFormatMatrix(input = {}) {
|
|
2253
|
+
const imports = input.imports ?? [];
|
|
2254
|
+
const adapters = input.adapters ?? [];
|
|
2255
|
+
const profiles = mergeNativeParserAstFormatProfiles(input.formats ?? NativeParserAstFormatProfiles, imports, adapters);
|
|
2256
|
+
const formats = profiles.map((profile) => nativeParserAstFormatCoverageForProfile(profile, imports, adapters));
|
|
2257
|
+
const summary = formats.reduce((totals, entry) => {
|
|
2258
|
+
totals.formats += 1;
|
|
2259
|
+
totals.adapterSlots += entry.parserAdapters.length;
|
|
2260
|
+
totals.adapters += entry.adapters.total;
|
|
2261
|
+
totals.imports += entry.imports.total;
|
|
2262
|
+
totals.nativeAstNodes += entry.imports.nativeAstNodes;
|
|
2263
|
+
totals.symbols += entry.imports.symbols;
|
|
2264
|
+
totals.sourceMapMappings += entry.imports.sourceMapMappings;
|
|
2265
|
+
totals.losses += entry.imports.losses;
|
|
2266
|
+
totals.byKind[entry.kind] = (totals.byKind[entry.kind] ?? 0) + 1;
|
|
2267
|
+
totals.byReadiness[entry.imports.readiness] = (totals.byReadiness[entry.imports.readiness] ?? 0) + 1;
|
|
2268
|
+
for (const [capability, count] of Object.entries(entry.adapters.effectiveCapabilities)) {
|
|
2269
|
+
totals.effectiveCapabilities[capability] = (totals.effectiveCapabilities[capability] ?? 0) + count;
|
|
2270
|
+
}
|
|
2271
|
+
return totals;
|
|
2272
|
+
}, {
|
|
2273
|
+
formats: 0,
|
|
2274
|
+
adapterSlots: 0,
|
|
2275
|
+
adapters: 0,
|
|
2276
|
+
imports: 0,
|
|
2277
|
+
nativeAstNodes: 0,
|
|
2278
|
+
symbols: 0,
|
|
2279
|
+
sourceMapMappings: 0,
|
|
2280
|
+
losses: 0,
|
|
2281
|
+
byKind: {},
|
|
2282
|
+
byReadiness: {},
|
|
2283
|
+
effectiveCapabilities: {}
|
|
2284
|
+
});
|
|
2285
|
+
return {
|
|
2286
|
+
kind: 'frontier.lang.nativeParserAstFormatMatrix',
|
|
2287
|
+
version: 1,
|
|
2288
|
+
generatedAt: input.generatedAt ?? Date.now(),
|
|
2289
|
+
formats,
|
|
2290
|
+
summary,
|
|
2291
|
+
metadata: {
|
|
2292
|
+
note: 'Parser AST format coverage describes normalization evidence and host-parser obligations; it is not a lossless portability claim.',
|
|
2293
|
+
profileIds: profiles.map((profile) => profile.id)
|
|
2294
|
+
}
|
|
2295
|
+
};
|
|
2296
|
+
}
|
|
2297
|
+
|
|
2128
2298
|
export function createProjectionTargetLossMatrix(input = {}) {
|
|
2129
2299
|
const imports = input.imports ?? [];
|
|
2130
2300
|
const adapters = input.adapters ?? [];
|
|
@@ -2435,6 +2605,112 @@ export function createTypeScriptCompilerNativeImporterAdapter(options = {}) {
|
|
|
2435
2605
|
};
|
|
2436
2606
|
}
|
|
2437
2607
|
|
|
2608
|
+
export function createPythonAstNativeImporterAdapter(options = {}) {
|
|
2609
|
+
return {
|
|
2610
|
+
id: options.id ?? 'frontier.python-ast-native-importer',
|
|
2611
|
+
language: options.language ?? 'python',
|
|
2612
|
+
parser: options.parser ?? 'python-ast',
|
|
2613
|
+
version: options.version,
|
|
2614
|
+
capabilities: uniqueStrings(['nativeAst', 'semanticIndex', 'sourceMaps', 'diagnostics', ...(options.capabilities ?? [])]),
|
|
2615
|
+
coverage: nativeImporterAdapterCoverage({
|
|
2616
|
+
exactness: 'exact-parser-ast',
|
|
2617
|
+
exactAst: true,
|
|
2618
|
+
tokens: false,
|
|
2619
|
+
trivia: false,
|
|
2620
|
+
diagnostics: true,
|
|
2621
|
+
sourceRanges: true,
|
|
2622
|
+
generatedRanges: false,
|
|
2623
|
+
semanticCoverage: declarationSemanticCoverage(),
|
|
2624
|
+
notes: [
|
|
2625
|
+
'Normalizes caller-owned Python stdlib ast trees into native AST nodes and declaration-level semantic index records.',
|
|
2626
|
+
'Python ast does not preserve comments, whitespace, or concrete formatting; use LibCST/parso-style host evidence for round-trip trivia.'
|
|
2627
|
+
]
|
|
2628
|
+
}, options.coverage),
|
|
2629
|
+
supportedExtensions: options.supportedExtensions ?? ['.py', '.pyi'],
|
|
2630
|
+
diagnostics: options.diagnostics,
|
|
2631
|
+
parse(input) {
|
|
2632
|
+
const parsed = input.options?.ast
|
|
2633
|
+
?? input.options?.nativeAst
|
|
2634
|
+
?? options.ast
|
|
2635
|
+
?? parsePythonAstSource(input, options);
|
|
2636
|
+
const root = pythonAstRoot(parsed);
|
|
2637
|
+
if (!root) {
|
|
2638
|
+
return missingInjectedParserResult(input, {
|
|
2639
|
+
parser: options.parser ?? 'python-ast',
|
|
2640
|
+
adapterId: options.id ?? 'frontier.python-ast-native-importer',
|
|
2641
|
+
message: 'createPythonAstNativeImporterAdapter requires an injected Python AST object, parserModule.parse function, parse function, or adapterOptions.ast.'
|
|
2642
|
+
});
|
|
2643
|
+
}
|
|
2644
|
+
const parseDiagnostics = normalizeParserErrors(parsed?.errors ?? parsed?.diagnostics, input, {
|
|
2645
|
+
parser: options.parser ?? 'python-ast'
|
|
2646
|
+
});
|
|
2647
|
+
return createNativeImportFromPythonAst(root, input, {
|
|
2648
|
+
parser: options.parser ?? 'python-ast',
|
|
2649
|
+
astFormat: 'python-ast',
|
|
2650
|
+
maxNodes: options.maxNodes,
|
|
2651
|
+
diagnostics: parseDiagnostics,
|
|
2652
|
+
pythonVersion: options.pythonVersion ?? input.options?.pythonVersion ?? parsed?.pythonVersion,
|
|
2653
|
+
includeAttributes: options.includeAttributes ?? input.options?.includeAttributes
|
|
2654
|
+
});
|
|
2655
|
+
}
|
|
2656
|
+
};
|
|
2657
|
+
}
|
|
2658
|
+
|
|
2659
|
+
export function createRustSynNativeImporterAdapter(options = {}) {
|
|
2660
|
+
return {
|
|
2661
|
+
id: options.id ?? 'frontier.rust-syn-native-importer',
|
|
2662
|
+
language: options.language ?? 'rust',
|
|
2663
|
+
parser: options.parser ?? 'syn',
|
|
2664
|
+
version: options.version,
|
|
2665
|
+
capabilities: uniqueStrings(['nativeAst', 'semanticIndex', 'sourceMaps', 'diagnostics', ...(options.capabilities ?? [])]),
|
|
2666
|
+
coverage: nativeImporterAdapterCoverage({
|
|
2667
|
+
exactness: 'exact-parser-ast',
|
|
2668
|
+
exactAst: true,
|
|
2669
|
+
tokens: false,
|
|
2670
|
+
trivia: false,
|
|
2671
|
+
diagnostics: true,
|
|
2672
|
+
sourceRanges: false,
|
|
2673
|
+
generatedRanges: false,
|
|
2674
|
+
semanticCoverage: declarationSemanticCoverage(),
|
|
2675
|
+
notes: [
|
|
2676
|
+
'Normalizes caller-owned syn-shaped Rust ASTs into native AST nodes and declaration-level semantic index records.',
|
|
2677
|
+
'syn does not expand macros, resolve names, type-check, or preserve full concrete syntax/trivia; attach rust-analyzer/rustc evidence for those claims.'
|
|
2678
|
+
]
|
|
2679
|
+
}, options.coverage),
|
|
2680
|
+
supportedExtensions: options.supportedExtensions ?? ['.rs'],
|
|
2681
|
+
diagnostics: options.diagnostics,
|
|
2682
|
+
parse(input) {
|
|
2683
|
+
const parsed = input.options?.ast
|
|
2684
|
+
?? input.options?.nativeAst
|
|
2685
|
+
?? input.options?.file
|
|
2686
|
+
?? input.options?.sourceFile
|
|
2687
|
+
?? options.ast
|
|
2688
|
+
?? options.file
|
|
2689
|
+
?? options.sourceFile
|
|
2690
|
+
?? parseRustSynSource(input, options);
|
|
2691
|
+
const root = rustSynAstRoot(parsed);
|
|
2692
|
+
if (!root) {
|
|
2693
|
+
return missingInjectedParserResult(input, {
|
|
2694
|
+
parser: options.parser ?? 'syn',
|
|
2695
|
+
adapterId: options.id ?? 'frontier.rust-syn-native-importer',
|
|
2696
|
+
message: 'createRustSynNativeImporterAdapter requires an injected syn-shaped AST object, parserModule.parse function, parse function, or adapterOptions.ast.'
|
|
2697
|
+
});
|
|
2698
|
+
}
|
|
2699
|
+
const parseDiagnostics = normalizeParserErrors(parsed?.errors ?? parsed?.diagnostics, input, {
|
|
2700
|
+
parser: options.parser ?? 'syn'
|
|
2701
|
+
});
|
|
2702
|
+
return createNativeImportFromRustSyn(root, input, {
|
|
2703
|
+
parser: options.parser ?? 'syn',
|
|
2704
|
+
astFormat: 'rust-syn',
|
|
2705
|
+
maxNodes: options.maxNodes,
|
|
2706
|
+
diagnostics: parseDiagnostics,
|
|
2707
|
+
rustEdition: options.rustEdition ?? input.options?.rustEdition ?? parsed?.rustEdition,
|
|
2708
|
+
includeAttributes: options.includeAttributes ?? input.options?.includeAttributes
|
|
2709
|
+
});
|
|
2710
|
+
}
|
|
2711
|
+
};
|
|
2712
|
+
}
|
|
2713
|
+
|
|
2438
2714
|
export function createTreeSitterNativeImporterAdapter(options = {}) {
|
|
2439
2715
|
return {
|
|
2440
2716
|
id: options.id ?? `frontier.tree-sitter-${idFragment(options.language ?? 'source')}-native-importer`,
|
|
@@ -6767,6 +7043,134 @@ function nativeImportLanguageProfile(language, input = {}) {
|
|
|
6767
7043
|
});
|
|
6768
7044
|
}
|
|
6769
7045
|
|
|
7046
|
+
function nativeParserAstFormatProfile(id, input = {}) {
|
|
7047
|
+
return Object.freeze({
|
|
7048
|
+
id,
|
|
7049
|
+
aliases: Object.freeze(uniqueStrings(input.aliases ?? [])),
|
|
7050
|
+
kind: input.kind ?? 'abstract-ast',
|
|
7051
|
+
languages: Object.freeze(uniqueStrings(input.languages ?? [])),
|
|
7052
|
+
parserAdapters: Object.freeze(uniqueStrings(input.parserAdapters ?? [id])),
|
|
7053
|
+
exactness: input.exactness ?? 'unknown',
|
|
7054
|
+
sourceRangeModel: input.sourceRangeModel ?? 'unknown',
|
|
7055
|
+
preservesTokens: Boolean(input.preservesTokens),
|
|
7056
|
+
preservesTrivia: Boolean(input.preservesTrivia),
|
|
7057
|
+
supportsIncremental: Boolean(input.supportsIncremental),
|
|
7058
|
+
supportsErrorRecovery: Boolean(input.supportsErrorRecovery),
|
|
7059
|
+
notes: Object.freeze(uniqueStrings(input.notes ?? []))
|
|
7060
|
+
});
|
|
7061
|
+
}
|
|
7062
|
+
|
|
7063
|
+
function normalizeParserAstFormatId(format) {
|
|
7064
|
+
return String(format ?? '').trim().toLowerCase().replace(/[_\s]+/g, '-');
|
|
7065
|
+
}
|
|
7066
|
+
|
|
7067
|
+
function mergeNativeParserAstFormatProfiles(profiles, imports, adapters) {
|
|
7068
|
+
const byId = new Map((profiles ?? []).map((profile) => [normalizeParserAstFormatId(profile.id ?? profile), nativeParserAstFormatProfile(normalizeParserAstFormatId(profile.id ?? profile), profile)]));
|
|
7069
|
+
for (const adapter of adapters ?? []) {
|
|
7070
|
+
const summary = safeNativeImporterAdapterSummary(adapter);
|
|
7071
|
+
if (!summary) continue;
|
|
7072
|
+
const formatId = parserAstFormatIdForParser(summary.parser);
|
|
7073
|
+
if (!byId.has(formatId)) {
|
|
7074
|
+
byId.set(formatId, nativeParserAstFormatProfile(formatId, {
|
|
7075
|
+
languages: [summary.language],
|
|
7076
|
+
parserAdapters: [summary.parser],
|
|
7077
|
+
exactness: summary.coverage.exactness,
|
|
7078
|
+
sourceRangeModel: summary.coverage.sourceRanges ? 'adapter-reported' : 'unknown'
|
|
7079
|
+
}));
|
|
7080
|
+
}
|
|
7081
|
+
}
|
|
7082
|
+
for (const imported of imports ?? []) {
|
|
7083
|
+
const formatId = parserAstFormatIdForImport(imported);
|
|
7084
|
+
if (formatId && !byId.has(formatId)) {
|
|
7085
|
+
byId.set(formatId, nativeParserAstFormatProfile(formatId, {
|
|
7086
|
+
languages: [imported.language].filter(Boolean),
|
|
7087
|
+
parserAdapters: [imported.parser ?? imported.nativeAst?.parser ?? formatId],
|
|
7088
|
+
exactness: 'unknown',
|
|
7089
|
+
sourceRangeModel: (imported.sourceMaps ?? []).some((sourceMap) => sourceMap.mappings?.some((mapping) => mapping.sourceSpan)) ? 'adapter-reported' : 'unknown'
|
|
7090
|
+
}));
|
|
7091
|
+
}
|
|
7092
|
+
}
|
|
7093
|
+
return [...byId.values()].sort((left, right) => left.id.localeCompare(right.id));
|
|
7094
|
+
}
|
|
7095
|
+
|
|
7096
|
+
function nativeParserAstFormatCoverageForProfile(profile, imports, adapters) {
|
|
7097
|
+
const formatIds = new Set([profile.id, ...profile.aliases].map(normalizeParserAstFormatId));
|
|
7098
|
+
const adapterParsers = new Set(profile.parserAdapters.map(parserAstFormatIdForParser));
|
|
7099
|
+
const matchingAdapters = (adapters ?? [])
|
|
7100
|
+
.map((adapter) => safeNativeImporterAdapterSummary(adapter))
|
|
7101
|
+
.filter(Boolean)
|
|
7102
|
+
.filter((adapter) => formatIds.has(parserAstFormatIdForParser(adapter.parser)) || adapterParsers.has(parserAstFormatIdForParser(adapter.parser)));
|
|
7103
|
+
const matchingImports = (imports ?? [])
|
|
7104
|
+
.filter((imported) => {
|
|
7105
|
+
const formatId = parserAstFormatIdForImport(imported);
|
|
7106
|
+
return formatId && (formatIds.has(formatId) || adapterParsers.has(formatId));
|
|
7107
|
+
});
|
|
7108
|
+
const effectiveCapabilities = {};
|
|
7109
|
+
for (const adapter of matchingAdapters) {
|
|
7110
|
+
for (const row of adapter.coverage.capabilityEvidence?.capabilities ?? []) {
|
|
7111
|
+
if (row.effective) effectiveCapabilities[row.capability] = (effectiveCapabilities[row.capability] ?? 0) + 1;
|
|
7112
|
+
}
|
|
7113
|
+
}
|
|
7114
|
+
const readiness = matchingImports.reduce(
|
|
7115
|
+
(current, imported) => maxSemanticMergeReadiness(current, nativeImportReadiness(imported)),
|
|
7116
|
+
matchingImports.length ? 'ready' : 'needs-review'
|
|
7117
|
+
);
|
|
7118
|
+
return {
|
|
7119
|
+
id: profile.id,
|
|
7120
|
+
kind: profile.kind,
|
|
7121
|
+
languages: profile.languages,
|
|
7122
|
+
parserAdapters: profile.parserAdapters,
|
|
7123
|
+
exactness: profile.exactness,
|
|
7124
|
+
sourceRangeModel: profile.sourceRangeModel,
|
|
7125
|
+
preservesTokens: profile.preservesTokens,
|
|
7126
|
+
preservesTrivia: profile.preservesTrivia,
|
|
7127
|
+
supportsIncremental: profile.supportsIncremental,
|
|
7128
|
+
supportsErrorRecovery: profile.supportsErrorRecovery,
|
|
7129
|
+
notes: profile.notes,
|
|
7130
|
+
adapters: {
|
|
7131
|
+
total: matchingAdapters.length,
|
|
7132
|
+
ids: matchingAdapters.map((adapter) => adapter.id),
|
|
7133
|
+
parsers: uniqueStrings(matchingAdapters.map((adapter) => adapter.parser)),
|
|
7134
|
+
effectiveCapabilities
|
|
7135
|
+
},
|
|
7136
|
+
imports: {
|
|
7137
|
+
total: matchingImports.length,
|
|
7138
|
+
sourcePaths: matchingImports.map((imported) => imported.sourcePath).filter(Boolean),
|
|
7139
|
+
readiness,
|
|
7140
|
+
nativeAstNodes: matchingImports.reduce((sum, imported) => sum + Object.keys(imported.nativeAst?.nodes ?? {}).length, 0),
|
|
7141
|
+
symbols: matchingImports.reduce((sum, imported) => sum + (imported.semanticIndex?.symbols?.length ?? 0), 0),
|
|
7142
|
+
sourceMapMappings: matchingImports.reduce((sum, imported) => sum + (imported.sourceMaps ?? []).reduce((mapSum, sourceMap) => mapSum + (sourceMap.mappings?.length ?? 0), 0), 0),
|
|
7143
|
+
losses: matchingImports.reduce((sum, imported) => sum + (imported.losses?.length ?? 0), 0)
|
|
7144
|
+
}
|
|
7145
|
+
};
|
|
7146
|
+
}
|
|
7147
|
+
|
|
7148
|
+
function parserAstFormatIdForParser(parser) {
|
|
7149
|
+
const text = normalizeParserAstFormatId(parser);
|
|
7150
|
+
if (text.includes('typescript')) return 'typescript-compiler-api';
|
|
7151
|
+
if (text.includes('python') && text.includes('ast')) return 'python-ast';
|
|
7152
|
+
if (text === 'syn' || text.includes('rust-syn')) return 'rust-syn';
|
|
7153
|
+
if (text.includes('rust-analyzer') || text.includes('rowan')) return 'rust-analyzer-rowan';
|
|
7154
|
+
if (text.includes('tree-sitter') || text.includes('treesitter')) return 'tree-sitter';
|
|
7155
|
+
if (text.includes('babel')) return 'babel';
|
|
7156
|
+
if (text.includes('estree')) return 'estree';
|
|
7157
|
+
if (text.includes('libcst')) return 'libcst';
|
|
7158
|
+
if (text.includes('scip')) return 'scip';
|
|
7159
|
+
if (text.includes('lsif')) return 'lsif';
|
|
7160
|
+
return text || 'unknown';
|
|
7161
|
+
}
|
|
7162
|
+
|
|
7163
|
+
function parserAstFormatIdForImport(imported) {
|
|
7164
|
+
return parserAstFormatIdForParser(
|
|
7165
|
+
imported?.metadata?.adapter?.parser
|
|
7166
|
+
?? imported?.metadata?.astFormat
|
|
7167
|
+
?? imported?.nativeAst?.metadata?.astFormat
|
|
7168
|
+
?? imported?.nativeAst?.parser
|
|
7169
|
+
?? imported?.parser
|
|
7170
|
+
?? imported?.metadata?.parser
|
|
7171
|
+
);
|
|
7172
|
+
}
|
|
7173
|
+
|
|
6770
7174
|
function mergeNativeImportProfiles(languages, imports, adapters, targetAdapters = []) {
|
|
6771
7175
|
const profilesByLanguage = new Map();
|
|
6772
7176
|
for (const profile of languages) {
|
|
@@ -7764,6 +8168,37 @@ function parseTreeSitterSource(input, options) {
|
|
|
7764
8168
|
return undefined;
|
|
7765
8169
|
}
|
|
7766
8170
|
|
|
8171
|
+
function parsePythonAstSource(input, options) {
|
|
8172
|
+
const parse = options.parse ?? options.parserModule?.parse ?? options.pythonAst?.parse;
|
|
8173
|
+
if (typeof parse !== 'function') return undefined;
|
|
8174
|
+
const parserOptions = {
|
|
8175
|
+
sourcePath: input.sourcePath,
|
|
8176
|
+
filename: input.sourcePath,
|
|
8177
|
+
mode: options.mode ?? input.options?.mode ?? 'exec',
|
|
8178
|
+
typeComments: options.typeComments ?? input.options?.typeComments,
|
|
8179
|
+
featureVersion: options.featureVersion ?? input.options?.featureVersion,
|
|
8180
|
+
optimize: options.optimize ?? input.options?.optimize,
|
|
8181
|
+
includeAttributes: options.includeAttributes ?? input.options?.includeAttributes,
|
|
8182
|
+
...(options.parserOptions ?? {}),
|
|
8183
|
+
...(input.options?.parserOptions ?? {})
|
|
8184
|
+
};
|
|
8185
|
+
return parse(input.sourceText, parserOptions);
|
|
8186
|
+
}
|
|
8187
|
+
|
|
8188
|
+
function parseRustSynSource(input, options) {
|
|
8189
|
+
const parse = options.parse ?? options.parserModule?.parse ?? options.rustSyn?.parse ?? options.syn?.parse;
|
|
8190
|
+
if (typeof parse !== 'function') return undefined;
|
|
8191
|
+
const parserOptions = {
|
|
8192
|
+
sourcePath: input.sourcePath,
|
|
8193
|
+
filename: input.sourcePath,
|
|
8194
|
+
edition: options.rustEdition ?? input.options?.rustEdition ?? '2021',
|
|
8195
|
+
includeAttributes: options.includeAttributes ?? input.options?.includeAttributes,
|
|
8196
|
+
...(options.parserOptions ?? {}),
|
|
8197
|
+
...(input.options?.parserOptions ?? {})
|
|
8198
|
+
};
|
|
8199
|
+
return parse(input.sourceText, parserOptions);
|
|
8200
|
+
}
|
|
8201
|
+
|
|
7767
8202
|
function createNativeImportFromSyntaxAst(ast, input, options) {
|
|
7768
8203
|
const root = normalizeSyntaxAstRoot(ast, options.astFormat);
|
|
7769
8204
|
if (!root) {
|
|
@@ -7824,6 +8259,66 @@ function createNativeImportFromTypeScriptAst(sourceFile, input, options) {
|
|
|
7824
8259
|
};
|
|
7825
8260
|
}
|
|
7826
8261
|
|
|
8262
|
+
function createNativeImportFromPythonAst(root, input, options) {
|
|
8263
|
+
const context = createAstNormalizationContext(input, options);
|
|
8264
|
+
visitPythonAstNode(root, context, 'root');
|
|
8265
|
+
if (context.truncated) {
|
|
8266
|
+
context.losses.push(truncatedAstLoss(input, context, options));
|
|
8267
|
+
}
|
|
8268
|
+
const semantic = semanticIndexFromNativeDeclarations(context.declarations, input, options);
|
|
8269
|
+
return {
|
|
8270
|
+
rootId: context.rootId,
|
|
8271
|
+
nodes: context.nodes,
|
|
8272
|
+
semanticIndex: semantic.semanticIndex,
|
|
8273
|
+
mappings: semantic.mappings,
|
|
8274
|
+
losses: mergeNativeLosses(context.losses, options.diagnostics?.map((diagnostic, index) => adapterDiagnosticToLoss(diagnostic, index, {
|
|
8275
|
+
id: input.adapterId,
|
|
8276
|
+
version: input.adapterVersion
|
|
8277
|
+
}, input)) ?? []),
|
|
8278
|
+
evidence: semantic.evidence,
|
|
8279
|
+
diagnostics: options.diagnostics,
|
|
8280
|
+
metadata: {
|
|
8281
|
+
astFormat: options.astFormat,
|
|
8282
|
+
parser: options.parser,
|
|
8283
|
+
pythonVersion: options.pythonVersion,
|
|
8284
|
+
includeAttributes: Boolean(options.includeAttributes),
|
|
8285
|
+
normalizedNodeCount: Object.keys(context.nodes).length,
|
|
8286
|
+
declarationCount: context.declarations.length,
|
|
8287
|
+
truncated: context.truncated
|
|
8288
|
+
}
|
|
8289
|
+
};
|
|
8290
|
+
}
|
|
8291
|
+
|
|
8292
|
+
function createNativeImportFromRustSyn(root, input, options) {
|
|
8293
|
+
const context = createAstNormalizationContext(input, options);
|
|
8294
|
+
visitRustSynNode(root, context, 'root');
|
|
8295
|
+
if (context.truncated) {
|
|
8296
|
+
context.losses.push(truncatedAstLoss(input, context, options));
|
|
8297
|
+
}
|
|
8298
|
+
const semantic = semanticIndexFromNativeDeclarations(context.declarations, input, options);
|
|
8299
|
+
return {
|
|
8300
|
+
rootId: context.rootId,
|
|
8301
|
+
nodes: context.nodes,
|
|
8302
|
+
semanticIndex: semantic.semanticIndex,
|
|
8303
|
+
mappings: semantic.mappings,
|
|
8304
|
+
losses: mergeNativeLosses(context.losses, options.diagnostics?.map((diagnostic, index) => adapterDiagnosticToLoss(diagnostic, index, {
|
|
8305
|
+
id: input.adapterId,
|
|
8306
|
+
version: input.adapterVersion
|
|
8307
|
+
}, input)) ?? []),
|
|
8308
|
+
evidence: semantic.evidence,
|
|
8309
|
+
diagnostics: options.diagnostics,
|
|
8310
|
+
metadata: {
|
|
8311
|
+
astFormat: options.astFormat,
|
|
8312
|
+
parser: options.parser,
|
|
8313
|
+
rustEdition: options.rustEdition,
|
|
8314
|
+
includeAttributes: Boolean(options.includeAttributes),
|
|
8315
|
+
normalizedNodeCount: Object.keys(context.nodes).length,
|
|
8316
|
+
declarationCount: context.declarations.length,
|
|
8317
|
+
truncated: context.truncated
|
|
8318
|
+
}
|
|
8319
|
+
};
|
|
8320
|
+
}
|
|
8321
|
+
|
|
7827
8322
|
function createNativeImportFromTreeSitter(root, input, options) {
|
|
7828
8323
|
const context = createAstNormalizationContext(input, options);
|
|
7829
8324
|
visitTreeSitterNode(root, context, 'root');
|
|
@@ -7960,6 +8455,114 @@ function visitTypeScriptAstNode(node, sourceFile, context, propertyPath, ts) {
|
|
|
7960
8455
|
return id;
|
|
7961
8456
|
}
|
|
7962
8457
|
|
|
8458
|
+
function visitPythonAstNode(node, context, propertyPath) {
|
|
8459
|
+
if (!isPythonAstNode(node) || context.truncated) return undefined;
|
|
8460
|
+
if (context.objectIds.has(node)) return context.objectIds.get(node);
|
|
8461
|
+
if (context.counter >= context.maxNodes) {
|
|
8462
|
+
context.truncated = true;
|
|
8463
|
+
return undefined;
|
|
8464
|
+
}
|
|
8465
|
+
const kind = pythonAstKind(node);
|
|
8466
|
+
const span = spanFromPythonAstNode(node, context.input);
|
|
8467
|
+
const id = nativeNodeId(context, kind, { start: { line: span?.startLine, column: span?.startColumn } }, propertyPath);
|
|
8468
|
+
context.objectIds.set(node, id);
|
|
8469
|
+
if (!context.rootId) context.rootId = id;
|
|
8470
|
+
const children = [];
|
|
8471
|
+
for (const [field, value] of pythonAstChildEntries(node)) {
|
|
8472
|
+
if (Array.isArray(value)) {
|
|
8473
|
+
value.forEach((entry, index) => {
|
|
8474
|
+
const childId = visitPythonAstNode(entry, context, `${propertyPath}.${field}[${index}]`);
|
|
8475
|
+
if (childId) children.push(childId);
|
|
8476
|
+
});
|
|
8477
|
+
} else {
|
|
8478
|
+
const childId = visitPythonAstNode(value, context, `${propertyPath}.${field}`);
|
|
8479
|
+
if (childId) children.push(childId);
|
|
8480
|
+
}
|
|
8481
|
+
}
|
|
8482
|
+
const declaration = pythonAstDeclaration(node, kind, id, context.input);
|
|
8483
|
+
const nativeNode = {
|
|
8484
|
+
id,
|
|
8485
|
+
kind,
|
|
8486
|
+
languageKind: `${context.input.language}.${kind}`,
|
|
8487
|
+
span,
|
|
8488
|
+
value: declaration?.name ?? pythonAstNodeValue(node),
|
|
8489
|
+
fields: primitivePythonAstFields(node, kind),
|
|
8490
|
+
children,
|
|
8491
|
+
metadata: {
|
|
8492
|
+
astFormat: context.options.astFormat,
|
|
8493
|
+
propertyPath,
|
|
8494
|
+
lineno: numberOrUndefined(node.lineno ?? node.line),
|
|
8495
|
+
colOffset: numberOrUndefined(node.col_offset ?? node.colOffset),
|
|
8496
|
+
endLineno: numberOrUndefined(node.end_lineno ?? node.endLine),
|
|
8497
|
+
endColOffset: numberOrUndefined(node.end_col_offset ?? node.endColOffset)
|
|
8498
|
+
}
|
|
8499
|
+
};
|
|
8500
|
+
context.nodes[id] = nativeNode;
|
|
8501
|
+
if (declaration) context.declarations.push({ ...declaration, nativeNode });
|
|
8502
|
+
return id;
|
|
8503
|
+
}
|
|
8504
|
+
|
|
8505
|
+
function visitRustSynNode(node, context, propertyPath) {
|
|
8506
|
+
if (!isRustSynAstNode(node) || context.truncated) return undefined;
|
|
8507
|
+
if (context.objectIds.has(node)) return context.objectIds.get(node);
|
|
8508
|
+
if (context.counter >= context.maxNodes) {
|
|
8509
|
+
context.truncated = true;
|
|
8510
|
+
return undefined;
|
|
8511
|
+
}
|
|
8512
|
+
const kind = rustSynKind(node);
|
|
8513
|
+
const payload = rustSynPayload(node);
|
|
8514
|
+
const span = spanFromRustSynNode(payload, context.input);
|
|
8515
|
+
const id = nativeNodeId(context, kind, { start: { line: span?.startLine, column: span?.startColumn } }, propertyPath);
|
|
8516
|
+
context.objectIds.set(node, id);
|
|
8517
|
+
if (!context.rootId) context.rootId = id;
|
|
8518
|
+
const children = [];
|
|
8519
|
+
for (const [field, value] of rustSynChildEntries(node)) {
|
|
8520
|
+
if (Array.isArray(value)) {
|
|
8521
|
+
value.forEach((entry, index) => {
|
|
8522
|
+
const childId = visitRustSynNode(entry, context, `${propertyPath}.${field}[${index}]`);
|
|
8523
|
+
if (childId) children.push(childId);
|
|
8524
|
+
});
|
|
8525
|
+
} else {
|
|
8526
|
+
const childId = visitRustSynNode(value, context, `${propertyPath}.${field}`);
|
|
8527
|
+
if (childId) children.push(childId);
|
|
8528
|
+
}
|
|
8529
|
+
}
|
|
8530
|
+
const declaration = rustSynDeclaration(payload, kind, id, context.input);
|
|
8531
|
+
const nativeNode = {
|
|
8532
|
+
id,
|
|
8533
|
+
kind,
|
|
8534
|
+
languageKind: `${context.input.language}.${kind}`,
|
|
8535
|
+
span,
|
|
8536
|
+
value: declaration?.name ?? rustSynNodeValue(payload),
|
|
8537
|
+
fields: primitiveRustSynFields(payload, kind),
|
|
8538
|
+
children,
|
|
8539
|
+
metadata: {
|
|
8540
|
+
astFormat: context.options.astFormat,
|
|
8541
|
+
propertyPath,
|
|
8542
|
+
spanKind: rustSynSpanKind(payload)
|
|
8543
|
+
}
|
|
8544
|
+
};
|
|
8545
|
+
context.nodes[id] = nativeNode;
|
|
8546
|
+
if (declaration) context.declarations.push({ ...declaration, nativeNode });
|
|
8547
|
+
if (rustSynMacroKind(kind)) {
|
|
8548
|
+
context.losses.push({
|
|
8549
|
+
id: `loss_${idFragment(id)}_rust_macro_expansion`,
|
|
8550
|
+
severity: 'warning',
|
|
8551
|
+
phase: 'parse',
|
|
8552
|
+
sourceFormat: context.input.language,
|
|
8553
|
+
kind: 'macroExpansion',
|
|
8554
|
+
message: 'Rust macro syntax was parsed but macro expansion and generated items require host compiler evidence.',
|
|
8555
|
+
span,
|
|
8556
|
+
nodeId: id,
|
|
8557
|
+
metadata: {
|
|
8558
|
+
parser: context.options.parser,
|
|
8559
|
+
astFormat: context.options.astFormat
|
|
8560
|
+
}
|
|
8561
|
+
});
|
|
8562
|
+
}
|
|
8563
|
+
return id;
|
|
8564
|
+
}
|
|
8565
|
+
|
|
7963
8566
|
function visitTreeSitterNode(node, context, propertyPath) {
|
|
7964
8567
|
if (!node || typeof node !== 'object' || context.truncated) return undefined;
|
|
7965
8568
|
if (context.objectIds.has(node)) return context.objectIds.get(node);
|
|
@@ -8455,6 +9058,14 @@ function nativeTargetProjectionDiagnosticToLoss(diagnostic, index, adapter, inpu
|
|
|
8455
9058
|
};
|
|
8456
9059
|
}
|
|
8457
9060
|
|
|
9061
|
+
function safeNativeImporterAdapterSummary(adapter) {
|
|
9062
|
+
try {
|
|
9063
|
+
return normalizeNativeImporterAdapter(adapter);
|
|
9064
|
+
} catch {
|
|
9065
|
+
return undefined;
|
|
9066
|
+
}
|
|
9067
|
+
}
|
|
9068
|
+
|
|
8458
9069
|
function normalizeNativeImporterAdapter(adapter) {
|
|
8459
9070
|
if (!adapter || typeof adapter !== 'object') {
|
|
8460
9071
|
throw new Error('Native importer adapter must be an object');
|
|
@@ -9089,6 +9700,104 @@ function isSyntaxAstNode(value) {
|
|
|
9089
9700
|
return Boolean(value && typeof value === 'object' && typeof (value.type ?? value.kind) === 'string');
|
|
9090
9701
|
}
|
|
9091
9702
|
|
|
9703
|
+
function pythonAstRoot(value) {
|
|
9704
|
+
if (!value || typeof value !== 'object') return undefined;
|
|
9705
|
+
if (isPythonAstNode(value)) return value;
|
|
9706
|
+
if (isPythonAstNode(value.ast)) return value.ast;
|
|
9707
|
+
if (isPythonAstNode(value.root)) return value.root;
|
|
9708
|
+
if (isPythonAstNode(value.module)) return value.module;
|
|
9709
|
+
return undefined;
|
|
9710
|
+
}
|
|
9711
|
+
|
|
9712
|
+
function isPythonAstNode(value) {
|
|
9713
|
+
return Boolean(value && typeof value === 'object' && typeof pythonAstKind(value) === 'string');
|
|
9714
|
+
}
|
|
9715
|
+
|
|
9716
|
+
function pythonAstKind(node) {
|
|
9717
|
+
return node?._type ?? node?.type ?? node?.kind ?? node?.nodeType;
|
|
9718
|
+
}
|
|
9719
|
+
|
|
9720
|
+
function rustSynAstRoot(value) {
|
|
9721
|
+
if (!value || typeof value !== 'object') return undefined;
|
|
9722
|
+
if (isRustSynAstNode(value)) return value;
|
|
9723
|
+
if (isRustSynAstNode(value.ast)) return value.ast;
|
|
9724
|
+
if (isRustSynAstNode(value.file)) return value.file;
|
|
9725
|
+
if (isRustSynAstNode(value.root)) return value.root;
|
|
9726
|
+
if (isRustSynAstNode(value.module)) return value.module;
|
|
9727
|
+
if (isRustSynAstNode(value.sourceFile)) return value.sourceFile;
|
|
9728
|
+
return undefined;
|
|
9729
|
+
}
|
|
9730
|
+
|
|
9731
|
+
function isRustSynAstNode(value) {
|
|
9732
|
+
return Boolean(value && typeof value === 'object' && typeof rustSynKind(value) === 'string');
|
|
9733
|
+
}
|
|
9734
|
+
|
|
9735
|
+
function rustSynKind(node) {
|
|
9736
|
+
const declared = node?._type ?? node?.type ?? node?.kind ?? node?.nodeType ?? node?.synKind;
|
|
9737
|
+
if (typeof declared === 'string') return normalizeRustSynKind(declared);
|
|
9738
|
+
const wrapper = rustSynWrapperKind(node);
|
|
9739
|
+
if (wrapper) return normalizeRustSynKind(wrapper);
|
|
9740
|
+
if (Array.isArray(node?.items)) return 'File';
|
|
9741
|
+
if (node?.sig && node?.block) return 'ItemFn';
|
|
9742
|
+
if (node?.ident && node?.fields && Array.isArray(node?.variants)) return 'ItemEnum';
|
|
9743
|
+
if (node?.ident && node?.fields) return 'ItemStruct';
|
|
9744
|
+
if (node?.ident && Array.isArray(node?.items)) return 'ItemMod';
|
|
9745
|
+
if (node?.trait_ || node?.self_ty || node?.selfType) return 'ItemImpl';
|
|
9746
|
+
if (node?.path && (node?.tree || node?.trees)) return 'ItemUse';
|
|
9747
|
+
return undefined;
|
|
9748
|
+
}
|
|
9749
|
+
|
|
9750
|
+
function rustSynPayload(node) {
|
|
9751
|
+
if (!node || typeof node !== 'object') return node;
|
|
9752
|
+
const wrapper = rustSynWrapperKind(node);
|
|
9753
|
+
return wrapper ? node[wrapper] : node;
|
|
9754
|
+
}
|
|
9755
|
+
|
|
9756
|
+
function rustSynWrapperKind(node) {
|
|
9757
|
+
if (!node || typeof node !== 'object') return undefined;
|
|
9758
|
+
const keys = Object.keys(node).filter((key) => !ignoredRustSynField(key));
|
|
9759
|
+
if (keys.length !== 1) return undefined;
|
|
9760
|
+
const key = keys[0];
|
|
9761
|
+
const value = node[key];
|
|
9762
|
+
if (!value || typeof value !== 'object') return undefined;
|
|
9763
|
+
if (/^(?:Fn|Struct|Enum|Trait|Impl|Use|Mod|Type|Const|Static|Union|Macro)$/.test(key)) return key;
|
|
9764
|
+
if (/^(?:Item|ImplItem|TraitItem|ForeignItem)/.test(key)) return key;
|
|
9765
|
+
return undefined;
|
|
9766
|
+
}
|
|
9767
|
+
|
|
9768
|
+
function normalizeRustSynKind(kind) {
|
|
9769
|
+
const text = String(kind);
|
|
9770
|
+
const compact = text.replace(/^(?:syn::)?/, '').replace(/^Item::/, 'Item').replace(/^ImplItem::/, 'ImplItem').replace(/^TraitItem::/, 'TraitItem');
|
|
9771
|
+
if (/^fn$/i.test(compact)) return 'ItemFn';
|
|
9772
|
+
if (/^struct$/i.test(compact)) return 'ItemStruct';
|
|
9773
|
+
if (/^enum$/i.test(compact)) return 'ItemEnum';
|
|
9774
|
+
if (/^trait$/i.test(compact)) return 'ItemTrait';
|
|
9775
|
+
if (/^impl$/i.test(compact)) return 'ItemImpl';
|
|
9776
|
+
if (/^use$/i.test(compact)) return 'ItemUse';
|
|
9777
|
+
if (/^mod$/i.test(compact)) return 'ItemMod';
|
|
9778
|
+
if (/^type$/i.test(compact)) return 'ItemType';
|
|
9779
|
+
if (/^const$/i.test(compact)) return 'ItemConst';
|
|
9780
|
+
if (/^static$/i.test(compact)) return 'ItemStatic';
|
|
9781
|
+
if (/^union$/i.test(compact)) return 'ItemUnion';
|
|
9782
|
+
if (/^item_fn$/i.test(compact)) return 'ItemFn';
|
|
9783
|
+
if (/^item_struct$/i.test(compact)) return 'ItemStruct';
|
|
9784
|
+
if (/^item_enum$/i.test(compact)) return 'ItemEnum';
|
|
9785
|
+
if (/^item_trait$/i.test(compact)) return 'ItemTrait';
|
|
9786
|
+
if (/^item_impl$/i.test(compact)) return 'ItemImpl';
|
|
9787
|
+
if (/^item_use$/i.test(compact)) return 'ItemUse';
|
|
9788
|
+
if (/^item_mod$/i.test(compact)) return 'ItemMod';
|
|
9789
|
+
if (/^item_type$/i.test(compact)) return 'ItemType';
|
|
9790
|
+
if (/^item_const$/i.test(compact)) return 'ItemConst';
|
|
9791
|
+
if (/^item_static$/i.test(compact)) return 'ItemStatic';
|
|
9792
|
+
if (/^item_union$/i.test(compact)) return 'ItemUnion';
|
|
9793
|
+
if (/^item_macro$/i.test(compact)) return 'ItemMacro';
|
|
9794
|
+
if (/^macro$/i.test(compact)) return 'Macro';
|
|
9795
|
+
if (/^impl_item_fn$/i.test(compact)) return 'ImplItemFn';
|
|
9796
|
+
if (/^trait_item_fn$/i.test(compact)) return 'TraitItemFn';
|
|
9797
|
+
if (/^foreign_item_fn$/i.test(compact)) return 'ForeignItemFn';
|
|
9798
|
+
return compact;
|
|
9799
|
+
}
|
|
9800
|
+
|
|
9092
9801
|
function ignoredSyntaxField(key) {
|
|
9093
9802
|
return key === 'type'
|
|
9094
9803
|
|| key === 'kind'
|
|
@@ -9105,6 +9814,36 @@ function ignoredSyntaxField(key) {
|
|
|
9105
9814
|
|| key === 'parent';
|
|
9106
9815
|
}
|
|
9107
9816
|
|
|
9817
|
+
function ignoredPythonAstField(key) {
|
|
9818
|
+
return key === '_type'
|
|
9819
|
+
|| key === 'type'
|
|
9820
|
+
|| key === 'kind'
|
|
9821
|
+
|| key === 'nodeType'
|
|
9822
|
+
|| key === '_fields'
|
|
9823
|
+
|| key === 'lineno'
|
|
9824
|
+
|| key === 'col_offset'
|
|
9825
|
+
|| key === 'end_lineno'
|
|
9826
|
+
|| key === 'end_col_offset'
|
|
9827
|
+
|| key === 'line'
|
|
9828
|
+
|| key === 'colOffset'
|
|
9829
|
+
|| key === 'endLine'
|
|
9830
|
+
|| key === 'endColOffset'
|
|
9831
|
+
|| key === 'ctx'
|
|
9832
|
+
|| key === 'parent';
|
|
9833
|
+
}
|
|
9834
|
+
|
|
9835
|
+
function ignoredRustSynField(key) {
|
|
9836
|
+
return key === '_type'
|
|
9837
|
+
|| key === 'type'
|
|
9838
|
+
|| key === 'kind'
|
|
9839
|
+
|| key === 'nodeType'
|
|
9840
|
+
|| key === 'synKind'
|
|
9841
|
+
|| key === 'span'
|
|
9842
|
+
|| key === 'tokens'
|
|
9843
|
+
|| key === 'tokenStream'
|
|
9844
|
+
|| key === 'parent';
|
|
9845
|
+
}
|
|
9846
|
+
|
|
9108
9847
|
function primitiveSyntaxFields(node) {
|
|
9109
9848
|
const fields = {};
|
|
9110
9849
|
for (const key of ['name', 'operator', 'sourceType', 'async', 'generator', 'computed', 'static', 'exportKind', 'importKind', 'optional']) {
|
|
@@ -9118,11 +9857,52 @@ function primitiveSyntaxFields(node) {
|
|
|
9118
9857
|
return fields;
|
|
9119
9858
|
}
|
|
9120
9859
|
|
|
9860
|
+
function primitivePythonAstFields(node, kind) {
|
|
9861
|
+
const fields = { kind };
|
|
9862
|
+
for (const key of ['name', 'id', 'arg', 'module', 'level', 'attr', 'asname', 'type_comment']) {
|
|
9863
|
+
if (typeof node[key] === 'string' || typeof node[key] === 'number' || typeof node[key] === 'boolean' || node[key] === null) {
|
|
9864
|
+
fields[key] = node[key];
|
|
9865
|
+
}
|
|
9866
|
+
}
|
|
9867
|
+
if (Array.isArray(node.names)) {
|
|
9868
|
+
fields.names = node.names
|
|
9869
|
+
.map((entry) => pythonAliasName(entry))
|
|
9870
|
+
.filter(Boolean)
|
|
9871
|
+
.join(',');
|
|
9872
|
+
}
|
|
9873
|
+
const literal = pythonAstLiteralValue(node);
|
|
9874
|
+
if (literal !== undefined) fields.literal = literal;
|
|
9875
|
+
return fields;
|
|
9876
|
+
}
|
|
9877
|
+
|
|
9878
|
+
function primitiveRustSynFields(node, kind) {
|
|
9879
|
+
const fields = { kind };
|
|
9880
|
+
const ident = rustSynIdentName(node.ident ?? node.name ?? node.sig?.ident);
|
|
9881
|
+
if (ident) fields.ident = ident;
|
|
9882
|
+
const path = rustSynPathName(node.path ?? node.trait_ ?? node.self_ty ?? node.selfType ?? node.ty);
|
|
9883
|
+
if (path) fields.path = path;
|
|
9884
|
+
const visibility = rustSynVisibility(node.vis ?? node.visibility);
|
|
9885
|
+
if (visibility) fields.visibility = visibility;
|
|
9886
|
+
for (const key of ['mutability', 'defaultness', 'constness', 'asyncness', 'unsafety', 'abi']) {
|
|
9887
|
+
const value = node[key];
|
|
9888
|
+
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean' || value === null) fields[key] = value;
|
|
9889
|
+
}
|
|
9890
|
+
if (Array.isArray(node.attrs) && node.attrs.length) fields.attributeCount = node.attrs.length;
|
|
9891
|
+
return fields;
|
|
9892
|
+
}
|
|
9893
|
+
|
|
9121
9894
|
function literalSyntaxValue(node) {
|
|
9122
9895
|
if (node.value === null || typeof node.value === 'string' || typeof node.value === 'number' || typeof node.value === 'boolean') return node.value;
|
|
9123
9896
|
return undefined;
|
|
9124
9897
|
}
|
|
9125
9898
|
|
|
9899
|
+
function pythonAstLiteralValue(node) {
|
|
9900
|
+
if (node.value === null || typeof node.value === 'string' || typeof node.value === 'number' || typeof node.value === 'boolean') return node.value;
|
|
9901
|
+
if (typeof node.s === 'string' || typeof node.s === 'number') return node.s;
|
|
9902
|
+
if (typeof node.n === 'number') return node.n;
|
|
9903
|
+
return undefined;
|
|
9904
|
+
}
|
|
9905
|
+
|
|
9126
9906
|
function spanFromLoc(loc, input) {
|
|
9127
9907
|
if (!loc?.start) return undefined;
|
|
9128
9908
|
return {
|
|
@@ -9135,6 +9915,52 @@ function spanFromLoc(loc, input) {
|
|
|
9135
9915
|
};
|
|
9136
9916
|
}
|
|
9137
9917
|
|
|
9918
|
+
function spanFromPythonAstNode(node, input) {
|
|
9919
|
+
const line = node.lineno ?? node.line;
|
|
9920
|
+
if (typeof line !== 'number') return undefined;
|
|
9921
|
+
const col = node.col_offset ?? node.colOffset;
|
|
9922
|
+
const endLine = node.end_lineno ?? node.endLine;
|
|
9923
|
+
const endCol = node.end_col_offset ?? node.endColOffset;
|
|
9924
|
+
return {
|
|
9925
|
+
sourceId: input.sourceHash,
|
|
9926
|
+
path: input.sourcePath,
|
|
9927
|
+
startLine: line,
|
|
9928
|
+
startColumn: typeof col === 'number' ? col + 1 : undefined,
|
|
9929
|
+
endLine: typeof endLine === 'number' ? endLine : undefined,
|
|
9930
|
+
endColumn: typeof endCol === 'number' ? endCol + 1 : undefined
|
|
9931
|
+
};
|
|
9932
|
+
}
|
|
9933
|
+
|
|
9934
|
+
function spanFromRustSynNode(node, input) {
|
|
9935
|
+
const span = node.span ?? node.ident?.span ?? node.sig?.ident?.span ?? node.name?.span;
|
|
9936
|
+
if (!span || typeof span !== 'object') return undefined;
|
|
9937
|
+
const start = span.start ?? span.lo ?? span.begin;
|
|
9938
|
+
const end = span.end ?? span.hi;
|
|
9939
|
+
const startLine = span.startLine ?? span.line ?? start?.line;
|
|
9940
|
+
const startColumn = span.startColumn ?? span.column ?? start?.column;
|
|
9941
|
+
const endLine = span.endLine ?? end?.line;
|
|
9942
|
+
const endColumn = span.endColumn ?? end?.column;
|
|
9943
|
+
if (typeof startLine !== 'number') return undefined;
|
|
9944
|
+
return {
|
|
9945
|
+
sourceId: input.sourceHash,
|
|
9946
|
+
path: input.sourcePath,
|
|
9947
|
+
startLine,
|
|
9948
|
+
startColumn: typeof startColumn === 'number' ? rustSynColumnToOneBased(startColumn, span) : undefined,
|
|
9949
|
+
endLine: typeof endLine === 'number' ? endLine : undefined,
|
|
9950
|
+
endColumn: typeof endColumn === 'number' ? rustSynColumnToOneBased(endColumn, span) : undefined
|
|
9951
|
+
};
|
|
9952
|
+
}
|
|
9953
|
+
|
|
9954
|
+
function rustSynColumnToOneBased(column, span) {
|
|
9955
|
+
return span.columnBase === 1 || span.columnsOneBased ? column : column + 1;
|
|
9956
|
+
}
|
|
9957
|
+
|
|
9958
|
+
function rustSynSpanKind(node) {
|
|
9959
|
+
const span = node.span ?? node.ident?.span ?? node.sig?.ident?.span ?? node.name?.span;
|
|
9960
|
+
if (!span || typeof span !== 'object') return undefined;
|
|
9961
|
+
return span.kind ?? span.source ?? 'host-span';
|
|
9962
|
+
}
|
|
9963
|
+
|
|
9138
9964
|
function syntaxDeclaration(node, nativeNodeId, input) {
|
|
9139
9965
|
const kind = String(node.type ?? node.kind ?? '');
|
|
9140
9966
|
if (kind === 'ImportDeclaration') {
|
|
@@ -9153,6 +9979,64 @@ function syntaxDeclaration(node, nativeNodeId, input) {
|
|
|
9153
9979
|
return undefined;
|
|
9154
9980
|
}
|
|
9155
9981
|
|
|
9982
|
+
function pythonAstDeclaration(node, kind, nativeNodeId, input) {
|
|
9983
|
+
if (kind === 'Import') {
|
|
9984
|
+
const name = (node.names ?? []).map((entry) => pythonAliasName(entry)).find(Boolean);
|
|
9985
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'module', 'import');
|
|
9986
|
+
}
|
|
9987
|
+
if (kind === 'ImportFrom') {
|
|
9988
|
+
const name = node.module ?? (node.names ?? []).map((entry) => pythonAliasName(entry)).find(Boolean);
|
|
9989
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'module', 'import');
|
|
9990
|
+
}
|
|
9991
|
+
if (kind === 'FunctionDef' || kind === 'AsyncFunctionDef') return declarationRecord(input, nativeNodeId, node.name, 'function', 'definition');
|
|
9992
|
+
if (kind === 'ClassDef') return declarationRecord(input, nativeNodeId, node.name, 'class', 'definition');
|
|
9993
|
+
if (kind === 'AnnAssign' || kind === 'Assign') {
|
|
9994
|
+
const name = pythonAssignmentName(node);
|
|
9995
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'variable', 'definition');
|
|
9996
|
+
}
|
|
9997
|
+
return undefined;
|
|
9998
|
+
}
|
|
9999
|
+
|
|
10000
|
+
function rustSynDeclaration(node, kind, nativeNodeId, input) {
|
|
10001
|
+
if (kind === 'ItemUse' || kind === 'UseTree' || kind === 'UsePath' || kind === 'UseName') {
|
|
10002
|
+
const name = rustSynUseName(node);
|
|
10003
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'module', 'import');
|
|
10004
|
+
}
|
|
10005
|
+
if (kind === 'ItemFn' || kind === 'ForeignItemFn') {
|
|
10006
|
+
const name = rustSynIdentName(node.sig?.ident ?? node.ident ?? node.name);
|
|
10007
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'function', 'definition');
|
|
10008
|
+
}
|
|
10009
|
+
if (kind === 'ImplItemFn' || kind === 'TraitItemFn') {
|
|
10010
|
+
const name = rustSynIdentName(node.sig?.ident ?? node.ident ?? node.name);
|
|
10011
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'method', 'definition');
|
|
10012
|
+
}
|
|
10013
|
+
if (kind === 'ItemStruct' || kind === 'ItemUnion') {
|
|
10014
|
+
const name = rustSynIdentName(node.ident ?? node.name);
|
|
10015
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'class', 'definition');
|
|
10016
|
+
}
|
|
10017
|
+
if (kind === 'ItemEnum' || kind === 'ItemTrait' || kind === 'ItemType') {
|
|
10018
|
+
const name = rustSynIdentName(node.ident ?? node.name);
|
|
10019
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'type', 'definition');
|
|
10020
|
+
}
|
|
10021
|
+
if (kind === 'ItemMod') {
|
|
10022
|
+
const name = rustSynIdentName(node.ident ?? node.name);
|
|
10023
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'module', 'definition');
|
|
10024
|
+
}
|
|
10025
|
+
if (kind === 'ItemConst' || kind === 'ItemStatic') {
|
|
10026
|
+
const name = rustSynIdentName(node.ident ?? node.name);
|
|
10027
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'variable', 'definition');
|
|
10028
|
+
}
|
|
10029
|
+
if (kind === 'ItemImpl') {
|
|
10030
|
+
const name = rustSynImplName(node);
|
|
10031
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'type', 'definition');
|
|
10032
|
+
}
|
|
10033
|
+
if (rustSynMacroKind(kind)) {
|
|
10034
|
+
const name = rustSynIdentName(node.ident ?? node.mac?.path ?? node.path);
|
|
10035
|
+
if (name) return declarationRecord(input, nativeNodeId, name, 'macro', 'definition');
|
|
10036
|
+
}
|
|
10037
|
+
return undefined;
|
|
10038
|
+
}
|
|
10039
|
+
|
|
9156
10040
|
function typeScriptDeclaration(node, kind, nativeNodeId, input) {
|
|
9157
10041
|
if (kind === 'ImportDeclaration' || kind === 'ImportEqualsDeclaration') {
|
|
9158
10042
|
const name = stringFromTsExpression(node.moduleSpecifier) ?? stringFromTsExpression(node.externalModuleReference?.expression);
|
|
@@ -9196,6 +10080,155 @@ function namedDeclaration(input, nativeNodeId, nameNode, symbolKind) {
|
|
|
9196
10080
|
return name ? declarationRecord(input, nativeNodeId, name, symbolKind, 'definition') : undefined;
|
|
9197
10081
|
}
|
|
9198
10082
|
|
|
10083
|
+
function pythonAstChildEntries(node) {
|
|
10084
|
+
const fieldNames = Array.isArray(node._fields)
|
|
10085
|
+
? node._fields
|
|
10086
|
+
: Object.keys(node).filter((key) => !ignoredPythonAstField(key));
|
|
10087
|
+
return fieldNames
|
|
10088
|
+
.map((field) => [field, node[field]])
|
|
10089
|
+
.filter(([, value]) => Array.isArray(value)
|
|
10090
|
+
? value.some(isPythonAstNode)
|
|
10091
|
+
: isPythonAstNode(value));
|
|
10092
|
+
}
|
|
10093
|
+
|
|
10094
|
+
function rustSynChildEntries(node) {
|
|
10095
|
+
const payload = rustSynPayload(node);
|
|
10096
|
+
const fieldNames = Object.keys(payload).filter((key) => !ignoredRustSynField(key));
|
|
10097
|
+
return fieldNames
|
|
10098
|
+
.map((field) => [field, payload[field]])
|
|
10099
|
+
.filter(([, value]) => Array.isArray(value)
|
|
10100
|
+
? value.some(isRustSynAstNode)
|
|
10101
|
+
: isRustSynAstNode(value));
|
|
10102
|
+
}
|
|
10103
|
+
|
|
10104
|
+
function pythonAstNodeValue(node) {
|
|
10105
|
+
return node.name ?? node.id ?? node.arg ?? node.module ?? pythonAstLiteralValue(node);
|
|
10106
|
+
}
|
|
10107
|
+
|
|
10108
|
+
function rustSynNodeValue(node) {
|
|
10109
|
+
return rustSynIdentName(node.ident ?? node.name ?? node.sig?.ident)
|
|
10110
|
+
?? rustSynPathName(node.path ?? node.trait_ ?? node.self_ty ?? node.selfType ?? node.ty)
|
|
10111
|
+
?? rustSynLiteralValue(node);
|
|
10112
|
+
}
|
|
10113
|
+
|
|
10114
|
+
function pythonAliasName(alias) {
|
|
10115
|
+
if (!alias) return undefined;
|
|
10116
|
+
if (typeof alias === 'string') return alias;
|
|
10117
|
+
return alias.name ?? alias.asname ?? alias.id;
|
|
10118
|
+
}
|
|
10119
|
+
|
|
10120
|
+
function pythonAssignmentName(node) {
|
|
10121
|
+
if (node.target) return pythonTargetName(node.target);
|
|
10122
|
+
for (const target of node.targets ?? []) {
|
|
10123
|
+
const name = pythonTargetName(target);
|
|
10124
|
+
if (name) return name;
|
|
10125
|
+
}
|
|
10126
|
+
return undefined;
|
|
10127
|
+
}
|
|
10128
|
+
|
|
10129
|
+
function pythonTargetName(target) {
|
|
10130
|
+
if (!target) return undefined;
|
|
10131
|
+
if (typeof target === 'string') return target;
|
|
10132
|
+
if (typeof target.id === 'string') return target.id;
|
|
10133
|
+
if (typeof target.name === 'string') return target.name;
|
|
10134
|
+
if (typeof target.arg === 'string') return target.arg;
|
|
10135
|
+
if (target.attr && target.value) {
|
|
10136
|
+
const base = pythonTargetName(target.value);
|
|
10137
|
+
return base ? `${base}.${target.attr}` : target.attr;
|
|
10138
|
+
}
|
|
10139
|
+
return undefined;
|
|
10140
|
+
}
|
|
10141
|
+
|
|
10142
|
+
function rustSynIdentName(value) {
|
|
10143
|
+
if (!value) return undefined;
|
|
10144
|
+
if (typeof value === 'string') return value;
|
|
10145
|
+
if (typeof value.ident === 'string') return value.ident;
|
|
10146
|
+
if (typeof value.name === 'string') return value.name;
|
|
10147
|
+
if (typeof value.text === 'string') return value.text;
|
|
10148
|
+
if (typeof value.sym === 'string') return value.sym;
|
|
10149
|
+
if (typeof value.value === 'string') return value.value;
|
|
10150
|
+
if (typeof value.path === 'string') return value.path;
|
|
10151
|
+
return rustSynPathName(value.path ?? value);
|
|
10152
|
+
}
|
|
10153
|
+
|
|
10154
|
+
function rustSynPathName(value) {
|
|
10155
|
+
if (!value) return undefined;
|
|
10156
|
+
if (typeof value === 'string') return value;
|
|
10157
|
+
if (typeof value.ident === 'string') return value.ident;
|
|
10158
|
+
if (typeof value.name === 'string') return value.name;
|
|
10159
|
+
if (typeof value.path === 'string') return value.path;
|
|
10160
|
+
if (value.path && typeof value.path === 'object') return rustSynPathName(value.path);
|
|
10161
|
+
if (Array.isArray(value.segments)) {
|
|
10162
|
+
const names = value.segments
|
|
10163
|
+
.map((segment) => rustSynIdentName(segment.ident ?? segment))
|
|
10164
|
+
.filter(Boolean);
|
|
10165
|
+
return names.length ? names.join('::') : undefined;
|
|
10166
|
+
}
|
|
10167
|
+
if (Array.isArray(value.qself)) return value.qself.map(rustSynPathName).filter(Boolean).join('::');
|
|
10168
|
+
if (value.leading_colon && value.segments) {
|
|
10169
|
+
const name = rustSynPathName({ segments: value.segments });
|
|
10170
|
+
return name ? `::${name}` : undefined;
|
|
10171
|
+
}
|
|
10172
|
+
return undefined;
|
|
10173
|
+
}
|
|
10174
|
+
|
|
10175
|
+
function rustSynUseName(node) {
|
|
10176
|
+
if (!node) return undefined;
|
|
10177
|
+
if (node.prefix && node.tree) {
|
|
10178
|
+
const prefix = rustSynPathName(node.prefix);
|
|
10179
|
+
const child = rustSynUseName(node.tree);
|
|
10180
|
+
return [prefix, child].filter(Boolean).join('::') || undefined;
|
|
10181
|
+
}
|
|
10182
|
+
if (node.ident && node.tree) {
|
|
10183
|
+
const prefix = rustSynIdentName(node.ident);
|
|
10184
|
+
const child = rustSynUseName(node.tree);
|
|
10185
|
+
return [prefix, child].filter(Boolean).join('::') || undefined;
|
|
10186
|
+
}
|
|
10187
|
+
if (node.path && node.tree) {
|
|
10188
|
+
const prefix = rustSynPathName(node.path);
|
|
10189
|
+
const child = rustSynUseName(node.tree);
|
|
10190
|
+
return [prefix, child].filter(Boolean).join('::') || undefined;
|
|
10191
|
+
}
|
|
10192
|
+
if (Array.isArray(node.trees)) return node.trees.map(rustSynUseName).find(Boolean);
|
|
10193
|
+
if (node.tree) return rustSynUseName(node.tree);
|
|
10194
|
+
if (node.path) return rustSynPathName(node.path);
|
|
10195
|
+
if (node.name) return rustSynIdentName(node.name);
|
|
10196
|
+
if (node.ident) return rustSynIdentName(node.ident);
|
|
10197
|
+
if (node.rename) return rustSynIdentName(node.rename);
|
|
10198
|
+
return undefined;
|
|
10199
|
+
}
|
|
10200
|
+
|
|
10201
|
+
function rustSynImplName(node) {
|
|
10202
|
+
const selfType = rustSynPathName(node.self_ty ?? node.selfType ?? node.ty);
|
|
10203
|
+
const traitPath = Array.isArray(node.trait_)
|
|
10204
|
+
? rustSynPathName(node.trait_[1] ?? node.trait_[0])
|
|
10205
|
+
: rustSynPathName(node.trait_);
|
|
10206
|
+
if (selfType && traitPath) return `${selfType}.${traitPath}.impl`;
|
|
10207
|
+
if (selfType) return `${selfType}.impl`;
|
|
10208
|
+
if (traitPath) return `${traitPath}.impl`;
|
|
10209
|
+
return undefined;
|
|
10210
|
+
}
|
|
10211
|
+
|
|
10212
|
+
function rustSynVisibility(value) {
|
|
10213
|
+
if (!value) return undefined;
|
|
10214
|
+
if (typeof value === 'string') return value;
|
|
10215
|
+
if (typeof value.kind === 'string') return value.kind;
|
|
10216
|
+
if (typeof value.type === 'string') return value.type;
|
|
10217
|
+
if (value.pub || value.Public) return 'pub';
|
|
10218
|
+
if (value.restricted || value.Restricted) return 'restricted';
|
|
10219
|
+
return undefined;
|
|
10220
|
+
}
|
|
10221
|
+
|
|
10222
|
+
function rustSynLiteralValue(node) {
|
|
10223
|
+
const value = node.value ?? node.lit?.value ?? node.lit;
|
|
10224
|
+
if (value === null || typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') return value;
|
|
10225
|
+
return undefined;
|
|
10226
|
+
}
|
|
10227
|
+
|
|
10228
|
+
function rustSynMacroKind(kind) {
|
|
10229
|
+
return /Macro|MacroRules|MacroCall/.test(String(kind));
|
|
10230
|
+
}
|
|
10231
|
+
|
|
9199
10232
|
function declarationRecord(input, nativeNodeId, name, symbolKind, role = 'definition') {
|
|
9200
10233
|
return {
|
|
9201
10234
|
name: String(name),
|