@shapeshift-labs/frontier-lang-compiler 0.2.101 → 0.2.103
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/dist/declarations/import-adapter-core.d.ts +6 -0
- package/dist/declarations/native-project-admission-semantic-evidence.d.ts +34 -0
- package/dist/declarations/native-project-admission.d.ts +6 -10
- package/dist/declarations/semantic-edit-script.d.ts +3 -0
- package/dist/declarations/semantic-patch-bundle-overlaps.d.ts +1 -0
- package/dist/internal/index-impl/createLightweightNativeImport.js +9 -1
- package/dist/internal/index-impl/createProjectImportAdmissionRecord.js +14 -2
- package/dist/internal/index-impl/diffNativeSymbols.js +82 -1
- package/dist/internal/index-impl/importNativeSource.js +14 -14
- package/dist/internal/index-impl/nativeImportSemanticIndex.js +33 -0
- package/dist/internal/index-impl/projectImportAdmissionImportEvidence.js +1 -1
- package/dist/internal/index-impl/projectImportAdmissionSemanticWarnings.js +178 -0
- package/dist/internal/index-impl/projectImportAdmissionSummaries.js +22 -3
- package/dist/internal/index-impl/projectSemanticEditScriptToSource.js +12 -62
- package/dist/internal/index-impl/replaySemanticEditProjection.js +43 -63
- package/dist/internal/index-impl/semanticEditImportProjection.js +53 -0
- package/dist/internal/index-impl/semanticEditProjectionRecord.js +79 -0
- package/dist/internal/index-impl/semanticEditReplayAnchors.js +63 -0
- package/dist/internal/index-impl/semanticEditSourceRanges.js +5 -0
- package/dist/internal/index-impl/semanticPatchBundleAdmission.js +51 -2
- package/dist/internal/index-impl/semanticPatchBundleOverlaps.js +33 -16
- package/dist/semantic-import-regions.js +12 -1
- package/package.json +1 -1
|
@@ -98,6 +98,10 @@ export interface ImportNativeSourceOptions {
|
|
|
98
98
|
readonly targetPath?: string;
|
|
99
99
|
readonly targetHash?: string;
|
|
100
100
|
readonly semanticIndex?: SemanticIndexRecord;
|
|
101
|
+
readonly ownershipRegions?: readonly SemanticImportOwnershipRegion[];
|
|
102
|
+
readonly semanticOwnershipRegions?: readonly SemanticImportOwnershipRegion[];
|
|
103
|
+
readonly patchHints?: readonly SemanticImportPatchHint[];
|
|
104
|
+
readonly semanticPatchHints?: readonly SemanticImportPatchHint[];
|
|
101
105
|
readonly sourceMapId?: string;
|
|
102
106
|
readonly sourceMaps?: readonly SourceMapRecord[];
|
|
103
107
|
readonly universalAstId?: string;
|
|
@@ -112,6 +116,8 @@ export interface ImportNativeSourceOptions {
|
|
|
112
116
|
export type NativeSourceImportResult = Omit<LanguageImportResult, 'metadata'> & {
|
|
113
117
|
readonly nativeSource: NativeSourceNode;
|
|
114
118
|
readonly semanticIndex?: SemanticIndexRecord;
|
|
119
|
+
readonly ownershipRegions: readonly SemanticImportOwnershipRegion[];
|
|
120
|
+
readonly patchHints: readonly SemanticImportPatchHint[];
|
|
115
121
|
readonly universalAst: FrontierUniversalAstEnvelope;
|
|
116
122
|
readonly metadata?: Record<string, unknown> & {
|
|
117
123
|
readonly sourcePreservationRecords?: readonly SourcePreservationRecord[];
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export type NativeProjectAdmissionSemanticEvidenceWarningCode =
|
|
2
|
+
| 'missing-ownership-regions'
|
|
3
|
+
| 'missing-patch-hints'
|
|
4
|
+
| (string & {});
|
|
5
|
+
|
|
6
|
+
export interface NativeProjectAdmissionSemanticEvidenceWarning {
|
|
7
|
+
readonly code: NativeProjectAdmissionSemanticEvidenceWarningCode;
|
|
8
|
+
readonly reasonCode: NativeProjectAdmissionSemanticEvidenceWarningCode;
|
|
9
|
+
readonly severity: 'warning' | string;
|
|
10
|
+
readonly message: string;
|
|
11
|
+
readonly action: string;
|
|
12
|
+
readonly sourcePath?: string;
|
|
13
|
+
readonly sourcePaths: readonly string[];
|
|
14
|
+
readonly semanticSymbols: number;
|
|
15
|
+
readonly ownershipRegions: number;
|
|
16
|
+
readonly patchHints: number;
|
|
17
|
+
readonly semanticImportExpected: boolean;
|
|
18
|
+
readonly changedSource: boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface NativeProjectAdmissionSemanticEvidence {
|
|
22
|
+
readonly empty: boolean;
|
|
23
|
+
readonly emptySourceCount: number;
|
|
24
|
+
readonly emptySourcePaths: readonly string[];
|
|
25
|
+
readonly symbols: number;
|
|
26
|
+
readonly occurrences: number;
|
|
27
|
+
readonly relations: number;
|
|
28
|
+
readonly facts: number;
|
|
29
|
+
readonly evidenceRecords: number;
|
|
30
|
+
readonly warningCount: number;
|
|
31
|
+
readonly warningReasonCodes: readonly NativeProjectAdmissionSemanticEvidenceWarningCode[];
|
|
32
|
+
readonly warningSourcePaths: readonly string[];
|
|
33
|
+
readonly warnings: readonly NativeProjectAdmissionSemanticEvidenceWarning[];
|
|
34
|
+
}
|
|
@@ -2,7 +2,13 @@ import type { FrontierSourceLanguage, SemanticMergeReadiness } from '@shapeshift
|
|
|
2
2
|
import type { NativeImportLossSummary } from './native-import-losses.js';
|
|
3
3
|
import type { NativeImportResultContract } from './native-import-contracts.js';
|
|
4
4
|
import type { NativeProjectImportResult } from './native-project.js';
|
|
5
|
+
import type { NativeProjectAdmissionSemanticEvidence } from './native-project-admission-semantic-evidence.js';
|
|
5
6
|
import type { SemanticMergeCandidateAdmissionRecord, SemanticMergeCandidateOverlapRecord, SemanticMergeCandidateProjectionRisk } from './semantic-merge-candidates.js';
|
|
7
|
+
export type {
|
|
8
|
+
NativeProjectAdmissionSemanticEvidence,
|
|
9
|
+
NativeProjectAdmissionSemanticEvidenceWarning,
|
|
10
|
+
NativeProjectAdmissionSemanticEvidenceWarningCode
|
|
11
|
+
} from './native-project-admission-semantic-evidence.js';
|
|
6
12
|
export type NativeProjectImportAdmissionAction = 'admit' | 'prioritize' | 'reject';
|
|
7
13
|
export type NativeProjectImportAdmissionPriority = 'low' | 'normal' | 'high' | 'critical' | 'blocker';
|
|
8
14
|
export type NativeProjectImportAdmissionRisk = 'low' | 'medium' | 'high' | 'unknown';
|
|
@@ -133,16 +139,6 @@ export interface NativeProjectAdmissionLanguages {
|
|
|
133
139
|
readonly readinessRows: readonly NativeProjectAdmissionLanguageReadinessSummary[];
|
|
134
140
|
readonly rows: readonly NativeProjectAdmissionLanguageSummary[];
|
|
135
141
|
}
|
|
136
|
-
export interface NativeProjectAdmissionSemanticEvidence {
|
|
137
|
-
readonly empty: boolean;
|
|
138
|
-
readonly emptySourceCount: number;
|
|
139
|
-
readonly emptySourcePaths: readonly string[];
|
|
140
|
-
readonly symbols: number;
|
|
141
|
-
readonly occurrences: number;
|
|
142
|
-
readonly relations: number;
|
|
143
|
-
readonly facts: number;
|
|
144
|
-
readonly evidenceRecords: number;
|
|
145
|
-
}
|
|
146
142
|
export type NativeProjectAdmissionSourceStalenessReason =
|
|
147
143
|
| 'source-hash-mismatch'
|
|
148
144
|
| 'content-hash-mismatch'
|
|
@@ -147,7 +147,10 @@ export interface SemanticEditProjectionEdit {
|
|
|
147
147
|
readonly replacementBytes: number;
|
|
148
148
|
readonly deletedTextHash?: string;
|
|
149
149
|
readonly replacementTextHash?: string;
|
|
150
|
+
readonly deletedTextLineEndingStableHash?: string;
|
|
151
|
+
readonly replacementTextLineEndingStableHash?: string;
|
|
150
152
|
readonly replacementSpanTextHash?: string;
|
|
153
|
+
readonly replacementSpanTextLineEndingStableHash?: string;
|
|
151
154
|
readonly insertionMode?: string;
|
|
152
155
|
readonly insertionAnchorKey?: string;
|
|
153
156
|
readonly insertionAnchorSymbolName?: string;
|
|
@@ -71,6 +71,7 @@ export interface SemanticPatchBundleOverlapRecord {
|
|
|
71
71
|
readonly sourceSignals: number;
|
|
72
72
|
readonly baseHashMismatch: boolean;
|
|
73
73
|
readonly targetHashMismatch: boolean;
|
|
74
|
+
readonly replayOutputHashMismatch: boolean;
|
|
74
75
|
};
|
|
75
76
|
readonly metadata?: Record<string, unknown>;
|
|
76
77
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{idFragment}from'../../native-import-utils.js';import{lightweightDependencyRelations}from'../../lightweight-dependency-relations.js';import{lightweightCoverageLosses,scanNativeDeclarations}from'../../native-region-scanner.js';import{semanticOwnershipRegionForDeclaration}from'../../semantic-import-regions.js';import{createSemanticIndexRecord,hashSemanticValue}from'@shapeshift-labs/frontier-lang-kernel';
|
|
1
|
+
import{idFragment,uniqueRecordsById}from'../../native-import-utils.js';import{lightweightDependencyRelations}from'../../lightweight-dependency-relations.js';import{lightweightCoverageLosses,scanNativeDeclarations}from'../../native-region-scanner.js';import{semanticOwnershipRegionForDeclaration,semanticPatchHintForRegion}from'../../semantic-import-regions.js';import{createSemanticIndexRecord,hashSemanticValue}from'@shapeshift-labs/frontier-lang-kernel';
|
|
2
2
|
export function createLightweightNativeImport(input) {
|
|
3
3
|
const parser = input.parser ?? `${input.language}.lightweight-declaration-scan`;
|
|
4
4
|
const rootId = 'native_root';
|
|
@@ -19,11 +19,13 @@ export function createLightweightNativeImport(input) {
|
|
|
19
19
|
const relations = [];
|
|
20
20
|
const facts = [];
|
|
21
21
|
const mappings = [];
|
|
22
|
+
const ownershipRegions = [];
|
|
22
23
|
const evidenceId = `evidence_${idFragment(input.sourcePath ?? input.language)}_lightweight_scan`;
|
|
23
24
|
const dependencies = lightweightDependencyRelations(input, declarations, documentId);
|
|
24
25
|
|
|
25
26
|
for (const declaration of declarations) {
|
|
26
27
|
const ownershipRegion = semanticOwnershipRegionForDeclaration(input, declaration, documentId);
|
|
28
|
+
ownershipRegions.push(ownershipRegion);
|
|
27
29
|
nodes[rootId].children.push(declaration.nodeId);
|
|
28
30
|
nodes[declaration.nodeId] = {
|
|
29
31
|
id: declaration.nodeId,
|
|
@@ -122,6 +124,8 @@ export function createLightweightNativeImport(input) {
|
|
|
122
124
|
});
|
|
123
125
|
}
|
|
124
126
|
losses.push(...lightweightCoverageLosses(input, declarations, input.sourcePreservation));
|
|
127
|
+
const semanticOwnershipRegions = uniqueRecordsById(ownershipRegions);
|
|
128
|
+
const semanticPatchHints = semanticOwnershipRegions.map((region) => semanticPatchHintForRegion(region, 'needs-review'));
|
|
125
129
|
|
|
126
130
|
const semanticIndex = createSemanticIndexRecord({
|
|
127
131
|
id: `index_${idFragment(input.sourcePath ?? input.language)}`,
|
|
@@ -135,6 +139,8 @@ export function createLightweightNativeImport(input) {
|
|
|
135
139
|
occurrences,
|
|
136
140
|
relations,
|
|
137
141
|
facts,
|
|
142
|
+
ownershipRegions: semanticOwnershipRegions,
|
|
143
|
+
patchHints: semanticPatchHints,
|
|
138
144
|
evidence: [{
|
|
139
145
|
id: evidenceId,
|
|
140
146
|
kind: 'import',
|
|
@@ -162,6 +168,8 @@ export function createLightweightNativeImport(input) {
|
|
|
162
168
|
losses,
|
|
163
169
|
semanticIndex,
|
|
164
170
|
mappings,
|
|
171
|
+
ownershipRegions: semanticOwnershipRegions,
|
|
172
|
+
patchHints: semanticPatchHints,
|
|
165
173
|
metadata: {
|
|
166
174
|
parser,
|
|
167
175
|
scanKind: 'lightweight-declaration-scan',
|
|
@@ -19,7 +19,7 @@ export function createProjectImportAdmissionRecord(projectResult,options={}){
|
|
|
19
19
|
...(projectResult?.mergeCandidates??[]),
|
|
20
20
|
...imports.flatMap((imported)=>imported?.mergeCandidates??[])
|
|
21
21
|
]);
|
|
22
|
-
const importSummaries=projectAdmissionImports(imports,contract?.sources??[],mergeCandidates);
|
|
22
|
+
const importSummaries=projectAdmissionImports(imports,contract?.sources??[],mergeCandidates,projectResult);
|
|
23
23
|
const languages=admissionLanguages(importSummaries);
|
|
24
24
|
const semanticEvidence=admissionSemanticEvidence(projectResult,imports,importSummaries);
|
|
25
25
|
const sourceStaleness=admissionSourceStaleness(imports,importSummaries,contract);
|
|
@@ -42,7 +42,10 @@ export function createProjectImportAdmissionRecord(projectResult,options={}){
|
|
|
42
42
|
failedEvidenceIds,
|
|
43
43
|
blockingLossIds:contract?.readiness?.blockingLossIds??lossSummary?.blockingLossIds??[]
|
|
44
44
|
});
|
|
45
|
-
const priorityReasons=
|
|
45
|
+
const priorityReasons=uniqueStrings([
|
|
46
|
+
...admissionPriorityReasons({readiness,semanticEvidence,sourcePreservation,ownership,mergeCandidateRisk}),
|
|
47
|
+
...semanticAdmissionWarningReasons(semanticEvidence)
|
|
48
|
+
]);
|
|
46
49
|
const action=rejectionReasons.length?'reject':priorityReasons.length?'prioritize':'admit';
|
|
47
50
|
const priority=admissionPriority(action,readiness,sourcePreservation,mergeCandidateRisk);
|
|
48
51
|
const mergeScore=admissionMergeScore({
|
|
@@ -221,6 +224,15 @@ function admissionSourcePreservationWithStaleness(sourcePreservation,sourceStale
|
|
|
221
224
|
};
|
|
222
225
|
}
|
|
223
226
|
|
|
227
|
+
function semanticAdmissionWarningReasons(semanticEvidence){
|
|
228
|
+
return (semanticEvidence?.warnings??[]).map((warning)=>{
|
|
229
|
+
const reasonCode=warning.reasonCode??warning.code;
|
|
230
|
+
const sourcePaths=warning.sourcePaths?.length?warning.sourcePaths:warning.sourcePath?[warning.sourcePath]:[];
|
|
231
|
+
const sourceText=sourcePaths.length?` for ${sourcePaths.join(', ')}`:'';
|
|
232
|
+
return `Project import semantic admission warning ${reasonCode}${sourceText}.`;
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
|
|
224
236
|
function sourcePaths(records){
|
|
225
237
|
return uniqueStrings(records.map((record)=>record.sourcePath).filter(Boolean));
|
|
226
238
|
}
|
|
@@ -37,5 +37,86 @@ export function diffNativeSymbols(beforeSymbols, afterSymbols) {
|
|
|
37
37
|
readiness: maxSemanticMergeReadiness(before?.readiness ?? 'ready', after?.readiness ?? 'ready')
|
|
38
38
|
});
|
|
39
39
|
}
|
|
40
|
-
return changed;
|
|
40
|
+
return downgradeCoveredContainerSymbols(changed);
|
|
41
41
|
}
|
|
42
|
+
|
|
43
|
+
function downgradeCoveredContainerSymbols(symbols) {
|
|
44
|
+
return symbols.filter((symbol) => !nativeDiffContainerCoveredByMorePreciseChange(symbol, symbols));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function nativeDiffContainerCoveredByMorePreciseChange(symbol, symbols) {
|
|
48
|
+
if (symbol.changeKind !== 'modified') return false;
|
|
49
|
+
if (!nativeDiffSymbolIsContainer(symbol)) return false;
|
|
50
|
+
if (nativeDiffSymbolHasOwnChange(symbol)) return false;
|
|
51
|
+
return symbols.some((candidate) => candidate !== symbol && nativeDiffSymbolIsMorePreciseNestedChange(candidate, symbol));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function nativeDiffSymbolHasOwnChange(symbol) {
|
|
55
|
+
return ((symbol.beforeSignatureHash ?? '') !== (symbol.afterSignatureHash ?? ''))
|
|
56
|
+
|| ((symbol.beforeOwnershipKey ?? '') !== (symbol.afterOwnershipKey ?? ''))
|
|
57
|
+
|| ((symbol.beforeNativeAstNodeId ?? '') !== (symbol.afterNativeAstNodeId ?? ''));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function nativeDiffSymbolIsMorePreciseNestedChange(candidate, container) {
|
|
61
|
+
if (candidate.changeKind === 'unchanged') return false;
|
|
62
|
+
if (nativeDiffSymbolIsContainer(candidate)) return false;
|
|
63
|
+
if ((candidate.ownershipKey ?? '') === (container.ownershipKey ?? '')) return false;
|
|
64
|
+
if (!nativeDiffAnySpanContains(container, candidate)) return false;
|
|
65
|
+
return nativeDiffNestedSymbolName(candidate, container) || nativeDiffSymbolIsMember(candidate);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function nativeDiffSymbolIsContainer(symbol) {
|
|
69
|
+
return nativeDiffContainerKinds.has(nativeDiffKind(symbol.ownershipRegionKind ?? symbol.kind));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function nativeDiffSymbolIsMember(symbol) {
|
|
73
|
+
return nativeDiffMemberKinds.has(nativeDiffKind(symbol.ownershipRegionKind ?? symbol.kind));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function nativeDiffNestedSymbolName(candidate, container) {
|
|
77
|
+
const candidateName = String(candidate.name ?? '');
|
|
78
|
+
const containerName = String(container.name ?? '');
|
|
79
|
+
return Boolean(containerName && candidateName && candidateName !== containerName && candidateName.startsWith(`${containerName}.`));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function nativeDiffAnySpanContains(container, candidate) {
|
|
83
|
+
return nativeDiffSymbolSpans(container).some((containerSpan) => nativeDiffSymbolSpans(candidate).some((candidateSpan) => (
|
|
84
|
+
nativeDiffSameSourcePath(candidateSpan, containerSpan) && nativeDiffSpanContains(containerSpan, candidateSpan)
|
|
85
|
+
)));
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function nativeDiffSymbolSpans(symbol) {
|
|
89
|
+
return [symbol.sourceSpan, symbol.beforeSourceSpan, symbol.afterSourceSpan].filter(Boolean);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function nativeDiffSameSourcePath(left, right) {
|
|
93
|
+
const leftPath = left?.path;
|
|
94
|
+
const rightPath = right?.path;
|
|
95
|
+
return !leftPath || !rightPath || leftPath === rightPath;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function nativeDiffSpanContains(containerSpan, candidateSpan) {
|
|
99
|
+
const container = nativeDiffSpanRange(containerSpan);
|
|
100
|
+
const candidate = nativeDiffSpanRange(candidateSpan);
|
|
101
|
+
if (!container || !candidate) return false;
|
|
102
|
+
return container.start <= candidate.start && candidate.end <= container.end && (container.start !== candidate.start || container.end !== candidate.end);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function nativeDiffSpanRange(span) {
|
|
106
|
+
const startLine = Number(span?.startLine ?? span?.line ?? span?.start?.line);
|
|
107
|
+
const endLine = Number(span?.endLine ?? span?.end?.line ?? startLine);
|
|
108
|
+
if (!Number.isFinite(startLine) || !Number.isFinite(endLine)) return undefined;
|
|
109
|
+
const startColumn = Number(span?.startColumn ?? span?.column ?? span?.start?.column ?? 0);
|
|
110
|
+
const endColumn = Number(span?.endColumn ?? span?.end?.column ?? startColumn);
|
|
111
|
+
return {
|
|
112
|
+
start: startLine * 100000 + (Number.isFinite(startColumn) ? startColumn : 0),
|
|
113
|
+
end: endLine * 100000 + Math.max(Number.isFinite(startColumn) ? startColumn : 0, Number.isFinite(endColumn) ? endColumn : 0)
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function nativeDiffKind(value) {
|
|
118
|
+
return String(value ?? '').toLowerCase();
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const nativeDiffContainerKinds = new Set(['type', 'class', 'interface', 'trait', 'protocol', 'struct', 'enum', 'record']);
|
|
122
|
+
const nativeDiffMemberKinds = new Set(['body', 'method', 'function', 'property', 'declaration']);
|
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
import{commonGeneratedTargetPath,idFragment}from'../../native-import-utils.js';import{inferSourceMapMappings,normalizeSourceMapMappings,normalizeSourceMaps}from'../../native-source-maps.js';import{createKernelSourcePreservationRecords,summarizeKernelSourcePreservationRecords}from'../../semantic-import-source-preservation.js';import{createDocument,createImportResult,createNativeAstRecord,createPatch,createSourceMapRecord,createUniversalAstEnvelope,hashSemanticValue,nativeSourceNode}from'@shapeshift-labs/frontier-lang-kernel';
|
|
2
2
|
import{attachInputUniversalDialectRegistry}from'../../universal-dialect-registry.js';
|
|
3
3
|
import{createLightweightSemanticLayers}from'./createLightweightSemanticLayers.js';
|
|
4
|
-
import{attachNativeImportLossSummary}from'./attachNativeImportLossSummary.js';import{createLightweightNativeImport}from'./createLightweightNativeImport.js';import{createNativeSourcePreservation}from'./createNativeSourcePreservation.js';import{hasNativeExactAstEvidence}from'./hasNativeExactAstEvidence.js';import{normalizeNativeLossRecords}from'./normalizeNativeLossRecords.js';import{summarizeNativeImportLosses}from'./summarizeNativeImportLosses.js';import{unverifiedNativeAstLosses}from'./unverifiedNativeAstLosses.js';import{withNativeImportReadiness}from'./withNativeImportReadiness.js';
|
|
4
|
+
import{attachNativeImportLossSummary}from'./attachNativeImportLossSummary.js';import{createLightweightNativeImport}from'./createLightweightNativeImport.js';import{createNativeSourcePreservation}from'./createNativeSourcePreservation.js';import{hasNativeExactAstEvidence}from'./hasNativeExactAstEvidence.js';import{createNativeImportSemanticIndex}from'./nativeImportSemanticIndex.js';import{normalizeNativeLossRecords}from'./normalizeNativeLossRecords.js';import{summarizeNativeImportLosses}from'./summarizeNativeImportLosses.js';import{unverifiedNativeAstLosses}from'./unverifiedNativeAstLosses.js';import{withNativeImportReadiness}from'./withNativeImportReadiness.js';
|
|
5
5
|
export function importNativeSource(input) {
|
|
6
6
|
const language = input.language ?? input.nativeAst?.language;
|
|
7
7
|
if (!language) throw new Error('importNativeSource requires a language or nativeAst.language');
|
|
8
8
|
const sourcePath = input.sourcePath ?? input.nativeAst?.sourcePath;
|
|
9
9
|
const declaredSourceHash = input.sourceHash ?? input.nativeAst?.sourceHash;
|
|
10
|
-
const sourceHash = typeof input.sourceText === 'string'
|
|
11
|
-
|
|
12
|
-
: declaredSourceHash ?? hashSemanticValue(input.nativeAst?.nodes ?? input.nativeAst ?? {});
|
|
13
|
-
const targetPath = input.targetPath ?? input.target?.emitPath;
|
|
14
|
-
const targetHash = input.targetHash;
|
|
10
|
+
const sourceHash = typeof input.sourceText === 'string' ? hashSemanticValue(input.sourceText) : declaredSourceHash ?? hashSemanticValue(input.nativeAst?.nodes ?? input.nativeAst ?? {});
|
|
11
|
+
const targetPath = input.targetPath ?? input.target?.emitPath; const targetHash = input.targetHash;
|
|
15
12
|
const importIdPart = idFragment(input.id ?? input.nativeSourceId ?? sourcePath ?? language);
|
|
16
13
|
const sourcePreservation = input.sourcePreservation ?? (typeof input.sourceText === 'string'
|
|
17
14
|
? createNativeSourcePreservation({
|
|
@@ -146,6 +143,7 @@ export function importNativeSource(input) {
|
|
|
146
143
|
});
|
|
147
144
|
const evidence = attachNativeImportLossSummary(baseEvidence, lossSummary);
|
|
148
145
|
const semanticIndex = input.semanticIndex ?? lightweight?.semanticIndex;
|
|
146
|
+
const { ownershipRegions, patchHints, semanticIndexForResult } = createNativeImportSemanticIndex(input, lightweight, semanticIndex);
|
|
149
147
|
const sourceMapMappings = normalizeSourceMapMappings(
|
|
150
148
|
input.mappings ?? lightweight?.mappings ?? inferSourceMapMappings({
|
|
151
149
|
semanticIndex,
|
|
@@ -174,7 +172,7 @@ export function importNativeSource(input) {
|
|
|
174
172
|
target: input.target,
|
|
175
173
|
targetPath: inferredTargetPath,
|
|
176
174
|
targetHash,
|
|
177
|
-
semanticIndexId:
|
|
175
|
+
semanticIndexId: semanticIndexForResult?.id,
|
|
178
176
|
nativeAstId: nativeAst.id,
|
|
179
177
|
nativeSourceId: nativeSource.id,
|
|
180
178
|
mappings: sourceMapMappings,
|
|
@@ -191,7 +189,7 @@ export function importNativeSource(input) {
|
|
|
191
189
|
nativeSources: [nativeSource],
|
|
192
190
|
nativeAst,
|
|
193
191
|
nativeSource,
|
|
194
|
-
semanticIndex,
|
|
192
|
+
semanticIndex: semanticIndexForResult,
|
|
195
193
|
evidence,
|
|
196
194
|
losses,
|
|
197
195
|
sourcePreservation,
|
|
@@ -213,16 +211,16 @@ export function importNativeSource(input) {
|
|
|
213
211
|
evidence,
|
|
214
212
|
nativeSource,
|
|
215
213
|
nativeAst,
|
|
216
|
-
semanticIndex
|
|
214
|
+
semanticIndex: semanticIndexForResult
|
|
217
215
|
});
|
|
218
216
|
const kernelSourcePreservationSummary = summarizeKernelSourcePreservationRecords(sourcePreservationRecords);
|
|
219
217
|
const resultSourceMapMappings = sourceMaps.flatMap((sourceMap) => sourceMap.mappings ?? []);
|
|
220
|
-
const semanticLayers=input.semanticLayers??createLightweightSemanticLayers({importIdPart,language,sourcePath,sourceHash,nativeSource,nativeAst,semanticIndex,sourceMaps,losses,evidence,sourcePreservationRecords});
|
|
218
|
+
const semanticLayers=input.semanticLayers??createLightweightSemanticLayers({importIdPart,language,sourcePath,sourceHash,nativeSource,nativeAst,semanticIndex:semanticIndexForResult,sourceMaps,losses,evidence,sourcePreservationRecords});
|
|
221
219
|
let universalAst = createUniversalAstEnvelope({
|
|
222
220
|
id: input.universalAstId ?? `universal_ast_${importIdPart}`,
|
|
223
221
|
document,
|
|
224
222
|
nativeSources: [nativeSource],
|
|
225
|
-
semanticIndex,
|
|
223
|
+
semanticIndex: semanticIndexForResult,
|
|
226
224
|
sourceMaps,
|
|
227
225
|
losses,
|
|
228
226
|
evidence,
|
|
@@ -262,7 +260,7 @@ export function importNativeSource(input) {
|
|
|
262
260
|
metadata: {
|
|
263
261
|
sourceLanguage: language,
|
|
264
262
|
sourcePath,
|
|
265
|
-
semanticIndexId:
|
|
263
|
+
semanticIndexId: semanticIndexForResult?.id,
|
|
266
264
|
universalAstId: universalAst.id,
|
|
267
265
|
sourceMapIds: sourceMaps.map((sourceMap) => sourceMap.id),
|
|
268
266
|
...(sourcePreservation ? {
|
|
@@ -287,14 +285,16 @@ export function importNativeSource(input) {
|
|
|
287
285
|
document,
|
|
288
286
|
patch,
|
|
289
287
|
nativeAst,
|
|
290
|
-
semanticIndex,
|
|
288
|
+
semanticIndex: semanticIndexForResult,
|
|
291
289
|
universalAst,
|
|
292
290
|
sourceMaps,
|
|
291
|
+
ownershipRegions,
|
|
292
|
+
patchHints: semanticIndexForResult?.patchHints ?? patchHints,
|
|
293
293
|
losses,
|
|
294
294
|
evidence,
|
|
295
295
|
metadata: {
|
|
296
296
|
nativeSourceId: nativeSource.id,
|
|
297
|
-
semanticIndexId:
|
|
297
|
+
semanticIndexId: semanticIndexForResult?.id,
|
|
298
298
|
universalAstId: universalAst.id,
|
|
299
299
|
sourceMapIds: sourceMaps.map((sourceMap) => sourceMap.id),
|
|
300
300
|
semanticStatus,
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import{uniqueRecordsById}from'../../native-import-utils.js';
|
|
2
|
+
import{semanticOwnershipRegionsFromSemanticIndex,semanticPatchHintForRegion}from'../../semantic-import-regions.js';
|
|
3
|
+
|
|
4
|
+
export function createNativeImportSemanticIndex(input, lightweight, semanticIndex) {
|
|
5
|
+
const ownershipRegions = uniqueRecordsById([
|
|
6
|
+
...(Array.isArray(input.ownershipRegions) ? input.ownershipRegions : []),
|
|
7
|
+
...(Array.isArray(input.semanticOwnershipRegions) ? input.semanticOwnershipRegions : []),
|
|
8
|
+
...(lightweight?.ownershipRegions ?? []),
|
|
9
|
+
...semanticOwnershipRegionsFromSemanticIndex(semanticIndex),
|
|
10
|
+
...(Array.isArray(input.universalAst?.ownershipRegions) ? input.universalAst.ownershipRegions : []),
|
|
11
|
+
...(Array.isArray(input.metadata?.ownershipRegions) ? input.metadata.ownershipRegions : [])
|
|
12
|
+
]);
|
|
13
|
+
const patchHints = uniqueRecordsById([
|
|
14
|
+
...(Array.isArray(input.patchHints) ? input.patchHints : []),
|
|
15
|
+
...(Array.isArray(input.semanticPatchHints) ? input.semanticPatchHints : []),
|
|
16
|
+
...(lightweight?.patchHints ?? []),
|
|
17
|
+
...(Array.isArray(semanticIndex?.patchHints) ? semanticIndex.patchHints : []),
|
|
18
|
+
...(Array.isArray(input.universalAst?.patchHints) ? input.universalAst.patchHints : []),
|
|
19
|
+
...(Array.isArray(input.metadata?.patchHints) ? input.metadata.patchHints : [])
|
|
20
|
+
]);
|
|
21
|
+
const resultPatchHints = patchHints.length
|
|
22
|
+
? patchHints
|
|
23
|
+
: ownershipRegions.map((region) => semanticPatchHintForRegion(region, 'needs-review'));
|
|
24
|
+
return {
|
|
25
|
+
ownershipRegions,
|
|
26
|
+
patchHints: resultPatchHints,
|
|
27
|
+
semanticIndexForResult: semanticIndex ? {
|
|
28
|
+
...semanticIndex,
|
|
29
|
+
ownershipRegions,
|
|
30
|
+
patchHints: resultPatchHints
|
|
31
|
+
} : semanticIndex
|
|
32
|
+
};
|
|
33
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import{uniqueStrings}from'../../native-import-utils.js';
|
|
2
2
|
import{nativeImportCategoryForLossKind}from'./nativeImportCategoryForLossKind.js';
|
|
3
|
+
export{summarizeSemanticAdmissionWarnings}from'./projectImportAdmissionSemanticWarnings.js';
|
|
3
4
|
|
|
4
5
|
export function importLosses(imported){
|
|
5
6
|
const nativeAst=imported?.nativeAst??imported?.nativeSource?.ast;
|
|
@@ -157,4 +158,3 @@ export function summarizeImportPreservation(imported,source){
|
|
|
157
158
|
const quality=stale?'stale':missing?'missing':truncated||!exactSourceAvailable||sourcePreservationLosses.length?'lossy':'exact';
|
|
158
159
|
return {quality,missing,stale,truncated,exactSourceAvailable,lossCount:sourcePreservationLosses.length,id:record?.id};
|
|
159
160
|
}
|
|
160
|
-
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { uniqueRecordsById, uniqueStrings } from '../../native-import-utils.js';
|
|
2
|
+
import { semanticOwnershipRegionsFromSemanticIndex } from '../../semantic-import-regions.js';
|
|
3
|
+
|
|
4
|
+
export function summarizeSemanticAdmissionWarnings(imported, context = {}) {
|
|
5
|
+
const semanticIndex = imported?.semanticIndex ?? imported?.universalAst?.semanticIndex;
|
|
6
|
+
const symbols = semanticSymbolsForImport(imported, semanticIndex);
|
|
7
|
+
const ownershipRegions = semanticOwnershipRegionsForImport(imported, semanticIndex);
|
|
8
|
+
const patchHints = semanticPatchHintsForImport(imported, semanticIndex);
|
|
9
|
+
const sourcePath = firstString(context.sourcePath, context.source?.sourcePath, imported?.sourcePath, imported?.nativeSource?.sourcePath, imported?.nativeAst?.sourcePath, semanticIndex?.documents?.[0]?.path);
|
|
10
|
+
const semanticImportExpected = isSemanticImportExpected(imported, context);
|
|
11
|
+
const semanticImportExpectedEmpty = isSemanticImportExpectedEmpty(imported, context);
|
|
12
|
+
const changedSource = isChangedSemanticAdmissionSource(imported, { ...context, sourcePath });
|
|
13
|
+
const warnings = [];
|
|
14
|
+
if (semanticImportExpected && !semanticImportExpectedEmpty && changedSource && symbols.length > 0 && ownershipRegions.length === 0) {
|
|
15
|
+
warnings.push(semanticAdmissionWarning({
|
|
16
|
+
code: 'missing-ownership-regions',
|
|
17
|
+
message: 'Semantic import was expected for a changed source and produced symbols, but no ownership regions were available.',
|
|
18
|
+
action: 'rerun-sidecar-generation-with-ownership-regions',
|
|
19
|
+
sourcePath,
|
|
20
|
+
symbols,
|
|
21
|
+
ownershipRegions,
|
|
22
|
+
patchHints,
|
|
23
|
+
semanticImportExpected,
|
|
24
|
+
changedSource
|
|
25
|
+
}));
|
|
26
|
+
}
|
|
27
|
+
if (semanticImportExpected && !semanticImportExpectedEmpty && changedSource && symbols.length > 0 && patchHints.length === 0) {
|
|
28
|
+
warnings.push(semanticAdmissionWarning({
|
|
29
|
+
code: 'missing-patch-hints',
|
|
30
|
+
message: 'Semantic import was expected for a changed source and produced symbols, but no patch hints were available.',
|
|
31
|
+
action: 'generate-semantic-patch-hints',
|
|
32
|
+
sourcePath,
|
|
33
|
+
symbols,
|
|
34
|
+
ownershipRegions,
|
|
35
|
+
patchHints,
|
|
36
|
+
semanticImportExpected,
|
|
37
|
+
changedSource
|
|
38
|
+
}));
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
semanticImportExpected,
|
|
42
|
+
semanticImportExpectedEmpty,
|
|
43
|
+
changedSource,
|
|
44
|
+
symbolCount: symbols.length,
|
|
45
|
+
ownershipRegionCount: ownershipRegions.length,
|
|
46
|
+
patchHintCount: patchHints.length,
|
|
47
|
+
warningCount: warnings.length,
|
|
48
|
+
reasonCodes: uniqueStrings(warnings.map((warning) => warning.reasonCode)),
|
|
49
|
+
warnings
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function semanticAdmissionWarning(input) {
|
|
54
|
+
return {
|
|
55
|
+
code: input.code,
|
|
56
|
+
reasonCode: input.code,
|
|
57
|
+
severity: 'warning',
|
|
58
|
+
message: input.message,
|
|
59
|
+
action: input.action,
|
|
60
|
+
...(input.sourcePath ? { sourcePath: input.sourcePath } : {}),
|
|
61
|
+
sourcePaths: uniqueStrings([input.sourcePath].filter(Boolean)),
|
|
62
|
+
semanticSymbols: input.symbols.length,
|
|
63
|
+
ownershipRegions: input.ownershipRegions.length,
|
|
64
|
+
patchHints: input.patchHints.length,
|
|
65
|
+
semanticImportExpected: input.semanticImportExpected,
|
|
66
|
+
changedSource: input.changedSource
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function semanticSymbolsForImport(imported, semanticIndex) {
|
|
71
|
+
if (Array.isArray(semanticIndex?.symbols)) return semanticIndex.symbols;
|
|
72
|
+
for (const symbols of [
|
|
73
|
+
imported?.semanticSymbols,
|
|
74
|
+
imported?.symbols,
|
|
75
|
+
imported?.metadata?.semanticSymbols,
|
|
76
|
+
imported?.metadata?.symbols
|
|
77
|
+
]) {
|
|
78
|
+
if (Array.isArray(symbols)) return symbols;
|
|
79
|
+
}
|
|
80
|
+
return [];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function semanticOwnershipRegionsForImport(imported, semanticIndex) {
|
|
84
|
+
return uniqueRecordsById([
|
|
85
|
+
...(Array.isArray(imported?.ownershipRegions) ? imported.ownershipRegions : []),
|
|
86
|
+
...(Array.isArray(imported?.semanticOwnershipRegions) ? imported.semanticOwnershipRegions : []),
|
|
87
|
+
...semanticOwnershipRegionsFromSemanticIndex(semanticIndex),
|
|
88
|
+
...(Array.isArray(imported?.universalAst?.ownershipRegions) ? imported.universalAst.ownershipRegions : []),
|
|
89
|
+
...(Array.isArray(imported?.metadata?.ownershipRegions) ? imported.metadata.ownershipRegions : [])
|
|
90
|
+
]);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function semanticPatchHintsForImport(imported, semanticIndex) {
|
|
94
|
+
return uniqueRecordsById([
|
|
95
|
+
...(Array.isArray(imported?.patchHints) ? imported.patchHints : []),
|
|
96
|
+
...(Array.isArray(imported?.semanticPatchHints) ? imported.semanticPatchHints : []),
|
|
97
|
+
...(Array.isArray(semanticIndex?.patchHints) ? semanticIndex.patchHints : []),
|
|
98
|
+
...(Array.isArray(imported?.universalAst?.patchHints) ? imported.universalAst.patchHints : []),
|
|
99
|
+
...(Array.isArray(imported?.metadata?.patchHints) ? imported.metadata.patchHints : [])
|
|
100
|
+
]);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function isSemanticImportExpected(imported, context) {
|
|
104
|
+
return semanticExpectationRecords(imported, context).some((entry) =>
|
|
105
|
+
entry.semanticImportExpected === true
|
|
106
|
+
|| entry.expectedSemanticImport === true
|
|
107
|
+
|| entry.semanticSidecarExpected === true
|
|
108
|
+
|| entry.expected === true && looksLikeSemanticSidecarQuality(entry)
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function isSemanticImportExpectedEmpty(imported, context) {
|
|
113
|
+
return semanticExpectationRecords(imported, context).some((entry) =>
|
|
114
|
+
entry.semanticImportExpectedEmpty === true
|
|
115
|
+
|| entry.expectedSemanticImportEmpty === true
|
|
116
|
+
|| entry.semanticSidecarExpectedEmpty === true
|
|
117
|
+
|| entry.expectedEmpty === true && looksLikeSemanticSidecarQuality(entry)
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function isChangedSemanticAdmissionSource(imported, context) {
|
|
122
|
+
const sourcePath = context.sourcePath;
|
|
123
|
+
const changedSourcePaths = uniqueStrings([
|
|
124
|
+
...(context.projectResult?.changedSourcePaths ?? []),
|
|
125
|
+
...(context.projectResult?.metadata?.changedSourcePaths ?? []),
|
|
126
|
+
...(context.projectResult?.metadata?.semanticChangedSourcePaths ?? []),
|
|
127
|
+
...(context.projectResult?.metadata?.semanticImportChangedSourcePaths ?? [])
|
|
128
|
+
]);
|
|
129
|
+
return Boolean(
|
|
130
|
+
(context.candidates?.length ?? 0) > 0
|
|
131
|
+
|| (sourcePath && changedSourcePaths.includes(sourcePath))
|
|
132
|
+
|| semanticExpectationRecords(imported, context).some((entry) =>
|
|
133
|
+
entry.changedSource === true
|
|
134
|
+
|| entry.sourceChanged === true
|
|
135
|
+
|| entry.semanticSourceChanged === true
|
|
136
|
+
|| entry.semanticImportChangedSource === true
|
|
137
|
+
)
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function semanticExpectationRecords(imported, context) {
|
|
142
|
+
const nativeAst = imported?.nativeAst ?? imported?.nativeSource?.ast;
|
|
143
|
+
const semanticIndex = imported?.semanticIndex ?? imported?.universalAst?.semanticIndex;
|
|
144
|
+
return [
|
|
145
|
+
context.projectResult?.metadata,
|
|
146
|
+
context.source?.metadata,
|
|
147
|
+
imported?.metadata,
|
|
148
|
+
imported?.nativeSource?.metadata,
|
|
149
|
+
nativeAst?.metadata,
|
|
150
|
+
imported?.universalAst?.metadata,
|
|
151
|
+
imported?.patch?.metadata,
|
|
152
|
+
semanticIndex?.metadata,
|
|
153
|
+
imported?.semanticSidecarQuality,
|
|
154
|
+
imported?.sidecarQuality,
|
|
155
|
+
imported?.semanticSidecar?.quality,
|
|
156
|
+
imported?.sidecar?.quality,
|
|
157
|
+
imported?.metadata?.semanticSidecarQuality,
|
|
158
|
+
imported?.metadata?.sidecarQuality,
|
|
159
|
+
imported?.patch?.metadata?.semanticSidecarQuality
|
|
160
|
+
].filter((entry) => entry && typeof entry === 'object');
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function looksLikeSemanticSidecarQuality(value) {
|
|
164
|
+
return value && typeof value === 'object' && (
|
|
165
|
+
value.schema === 'frontier.lang.semanticSidecarQuality.v1'
|
|
166
|
+
|| value.imported !== undefined
|
|
167
|
+
|| value.expectedSatisfied !== undefined
|
|
168
|
+
|| value.warningCount !== undefined
|
|
169
|
+
|| value.proofSummary !== undefined
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function firstString(...values) {
|
|
174
|
+
for (const value of values) {
|
|
175
|
+
if (value !== undefined && value !== null && String(value)) return String(value);
|
|
176
|
+
}
|
|
177
|
+
return undefined;
|
|
178
|
+
}
|