@shapeshift-labs/frontier-lang-compiler 0.2.103 → 0.2.104
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 +13 -0
- package/dist/declarations/bidirectional-target-change-source-edit.d.ts +30 -0
- package/dist/declarations/bidirectional-target-change.d.ts +10 -0
- package/dist/declarations/js-ts-safe-member-merge.d.ts +58 -0
- package/dist/declarations/js-ts-safe-merge.d.ts +120 -0
- package/dist/declarations/js-ts-semantic-conflict-sidecars.d.ts +235 -0
- package/dist/declarations/js-ts-semantic-merge-contracts.d.ts +287 -0
- package/dist/declarations/js-ts-semantic-merge.d.ts +4 -0
- package/dist/declarations/native-import-losses.d.ts +3 -0
- package/dist/declarations/semantic-edit-replay-diagnostics.d.ts +12 -0
- package/dist/declarations/semantic-edit-script.d.ts +7 -4
- package/dist/declarations/semantic-patch-bundle-index.d.ts +45 -0
- package/dist/declarations/semantic-patch-bundle.d.ts +6 -4
- package/dist/declarations/semantic-sidecar-example.d.ts +18 -0
- package/dist/declarations/semantic-transform-identity.d.ts +3 -0
- package/dist/declarations/source-preservation.d.ts +72 -0
- package/dist/declarations/universal-capability.d.ts +4 -0
- package/dist/declarations/universal-conversion-artifacts.d.ts +61 -1
- package/dist/declarations/universal-conversion-compact-counts.d.ts +51 -0
- package/dist/declarations/universal-conversion-plan.d.ts +6 -1
- package/dist/declarations/universal-representation-coverage.d.ts +90 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +3 -0
- package/dist/internal/index-impl/bidirectionalExactSourceBackprojection.js +199 -0
- package/dist/internal/index-impl/bidirectionalSameLanguageSourceProjection.js +112 -0
- package/dist/internal/index-impl/bidirectionalSourceEditProjection.js +319 -0
- package/dist/internal/index-impl/bidirectionalSourceEditProjectionArtifacts.js +67 -0
- package/dist/internal/index-impl/bidirectionalTargetChangeRecordInternals.js +17 -5
- package/dist/internal/index-impl/bidirectionalTargetRoundtripEvidence.js +58 -20
- package/dist/internal/index-impl/createBidirectionalTargetChangeRecord.js +60 -7
- package/dist/internal/index-impl/createLightweightNativeImport.js +1 -0
- package/dist/internal/index-impl/createNativeSourcePreservation.js +28 -2
- package/dist/internal/index-impl/diffNativeSymbols.js +3 -3
- package/dist/internal/index-impl/nativeChangeProjectionSourceMapLinks.js +2 -0
- package/dist/internal/index-impl/projectSemanticEditScriptToSource.js +43 -8
- package/dist/internal/index-impl/replaySemanticEditLineEndings.js +34 -0
- package/dist/internal/index-impl/replaySemanticEditProjection.js +39 -19
- package/dist/internal/index-impl/semanticEditBundleAdmission.js +7 -3
- package/dist/internal/index-impl/semanticEditBundleIndex.js +47 -1
- package/dist/internal/index-impl/semanticEditExplicitSourceReplacement.js +40 -0
- package/dist/internal/index-impl/semanticEditOperationCoverage.js +33 -3
- package/dist/internal/index-impl/semanticEditProjectionRecord.js +29 -0
- package/dist/internal/index-impl/semanticEditReplayDiagnostics.js +39 -0
- package/dist/internal/index-impl/semanticEditReplaySourceReplacement.js +85 -0
- package/dist/internal/index-impl/semanticEditScripts.js +4 -0
- package/dist/internal/index-impl/semanticEditSourceRanges.js +27 -0
- package/dist/internal/index-impl/semanticIndexFromNativeDeclarations.js +1 -0
- package/dist/internal/index-impl/semanticPatchBundleAdmission.js +41 -7
- package/dist/internal/index-impl/semanticPatchBundleRecords.js +16 -0
- package/dist/internal/index-impl/semanticPatchBundleSourceRecords.js +2 -0
- package/dist/internal/index-impl/semanticSidecarQuality.js +111 -0
- package/dist/internal/index-impl/semanticSourceEditDedupe.js +69 -9
- package/dist/internal/index-impl/semanticTransformIdentityRecords.js +85 -9
- package/dist/js-ts-safe-member-merge-result.js +158 -0
- package/dist/js-ts-safe-member-merge.js +202 -0
- package/dist/js-ts-safe-merge-analyze.js +279 -0
- package/dist/js-ts-safe-merge-constants.js +50 -0
- package/dist/js-ts-safe-merge-context.js +118 -0
- package/dist/js-ts-safe-merge-ledger-validation.js +92 -0
- package/dist/js-ts-safe-merge-ledger.js +85 -0
- package/dist/js-ts-safe-merge-parse-declarations.js +210 -0
- package/dist/js-ts-safe-merge-parse-statements.js +155 -0
- package/dist/js-ts-safe-merge-plan.js +190 -0
- package/dist/js-ts-safe-merge.js +175 -0
- package/dist/js-ts-semantic-conflict-sidecar-constants.js +77 -0
- package/dist/js-ts-semantic-conflict-sidecar-detectors.js +195 -0
- package/dist/js-ts-semantic-conflict-sidecar-normalize.js +203 -0
- package/dist/js-ts-semantic-conflict-sidecar-utils.js +190 -0
- package/dist/js-ts-semantic-conflict-sidecars.js +81 -0
- package/dist/js-ts-semantic-merge-contract-helpers.js +128 -0
- package/dist/js-ts-semantic-merge-contracts.js +217 -0
- package/dist/js-ts-semantic-merge-member-containers.js +100 -0
- package/dist/js-ts-semantic-merge-member-keys.js +142 -0
- package/dist/js-ts-semantic-merge-member-segments.js +185 -0
- package/dist/js-ts-semantic-merge-member-source.js +64 -0
- package/dist/js-ts-semantic-merge-member-utils.js +18 -0
- package/dist/js-ts-semantic-merge-parse.js +15 -0
- package/dist/js-ts-semantic-merge.js +21 -0
- package/dist/lightweight-dependency-effects.js +51 -0
- package/dist/lightweight-dependency-language.js +12 -1
- package/dist/lightweight-dependency-relations.js +14 -27
- package/dist/native-region-scanner-core.js +33 -1
- package/dist/native-region-scanner-csharp.js +151 -0
- package/dist/native-region-scanner-dart.js +91 -0
- package/dist/native-region-scanner-dynamic.js +21 -151
- package/dist/native-region-scanner-functional.js +40 -13
- package/dist/native-region-scanner-java.js +97 -0
- package/dist/native-region-scanner-js-class.js +100 -0
- package/dist/native-region-scanner-js-helpers.js +28 -86
- package/dist/native-region-scanner-js-imports.js +121 -1
- package/dist/native-region-scanner-js-nested.js +96 -8
- package/dist/native-region-scanner-js-structure.js +27 -0
- package/dist/native-region-scanner-js-types.js +99 -0
- package/dist/native-region-scanner-js.js +70 -118
- package/dist/native-region-scanner-kotlin.js +94 -0
- package/dist/native-region-scanner-main.js +15 -181
- package/dist/native-region-scanner-php.js +80 -0
- package/dist/native-region-scanner-python.js +62 -0
- package/dist/native-region-scanner-ruby.js +72 -0
- package/dist/native-region-scanner-scala.js +91 -0
- package/dist/native-region-scanner-spans.js +74 -0
- package/dist/native-region-scanner-swift.js +155 -0
- package/dist/native-region-scanner.js +14 -10
- package/dist/native-source-ledger-helpers.js +195 -0
- package/dist/native-source-ledger.js +306 -0
- package/dist/native-source-preservation-scanner.js +4 -0
- package/dist/semantic-import-callsite-regions.js +136 -0
- package/dist/semantic-import-effect-regions.js +283 -0
- package/dist/semantic-import-regions.js +11 -2
- package/dist/semantic-import-sidecar-entry.js +16 -2
- package/dist/semantic-import-sidecar-types.d.ts +2 -0
- package/dist/semantic-sidecar-example.js +68 -0
- package/dist/universal-capability-matrix.js +23 -0
- package/dist/universal-conversion-artifact-query.js +79 -2
- package/dist/universal-conversion-artifact-semantic-edit.js +103 -0
- package/dist/universal-conversion-artifact-summary.js +33 -1
- package/dist/universal-conversion-artifacts.js +13 -48
- package/dist/universal-conversion-plan-scoring.js +21 -1
- package/dist/universal-conversion-plan-summary.js +30 -0
- package/dist/universal-conversion-plan.js +25 -9
- package/dist/universal-conversion-route-metadata.js +96 -0
- package/dist/universal-conversion-route-operations.js +7 -0
- package/dist/universal-representation-coverage.js +193 -0
- package/package.json +1 -1
|
@@ -102,6 +102,8 @@ export function normalizeSourceMapLinks(links) {
|
|
|
102
102
|
precision: link.precision,
|
|
103
103
|
sourceSpan: link.sourceSpan,
|
|
104
104
|
generatedSpan: link.generatedSpan,
|
|
105
|
+
sourceReplacementText: link.sourceReplacementText,
|
|
106
|
+
sourceReplacementTextHash: link.sourceReplacementTextHash,
|
|
105
107
|
regionKey: link.ownershipRegionKey,
|
|
106
108
|
regionKind: link.ownershipRegionKind
|
|
107
109
|
}));
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { uniqueStrings } from '../../native-import-utils.js';
|
|
2
|
+
|
|
3
|
+
function summarizeSemanticSidecarQuality(sources) {
|
|
4
|
+
const records = uniqueSemanticSidecarQualityRecords(array(sources).flatMap(semanticSidecarQualityRecords));
|
|
5
|
+
const warningCodes = uniqueStrings(records.flatMap(sidecarQualityWarningCodes));
|
|
6
|
+
const zeroRecordWarningCodes = uniqueStrings(records.flatMap(sidecarQualityZeroRecordWarningCodes));
|
|
7
|
+
return {
|
|
8
|
+
records: records.length,
|
|
9
|
+
symbols: records.reduce((sum, record) => sum + sidecarQualityCount(record, 'symbolCount', 'symbols'), 0),
|
|
10
|
+
ownershipRegions: records.reduce((sum, record) => sum + sidecarQualityCount(record, 'ownershipRegionCount', 'ownershipRegions'), 0),
|
|
11
|
+
patchHints: records.reduce((sum, record) => sum + sidecarQualityCount(record, 'patchHintCount', 'patchHints'), 0),
|
|
12
|
+
warnings: records.reduce((sum, record) => sum + sidecarQualityWarningCount(record), 0),
|
|
13
|
+
zeroRecordWarnings: zeroRecordWarningCodes.length,
|
|
14
|
+
warningCodes,
|
|
15
|
+
zeroRecordWarningCodes
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function semanticSidecarQualityRecords(source) {
|
|
20
|
+
if (!source || typeof source !== 'object') return [];
|
|
21
|
+
return [
|
|
22
|
+
source.semanticSidecarQuality,
|
|
23
|
+
source.sidecarQuality,
|
|
24
|
+
source.semanticSidecar?.quality,
|
|
25
|
+
source.sidecar?.quality,
|
|
26
|
+
source.semanticSidecarAdmission,
|
|
27
|
+
source.sidecarAdmission,
|
|
28
|
+
source.semanticSidecar?.admission,
|
|
29
|
+
source.sidecar?.admission,
|
|
30
|
+
source.metadata?.semanticSidecarQuality,
|
|
31
|
+
source.metadata?.sidecarQuality,
|
|
32
|
+
source.metadata?.semanticSidecarAdmission,
|
|
33
|
+
source.metadata?.sidecarAdmission
|
|
34
|
+
].filter(looksLikeSemanticSidecarQuality);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function looksLikeSemanticSidecarQuality(value) {
|
|
38
|
+
return value && typeof value === 'object' && (
|
|
39
|
+
value.schema === 'frontier.lang.semanticSidecarQuality.v1' ||
|
|
40
|
+
value.schema === 'frontier.lang.semanticSidecarAdmission.v1' ||
|
|
41
|
+
value.imported !== undefined ||
|
|
42
|
+
value.eligible !== undefined ||
|
|
43
|
+
value.expectedSatisfied !== undefined ||
|
|
44
|
+
value.warningCount !== undefined ||
|
|
45
|
+
value.emptyEvidenceWarnings !== undefined ||
|
|
46
|
+
value.proofSummary !== undefined ||
|
|
47
|
+
value.counts !== undefined
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function uniqueSemanticSidecarQualityRecords(records) {
|
|
52
|
+
const seen = new Set();
|
|
53
|
+
const result = [];
|
|
54
|
+
for (const record of records) {
|
|
55
|
+
const key = record.id ?? JSON.stringify({
|
|
56
|
+
schema: record.schema,
|
|
57
|
+
symbols: sidecarQualityCount(record, 'symbolCount', 'symbols'),
|
|
58
|
+
ownershipRegions: sidecarQualityCount(record, 'ownershipRegionCount', 'ownershipRegions'),
|
|
59
|
+
patchHints: sidecarQualityCount(record, 'patchHintCount', 'patchHints'),
|
|
60
|
+
warningCodes: sidecarQualityWarningCodes(record)
|
|
61
|
+
});
|
|
62
|
+
if (seen.has(key)) continue;
|
|
63
|
+
seen.add(key);
|
|
64
|
+
result.push(record);
|
|
65
|
+
}
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function sidecarQualityCount(record, field, countsField) {
|
|
70
|
+
for (const value of [record?.[field], record?.counts?.[countsField]]) {
|
|
71
|
+
const count = Number(value ?? 0);
|
|
72
|
+
if (Number.isFinite(count) && count > 0) return count;
|
|
73
|
+
}
|
|
74
|
+
return 0;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function sidecarQualityWarningCount(record) {
|
|
78
|
+
const count = Number(record?.warningCount ?? 0);
|
|
79
|
+
if (Number.isFinite(count) && count > 0) return count;
|
|
80
|
+
return sidecarQualityWarningCodes(record).length;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function sidecarQualityWarningCodes(record) {
|
|
84
|
+
return uniqueStrings([
|
|
85
|
+
...array(record?.warnings).map((warning) => warning?.code ?? warning?.reasonCode),
|
|
86
|
+
...array(record?.emptyEvidenceWarnings).map((warning) => warning?.code ?? warning?.reasonCode),
|
|
87
|
+
...strings(record?.expectedMissingReasonCodes),
|
|
88
|
+
...strings(record?.reasonCodes)
|
|
89
|
+
].filter(Boolean));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function sidecarQualityZeroRecordWarningCodes(record) {
|
|
93
|
+
return sidecarQualityWarningCodes(record).filter(isZeroRecordWarningCode);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function isZeroRecordWarningCode(code) {
|
|
97
|
+
return [
|
|
98
|
+
'empty-evidence',
|
|
99
|
+
'empty-semantic-index',
|
|
100
|
+
'expected-semantic-import-empty',
|
|
101
|
+
'expected-semantic-import-missing',
|
|
102
|
+
'missing-imports',
|
|
103
|
+
'missing-ownership-regions',
|
|
104
|
+
'missing-patch-hints'
|
|
105
|
+
].includes(code);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function array(value) { if (value === undefined || value === null) return []; return Array.isArray(value) ? value : [value]; }
|
|
109
|
+
function strings(value) { return array(value).map((entry) => String(entry ?? '')).filter(Boolean); }
|
|
110
|
+
|
|
111
|
+
export { summarizeSemanticSidecarQuality };
|
|
@@ -8,11 +8,18 @@ export function applySourceEdits(sourceText, edits) {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
export function dedupeSourceEdits(edits) {
|
|
11
|
-
const exact =
|
|
12
|
-
const
|
|
11
|
+
const exact = dedupeExactEdits(edits);
|
|
12
|
+
const noops = removeNoopReplacements(exact.edits);
|
|
13
|
+
const coveredDeletes = removeContainedDeletionEdits(noops.edits);
|
|
14
|
+
const covered = removeCoveredContainerReplacements(coveredDeletes.edits);
|
|
13
15
|
return {
|
|
14
16
|
edits: covered.edits,
|
|
15
|
-
skippedOperationIds: [
|
|
17
|
+
skippedOperationIds: [
|
|
18
|
+
...exact.skippedOperationIds,
|
|
19
|
+
...noops.skippedOperationIds,
|
|
20
|
+
...coveredDeletes.skippedOperationIds,
|
|
21
|
+
...covered.skippedOperationIds
|
|
22
|
+
]
|
|
16
23
|
};
|
|
17
24
|
}
|
|
18
25
|
|
|
@@ -27,7 +34,7 @@ export function validateSourceEdits(edits) {
|
|
|
27
34
|
return uniqueStrings(reasons);
|
|
28
35
|
}
|
|
29
36
|
|
|
30
|
-
function
|
|
37
|
+
function dedupeExactEdits(edits) {
|
|
31
38
|
const seen = new Map();
|
|
32
39
|
const result = [];
|
|
33
40
|
const skippedOperationIds = [];
|
|
@@ -43,6 +50,19 @@ function dedupeExactInsertions(edits) {
|
|
|
43
50
|
return { edits: result, skippedOperationIds };
|
|
44
51
|
}
|
|
45
52
|
|
|
53
|
+
function removeNoopReplacements(edits) {
|
|
54
|
+
const skippedOperationIds = [];
|
|
55
|
+
const result = [];
|
|
56
|
+
for (const edit of edits) {
|
|
57
|
+
if (edit.editKind === 'replace' && !edit.alreadyApplied && edit.current === edit.replacement) {
|
|
58
|
+
skippedOperationIds.push(edit.operationId);
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
result.push(edit);
|
|
62
|
+
}
|
|
63
|
+
return { edits: result, skippedOperationIds };
|
|
64
|
+
}
|
|
65
|
+
|
|
46
66
|
function removeCoveredContainerReplacements(edits) {
|
|
47
67
|
const skippedOperationIds = [];
|
|
48
68
|
const result = [];
|
|
@@ -56,6 +76,31 @@ function removeCoveredContainerReplacements(edits) {
|
|
|
56
76
|
return { edits: result, skippedOperationIds };
|
|
57
77
|
}
|
|
58
78
|
|
|
79
|
+
function removeContainedDeletionEdits(edits) {
|
|
80
|
+
const skippedOperationIds = [];
|
|
81
|
+
const result = [];
|
|
82
|
+
for (const edit of edits) {
|
|
83
|
+
if (deleteCoveredByLargerDelete(edit, edits)) {
|
|
84
|
+
skippedOperationIds.push(edit.operationId);
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
result.push(edit);
|
|
88
|
+
}
|
|
89
|
+
return { edits: result, skippedOperationIds };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function deleteCoveredByLargerDelete(edit, edits) {
|
|
93
|
+
return edit.editKind === 'delete' && !edit.alreadyApplied && edits.some((candidate) => (
|
|
94
|
+
candidate !== edit &&
|
|
95
|
+
candidate.editKind === 'delete' &&
|
|
96
|
+
!candidate.alreadyApplied &&
|
|
97
|
+
sameSourcePath(candidate, edit) &&
|
|
98
|
+
candidate.start <= edit.start &&
|
|
99
|
+
edit.end <= candidate.end &&
|
|
100
|
+
(candidate.start !== edit.start || candidate.end !== edit.end)
|
|
101
|
+
));
|
|
102
|
+
}
|
|
103
|
+
|
|
59
104
|
function containerReplacementCoveredByInsertions(edit, edits) {
|
|
60
105
|
if (edit.editKind !== 'replace' || edit.alreadyApplied) return false;
|
|
61
106
|
const insertions = containedInsertions(edit, edits);
|
|
@@ -76,15 +121,30 @@ function containedInsertions(container, edits) {
|
|
|
76
121
|
.sort((left, right) => left.start - right.start || (left.order ?? 0) - (right.order ?? 0));
|
|
77
122
|
}
|
|
78
123
|
|
|
124
|
+
function sameSourcePath(left, right) {
|
|
125
|
+
const leftPath = left.targetSourcePath ?? left.sourcePath;
|
|
126
|
+
const rightPath = right.targetSourcePath ?? right.sourcePath;
|
|
127
|
+
return !leftPath || !rightPath || leftPath === rightPath;
|
|
128
|
+
}
|
|
129
|
+
|
|
79
130
|
function duplicateEditKey(edit) {
|
|
80
|
-
if (edit.
|
|
131
|
+
if (edit.alreadyApplied) return undefined;
|
|
132
|
+
if (edit.editKind === 'insert') {
|
|
133
|
+
return [
|
|
134
|
+
'insert',
|
|
135
|
+
edit.start,
|
|
136
|
+
edit.end,
|
|
137
|
+
edit.insertion?.mode,
|
|
138
|
+
edit.insertion?.anchorKey,
|
|
139
|
+
hashSemanticValue(edit.replacementSpanText ?? edit.replacement)
|
|
140
|
+
].join(':');
|
|
141
|
+
}
|
|
81
142
|
return [
|
|
82
|
-
|
|
143
|
+
edit.editKind,
|
|
83
144
|
edit.start,
|
|
84
145
|
edit.end,
|
|
85
|
-
edit.
|
|
86
|
-
edit.
|
|
87
|
-
hashSemanticValue(edit.replacementSpanText ?? edit.replacement)
|
|
146
|
+
hashSemanticValue(edit.current),
|
|
147
|
+
hashSemanticValue(edit.replacement)
|
|
88
148
|
].join(':');
|
|
89
149
|
}
|
|
90
150
|
|
|
@@ -4,7 +4,7 @@ import { semanticEditIdentityFields } from './semanticEditIdentityRecords.js';
|
|
|
4
4
|
|
|
5
5
|
export function createSemanticTransformIdentityRecord(input = {}, options = {}) {
|
|
6
6
|
const source = input?.transform ?? input;
|
|
7
|
-
const merged = { ...source, ...options };
|
|
7
|
+
const merged = { ...source, ...definedEntries(options) };
|
|
8
8
|
const editIdentity = semanticEditIdentityFields(merged);
|
|
9
9
|
const semanticKey = firstString(merged.semanticKey, editIdentity.semanticKey);
|
|
10
10
|
const transformKey = firstString(merged.transformKey, semanticTransformKey({ ...merged, semanticKey }));
|
|
@@ -32,6 +32,9 @@ export function createSemanticTransformIdentityRecord(input = {}, options = {})
|
|
|
32
32
|
merged.transformContentHash,
|
|
33
33
|
operationContentHash || editContentHash ? hashSemanticValue(compactRecord({ transformIdentityHash, operationContentHash, editContentHash })) : undefined
|
|
34
34
|
);
|
|
35
|
+
const sourceMapIds = uniqueStrings([...strings(merged.sourceMapIds), ...strings(merged.sourceMapId), ...strings(merged.metadata?.sourceMapIds), ...strings(merged.metadata?.sourceMapId)]);
|
|
36
|
+
const sourceMapLinkIds = uniqueStrings([...strings(merged.sourceMapLinkIds), ...strings(merged.sourceMapLinkId), ...strings(merged.metadata?.sourceMapLinkIds), ...strings(merged.metadata?.sourceMapLinkId)]);
|
|
37
|
+
const sourceMapMappingIds = uniqueStrings([...strings(merged.sourceMapMappingIds), ...strings(merged.sourceMapMappingId), ...strings(merged.metadata?.sourceMapMappingIds), ...strings(merged.metadata?.sourceMapMappingId)]);
|
|
35
38
|
const id = merged.id && source.kind === 'frontier.lang.semanticTransformIdentityRecord'
|
|
36
39
|
? merged.id
|
|
37
40
|
: firstString(merged.id, `semantic_transform_${idFragment(firstString(transformKey, semanticKey, sourcePath, targetPath, 'record'))}`);
|
|
@@ -55,6 +58,9 @@ export function createSemanticTransformIdentityRecord(input = {}, options = {})
|
|
|
55
58
|
transformIdentityHash,
|
|
56
59
|
projectionIdentityHash,
|
|
57
60
|
transformContentHash,
|
|
61
|
+
sourceMapIds,
|
|
62
|
+
sourceMapLinkIds,
|
|
63
|
+
sourceMapMappingIds,
|
|
58
64
|
readiness: firstString(merged.readiness),
|
|
59
65
|
confidence: typeof merged.confidence === 'number' ? merged.confidence : undefined,
|
|
60
66
|
evidenceIds: uniqueStrings(merged.evidenceIds),
|
|
@@ -80,20 +86,29 @@ export function semanticTransformInputs(source = {}, options = {}) {
|
|
|
80
86
|
...array(options.semanticEditProjections ?? options.semanticEditProjection),
|
|
81
87
|
...array(source.semanticEditProjections ?? source.semanticEditProjection)
|
|
82
88
|
];
|
|
89
|
+
const scripts = [
|
|
90
|
+
...array(options.semanticEditScripts ?? options.semanticEditScript),
|
|
91
|
+
...array(source.semanticEditScripts ?? source.semanticEditScript)
|
|
92
|
+
];
|
|
83
93
|
return [
|
|
84
94
|
...array(options.semanticTransformIdentities ?? options.semanticTransformIdentity),
|
|
85
95
|
...array(source.semanticTransformIdentities ?? source.semanticTransformIdentity ?? source.semanticTransforms),
|
|
86
96
|
...array(source.index?.semanticTransformIdentities),
|
|
87
|
-
...deriveSemanticTransformIdentityRecords({ semanticEditProjections: projections }, { ...source, ...options })
|
|
97
|
+
...deriveSemanticTransformIdentityRecords({ semanticEditProjections: projections, semanticEditScripts: scripts }, { ...source, ...options })
|
|
88
98
|
];
|
|
89
99
|
}
|
|
90
100
|
|
|
91
101
|
export function deriveSemanticTransformIdentityRecords(input = {}, options = {}) {
|
|
92
102
|
const projections = semanticEditProjectionInputs(input);
|
|
93
|
-
|
|
103
|
+
const projectionRecords = projections.flatMap((projection, projectionIndex) => {
|
|
94
104
|
const edits = array(projection.edits).filter((edit) => edit && typeof edit === 'object');
|
|
95
105
|
return edits.map((edit, editIndex) => transformRecordForProjectionEdit(edit, projection, input, options, projectionIndex, editIndex));
|
|
96
|
-
})
|
|
106
|
+
});
|
|
107
|
+
const scriptRecords = projections.length ? [] : semanticEditScriptInputs(input).flatMap((script, scriptIndex) => {
|
|
108
|
+
const operations = array(script.operations).filter((operation) => operation && typeof operation === 'object');
|
|
109
|
+
return operations.map((operation, operationIndex) => transformRecordForScriptOperation(operation, script, input, options, scriptIndex, operationIndex));
|
|
110
|
+
});
|
|
111
|
+
return uniqueRecords([...projectionRecords, ...scriptRecords]);
|
|
97
112
|
}
|
|
98
113
|
|
|
99
114
|
export function semanticTransformRecordIndex(records, source = {}) {
|
|
@@ -104,12 +119,18 @@ export function semanticTransformRecordIndex(records, source = {}) {
|
|
|
104
119
|
semanticTransformIdentityHashes: uniqueStrings([...strings(source.semanticTransformIdentityHashes), ...strings(index.semanticTransformIdentityHashes), ...records.map((record) => record.transformIdentityHash)]),
|
|
105
120
|
semanticTransformContentHashes: uniqueStrings([...strings(source.semanticTransformContentHashes), ...strings(index.semanticTransformContentHashes), ...records.map((record) => record.transformContentHash)]),
|
|
106
121
|
projectionIdentityHashes: uniqueStrings([...strings(source.projectionIdentityHashes), ...strings(index.projectionIdentityHashes), ...records.map((record) => record.projectionIdentityHash)]),
|
|
122
|
+
transformBaseHashes: uniqueStrings([...strings(source.transformBaseHashes), ...strings(index.transformBaseHashes), ...records.map((record) => record.baseHash)]),
|
|
123
|
+
transformTargetHashes: uniqueStrings([...strings(source.transformTargetHashes), ...strings(index.transformTargetHashes), ...records.map((record) => record.targetHash)]),
|
|
107
124
|
semanticTransformReadinesses: uniqueStrings([...strings(source.semanticTransformReadinesses), ...strings(index.semanticTransformReadinesses), ...records.map((record) => record.readiness)]),
|
|
108
125
|
semanticTransformEvidenceIds: uniqueStrings([...strings(source.semanticTransformEvidenceIds), ...strings(index.semanticTransformEvidenceIds), ...records.flatMap((record) => record.evidenceIds)]),
|
|
109
126
|
transformSourceLanguages: uniqueStrings([...strings(source.transformSourceLanguages), ...strings(index.transformSourceLanguages), ...records.map((record) => record.sourceLanguage)]),
|
|
110
127
|
transformTargetLanguages: uniqueStrings([...strings(source.transformTargetLanguages), ...strings(index.transformTargetLanguages), ...records.map((record) => record.targetLanguage)]),
|
|
111
128
|
transformSourcePaths: uniqueStrings([...strings(source.transformSourcePaths), ...strings(index.transformSourcePaths), ...records.map((record) => record.sourcePath)]),
|
|
112
|
-
transformTargetPaths: uniqueStrings([...strings(source.transformTargetPaths), ...strings(index.transformTargetPaths), ...records.map((record) => record.targetPath)])
|
|
129
|
+
transformTargetPaths: uniqueStrings([...strings(source.transformTargetPaths), ...strings(index.transformTargetPaths), ...records.map((record) => record.targetPath)]),
|
|
130
|
+
transformCrossLanguages: uniqueStrings([...strings(source.transformCrossLanguages), ...strings(index.transformCrossLanguages), ...records.map(transformCrossLanguageFlag)]),
|
|
131
|
+
transformSourceMapIds: uniqueStrings([...strings(source.transformSourceMapIds), ...strings(index.transformSourceMapIds), ...records.flatMap((record) => record.sourceMapIds)]),
|
|
132
|
+
transformSourceMapLinkIds: uniqueStrings([...strings(source.transformSourceMapLinkIds), ...strings(index.transformSourceMapLinkIds), ...records.flatMap((record) => record.sourceMapLinkIds)]),
|
|
133
|
+
transformSourceMapMappingIds: uniqueStrings([...strings(source.transformSourceMapMappingIds), ...strings(index.transformSourceMapMappingIds), ...records.flatMap((record) => record.sourceMapMappingIds)])
|
|
113
134
|
};
|
|
114
135
|
}
|
|
115
136
|
|
|
@@ -121,14 +142,24 @@ export function semanticTransformSummary(index) {
|
|
|
121
142
|
identityHashes: index.semanticTransformIdentityHashes,
|
|
122
143
|
contentHashes: index.semanticTransformContentHashes,
|
|
123
144
|
projectionIdentityHashes: index.projectionIdentityHashes,
|
|
145
|
+
baseHashes: index.transformBaseHashes,
|
|
146
|
+
targetHashes: index.transformTargetHashes,
|
|
124
147
|
readinesses: index.semanticTransformReadinesses,
|
|
125
148
|
evidenceIds: index.semanticTransformEvidenceIds,
|
|
126
149
|
sourceLanguages: index.transformSourceLanguages,
|
|
127
150
|
targetLanguages: index.transformTargetLanguages,
|
|
128
|
-
targetPaths: index.transformTargetPaths
|
|
151
|
+
targetPaths: index.transformTargetPaths,
|
|
152
|
+
crossLanguages: index.transformCrossLanguages,
|
|
153
|
+
sourceMapIds: index.transformSourceMapIds,
|
|
154
|
+
sourceMapLinkIds: index.transformSourceMapLinkIds,
|
|
155
|
+
sourceMapMappingIds: index.transformSourceMapMappingIds
|
|
129
156
|
});
|
|
130
157
|
}
|
|
131
158
|
|
|
159
|
+
function transformCrossLanguageFlag(record) {
|
|
160
|
+
return record.sourceLanguage && record.targetLanguage && record.sourceLanguage !== record.targetLanguage ? 'true' : 'false';
|
|
161
|
+
}
|
|
162
|
+
|
|
132
163
|
function semanticTransformKey(record) {
|
|
133
164
|
const scope = record.semanticKey ?? (record.symbolName
|
|
134
165
|
? `${record.symbolKind ?? 'symbol'}:${record.symbolName}`
|
|
@@ -145,11 +176,19 @@ function semanticEditProjectionInputs(input) {
|
|
|
145
176
|
].filter((entry) => entry && typeof entry === 'object');
|
|
146
177
|
}
|
|
147
178
|
|
|
179
|
+
function semanticEditScriptInputs(input) {
|
|
180
|
+
if (input.kind === 'frontier.lang.semanticEditScript') return [input];
|
|
181
|
+
return [
|
|
182
|
+
...array(input.semanticEditScripts ?? input.semanticEditScript),
|
|
183
|
+
...array(input.scripts ?? input.script)
|
|
184
|
+
].filter((entry) => entry && typeof entry === 'object');
|
|
185
|
+
}
|
|
186
|
+
|
|
148
187
|
function transformRecordForProjectionEdit(edit, projection, input, options, projectionIndex, editIndex) {
|
|
149
188
|
const sourceLanguage = firstString(edit.sourceLanguage, edit.language, input.sourceLanguage, options.sourceLanguage, projection.sourceLanguage, projection.language);
|
|
150
|
-
const targetLanguage = firstString(edit.targetLanguage, edit.projectedLanguage, input.targetLanguage, options.targetLanguage, projection.targetLanguage, projection.projectedLanguage, projection.language);
|
|
189
|
+
const targetLanguage = firstString(edit.targetLanguage, edit.projectedLanguage, input.targetLanguage, options.targetLanguage, projection.metadata?.targetLanguage, projection.targetLanguage, projection.projectedLanguage, projection.language);
|
|
151
190
|
const sourcePath = firstString(edit.originalSourcePath, edit.sourcePath, input.sourcePath, options.sourcePath, projection.sourcePath);
|
|
152
|
-
const targetPath = firstString(edit.targetPath, edit.targetSourcePath, input.targetPath, options.targetPath, projection.targetPath, projection.projectedSourcePath, projection.sourcePath);
|
|
191
|
+
const targetPath = firstString(edit.targetPath, edit.targetSourcePath, input.targetPath, options.targetPath, projection.metadata?.targetPath, projection.targetPath, projection.projectedSourcePath, projection.sourcePath);
|
|
153
192
|
const transformId = [projection.id, edit.operationId, projectionIndex, editIndex].filter((entry) => entry !== undefined && entry !== null).join(':');
|
|
154
193
|
return createSemanticTransformIdentityRecord(edit, {
|
|
155
194
|
id: `semantic_transform_${idFragment(transformId)}`,
|
|
@@ -158,7 +197,10 @@ function transformRecordForProjectionEdit(edit, projection, input, options, proj
|
|
|
158
197
|
sourcePath,
|
|
159
198
|
targetPath,
|
|
160
199
|
baseHash: firstString(edit.baseHash, projection.baseHash, input.baseHash, options.baseHash),
|
|
161
|
-
targetHash: firstString(edit.targetHash, projection.projectedHash, projection.targetHash, input.targetHash, options.targetHash),
|
|
200
|
+
targetHash: firstString(edit.targetHash, projection.metadata?.targetHash, projection.projectedHash, projection.targetHash, input.targetHash, options.targetHash),
|
|
201
|
+
sourceMapIds: projection.metadata?.sourceMapIds,
|
|
202
|
+
sourceMapLinkIds: projection.metadata?.sourceMapLinkIds,
|
|
203
|
+
sourceMapMappingIds: projection.metadata?.sourceMapMappingIds,
|
|
162
204
|
readiness: firstString(edit.readiness, projection.admission?.status, projection.status),
|
|
163
205
|
evidenceIds: uniqueStrings([...strings(input.evidenceIds), ...strings(options.evidenceIds), ...strings(projection.evidenceIds), ...strings(edit.evidenceIds)]),
|
|
164
206
|
metadata: compactRecord({
|
|
@@ -168,6 +210,39 @@ function transformRecordForProjectionEdit(edit, projection, input, options, proj
|
|
|
168
210
|
});
|
|
169
211
|
}
|
|
170
212
|
|
|
213
|
+
function transformRecordForScriptOperation(operation, script, input, options, scriptIndex, operationIndex) {
|
|
214
|
+
const targetRegion = operation.metadata?.targetRegion ?? {};
|
|
215
|
+
const transformId = [script.id, operation.id, scriptIndex, operationIndex].filter((entry) => entry !== undefined && entry !== null).join(':');
|
|
216
|
+
return createSemanticTransformIdentityRecord(operation, {
|
|
217
|
+
id: `semantic_transform_${idFragment(transformId)}`,
|
|
218
|
+
sourceLanguage: firstString(operation.anchor?.language, script.language, input.sourceLanguage, options.sourceLanguage),
|
|
219
|
+
targetLanguage: firstString(targetRegion.language, script.metadata?.targetLanguage, input.targetLanguage, options.targetLanguage),
|
|
220
|
+
sourcePath: firstString(operation.anchor?.sourcePath, script.sourcePath, input.sourcePath, options.sourcePath),
|
|
221
|
+
targetPath: firstString(targetRegion.sourcePath, script.metadata?.targetPath, input.targetPath, options.targetPath),
|
|
222
|
+
baseHash: firstString(operation.hashes?.baseSourceHash, script.baseHash, input.baseHash, options.baseHash),
|
|
223
|
+
targetHash: firstString(targetRegion.sourceHash, operation.hashes?.workerSourceHash, input.targetHash, options.targetHash),
|
|
224
|
+
sourceMapIds: script.metadata?.sourceProjectionHint?.sourceMapIds,
|
|
225
|
+
sourceMapLinkIds: operation.metadata?.sourceMapLinkIds,
|
|
226
|
+
sourceMapMappingIds: operation.metadata?.sourceMapMappingIds,
|
|
227
|
+
readiness: firstString(script.admission?.status, script.metadata?.sourceProjectionHint?.status),
|
|
228
|
+
evidenceIds: uniqueStrings([
|
|
229
|
+
...strings(input.evidenceIds),
|
|
230
|
+
...strings(options.evidenceIds),
|
|
231
|
+
...array(script.evidence).map((record) => record?.id),
|
|
232
|
+
...strings(operation.evidenceIds)
|
|
233
|
+
]),
|
|
234
|
+
metadata: compactRecord({
|
|
235
|
+
sourceEditScriptId: script.id,
|
|
236
|
+
sourceEditOperationId: operation.id,
|
|
237
|
+
sourceProjectionHintId: script.metadata?.sourceProjectionHint?.id,
|
|
238
|
+
sourceMapIds: script.metadata?.sourceProjectionHint?.sourceMapIds,
|
|
239
|
+
sourceMapLinkIds: operation.metadata?.sourceMapLinkIds,
|
|
240
|
+
sourceMapMappingIds: operation.metadata?.sourceMapMappingIds,
|
|
241
|
+
reviewOnly: script.admission?.reviewRequired === true
|
|
242
|
+
})
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
|
|
171
246
|
function uniqueRecords(records) {
|
|
172
247
|
const seen = new Set();
|
|
173
248
|
const result = [];
|
|
@@ -184,4 +259,5 @@ function array(value) { if (value === undefined || value === null) return []; re
|
|
|
184
259
|
function strings(value) { return array(value).map((entry) => String(entry ?? '')).filter(Boolean); }
|
|
185
260
|
function firstString(...values) { return values.map((value) => value === undefined || value === null ? '' : String(value)).find(Boolean); }
|
|
186
261
|
function uniqueStrings(values) { return uniqueRawStrings((values ?? []).filter((entry) => entry !== undefined && entry !== null && String(entry) !== '')); }
|
|
262
|
+
function definedEntries(value) { return Object.fromEntries(Object.entries(value ?? {}).filter(([, entry]) => entry !== undefined)); }
|
|
187
263
|
function compactRecord(value) { return Object.fromEntries(Object.entries(value ?? {}).filter(([, entry]) => entry !== undefined && (!Array.isArray(entry) || entry.length > 0))); }
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import {
|
|
2
|
+
JsTsSafeMergeConflictCodes,
|
|
3
|
+
JsTsSafeMergeGateIds,
|
|
4
|
+
jsTsSafeMergeGateOrder
|
|
5
|
+
} from './js-ts-safe-merge-constants.js';
|
|
6
|
+
import { uniqueStrings } from './js-ts-semantic-merge-parse.js';
|
|
7
|
+
|
|
8
|
+
function mergeResult(status, sourceText, reasonCodes, regions, input, explicitPolicy) {
|
|
9
|
+
const conflicts = status === 'merged'
|
|
10
|
+
? []
|
|
11
|
+
: reasonCodes.map((reason, index) => memberConflictForReason(reason, input, index));
|
|
12
|
+
const mergedRegions = regions.map((region) => ({
|
|
13
|
+
kind: region.kind,
|
|
14
|
+
name: region.name,
|
|
15
|
+
regionKind: region.policy.regionKind,
|
|
16
|
+
workerAddedKeys: region.workerAddedKeys,
|
|
17
|
+
headAddedKeys: region.headAddedKeys
|
|
18
|
+
}));
|
|
19
|
+
return {
|
|
20
|
+
kind: 'frontier.lang.jsTsSafeMemberMerge',
|
|
21
|
+
version: 1,
|
|
22
|
+
status,
|
|
23
|
+
sourceText,
|
|
24
|
+
reasonCodes,
|
|
25
|
+
conflicts,
|
|
26
|
+
gates: memberGates(conflicts),
|
|
27
|
+
admission: memberAdmission(status, conflicts),
|
|
28
|
+
mergedRegions,
|
|
29
|
+
summary: {
|
|
30
|
+
regions: mergedRegions.length,
|
|
31
|
+
workerAdditions: mergedRegions.reduce((total, region) => total + region.workerAddedKeys.length, 0),
|
|
32
|
+
headAdditions: mergedRegions.reduce((total, region) => total + region.headAddedKeys.length, 0),
|
|
33
|
+
appliedAdditions: status === 'merged' ? mergedRegions.reduce((total, region) => total + region.workerAddedKeys.length, 0) : 0,
|
|
34
|
+
conflicts: conflicts.length
|
|
35
|
+
},
|
|
36
|
+
metadata: { explicitPolicy }
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function memberAdmission(status, conflicts) {
|
|
41
|
+
const reasonCodes = uniqueStrings(conflicts.map((conflict) => conflict.details.reasonCode ?? conflict.code));
|
|
42
|
+
if (status === 'merged') {
|
|
43
|
+
return {
|
|
44
|
+
status: 'auto-merge-candidate',
|
|
45
|
+
action: 'apply',
|
|
46
|
+
reviewRequired: false,
|
|
47
|
+
autoApplyCandidate: true,
|
|
48
|
+
reasonCodes: []
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
status: 'blocked',
|
|
53
|
+
action: 'human-review',
|
|
54
|
+
reviewRequired: true,
|
|
55
|
+
autoApplyCandidate: false,
|
|
56
|
+
reasonCodes
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function memberGates(conflicts) {
|
|
61
|
+
const blockedGateIds = new Set(conflicts.map((conflict) => conflict.gateId));
|
|
62
|
+
const reasonCodesByGate = new Map();
|
|
63
|
+
for (const conflict of conflicts) {
|
|
64
|
+
const gateReasonCodes = reasonCodesByGate.get(conflict.gateId) ?? [];
|
|
65
|
+
gateReasonCodes.push(conflict.details.reasonCode ?? conflict.code);
|
|
66
|
+
reasonCodesByGate.set(conflict.gateId, uniqueStrings(gateReasonCodes));
|
|
67
|
+
}
|
|
68
|
+
let blockedSeen = false;
|
|
69
|
+
return jsTsSafeMergeGateOrder.map((id) => {
|
|
70
|
+
const blocked = blockedGateIds.has(id);
|
|
71
|
+
const status = blocked ? 'blocked' : blockedSeen ? 'skipped' : 'passed';
|
|
72
|
+
if (blocked) blockedSeen = true;
|
|
73
|
+
return { id, status, reasonCodes: reasonCodesByGate.get(id) ?? [] };
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function memberConflictForReason(reason, input, index) {
|
|
78
|
+
const reasonCode = blockedReasonCode(reason);
|
|
79
|
+
const code = conflictCodeForReason(reasonCode);
|
|
80
|
+
const gateId = gateIdForReason(reasonCode);
|
|
81
|
+
const details = reasonDetails(reason, reasonCode);
|
|
82
|
+
return {
|
|
83
|
+
code,
|
|
84
|
+
gateId,
|
|
85
|
+
message: memberConflictMessage(reasonCode, details),
|
|
86
|
+
side: details.side,
|
|
87
|
+
sourcePath: input.sourcePath,
|
|
88
|
+
details: { ...details, index }
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function blockedReasonCode(reason) {
|
|
93
|
+
if (reason.includes('computed-key')) return 'computed-key';
|
|
94
|
+
if (reason.includes('spread-like-member') || reason.includes('spread-member')) return 'spread-like-member';
|
|
95
|
+
if (reason.includes('overload-collision')) return 'overload-collision';
|
|
96
|
+
if (reason.includes('type-alias-conflict')) return 'type-alias-conflict';
|
|
97
|
+
if (reason.includes('duplicate-added-key') || reason.includes('duplicate-key')) return 'duplicate-member-name';
|
|
98
|
+
if (reason.includes('existing-member-changed')) return 'changed-existing-member';
|
|
99
|
+
if (reason.includes('existing-member-removed')) return 'removed-existing-member';
|
|
100
|
+
if (reason.includes('existing-member-order-changed')) return 'existing-member-order-changed';
|
|
101
|
+
if (reason.includes('order-sensitive-region-kind')) return 'order-sensitive-region-kind';
|
|
102
|
+
if (reason.includes('non-policy-source-change')) return 'non-policy-source-change';
|
|
103
|
+
if (reason.includes('unterminated-container')) return 'malformed-syntax';
|
|
104
|
+
if (reason.includes('unsupported-')) return 'unsupported-js-ts-syntax';
|
|
105
|
+
if (reason.includes('missing-') || reason.includes('not-safe-listed') || reason.includes('not-declared')) return 'invalid-input';
|
|
106
|
+
if (reason.includes('ambiguous-container') || reason.includes('container-not-found')) return 'parser-or-ledger-loss';
|
|
107
|
+
return reason.split(':')[0] || 'member-merge-blocked';
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function conflictCodeForReason(reasonCode) {
|
|
111
|
+
if (reasonCode === 'computed-key') return JsTsSafeMergeConflictCodes.computedKey;
|
|
112
|
+
if (reasonCode === 'overload-collision') return JsTsSafeMergeConflictCodes.unsupportedOverload;
|
|
113
|
+
if (reasonCode === 'type-alias-conflict') return JsTsSafeMergeConflictCodes.typeAliasConflict;
|
|
114
|
+
if (reasonCode === 'duplicate-member-name') return JsTsSafeMergeConflictCodes.duplicateName;
|
|
115
|
+
if (reasonCode === 'changed-existing-member' || reasonCode === 'removed-existing-member' || reasonCode === 'non-policy-source-change') {
|
|
116
|
+
return JsTsSafeMergeConflictCodes.changedExistingDeclaration;
|
|
117
|
+
}
|
|
118
|
+
if (reasonCode === 'existing-member-order-changed' || reasonCode === 'order-sensitive-region-kind') return JsTsSafeMergeConflictCodes.topLevelOrderChanged;
|
|
119
|
+
if (reasonCode === 'malformed-syntax') return JsTsSafeMergeConflictCodes.malformedSyntax;
|
|
120
|
+
if (reasonCode === 'invalid-input') return JsTsSafeMergeConflictCodes.invalidInput;
|
|
121
|
+
return JsTsSafeMergeConflictCodes.parserLedgerLoss;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function gateIdForReason(reasonCode) {
|
|
125
|
+
if (reasonCode === 'duplicate-member-name' || reasonCode === 'overload-collision') return JsTsSafeMergeGateIds.uniqueNames;
|
|
126
|
+
if (reasonCode === 'changed-existing-member' || reasonCode === 'removed-existing-member' || reasonCode === 'non-policy-source-change') {
|
|
127
|
+
return JsTsSafeMergeGateIds.stableExistingDeclarations;
|
|
128
|
+
}
|
|
129
|
+
if (reasonCode === 'existing-member-order-changed' || reasonCode === 'order-sensitive-region-kind') return JsTsSafeMergeGateIds.preserveBaseOrder;
|
|
130
|
+
return JsTsSafeMergeGateIds.parseLedger;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function reasonDetails(reason, reasonCode) {
|
|
134
|
+
const parts = String(reason).split(':');
|
|
135
|
+
const details = { reason, reasonCode };
|
|
136
|
+
if (['base', 'worker', 'head'].includes(parts[1])) details.side = parts[1];
|
|
137
|
+
if (['base', 'worker', 'head'].includes(parts[2])) details.side = parts[2];
|
|
138
|
+
const kind = parts.find((part) => ['interface', 'type', 'class', 'object'].includes(part));
|
|
139
|
+
if (kind) details.regionKind = kind;
|
|
140
|
+
if (reasonCode === 'duplicate-member-name' || reasonCode === 'overload-collision') details.memberName = parts.at(-3) ?? parts.at(-1);
|
|
141
|
+
if (reasonCode === 'changed-existing-member' || reasonCode === 'removed-existing-member') details.memberName = parts.at(-3);
|
|
142
|
+
return details;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function memberConflictMessage(reasonCode, details) {
|
|
146
|
+
if (reasonCode === 'computed-key') return 'Computed member keys are not safe for automatic member merge.';
|
|
147
|
+
if (reasonCode === 'spread-like-member') return 'Spread-like member syntax makes object member merge ambiguous.';
|
|
148
|
+
if (reasonCode === 'overload-collision') return 'Member overloads or duplicate method signatures collide in an unordered member region.';
|
|
149
|
+
if (reasonCode === 'changed-existing-member') return 'An existing member changed inside a safe member-addition region.';
|
|
150
|
+
if (reasonCode === 'removed-existing-member') return 'An existing member was removed inside a safe member-addition region.';
|
|
151
|
+
if (reasonCode === 'duplicate-member-name') return 'Worker and head member additions contain the same member key.';
|
|
152
|
+
if (reasonCode === 'existing-member-order-changed') return 'A side changed the order of existing members in a non-semantic member region.';
|
|
153
|
+
return `JS/TS member merge blocked: ${details.reason}`;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export {
|
|
157
|
+
mergeResult
|
|
158
|
+
};
|