@shapeshift-labs/frontier-lang-compiler 0.2.11 → 0.2.13
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 +5 -0
- package/bench/smoke.mjs +4 -0
- package/dist/index.d.ts +299 -1
- package/dist/index.js +932 -39
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -127,6 +127,17 @@ export const NativeImportReadinessBySeverity = Object.freeze({
|
|
|
127
127
|
error: 'blocked'
|
|
128
128
|
});
|
|
129
129
|
|
|
130
|
+
export const NativeImportRegionTaxonomyKinds = Object.freeze([
|
|
131
|
+
'symbol',
|
|
132
|
+
'declaration',
|
|
133
|
+
'import',
|
|
134
|
+
'body',
|
|
135
|
+
'call',
|
|
136
|
+
'type',
|
|
137
|
+
'effect',
|
|
138
|
+
'generatedOutput'
|
|
139
|
+
]);
|
|
140
|
+
|
|
130
141
|
export const NativeImportLanguageProfiles = Object.freeze([
|
|
131
142
|
nativeImportLanguageProfile('javascript', {
|
|
132
143
|
aliases: ['js', 'mjs', 'cjs', 'jsx'],
|
|
@@ -482,6 +493,7 @@ export function createNativeImportCoverageMatrix(input = {}) {
|
|
|
482
493
|
for (const [kind, count] of Object.entries(entry.imports.lossKinds)) {
|
|
483
494
|
totals.lossKinds[kind] = (totals.lossKinds[kind] ?? 0) + count;
|
|
484
495
|
}
|
|
496
|
+
totals.adapterCoverage = mergeNativeImporterAdapterCoverageAggregates(totals.adapterCoverage, entry.adapterCoverage);
|
|
485
497
|
return totals;
|
|
486
498
|
}, {
|
|
487
499
|
languages: 0,
|
|
@@ -493,7 +505,8 @@ export function createNativeImportCoverageMatrix(input = {}) {
|
|
|
493
505
|
sourceMapMappings: 0,
|
|
494
506
|
losses: 0,
|
|
495
507
|
byReadiness: {},
|
|
496
|
-
lossKinds: {}
|
|
508
|
+
lossKinds: {},
|
|
509
|
+
adapterCoverage: emptyNativeImporterAdapterCoverageAggregate()
|
|
497
510
|
});
|
|
498
511
|
return {
|
|
499
512
|
kind: 'frontier.lang.nativeImportCoverageMatrix',
|
|
@@ -583,6 +596,7 @@ export function createSemanticImportSidecar(importResult, options = {}) {
|
|
|
583
596
|
const evidence = uniqueRecordsById(imports.flatMap((imported) => imported?.evidence ?? []));
|
|
584
597
|
const mergeCandidates = imports.flatMap((imported) => imported?.mergeCandidates ?? []);
|
|
585
598
|
const lossSummary = summarizeNativeImportLosses(losses, { evidence });
|
|
599
|
+
const regionTaxonomy = summarizeSemanticImportRegionTaxonomy(ownershipRegions);
|
|
586
600
|
const readiness = mergeCandidates.reduce(
|
|
587
601
|
(current, candidate) => maxSemanticMergeReadiness(current, candidate.readiness),
|
|
588
602
|
lossSummary.semanticMergeReadiness
|
|
@@ -619,6 +633,7 @@ export function createSemanticImportSidecar(importResult, options = {}) {
|
|
|
619
633
|
blockingLossIds: lossSummary.blockingLossIds,
|
|
620
634
|
reviewLossIds: lossSummary.reviewLossIds
|
|
621
635
|
},
|
|
636
|
+
regionTaxonomy,
|
|
622
637
|
evidence: {
|
|
623
638
|
total: evidence.length,
|
|
624
639
|
failed: evidence.filter((record) => record.status === 'failed').map((record) => record.id),
|
|
@@ -628,6 +643,7 @@ export function createSemanticImportSidecar(importResult, options = {}) {
|
|
|
628
643
|
imports: imports.length,
|
|
629
644
|
symbols: symbols.length,
|
|
630
645
|
ownershipRegions: ownershipRegions.length,
|
|
646
|
+
regionKinds: regionTaxonomy.presentKinds.length,
|
|
631
647
|
sourceMapMappings: sourceMapMappings.length,
|
|
632
648
|
readiness,
|
|
633
649
|
emptySemanticIndex: symbols.length === 0
|
|
@@ -639,6 +655,83 @@ export function createSemanticImportSidecar(importResult, options = {}) {
|
|
|
639
655
|
};
|
|
640
656
|
}
|
|
641
657
|
|
|
658
|
+
export function createNativeImportResultContract(importResult, options = {}) {
|
|
659
|
+
if (!importResult || typeof importResult !== 'object') {
|
|
660
|
+
throw new Error('createNativeImportResultContract requires a native import result');
|
|
661
|
+
}
|
|
662
|
+
const imports = nativeImportEntries(importResult);
|
|
663
|
+
const evidence = uniqueByEvidenceId([
|
|
664
|
+
...(importResult.evidence ?? []),
|
|
665
|
+
...imports.flatMap((imported) => imported?.evidence ?? [])
|
|
666
|
+
]);
|
|
667
|
+
const losses = uniqueByLossId([
|
|
668
|
+
...(importResult.losses ?? []),
|
|
669
|
+
...imports.flatMap((imported) => imported?.losses ?? imported?.nativeAst?.losses ?? [])
|
|
670
|
+
]);
|
|
671
|
+
const sourceMaps = collectImportSourceMaps(importResult, imports);
|
|
672
|
+
const regionSummary = summarizeImportRegions(importResult, imports, options);
|
|
673
|
+
const sourceMapSummary = summarizeImportSourceMaps(sourceMaps);
|
|
674
|
+
const sourcePreservation = summarizeImportSourcePreservation(importResult, imports);
|
|
675
|
+
const adapterCoverage = summarizeImportAdapterCoverage(importResult, imports);
|
|
676
|
+
const primary = imports[0] ?? importResult;
|
|
677
|
+
const nativeSource = importResult.nativeSource ?? importResult.nativeSources?.[0] ?? primary?.nativeSource;
|
|
678
|
+
const nativeAst = importResult.nativeAst ?? nativeSource?.ast ?? primary?.nativeAst ?? primary?.nativeSource?.ast;
|
|
679
|
+
const semanticIndex = importResult.semanticIndex ?? importResult.universalAst?.semanticIndex ?? primary?.semanticIndex ?? primary?.universalAst?.semanticIndex;
|
|
680
|
+
const lossSummary = options.lossSummary ?? importResult.metadata?.nativeImportLossSummary ?? summarizeNativeImportLosses(losses, {
|
|
681
|
+
evidence,
|
|
682
|
+
parser: nativeAst?.parser,
|
|
683
|
+
scanKind: importResult.metadata?.scanKind,
|
|
684
|
+
semanticStatus: importResult.metadata?.semanticStatus ?? importResult.universalAst?.metadata?.semanticStatus
|
|
685
|
+
});
|
|
686
|
+
const mergeCandidates = [
|
|
687
|
+
...(importResult.mergeCandidates ?? []),
|
|
688
|
+
...imports.flatMap((imported) => imported?.mergeCandidates ?? [])
|
|
689
|
+
];
|
|
690
|
+
const readiness = summarizeImportContractReadiness(importResult, mergeCandidates, lossSummary);
|
|
691
|
+
const defaultSidecarId = defaultSemanticImportSidecarId(importResult, imports);
|
|
692
|
+
return {
|
|
693
|
+
kind: 'frontier.lang.nativeImportResultContract',
|
|
694
|
+
version: 1,
|
|
695
|
+
importResultId: importResult.id,
|
|
696
|
+
language: importResult.language ?? (imports.length === 1 ? imports[0]?.language : 'mixed'),
|
|
697
|
+
sourcePath: importResult.sourcePath ?? primary?.sourcePath ?? nativeSource?.sourcePath ?? nativeAst?.sourcePath,
|
|
698
|
+
sourceHash: nativeSource?.sourceHash ?? nativeAst?.sourceHash,
|
|
699
|
+
sourceCount: imports.length,
|
|
700
|
+
sources: imports.map((imported, index) => compactImportContractSource(imported, index)),
|
|
701
|
+
ids: {
|
|
702
|
+
nativeSourceId: nativeSource?.id,
|
|
703
|
+
nativeAstId: nativeAst?.id,
|
|
704
|
+
semanticIndexId: semanticIndex?.id,
|
|
705
|
+
universalAstId: importResult.universalAst?.id ?? primary?.universalAst?.id,
|
|
706
|
+
patchId: importResult.patch?.id,
|
|
707
|
+
sourceMapIds: sourceMapSummary.ids,
|
|
708
|
+
semanticSidecarIds: uniqueStrings([
|
|
709
|
+
...normalizeStringList(options.semanticSidecarIds ?? options.sidecarIds ?? options.sidecarId),
|
|
710
|
+
defaultSidecarId
|
|
711
|
+
])
|
|
712
|
+
},
|
|
713
|
+
sourcePreservation,
|
|
714
|
+
adapterCoverage,
|
|
715
|
+
lossSummary,
|
|
716
|
+
regions: regionSummary,
|
|
717
|
+
sourceMaps: sourceMapSummary,
|
|
718
|
+
readiness,
|
|
719
|
+
evidence: {
|
|
720
|
+
total: evidence.length,
|
|
721
|
+
failed: evidence.filter((record) => record?.status === 'failed').map((record) => record.id).filter(Boolean),
|
|
722
|
+
ids: evidence.map((record) => record.id).filter(Boolean)
|
|
723
|
+
},
|
|
724
|
+
metadata: {
|
|
725
|
+
parser: nativeAst?.parser,
|
|
726
|
+
semanticStatus: importResult.metadata?.semanticStatus ?? importResult.universalAst?.metadata?.semanticStatus,
|
|
727
|
+
projectRoot: importResult.projectRoot,
|
|
728
|
+
defaultSemanticSidecarId: defaultSidecarId,
|
|
729
|
+
note: 'Contract summarizes import-result evidence for merge admission; it does not upgrade lightweight scans into exact semantic imports.',
|
|
730
|
+
...options.metadata
|
|
731
|
+
}
|
|
732
|
+
};
|
|
733
|
+
}
|
|
734
|
+
|
|
642
735
|
export function createEstreeNativeImporterAdapter(options = {}) {
|
|
643
736
|
return createJavaScriptSyntaxImporterAdapter({
|
|
644
737
|
id: 'frontier.estree-native-importer',
|
|
@@ -1311,7 +1404,8 @@ function createLightweightNativeImport(input) {
|
|
|
1311
1404
|
metadata: {
|
|
1312
1405
|
...declaration.metadata,
|
|
1313
1406
|
ownershipRegionId: ownershipRegion.id,
|
|
1314
|
-
ownershipRegionKey: ownershipRegion.key
|
|
1407
|
+
ownershipRegionKey: ownershipRegion.key,
|
|
1408
|
+
ownershipRegionKind: ownershipRegion.regionKind
|
|
1315
1409
|
}
|
|
1316
1410
|
};
|
|
1317
1411
|
if (declaration.symbolId) {
|
|
@@ -1327,7 +1421,8 @@ function createLightweightNativeImport(input) {
|
|
|
1327
1421
|
definitionSpan: declaration.span,
|
|
1328
1422
|
metadata: {
|
|
1329
1423
|
ownershipRegionId: ownershipRegion.id,
|
|
1330
|
-
ownershipRegionKey: ownershipRegion.key
|
|
1424
|
+
ownershipRegionKey: ownershipRegion.key,
|
|
1425
|
+
ownershipRegionKind: ownershipRegion.regionKind
|
|
1331
1426
|
}
|
|
1332
1427
|
});
|
|
1333
1428
|
occurrences.push({
|
|
@@ -1354,6 +1449,15 @@ function createLightweightNativeImport(input) {
|
|
|
1354
1449
|
predicate: 'semanticOwnershipRegion',
|
|
1355
1450
|
subjectId: declaration.symbolId,
|
|
1356
1451
|
value: ownershipRegion
|
|
1452
|
+
}, {
|
|
1453
|
+
id: `fact_${idFragment(declaration.nodeId)}_ownership_region_taxonomy`,
|
|
1454
|
+
predicate: 'semanticOwnershipRegionTaxonomy',
|
|
1455
|
+
subjectId: declaration.symbolId,
|
|
1456
|
+
value: {
|
|
1457
|
+
regionKind: ownershipRegion.regionKind,
|
|
1458
|
+
granularity: ownershipRegion.granularity,
|
|
1459
|
+
key: ownershipRegion.key
|
|
1460
|
+
}
|
|
1357
1461
|
});
|
|
1358
1462
|
mappings.push({
|
|
1359
1463
|
id: `map_${idFragment(declaration.nodeId)}`,
|
|
@@ -1364,6 +1468,8 @@ function createLightweightNativeImport(input) {
|
|
|
1364
1468
|
evidenceIds: [evidenceId],
|
|
1365
1469
|
lossIds: declaration.loss ? [declaration.loss.id] : [],
|
|
1366
1470
|
ownershipRegionId: ownershipRegion.id,
|
|
1471
|
+
ownershipRegionKey: ownershipRegion.key,
|
|
1472
|
+
ownershipRegionKind: ownershipRegion.regionKind,
|
|
1367
1473
|
precision: 'declaration'
|
|
1368
1474
|
});
|
|
1369
1475
|
}
|
|
@@ -2974,6 +3080,9 @@ function inferSourceMapMappings(input) {
|
|
|
2974
3080
|
sourceSpan: occurrence.span ?? nativeNode?.span,
|
|
2975
3081
|
evidenceIds,
|
|
2976
3082
|
lossIds: lossIdsForNativeNode(input.losses ?? nativeAst?.losses ?? [], occurrence.nativeAstNodeId),
|
|
3083
|
+
ownershipRegionId: symbol?.metadata?.ownershipRegionId,
|
|
3084
|
+
ownershipRegionKey: symbol?.metadata?.ownershipRegionKey,
|
|
3085
|
+
ownershipRegionKind: symbol?.metadata?.ownershipRegionKind,
|
|
2977
3086
|
precision: occurrence.span || nativeNode?.span ? 'declaration' : 'unknown'
|
|
2978
3087
|
};
|
|
2979
3088
|
});
|
|
@@ -3043,6 +3152,9 @@ function normalizeSourceMapMappings(mappings, context) {
|
|
|
3043
3152
|
target,
|
|
3044
3153
|
evidenceIds: normalizeReferenceIds(mapping.evidenceIds, evidenceIds),
|
|
3045
3154
|
lossIds: normalizeReferenceIds(mapping.lossIds, lossIdsForNativeNode(context.losses ?? nativeAst?.losses ?? [], nativeAstNodeId)),
|
|
3155
|
+
ownershipRegionId: mapping.ownershipRegionId ?? symbol?.metadata?.ownershipRegionId,
|
|
3156
|
+
ownershipRegionKey: mapping.ownershipRegionKey ?? symbol?.metadata?.ownershipRegionKey,
|
|
3157
|
+
ownershipRegionKind: mapping.ownershipRegionKind ?? symbol?.metadata?.ownershipRegionKind,
|
|
3046
3158
|
precision: normalizeSourceMapPrecision(mapping.precision, sourceSpan, generatedSpan)
|
|
3047
3159
|
};
|
|
3048
3160
|
return {
|
|
@@ -3330,6 +3442,10 @@ function nativeImportCoverageForProfile(profile, imports, adapters) {
|
|
|
3330
3442
|
: profile.supportsLightweightScan ? profile.defaultReadiness : 'blocked';
|
|
3331
3443
|
const importedParsers = uniqueStrings(matchingImports.map((imported) => imported?.nativeAst?.parser ?? imported?.parser ?? imported?.metadata?.parser).filter(Boolean));
|
|
3332
3444
|
const sourceMaps = matchingImports.flatMap((imported) => imported?.sourceMaps ?? imported?.universalAst?.sourceMaps ?? []);
|
|
3445
|
+
const adapterCoverage = summarizeNativeImporterAdapterCoverageEntries([
|
|
3446
|
+
...matchingImports.map((imported) => nativeImporterAdapterCoverageEntryFromImport(imported)).filter(Boolean),
|
|
3447
|
+
...matchingAdapters.map((adapter) => nativeImporterAdapterCoverageEntryFromAdapter(adapter)).filter(Boolean)
|
|
3448
|
+
]);
|
|
3333
3449
|
return {
|
|
3334
3450
|
language: profile.language,
|
|
3335
3451
|
aliases: profile.aliases,
|
|
@@ -3340,6 +3456,7 @@ function nativeImportCoverageForProfile(profile, imports, adapters) {
|
|
|
3340
3456
|
knownLossKinds: uniqueStrings([...(profile.knownLossKinds ?? []), ...Object.keys(lossSummary.byKind)]),
|
|
3341
3457
|
defaultReadiness: profile.defaultReadiness,
|
|
3342
3458
|
notes: profile.notes,
|
|
3459
|
+
adapterCoverage,
|
|
3343
3460
|
imports: {
|
|
3344
3461
|
total: matchingImports.length,
|
|
3345
3462
|
parsers: importedParsers,
|
|
@@ -3355,6 +3472,125 @@ function nativeImportCoverageForProfile(profile, imports, adapters) {
|
|
|
3355
3472
|
};
|
|
3356
3473
|
}
|
|
3357
3474
|
|
|
3475
|
+
function nativeImporterAdapterCoverageEntryFromImport(imported) {
|
|
3476
|
+
const coverage = imported?.adapter?.coverage
|
|
3477
|
+
?? imported?.metadata?.adapterCoverage
|
|
3478
|
+
?? imported?.nativeAst?.metadata?.adapterCoverage
|
|
3479
|
+
?? imported?.nativeSource?.metadata?.adapterCoverage;
|
|
3480
|
+
if (!coverage) return undefined;
|
|
3481
|
+
return {
|
|
3482
|
+
adapterId: imported?.adapter?.id ?? imported?.metadata?.adapterId ?? imported?.nativeAst?.metadata?.adapterId,
|
|
3483
|
+
language: imported?.adapter?.language ?? imported?.language ?? imported?.nativeAst?.language,
|
|
3484
|
+
parser: imported?.adapter?.parser ?? imported?.nativeAst?.parser ?? imported?.nativeSource?.parser,
|
|
3485
|
+
coverage
|
|
3486
|
+
};
|
|
3487
|
+
}
|
|
3488
|
+
|
|
3489
|
+
function nativeImporterAdapterCoverageEntryFromAdapter(adapter) {
|
|
3490
|
+
if (!adapter) return undefined;
|
|
3491
|
+
const summary = normalizeNativeImporterAdapter(adapter);
|
|
3492
|
+
return {
|
|
3493
|
+
adapterId: summary.id,
|
|
3494
|
+
language: summary.language,
|
|
3495
|
+
parser: summary.parser,
|
|
3496
|
+
coverage: summary.coverage
|
|
3497
|
+
};
|
|
3498
|
+
}
|
|
3499
|
+
|
|
3500
|
+
function summarizeNativeImporterAdapterCoverageEntries(entries = []) {
|
|
3501
|
+
const aggregate = emptyNativeImporterAdapterCoverageAggregate();
|
|
3502
|
+
for (const entry of entries) {
|
|
3503
|
+
const coverage = normalizeNativeImporterAdapterCoverageForEvidence(entry.coverage);
|
|
3504
|
+
const capabilityEvidence = coverage.capabilityEvidence;
|
|
3505
|
+
const summary = {
|
|
3506
|
+
adapterId: entry.adapterId,
|
|
3507
|
+
language: entry.language,
|
|
3508
|
+
parser: entry.parser,
|
|
3509
|
+
exactness: coverage.exactness,
|
|
3510
|
+
declared: capabilityNamesByBoolean(capabilityEvidence.capabilities, 'declared'),
|
|
3511
|
+
observed: capabilityNamesByBoolean(capabilityEvidence.capabilities, 'observed'),
|
|
3512
|
+
effective: capabilityNamesByBoolean(capabilityEvidence.capabilities, 'effective'),
|
|
3513
|
+
gaps: capabilityEvidence.gaps,
|
|
3514
|
+
declaredOnly: capabilityEvidence.declaredOnly,
|
|
3515
|
+
observedOnly: capabilityEvidence.observedOnly
|
|
3516
|
+
};
|
|
3517
|
+
aggregate.total += 1;
|
|
3518
|
+
aggregate.summaries.push(summary);
|
|
3519
|
+
incrementCoverageCapabilityCounts(aggregate.declared, summary.declared);
|
|
3520
|
+
incrementCoverageCapabilityCounts(aggregate.observed, summary.observed);
|
|
3521
|
+
incrementCoverageCapabilityCounts(aggregate.effective, summary.effective);
|
|
3522
|
+
incrementCoverageCapabilityCounts(aggregate.gaps, summary.gaps);
|
|
3523
|
+
incrementCoverageCapabilityCounts(aggregate.declaredOnly, summary.declaredOnly);
|
|
3524
|
+
incrementCoverageCapabilityCounts(aggregate.observedOnly, summary.observedOnly);
|
|
3525
|
+
}
|
|
3526
|
+
return {
|
|
3527
|
+
...aggregate,
|
|
3528
|
+
summaries: Object.freeze(aggregate.summaries)
|
|
3529
|
+
};
|
|
3530
|
+
}
|
|
3531
|
+
|
|
3532
|
+
function normalizeNativeImporterAdapterCoverageForEvidence(coverage = {}) {
|
|
3533
|
+
if (coverage.capabilityEvidence) return coverage;
|
|
3534
|
+
const declared = coverage.declared ?? adapterCoverageSnapshotFromSummary(coverage);
|
|
3535
|
+
const observed = normalizeNativeImporterAdapterObservedCoverage(coverage.observed, declared);
|
|
3536
|
+
const effective = effectiveNativeImporterAdapterCoverage(declared, observed);
|
|
3537
|
+
return {
|
|
3538
|
+
...coverage,
|
|
3539
|
+
...effective,
|
|
3540
|
+
declared,
|
|
3541
|
+
observed,
|
|
3542
|
+
capabilityEvidence: nativeImporterAdapterCapabilityEvidence(declared, observed, effective)
|
|
3543
|
+
};
|
|
3544
|
+
}
|
|
3545
|
+
|
|
3546
|
+
function emptyNativeImporterAdapterCoverageAggregate() {
|
|
3547
|
+
return {
|
|
3548
|
+
total: 0,
|
|
3549
|
+
declared: {},
|
|
3550
|
+
observed: {},
|
|
3551
|
+
effective: {},
|
|
3552
|
+
gaps: {},
|
|
3553
|
+
declaredOnly: {},
|
|
3554
|
+
observedOnly: {},
|
|
3555
|
+
summaries: []
|
|
3556
|
+
};
|
|
3557
|
+
}
|
|
3558
|
+
|
|
3559
|
+
function mergeNativeImporterAdapterCoverageAggregates(left, right) {
|
|
3560
|
+
const merged = emptyNativeImporterAdapterCoverageAggregate();
|
|
3561
|
+
for (const aggregate of [left, right]) {
|
|
3562
|
+
if (!aggregate) continue;
|
|
3563
|
+
merged.total += aggregate.total ?? 0;
|
|
3564
|
+
incrementCoverageCapabilityCounts(merged.declared, aggregate.declared ?? {});
|
|
3565
|
+
incrementCoverageCapabilityCounts(merged.observed, aggregate.observed ?? {});
|
|
3566
|
+
incrementCoverageCapabilityCounts(merged.effective, aggregate.effective ?? {});
|
|
3567
|
+
incrementCoverageCapabilityCounts(merged.gaps, aggregate.gaps ?? {});
|
|
3568
|
+
incrementCoverageCapabilityCounts(merged.declaredOnly, aggregate.declaredOnly ?? {});
|
|
3569
|
+
incrementCoverageCapabilityCounts(merged.observedOnly, aggregate.observedOnly ?? {});
|
|
3570
|
+
merged.summaries.push(...(aggregate.summaries ?? []));
|
|
3571
|
+
}
|
|
3572
|
+
return {
|
|
3573
|
+
...merged,
|
|
3574
|
+
summaries: Object.freeze(merged.summaries)
|
|
3575
|
+
};
|
|
3576
|
+
}
|
|
3577
|
+
|
|
3578
|
+
function capabilityNamesByBoolean(rows, property) {
|
|
3579
|
+
return rows.filter((row) => row[property]).map((row) => row.capability);
|
|
3580
|
+
}
|
|
3581
|
+
|
|
3582
|
+
function incrementCoverageCapabilityCounts(target, capabilities) {
|
|
3583
|
+
if (Array.isArray(capabilities)) {
|
|
3584
|
+
for (const capability of capabilities) {
|
|
3585
|
+
target[capability] = (target[capability] ?? 0) + 1;
|
|
3586
|
+
}
|
|
3587
|
+
return;
|
|
3588
|
+
}
|
|
3589
|
+
for (const [capability, count] of Object.entries(capabilities ?? {})) {
|
|
3590
|
+
target[capability] = (target[capability] ?? 0) + count;
|
|
3591
|
+
}
|
|
3592
|
+
}
|
|
3593
|
+
|
|
3358
3594
|
function semanticImportSidecarEntry(imported, index, options) {
|
|
3359
3595
|
const semanticIndex = imported?.semanticIndex ?? imported?.universalAst?.semanticIndex;
|
|
3360
3596
|
const nativeAst = imported?.nativeAst ?? imported?.nativeSource?.ast;
|
|
@@ -3385,9 +3621,12 @@ function semanticImportSidecarEntry(imported, index, options) {
|
|
|
3385
3621
|
signatureHash: symbol.signatureHash,
|
|
3386
3622
|
ownershipRegionId: region.id,
|
|
3387
3623
|
ownershipKey: region.key,
|
|
3624
|
+
ownershipRegionKind: region.regionKind,
|
|
3388
3625
|
readiness: imported?.metadata?.semanticMergeReadiness ?? imported?.mergeCandidates?.[0]?.readiness ?? 'needs-review'
|
|
3389
3626
|
});
|
|
3390
3627
|
}
|
|
3628
|
+
const ownershipRegions = uniqueRecordsById(regions);
|
|
3629
|
+
const regionTaxonomy = summarizeSemanticImportRegionTaxonomy(ownershipRegions);
|
|
3391
3630
|
return {
|
|
3392
3631
|
id: imported?.id ?? `import_${index + 1}`,
|
|
3393
3632
|
language: imported?.language,
|
|
@@ -3403,8 +3642,9 @@ function semanticImportSidecarEntry(imported, index, options) {
|
|
|
3403
3642
|
sourceMapMappingCount: sourceMapMappings.length,
|
|
3404
3643
|
readiness: imported?.metadata?.semanticMergeReadiness ?? imported?.mergeCandidates?.[0]?.readiness ?? 'needs-review',
|
|
3405
3644
|
emptySemanticIndex: symbols.length === 0,
|
|
3645
|
+
regionTaxonomy,
|
|
3406
3646
|
symbols,
|
|
3407
|
-
ownershipRegions
|
|
3647
|
+
ownershipRegions
|
|
3408
3648
|
};
|
|
3409
3649
|
}
|
|
3410
3650
|
|
|
@@ -3412,15 +3652,17 @@ function semanticOwnershipRegionForSymbol(imported, symbol, mapping, nativeNode,
|
|
|
3412
3652
|
const sourcePath = mapping?.sourceSpan?.path ?? symbol.definitionSpan?.path ?? nativeNode?.span?.path ?? imported?.sourcePath ?? imported?.nativeSource?.sourcePath ?? imported?.nativeAst?.sourcePath;
|
|
3413
3653
|
const language = symbol.language ?? imported?.language ?? imported?.nativeAst?.language ?? imported?.nativeSource?.language;
|
|
3414
3654
|
const sourceSpan = mapping?.sourceSpan ?? symbol.definitionSpan ?? nativeNode?.span;
|
|
3655
|
+
const regionKind = semanticRegionKindForSymbol(symbol, mapping, nativeNode);
|
|
3415
3656
|
const key = [
|
|
3416
3657
|
options.regionPrefix ?? 'source',
|
|
3417
3658
|
sourcePath ?? `${language}:memory`,
|
|
3418
|
-
|
|
3659
|
+
regionKind,
|
|
3419
3660
|
symbol.name ?? symbol.id
|
|
3420
3661
|
].map((part) => String(part).replace(/\s+/g, ' ').trim()).join('#');
|
|
3421
3662
|
return {
|
|
3422
3663
|
id: `region_${idFragment(key)}`,
|
|
3423
3664
|
key,
|
|
3665
|
+
regionKind,
|
|
3424
3666
|
granularity: 'symbol',
|
|
3425
3667
|
language,
|
|
3426
3668
|
sourcePath,
|
|
@@ -3431,7 +3673,10 @@ function semanticOwnershipRegionForSymbol(imported, symbol, mapping, nativeNode,
|
|
|
3431
3673
|
nativeAstNodeId: symbol.nativeAstNodeId ?? nativeNode?.id,
|
|
3432
3674
|
sourceSpan,
|
|
3433
3675
|
precision: mapping?.precision ?? (sourceSpan ? 'declaration' : 'unknown'),
|
|
3434
|
-
mergePolicy:
|
|
3676
|
+
mergePolicy: semanticRegionMergePolicy(regionKind),
|
|
3677
|
+
metadata: {
|
|
3678
|
+
semanticRegionTaxonomy: true
|
|
3679
|
+
}
|
|
3435
3680
|
};
|
|
3436
3681
|
}
|
|
3437
3682
|
|
|
@@ -3439,10 +3684,12 @@ function semanticOwnershipRegionForDeclaration(input, declaration, documentId) {
|
|
|
3439
3684
|
const name = declaration.name ?? declaration.importPath ?? declaration.nodeId ?? declaration.nativeNode?.id;
|
|
3440
3685
|
const kind = declaration.symbolKind ?? declaration.kind ?? declaration.nativeNode?.kind ?? 'symbol';
|
|
3441
3686
|
const sourcePath = declaration.span?.path ?? declaration.nativeNode?.span?.path ?? input.sourcePath ?? `${input.language}:memory`;
|
|
3442
|
-
const
|
|
3687
|
+
const regionKind = semanticRegionKindForDeclaration(declaration);
|
|
3688
|
+
const key = ['source', sourcePath, regionKind, name].map((part) => String(part).replace(/\s+/g, ' ').trim()).join('#');
|
|
3443
3689
|
return {
|
|
3444
3690
|
id: `region_${idFragment(key)}`,
|
|
3445
3691
|
key,
|
|
3692
|
+
regionKind,
|
|
3446
3693
|
granularity: 'symbol',
|
|
3447
3694
|
language: input.language,
|
|
3448
3695
|
documentId,
|
|
@@ -3454,7 +3701,10 @@ function semanticOwnershipRegionForDeclaration(input, declaration, documentId) {
|
|
|
3454
3701
|
nativeAstNodeId: declaration.nodeId ?? declaration.nativeNode?.id,
|
|
3455
3702
|
sourceSpan: declaration.span ?? declaration.nativeNode?.span,
|
|
3456
3703
|
precision: declaration.span || declaration.nativeNode?.span ? 'declaration' : 'unknown',
|
|
3457
|
-
mergePolicy:
|
|
3704
|
+
mergePolicy: semanticRegionMergePolicy(regionKind),
|
|
3705
|
+
metadata: {
|
|
3706
|
+
semanticRegionTaxonomy: true
|
|
3707
|
+
}
|
|
3458
3708
|
};
|
|
3459
3709
|
}
|
|
3460
3710
|
|
|
@@ -3469,7 +3719,7 @@ function semanticPatchHintForRegion(region, readiness, options = {}) {
|
|
|
3469
3719
|
sourceSpan: region.sourceSpan,
|
|
3470
3720
|
readiness,
|
|
3471
3721
|
precision: region.precision,
|
|
3472
|
-
supportedOperations:
|
|
3722
|
+
supportedOperations: semanticRegionSupportedOperations(region),
|
|
3473
3723
|
projection: {
|
|
3474
3724
|
sourceLanguage: region.language,
|
|
3475
3725
|
targetPath: options.targetPath ?? region.sourcePath,
|
|
@@ -3478,6 +3728,79 @@ function semanticPatchHintForRegion(region, readiness, options = {}) {
|
|
|
3478
3728
|
};
|
|
3479
3729
|
}
|
|
3480
3730
|
|
|
3731
|
+
function semanticRegionKindForDeclaration(declaration) {
|
|
3732
|
+
if (declaration.role === 'import' || declaration.importPath) return 'import';
|
|
3733
|
+
const kind = declaration.symbolKind ?? declaration.kind ?? declaration.nativeNode?.kind;
|
|
3734
|
+
if (semanticKindIsType(kind)) return 'type';
|
|
3735
|
+
if (semanticKindCanOwnBody(kind, declaration.span ?? declaration.nativeNode?.span)) return 'body';
|
|
3736
|
+
return 'declaration';
|
|
3737
|
+
}
|
|
3738
|
+
|
|
3739
|
+
function semanticRegionKindForSymbol(symbol, mapping, nativeNode) {
|
|
3740
|
+
if (mapping?.generatedSpan || mapping?.generatedName || mapping?.target?.emitPath) return 'generatedOutput';
|
|
3741
|
+
if (symbol?.metadata?.ownershipRegionKind) return normalizeNativeImportRegionKind(symbol.metadata.ownershipRegionKind);
|
|
3742
|
+
if (String(symbol?.id ?? '').includes(':import:') || symbol?.metadata?.role === 'import') return 'import';
|
|
3743
|
+
if (semanticKindIsType(symbol?.kind ?? nativeNode?.kind)) return 'type';
|
|
3744
|
+
if (semanticKindCanOwnBody(symbol?.kind ?? nativeNode?.kind, nativeNode?.span ?? symbol?.definitionSpan)) return 'body';
|
|
3745
|
+
return 'declaration';
|
|
3746
|
+
}
|
|
3747
|
+
|
|
3748
|
+
function semanticKindIsType(kind) {
|
|
3749
|
+
return ['type', 'class', 'interface', 'trait', 'protocol', 'struct', 'enum', 'record'].includes(String(kind ?? '').toLowerCase());
|
|
3750
|
+
}
|
|
3751
|
+
|
|
3752
|
+
function semanticKindCanOwnBody(kind, span) {
|
|
3753
|
+
const text = String(kind ?? '').toLowerCase();
|
|
3754
|
+
if (/function|method|class|implementation|module|namespace|package|action|effect|capability/.test(text)) return true;
|
|
3755
|
+
return typeof span?.startLine === 'number' && typeof span?.endLine === 'number' && span.endLine > span.startLine;
|
|
3756
|
+
}
|
|
3757
|
+
|
|
3758
|
+
function semanticRegionMergePolicy(regionKind) {
|
|
3759
|
+
if (regionKind === 'import') return 'module-edge-review-required';
|
|
3760
|
+
if (regionKind === 'body') return 'implementation-single-writer-review-required';
|
|
3761
|
+
if (regionKind === 'call') return 'callsite-overlap-review-required';
|
|
3762
|
+
if (regionKind === 'type') return 'type-surface-review-required';
|
|
3763
|
+
if (regionKind === 'effect') return 'effect-boundary-review-required';
|
|
3764
|
+
if (regionKind === 'generatedOutput') return 'generated-output-source-map-review-required';
|
|
3765
|
+
return 'single-writer-review-required';
|
|
3766
|
+
}
|
|
3767
|
+
|
|
3768
|
+
function semanticRegionSupportedOperations(region) {
|
|
3769
|
+
if (region.regionKind === 'import') return ['replace-import', 'insert-import-before', 'insert-import-after', 'replace-region'];
|
|
3770
|
+
if (region.regionKind === 'body') return ['replace-body', 'insert-before-body', 'insert-after-body'];
|
|
3771
|
+
if (region.regionKind === 'call') return ['replace-callsite', 'review-callsite'];
|
|
3772
|
+
if (region.regionKind === 'type') return ['replace-type-declaration', 'merge-type-members', 'replace-region'];
|
|
3773
|
+
if (region.regionKind === 'effect') return ['route-effect', 'replace-effect-boundary', 'review-effect-policy'];
|
|
3774
|
+
if (region.regionKind === 'generatedOutput') return ['replace-generated-output', 'attach-generated-source-map', 'review-generator-input'];
|
|
3775
|
+
return ['replace-region', 'insert-before-region', 'insert-after-region'];
|
|
3776
|
+
}
|
|
3777
|
+
|
|
3778
|
+
function normalizeNativeImportRegionKind(value) {
|
|
3779
|
+
const text = String(value ?? 'symbol').trim();
|
|
3780
|
+
if (text === 'generated' || text === 'generated-output' || text === 'generated_output') return 'generatedOutput';
|
|
3781
|
+
if (NativeImportRegionTaxonomyKinds.includes(text)) return text;
|
|
3782
|
+
return text || 'symbol';
|
|
3783
|
+
}
|
|
3784
|
+
|
|
3785
|
+
function summarizeSemanticImportRegionTaxonomy(regions) {
|
|
3786
|
+
const byKind = {};
|
|
3787
|
+
const keysByKind = {};
|
|
3788
|
+
const keys = [];
|
|
3789
|
+
for (const region of regions ?? []) {
|
|
3790
|
+
const kind = normalizeNativeImportRegionKind(region.regionKind ?? region.granularity);
|
|
3791
|
+
byKind[kind] = (byKind[kind] ?? 0) + 1;
|
|
3792
|
+
keysByKind[kind] = [...(keysByKind[kind] ?? []), region.key].filter(Boolean);
|
|
3793
|
+
if (region.key) keys.push(region.key);
|
|
3794
|
+
}
|
|
3795
|
+
return {
|
|
3796
|
+
kinds: [...NativeImportRegionTaxonomyKinds],
|
|
3797
|
+
presentKinds: uniqueStrings(Object.keys(byKind)),
|
|
3798
|
+
byKind,
|
|
3799
|
+
keys,
|
|
3800
|
+
keysByKind
|
|
3801
|
+
};
|
|
3802
|
+
}
|
|
3803
|
+
|
|
3481
3804
|
function nativeImportCoverageReasons(profile) {
|
|
3482
3805
|
if (!profile.supportsLightweightScan) return ['No built-in scanner coverage profile; host must provide an exact adapter or mark unsupported.'];
|
|
3483
3806
|
return ['Built-in coverage is declaration-level only; use injected parser adapters for exact AST/CST, tokens, trivia, type resolution, and round-trip evidence.'];
|
|
@@ -3590,13 +3913,30 @@ function withNativeImportReadiness(importResult, lossSummary) {
|
|
|
3590
3913
|
}
|
|
3591
3914
|
};
|
|
3592
3915
|
});
|
|
3916
|
+
const semanticMergeReadiness = mergeCandidates[0]?.readiness ?? lossSummary.semanticMergeReadiness;
|
|
3917
|
+
const contractInput = {
|
|
3918
|
+
...importResult,
|
|
3919
|
+
mergeCandidates,
|
|
3920
|
+
metadata: {
|
|
3921
|
+
...importResult.metadata,
|
|
3922
|
+
nativeImportLossSummary: lossSummary,
|
|
3923
|
+
semanticMergeReadiness
|
|
3924
|
+
}
|
|
3925
|
+
};
|
|
3926
|
+
const importResultContract = createNativeImportResultContract(contractInput, { lossSummary });
|
|
3593
3927
|
return {
|
|
3594
3928
|
...importResult,
|
|
3595
3929
|
mergeCandidates,
|
|
3596
3930
|
metadata: {
|
|
3597
3931
|
...importResult.metadata,
|
|
3932
|
+
importResultContract,
|
|
3598
3933
|
nativeImportLossSummary: lossSummary,
|
|
3599
|
-
semanticMergeReadiness
|
|
3934
|
+
semanticMergeReadiness,
|
|
3935
|
+
readinessReasons: importResultContract.readiness.reasons,
|
|
3936
|
+
sourcePreservationSummary: importResultContract.sourcePreservation,
|
|
3937
|
+
adapterCoverageSummary: importResultContract.adapterCoverage,
|
|
3938
|
+
regionSummary: importResultContract.regions,
|
|
3939
|
+
sourceMapSummary: importResultContract.sourceMaps,
|
|
3600
3940
|
lossCategories: lossSummary.categories,
|
|
3601
3941
|
lossSeverityCounts: lossSummary.bySeverity,
|
|
3602
3942
|
lossKindCounts: lossSummary.byKind
|
|
@@ -3647,6 +3987,257 @@ function nativeImportRoundtripReasons(status, input) {
|
|
|
3647
3987
|
return ['Native import roundtrip readiness requires review.'];
|
|
3648
3988
|
}
|
|
3649
3989
|
|
|
3990
|
+
function collectImportSourceMaps(importResult, imports) {
|
|
3991
|
+
return uniqueRecordsById([
|
|
3992
|
+
...(importResult?.sourceMaps ?? importResult?.universalAst?.sourceMaps ?? []),
|
|
3993
|
+
...imports.flatMap((imported) => imported?.sourceMaps ?? imported?.universalAst?.sourceMaps ?? [])
|
|
3994
|
+
]);
|
|
3995
|
+
}
|
|
3996
|
+
|
|
3997
|
+
function summarizeImportSourceMaps(sourceMaps) {
|
|
3998
|
+
const mappings = sourceMaps.flatMap((sourceMap) => sourceMap?.mappings ?? []);
|
|
3999
|
+
return {
|
|
4000
|
+
total: sourceMaps.length,
|
|
4001
|
+
ids: sourceMaps.map((sourceMap) => sourceMap.id).filter(Boolean),
|
|
4002
|
+
mappingCount: mappings.length,
|
|
4003
|
+
sourcePaths: uniqueStrings([
|
|
4004
|
+
...sourceMaps.map((sourceMap) => sourceMap.sourcePath),
|
|
4005
|
+
...mappings.map((mapping) => mapping.sourceSpan?.path)
|
|
4006
|
+
].filter(Boolean)),
|
|
4007
|
+
targetPaths: uniqueStrings([
|
|
4008
|
+
...sourceMaps.map((sourceMap) => sourceMap.targetPath ?? sourceMap.target?.emitPath),
|
|
4009
|
+
...mappings.map((mapping) => mapping.generatedSpan?.targetPath ?? mapping.target?.emitPath)
|
|
4010
|
+
].filter(Boolean)),
|
|
4011
|
+
byPrecision: countBy(mappings.map((mapping) => mapping.precision ?? 'unknown')),
|
|
4012
|
+
sourceRangeMappings: mappings.filter((mapping) => mapping.sourceSpan).length,
|
|
4013
|
+
generatedRangeMappings: mappings.filter((mapping) => mapping.generatedSpan).length
|
|
4014
|
+
};
|
|
4015
|
+
}
|
|
4016
|
+
|
|
4017
|
+
function summarizeImportRegions(importResult, imports, options = {}) {
|
|
4018
|
+
const entries = imports.map((imported, index) => semanticImportSidecarEntry(imported, index, options));
|
|
4019
|
+
const regions = uniqueRecordsById(entries.flatMap((entry) => entry.ownershipRegions ?? []));
|
|
4020
|
+
const taxonomy = summarizeSemanticImportRegionTaxonomy(regions);
|
|
4021
|
+
return {
|
|
4022
|
+
total: regions.length,
|
|
4023
|
+
ids: regions.map((region) => region.id),
|
|
4024
|
+
keys: regions.map((region) => region.key),
|
|
4025
|
+
sourcePaths: uniqueStrings(regions.map((region) => region.sourcePath).filter(Boolean)),
|
|
4026
|
+
byKind: taxonomy.byKind,
|
|
4027
|
+
byGranularity: countBy(regions.map((region) => region.granularity ?? 'unknown')),
|
|
4028
|
+
byPrecision: countBy(regions.map((region) => region.precision ?? 'unknown')),
|
|
4029
|
+
byLanguage: countBy(regions.map((region) => region.language ?? importResult?.language ?? 'unknown')),
|
|
4030
|
+
symbolIds: uniqueStrings(regions.map((region) => region.symbolId).filter(Boolean)),
|
|
4031
|
+
taxonomy
|
|
4032
|
+
};
|
|
4033
|
+
}
|
|
4034
|
+
|
|
4035
|
+
function summarizeImportSourcePreservation(importResult, imports) {
|
|
4036
|
+
const records = uniqueSourcePreservationRecords([
|
|
4037
|
+
...collectSourcePreservationFromImport(importResult),
|
|
4038
|
+
...imports.flatMap((imported) => collectSourcePreservationFromImport(imported))
|
|
4039
|
+
]);
|
|
4040
|
+
const compactRecords = records.map(compactSourcePreservationRecord);
|
|
4041
|
+
return {
|
|
4042
|
+
total: compactRecords.length,
|
|
4043
|
+
ids: compactRecords.map((record) => record.id).filter(Boolean),
|
|
4044
|
+
sourcePaths: uniqueStrings(compactRecords.map((record) => record.sourcePath).filter(Boolean)),
|
|
4045
|
+
sourceHashes: uniqueStrings(compactRecords.map((record) => record.sourceHash).filter(Boolean)),
|
|
4046
|
+
exactSourceAvailable: compactRecords.filter((record) => record.exactSourceAvailable).length,
|
|
4047
|
+
sourceBytes: compactRecords.reduce((sum, record) => sum + (record.sourceBytes ?? 0), 0),
|
|
4048
|
+
lineCount: compactRecords.reduce((sum, record) => sum + (record.lineCount ?? 0), 0),
|
|
4049
|
+
tokens: compactRecords.reduce((sum, record) => sum + (record.tokens ?? 0), 0),
|
|
4050
|
+
trivia: compactRecords.reduce((sum, record) => sum + (record.trivia ?? 0), 0),
|
|
4051
|
+
directives: compactRecords.reduce((sum, record) => sum + (record.directives ?? 0), 0),
|
|
4052
|
+
comments: compactRecords.reduce((sum, record) => sum + (record.comments ?? 0), 0),
|
|
4053
|
+
whitespace: compactRecords.reduce((sum, record) => sum + (record.whitespace ?? 0), 0),
|
|
4054
|
+
truncated: compactRecords.some((record) => record.truncated),
|
|
4055
|
+
records: compactRecords
|
|
4056
|
+
};
|
|
4057
|
+
}
|
|
4058
|
+
|
|
4059
|
+
function collectSourcePreservationFromImport(imported) {
|
|
4060
|
+
const nativeAst = imported?.nativeAst ?? imported?.nativeSource?.ast;
|
|
4061
|
+
return [
|
|
4062
|
+
imported?.metadata?.sourcePreservation,
|
|
4063
|
+
imported?.nativeSource?.metadata?.sourcePreservation,
|
|
4064
|
+
nativeAst?.metadata?.sourcePreservation,
|
|
4065
|
+
imported?.universalAst?.metadata?.sourcePreservation,
|
|
4066
|
+
...(imported?.nativeSources ?? []).map((nativeSource) => nativeSource?.metadata?.sourcePreservation ?? nativeSource?.ast?.metadata?.sourcePreservation)
|
|
4067
|
+
].filter(Boolean);
|
|
4068
|
+
}
|
|
4069
|
+
|
|
4070
|
+
function uniqueSourcePreservationRecords(records) {
|
|
4071
|
+
const seen = new Set();
|
|
4072
|
+
const result = [];
|
|
4073
|
+
for (const record of records) {
|
|
4074
|
+
const key = record.id ?? `${record.sourcePath ?? 'source'}#${record.sourceHash ?? result.length}`;
|
|
4075
|
+
if (seen.has(key)) continue;
|
|
4076
|
+
seen.add(key);
|
|
4077
|
+
result.push(record);
|
|
4078
|
+
}
|
|
4079
|
+
return result;
|
|
4080
|
+
}
|
|
4081
|
+
|
|
4082
|
+
function compactSourcePreservationRecord(record) {
|
|
4083
|
+
return {
|
|
4084
|
+
id: record.id,
|
|
4085
|
+
language: record.language,
|
|
4086
|
+
sourcePath: record.sourcePath,
|
|
4087
|
+
sourceHash: record.sourceHash,
|
|
4088
|
+
sourceBytes: record.sourceBytes,
|
|
4089
|
+
lineCount: record.lineCount,
|
|
4090
|
+
newline: record.newline,
|
|
4091
|
+
encoding: record.encoding,
|
|
4092
|
+
exactSourceAvailable: record.summary?.exactSourceAvailable === true,
|
|
4093
|
+
tokens: record.summary?.tokens ?? record.tokens?.length ?? 0,
|
|
4094
|
+
trivia: record.summary?.trivia ?? record.trivia?.length ?? 0,
|
|
4095
|
+
directives: record.summary?.directives ?? record.directives?.length ?? 0,
|
|
4096
|
+
comments: record.summary?.comments ?? 0,
|
|
4097
|
+
whitespace: record.summary?.whitespace ?? 0,
|
|
4098
|
+
truncated: record.summary?.truncated === true
|
|
4099
|
+
};
|
|
4100
|
+
}
|
|
4101
|
+
|
|
4102
|
+
function summarizeImportAdapterCoverage(importResult, imports) {
|
|
4103
|
+
const records = uniqueAdapterCoverageRecords([
|
|
4104
|
+
compactAdapterCoverageRecord(importResult),
|
|
4105
|
+
...imports.map((imported) => compactAdapterCoverageRecord(imported))
|
|
4106
|
+
].filter(Boolean));
|
|
4107
|
+
const observed = records.reduce((totals, record) => {
|
|
4108
|
+
for (const key of ['diagnostics', 'losses', 'nativeAstNodes', 'semanticSymbols', 'sourceMapMappings']) {
|
|
4109
|
+
totals[key] += record.observed?.[key] ?? 0;
|
|
4110
|
+
}
|
|
4111
|
+
totals.sourceRanges = totals.sourceRanges || record.observed?.sourceRanges === true;
|
|
4112
|
+
totals.generatedRanges = totals.generatedRanges || record.observed?.generatedRanges === true;
|
|
4113
|
+
return totals;
|
|
4114
|
+
}, {
|
|
4115
|
+
diagnostics: 0,
|
|
4116
|
+
losses: 0,
|
|
4117
|
+
nativeAstNodes: 0,
|
|
4118
|
+
semanticSymbols: 0,
|
|
4119
|
+
sourceMapMappings: 0,
|
|
4120
|
+
sourceRanges: false,
|
|
4121
|
+
generatedRanges: false
|
|
4122
|
+
});
|
|
4123
|
+
return {
|
|
4124
|
+
total: records.length,
|
|
4125
|
+
adapterIds: uniqueStrings(records.map((record) => record.adapterId).filter(Boolean)),
|
|
4126
|
+
parsers: uniqueStrings(records.map((record) => record.parser).filter(Boolean)),
|
|
4127
|
+
exactness: uniqueStrings(records.map((record) => record.exactness).filter(Boolean)),
|
|
4128
|
+
exactAst: records.filter((record) => record.exactAst).length,
|
|
4129
|
+
tokens: records.filter((record) => record.tokens).length,
|
|
4130
|
+
trivia: records.filter((record) => record.trivia).length,
|
|
4131
|
+
diagnostics: records.filter((record) => record.diagnostics).length,
|
|
4132
|
+
sourceRanges: records.filter((record) => record.sourceRanges).length,
|
|
4133
|
+
generatedRanges: records.filter((record) => record.generatedRanges).length,
|
|
4134
|
+
semanticCoverageLevels: uniqueStrings(records.map((record) => record.semanticCoverage?.level).filter(Boolean)),
|
|
4135
|
+
observed,
|
|
4136
|
+
records
|
|
4137
|
+
};
|
|
4138
|
+
}
|
|
4139
|
+
|
|
4140
|
+
function compactAdapterCoverageRecord(imported) {
|
|
4141
|
+
const nativeAst = imported?.nativeAst ?? imported?.nativeSource?.ast;
|
|
4142
|
+
const nativeSource = imported?.nativeSource;
|
|
4143
|
+
const coverage = imported?.adapter?.coverage
|
|
4144
|
+
?? imported?.metadata?.adapterCoverage
|
|
4145
|
+
?? nativeAst?.metadata?.adapterCoverage
|
|
4146
|
+
?? nativeSource?.metadata?.adapterCoverage;
|
|
4147
|
+
if (!coverage) return undefined;
|
|
4148
|
+
return {
|
|
4149
|
+
adapterId: imported?.adapter?.id ?? imported?.metadata?.adapterId ?? nativeAst?.metadata?.adapterId ?? nativeSource?.metadata?.adapterId,
|
|
4150
|
+
adapterVersion: imported?.adapter?.version ?? imported?.metadata?.adapterVersion ?? nativeAst?.metadata?.adapterVersion ?? nativeSource?.metadata?.adapterVersion,
|
|
4151
|
+
parser: imported?.adapter?.parser ?? nativeAst?.parser ?? nativeSource?.parser ?? imported?.metadata?.parser,
|
|
4152
|
+
capabilities: uniqueStrings(imported?.adapter?.capabilities ?? imported?.metadata?.adapterCapabilities ?? []),
|
|
4153
|
+
supportedExtensions: uniqueStrings(imported?.adapter?.supportedExtensions ?? imported?.metadata?.supportedExtensions ?? []),
|
|
4154
|
+
exactness: coverage.exactness,
|
|
4155
|
+
exactAst: Boolean(coverage.exactAst),
|
|
4156
|
+
tokens: Boolean(coverage.tokens),
|
|
4157
|
+
trivia: Boolean(coverage.trivia),
|
|
4158
|
+
diagnostics: Boolean(coverage.diagnostics),
|
|
4159
|
+
sourceRanges: Boolean(coverage.sourceRanges),
|
|
4160
|
+
generatedRanges: Boolean(coverage.generatedRanges),
|
|
4161
|
+
semanticCoverage: coverage.semanticCoverage,
|
|
4162
|
+
observed: coverage.observed,
|
|
4163
|
+
notes: uniqueStrings(coverage.notes ?? [])
|
|
4164
|
+
};
|
|
4165
|
+
}
|
|
4166
|
+
|
|
4167
|
+
function uniqueAdapterCoverageRecords(records) {
|
|
4168
|
+
const seen = new Set();
|
|
4169
|
+
const result = [];
|
|
4170
|
+
for (const record of records) {
|
|
4171
|
+
const key = [record.adapterId, record.adapterVersion, record.parser, record.exactness].join('#');
|
|
4172
|
+
if (seen.has(key)) continue;
|
|
4173
|
+
seen.add(key);
|
|
4174
|
+
result.push(record);
|
|
4175
|
+
}
|
|
4176
|
+
return result;
|
|
4177
|
+
}
|
|
4178
|
+
|
|
4179
|
+
function compactImportContractSource(imported, index) {
|
|
4180
|
+
const nativeAst = imported?.nativeAst ?? imported?.nativeSource?.ast;
|
|
4181
|
+
const nativeSource = imported?.nativeSource;
|
|
4182
|
+
const semanticIndex = imported?.semanticIndex ?? imported?.universalAst?.semanticIndex;
|
|
4183
|
+
const sourceMaps = collectImportSourceMaps(imported, [imported].filter(Boolean));
|
|
4184
|
+
return {
|
|
4185
|
+
id: imported?.id ?? `import_${index + 1}`,
|
|
4186
|
+
language: imported?.language ?? nativeSource?.language ?? nativeAst?.language,
|
|
4187
|
+
sourcePath: imported?.sourcePath ?? nativeSource?.sourcePath ?? nativeAst?.sourcePath,
|
|
4188
|
+
sourceHash: nativeSource?.sourceHash ?? nativeAst?.sourceHash,
|
|
4189
|
+
parser: nativeAst?.parser ?? nativeSource?.parser,
|
|
4190
|
+
nativeSourceId: nativeSource?.id,
|
|
4191
|
+
nativeAstId: nativeAst?.id,
|
|
4192
|
+
semanticIndexId: semanticIndex?.id,
|
|
4193
|
+
universalAstId: imported?.universalAst?.id,
|
|
4194
|
+
patchId: imported?.patch?.id,
|
|
4195
|
+
sourceMapIds: sourceMaps.map((sourceMap) => sourceMap.id).filter(Boolean),
|
|
4196
|
+
sourceMapMappings: sourceMaps.reduce((sum, sourceMap) => sum + (sourceMap.mappings?.length ?? 0), 0),
|
|
4197
|
+
symbolCount: semanticIndex?.symbols?.length ?? 0,
|
|
4198
|
+
lossCount: imported?.losses?.length ?? nativeAst?.losses?.length ?? 0,
|
|
4199
|
+
evidenceCount: imported?.evidence?.length ?? 0,
|
|
4200
|
+
readiness: imported?.metadata?.semanticMergeReadiness ?? imported?.mergeCandidates?.[0]?.readiness
|
|
4201
|
+
};
|
|
4202
|
+
}
|
|
4203
|
+
|
|
4204
|
+
function summarizeImportContractReadiness(importResult, mergeCandidates, lossSummary) {
|
|
4205
|
+
const candidateReadiness = mergeCandidates.reduce(
|
|
4206
|
+
(current, candidate) => maxSemanticMergeReadiness(current, candidate.readiness),
|
|
4207
|
+
lossSummary.semanticMergeReadiness
|
|
4208
|
+
);
|
|
4209
|
+
const semanticMergeReadiness = maxSemanticMergeReadiness(
|
|
4210
|
+
importResult?.metadata?.semanticMergeReadiness ?? lossSummary.semanticMergeReadiness,
|
|
4211
|
+
candidateReadiness
|
|
4212
|
+
);
|
|
4213
|
+
return {
|
|
4214
|
+
semanticMergeReadiness,
|
|
4215
|
+
severityReadiness: lossSummary.semanticMergeReadiness,
|
|
4216
|
+
reasons: uniqueStrings([
|
|
4217
|
+
...(lossSummary.readinessReasons ?? []),
|
|
4218
|
+
...mergeCandidates.flatMap((candidate) => candidate?.reasons ?? []),
|
|
4219
|
+
...normalizeStringList(importResult?.metadata?.readinessReasons)
|
|
4220
|
+
]),
|
|
4221
|
+
failedEvidenceIds: lossSummary.failedEvidenceIds,
|
|
4222
|
+
blockingLossIds: lossSummary.blockingLossIds,
|
|
4223
|
+
reviewLossIds: lossSummary.reviewLossIds,
|
|
4224
|
+
informationalLossIds: lossSummary.informationalLossIds
|
|
4225
|
+
};
|
|
4226
|
+
}
|
|
4227
|
+
|
|
4228
|
+
function defaultSemanticImportSidecarId(importResult, imports = []) {
|
|
4229
|
+
return `semantic_import_${idFragment(importResult?.id ?? importResult?.projectRoot ?? imports[0]?.sourcePath ?? imports[0]?.language ?? 'source')}`;
|
|
4230
|
+
}
|
|
4231
|
+
|
|
4232
|
+
function countBy(values) {
|
|
4233
|
+
const counts = {};
|
|
4234
|
+
for (const value of values ?? []) {
|
|
4235
|
+
const key = String(value ?? 'unknown');
|
|
4236
|
+
counts[key] = (counts[key] ?? 0) + 1;
|
|
4237
|
+
}
|
|
4238
|
+
return counts;
|
|
4239
|
+
}
|
|
4240
|
+
|
|
3650
4241
|
function maxSemanticMergeReadiness(left, right) {
|
|
3651
4242
|
const leftRank = semanticMergeReadinessRank[left] ?? semanticMergeReadinessRank['needs-review'];
|
|
3652
4243
|
const rightRank = semanticMergeReadinessRank[right] ?? semanticMergeReadinessRank['needs-review'];
|
|
@@ -4042,7 +4633,8 @@ function semanticIndexFromNativeDeclarations(declarations, input, options) {
|
|
|
4042
4633
|
declaration.nativeNode.metadata = {
|
|
4043
4634
|
...declaration.nativeNode.metadata,
|
|
4044
4635
|
ownershipRegionId: ownershipRegion.id,
|
|
4045
|
-
ownershipRegionKey: ownershipRegion.key
|
|
4636
|
+
ownershipRegionKey: ownershipRegion.key,
|
|
4637
|
+
ownershipRegionKind: ownershipRegion.regionKind
|
|
4046
4638
|
};
|
|
4047
4639
|
symbols.push({
|
|
4048
4640
|
id: symbolId,
|
|
@@ -4055,7 +4647,8 @@ function semanticIndexFromNativeDeclarations(declarations, input, options) {
|
|
|
4055
4647
|
definitionSpan: declaration.nativeNode.span,
|
|
4056
4648
|
metadata: {
|
|
4057
4649
|
ownershipRegionId: ownershipRegion.id,
|
|
4058
|
-
ownershipRegionKey: ownershipRegion.key
|
|
4650
|
+
ownershipRegionKey: ownershipRegion.key,
|
|
4651
|
+
ownershipRegionKind: ownershipRegion.regionKind
|
|
4059
4652
|
}
|
|
4060
4653
|
});
|
|
4061
4654
|
occurrences.push({
|
|
@@ -4082,6 +4675,15 @@ function semanticIndexFromNativeDeclarations(declarations, input, options) {
|
|
|
4082
4675
|
predicate: 'semanticOwnershipRegion',
|
|
4083
4676
|
subjectId: symbolId,
|
|
4084
4677
|
value: ownershipRegion
|
|
4678
|
+
}, {
|
|
4679
|
+
id: `fact_${idFragment(declaration.nativeNode.id)}_ownership_region_taxonomy`,
|
|
4680
|
+
predicate: 'semanticOwnershipRegionTaxonomy',
|
|
4681
|
+
subjectId: symbolId,
|
|
4682
|
+
value: {
|
|
4683
|
+
regionKind: ownershipRegion.regionKind,
|
|
4684
|
+
granularity: ownershipRegion.granularity,
|
|
4685
|
+
key: ownershipRegion.key
|
|
4686
|
+
}
|
|
4085
4687
|
});
|
|
4086
4688
|
mappings.push({
|
|
4087
4689
|
id: `map_${idFragment(declaration.nativeNode.id)}`,
|
|
@@ -4092,6 +4694,8 @@ function semanticIndexFromNativeDeclarations(declarations, input, options) {
|
|
|
4092
4694
|
evidenceIds: [evidenceId],
|
|
4093
4695
|
lossIds: [],
|
|
4094
4696
|
ownershipRegionId: ownershipRegion.id,
|
|
4697
|
+
ownershipRegionKey: ownershipRegion.key,
|
|
4698
|
+
ownershipRegionKind: ownershipRegion.regionKind,
|
|
4095
4699
|
precision: declaration.nativeNode.span ? 'declaration' : 'unknown'
|
|
4096
4700
|
});
|
|
4097
4701
|
}
|
|
@@ -4211,7 +4815,7 @@ function createNativeProjectImportResult(input, imports) {
|
|
|
4211
4815
|
sourcePreservationSummary
|
|
4212
4816
|
}
|
|
4213
4817
|
});
|
|
4214
|
-
|
|
4818
|
+
const projectResult = {
|
|
4215
4819
|
kind: 'frontier.lang.projectImportResult',
|
|
4216
4820
|
version: 1,
|
|
4217
4821
|
id: input.id ?? `project_import_${idPart}`,
|
|
@@ -4235,6 +4839,21 @@ function createNativeProjectImportResult(input, imports) {
|
|
|
4235
4839
|
...input.metadata
|
|
4236
4840
|
}
|
|
4237
4841
|
};
|
|
4842
|
+
const importResultContract = createNativeImportResultContract(projectResult, {
|
|
4843
|
+
lossSummary: nativeImportLossSummary
|
|
4844
|
+
});
|
|
4845
|
+
return {
|
|
4846
|
+
...projectResult,
|
|
4847
|
+
metadata: {
|
|
4848
|
+
...projectResult.metadata,
|
|
4849
|
+
importResultContract,
|
|
4850
|
+
semanticMergeReadiness: importResultContract.readiness.semanticMergeReadiness,
|
|
4851
|
+
readinessReasons: importResultContract.readiness.reasons,
|
|
4852
|
+
regionSummary: importResultContract.regions,
|
|
4853
|
+
sourceMapSummary: importResultContract.sourceMaps,
|
|
4854
|
+
adapterCoverageSummary: importResultContract.adapterCoverage
|
|
4855
|
+
}
|
|
4856
|
+
};
|
|
4238
4857
|
}
|
|
4239
4858
|
|
|
4240
4859
|
function summarizeProjectSourcePreservation(imports) {
|
|
@@ -4335,7 +4954,7 @@ function normalizeNativeImporterAdapterCoverage(value = {}, context = {}) {
|
|
|
4335
4954
|
const sourceRanges = Boolean(value.sourceRanges ?? hasCapability('sourceRanges', 'sourceRange', 'ranges', 'sourceMaps'));
|
|
4336
4955
|
const generatedRanges = Boolean(value.generatedRanges ?? hasCapability('generatedRanges', 'generatedRange', 'generatedSourceMaps'));
|
|
4337
4956
|
const diagnostics = Boolean(value.diagnostics ?? hasCapability('diagnostics', 'parserDiagnostics'));
|
|
4338
|
-
|
|
4957
|
+
const declared = freezeNativeImporterAdapterCoverageSnapshot({
|
|
4339
4958
|
exactness: String(value.exactness ?? inferredAdapterExactness(exactAst, capabilities)),
|
|
4340
4959
|
exactAst,
|
|
4341
4960
|
tokens: Boolean(value.tokens ?? hasCapability('tokens', 'tokenStream')),
|
|
@@ -4347,13 +4966,21 @@ function normalizeNativeImporterAdapterCoverage(value = {}, context = {}) {
|
|
|
4347
4966
|
capabilities,
|
|
4348
4967
|
sourceRanges,
|
|
4349
4968
|
generatedRanges
|
|
4350
|
-
})
|
|
4969
|
+
})
|
|
4970
|
+
});
|
|
4971
|
+
const observed = normalizeNativeImporterAdapterObservedCoverage(value.observed, declared);
|
|
4972
|
+
const effective = effectiveNativeImporterAdapterCoverage(declared, observed);
|
|
4973
|
+
return Object.freeze({
|
|
4974
|
+
...effective,
|
|
4975
|
+
declared,
|
|
4976
|
+
observed,
|
|
4351
4977
|
notes: uniqueStrings(value.notes ?? inferredAdapterCoverageNotes(context, {
|
|
4352
4978
|
exactAst,
|
|
4353
4979
|
sourceRanges,
|
|
4354
4980
|
generatedRanges,
|
|
4355
4981
|
diagnostics
|
|
4356
|
-
}))
|
|
4982
|
+
})),
|
|
4983
|
+
capabilityEvidence: nativeImporterAdapterCapabilityEvidence(declared, observed, effective)
|
|
4357
4984
|
});
|
|
4358
4985
|
}
|
|
4359
4986
|
|
|
@@ -4363,31 +4990,297 @@ function observeNativeImporterAdapterCoverage(coverage, parseResult = {}, contex
|
|
|
4363
4990
|
const sourceMapMappings = parseResult.sourceMaps?.flatMap((sourceMap) => sourceMap.mappings ?? []) ?? parseResult.mappings ?? [];
|
|
4364
4991
|
const semanticIndex = parseResult.semanticIndex;
|
|
4365
4992
|
const semanticSymbols = semanticIndex?.symbols?.length ?? 0;
|
|
4366
|
-
const
|
|
4367
|
-
const
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
|
|
4375
|
-
}, {});
|
|
4993
|
+
const declared = coverage.declared ?? adapterCoverageSnapshotFromSummary(coverage);
|
|
4994
|
+
const observed = observeNativeImporterAdapterCoverageDetails(parseResult, context, {
|
|
4995
|
+
declared,
|
|
4996
|
+
nodeList,
|
|
4997
|
+
sourceMapMappings,
|
|
4998
|
+
semanticIndex,
|
|
4999
|
+
semanticSymbols
|
|
5000
|
+
});
|
|
5001
|
+
const effective = effectiveNativeImporterAdapterCoverage(declared, observed);
|
|
4376
5002
|
return Object.freeze({
|
|
4377
5003
|
...coverage,
|
|
4378
|
-
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
|
|
4382
|
-
|
|
4383
|
-
|
|
4384
|
-
|
|
4385
|
-
|
|
4386
|
-
|
|
4387
|
-
|
|
4388
|
-
|
|
4389
|
-
|
|
4390
|
-
|
|
5004
|
+
...effective,
|
|
5005
|
+
declared,
|
|
5006
|
+
observed,
|
|
5007
|
+
capabilityEvidence: nativeImporterAdapterCapabilityEvidence(declared, observed, effective)
|
|
5008
|
+
});
|
|
5009
|
+
}
|
|
5010
|
+
|
|
5011
|
+
function adapterCoverageSnapshotFromSummary(coverage = {}) {
|
|
5012
|
+
return freezeNativeImporterAdapterCoverageSnapshot({
|
|
5013
|
+
exactness: coverage.exactness ?? 'unknown',
|
|
5014
|
+
exactAst: coverage.exactAst,
|
|
5015
|
+
tokens: coverage.tokens,
|
|
5016
|
+
trivia: coverage.trivia,
|
|
5017
|
+
diagnostics: coverage.diagnostics,
|
|
5018
|
+
sourceRanges: coverage.sourceRanges,
|
|
5019
|
+
generatedRanges: coverage.generatedRanges,
|
|
5020
|
+
semanticCoverage: coverage.semanticCoverage
|
|
5021
|
+
});
|
|
5022
|
+
}
|
|
5023
|
+
|
|
5024
|
+
function freezeNativeImporterAdapterCoverageSnapshot(value = {}) {
|
|
5025
|
+
return Object.freeze({
|
|
5026
|
+
exactness: String(value.exactness ?? 'unknown'),
|
|
5027
|
+
exactAst: Boolean(value.exactAst),
|
|
5028
|
+
tokens: Boolean(value.tokens),
|
|
5029
|
+
trivia: Boolean(value.trivia),
|
|
5030
|
+
diagnostics: Boolean(value.diagnostics),
|
|
5031
|
+
sourceRanges: Boolean(value.sourceRanges),
|
|
5032
|
+
generatedRanges: Boolean(value.generatedRanges),
|
|
5033
|
+
semanticCoverage: normalizeNativeImporterSemanticCoverage(value.semanticCoverage, {})
|
|
5034
|
+
});
|
|
5035
|
+
}
|
|
5036
|
+
|
|
5037
|
+
function normalizeNativeImporterAdapterObservedCoverage(value = {}, declared = {}) {
|
|
5038
|
+
const diagnostics = Number(value.diagnostics ?? value.parserDiagnostics ?? 0) || 0;
|
|
5039
|
+
const semanticCoverage = normalizeNativeImporterSemanticCoverage({
|
|
5040
|
+
...(value.semanticCoverage ?? {}),
|
|
5041
|
+
declarations: value.semanticCoverage?.declarations ?? value.declarations,
|
|
5042
|
+
symbols: value.semanticCoverage?.symbols ?? value.symbols,
|
|
5043
|
+
references: value.semanticCoverage?.references ?? value.references,
|
|
5044
|
+
types: value.semanticCoverage?.types ?? value.types,
|
|
5045
|
+
controlFlow: value.semanticCoverage?.controlFlow ?? value.controlFlow
|
|
5046
|
+
}, {});
|
|
5047
|
+
const nativeAstNodes = Number(value.nativeAstNodes ?? 0) || 0;
|
|
5048
|
+
const exactness = String(value.exactness ?? observedAdapterExactness(declared, nativeAstNodes));
|
|
5049
|
+
return Object.freeze({
|
|
5050
|
+
exactness,
|
|
5051
|
+
exactAst: Boolean(value.exactAst ?? (declared.exactAst && nativeAstNodes > 0)),
|
|
5052
|
+
tokens: Boolean(value.tokens),
|
|
5053
|
+
tokenCount: Number(value.tokenCount ?? 0) || 0,
|
|
5054
|
+
trivia: Boolean(value.trivia),
|
|
5055
|
+
triviaCount: Number(value.triviaCount ?? 0) || 0,
|
|
5056
|
+
diagnostics,
|
|
5057
|
+
parserDiagnostics: diagnostics,
|
|
5058
|
+
diagnosticErrors: Number(value.diagnosticErrors ?? 0) || 0,
|
|
5059
|
+
diagnosticWarnings: Number(value.diagnosticWarnings ?? 0) || 0,
|
|
5060
|
+
diagnosticInfos: Number(value.diagnosticInfos ?? 0) || 0,
|
|
5061
|
+
losses: Number(value.losses ?? 0) || 0,
|
|
5062
|
+
nativeAstNodes,
|
|
5063
|
+
semanticSymbols: Number(value.semanticSymbols ?? 0) || 0,
|
|
5064
|
+
semanticReferences: Number(value.semanticReferences ?? 0) || 0,
|
|
5065
|
+
semanticTypes: Number(value.semanticTypes ?? 0) || 0,
|
|
5066
|
+
semanticControlFlow: Number(value.semanticControlFlow ?? 0) || 0,
|
|
5067
|
+
references: Boolean(value.references ?? semanticCoverage.references),
|
|
5068
|
+
types: Boolean(value.types ?? semanticCoverage.types),
|
|
5069
|
+
controlFlow: Boolean(value.controlFlow ?? semanticCoverage.controlFlow),
|
|
5070
|
+
sourceMapMappings: Number(value.sourceMapMappings ?? 0) || 0,
|
|
5071
|
+
sourceRanges: Boolean(value.sourceRanges),
|
|
5072
|
+
sourceRangeNodes: Number(value.sourceRangeNodes ?? 0) || 0,
|
|
5073
|
+
sourceRangeMappings: Number(value.sourceRangeMappings ?? 0) || 0,
|
|
5074
|
+
generatedRanges: Boolean(value.generatedRanges),
|
|
5075
|
+
generatedRangeMappings: Number(value.generatedRangeMappings ?? 0) || 0,
|
|
5076
|
+
semanticCoverage
|
|
5077
|
+
});
|
|
5078
|
+
}
|
|
5079
|
+
|
|
5080
|
+
function observeNativeImporterAdapterCoverageDetails(parseResult = {}, context = {}, observedContext = {}) {
|
|
5081
|
+
const declared = observedContext.declared ?? {};
|
|
5082
|
+
const nodeList = observedContext.nodeList ?? Object.values(parseResult.nativeAst?.nodes ?? parseResult.nodes ?? {});
|
|
5083
|
+
const sourceMapMappings = observedContext.sourceMapMappings
|
|
5084
|
+
?? parseResult.sourceMaps?.flatMap((sourceMap) => sourceMap.mappings ?? [])
|
|
5085
|
+
?? parseResult.mappings
|
|
5086
|
+
?? [];
|
|
5087
|
+
const semanticIndex = observedContext.semanticIndex ?? parseResult.semanticIndex;
|
|
5088
|
+
const semanticSymbols = observedContext.semanticSymbols ?? semanticIndex?.symbols?.length ?? 0;
|
|
5089
|
+
const diagnostics = context.diagnostics ?? [];
|
|
5090
|
+
const diagnosticErrors = diagnostics.filter((diagnostic) => diagnostic.severity === 'error').length;
|
|
5091
|
+
const diagnosticWarnings = diagnostics.filter((diagnostic) => diagnostic.severity === 'warning').length;
|
|
5092
|
+
const diagnosticInfos = diagnostics.filter((diagnostic) => diagnostic.severity === 'info').length;
|
|
5093
|
+
const sourceRangeNodes = nodeList.filter((node) => Boolean(node?.span)).length;
|
|
5094
|
+
const sourceRangeMappings = sourceMapMappings.filter((mapping) => Boolean(mapping?.sourceSpan)).length;
|
|
5095
|
+
const generatedRangeMappings = sourceMapMappings.filter((mapping) => Boolean(mapping?.generatedSpan)).length;
|
|
5096
|
+
const preservation = adapterCoverageSourcePreservation(parseResult);
|
|
5097
|
+
const tokenCount = preservation?.summary?.tokens ?? preservation?.tokens?.length ?? 0;
|
|
5098
|
+
const triviaCount = preservation?.summary?.trivia ?? preservation?.trivia?.length ?? 0;
|
|
5099
|
+
const semanticEvidence = observeNativeImporterSemanticEvidence(semanticIndex);
|
|
5100
|
+
const semanticCoverage = normalizeNativeImporterSemanticCoverage({
|
|
5101
|
+
level: maxSemanticCoverageLevel(
|
|
5102
|
+
semanticSymbols || semanticEvidence.declarations
|
|
5103
|
+
? 'declaration-index'
|
|
5104
|
+
: 'native-ast',
|
|
5105
|
+
semanticEvidence.references || semanticEvidence.types || semanticEvidence.controlFlow
|
|
5106
|
+
? 'semantic-index'
|
|
5107
|
+
: semanticSymbols ? 'declaration-index' : 'native-ast'
|
|
5108
|
+
),
|
|
5109
|
+
declarations: semanticSymbols > 0 || semanticEvidence.declarations > 0,
|
|
5110
|
+
symbols: semanticSymbols > 0,
|
|
5111
|
+
references: semanticEvidence.references > 0,
|
|
5112
|
+
types: semanticEvidence.types > 0,
|
|
5113
|
+
controlFlow: semanticEvidence.controlFlow > 0
|
|
5114
|
+
}, {});
|
|
5115
|
+
return normalizeNativeImporterAdapterObservedCoverage({
|
|
5116
|
+
exactness: observedAdapterExactness(declared, nodeList.length),
|
|
5117
|
+
exactAst: Boolean(declared.exactAst && nodeList.length > 0),
|
|
5118
|
+
tokens: tokenCount > 0,
|
|
5119
|
+
tokenCount,
|
|
5120
|
+
trivia: triviaCount > 0,
|
|
5121
|
+
triviaCount,
|
|
5122
|
+
diagnostics: diagnostics.length,
|
|
5123
|
+
parserDiagnostics: diagnostics.length,
|
|
5124
|
+
diagnosticErrors,
|
|
5125
|
+
diagnosticWarnings,
|
|
5126
|
+
diagnosticInfos,
|
|
5127
|
+
losses: context.losses?.length ?? 0,
|
|
5128
|
+
nativeAstNodes: nodeList.length,
|
|
5129
|
+
semanticSymbols,
|
|
5130
|
+
semanticReferences: semanticEvidence.references,
|
|
5131
|
+
semanticTypes: semanticEvidence.types,
|
|
5132
|
+
semanticControlFlow: semanticEvidence.controlFlow,
|
|
5133
|
+
references: semanticEvidence.references > 0,
|
|
5134
|
+
types: semanticEvidence.types > 0,
|
|
5135
|
+
controlFlow: semanticEvidence.controlFlow > 0,
|
|
5136
|
+
sourceMapMappings: sourceMapMappings.length,
|
|
5137
|
+
sourceRanges: sourceRangeNodes > 0 || sourceRangeMappings > 0,
|
|
5138
|
+
sourceRangeNodes,
|
|
5139
|
+
sourceRangeMappings,
|
|
5140
|
+
generatedRanges: generatedRangeMappings > 0,
|
|
5141
|
+
generatedRangeMappings,
|
|
5142
|
+
semanticCoverage
|
|
5143
|
+
}, declared);
|
|
5144
|
+
}
|
|
5145
|
+
|
|
5146
|
+
function adapterCoverageSourcePreservation(parseResult = {}) {
|
|
5147
|
+
return parseResult.sourcePreservation
|
|
5148
|
+
?? parseResult.nativeAst?.metadata?.sourcePreservation
|
|
5149
|
+
?? parseResult.nativeAstMetadata?.sourcePreservation
|
|
5150
|
+
?? parseResult.metadata?.sourcePreservation;
|
|
5151
|
+
}
|
|
5152
|
+
|
|
5153
|
+
function observeNativeImporterSemanticEvidence(semanticIndex = {}) {
|
|
5154
|
+
const occurrences = semanticIndex?.occurrences ?? [];
|
|
5155
|
+
const relations = semanticIndex?.relations ?? [];
|
|
5156
|
+
const facts = semanticIndex?.facts ?? [];
|
|
5157
|
+
const symbols = semanticIndex?.symbols ?? [];
|
|
5158
|
+
const referenceRelations = relations.filter((relation) => semanticPredicateMatches(relation?.predicate, ['reference', 'call', 'read', 'write', 'use']));
|
|
5159
|
+
const typeFacts = facts.filter((fact) => semanticPredicateMatches(fact?.predicate, ['type', 'declaredtype', 'inferredtype', 'typeof']));
|
|
5160
|
+
const typedSymbols = symbols.filter((symbol) => Boolean(symbol?.declaredType ?? symbol?.inferredType ?? symbol?.typeId ?? symbol?.valueType));
|
|
5161
|
+
const controlFlowRecords = [
|
|
5162
|
+
...relations.filter((relation) => semanticPredicateMatches(relation?.predicate, ['controlflow', 'cfg', 'flow'])),
|
|
5163
|
+
...facts.filter((fact) => semanticPredicateMatches(fact?.predicate, ['controlflow', 'cfg', 'flow']))
|
|
5164
|
+
];
|
|
5165
|
+
return {
|
|
5166
|
+
declarations: occurrences.filter((occurrence) => occurrence?.role === 'definition' || occurrence?.role === 'declaration').length,
|
|
5167
|
+
references: occurrences.filter((occurrence) => {
|
|
5168
|
+
const role = String(occurrence?.role ?? '').toLowerCase();
|
|
5169
|
+
return role && role !== 'definition' && role !== 'declaration';
|
|
5170
|
+
}).length + referenceRelations.length,
|
|
5171
|
+
types: typeFacts.length + typedSymbols.length,
|
|
5172
|
+
controlFlow: controlFlowRecords.length
|
|
5173
|
+
};
|
|
5174
|
+
}
|
|
5175
|
+
|
|
5176
|
+
function semanticPredicateMatches(value, fragments) {
|
|
5177
|
+
const predicate = String(value ?? '').toLowerCase().replace(/[^a-z0-9]+/g, '');
|
|
5178
|
+
return fragments.some((fragment) => predicate.includes(fragment));
|
|
5179
|
+
}
|
|
5180
|
+
|
|
5181
|
+
function observedAdapterExactness(declared = {}, nativeAstNodes = 0) {
|
|
5182
|
+
if (!nativeAstNodes) return 'unknown';
|
|
5183
|
+
if (declared.exactAst) return declared.exactness ?? 'exact-parser-ast';
|
|
5184
|
+
return 'adapter-reported-native-ast';
|
|
5185
|
+
}
|
|
5186
|
+
|
|
5187
|
+
function effectiveNativeImporterAdapterCoverage(declared, observed) {
|
|
5188
|
+
const semanticCoverage = normalizeNativeImporterSemanticCoverage({
|
|
5189
|
+
level: maxSemanticCoverageLevel(declared.semanticCoverage?.level, observed.semanticCoverage?.level),
|
|
5190
|
+
declarations: declared.semanticCoverage?.declarations || observed.semanticCoverage?.declarations,
|
|
5191
|
+
symbols: declared.semanticCoverage?.symbols || observed.semanticCoverage?.symbols,
|
|
5192
|
+
references: declared.semanticCoverage?.references || observed.semanticCoverage?.references,
|
|
5193
|
+
types: declared.semanticCoverage?.types || observed.semanticCoverage?.types,
|
|
5194
|
+
controlFlow: declared.semanticCoverage?.controlFlow || observed.semanticCoverage?.controlFlow
|
|
5195
|
+
}, {});
|
|
5196
|
+
return freezeNativeImporterAdapterCoverageSnapshot({
|
|
5197
|
+
exactness: effectiveAdapterExactness(declared, observed),
|
|
5198
|
+
exactAst: declared.exactAst || observed.exactAst,
|
|
5199
|
+
tokens: declared.tokens || observed.tokens,
|
|
5200
|
+
trivia: declared.trivia || observed.trivia,
|
|
5201
|
+
diagnostics: declared.diagnostics || observed.parserDiagnostics > 0,
|
|
5202
|
+
sourceRanges: declared.sourceRanges || observed.sourceRanges,
|
|
5203
|
+
generatedRanges: declared.generatedRanges || observed.generatedRanges,
|
|
5204
|
+
semanticCoverage
|
|
5205
|
+
});
|
|
5206
|
+
}
|
|
5207
|
+
|
|
5208
|
+
function effectiveAdapterExactness(declared, observed) {
|
|
5209
|
+
if (declared.exactAst || observed.exactAst) return declared.exactness ?? 'exact-parser-ast';
|
|
5210
|
+
if (observed.nativeAstNodes > 0) return observed.exactness ?? 'adapter-reported-native-ast';
|
|
5211
|
+
return declared.exactness ?? 'unknown';
|
|
5212
|
+
}
|
|
5213
|
+
|
|
5214
|
+
function nativeImporterAdapterCapabilityEvidence(declared, observed, effective) {
|
|
5215
|
+
const capabilityRows = [
|
|
5216
|
+
adapterCoverageCapabilityRow('exactAst', declared.exactAst, observed.exactAst, effective.exactAst, observed.nativeAstNodes),
|
|
5217
|
+
adapterCoverageCapabilityRow('tokens', declared.tokens, observed.tokens, effective.tokens, observed.tokenCount),
|
|
5218
|
+
adapterCoverageCapabilityRow('trivia', declared.trivia, observed.trivia, effective.trivia, observed.triviaCount),
|
|
5219
|
+
adapterCoverageCapabilityRow('parserDiagnostics', declared.diagnostics, observed.parserDiagnostics > 0, effective.diagnostics, observed.parserDiagnostics),
|
|
5220
|
+
adapterCoverageCapabilityRow('sourceRanges', declared.sourceRanges, observed.sourceRanges, effective.sourceRanges, observed.sourceRangeNodes + observed.sourceRangeMappings),
|
|
5221
|
+
adapterCoverageCapabilityRow('generatedRanges', declared.generatedRanges, observed.generatedRanges, effective.generatedRanges, observed.generatedRangeMappings),
|
|
5222
|
+
adapterCoverageCapabilityRow('semanticDeclarations', declared.semanticCoverage.declarations, observed.semanticCoverage.declarations, effective.semanticCoverage.declarations, observed.semanticSymbols),
|
|
5223
|
+
adapterCoverageCapabilityRow('semanticSymbols', declared.semanticCoverage.symbols, observed.semanticCoverage.symbols, effective.semanticCoverage.symbols, observed.semanticSymbols),
|
|
5224
|
+
adapterCoverageCapabilityRow('references', declared.semanticCoverage.references, observed.semanticCoverage.references, effective.semanticCoverage.references, observed.semanticReferences),
|
|
5225
|
+
adapterCoverageCapabilityRow('types', declared.semanticCoverage.types, observed.semanticCoverage.types, effective.semanticCoverage.types, observed.semanticTypes),
|
|
5226
|
+
adapterCoverageCapabilityRow('controlFlow', declared.semanticCoverage.controlFlow, observed.semanticCoverage.controlFlow, effective.semanticCoverage.controlFlow, observed.semanticControlFlow)
|
|
5227
|
+
];
|
|
5228
|
+
const reviewCapabilities = new Set(['exactAst', 'tokens', 'trivia', 'parserDiagnostics', 'sourceRanges', 'generatedRanges', 'references', 'types', 'controlFlow']);
|
|
5229
|
+
return Object.freeze({
|
|
5230
|
+
declared,
|
|
5231
|
+
observed,
|
|
5232
|
+
effective,
|
|
5233
|
+
capabilities: Object.freeze(capabilityRows),
|
|
5234
|
+
gaps: Object.freeze(capabilityRows.filter((row) => reviewCapabilities.has(row.capability) && !row.effective).map((row) => row.capability)),
|
|
5235
|
+
declaredOnly: Object.freeze(capabilityRows.filter((row) => row.declared && !row.observed).map((row) => row.capability)),
|
|
5236
|
+
observedOnly: Object.freeze(capabilityRows.filter((row) => !row.declared && row.observed).map((row) => row.capability)),
|
|
5237
|
+
parserDiagnostics: Object.freeze({
|
|
5238
|
+
declared: declared.diagnostics,
|
|
5239
|
+
observed: observed.parserDiagnostics > 0,
|
|
5240
|
+
count: observed.parserDiagnostics,
|
|
5241
|
+
errors: observed.diagnosticErrors,
|
|
5242
|
+
warnings: observed.diagnosticWarnings,
|
|
5243
|
+
infos: observed.diagnosticInfos
|
|
5244
|
+
}),
|
|
5245
|
+
sourceRanges: Object.freeze({
|
|
5246
|
+
declared: declared.sourceRanges,
|
|
5247
|
+
observed: observed.sourceRanges,
|
|
5248
|
+
nativeAstNodes: observed.nativeAstNodes,
|
|
5249
|
+
sourceRangeNodes: observed.sourceRangeNodes,
|
|
5250
|
+
sourceMapMappings: observed.sourceMapMappings,
|
|
5251
|
+
sourceRangeMappings: observed.sourceRangeMappings,
|
|
5252
|
+
generatedRangeMappings: observed.generatedRangeMappings
|
|
5253
|
+
}),
|
|
5254
|
+
tokensTrivia: Object.freeze({
|
|
5255
|
+
tokens: Object.freeze({ declared: declared.tokens, observed: observed.tokens, count: observed.tokenCount }),
|
|
5256
|
+
trivia: Object.freeze({ declared: declared.trivia, observed: observed.trivia, count: observed.triviaCount })
|
|
5257
|
+
}),
|
|
5258
|
+
semantic: Object.freeze({
|
|
5259
|
+
level: Object.freeze({
|
|
5260
|
+
declared: declared.semanticCoverage.level,
|
|
5261
|
+
observed: observed.semanticCoverage.level,
|
|
5262
|
+
effective: effective.semanticCoverage.level
|
|
5263
|
+
}),
|
|
5264
|
+
declarations: adapterCoverageCapabilityRow('semanticDeclarations', declared.semanticCoverage.declarations, observed.semanticCoverage.declarations, effective.semanticCoverage.declarations, observed.semanticSymbols),
|
|
5265
|
+
symbols: adapterCoverageCapabilityRow('semanticSymbols', declared.semanticCoverage.symbols, observed.semanticCoverage.symbols, effective.semanticCoverage.symbols, observed.semanticSymbols),
|
|
5266
|
+
references: adapterCoverageCapabilityRow('references', declared.semanticCoverage.references, observed.semanticCoverage.references, effective.semanticCoverage.references, observed.semanticReferences),
|
|
5267
|
+
types: adapterCoverageCapabilityRow('types', declared.semanticCoverage.types, observed.semanticCoverage.types, effective.semanticCoverage.types, observed.semanticTypes),
|
|
5268
|
+
controlFlow: adapterCoverageCapabilityRow('controlFlow', declared.semanticCoverage.controlFlow, observed.semanticCoverage.controlFlow, effective.semanticCoverage.controlFlow, observed.semanticControlFlow)
|
|
5269
|
+
})
|
|
5270
|
+
});
|
|
5271
|
+
}
|
|
5272
|
+
|
|
5273
|
+
function adapterCoverageCapabilityRow(capability, declared, observed, effective, count = 0) {
|
|
5274
|
+
const status = declared && observed
|
|
5275
|
+
? 'declared-and-observed'
|
|
5276
|
+
: declared ? 'declared-unobserved' : observed ? 'observed-undeclared' : 'absent';
|
|
5277
|
+
return Object.freeze({
|
|
5278
|
+
capability,
|
|
5279
|
+
declared: Boolean(declared),
|
|
5280
|
+
observed: Boolean(observed),
|
|
5281
|
+
effective: Boolean(effective),
|
|
5282
|
+
count: Number(count ?? 0) || 0,
|
|
5283
|
+
status
|
|
4391
5284
|
});
|
|
4392
5285
|
}
|
|
4393
5286
|
|