@shapeshift-labs/frontier-lang-compiler 0.2.103 → 0.2.105

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.
Files changed (125) hide show
  1. package/README.md +14 -0
  2. package/dist/declarations/bidirectional-target-change-source-edit.d.ts +30 -0
  3. package/dist/declarations/bidirectional-target-change.d.ts +10 -0
  4. package/dist/declarations/js-ts-safe-member-merge.d.ts +86 -0
  5. package/dist/declarations/js-ts-safe-merge.d.ts +131 -0
  6. package/dist/declarations/js-ts-semantic-conflict-sidecars.d.ts +235 -0
  7. package/dist/declarations/js-ts-semantic-merge-contracts.d.ts +287 -0
  8. package/dist/declarations/js-ts-semantic-merge.d.ts +4 -0
  9. package/dist/declarations/native-import-losses.d.ts +3 -0
  10. package/dist/declarations/semantic-edit-replay-diagnostics.d.ts +12 -0
  11. package/dist/declarations/semantic-edit-script.d.ts +7 -4
  12. package/dist/declarations/semantic-patch-bundle-index.d.ts +45 -0
  13. package/dist/declarations/semantic-patch-bundle.d.ts +6 -4
  14. package/dist/declarations/semantic-sidecar-example.d.ts +18 -0
  15. package/dist/declarations/semantic-transform-identity.d.ts +3 -0
  16. package/dist/declarations/source-preservation.d.ts +72 -0
  17. package/dist/declarations/universal-capability.d.ts +4 -0
  18. package/dist/declarations/universal-conversion-artifacts.d.ts +61 -1
  19. package/dist/declarations/universal-conversion-compact-counts.d.ts +51 -0
  20. package/dist/declarations/universal-conversion-plan.d.ts +6 -1
  21. package/dist/declarations/universal-representation-coverage.d.ts +90 -0
  22. package/dist/index.d.ts +4 -0
  23. package/dist/index.js +3 -0
  24. package/dist/internal/index-impl/bidirectionalExactSourceBackprojection.js +199 -0
  25. package/dist/internal/index-impl/bidirectionalSameLanguageSourceProjection.js +112 -0
  26. package/dist/internal/index-impl/bidirectionalSourceEditProjection.js +319 -0
  27. package/dist/internal/index-impl/bidirectionalSourceEditProjectionArtifacts.js +67 -0
  28. package/dist/internal/index-impl/bidirectionalTargetChangeRecordInternals.js +17 -5
  29. package/dist/internal/index-impl/bidirectionalTargetRoundtripEvidence.js +58 -20
  30. package/dist/internal/index-impl/createBidirectionalTargetChangeRecord.js +60 -7
  31. package/dist/internal/index-impl/createLightweightNativeImport.js +1 -0
  32. package/dist/internal/index-impl/createNativeSourcePreservation.js +28 -2
  33. package/dist/internal/index-impl/diffNativeSymbols.js +3 -3
  34. package/dist/internal/index-impl/nativeChangeProjectionSourceMapLinks.js +2 -0
  35. package/dist/internal/index-impl/projectSemanticEditScriptToSource.js +43 -8
  36. package/dist/internal/index-impl/replaySemanticEditLineEndings.js +34 -0
  37. package/dist/internal/index-impl/replaySemanticEditProjection.js +39 -19
  38. package/dist/internal/index-impl/semanticEditBundleAdmission.js +7 -3
  39. package/dist/internal/index-impl/semanticEditBundleIndex.js +47 -1
  40. package/dist/internal/index-impl/semanticEditExplicitSourceReplacement.js +40 -0
  41. package/dist/internal/index-impl/semanticEditOperationCoverage.js +33 -3
  42. package/dist/internal/index-impl/semanticEditProjectionRecord.js +29 -0
  43. package/dist/internal/index-impl/semanticEditReplayDiagnostics.js +39 -0
  44. package/dist/internal/index-impl/semanticEditReplaySourceReplacement.js +85 -0
  45. package/dist/internal/index-impl/semanticEditScripts.js +4 -0
  46. package/dist/internal/index-impl/semanticEditSourceRanges.js +27 -0
  47. package/dist/internal/index-impl/semanticIndexFromNativeDeclarations.js +1 -0
  48. package/dist/internal/index-impl/semanticPatchBundleAdmission.js +41 -7
  49. package/dist/internal/index-impl/semanticPatchBundleRecords.js +16 -0
  50. package/dist/internal/index-impl/semanticPatchBundleSourceRecords.js +2 -0
  51. package/dist/internal/index-impl/semanticSidecarQuality.js +111 -0
  52. package/dist/internal/index-impl/semanticSourceEditDedupe.js +69 -9
  53. package/dist/internal/index-impl/semanticTransformIdentityRecords.js +85 -9
  54. package/dist/js-ts-safe-member-merge-result.js +158 -0
  55. package/dist/js-ts-safe-member-merge.js +265 -0
  56. package/dist/js-ts-safe-merge-analyze.js +279 -0
  57. package/dist/js-ts-safe-merge-composed.js +170 -0
  58. package/dist/js-ts-safe-merge-constants.js +50 -0
  59. package/dist/js-ts-safe-merge-context.js +118 -0
  60. package/dist/js-ts-safe-merge-ledger-validation.js +92 -0
  61. package/dist/js-ts-safe-merge-ledger.js +85 -0
  62. package/dist/js-ts-safe-merge-parse-declarations.js +210 -0
  63. package/dist/js-ts-safe-merge-parse-statements.js +155 -0
  64. package/dist/js-ts-safe-merge-plan.js +190 -0
  65. package/dist/js-ts-safe-merge.js +175 -0
  66. package/dist/js-ts-semantic-conflict-sidecar-constants.js +77 -0
  67. package/dist/js-ts-semantic-conflict-sidecar-detectors.js +195 -0
  68. package/dist/js-ts-semantic-conflict-sidecar-normalize.js +203 -0
  69. package/dist/js-ts-semantic-conflict-sidecar-utils.js +190 -0
  70. package/dist/js-ts-semantic-conflict-sidecars.js +81 -0
  71. package/dist/js-ts-semantic-merge-contract-helpers.js +128 -0
  72. package/dist/js-ts-semantic-merge-contracts.js +217 -0
  73. package/dist/js-ts-semantic-merge-member-containers.js +100 -0
  74. package/dist/js-ts-semantic-merge-member-keys.js +142 -0
  75. package/dist/js-ts-semantic-merge-member-segments.js +185 -0
  76. package/dist/js-ts-semantic-merge-member-source.js +82 -0
  77. package/dist/js-ts-semantic-merge-member-utils.js +18 -0
  78. package/dist/js-ts-semantic-merge-parse.js +16 -0
  79. package/dist/js-ts-semantic-merge.js +24 -0
  80. package/dist/lightweight-dependency-effects.js +51 -0
  81. package/dist/lightweight-dependency-language.js +12 -1
  82. package/dist/lightweight-dependency-relations.js +14 -27
  83. package/dist/native-region-scanner-core.js +33 -1
  84. package/dist/native-region-scanner-csharp.js +151 -0
  85. package/dist/native-region-scanner-dart.js +91 -0
  86. package/dist/native-region-scanner-dynamic.js +21 -151
  87. package/dist/native-region-scanner-functional.js +40 -13
  88. package/dist/native-region-scanner-java.js +97 -0
  89. package/dist/native-region-scanner-js-class.js +100 -0
  90. package/dist/native-region-scanner-js-helpers.js +28 -86
  91. package/dist/native-region-scanner-js-imports.js +121 -1
  92. package/dist/native-region-scanner-js-nested.js +96 -8
  93. package/dist/native-region-scanner-js-structure.js +27 -0
  94. package/dist/native-region-scanner-js-types.js +99 -0
  95. package/dist/native-region-scanner-js.js +70 -118
  96. package/dist/native-region-scanner-kotlin.js +94 -0
  97. package/dist/native-region-scanner-main.js +15 -181
  98. package/dist/native-region-scanner-php.js +80 -0
  99. package/dist/native-region-scanner-python.js +62 -0
  100. package/dist/native-region-scanner-ruby.js +72 -0
  101. package/dist/native-region-scanner-scala.js +91 -0
  102. package/dist/native-region-scanner-spans.js +74 -0
  103. package/dist/native-region-scanner-swift.js +155 -0
  104. package/dist/native-region-scanner.js +14 -10
  105. package/dist/native-source-ledger-helpers.js +195 -0
  106. package/dist/native-source-ledger.js +306 -0
  107. package/dist/native-source-preservation-scanner.js +4 -0
  108. package/dist/semantic-import-callsite-regions.js +136 -0
  109. package/dist/semantic-import-effect-regions.js +283 -0
  110. package/dist/semantic-import-regions.js +11 -2
  111. package/dist/semantic-import-sidecar-entry.js +16 -2
  112. package/dist/semantic-import-sidecar-types.d.ts +2 -0
  113. package/dist/semantic-sidecar-example.js +68 -0
  114. package/dist/universal-capability-matrix.js +23 -0
  115. package/dist/universal-conversion-artifact-query.js +79 -2
  116. package/dist/universal-conversion-artifact-semantic-edit.js +103 -0
  117. package/dist/universal-conversion-artifact-summary.js +33 -1
  118. package/dist/universal-conversion-artifacts.js +13 -48
  119. package/dist/universal-conversion-plan-scoring.js +21 -1
  120. package/dist/universal-conversion-plan-summary.js +30 -0
  121. package/dist/universal-conversion-plan.js +25 -9
  122. package/dist/universal-conversion-route-metadata.js +96 -0
  123. package/dist/universal-conversion-route-operations.js +7 -0
  124. package/dist/universal-representation-coverage.js +193 -0
  125. package/package.json +1 -1
@@ -0,0 +1,100 @@
1
+ function normalizeKind(kind) {
2
+ const text = String(kind ?? '').toLowerCase();
3
+ if (text === 'interface') return 'interface';
4
+ if (text === 'type' || text === 'typealias' || text === 'type-alias') return 'type';
5
+ if (text === 'class') return 'class';
6
+ if (text === 'object' || text === 'object-literal') return 'object';
7
+ return undefined;
8
+ }
9
+
10
+ function findContainer(sourceText, region) {
11
+ const kind = normalizeKind(region.kind);
12
+ const pattern = containerPattern(kind, region.name);
13
+ const matches = [];
14
+ let match;
15
+ while ((match = pattern.exec(sourceText))) {
16
+ const openIndex = sourceText.indexOf('{', match.index);
17
+ if (openIndex < 0 || openIndex >= pattern.lastIndex) continue;
18
+ const closeIndex = findMatchingBrace(sourceText, openIndex);
19
+ if (closeIndex < 0) return { reasonCodes: ['unterminated-container'] };
20
+ matches.push({
21
+ kind,
22
+ name: region.name,
23
+ start: match.index,
24
+ openStart: openIndex,
25
+ bodyStart: openIndex + 1,
26
+ bodyEnd: closeIndex,
27
+ end: closeIndex + 1,
28
+ body: sourceText.slice(openIndex + 1, closeIndex)
29
+ });
30
+ }
31
+ if (!matches.length) return { reasonCodes: ['container-not-found'] };
32
+ if (matches.length > 1) return { reasonCodes: ['ambiguous-container'] };
33
+ return { reasonCodes: [], value: matches[0] };
34
+ }
35
+
36
+ function containerPattern(kind, name) {
37
+ const escapedName = escapeRegExp(name);
38
+ if (kind === 'interface') return new RegExp(`\\b(?:export\\s+)?interface\\s+${escapedName}\\b[^{};=]*\\{`, 'g');
39
+ if (kind === 'type') return new RegExp(`\\b(?:export\\s+)?type\\s+${escapedName}\\b\\s*=\\s*\\{`, 'g');
40
+ if (kind === 'class') return new RegExp(`\\b(?:export\\s+)?(?:default\\s+)?(?:abstract\\s+)?class\\s+${escapedName}\\b[^{};=]*\\{`, 'g');
41
+ return new RegExp(`\\b(?:export\\s+)?(?:const|let|var)\\s+${escapedName}\\b[^=;{}]*=\\s*\\{`, 'g');
42
+ }
43
+
44
+ function findMatchingBrace(sourceText, openIndex) {
45
+ let depth = 0;
46
+ let quote;
47
+ let escaped = false;
48
+ let blockComment = false;
49
+ let lineComment = false;
50
+ for (let index = openIndex; index < sourceText.length; index += 1) {
51
+ const char = sourceText[index];
52
+ const next = sourceText[index + 1];
53
+ if (lineComment) {
54
+ if (char === '\n' || char === '\r') lineComment = false;
55
+ continue;
56
+ }
57
+ if (blockComment) {
58
+ if (char === '*' && next === '/') {
59
+ blockComment = false;
60
+ index += 1;
61
+ }
62
+ continue;
63
+ }
64
+ if (quote) {
65
+ if (escaped) escaped = false;
66
+ else if (char === '\\') escaped = true;
67
+ else if (char === quote) quote = undefined;
68
+ continue;
69
+ }
70
+ if (char === '/' && next === '/') {
71
+ lineComment = true;
72
+ index += 1;
73
+ continue;
74
+ }
75
+ if (char === '/' && next === '*') {
76
+ blockComment = true;
77
+ index += 1;
78
+ continue;
79
+ }
80
+ if (char === '\'' || char === '"' || char === '`') {
81
+ quote = char;
82
+ continue;
83
+ }
84
+ if (char === '{') depth += 1;
85
+ else if (char === '}') {
86
+ depth -= 1;
87
+ if (depth === 0) return index;
88
+ }
89
+ }
90
+ return -1;
91
+ }
92
+
93
+ function escapeRegExp(value) {
94
+ return String(value).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
95
+ }
96
+
97
+ export {
98
+ findContainer,
99
+ normalizeKind
100
+ };
@@ -0,0 +1,142 @@
1
+ function memberKey(text, kind) {
2
+ if (kind === 'object') return objectMemberKey(text);
3
+ if (kind === 'class') return classMemberKey(text);
4
+ return typeMemberKey(text);
5
+ }
6
+
7
+ function objectMemberKey(text) {
8
+ const source = text.replace(/[;,]\s*$/, '').trim();
9
+ const methodSource = stripObjectMemberPrefixes(source);
10
+ const methodMatch = methodSource.match(/^(['"]?)([A-Za-z_$][\w$-]*)\1\s*(?:<[^({;]+>)?\s*\(/);
11
+ if (methodMatch) return { key: methodMatch[2], memberKind: 'method' };
12
+ const colon = topLevelColon(text);
13
+ if (colon >= 0) {
14
+ const key = propertyKey(text.slice(0, colon).trim());
15
+ return key ? { key, memberKind: 'property' } : undefined;
16
+ }
17
+ const shorthand = propertyKey(source);
18
+ return shorthand ? { key: shorthand, memberKind: 'property' } : undefined;
19
+ }
20
+
21
+ function typeMemberKey(text) {
22
+ const source = text.replace(/[;,]\s*$/, '').trim().replace(/^readonly\s+/, '');
23
+ const methodMatch = source.match(/^(['"]?)([A-Za-z_$][\w$-]*)\1\??\s*(?:<[^({;]+>)?\s*\(/);
24
+ if (methodMatch) return { key: methodMatch[2], memberKind: 'method' };
25
+ const colon = topLevelColon(source);
26
+ if (colon < 0) return undefined;
27
+ const key = propertyKey(source.slice(0, colon).trim().replace(/\?$/, '').trim());
28
+ return key ? { key, memberKind: 'property' } : undefined;
29
+ }
30
+
31
+ function classMemberKey(text) {
32
+ const stripped = stripClassMemberPrefixes(text.replace(/[;,]\s*$/, '').trim());
33
+ const source = stripped.source;
34
+ if (!source || source.startsWith('@') || /^static\s*\{/.test(source)) return undefined;
35
+ const constructorMatch = source.match(/^constructor\s*\(/);
36
+ if (constructorMatch) return { key: 'constructor', memberKind: 'constructor' };
37
+ const accessorMatch = source.match(/^(get|set)\s+(['"]?)(#?[A-Za-z_$][\w$-]*)\2\s*\(/);
38
+ if (accessorMatch) return { key: classMemberKeyName(accessorMatch[3], stripped.isStatic), memberKind: 'accessor' };
39
+ const methodMatch = source.match(/^(?:async\s+)?(['"]?)(#?[A-Za-z_$][\w$-]*)\1\s*(?:<[^({;]+>)?\s*\(/);
40
+ if (methodMatch) return { key: classMemberKeyName(methodMatch[2], stripped.isStatic), memberKind: 'method' };
41
+ const propertyMatch = source.match(/^(['"]?)(#?[A-Za-z_$][\w$-]*)\1[?!]?\s*(?::|=|$)/);
42
+ if (propertyMatch) return { key: classMemberKeyName(propertyMatch[2], stripped.isStatic), memberKind: 'property' };
43
+ return undefined;
44
+ }
45
+
46
+ function classMemberKeyName(name, isStatic) {
47
+ return isStatic ? `static.${name}` : name;
48
+ }
49
+
50
+ function stripObjectMemberPrefixes(source) {
51
+ return String(source ?? '').replace(/^(?:async|get|set)\s+/, '');
52
+ }
53
+
54
+ function stripClassMemberPrefixes(source) {
55
+ let output = String(source ?? '').trim();
56
+ let isStatic = false;
57
+ const prefixes = ['public', 'private', 'protected', 'abstract', 'override', 'declare', 'readonly', 'accessor'];
58
+ let changed = true;
59
+ while (changed) {
60
+ changed = false;
61
+ for (const prefix of prefixes) {
62
+ const pattern = new RegExp(`^${prefix}\\s+`);
63
+ if (pattern.test(output)) {
64
+ output = output.replace(pattern, '').trimStart();
65
+ changed = true;
66
+ }
67
+ }
68
+ if (/^static\s+/.test(output)) {
69
+ output = output.replace(/^static\s+/, '').trimStart();
70
+ isStatic = true;
71
+ changed = true;
72
+ }
73
+ }
74
+ return { source: output, isStatic };
75
+ }
76
+
77
+ function isTypeAliasConflictMember(text) {
78
+ return /^\|/.test(text) || /^&/.test(text);
79
+ }
80
+
81
+ function hasSpreadLikeMember(text) {
82
+ return stripLeadingMemberKeywords(text).startsWith('...');
83
+ }
84
+
85
+ function hasComputedMemberKey(text) {
86
+ return stripLeadingMemberKeywords(text).startsWith('[');
87
+ }
88
+
89
+ function stripLeadingMemberKeywords(text) {
90
+ let source = String(text ?? '').trim();
91
+ const prefixes = ['public', 'private', 'protected', 'abstract', 'override', 'declare', 'readonly', 'static', 'accessor', 'async', 'get', 'set'];
92
+ let changed = true;
93
+ while (changed) {
94
+ changed = false;
95
+ for (const prefix of prefixes) {
96
+ const pattern = new RegExp(`^${prefix}\\s+`);
97
+ if (pattern.test(source)) {
98
+ source = source.replace(pattern, '').trimStart();
99
+ changed = true;
100
+ }
101
+ }
102
+ }
103
+ return source;
104
+ }
105
+
106
+ function propertyKey(source) {
107
+ if (!source || source.startsWith('[')) return undefined;
108
+ const quoted = source.match(/^(['"])([^'"\\]+)\1$/);
109
+ if (quoted) return quoted[2];
110
+ const identifier = source.match(/^[A-Za-z_$][\w$-]*$/);
111
+ return identifier?.[0];
112
+ }
113
+
114
+ function topLevelColon(source) {
115
+ let quote;
116
+ let escaped = false;
117
+ let depth = 0;
118
+ for (let index = 0; index < source.length; index += 1) {
119
+ const char = source[index];
120
+ if (quote) {
121
+ if (escaped) escaped = false;
122
+ else if (char === '\\') escaped = true;
123
+ else if (char === quote) quote = undefined;
124
+ continue;
125
+ }
126
+ if (char === '\'' || char === '"' || char === '`') {
127
+ quote = char;
128
+ continue;
129
+ }
130
+ if (char === '{' || char === '[' || char === '(') depth += 1;
131
+ else if (char === '}' || char === ']' || char === ')') depth -= 1;
132
+ else if (char === ':' && depth === 0) return index;
133
+ }
134
+ return -1;
135
+ }
136
+
137
+ export {
138
+ hasComputedMemberKey,
139
+ hasSpreadLikeMember,
140
+ isTypeAliasConflictMember,
141
+ memberKey
142
+ };
@@ -0,0 +1,185 @@
1
+ import {
2
+ hasComputedMemberKey,
3
+ hasSpreadLikeMember,
4
+ isTypeAliasConflictMember,
5
+ memberKey
6
+ } from './js-ts-semantic-merge-member-keys.js';
7
+ import { uniqueStrings } from './js-ts-semantic-merge-member-utils.js';
8
+
9
+ function parseMembers(body, kind) {
10
+ const reasonCodes = [];
11
+ const members = [];
12
+ for (const segment of splitMemberSegments(body, kind)) {
13
+ const trimmed = segment.text.trim();
14
+ if (!trimmed) continue;
15
+ if (hasSpreadLikeMember(trimmed)) {
16
+ reasonCodes.push('spread-like-member');
17
+ continue;
18
+ }
19
+ if (hasComputedMemberKey(trimmed)) {
20
+ reasonCodes.push('computed-key');
21
+ continue;
22
+ }
23
+ if (kind === 'type' && isTypeAliasConflictMember(trimmed)) {
24
+ reasonCodes.push('type-alias-conflict');
25
+ continue;
26
+ }
27
+ const parsed = memberKey(trimmed, kind);
28
+ if (!parsed?.key) {
29
+ reasonCodes.push(`unsupported-${kind}-member`);
30
+ continue;
31
+ }
32
+ members.push({ ...segment, ...parsed });
33
+ }
34
+ return { members, reasonCodes: uniqueStrings(reasonCodes) };
35
+ }
36
+
37
+ function splitMemberSegments(body, kind) {
38
+ if (kind === 'class') return splitClassMemberSegments(body);
39
+ const entries = [];
40
+ const text = String(body ?? '');
41
+ let start = 0;
42
+ let quote;
43
+ let escaped = false;
44
+ let blockComment = false;
45
+ let lineComment = false;
46
+ let depth = 0;
47
+ for (let index = 0; index < text.length; index += 1) {
48
+ const char = text[index];
49
+ const next = text[index + 1];
50
+ if (lineComment) {
51
+ if (char === '\n' || char === '\r') lineComment = false;
52
+ continue;
53
+ }
54
+ if (blockComment) {
55
+ if (char === '*' && next === '/') {
56
+ blockComment = false;
57
+ index += 1;
58
+ }
59
+ continue;
60
+ }
61
+ if (quote) {
62
+ if (escaped) escaped = false;
63
+ else if (char === '\\') escaped = true;
64
+ else if (char === quote) quote = undefined;
65
+ continue;
66
+ }
67
+ if (char === '/' && next === '/') {
68
+ lineComment = true;
69
+ index += 1;
70
+ continue;
71
+ }
72
+ if (char === '/' && next === '*') {
73
+ blockComment = true;
74
+ index += 1;
75
+ continue;
76
+ }
77
+ if (char === '\'' || char === '"' || char === '`') {
78
+ quote = char;
79
+ continue;
80
+ }
81
+ if (char === '{' || char === '[' || char === '(') depth += 1;
82
+ else if (char === '}' || char === ']' || char === ')') depth -= 1;
83
+ const separator = kind === 'object' ? ',' : ';';
84
+ if (char === separator && depth === 0) {
85
+ entries.push({ text: text.slice(start, index + 1), start, end: index + 1 });
86
+ start = index + 1;
87
+ }
88
+ }
89
+ entries.push({ text: text.slice(start), start, end: text.length });
90
+ return entries.filter((entry) => entry.text.trim());
91
+ }
92
+
93
+ function splitClassMemberSegments(body) {
94
+ const entries = [];
95
+ const text = String(body ?? '');
96
+ let start = 0;
97
+ let quote;
98
+ let escaped = false;
99
+ let blockComment = false;
100
+ let lineComment = false;
101
+ let depth = 0;
102
+ for (let index = 0; index < text.length; index += 1) {
103
+ const char = text[index];
104
+ const next = text[index + 1];
105
+ if (lineComment) {
106
+ if (char === '\n' || char === '\r') lineComment = false;
107
+ continue;
108
+ }
109
+ if (blockComment) {
110
+ if (char === '*' && next === '/') {
111
+ blockComment = false;
112
+ index += 1;
113
+ }
114
+ continue;
115
+ }
116
+ if (quote) {
117
+ if (escaped) escaped = false;
118
+ else if (char === '\\') escaped = true;
119
+ else if (char === quote) quote = undefined;
120
+ continue;
121
+ }
122
+ if (char === '/' && next === '/') {
123
+ lineComment = true;
124
+ index += 1;
125
+ continue;
126
+ }
127
+ if (char === '/' && next === '*') {
128
+ blockComment = true;
129
+ index += 1;
130
+ continue;
131
+ }
132
+ if (char === '\'' || char === '"' || char === '`') {
133
+ quote = char;
134
+ continue;
135
+ }
136
+ if (char === '{' || char === '[' || char === '(') {
137
+ depth += 1;
138
+ continue;
139
+ }
140
+ if (char === '}' || char === ']' || char === ')') {
141
+ depth -= 1;
142
+ if (depth === 0 && char === '}') {
143
+ const nextIndex = nextSignificantIndex(text, index + 1);
144
+ if (text[nextIndex] !== ';') {
145
+ entries.push({ text: text.slice(start, index + 1), start, end: index + 1 });
146
+ start = index + 1;
147
+ }
148
+ }
149
+ continue;
150
+ }
151
+ if (char === ';' && depth === 0) {
152
+ entries.push({ text: text.slice(start, index + 1), start, end: index + 1 });
153
+ start = index + 1;
154
+ }
155
+ }
156
+ entries.push({ text: text.slice(start), start, end: text.length });
157
+ return entries.filter((entry) => entry.text.trim());
158
+ }
159
+
160
+ function nextSignificantIndex(text, offset) {
161
+ let index = offset;
162
+ while (index < text.length) {
163
+ if (/\s/.test(text[index])) {
164
+ index += 1;
165
+ continue;
166
+ }
167
+ if (text[index] === '/' && text[index + 1] === '/') {
168
+ index += 2;
169
+ while (index < text.length && text[index] !== '\n' && text[index] !== '\r') index += 1;
170
+ continue;
171
+ }
172
+ if (text[index] === '/' && text[index + 1] === '*') {
173
+ index += 2;
174
+ while (index < text.length && !(text[index] === '*' && text[index + 1] === '/')) index += 1;
175
+ index += 2;
176
+ continue;
177
+ }
178
+ break;
179
+ }
180
+ return index;
181
+ }
182
+
183
+ export {
184
+ parseMembers
185
+ };
@@ -0,0 +1,82 @@
1
+ import { findContainer } from './js-ts-semantic-merge-member-containers.js';
2
+ import { uniqueStrings } from './js-ts-semantic-merge-member-utils.js';
3
+
4
+ function canonicalizeSourceBodies(sourceText, preparedRegions, side) {
5
+ let output = sourceText;
6
+ const replacements = preparedRegions
7
+ .map((region) => ({ range: region[side], replacement: region.base.body }))
8
+ .sort((left, right) => right.range.bodyStart - left.range.bodyStart);
9
+ for (const { range, replacement } of replacements) {
10
+ output = `${output.slice(0, range.bodyStart)}${replacement}${output.slice(range.bodyEnd)}`;
11
+ }
12
+ return output;
13
+ }
14
+
15
+ function applyMemberAdditions(headSourceText, preparedRegions) {
16
+ return applyPreparedMemberAdditions(headSourceText, preparedRegions, ['worker']).sourceText;
17
+ }
18
+
19
+ function applyPreparedMemberAdditions(sourceText, preparedRegions, sides = ['worker']) {
20
+ let output = sourceText;
21
+ const reasonCodes = [];
22
+ const replacements = preparedRegions
23
+ .map((region) => {
24
+ const match = findContainer(sourceText, region.policy);
25
+ if (match.reasonCodes.length) {
26
+ reasonCodes.push(...match.reasonCodes.map((reason) => `target-${reason}:${region.kind}:${region.name}`));
27
+ return undefined;
28
+ }
29
+ const members = sides.flatMap((side) => region[`${side}AddedMembers`] ?? []);
30
+ if (!members.length) return undefined;
31
+ return { range: match.value, replacement: appendMembersToBody(match.value.body, members) };
32
+ })
33
+ .filter(Boolean)
34
+ .sort((left, right) => right.range.bodyStart - left.range.bodyStart);
35
+ for (const { range, replacement } of replacements) {
36
+ output = `${output.slice(0, range.bodyStart)}${replacement}${output.slice(range.bodyEnd)}`;
37
+ }
38
+ return { sourceText: output, reasonCodes: uniqueStrings(reasonCodes) };
39
+ }
40
+
41
+ function appendMembersToBody(body, members) {
42
+ if (!members.length) return body;
43
+ const indent = inferMemberIndent(body) ?? inferMemberIndent(members.map((member) => member.text).join('\n')) ?? ' ';
44
+ const addedText = members.map((member) => normalizeMemberForInsertion(member.text, indent)).join('\n');
45
+ const trailing = body.match(/\s*$/)?.[0] ?? '';
46
+ const before = body.slice(0, body.length - trailing.length);
47
+ if (!before.trim()) {
48
+ const closingIndent = trailing.includes('\n') ? trailing.slice(trailing.lastIndexOf('\n') + 1) : '';
49
+ return `\n${addedText}\n${closingIndent}`;
50
+ }
51
+ return `${before}${before.endsWith('\n') ? '' : '\n'}${addedText}${trailing.includes('\n') ? trailing : `\n${trailing}`}`;
52
+ }
53
+
54
+ function inferMemberIndent(text) {
55
+ return String(text ?? '').match(/\n([ \t]*)\S/)?.[1];
56
+ }
57
+
58
+ function normalizeMemberForInsertion(text, indent) {
59
+ const lines = String(text ?? '').replace(/\r\n/g, '\n').replace(/\r/g, '\n').split('\n');
60
+ while (lines.length && !lines[0].trim()) lines.shift();
61
+ while (lines.length && !lines[lines.length - 1].trim()) lines.pop();
62
+ const commonIndent = minimumIndent(lines);
63
+ return lines.map((line) => {
64
+ const normalized = commonIndent ? line.slice(Math.min(commonIndent, leadingWhitespace(line))) : line;
65
+ return normalized.trim() ? `${indent}${normalized}` : normalized;
66
+ }).join('\n');
67
+ }
68
+
69
+ function minimumIndent(lines) {
70
+ const indents = lines.filter((line) => line.trim()).map(leadingWhitespace);
71
+ return indents.length ? Math.min(...indents) : 0;
72
+ }
73
+
74
+ function leadingWhitespace(line) {
75
+ return line.match(/^[ \t]*/)?.[0].length ?? 0;
76
+ }
77
+
78
+ export {
79
+ applyMemberAdditions,
80
+ applyPreparedMemberAdditions,
81
+ canonicalizeSourceBodies
82
+ };
@@ -0,0 +1,18 @@
1
+ function normalizeMemberText(text) {
2
+ return String(text ?? '')
3
+ .replace(/\r\n/g, '\n')
4
+ .replace(/\r/g, '\n')
5
+ .split('\n')
6
+ .map((line) => line.trimEnd())
7
+ .join('\n')
8
+ .trim();
9
+ }
10
+
11
+ function uniqueStrings(values) {
12
+ return [...new Set(values.filter(Boolean).map(String))];
13
+ }
14
+
15
+ export {
16
+ normalizeMemberText,
17
+ uniqueStrings
18
+ };
@@ -0,0 +1,16 @@
1
+ export {
2
+ findContainer,
3
+ normalizeKind
4
+ } from './js-ts-semantic-merge-member-containers.js';
5
+ export {
6
+ parseMembers
7
+ } from './js-ts-semantic-merge-member-segments.js';
8
+ export {
9
+ applyMemberAdditions,
10
+ applyPreparedMemberAdditions,
11
+ canonicalizeSourceBodies
12
+ } from './js-ts-semantic-merge-member-source.js';
13
+ export {
14
+ normalizeMemberText,
15
+ uniqueStrings
16
+ } from './js-ts-semantic-merge-member-utils.js';
@@ -0,0 +1,24 @@
1
+ export {
2
+ JsTsSafeMergeConflictCodes,
3
+ JsTsSafeMergeGateIds,
4
+ JsTsSafeMergeStatuses,
5
+ safeMergeJsTsImportsAndDeclarations
6
+ } from './js-ts-safe-merge.js';
7
+ export {
8
+ safeMergeJsTsSource
9
+ } from './js-ts-safe-merge-composed.js';
10
+ export {
11
+ mergeJsTsSafeMemberAdditions,
12
+ safeMergeJsTsMembers
13
+ } from './js-ts-safe-member-merge.js';
14
+ export {
15
+ createJsTsSemanticMergeConflictExplanation,
16
+ createJsTsSemanticMergeGateResult,
17
+ JsTsSemanticMergeConflictClasses,
18
+ JsTsSemanticMergeGateStatuses
19
+ } from './js-ts-semantic-merge-contracts.js';
20
+ export {
21
+ createJsTsSemanticConflictSidecars,
22
+ JsTsSemanticConflictSidecarClasses,
23
+ summarizeJsTsSemanticConflictSidecars
24
+ } from './js-ts-semantic-conflict-sidecars.js';
@@ -0,0 +1,51 @@
1
+ function lightweightEffectKinds(line) {
2
+ const kinds = [];
3
+ if (/\bawait\b|import\s*\(/.test(line)) kinds.push('async');
4
+ if (hasGlobalNetworkCall(line)) kinds.push('network');
5
+ if (/\b(localStorage|sessionStorage|indexedDB|caches|cookie)\b/.test(line)) kinds.push('storage');
6
+ if (hasGlobalSchedulerCall(line)) kinds.push('scheduler');
7
+ if (/\b(console|process|Deno|Bun)\s*\./.test(line)) kinds.push('host');
8
+ if (hasBrowserEffect(line)) kinds.push('browser');
9
+ return kinds;
10
+ }
11
+
12
+ function hasGlobalNetworkCall(line) {
13
+ return hasBareCall(line, ['fetch', 'XMLHttpRequest', 'WebSocket', 'EventSource'])
14
+ || hasGlobalPropertyCall(line, ['fetch', 'XMLHttpRequest', 'WebSocket', 'EventSource']);
15
+ }
16
+
17
+ function hasGlobalSchedulerCall(line) {
18
+ const names = [
19
+ 'setTimeout',
20
+ 'setInterval',
21
+ 'clearTimeout',
22
+ 'clearInterval',
23
+ 'requestAnimationFrame',
24
+ 'cancelAnimationFrame',
25
+ 'requestIdleCallback',
26
+ 'cancelIdleCallback',
27
+ 'queueMicrotask',
28
+ 'setImmediate',
29
+ 'clearImmediate'
30
+ ];
31
+ return hasBareCall(line, names) || hasGlobalPropertyCall(line, names);
32
+ }
33
+
34
+ function hasBrowserEffect(line) {
35
+ return /\b(document|window|navigator|location|history)\s*\./.test(line)
36
+ || hasGlobalConstructorCall(line, ['Worker', 'SharedWorker']);
37
+ }
38
+
39
+ function hasBareCall(line, names) {
40
+ return names.some((name) => new RegExp(`(?:^|[^\\w$.])${name}\\s*\\(`).test(line));
41
+ }
42
+
43
+ function hasGlobalPropertyCall(line, names) {
44
+ return names.some((name) => new RegExp(`\\b(?:window|globalThis|self)\\s*\\.\\s*${name}\\s*\\(`).test(line));
45
+ }
46
+
47
+ function hasGlobalConstructorCall(line, names) {
48
+ return names.some((name) => new RegExp(`(?:^|[^\\w$.])new\\s+(?:(?:window|globalThis|self)\\s*\\.\\s*)?${name}\\s*\\(`).test(line));
49
+ }
50
+
51
+ export { lightweightEffectKinds };
@@ -41,7 +41,7 @@ export function isDependencyIdentifier(value) {
41
41
  export function dependencyScanRanges(input, declarations, lines) {
42
42
  const ordered = [...(declarations ?? [])].sort((left, right) => (left.span?.startLine ?? 0) - (right.span?.startLine ?? 0));
43
43
  return ordered
44
- .filter((declaration) => declaration?.symbolId && declaration.role !== 'import')
44
+ .filter((declaration) => declaration?.symbolId && declaration.role !== 'import' && shouldScanDependencyDeclaration(input, declaration))
45
45
  .map((declaration, index) => ({
46
46
  declaration,
47
47
  startLine: declaration.span?.startLine ?? 1,
@@ -49,6 +49,17 @@ export function dependencyScanRanges(input, declarations, lines) {
49
49
  }));
50
50
  }
51
51
 
52
+ function shouldScanDependencyDeclaration(input, declaration) {
53
+ if (!isJavaScriptLikeLanguage(input)) return true;
54
+ if (declaration.metadata?.signatureOnly || declaration.fields?.typeKind) return false;
55
+ if (/^Type(?:Alias|Method|Property|FunctionProperty)/.test(String(declaration?.kind ?? ''))) return false;
56
+ return !['interface', 'type'].includes(String(declaration?.symbolKind ?? '').toLowerCase());
57
+ }
58
+
59
+ function isJavaScriptLikeLanguage(input) {
60
+ return ['javascript', 'typescript'].includes(String(input?.language ?? '').toLowerCase());
61
+ }
62
+
52
63
  export function maskDependencyLine(input, line, state) {
53
64
  const language = String(input.language ?? '').toLowerCase();
54
65
  const text = String(line ?? '');