@shapeshift-labs/frontier-lang-compiler 0.2.12 → 0.2.14
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 +20 -0
- package/bench/smoke.mjs +13 -0
- package/dist/index.d.ts +205 -3
- package/dist/index.js +721 -30
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -57,6 +57,7 @@ Ask the compiler what is actually covered before sending native imports into a m
|
|
|
57
57
|
```js
|
|
58
58
|
import {
|
|
59
59
|
createNativeImportCoverageMatrix,
|
|
60
|
+
createProjectionTargetLossMatrix,
|
|
60
61
|
importNativeSource
|
|
61
62
|
} from '@shapeshift-labs/frontier-lang-compiler';
|
|
62
63
|
|
|
@@ -71,8 +72,22 @@ const python = matrix.languages.find((entry) => entry.language === 'python');
|
|
|
71
72
|
|
|
72
73
|
console.log(python.imports.readiness); // scanner imports are intentionally review-required
|
|
73
74
|
console.log(python.parserAdapters); // host-owned exact parsers such as LibCST can be injected
|
|
75
|
+
|
|
76
|
+
const projectionMatrix = createProjectionTargetLossMatrix({ imports: [imported] });
|
|
77
|
+
const pythonProjection = projectionMatrix.languages.find((entry) => entry.language === 'python');
|
|
78
|
+
|
|
79
|
+
console.log(pythonProjection.sourceProjection.exactSource.lossClass); // "exactSourceProjection"
|
|
80
|
+
console.log(pythonProjection.sourceProjection.stubs.lossClass); // "nativeSourceStubs"
|
|
81
|
+
console.log(pythonProjection.targets.find((entry) => entry.target === 'rust').lossClass); // "missingAdapter"
|
|
74
82
|
```
|
|
75
83
|
|
|
84
|
+
The projection target matrix separates four runtime/API classes:
|
|
85
|
+
|
|
86
|
+
- `exactSourceProjection`: exact source can be emitted when the import carries matching source text or source-preservation evidence.
|
|
87
|
+
- `nativeSourceStubs`: declaration stubs can be emitted, but bodies, resolved types, and executable semantics are review-required.
|
|
88
|
+
- `unsupportedTargetFeatures`: a target slot exists, but the source profile or import evidence declares features such as macros, preprocessors, dynamic runtime behavior, generated code, unsupported syntax, or unresolved inference that this facade cannot prove lossless.
|
|
89
|
+
- `missingAdapter`: no native-to-target projection adapter is declared; preserve or stub the original source language instead, or inject host-owned parser/semantic adapter evidence.
|
|
90
|
+
|
|
76
91
|
Preserve exact native source text, token/trivia hashes, comments, whitespace, and source directives as evidence. This does not claim full semantic understanding; it keeps round-trip material available while exact parser adapters catch up:
|
|
77
92
|
|
|
78
93
|
```js
|
|
@@ -171,6 +186,9 @@ const project = await importNativeProject({
|
|
|
171
186
|
console.log(imported.universalAst.sourceMaps.length);
|
|
172
187
|
console.log(project.semanticIndex.symbols.length);
|
|
173
188
|
console.log(imported.adapter.coverage.exactness);
|
|
189
|
+
console.log(imported.adapter.coverage.capabilityEvidence.declared.exactness);
|
|
190
|
+
console.log(imported.adapter.coverage.capabilityEvidence.observed.sourceRanges);
|
|
191
|
+
console.log(imported.adapter.coverage.capabilityEvidence.gaps);
|
|
174
192
|
console.log(imported.adapter.coverage.semanticCoverage.level);
|
|
175
193
|
console.log(project.metadata.sourcePreservationSummary.total);
|
|
176
194
|
```
|
|
@@ -184,6 +202,8 @@ The built-in adapter factories are dependency-light wrappers for caller-owned pa
|
|
|
184
202
|
|
|
185
203
|
Adapter summaries include a structured `coverage` record so merge queues can distinguish exact parser AST imports from declaration scans. The record declares exactness, parser token/trivia support, diagnostics support, source-range and generated-range support, and semantic coverage. Built-in wrappers normalize native AST/CST nodes and declaration-level semantic indexes; they do not claim resolved references, types, control flow, generated ranges, or token/trivia fidelity unless the host adapter supplies that evidence.
|
|
186
204
|
|
|
205
|
+
Coverage records also keep declared, observed, and effective capability evidence separate. `coverage.capabilityEvidence.gaps` highlights missing exact AST, token/trivia, parser diagnostics, source range, generated range, reference, type, and control-flow evidence for the current adapter/import. `observedOnly` means the import produced evidence the adapter did not declare, while `declaredOnly` means the adapter declared support that this run did not exercise.
|
|
206
|
+
|
|
187
207
|
## Related Packages
|
|
188
208
|
|
|
189
209
|
The published Frontier package family is generated from one shared package catalog so READMEs stay in sync across packages:
|
package/bench/smoke.mjs
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
compileFrontierSource,
|
|
4
4
|
createEstreeNativeImporterAdapter,
|
|
5
5
|
createNativeImportCoverageMatrix,
|
|
6
|
+
createProjectionTargetLossMatrix,
|
|
6
7
|
createNativeSourcePreservation,
|
|
7
8
|
createSemanticImportSidecar,
|
|
8
9
|
importNativeSource,
|
|
@@ -68,6 +69,10 @@ const matrixStart = performance.now();
|
|
|
68
69
|
const coverageMatrix = createNativeImportCoverageMatrix({ imports: nativeImportResults });
|
|
69
70
|
const matrixDurationMs = performance.now() - matrixStart;
|
|
70
71
|
|
|
72
|
+
const projectionMatrixStart = performance.now();
|
|
73
|
+
const projectionLossMatrix = createProjectionTargetLossMatrix({ imports: nativeImportResults });
|
|
74
|
+
const projectionMatrixDurationMs = performance.now() - projectionMatrixStart;
|
|
75
|
+
|
|
71
76
|
const preservationStart = performance.now();
|
|
72
77
|
const preservationRecords = nativeImportResults.map((imported) => imported.metadata.sourcePreservation ?? createNativeSourcePreservation({
|
|
73
78
|
language: imported.language,
|
|
@@ -96,7 +101,15 @@ console.log(JSON.stringify({
|
|
|
96
101
|
nativeImportDurationMs: Number(importDurationMs.toFixed(2)),
|
|
97
102
|
coverageMatrixLanguages: coverageMatrix.summary.languages,
|
|
98
103
|
coverageMatrixImports: coverageMatrix.summary.imports,
|
|
104
|
+
adapterCoverageSummaries: coverageMatrix.summary.adapterCoverage.total,
|
|
105
|
+
adapterCoverageSourceRanges: coverageMatrix.summary.adapterCoverage.effective.sourceRanges ?? 0,
|
|
106
|
+
adapterCoverageTokenGaps: coverageMatrix.summary.adapterCoverage.gaps.tokens ?? 0,
|
|
107
|
+
adapterCoverageReferenceGaps: coverageMatrix.summary.adapterCoverage.gaps.references ?? 0,
|
|
99
108
|
coverageMatrixDurationMs: Number(matrixDurationMs.toFixed(2)),
|
|
109
|
+
projectionMatrixLanguages: projectionLossMatrix.summary.languages,
|
|
110
|
+
projectionMatrixMissingAdapters: projectionLossMatrix.summary.missingAdapters,
|
|
111
|
+
projectionMatrixUnsupportedTargetFeatures: projectionLossMatrix.summary.unsupportedTargetFeatures,
|
|
112
|
+
projectionMatrixDurationMs: Number(projectionMatrixDurationMs.toFixed(2)),
|
|
100
113
|
sourcePreservationRecords: preservationRecords.length,
|
|
101
114
|
sourcePreservationTokens: preservationTokens,
|
|
102
115
|
sourcePreservationDurationMs: Number(preservationDurationMs.toFixed(2)),
|
package/dist/index.d.ts
CHANGED
|
@@ -168,22 +168,45 @@ export interface NativeImportLanguageProfile {
|
|
|
168
168
|
readonly extensions: readonly string[];
|
|
169
169
|
readonly supportsLightweightScan: boolean;
|
|
170
170
|
readonly parserAdapters: readonly string[];
|
|
171
|
-
readonly projectionTargets: readonly FrontierCompileTarget[];
|
|
171
|
+
readonly projectionTargets: readonly (FrontierCompileTarget | string)[];
|
|
172
172
|
readonly knownLossKinds: readonly NativeImportKnownLossKind[];
|
|
173
173
|
readonly defaultReadiness: SemanticMergeReadiness;
|
|
174
174
|
readonly notes: readonly string[];
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
+
export interface NativeImporterAdapterCoverageAggregate {
|
|
178
|
+
readonly total: number;
|
|
179
|
+
readonly declared: Readonly<Record<string, number>>;
|
|
180
|
+
readonly observed: Readonly<Record<string, number>>;
|
|
181
|
+
readonly effective: Readonly<Record<string, number>>;
|
|
182
|
+
readonly gaps: Readonly<Record<string, number>>;
|
|
183
|
+
readonly declaredOnly: Readonly<Record<string, number>>;
|
|
184
|
+
readonly observedOnly: Readonly<Record<string, number>>;
|
|
185
|
+
readonly summaries: readonly {
|
|
186
|
+
readonly adapterId?: string;
|
|
187
|
+
readonly language?: FrontierSourceLanguage | string;
|
|
188
|
+
readonly parser?: string;
|
|
189
|
+
readonly exactness?: NativeImporterAdapterExactness;
|
|
190
|
+
readonly declared: readonly string[];
|
|
191
|
+
readonly observed: readonly string[];
|
|
192
|
+
readonly effective: readonly string[];
|
|
193
|
+
readonly gaps: readonly string[];
|
|
194
|
+
readonly declaredOnly: readonly string[];
|
|
195
|
+
readonly observedOnly: readonly string[];
|
|
196
|
+
}[];
|
|
197
|
+
}
|
|
198
|
+
|
|
177
199
|
export interface NativeImportCoverageLanguage {
|
|
178
200
|
readonly language: FrontierSourceLanguage;
|
|
179
201
|
readonly aliases: readonly string[];
|
|
180
202
|
readonly extensions: readonly string[];
|
|
181
203
|
readonly supportsLightweightScan: boolean;
|
|
182
204
|
readonly parserAdapters: readonly string[];
|
|
183
|
-
readonly projectionTargets: readonly FrontierCompileTarget[];
|
|
205
|
+
readonly projectionTargets: readonly (FrontierCompileTarget | string)[];
|
|
184
206
|
readonly knownLossKinds: readonly NativeImportKnownLossKind[];
|
|
185
207
|
readonly defaultReadiness: SemanticMergeReadiness;
|
|
186
208
|
readonly notes: readonly string[];
|
|
209
|
+
readonly adapterCoverage: NativeImporterAdapterCoverageAggregate;
|
|
187
210
|
readonly imports: {
|
|
188
211
|
readonly total: number;
|
|
189
212
|
readonly parsers: readonly string[];
|
|
@@ -214,9 +237,11 @@ export interface NativeImportCoverageMatrix {
|
|
|
214
237
|
readonly losses: number;
|
|
215
238
|
readonly byReadiness: Readonly<Record<string, number>>;
|
|
216
239
|
readonly lossKinds: Readonly<Record<string, number>>;
|
|
240
|
+
readonly adapterCoverage: NativeImporterAdapterCoverageAggregate;
|
|
217
241
|
};
|
|
218
242
|
readonly metadata: {
|
|
219
243
|
readonly compileTargets: readonly FrontierCompileTarget[];
|
|
244
|
+
readonly projectionTargetLossClasses: readonly ProjectionTargetLossClass[];
|
|
220
245
|
readonly note: string;
|
|
221
246
|
};
|
|
222
247
|
}
|
|
@@ -228,6 +253,96 @@ export interface NativeImportCoverageMatrixOptions {
|
|
|
228
253
|
readonly generatedAt?: number;
|
|
229
254
|
}
|
|
230
255
|
|
|
256
|
+
export type ProjectionTargetLossClass =
|
|
257
|
+
| 'exactSourceProjection'
|
|
258
|
+
| 'nativeSourceStubs'
|
|
259
|
+
| 'unsupportedTargetFeatures'
|
|
260
|
+
| 'missingAdapter'
|
|
261
|
+
| string;
|
|
262
|
+
|
|
263
|
+
export interface ProjectionSourceProjectionCoverage {
|
|
264
|
+
readonly lossClass: ProjectionTargetLossClass;
|
|
265
|
+
readonly mode: NativeSourceProjectionMode;
|
|
266
|
+
readonly supported: boolean;
|
|
267
|
+
readonly readiness: SemanticMergeReadiness;
|
|
268
|
+
readonly lossKinds: readonly NativeImportKnownLossKind[];
|
|
269
|
+
readonly categories: readonly NativeImportTaxonomyKind[];
|
|
270
|
+
readonly reason: string;
|
|
271
|
+
readonly evidence: {
|
|
272
|
+
readonly imports: number;
|
|
273
|
+
readonly importsWithExactSource?: number;
|
|
274
|
+
readonly importsWithDeclarations?: number;
|
|
275
|
+
};
|
|
276
|
+
readonly notes: readonly string[];
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
export interface ProjectionTargetCoverageEntry {
|
|
280
|
+
readonly target: FrontierCompileTarget | string;
|
|
281
|
+
readonly lossClass: ProjectionTargetLossClass;
|
|
282
|
+
readonly supported: boolean;
|
|
283
|
+
readonly readiness: SemanticMergeReadiness;
|
|
284
|
+
readonly lossKinds: readonly NativeImportKnownLossKind[];
|
|
285
|
+
readonly categories: readonly NativeImportTaxonomyKind[];
|
|
286
|
+
readonly reason: string;
|
|
287
|
+
readonly adapter?: string;
|
|
288
|
+
readonly notes: readonly string[];
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
export interface ProjectionTargetLanguageCoverage {
|
|
292
|
+
readonly language: FrontierSourceLanguage | string;
|
|
293
|
+
readonly aliases: readonly string[];
|
|
294
|
+
readonly extensions: readonly string[];
|
|
295
|
+
readonly supportsLightweightScan: boolean;
|
|
296
|
+
readonly parserAdapters: readonly string[];
|
|
297
|
+
readonly projectionTargets: readonly (FrontierCompileTarget | string)[];
|
|
298
|
+
readonly knownLossKinds: readonly NativeImportKnownLossKind[];
|
|
299
|
+
readonly defaultReadiness: SemanticMergeReadiness;
|
|
300
|
+
readonly notes: readonly string[];
|
|
301
|
+
readonly sourceProjection: {
|
|
302
|
+
readonly exactSource: ProjectionSourceProjectionCoverage;
|
|
303
|
+
readonly stubs: ProjectionSourceProjectionCoverage;
|
|
304
|
+
};
|
|
305
|
+
readonly targets: readonly ProjectionTargetCoverageEntry[];
|
|
306
|
+
readonly summary: {
|
|
307
|
+
readonly imports: number;
|
|
308
|
+
readonly parserAdapters: number;
|
|
309
|
+
readonly targetEntries: number;
|
|
310
|
+
readonly byLossClass: Readonly<Record<ProjectionTargetLossClass, number>>;
|
|
311
|
+
readonly exactSourceImports: number;
|
|
312
|
+
readonly stubDeclarationImports: number;
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
export interface ProjectionTargetLossMatrix {
|
|
317
|
+
readonly kind: 'frontier.lang.projectionTargetLossMatrix';
|
|
318
|
+
readonly version: 1;
|
|
319
|
+
readonly generatedAt: number;
|
|
320
|
+
readonly languages: readonly ProjectionTargetLanguageCoverage[];
|
|
321
|
+
readonly summary: {
|
|
322
|
+
readonly languages: number;
|
|
323
|
+
readonly targetEntries: number;
|
|
324
|
+
readonly byLossClass: Readonly<Record<ProjectionTargetLossClass, number>>;
|
|
325
|
+
readonly sourceProjectionByLossClass: Readonly<Record<ProjectionTargetLossClass, number>>;
|
|
326
|
+
readonly exactSourceProjection: number;
|
|
327
|
+
readonly nativeSourceStubs: number;
|
|
328
|
+
readonly unsupportedTargetFeatures: number;
|
|
329
|
+
readonly missingAdapters: number;
|
|
330
|
+
};
|
|
331
|
+
readonly metadata: {
|
|
332
|
+
readonly compileTargets: readonly (FrontierCompileTarget | string)[];
|
|
333
|
+
readonly lossClasses: readonly ProjectionTargetLossClass[];
|
|
334
|
+
readonly note: string;
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
export interface ProjectionTargetLossMatrixOptions {
|
|
339
|
+
readonly languages?: readonly NativeImportLanguageProfile[];
|
|
340
|
+
readonly imports?: readonly NativeSourceImportResult[];
|
|
341
|
+
readonly adapters?: readonly NativeImporterAdapter[];
|
|
342
|
+
readonly targets?: readonly (FrontierCompileTarget | string)[];
|
|
343
|
+
readonly generatedAt?: number;
|
|
344
|
+
}
|
|
345
|
+
|
|
231
346
|
export interface NativeImportContractSource {
|
|
232
347
|
readonly id: string;
|
|
233
348
|
readonly language?: FrontierSourceLanguage | string;
|
|
@@ -618,14 +733,97 @@ export interface NativeImporterAdapterSemanticCoverage {
|
|
|
618
733
|
readonly controlFlow: boolean;
|
|
619
734
|
}
|
|
620
735
|
|
|
736
|
+
export interface NativeImporterAdapterCoverageSnapshot {
|
|
737
|
+
readonly exactness: NativeImporterAdapterExactness;
|
|
738
|
+
readonly exactAst: boolean;
|
|
739
|
+
readonly tokens: boolean;
|
|
740
|
+
readonly trivia: boolean;
|
|
741
|
+
readonly diagnostics: boolean;
|
|
742
|
+
readonly sourceRanges: boolean;
|
|
743
|
+
readonly generatedRanges: boolean;
|
|
744
|
+
readonly semanticCoverage: NativeImporterAdapterSemanticCoverage;
|
|
745
|
+
}
|
|
746
|
+
|
|
621
747
|
export interface NativeImporterAdapterCoverageObserved {
|
|
748
|
+
readonly exactness?: NativeImporterAdapterExactness;
|
|
749
|
+
readonly exactAst?: boolean;
|
|
750
|
+
readonly tokens?: boolean;
|
|
751
|
+
readonly tokenCount?: number;
|
|
752
|
+
readonly trivia?: boolean;
|
|
753
|
+
readonly triviaCount?: number;
|
|
622
754
|
readonly diagnostics: number;
|
|
755
|
+
readonly parserDiagnostics?: number;
|
|
756
|
+
readonly diagnosticErrors?: number;
|
|
757
|
+
readonly diagnosticWarnings?: number;
|
|
758
|
+
readonly diagnosticInfos?: number;
|
|
623
759
|
readonly losses: number;
|
|
624
760
|
readonly nativeAstNodes: number;
|
|
625
761
|
readonly semanticSymbols: number;
|
|
762
|
+
readonly semanticReferences?: number;
|
|
763
|
+
readonly semanticTypes?: number;
|
|
764
|
+
readonly semanticControlFlow?: number;
|
|
765
|
+
readonly references?: boolean;
|
|
766
|
+
readonly types?: boolean;
|
|
767
|
+
readonly controlFlow?: boolean;
|
|
626
768
|
readonly sourceMapMappings: number;
|
|
627
769
|
readonly sourceRanges: boolean;
|
|
770
|
+
readonly sourceRangeNodes?: number;
|
|
771
|
+
readonly sourceRangeMappings?: number;
|
|
628
772
|
readonly generatedRanges: boolean;
|
|
773
|
+
readonly generatedRangeMappings?: number;
|
|
774
|
+
readonly semanticCoverage?: NativeImporterAdapterSemanticCoverage;
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
export interface NativeImporterAdapterCoverageCapabilityRow {
|
|
778
|
+
readonly capability: string;
|
|
779
|
+
readonly declared: boolean;
|
|
780
|
+
readonly observed: boolean;
|
|
781
|
+
readonly effective: boolean;
|
|
782
|
+
readonly count: number;
|
|
783
|
+
readonly status: 'declared-and-observed' | 'declared-unobserved' | 'observed-undeclared' | 'absent';
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
export interface NativeImporterAdapterCoverageCapabilityEvidence {
|
|
787
|
+
readonly declared: NativeImporterAdapterCoverageSnapshot;
|
|
788
|
+
readonly observed: NativeImporterAdapterCoverageObserved;
|
|
789
|
+
readonly effective: NativeImporterAdapterCoverageSnapshot;
|
|
790
|
+
readonly capabilities: readonly NativeImporterAdapterCoverageCapabilityRow[];
|
|
791
|
+
readonly gaps: readonly string[];
|
|
792
|
+
readonly declaredOnly: readonly string[];
|
|
793
|
+
readonly observedOnly: readonly string[];
|
|
794
|
+
readonly parserDiagnostics: {
|
|
795
|
+
readonly declared: boolean;
|
|
796
|
+
readonly observed: boolean;
|
|
797
|
+
readonly count: number;
|
|
798
|
+
readonly errors: number;
|
|
799
|
+
readonly warnings: number;
|
|
800
|
+
readonly infos: number;
|
|
801
|
+
};
|
|
802
|
+
readonly sourceRanges: {
|
|
803
|
+
readonly declared: boolean;
|
|
804
|
+
readonly observed: boolean;
|
|
805
|
+
readonly nativeAstNodes: number;
|
|
806
|
+
readonly sourceRangeNodes: number;
|
|
807
|
+
readonly sourceMapMappings: number;
|
|
808
|
+
readonly sourceRangeMappings: number;
|
|
809
|
+
readonly generatedRangeMappings: number;
|
|
810
|
+
};
|
|
811
|
+
readonly tokensTrivia: {
|
|
812
|
+
readonly tokens: { readonly declared: boolean; readonly observed: boolean; readonly count: number };
|
|
813
|
+
readonly trivia: { readonly declared: boolean; readonly observed: boolean; readonly count: number };
|
|
814
|
+
};
|
|
815
|
+
readonly semantic: {
|
|
816
|
+
readonly level: {
|
|
817
|
+
readonly declared: string;
|
|
818
|
+
readonly observed: string;
|
|
819
|
+
readonly effective: string;
|
|
820
|
+
};
|
|
821
|
+
readonly declarations: NativeImporterAdapterCoverageCapabilityRow;
|
|
822
|
+
readonly symbols: NativeImporterAdapterCoverageCapabilityRow;
|
|
823
|
+
readonly references: NativeImporterAdapterCoverageCapabilityRow;
|
|
824
|
+
readonly types: NativeImporterAdapterCoverageCapabilityRow;
|
|
825
|
+
readonly controlFlow: NativeImporterAdapterCoverageCapabilityRow;
|
|
826
|
+
};
|
|
629
827
|
}
|
|
630
828
|
|
|
631
829
|
export interface NativeImporterAdapterCoverageSummary {
|
|
@@ -638,11 +836,13 @@ export interface NativeImporterAdapterCoverageSummary {
|
|
|
638
836
|
readonly generatedRanges: boolean;
|
|
639
837
|
readonly semanticCoverage: NativeImporterAdapterSemanticCoverage;
|
|
640
838
|
readonly notes: readonly string[];
|
|
839
|
+
readonly declared?: NativeImporterAdapterCoverageSnapshot;
|
|
641
840
|
readonly observed?: NativeImporterAdapterCoverageObserved;
|
|
841
|
+
readonly capabilityEvidence?: NativeImporterAdapterCoverageCapabilityEvidence;
|
|
642
842
|
}
|
|
643
843
|
|
|
644
844
|
export type NativeImporterAdapterCoverageInput =
|
|
645
|
-
Omit<Partial<NativeImporterAdapterCoverageSummary>, 'semanticCoverage' | 'observed'> & {
|
|
845
|
+
Omit<Partial<NativeImporterAdapterCoverageSummary>, 'semanticCoverage' | 'observed' | 'declared' | 'capabilityEvidence'> & {
|
|
646
846
|
readonly semanticCoverage?: Partial<NativeImporterAdapterSemanticCoverage>;
|
|
647
847
|
readonly observed?: Partial<NativeImporterAdapterCoverageObserved>;
|
|
648
848
|
};
|
|
@@ -972,6 +1172,7 @@ export declare const NativeImportRoundtripReadinessStatuses: readonly NativeImpo
|
|
|
972
1172
|
export declare const NativeImportTaxonomyKinds: readonly NativeImportTaxonomyKind[];
|
|
973
1173
|
export declare const NativeImportLossKinds: readonly NativeImportKnownLossKind[];
|
|
974
1174
|
export declare const NativeImportRegionTaxonomyKinds: readonly NativeImportRegionTaxonomyKind[];
|
|
1175
|
+
export declare const ProjectionTargetLossClasses: readonly ProjectionTargetLossClass[];
|
|
975
1176
|
export declare const NativeImportReadinessBySeverity: Readonly<Record<NativeImportLossSummary['highestSeverity'], SemanticMergeReadiness>>;
|
|
976
1177
|
export declare const NativeImportLanguageProfiles: readonly NativeImportLanguageProfile[];
|
|
977
1178
|
export declare function normalizeCompileTarget(target?: string): FrontierCompileTarget;
|
|
@@ -984,6 +1185,7 @@ export declare function summarizeNativeImportLosses(losses?: readonly NativeAstL
|
|
|
984
1185
|
export declare function classifyNativeImportReadiness(losses?: readonly NativeAstLossRecord[], options?: NativeImportLossSummaryOptions): NativeImportReadinessClassification;
|
|
985
1186
|
export declare function classifyNativeImportRoundtripReadiness(importResult: NativeSourceImportResult | NativeProjectImportResult, options?: NativeImportRoundtripReadinessOptions): NativeImportRoundtripReadinessClassification;
|
|
986
1187
|
export declare function createNativeImportCoverageMatrix(options?: NativeImportCoverageMatrixOptions): NativeImportCoverageMatrix;
|
|
1188
|
+
export declare function createProjectionTargetLossMatrix(options?: ProjectionTargetLossMatrixOptions): ProjectionTargetLossMatrix;
|
|
987
1189
|
export declare function createNativeSourcePreservation(options: CreateNativeSourcePreservationOptions): NativeSourcePreservation;
|
|
988
1190
|
export declare function createSemanticImportSidecar(importResult: NativeSourceImportResult | NativeProjectImportResult, options?: SemanticImportSidecarOptions): SemanticImportSidecar;
|
|
989
1191
|
export declare function createNativeImportResultContract(importResult: NativeSourceImportResult | NativeProjectImportResult, options?: NativeImportResultContractOptions): NativeImportResultContract;
|
package/dist/index.js
CHANGED
|
@@ -138,6 +138,13 @@ export const NativeImportRegionTaxonomyKinds = Object.freeze([
|
|
|
138
138
|
'generatedOutput'
|
|
139
139
|
]);
|
|
140
140
|
|
|
141
|
+
export const ProjectionTargetLossClasses = Object.freeze([
|
|
142
|
+
'exactSourceProjection',
|
|
143
|
+
'nativeSourceStubs',
|
|
144
|
+
'unsupportedTargetFeatures',
|
|
145
|
+
'missingAdapter'
|
|
146
|
+
]);
|
|
147
|
+
|
|
141
148
|
export const NativeImportLanguageProfiles = Object.freeze([
|
|
142
149
|
nativeImportLanguageProfile('javascript', {
|
|
143
150
|
aliases: ['js', 'mjs', 'cjs', 'jsx'],
|
|
@@ -493,6 +500,7 @@ export function createNativeImportCoverageMatrix(input = {}) {
|
|
|
493
500
|
for (const [kind, count] of Object.entries(entry.imports.lossKinds)) {
|
|
494
501
|
totals.lossKinds[kind] = (totals.lossKinds[kind] ?? 0) + count;
|
|
495
502
|
}
|
|
503
|
+
totals.adapterCoverage = mergeNativeImporterAdapterCoverageAggregates(totals.adapterCoverage, entry.adapterCoverage);
|
|
496
504
|
return totals;
|
|
497
505
|
}, {
|
|
498
506
|
languages: 0,
|
|
@@ -504,7 +512,8 @@ export function createNativeImportCoverageMatrix(input = {}) {
|
|
|
504
512
|
sourceMapMappings: 0,
|
|
505
513
|
losses: 0,
|
|
506
514
|
byReadiness: {},
|
|
507
|
-
lossKinds: {}
|
|
515
|
+
lossKinds: {},
|
|
516
|
+
adapterCoverage: emptyNativeImporterAdapterCoverageAggregate()
|
|
508
517
|
});
|
|
509
518
|
return {
|
|
510
519
|
kind: 'frontier.lang.nativeImportCoverageMatrix',
|
|
@@ -514,11 +523,37 @@ export function createNativeImportCoverageMatrix(input = {}) {
|
|
|
514
523
|
summary,
|
|
515
524
|
metadata: {
|
|
516
525
|
compileTargets: [...FrontierCompileTargets],
|
|
526
|
+
projectionTargetLossClasses: [...ProjectionTargetLossClasses],
|
|
517
527
|
note: 'Coverage is evidence and capability metadata, not a claim that every language feature is losslessly portable.'
|
|
518
528
|
}
|
|
519
529
|
};
|
|
520
530
|
}
|
|
521
531
|
|
|
532
|
+
export function createProjectionTargetLossMatrix(input = {}) {
|
|
533
|
+
const imports = input.imports ?? [];
|
|
534
|
+
const adapters = input.adapters ?? [];
|
|
535
|
+
const profiles = mergeNativeImportProfiles(input.languages ?? NativeImportLanguageProfiles, imports, adapters);
|
|
536
|
+
const targets = normalizeProjectionMatrixTargets(input.targets ?? FrontierCompileTargets);
|
|
537
|
+
const languages = profiles.map((profile) => projectionTargetCoverageForProfile(profile, {
|
|
538
|
+
imports,
|
|
539
|
+
adapters,
|
|
540
|
+
targets
|
|
541
|
+
}));
|
|
542
|
+
const summary = projectionTargetLossMatrixSummary(languages);
|
|
543
|
+
return {
|
|
544
|
+
kind: 'frontier.lang.projectionTargetLossMatrix',
|
|
545
|
+
version: 1,
|
|
546
|
+
generatedAt: input.generatedAt ?? Date.now(),
|
|
547
|
+
languages,
|
|
548
|
+
summary,
|
|
549
|
+
metadata: {
|
|
550
|
+
compileTargets: targets,
|
|
551
|
+
lossClasses: [...ProjectionTargetLossClasses],
|
|
552
|
+
note: 'Projection target coverage separates exact source preservation, declaration stubs, known unsupported target features, and missing native-to-target adapters.'
|
|
553
|
+
}
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
|
|
522
557
|
export function createNativeSourcePreservation(options) {
|
|
523
558
|
if (!options || typeof options.sourceText !== 'string') {
|
|
524
559
|
throw new Error('createNativeSourcePreservation requires sourceText');
|
|
@@ -3369,15 +3404,273 @@ function nativeImportCategoryForLossKind(kind) {
|
|
|
3369
3404
|
return String(kind ?? 'opaqueNative');
|
|
3370
3405
|
}
|
|
3371
3406
|
|
|
3407
|
+
function normalizeProjectionMatrixTargets(targets) {
|
|
3408
|
+
return uniqueStrings((Array.isArray(targets) ? targets : [targets])
|
|
3409
|
+
.map((target) => {
|
|
3410
|
+
if (target === undefined || target === null) return undefined;
|
|
3411
|
+
try {
|
|
3412
|
+
return normalizeCompileTarget(target);
|
|
3413
|
+
} catch {
|
|
3414
|
+
return String(target).trim().toLowerCase();
|
|
3415
|
+
}
|
|
3416
|
+
})
|
|
3417
|
+
.filter(Boolean));
|
|
3418
|
+
}
|
|
3419
|
+
|
|
3420
|
+
function projectionTargetCoverageForProfile(profile, context) {
|
|
3421
|
+
const aliases = new Set([profile.language, ...(profile.aliases ?? [])].map(normalizeNativeLanguageId).filter(Boolean));
|
|
3422
|
+
const matchingImports = (context.imports ?? []).filter((imported) => aliases.has(normalizeNativeLanguageId(imported?.language ?? imported?.nativeAst?.language)));
|
|
3423
|
+
const matchingAdapters = (context.adapters ?? []).filter((adapter) => aliases.has(normalizeNativeLanguageId(adapter?.language)));
|
|
3424
|
+
const importedLossKinds = uniqueStrings(matchingImports.flatMap((imported) => (imported?.losses ?? []).map((loss) => loss.kind).filter(Boolean)));
|
|
3425
|
+
const knownLossKinds = uniqueStrings([...(profile.knownLossKinds ?? []), ...importedLossKinds]);
|
|
3426
|
+
const parserAdapters = uniqueStrings([
|
|
3427
|
+
...(profile.parserAdapters ?? []),
|
|
3428
|
+
...matchingAdapters.map((adapter) => adapter.parser ?? adapter.id).filter(Boolean)
|
|
3429
|
+
]);
|
|
3430
|
+
const sourceProjection = sourceProjectionCoverageForProfile(profile, matchingImports, knownLossKinds);
|
|
3431
|
+
const targets = (context.targets ?? FrontierCompileTargets).map((target) => projectionTargetCoverageEntry(profile, target, {
|
|
3432
|
+
matchingImports,
|
|
3433
|
+
matchingAdapters,
|
|
3434
|
+
knownLossKinds
|
|
3435
|
+
}));
|
|
3436
|
+
return {
|
|
3437
|
+
language: profile.language,
|
|
3438
|
+
aliases: profile.aliases,
|
|
3439
|
+
extensions: profile.extensions,
|
|
3440
|
+
supportsLightweightScan: profile.supportsLightweightScan,
|
|
3441
|
+
parserAdapters,
|
|
3442
|
+
projectionTargets: profile.projectionTargets,
|
|
3443
|
+
knownLossKinds,
|
|
3444
|
+
defaultReadiness: profile.defaultReadiness,
|
|
3445
|
+
notes: profile.notes,
|
|
3446
|
+
sourceProjection,
|
|
3447
|
+
targets,
|
|
3448
|
+
summary: {
|
|
3449
|
+
imports: matchingImports.length,
|
|
3450
|
+
parserAdapters: parserAdapters.length,
|
|
3451
|
+
targetEntries: targets.length,
|
|
3452
|
+
byLossClass: countProjectionLossClasses(targets),
|
|
3453
|
+
exactSourceImports: sourceProjection.exactSource.evidence.importsWithExactSource,
|
|
3454
|
+
stubDeclarationImports: sourceProjection.stubs.evidence.importsWithDeclarations
|
|
3455
|
+
}
|
|
3456
|
+
};
|
|
3457
|
+
}
|
|
3458
|
+
|
|
3459
|
+
function sourceProjectionCoverageForProfile(profile, imports, knownLossKinds) {
|
|
3460
|
+
const exactSourceImports = imports.filter(hasExactSourceProjectionEvidence).length;
|
|
3461
|
+
const declarationImports = imports.filter(hasNativeProjectionDeclarations).length;
|
|
3462
|
+
return {
|
|
3463
|
+
exactSource: {
|
|
3464
|
+
lossClass: 'exactSourceProjection',
|
|
3465
|
+
mode: 'preserved-source',
|
|
3466
|
+
supported: true,
|
|
3467
|
+
readiness: 'ready',
|
|
3468
|
+
lossKinds: [],
|
|
3469
|
+
categories: [],
|
|
3470
|
+
reason: exactSourceImports
|
|
3471
|
+
? 'At least one import carries matching source-preservation evidence, so projectNativeImportToSource can emit the original source exactly.'
|
|
3472
|
+
: 'Exact source projection is available when the import carries sourceText or source-preservation evidence whose hash matches the native source hash.',
|
|
3473
|
+
evidence: {
|
|
3474
|
+
imports: imports.length,
|
|
3475
|
+
importsWithExactSource: exactSourceImports
|
|
3476
|
+
},
|
|
3477
|
+
notes: ['Preserved source is the only currently lossless native-source projection mode in this facade.']
|
|
3478
|
+
},
|
|
3479
|
+
stubs: {
|
|
3480
|
+
lossClass: 'nativeSourceStubs',
|
|
3481
|
+
mode: 'native-source-stubs',
|
|
3482
|
+
supported: profile.supportsLightweightScan || declarationImports > 0,
|
|
3483
|
+
readiness: 'needs-review',
|
|
3484
|
+
lossKinds: uniqueStrings([
|
|
3485
|
+
'targetProjectionLoss',
|
|
3486
|
+
...(declarationImports || profile.supportsLightweightScan ? [] : ['declarationOnlyCoverage'])
|
|
3487
|
+
]),
|
|
3488
|
+
categories: uniqueStrings([
|
|
3489
|
+
'targetProjectionLoss',
|
|
3490
|
+
...(declarationImports || profile.supportsLightweightScan ? [] : ['declarationsOnly'])
|
|
3491
|
+
]),
|
|
3492
|
+
reason: 'Declaration stubs are emitted when exact source is unavailable or disabled; executable bodies and full type semantics remain unavailable.',
|
|
3493
|
+
evidence: {
|
|
3494
|
+
imports: imports.length,
|
|
3495
|
+
importsWithDeclarations: declarationImports
|
|
3496
|
+
},
|
|
3497
|
+
notes: uniqueStrings([
|
|
3498
|
+
'Stub projection is review-required and should not be treated as a round-trip proof.',
|
|
3499
|
+
...(projectionUnsupportedFeatureLossKinds(knownLossKinds).length
|
|
3500
|
+
? ['Known source-language feature losses may still be present behind preserved source or stubs.']
|
|
3501
|
+
: [])
|
|
3502
|
+
])
|
|
3503
|
+
}
|
|
3504
|
+
};
|
|
3505
|
+
}
|
|
3506
|
+
|
|
3507
|
+
function projectionTargetCoverageEntry(profile, target, context) {
|
|
3508
|
+
const normalizedTarget = normalizeProjectionMatrixTargets([target])[0] ?? String(target);
|
|
3509
|
+
const declaredTargets = new Set(normalizeProjectionMatrixTargets(profile.projectionTargets ?? []));
|
|
3510
|
+
const adapterTargets = new Set((context.matchingAdapters ?? []).flatMap(adapterProjectionTargets));
|
|
3511
|
+
const sameSourceTarget = nativeLanguageCompileTarget(profile.language, profile.aliases) === normalizedTarget;
|
|
3512
|
+
const hasProjectionAdapter = declaredTargets.has(normalizedTarget) || adapterTargets.has(normalizedTarget);
|
|
3513
|
+
if (!hasProjectionAdapter) {
|
|
3514
|
+
return {
|
|
3515
|
+
target: normalizedTarget,
|
|
3516
|
+
lossClass: 'missingAdapter',
|
|
3517
|
+
supported: false,
|
|
3518
|
+
readiness: 'blocked',
|
|
3519
|
+
lossKinds: ['targetProjectionLoss'],
|
|
3520
|
+
categories: ['targetProjectionLoss'],
|
|
3521
|
+
reason: `No native-to-${normalizedTarget} projection adapter is declared for ${profile.language}.`,
|
|
3522
|
+
adapter: undefined,
|
|
3523
|
+
notes: ['The source can still be preserved or stubbed in its original language when import evidence supports that mode.']
|
|
3524
|
+
};
|
|
3525
|
+
}
|
|
3526
|
+
|
|
3527
|
+
const featureLossKinds = projectionUnsupportedFeatureLossKinds(context.knownLossKinds);
|
|
3528
|
+
if (featureLossKinds.length) {
|
|
3529
|
+
return {
|
|
3530
|
+
target: normalizedTarget,
|
|
3531
|
+
lossClass: 'unsupportedTargetFeatures',
|
|
3532
|
+
supported: true,
|
|
3533
|
+
readiness: 'needs-review',
|
|
3534
|
+
lossKinds: featureLossKinds,
|
|
3535
|
+
categories: uniqueStrings(featureLossKinds.map(nativeImportCategoryForLossKind)),
|
|
3536
|
+
reason: `${profile.language} coverage declares source features that this facade cannot prove lossless for ${normalizedTarget}: ${featureLossKinds.join(', ')}.`,
|
|
3537
|
+
adapter: projectionTargetAdapterName(profile, normalizedTarget, context.matchingAdapters),
|
|
3538
|
+
notes: ['Use exact parser or semantic adapter evidence before treating this target projection as merge-ready.']
|
|
3539
|
+
};
|
|
3540
|
+
}
|
|
3541
|
+
|
|
3542
|
+
if (sameSourceTarget) {
|
|
3543
|
+
return {
|
|
3544
|
+
target: normalizedTarget,
|
|
3545
|
+
lossClass: 'exactSourceProjection',
|
|
3546
|
+
supported: true,
|
|
3547
|
+
readiness: 'ready',
|
|
3548
|
+
lossKinds: [],
|
|
3549
|
+
categories: [],
|
|
3550
|
+
reason: `${profile.language} can project to its source language exactly when source preservation evidence is available.`,
|
|
3551
|
+
adapter: projectionTargetAdapterName(profile, normalizedTarget, context.matchingAdapters),
|
|
3552
|
+
notes: ['Without exact source text, the source projection falls back to declaration stubs.']
|
|
3553
|
+
};
|
|
3554
|
+
}
|
|
3555
|
+
|
|
3556
|
+
return {
|
|
3557
|
+
target: normalizedTarget,
|
|
3558
|
+
lossClass: 'nativeSourceStubs',
|
|
3559
|
+
supported: true,
|
|
3560
|
+
readiness: 'needs-review',
|
|
3561
|
+
lossKinds: ['targetProjectionLoss'],
|
|
3562
|
+
categories: ['targetProjectionLoss'],
|
|
3563
|
+
reason: `${profile.language} declares a ${normalizedTarget} target slot, but this facade only exposes declaration-level native import projection evidence.`,
|
|
3564
|
+
adapter: projectionTargetAdapterName(profile, normalizedTarget, context.matchingAdapters),
|
|
3565
|
+
notes: ['Host-owned semantic adapters can upgrade this cell with stronger evidence.']
|
|
3566
|
+
};
|
|
3567
|
+
}
|
|
3568
|
+
|
|
3569
|
+
function projectionTargetLossMatrixSummary(languages) {
|
|
3570
|
+
const byLossClass = {};
|
|
3571
|
+
const sourceProjectionByLossClass = {};
|
|
3572
|
+
let targetEntries = 0;
|
|
3573
|
+
for (const language of languages) {
|
|
3574
|
+
for (const projection of [language.sourceProjection?.exactSource, language.sourceProjection?.stubs].filter(Boolean)) {
|
|
3575
|
+
sourceProjectionByLossClass[projection.lossClass] = (sourceProjectionByLossClass[projection.lossClass] ?? 0) + 1;
|
|
3576
|
+
}
|
|
3577
|
+
for (const target of language.targets ?? []) {
|
|
3578
|
+
targetEntries += 1;
|
|
3579
|
+
byLossClass[target.lossClass] = (byLossClass[target.lossClass] ?? 0) + 1;
|
|
3580
|
+
}
|
|
3581
|
+
}
|
|
3582
|
+
return {
|
|
3583
|
+
languages: languages.length,
|
|
3584
|
+
targetEntries,
|
|
3585
|
+
byLossClass,
|
|
3586
|
+
sourceProjectionByLossClass,
|
|
3587
|
+
exactSourceProjection: (sourceProjectionByLossClass.exactSourceProjection ?? 0) + (byLossClass.exactSourceProjection ?? 0),
|
|
3588
|
+
nativeSourceStubs: (sourceProjectionByLossClass.nativeSourceStubs ?? 0) + (byLossClass.nativeSourceStubs ?? 0),
|
|
3589
|
+
unsupportedTargetFeatures: byLossClass.unsupportedTargetFeatures ?? 0,
|
|
3590
|
+
missingAdapters: byLossClass.missingAdapter ?? 0
|
|
3591
|
+
};
|
|
3592
|
+
}
|
|
3593
|
+
|
|
3594
|
+
function countProjectionLossClasses(entries) {
|
|
3595
|
+
const counts = {};
|
|
3596
|
+
for (const entry of entries ?? []) {
|
|
3597
|
+
counts[entry.lossClass] = (counts[entry.lossClass] ?? 0) + 1;
|
|
3598
|
+
}
|
|
3599
|
+
return counts;
|
|
3600
|
+
}
|
|
3601
|
+
|
|
3602
|
+
function hasExactSourceProjectionEvidence(imported) {
|
|
3603
|
+
const preservation = imported?.metadata?.sourcePreservation
|
|
3604
|
+
?? imported?.nativeSource?.metadata?.sourcePreservation
|
|
3605
|
+
?? imported?.nativeAst?.metadata?.sourcePreservation;
|
|
3606
|
+
const expectedHash = imported?.nativeSource?.sourceHash ?? imported?.nativeAst?.sourceHash ?? imported?.sourceHash;
|
|
3607
|
+
return Boolean(preservation?.summary?.exactSourceAvailable && (!expectedHash || preservation.sourceHash === expectedHash));
|
|
3608
|
+
}
|
|
3609
|
+
|
|
3610
|
+
function hasNativeProjectionDeclarations(imported) {
|
|
3611
|
+
const semanticIndex = imported?.semanticIndex ?? imported?.universalAst?.semanticIndex;
|
|
3612
|
+
return (semanticIndex?.symbols?.length ?? 0) > 0;
|
|
3613
|
+
}
|
|
3614
|
+
|
|
3615
|
+
function projectionUnsupportedFeatureLossKinds(lossKinds) {
|
|
3616
|
+
const unsupported = new Set([
|
|
3617
|
+
'macroExpansion',
|
|
3618
|
+
'macroHygiene',
|
|
3619
|
+
'preprocessor',
|
|
3620
|
+
'conditionalCompilation',
|
|
3621
|
+
'metaprogramming',
|
|
3622
|
+
'reflection',
|
|
3623
|
+
'dynamicRuntime',
|
|
3624
|
+
'dynamicDispatch',
|
|
3625
|
+
'generatedCode',
|
|
3626
|
+
'overloadResolution',
|
|
3627
|
+
'typeInference',
|
|
3628
|
+
'unsupportedSyntax',
|
|
3629
|
+
'unsupportedSemantic'
|
|
3630
|
+
]);
|
|
3631
|
+
return uniqueStrings((lossKinds ?? []).filter((kind) => unsupported.has(kind)));
|
|
3632
|
+
}
|
|
3633
|
+
|
|
3634
|
+
function adapterProjectionTargets(adapter) {
|
|
3635
|
+
return normalizeProjectionMatrixTargets(
|
|
3636
|
+
adapter?.projectionTargets
|
|
3637
|
+
?? adapter?.coverage?.projectionTargets
|
|
3638
|
+
?? adapter?.metadata?.projectionTargets
|
|
3639
|
+
?? []
|
|
3640
|
+
);
|
|
3641
|
+
}
|
|
3642
|
+
|
|
3643
|
+
function projectionTargetAdapterName(profile, target, adapters = []) {
|
|
3644
|
+
const adapter = adapters.find((candidate) => adapterProjectionTargets(candidate).includes(target));
|
|
3645
|
+
if (adapter) return adapter.id ?? adapter.parser;
|
|
3646
|
+
return profile.projectionTargets?.includes(target) ? `frontier-native-source-${target}` : undefined;
|
|
3647
|
+
}
|
|
3648
|
+
|
|
3649
|
+
function nativeLanguageCompileTarget(language, aliases = []) {
|
|
3650
|
+
const ids = [language, ...aliases].map(normalizeNativeLanguageId);
|
|
3651
|
+
if (ids.includes('typescript')) return 'typescript';
|
|
3652
|
+
if (ids.includes('javascript')) return 'javascript';
|
|
3653
|
+
if (ids.includes('rust')) return 'rust';
|
|
3654
|
+
if (ids.includes('python')) return 'python';
|
|
3655
|
+
if (ids.includes('c')) return 'c';
|
|
3656
|
+
return undefined;
|
|
3657
|
+
}
|
|
3658
|
+
|
|
3659
|
+
function nativeProjectionTargetsForLanguage(language, aliases = []) {
|
|
3660
|
+
const target = nativeLanguageCompileTarget(language, aliases);
|
|
3661
|
+
return target ? [target] : [];
|
|
3662
|
+
}
|
|
3663
|
+
|
|
3372
3664
|
function nativeImportLanguageProfile(language, input = {}) {
|
|
3373
3665
|
const lossKinds = input.lossKinds ?? ['declarationOnlyCoverage', 'opaqueNative', 'sourceMapApproximation', 'sourcePreservation'];
|
|
3666
|
+
const aliases = uniqueStrings(input.aliases ?? []);
|
|
3374
3667
|
return Object.freeze({
|
|
3375
3668
|
language,
|
|
3376
|
-
aliases: Object.freeze(
|
|
3669
|
+
aliases: Object.freeze(aliases),
|
|
3377
3670
|
extensions: Object.freeze(uniqueStrings(input.extensions ?? [])),
|
|
3378
3671
|
supportsLightweightScan: input.supportsLightweightScan !== false,
|
|
3379
3672
|
parserAdapters: Object.freeze(uniqueStrings(input.parserAdapters ?? ['tree-sitter'])),
|
|
3380
|
-
projectionTargets: Object.freeze(uniqueStrings(input.projectionTargets ??
|
|
3673
|
+
projectionTargets: Object.freeze(uniqueStrings(input.projectionTargets ?? nativeProjectionTargetsForLanguage(language, aliases))),
|
|
3381
3674
|
knownLossKinds: Object.freeze(uniqueStrings(lossKinds)),
|
|
3382
3675
|
defaultReadiness: input.defaultReadiness ?? 'needs-review',
|
|
3383
3676
|
notes: Object.freeze(uniqueStrings(input.notes ?? ['lightweight scanner records declarations only; exact parser adapters must be injected by the host']))
|
|
@@ -3421,7 +3714,7 @@ function normalizeNativeImportLanguageProfile(profile, fallbackLanguage) {
|
|
|
3421
3714
|
extensions: uniqueStrings(profile.extensions ?? []),
|
|
3422
3715
|
supportsLightweightScan: profile.supportsLightweightScan !== false,
|
|
3423
3716
|
parserAdapters: uniqueStrings(profile.parserAdapters ?? []),
|
|
3424
|
-
projectionTargets: uniqueStrings(profile.projectionTargets ??
|
|
3717
|
+
projectionTargets: uniqueStrings(profile.projectionTargets ?? nativeProjectionTargetsForLanguage(language, profile.aliases ?? [])),
|
|
3425
3718
|
knownLossKinds: uniqueStrings(profile.knownLossKinds ?? profile.lossKinds ?? []),
|
|
3426
3719
|
defaultReadiness: profile.defaultReadiness ?? 'needs-review',
|
|
3427
3720
|
notes: uniqueStrings(profile.notes ?? [])
|
|
@@ -3440,6 +3733,10 @@ function nativeImportCoverageForProfile(profile, imports, adapters) {
|
|
|
3440
3733
|
: profile.supportsLightweightScan ? profile.defaultReadiness : 'blocked';
|
|
3441
3734
|
const importedParsers = uniqueStrings(matchingImports.map((imported) => imported?.nativeAst?.parser ?? imported?.parser ?? imported?.metadata?.parser).filter(Boolean));
|
|
3442
3735
|
const sourceMaps = matchingImports.flatMap((imported) => imported?.sourceMaps ?? imported?.universalAst?.sourceMaps ?? []);
|
|
3736
|
+
const adapterCoverage = summarizeNativeImporterAdapterCoverageEntries([
|
|
3737
|
+
...matchingImports.map((imported) => nativeImporterAdapterCoverageEntryFromImport(imported)).filter(Boolean),
|
|
3738
|
+
...matchingAdapters.map((adapter) => nativeImporterAdapterCoverageEntryFromAdapter(adapter)).filter(Boolean)
|
|
3739
|
+
]);
|
|
3443
3740
|
return {
|
|
3444
3741
|
language: profile.language,
|
|
3445
3742
|
aliases: profile.aliases,
|
|
@@ -3450,6 +3747,7 @@ function nativeImportCoverageForProfile(profile, imports, adapters) {
|
|
|
3450
3747
|
knownLossKinds: uniqueStrings([...(profile.knownLossKinds ?? []), ...Object.keys(lossSummary.byKind)]),
|
|
3451
3748
|
defaultReadiness: profile.defaultReadiness,
|
|
3452
3749
|
notes: profile.notes,
|
|
3750
|
+
adapterCoverage,
|
|
3453
3751
|
imports: {
|
|
3454
3752
|
total: matchingImports.length,
|
|
3455
3753
|
parsers: importedParsers,
|
|
@@ -3465,6 +3763,125 @@ function nativeImportCoverageForProfile(profile, imports, adapters) {
|
|
|
3465
3763
|
};
|
|
3466
3764
|
}
|
|
3467
3765
|
|
|
3766
|
+
function nativeImporterAdapterCoverageEntryFromImport(imported) {
|
|
3767
|
+
const coverage = imported?.adapter?.coverage
|
|
3768
|
+
?? imported?.metadata?.adapterCoverage
|
|
3769
|
+
?? imported?.nativeAst?.metadata?.adapterCoverage
|
|
3770
|
+
?? imported?.nativeSource?.metadata?.adapterCoverage;
|
|
3771
|
+
if (!coverage) return undefined;
|
|
3772
|
+
return {
|
|
3773
|
+
adapterId: imported?.adapter?.id ?? imported?.metadata?.adapterId ?? imported?.nativeAst?.metadata?.adapterId,
|
|
3774
|
+
language: imported?.adapter?.language ?? imported?.language ?? imported?.nativeAst?.language,
|
|
3775
|
+
parser: imported?.adapter?.parser ?? imported?.nativeAst?.parser ?? imported?.nativeSource?.parser,
|
|
3776
|
+
coverage
|
|
3777
|
+
};
|
|
3778
|
+
}
|
|
3779
|
+
|
|
3780
|
+
function nativeImporterAdapterCoverageEntryFromAdapter(adapter) {
|
|
3781
|
+
if (!adapter) return undefined;
|
|
3782
|
+
const summary = normalizeNativeImporterAdapter(adapter);
|
|
3783
|
+
return {
|
|
3784
|
+
adapterId: summary.id,
|
|
3785
|
+
language: summary.language,
|
|
3786
|
+
parser: summary.parser,
|
|
3787
|
+
coverage: summary.coverage
|
|
3788
|
+
};
|
|
3789
|
+
}
|
|
3790
|
+
|
|
3791
|
+
function summarizeNativeImporterAdapterCoverageEntries(entries = []) {
|
|
3792
|
+
const aggregate = emptyNativeImporterAdapterCoverageAggregate();
|
|
3793
|
+
for (const entry of entries) {
|
|
3794
|
+
const coverage = normalizeNativeImporterAdapterCoverageForEvidence(entry.coverage);
|
|
3795
|
+
const capabilityEvidence = coverage.capabilityEvidence;
|
|
3796
|
+
const summary = {
|
|
3797
|
+
adapterId: entry.adapterId,
|
|
3798
|
+
language: entry.language,
|
|
3799
|
+
parser: entry.parser,
|
|
3800
|
+
exactness: coverage.exactness,
|
|
3801
|
+
declared: capabilityNamesByBoolean(capabilityEvidence.capabilities, 'declared'),
|
|
3802
|
+
observed: capabilityNamesByBoolean(capabilityEvidence.capabilities, 'observed'),
|
|
3803
|
+
effective: capabilityNamesByBoolean(capabilityEvidence.capabilities, 'effective'),
|
|
3804
|
+
gaps: capabilityEvidence.gaps,
|
|
3805
|
+
declaredOnly: capabilityEvidence.declaredOnly,
|
|
3806
|
+
observedOnly: capabilityEvidence.observedOnly
|
|
3807
|
+
};
|
|
3808
|
+
aggregate.total += 1;
|
|
3809
|
+
aggregate.summaries.push(summary);
|
|
3810
|
+
incrementCoverageCapabilityCounts(aggregate.declared, summary.declared);
|
|
3811
|
+
incrementCoverageCapabilityCounts(aggregate.observed, summary.observed);
|
|
3812
|
+
incrementCoverageCapabilityCounts(aggregate.effective, summary.effective);
|
|
3813
|
+
incrementCoverageCapabilityCounts(aggregate.gaps, summary.gaps);
|
|
3814
|
+
incrementCoverageCapabilityCounts(aggregate.declaredOnly, summary.declaredOnly);
|
|
3815
|
+
incrementCoverageCapabilityCounts(aggregate.observedOnly, summary.observedOnly);
|
|
3816
|
+
}
|
|
3817
|
+
return {
|
|
3818
|
+
...aggregate,
|
|
3819
|
+
summaries: Object.freeze(aggregate.summaries)
|
|
3820
|
+
};
|
|
3821
|
+
}
|
|
3822
|
+
|
|
3823
|
+
function normalizeNativeImporterAdapterCoverageForEvidence(coverage = {}) {
|
|
3824
|
+
if (coverage.capabilityEvidence) return coverage;
|
|
3825
|
+
const declared = coverage.declared ?? adapterCoverageSnapshotFromSummary(coverage);
|
|
3826
|
+
const observed = normalizeNativeImporterAdapterObservedCoverage(coverage.observed, declared);
|
|
3827
|
+
const effective = effectiveNativeImporterAdapterCoverage(declared, observed);
|
|
3828
|
+
return {
|
|
3829
|
+
...coverage,
|
|
3830
|
+
...effective,
|
|
3831
|
+
declared,
|
|
3832
|
+
observed,
|
|
3833
|
+
capabilityEvidence: nativeImporterAdapterCapabilityEvidence(declared, observed, effective)
|
|
3834
|
+
};
|
|
3835
|
+
}
|
|
3836
|
+
|
|
3837
|
+
function emptyNativeImporterAdapterCoverageAggregate() {
|
|
3838
|
+
return {
|
|
3839
|
+
total: 0,
|
|
3840
|
+
declared: {},
|
|
3841
|
+
observed: {},
|
|
3842
|
+
effective: {},
|
|
3843
|
+
gaps: {},
|
|
3844
|
+
declaredOnly: {},
|
|
3845
|
+
observedOnly: {},
|
|
3846
|
+
summaries: []
|
|
3847
|
+
};
|
|
3848
|
+
}
|
|
3849
|
+
|
|
3850
|
+
function mergeNativeImporterAdapterCoverageAggregates(left, right) {
|
|
3851
|
+
const merged = emptyNativeImporterAdapterCoverageAggregate();
|
|
3852
|
+
for (const aggregate of [left, right]) {
|
|
3853
|
+
if (!aggregate) continue;
|
|
3854
|
+
merged.total += aggregate.total ?? 0;
|
|
3855
|
+
incrementCoverageCapabilityCounts(merged.declared, aggregate.declared ?? {});
|
|
3856
|
+
incrementCoverageCapabilityCounts(merged.observed, aggregate.observed ?? {});
|
|
3857
|
+
incrementCoverageCapabilityCounts(merged.effective, aggregate.effective ?? {});
|
|
3858
|
+
incrementCoverageCapabilityCounts(merged.gaps, aggregate.gaps ?? {});
|
|
3859
|
+
incrementCoverageCapabilityCounts(merged.declaredOnly, aggregate.declaredOnly ?? {});
|
|
3860
|
+
incrementCoverageCapabilityCounts(merged.observedOnly, aggregate.observedOnly ?? {});
|
|
3861
|
+
merged.summaries.push(...(aggregate.summaries ?? []));
|
|
3862
|
+
}
|
|
3863
|
+
return {
|
|
3864
|
+
...merged,
|
|
3865
|
+
summaries: Object.freeze(merged.summaries)
|
|
3866
|
+
};
|
|
3867
|
+
}
|
|
3868
|
+
|
|
3869
|
+
function capabilityNamesByBoolean(rows, property) {
|
|
3870
|
+
return rows.filter((row) => row[property]).map((row) => row.capability);
|
|
3871
|
+
}
|
|
3872
|
+
|
|
3873
|
+
function incrementCoverageCapabilityCounts(target, capabilities) {
|
|
3874
|
+
if (Array.isArray(capabilities)) {
|
|
3875
|
+
for (const capability of capabilities) {
|
|
3876
|
+
target[capability] = (target[capability] ?? 0) + 1;
|
|
3877
|
+
}
|
|
3878
|
+
return;
|
|
3879
|
+
}
|
|
3880
|
+
for (const [capability, count] of Object.entries(capabilities ?? {})) {
|
|
3881
|
+
target[capability] = (target[capability] ?? 0) + count;
|
|
3882
|
+
}
|
|
3883
|
+
}
|
|
3884
|
+
|
|
3468
3885
|
function semanticImportSidecarEntry(imported, index, options) {
|
|
3469
3886
|
const semanticIndex = imported?.semanticIndex ?? imported?.universalAst?.semanticIndex;
|
|
3470
3887
|
const nativeAst = imported?.nativeAst ?? imported?.nativeSource?.ast;
|
|
@@ -4828,7 +5245,7 @@ function normalizeNativeImporterAdapterCoverage(value = {}, context = {}) {
|
|
|
4828
5245
|
const sourceRanges = Boolean(value.sourceRanges ?? hasCapability('sourceRanges', 'sourceRange', 'ranges', 'sourceMaps'));
|
|
4829
5246
|
const generatedRanges = Boolean(value.generatedRanges ?? hasCapability('generatedRanges', 'generatedRange', 'generatedSourceMaps'));
|
|
4830
5247
|
const diagnostics = Boolean(value.diagnostics ?? hasCapability('diagnostics', 'parserDiagnostics'));
|
|
4831
|
-
|
|
5248
|
+
const declared = freezeNativeImporterAdapterCoverageSnapshot({
|
|
4832
5249
|
exactness: String(value.exactness ?? inferredAdapterExactness(exactAst, capabilities)),
|
|
4833
5250
|
exactAst,
|
|
4834
5251
|
tokens: Boolean(value.tokens ?? hasCapability('tokens', 'tokenStream')),
|
|
@@ -4840,13 +5257,21 @@ function normalizeNativeImporterAdapterCoverage(value = {}, context = {}) {
|
|
|
4840
5257
|
capabilities,
|
|
4841
5258
|
sourceRanges,
|
|
4842
5259
|
generatedRanges
|
|
4843
|
-
})
|
|
5260
|
+
})
|
|
5261
|
+
});
|
|
5262
|
+
const observed = normalizeNativeImporterAdapterObservedCoverage(value.observed, declared);
|
|
5263
|
+
const effective = effectiveNativeImporterAdapterCoverage(declared, observed);
|
|
5264
|
+
return Object.freeze({
|
|
5265
|
+
...effective,
|
|
5266
|
+
declared,
|
|
5267
|
+
observed,
|
|
4844
5268
|
notes: uniqueStrings(value.notes ?? inferredAdapterCoverageNotes(context, {
|
|
4845
5269
|
exactAst,
|
|
4846
5270
|
sourceRanges,
|
|
4847
5271
|
generatedRanges,
|
|
4848
5272
|
diagnostics
|
|
4849
|
-
}))
|
|
5273
|
+
})),
|
|
5274
|
+
capabilityEvidence: nativeImporterAdapterCapabilityEvidence(declared, observed, effective)
|
|
4850
5275
|
});
|
|
4851
5276
|
}
|
|
4852
5277
|
|
|
@@ -4856,31 +5281,297 @@ function observeNativeImporterAdapterCoverage(coverage, parseResult = {}, contex
|
|
|
4856
5281
|
const sourceMapMappings = parseResult.sourceMaps?.flatMap((sourceMap) => sourceMap.mappings ?? []) ?? parseResult.mappings ?? [];
|
|
4857
5282
|
const semanticIndex = parseResult.semanticIndex;
|
|
4858
5283
|
const semanticSymbols = semanticIndex?.symbols?.length ?? 0;
|
|
4859
|
-
const
|
|
4860
|
-
const
|
|
4861
|
-
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
|
|
4865
|
-
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
}, {});
|
|
5284
|
+
const declared = coverage.declared ?? adapterCoverageSnapshotFromSummary(coverage);
|
|
5285
|
+
const observed = observeNativeImporterAdapterCoverageDetails(parseResult, context, {
|
|
5286
|
+
declared,
|
|
5287
|
+
nodeList,
|
|
5288
|
+
sourceMapMappings,
|
|
5289
|
+
semanticIndex,
|
|
5290
|
+
semanticSymbols
|
|
5291
|
+
});
|
|
5292
|
+
const effective = effectiveNativeImporterAdapterCoverage(declared, observed);
|
|
4869
5293
|
return Object.freeze({
|
|
4870
5294
|
...coverage,
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
|
|
4877
|
-
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
|
|
4881
|
-
|
|
4882
|
-
|
|
4883
|
-
|
|
5295
|
+
...effective,
|
|
5296
|
+
declared,
|
|
5297
|
+
observed,
|
|
5298
|
+
capabilityEvidence: nativeImporterAdapterCapabilityEvidence(declared, observed, effective)
|
|
5299
|
+
});
|
|
5300
|
+
}
|
|
5301
|
+
|
|
5302
|
+
function adapterCoverageSnapshotFromSummary(coverage = {}) {
|
|
5303
|
+
return freezeNativeImporterAdapterCoverageSnapshot({
|
|
5304
|
+
exactness: coverage.exactness ?? 'unknown',
|
|
5305
|
+
exactAst: coverage.exactAst,
|
|
5306
|
+
tokens: coverage.tokens,
|
|
5307
|
+
trivia: coverage.trivia,
|
|
5308
|
+
diagnostics: coverage.diagnostics,
|
|
5309
|
+
sourceRanges: coverage.sourceRanges,
|
|
5310
|
+
generatedRanges: coverage.generatedRanges,
|
|
5311
|
+
semanticCoverage: coverage.semanticCoverage
|
|
5312
|
+
});
|
|
5313
|
+
}
|
|
5314
|
+
|
|
5315
|
+
function freezeNativeImporterAdapterCoverageSnapshot(value = {}) {
|
|
5316
|
+
return Object.freeze({
|
|
5317
|
+
exactness: String(value.exactness ?? 'unknown'),
|
|
5318
|
+
exactAst: Boolean(value.exactAst),
|
|
5319
|
+
tokens: Boolean(value.tokens),
|
|
5320
|
+
trivia: Boolean(value.trivia),
|
|
5321
|
+
diagnostics: Boolean(value.diagnostics),
|
|
5322
|
+
sourceRanges: Boolean(value.sourceRanges),
|
|
5323
|
+
generatedRanges: Boolean(value.generatedRanges),
|
|
5324
|
+
semanticCoverage: normalizeNativeImporterSemanticCoverage(value.semanticCoverage, {})
|
|
5325
|
+
});
|
|
5326
|
+
}
|
|
5327
|
+
|
|
5328
|
+
function normalizeNativeImporterAdapterObservedCoverage(value = {}, declared = {}) {
|
|
5329
|
+
const diagnostics = Number(value.diagnostics ?? value.parserDiagnostics ?? 0) || 0;
|
|
5330
|
+
const semanticCoverage = normalizeNativeImporterSemanticCoverage({
|
|
5331
|
+
...(value.semanticCoverage ?? {}),
|
|
5332
|
+
declarations: value.semanticCoverage?.declarations ?? value.declarations,
|
|
5333
|
+
symbols: value.semanticCoverage?.symbols ?? value.symbols,
|
|
5334
|
+
references: value.semanticCoverage?.references ?? value.references,
|
|
5335
|
+
types: value.semanticCoverage?.types ?? value.types,
|
|
5336
|
+
controlFlow: value.semanticCoverage?.controlFlow ?? value.controlFlow
|
|
5337
|
+
}, {});
|
|
5338
|
+
const nativeAstNodes = Number(value.nativeAstNodes ?? 0) || 0;
|
|
5339
|
+
const exactness = String(value.exactness ?? observedAdapterExactness(declared, nativeAstNodes));
|
|
5340
|
+
return Object.freeze({
|
|
5341
|
+
exactness,
|
|
5342
|
+
exactAst: Boolean(value.exactAst ?? (declared.exactAst && nativeAstNodes > 0)),
|
|
5343
|
+
tokens: Boolean(value.tokens),
|
|
5344
|
+
tokenCount: Number(value.tokenCount ?? 0) || 0,
|
|
5345
|
+
trivia: Boolean(value.trivia),
|
|
5346
|
+
triviaCount: Number(value.triviaCount ?? 0) || 0,
|
|
5347
|
+
diagnostics,
|
|
5348
|
+
parserDiagnostics: diagnostics,
|
|
5349
|
+
diagnosticErrors: Number(value.diagnosticErrors ?? 0) || 0,
|
|
5350
|
+
diagnosticWarnings: Number(value.diagnosticWarnings ?? 0) || 0,
|
|
5351
|
+
diagnosticInfos: Number(value.diagnosticInfos ?? 0) || 0,
|
|
5352
|
+
losses: Number(value.losses ?? 0) || 0,
|
|
5353
|
+
nativeAstNodes,
|
|
5354
|
+
semanticSymbols: Number(value.semanticSymbols ?? 0) || 0,
|
|
5355
|
+
semanticReferences: Number(value.semanticReferences ?? 0) || 0,
|
|
5356
|
+
semanticTypes: Number(value.semanticTypes ?? 0) || 0,
|
|
5357
|
+
semanticControlFlow: Number(value.semanticControlFlow ?? 0) || 0,
|
|
5358
|
+
references: Boolean(value.references ?? semanticCoverage.references),
|
|
5359
|
+
types: Boolean(value.types ?? semanticCoverage.types),
|
|
5360
|
+
controlFlow: Boolean(value.controlFlow ?? semanticCoverage.controlFlow),
|
|
5361
|
+
sourceMapMappings: Number(value.sourceMapMappings ?? 0) || 0,
|
|
5362
|
+
sourceRanges: Boolean(value.sourceRanges),
|
|
5363
|
+
sourceRangeNodes: Number(value.sourceRangeNodes ?? 0) || 0,
|
|
5364
|
+
sourceRangeMappings: Number(value.sourceRangeMappings ?? 0) || 0,
|
|
5365
|
+
generatedRanges: Boolean(value.generatedRanges),
|
|
5366
|
+
generatedRangeMappings: Number(value.generatedRangeMappings ?? 0) || 0,
|
|
5367
|
+
semanticCoverage
|
|
5368
|
+
});
|
|
5369
|
+
}
|
|
5370
|
+
|
|
5371
|
+
function observeNativeImporterAdapterCoverageDetails(parseResult = {}, context = {}, observedContext = {}) {
|
|
5372
|
+
const declared = observedContext.declared ?? {};
|
|
5373
|
+
const nodeList = observedContext.nodeList ?? Object.values(parseResult.nativeAst?.nodes ?? parseResult.nodes ?? {});
|
|
5374
|
+
const sourceMapMappings = observedContext.sourceMapMappings
|
|
5375
|
+
?? parseResult.sourceMaps?.flatMap((sourceMap) => sourceMap.mappings ?? [])
|
|
5376
|
+
?? parseResult.mappings
|
|
5377
|
+
?? [];
|
|
5378
|
+
const semanticIndex = observedContext.semanticIndex ?? parseResult.semanticIndex;
|
|
5379
|
+
const semanticSymbols = observedContext.semanticSymbols ?? semanticIndex?.symbols?.length ?? 0;
|
|
5380
|
+
const diagnostics = context.diagnostics ?? [];
|
|
5381
|
+
const diagnosticErrors = diagnostics.filter((diagnostic) => diagnostic.severity === 'error').length;
|
|
5382
|
+
const diagnosticWarnings = diagnostics.filter((diagnostic) => diagnostic.severity === 'warning').length;
|
|
5383
|
+
const diagnosticInfos = diagnostics.filter((diagnostic) => diagnostic.severity === 'info').length;
|
|
5384
|
+
const sourceRangeNodes = nodeList.filter((node) => Boolean(node?.span)).length;
|
|
5385
|
+
const sourceRangeMappings = sourceMapMappings.filter((mapping) => Boolean(mapping?.sourceSpan)).length;
|
|
5386
|
+
const generatedRangeMappings = sourceMapMappings.filter((mapping) => Boolean(mapping?.generatedSpan)).length;
|
|
5387
|
+
const preservation = adapterCoverageSourcePreservation(parseResult);
|
|
5388
|
+
const tokenCount = preservation?.summary?.tokens ?? preservation?.tokens?.length ?? 0;
|
|
5389
|
+
const triviaCount = preservation?.summary?.trivia ?? preservation?.trivia?.length ?? 0;
|
|
5390
|
+
const semanticEvidence = observeNativeImporterSemanticEvidence(semanticIndex);
|
|
5391
|
+
const semanticCoverage = normalizeNativeImporterSemanticCoverage({
|
|
5392
|
+
level: maxSemanticCoverageLevel(
|
|
5393
|
+
semanticSymbols || semanticEvidence.declarations
|
|
5394
|
+
? 'declaration-index'
|
|
5395
|
+
: 'native-ast',
|
|
5396
|
+
semanticEvidence.references || semanticEvidence.types || semanticEvidence.controlFlow
|
|
5397
|
+
? 'semantic-index'
|
|
5398
|
+
: semanticSymbols ? 'declaration-index' : 'native-ast'
|
|
5399
|
+
),
|
|
5400
|
+
declarations: semanticSymbols > 0 || semanticEvidence.declarations > 0,
|
|
5401
|
+
symbols: semanticSymbols > 0,
|
|
5402
|
+
references: semanticEvidence.references > 0,
|
|
5403
|
+
types: semanticEvidence.types > 0,
|
|
5404
|
+
controlFlow: semanticEvidence.controlFlow > 0
|
|
5405
|
+
}, {});
|
|
5406
|
+
return normalizeNativeImporterAdapterObservedCoverage({
|
|
5407
|
+
exactness: observedAdapterExactness(declared, nodeList.length),
|
|
5408
|
+
exactAst: Boolean(declared.exactAst && nodeList.length > 0),
|
|
5409
|
+
tokens: tokenCount > 0,
|
|
5410
|
+
tokenCount,
|
|
5411
|
+
trivia: triviaCount > 0,
|
|
5412
|
+
triviaCount,
|
|
5413
|
+
diagnostics: diagnostics.length,
|
|
5414
|
+
parserDiagnostics: diagnostics.length,
|
|
5415
|
+
diagnosticErrors,
|
|
5416
|
+
diagnosticWarnings,
|
|
5417
|
+
diagnosticInfos,
|
|
5418
|
+
losses: context.losses?.length ?? 0,
|
|
5419
|
+
nativeAstNodes: nodeList.length,
|
|
5420
|
+
semanticSymbols,
|
|
5421
|
+
semanticReferences: semanticEvidence.references,
|
|
5422
|
+
semanticTypes: semanticEvidence.types,
|
|
5423
|
+
semanticControlFlow: semanticEvidence.controlFlow,
|
|
5424
|
+
references: semanticEvidence.references > 0,
|
|
5425
|
+
types: semanticEvidence.types > 0,
|
|
5426
|
+
controlFlow: semanticEvidence.controlFlow > 0,
|
|
5427
|
+
sourceMapMappings: sourceMapMappings.length,
|
|
5428
|
+
sourceRanges: sourceRangeNodes > 0 || sourceRangeMappings > 0,
|
|
5429
|
+
sourceRangeNodes,
|
|
5430
|
+
sourceRangeMappings,
|
|
5431
|
+
generatedRanges: generatedRangeMappings > 0,
|
|
5432
|
+
generatedRangeMappings,
|
|
5433
|
+
semanticCoverage
|
|
5434
|
+
}, declared);
|
|
5435
|
+
}
|
|
5436
|
+
|
|
5437
|
+
function adapterCoverageSourcePreservation(parseResult = {}) {
|
|
5438
|
+
return parseResult.sourcePreservation
|
|
5439
|
+
?? parseResult.nativeAst?.metadata?.sourcePreservation
|
|
5440
|
+
?? parseResult.nativeAstMetadata?.sourcePreservation
|
|
5441
|
+
?? parseResult.metadata?.sourcePreservation;
|
|
5442
|
+
}
|
|
5443
|
+
|
|
5444
|
+
function observeNativeImporterSemanticEvidence(semanticIndex = {}) {
|
|
5445
|
+
const occurrences = semanticIndex?.occurrences ?? [];
|
|
5446
|
+
const relations = semanticIndex?.relations ?? [];
|
|
5447
|
+
const facts = semanticIndex?.facts ?? [];
|
|
5448
|
+
const symbols = semanticIndex?.symbols ?? [];
|
|
5449
|
+
const referenceRelations = relations.filter((relation) => semanticPredicateMatches(relation?.predicate, ['reference', 'call', 'read', 'write', 'use']));
|
|
5450
|
+
const typeFacts = facts.filter((fact) => semanticPredicateMatches(fact?.predicate, ['type', 'declaredtype', 'inferredtype', 'typeof']));
|
|
5451
|
+
const typedSymbols = symbols.filter((symbol) => Boolean(symbol?.declaredType ?? symbol?.inferredType ?? symbol?.typeId ?? symbol?.valueType));
|
|
5452
|
+
const controlFlowRecords = [
|
|
5453
|
+
...relations.filter((relation) => semanticPredicateMatches(relation?.predicate, ['controlflow', 'cfg', 'flow'])),
|
|
5454
|
+
...facts.filter((fact) => semanticPredicateMatches(fact?.predicate, ['controlflow', 'cfg', 'flow']))
|
|
5455
|
+
];
|
|
5456
|
+
return {
|
|
5457
|
+
declarations: occurrences.filter((occurrence) => occurrence?.role === 'definition' || occurrence?.role === 'declaration').length,
|
|
5458
|
+
references: occurrences.filter((occurrence) => {
|
|
5459
|
+
const role = String(occurrence?.role ?? '').toLowerCase();
|
|
5460
|
+
return role && role !== 'definition' && role !== 'declaration';
|
|
5461
|
+
}).length + referenceRelations.length,
|
|
5462
|
+
types: typeFacts.length + typedSymbols.length,
|
|
5463
|
+
controlFlow: controlFlowRecords.length
|
|
5464
|
+
};
|
|
5465
|
+
}
|
|
5466
|
+
|
|
5467
|
+
function semanticPredicateMatches(value, fragments) {
|
|
5468
|
+
const predicate = String(value ?? '').toLowerCase().replace(/[^a-z0-9]+/g, '');
|
|
5469
|
+
return fragments.some((fragment) => predicate.includes(fragment));
|
|
5470
|
+
}
|
|
5471
|
+
|
|
5472
|
+
function observedAdapterExactness(declared = {}, nativeAstNodes = 0) {
|
|
5473
|
+
if (!nativeAstNodes) return 'unknown';
|
|
5474
|
+
if (declared.exactAst) return declared.exactness ?? 'exact-parser-ast';
|
|
5475
|
+
return 'adapter-reported-native-ast';
|
|
5476
|
+
}
|
|
5477
|
+
|
|
5478
|
+
function effectiveNativeImporterAdapterCoverage(declared, observed) {
|
|
5479
|
+
const semanticCoverage = normalizeNativeImporterSemanticCoverage({
|
|
5480
|
+
level: maxSemanticCoverageLevel(declared.semanticCoverage?.level, observed.semanticCoverage?.level),
|
|
5481
|
+
declarations: declared.semanticCoverage?.declarations || observed.semanticCoverage?.declarations,
|
|
5482
|
+
symbols: declared.semanticCoverage?.symbols || observed.semanticCoverage?.symbols,
|
|
5483
|
+
references: declared.semanticCoverage?.references || observed.semanticCoverage?.references,
|
|
5484
|
+
types: declared.semanticCoverage?.types || observed.semanticCoverage?.types,
|
|
5485
|
+
controlFlow: declared.semanticCoverage?.controlFlow || observed.semanticCoverage?.controlFlow
|
|
5486
|
+
}, {});
|
|
5487
|
+
return freezeNativeImporterAdapterCoverageSnapshot({
|
|
5488
|
+
exactness: effectiveAdapterExactness(declared, observed),
|
|
5489
|
+
exactAst: declared.exactAst || observed.exactAst,
|
|
5490
|
+
tokens: declared.tokens || observed.tokens,
|
|
5491
|
+
trivia: declared.trivia || observed.trivia,
|
|
5492
|
+
diagnostics: declared.diagnostics || observed.parserDiagnostics > 0,
|
|
5493
|
+
sourceRanges: declared.sourceRanges || observed.sourceRanges,
|
|
5494
|
+
generatedRanges: declared.generatedRanges || observed.generatedRanges,
|
|
5495
|
+
semanticCoverage
|
|
5496
|
+
});
|
|
5497
|
+
}
|
|
5498
|
+
|
|
5499
|
+
function effectiveAdapterExactness(declared, observed) {
|
|
5500
|
+
if (declared.exactAst || observed.exactAst) return declared.exactness ?? 'exact-parser-ast';
|
|
5501
|
+
if (observed.nativeAstNodes > 0) return observed.exactness ?? 'adapter-reported-native-ast';
|
|
5502
|
+
return declared.exactness ?? 'unknown';
|
|
5503
|
+
}
|
|
5504
|
+
|
|
5505
|
+
function nativeImporterAdapterCapabilityEvidence(declared, observed, effective) {
|
|
5506
|
+
const capabilityRows = [
|
|
5507
|
+
adapterCoverageCapabilityRow('exactAst', declared.exactAst, observed.exactAst, effective.exactAst, observed.nativeAstNodes),
|
|
5508
|
+
adapterCoverageCapabilityRow('tokens', declared.tokens, observed.tokens, effective.tokens, observed.tokenCount),
|
|
5509
|
+
adapterCoverageCapabilityRow('trivia', declared.trivia, observed.trivia, effective.trivia, observed.triviaCount),
|
|
5510
|
+
adapterCoverageCapabilityRow('parserDiagnostics', declared.diagnostics, observed.parserDiagnostics > 0, effective.diagnostics, observed.parserDiagnostics),
|
|
5511
|
+
adapterCoverageCapabilityRow('sourceRanges', declared.sourceRanges, observed.sourceRanges, effective.sourceRanges, observed.sourceRangeNodes + observed.sourceRangeMappings),
|
|
5512
|
+
adapterCoverageCapabilityRow('generatedRanges', declared.generatedRanges, observed.generatedRanges, effective.generatedRanges, observed.generatedRangeMappings),
|
|
5513
|
+
adapterCoverageCapabilityRow('semanticDeclarations', declared.semanticCoverage.declarations, observed.semanticCoverage.declarations, effective.semanticCoverage.declarations, observed.semanticSymbols),
|
|
5514
|
+
adapterCoverageCapabilityRow('semanticSymbols', declared.semanticCoverage.symbols, observed.semanticCoverage.symbols, effective.semanticCoverage.symbols, observed.semanticSymbols),
|
|
5515
|
+
adapterCoverageCapabilityRow('references', declared.semanticCoverage.references, observed.semanticCoverage.references, effective.semanticCoverage.references, observed.semanticReferences),
|
|
5516
|
+
adapterCoverageCapabilityRow('types', declared.semanticCoverage.types, observed.semanticCoverage.types, effective.semanticCoverage.types, observed.semanticTypes),
|
|
5517
|
+
adapterCoverageCapabilityRow('controlFlow', declared.semanticCoverage.controlFlow, observed.semanticCoverage.controlFlow, effective.semanticCoverage.controlFlow, observed.semanticControlFlow)
|
|
5518
|
+
];
|
|
5519
|
+
const reviewCapabilities = new Set(['exactAst', 'tokens', 'trivia', 'parserDiagnostics', 'sourceRanges', 'generatedRanges', 'references', 'types', 'controlFlow']);
|
|
5520
|
+
return Object.freeze({
|
|
5521
|
+
declared,
|
|
5522
|
+
observed,
|
|
5523
|
+
effective,
|
|
5524
|
+
capabilities: Object.freeze(capabilityRows),
|
|
5525
|
+
gaps: Object.freeze(capabilityRows.filter((row) => reviewCapabilities.has(row.capability) && !row.effective).map((row) => row.capability)),
|
|
5526
|
+
declaredOnly: Object.freeze(capabilityRows.filter((row) => row.declared && !row.observed).map((row) => row.capability)),
|
|
5527
|
+
observedOnly: Object.freeze(capabilityRows.filter((row) => !row.declared && row.observed).map((row) => row.capability)),
|
|
5528
|
+
parserDiagnostics: Object.freeze({
|
|
5529
|
+
declared: declared.diagnostics,
|
|
5530
|
+
observed: observed.parserDiagnostics > 0,
|
|
5531
|
+
count: observed.parserDiagnostics,
|
|
5532
|
+
errors: observed.diagnosticErrors,
|
|
5533
|
+
warnings: observed.diagnosticWarnings,
|
|
5534
|
+
infos: observed.diagnosticInfos
|
|
5535
|
+
}),
|
|
5536
|
+
sourceRanges: Object.freeze({
|
|
5537
|
+
declared: declared.sourceRanges,
|
|
5538
|
+
observed: observed.sourceRanges,
|
|
5539
|
+
nativeAstNodes: observed.nativeAstNodes,
|
|
5540
|
+
sourceRangeNodes: observed.sourceRangeNodes,
|
|
5541
|
+
sourceMapMappings: observed.sourceMapMappings,
|
|
5542
|
+
sourceRangeMappings: observed.sourceRangeMappings,
|
|
5543
|
+
generatedRangeMappings: observed.generatedRangeMappings
|
|
5544
|
+
}),
|
|
5545
|
+
tokensTrivia: Object.freeze({
|
|
5546
|
+
tokens: Object.freeze({ declared: declared.tokens, observed: observed.tokens, count: observed.tokenCount }),
|
|
5547
|
+
trivia: Object.freeze({ declared: declared.trivia, observed: observed.trivia, count: observed.triviaCount })
|
|
5548
|
+
}),
|
|
5549
|
+
semantic: Object.freeze({
|
|
5550
|
+
level: Object.freeze({
|
|
5551
|
+
declared: declared.semanticCoverage.level,
|
|
5552
|
+
observed: observed.semanticCoverage.level,
|
|
5553
|
+
effective: effective.semanticCoverage.level
|
|
5554
|
+
}),
|
|
5555
|
+
declarations: adapterCoverageCapabilityRow('semanticDeclarations', declared.semanticCoverage.declarations, observed.semanticCoverage.declarations, effective.semanticCoverage.declarations, observed.semanticSymbols),
|
|
5556
|
+
symbols: adapterCoverageCapabilityRow('semanticSymbols', declared.semanticCoverage.symbols, observed.semanticCoverage.symbols, effective.semanticCoverage.symbols, observed.semanticSymbols),
|
|
5557
|
+
references: adapterCoverageCapabilityRow('references', declared.semanticCoverage.references, observed.semanticCoverage.references, effective.semanticCoverage.references, observed.semanticReferences),
|
|
5558
|
+
types: adapterCoverageCapabilityRow('types', declared.semanticCoverage.types, observed.semanticCoverage.types, effective.semanticCoverage.types, observed.semanticTypes),
|
|
5559
|
+
controlFlow: adapterCoverageCapabilityRow('controlFlow', declared.semanticCoverage.controlFlow, observed.semanticCoverage.controlFlow, effective.semanticCoverage.controlFlow, observed.semanticControlFlow)
|
|
5560
|
+
})
|
|
5561
|
+
});
|
|
5562
|
+
}
|
|
5563
|
+
|
|
5564
|
+
function adapterCoverageCapabilityRow(capability, declared, observed, effective, count = 0) {
|
|
5565
|
+
const status = declared && observed
|
|
5566
|
+
? 'declared-and-observed'
|
|
5567
|
+
: declared ? 'declared-unobserved' : observed ? 'observed-undeclared' : 'absent';
|
|
5568
|
+
return Object.freeze({
|
|
5569
|
+
capability,
|
|
5570
|
+
declared: Boolean(declared),
|
|
5571
|
+
observed: Boolean(observed),
|
|
5572
|
+
effective: Boolean(effective),
|
|
5573
|
+
count: Number(count ?? 0) || 0,
|
|
5574
|
+
status
|
|
4884
5575
|
});
|
|
4885
5576
|
}
|
|
4886
5577
|
|
package/package.json
CHANGED