@shapeshift-labs/frontier-lang-compiler 0.2.138 → 0.2.140
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/dist/js-ts-safe-merge-semantic-edit-fallback-utils.js +41 -0
- package/dist/js-ts-safe-merge-semantic-edit-fallback.js +42 -40
- package/dist/js-ts-safe-merge-staged-top-level-fallback.js +8 -0
- package/dist/js-ts-safe-merge-top-level-neutralization.js +10 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -200,6 +200,11 @@ interface, type, class, or object member additions. Existing class/object method
|
|
|
200
200
|
or property body edits inside the declared member region are preserved for
|
|
201
201
|
semantic replay while added members are neutralized; object member additions are
|
|
202
202
|
re-emitted with safe commas when both sides add final properties.
|
|
203
|
+
If staged whole-declaration replay cannot verify because head changed a sibling
|
|
204
|
+
member inside the same declaration, `safeMergeJsTsSource` retries the direct
|
|
205
|
+
semantic edit projection and admits the merge only when replay still verifies
|
|
206
|
+
cleanly. That direct retry can project onto the staged top-level merge output,
|
|
207
|
+
so safe import/declaration additions are preserved alongside the sibling edit.
|
|
203
208
|
|
|
204
209
|
Project-level JS/TS safe merges compose the same file-level gates across a
|
|
205
210
|
base/worker/head file set. They preserve head-only files, admit worker-only
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { JsTsSafeMergeConflictCodes } from './js-ts-safe-merge-constants.js';
|
|
2
|
+
|
|
3
|
+
const semanticFallbackConflictCodes = new Set([
|
|
4
|
+
JsTsSafeMergeConflictCodes.changedExistingDeclaration,
|
|
5
|
+
JsTsSafeMergeConflictCodes.typeAliasConflict
|
|
6
|
+
]);
|
|
7
|
+
|
|
8
|
+
function shouldTrySemanticEditFallback(result) {
|
|
9
|
+
const conflicts = result.conflicts ?? [];
|
|
10
|
+
return conflicts.length > 0 && conflicts.every((conflict) => semanticFallbackConflictCodes.has(conflict.code));
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function semanticFallbackConflictCode(result) {
|
|
14
|
+
return result.conflicts?.find((conflict) => semanticFallbackConflictCodes.has(conflict.code))?.code
|
|
15
|
+
?? JsTsSafeMergeConflictCodes.changedExistingDeclaration;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function semanticFallbackChangedExistingDeclarations(topLevelResult, resultBase, stagedFallback) {
|
|
19
|
+
const conflictCount = (topLevelResult.conflicts ?? [])
|
|
20
|
+
.filter((conflict) => semanticFallbackConflictCodes.has(conflict.code)).length;
|
|
21
|
+
return Math.max(
|
|
22
|
+
topLevelResult.summary?.changedExistingDeclarations ?? 0,
|
|
23
|
+
resultBase?.summary?.changedExistingDeclarations ?? 0,
|
|
24
|
+
stagedFallback?.neutralization?.summary?.workerChangedExistingDeclarations ?? 0,
|
|
25
|
+
conflictCount
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function semanticFallbackPhase(fallback) {
|
|
30
|
+
if (!fallback) return 'semantic-edit-fallback';
|
|
31
|
+
return fallback.projectionMode === 'direct'
|
|
32
|
+
? 'staged-top-level-direct-semantic-edit-fallback'
|
|
33
|
+
: 'staged-top-level-semantic-edit-fallback';
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export {
|
|
37
|
+
semanticFallbackChangedExistingDeclarations,
|
|
38
|
+
semanticFallbackConflictCode,
|
|
39
|
+
semanticFallbackPhase,
|
|
40
|
+
shouldTrySemanticEditFallback
|
|
41
|
+
};
|
|
@@ -2,7 +2,13 @@ import { hashSemanticValue } from '@shapeshift-labs/frontier-lang-kernel';
|
|
|
2
2
|
import { createSemanticEditScript } from './internal/index-impl/semanticEditScripts.js';
|
|
3
3
|
import { projectSemanticEditScriptToSource } from './internal/index-impl/projectSemanticEditScriptToSource.js';
|
|
4
4
|
import { replaySemanticEditProjection } from './internal/index-impl/replaySemanticEditProjection.js';
|
|
5
|
-
import {
|
|
5
|
+
import { JsTsSafeMergeStatuses } from './js-ts-safe-merge-constants.js';
|
|
6
|
+
import {
|
|
7
|
+
semanticFallbackChangedExistingDeclarations,
|
|
8
|
+
semanticFallbackConflictCode,
|
|
9
|
+
semanticFallbackPhase,
|
|
10
|
+
shouldTrySemanticEditFallback
|
|
11
|
+
} from './js-ts-safe-merge-semantic-edit-fallback-utils.js';
|
|
6
12
|
import {
|
|
7
13
|
createStagedDeclarationAlreadyAppliedReplay,
|
|
8
14
|
createStagedDeclarationProjection,
|
|
@@ -14,9 +20,26 @@ import { idFragment, uniqueStrings } from './native-import-utils.js';
|
|
|
14
20
|
function semanticEditFallbackResult(input, topLevelResult) {
|
|
15
21
|
if (!shouldTrySemanticEditFallback(topLevelResult)) return topLevelResult;
|
|
16
22
|
const stagedFallback = createStagedTopLevelSemanticFallback(input, topLevelResult);
|
|
17
|
-
|
|
23
|
+
let selectedFallback = stagedFallback;
|
|
24
|
+
let artifacts = createSemanticEditFallbackArtifacts(input, topLevelResult, stagedFallback);
|
|
25
|
+
if (stagedFallback && artifacts.status !== 'verified') {
|
|
26
|
+
const directFallback = stagedFallback.directProjectionHeadSourceText && stagedFallback.safeTopLevelChanges > 0
|
|
27
|
+
? { ...stagedFallback, projectionMode: 'direct' }
|
|
28
|
+
: undefined;
|
|
29
|
+
const directArtifacts = createSemanticEditFallbackArtifacts(input, topLevelResult, directFallback);
|
|
30
|
+
if (directArtifacts.status === 'verified') {
|
|
31
|
+
artifacts = directArtifacts;
|
|
32
|
+
selectedFallback = directFallback;
|
|
33
|
+
} else if (directFallback) {
|
|
34
|
+
const plainDirectArtifacts = createSemanticEditFallbackArtifacts(input, topLevelResult, undefined);
|
|
35
|
+
if (plainDirectArtifacts.status === 'verified') {
|
|
36
|
+
artifacts = plainDirectArtifacts;
|
|
37
|
+
selectedFallback = undefined;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
18
41
|
if (artifacts.status !== 'verified') return semanticEditFallbackBlockedResult(input, topLevelResult, artifacts);
|
|
19
|
-
const resultBase =
|
|
42
|
+
const resultBase = selectedFallback?.stagedTopLevelResult ?? topLevelResult;
|
|
20
43
|
const mergedSourceText = artifacts.projection.sourceText;
|
|
21
44
|
const gates = semanticEditGates(artifacts);
|
|
22
45
|
return {
|
|
@@ -38,7 +61,7 @@ function semanticEditFallbackResult(input, topLevelResult) {
|
|
|
38
61
|
},
|
|
39
62
|
summary: {
|
|
40
63
|
...resultBase.summary,
|
|
41
|
-
changedExistingDeclarations: semanticFallbackChangedExistingDeclarations(topLevelResult, resultBase,
|
|
64
|
+
changedExistingDeclarations: semanticFallbackChangedExistingDeclarations(topLevelResult, resultBase, selectedFallback),
|
|
42
65
|
conflicts: 0,
|
|
43
66
|
gatesPassed: gates.filter((gate) => gate.status === 'passed').length,
|
|
44
67
|
semanticEditOperations: artifacts.script.summary.operations,
|
|
@@ -49,58 +72,37 @@ function semanticEditFallbackResult(input, topLevelResult) {
|
|
|
49
72
|
metadata: {
|
|
50
73
|
...resultBase.metadata,
|
|
51
74
|
composed: {
|
|
52
|
-
phase:
|
|
53
|
-
phases:
|
|
75
|
+
phase: semanticFallbackPhase(selectedFallback),
|
|
76
|
+
phases: selectedFallback ? ['top-level-neutralization', 'top-level-ledger', 'semantic-edit'] : ['top-level-ledger', 'semantic-edit'],
|
|
54
77
|
originalReasonCodes: topLevelResult.admission?.reasonCodes ?? [],
|
|
55
|
-
stagedTopLevelSummary:
|
|
56
|
-
neutralization:
|
|
78
|
+
stagedTopLevelSummary: selectedFallback?.stagedTopLevelResult?.summary,
|
|
79
|
+
neutralization: selectedFallback?.neutralization?.summary
|
|
57
80
|
}
|
|
58
81
|
},
|
|
59
82
|
semanticArtifacts: artifacts
|
|
60
83
|
};
|
|
61
84
|
}
|
|
62
85
|
|
|
63
|
-
function shouldTrySemanticEditFallback(result) {
|
|
64
|
-
const conflicts = result.conflicts ?? [];
|
|
65
|
-
return conflicts.length > 0 && conflicts.every((conflict) => semanticFallbackConflictCodes.has(conflict.code));
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const semanticFallbackConflictCodes = new Set([
|
|
69
|
-
JsTsSafeMergeConflictCodes.changedExistingDeclaration,
|
|
70
|
-
JsTsSafeMergeConflictCodes.typeAliasConflict
|
|
71
|
-
]);
|
|
72
|
-
|
|
73
|
-
function semanticFallbackConflictCode(result) {
|
|
74
|
-
return result.conflicts?.find((conflict) => semanticFallbackConflictCodes.has(conflict.code))?.code
|
|
75
|
-
?? JsTsSafeMergeConflictCodes.changedExistingDeclaration;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function semanticFallbackChangedExistingDeclarations(topLevelResult, resultBase, stagedFallback) {
|
|
79
|
-
const conflictCount = (topLevelResult.conflicts ?? [])
|
|
80
|
-
.filter((conflict) => semanticFallbackConflictCodes.has(conflict.code)).length;
|
|
81
|
-
return Math.max(
|
|
82
|
-
topLevelResult.summary?.changedExistingDeclarations ?? 0,
|
|
83
|
-
resultBase?.summary?.changedExistingDeclarations ?? 0,
|
|
84
|
-
stagedFallback?.neutralization?.summary?.workerChangedExistingDeclarations ?? 0,
|
|
85
|
-
conflictCount
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
86
|
function createSemanticEditFallbackArtifacts(input, topLevelResult, stagedFallback) {
|
|
90
87
|
try {
|
|
91
88
|
const id = String(input.id ?? topLevelResult.id ?? 'js_ts_safe_merge');
|
|
92
89
|
const language = input.language ?? topLevelResult.language ?? 'typescript';
|
|
93
90
|
const sourcePath = input.sourcePath ?? topLevelResult.sourcePath ?? 'inline.ts';
|
|
91
|
+
const stagedDeclarationProjection = stagedFallback && stagedFallback.projectionMode !== 'direct';
|
|
94
92
|
const scriptInput = stagedFallback?.scriptInput ?? input;
|
|
95
|
-
const projectionHeadSourceText = stagedFallback?.
|
|
96
|
-
|
|
93
|
+
const projectionHeadSourceText = stagedFallback?.projectionMode === 'direct'
|
|
94
|
+
? stagedFallback.directProjectionHeadSourceText
|
|
95
|
+
: stagedFallback?.projectionHeadSourceText ?? input.headSourceText;
|
|
96
|
+
const replayCurrentSourceText = stagedFallback?.projectionMode === 'direct'
|
|
97
|
+
? stagedFallback.directReplayCurrentSourceText
|
|
98
|
+
: stagedFallback?.replayCurrentSourceText ?? input.headSourceText;
|
|
97
99
|
const script = createSemanticEditScript({
|
|
98
100
|
...scriptInput,
|
|
99
101
|
id: `${id}_semantic_edit`,
|
|
100
102
|
language,
|
|
101
103
|
sourcePath
|
|
102
104
|
});
|
|
103
|
-
const projection =
|
|
105
|
+
const projection = stagedDeclarationProjection
|
|
104
106
|
? createStagedDeclarationProjection({ id, script, sourcePath, language, stagedFallback })
|
|
105
107
|
: projectSemanticEditScriptToSource({
|
|
106
108
|
id: `${id}_semantic_edit_projection`,
|
|
@@ -111,7 +113,7 @@ function createSemanticEditFallbackArtifacts(input, topLevelResult, stagedFallba
|
|
|
111
113
|
parser: input.parser,
|
|
112
114
|
metadata: stagedFallback?.metadata
|
|
113
115
|
});
|
|
114
|
-
const replay =
|
|
116
|
+
const replay = stagedDeclarationProjection
|
|
115
117
|
? createStagedDeclarationReplayRecord({ id, projection, sourcePath, language, stagedFallback, replayCurrentSourceText })
|
|
116
118
|
: replaySemanticEditProjection({
|
|
117
119
|
id: `${id}_semantic_edit_replay`,
|
|
@@ -122,7 +124,7 @@ function createSemanticEditFallbackArtifacts(input, topLevelResult, stagedFallba
|
|
|
122
124
|
parser: input.parser,
|
|
123
125
|
metadata: stagedFallback?.metadata
|
|
124
126
|
});
|
|
125
|
-
const alreadyAppliedReplay =
|
|
127
|
+
const alreadyAppliedReplay = stagedDeclarationProjection
|
|
126
128
|
? createStagedDeclarationAlreadyAppliedReplay({ id, projection, sourcePath, language })
|
|
127
129
|
: replaySemanticEditProjection({
|
|
128
130
|
id: `${id}_semantic_edit_already_applied`,
|
|
@@ -193,7 +195,7 @@ function semanticEditArtifacts(input) {
|
|
|
193
195
|
metadata: {
|
|
194
196
|
autoMergeClaim: false,
|
|
195
197
|
semanticEquivalenceClaim: false,
|
|
196
|
-
source: input.stagedFallback ?
|
|
198
|
+
source: input.stagedFallback ? semanticFallbackPhase(input.stagedFallback) : 'js-ts-semantic-edit-fallback',
|
|
197
199
|
originalReasonCodes: input.topLevelResult.admission?.reasonCodes ?? [],
|
|
198
200
|
stagedTopLevelSummary: input.stagedFallback?.stagedTopLevelResult?.summary,
|
|
199
201
|
neutralization: input.stagedFallback?.neutralization?.summary
|
|
@@ -14,11 +14,13 @@ function createStagedTopLevelSemanticFallback(input, topLevelResult) {
|
|
|
14
14
|
if (stagedTopLevelResult.status !== JsTsSafeMergeStatuses.merged) return undefined;
|
|
15
15
|
const safeTopLevelChanges = safeTopLevelChangeCount(stagedTopLevelResult.summary);
|
|
16
16
|
const declarationReplay = createJsTsChangedDeclarationReplay(input, neutralization, stagedTopLevelResult.mergedSourceText);
|
|
17
|
+
const directSemanticHeadReplay = createJsTsChangedDeclarationReplay(input, neutralization, stagedTopLevelResult.mergedSourceText, 'head');
|
|
17
18
|
const workerDeclarationChanges = neutralization.summary.workerChangedExistingDeclarations ?? 0;
|
|
18
19
|
if (safeTopLevelChanges === 0 && workerDeclarationChanges === 0) return undefined;
|
|
19
20
|
return {
|
|
20
21
|
neutralization,
|
|
21
22
|
declarationReplay,
|
|
23
|
+
safeTopLevelChanges,
|
|
22
24
|
stagedTopLevelResult,
|
|
23
25
|
scriptInput: {
|
|
24
26
|
...input,
|
|
@@ -28,13 +30,19 @@ function createStagedTopLevelSemanticFallback(input, topLevelResult) {
|
|
|
28
30
|
headSourceHash: undefined
|
|
29
31
|
},
|
|
30
32
|
projectionHeadSourceText: stagedTopLevelResult.mergedSourceText,
|
|
33
|
+
directProjectionHeadSourceText: directSemanticHeadReplay.outputSourceText,
|
|
31
34
|
replayCurrentSourceText: stagedTopLevelResult.mergedSourceText,
|
|
35
|
+
directReplayCurrentSourceText: directSemanticHeadReplay.outputSourceText,
|
|
32
36
|
metadata: {
|
|
33
37
|
stagedTopLevelSummary: stagedTopLevelResult.summary,
|
|
34
38
|
declarationReplay: {
|
|
35
39
|
edits: declarationReplay.edits.length,
|
|
36
40
|
reasonCodes: declarationReplay.reasonCodes
|
|
37
41
|
},
|
|
42
|
+
directSemanticHeadReplay: {
|
|
43
|
+
edits: directSemanticHeadReplay.edits.length,
|
|
44
|
+
reasonCodes: directSemanticHeadReplay.reasonCodes
|
|
45
|
+
},
|
|
38
46
|
neutralization: neutralization.summary,
|
|
39
47
|
originalReasonCodes: topLevelResult.admission?.reasonCodes ?? []
|
|
40
48
|
}
|
|
@@ -42,7 +42,7 @@ function neutralizeJsTsSafeTopLevelMergeSources(input = {}) {
|
|
|
42
42
|
};
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
function createJsTsChangedDeclarationReplay(input = {}, neutralization, currentSourceText) {
|
|
45
|
+
function createJsTsChangedDeclarationReplay(input = {}, neutralization, currentSourceText, side = 'worker') {
|
|
46
46
|
if (!neutralization?.ok || typeof currentSourceText !== 'string') {
|
|
47
47
|
return { ok: false, reasonCodes: ['missing-neutralized-current-source'], edits: [] };
|
|
48
48
|
}
|
|
@@ -56,15 +56,17 @@ function createJsTsChangedDeclarationReplay(input = {}, neutralization, currentS
|
|
|
56
56
|
const workerMatches = matchedEntriesByBaseKey(neutralization.worker, baseEntries);
|
|
57
57
|
const headMatches = matchedEntriesByBaseKey(neutralization.head, baseEntries);
|
|
58
58
|
const currentMatches = matchedEntriesByBaseKey(current, baseEntries);
|
|
59
|
+
const sourceMatches = side === 'head' ? headMatches : workerMatches;
|
|
60
|
+
const guardMatches = side === 'head' ? undefined : headMatches;
|
|
59
61
|
const edits = [];
|
|
60
62
|
const reasonCodes = [];
|
|
61
63
|
for (const baseEntry of baseEntries) {
|
|
62
64
|
if (baseEntry.kind === 'import') continue;
|
|
63
|
-
const
|
|
64
|
-
if (!
|
|
65
|
-
const headEntry = headMatches.get(baseEntry.key);
|
|
65
|
+
const sourceEntry = sourceMatches.get(baseEntry.key);
|
|
66
|
+
if (!sourceEntry || sameStatementText(sourceEntry.text, baseEntry.text)) continue;
|
|
66
67
|
const currentEntry = currentMatches.get(baseEntry.key);
|
|
67
|
-
|
|
68
|
+
const guardEntry = guardMatches?.get(baseEntry.key);
|
|
69
|
+
if (guardMatches && (!guardEntry || !sameStatementText(guardEntry.text, baseEntry.text))) {
|
|
68
70
|
reasonCodes.push(`head-anchor-changed-since-base:${baseEntry.key}`);
|
|
69
71
|
continue;
|
|
70
72
|
}
|
|
@@ -74,12 +76,12 @@ function createJsTsChangedDeclarationReplay(input = {}, neutralization, currentS
|
|
|
74
76
|
}
|
|
75
77
|
edits.push({
|
|
76
78
|
key: baseEntry.key,
|
|
77
|
-
names:
|
|
78
|
-
declarationKind:
|
|
79
|
+
names: sourceEntry.names ?? baseEntry.names ?? [],
|
|
80
|
+
declarationKind: sourceEntry.declarationInfo?.declarationKind ?? baseEntry.declarationInfo?.declarationKind,
|
|
79
81
|
start: currentEntry.start,
|
|
80
82
|
end: currentEntry.end,
|
|
81
83
|
currentText: currentEntry.text,
|
|
82
|
-
replacementText:
|
|
84
|
+
replacementText: sourceEntry.text
|
|
83
85
|
});
|
|
84
86
|
}
|
|
85
87
|
return {
|
package/package.json
CHANGED