@shapeshift-labs/frontier-lang-compiler 0.2.102 → 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.
Files changed (134) hide show
  1. package/README.md +13 -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 +58 -0
  5. package/dist/declarations/js-ts-safe-merge.d.ts +120 -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/native-project-admission-semantic-evidence.d.ts +34 -0
  11. package/dist/declarations/native-project-admission.d.ts +6 -10
  12. package/dist/declarations/semantic-edit-replay-diagnostics.d.ts +12 -0
  13. package/dist/declarations/semantic-edit-script.d.ts +10 -4
  14. package/dist/declarations/semantic-patch-bundle-index.d.ts +45 -0
  15. package/dist/declarations/semantic-patch-bundle-overlaps.d.ts +1 -0
  16. package/dist/declarations/semantic-patch-bundle.d.ts +6 -4
  17. package/dist/declarations/semantic-sidecar-example.d.ts +18 -0
  18. package/dist/declarations/semantic-transform-identity.d.ts +3 -0
  19. package/dist/declarations/source-preservation.d.ts +72 -0
  20. package/dist/declarations/universal-capability.d.ts +4 -0
  21. package/dist/declarations/universal-conversion-artifacts.d.ts +61 -1
  22. package/dist/declarations/universal-conversion-compact-counts.d.ts +51 -0
  23. package/dist/declarations/universal-conversion-plan.d.ts +6 -1
  24. package/dist/declarations/universal-representation-coverage.d.ts +90 -0
  25. package/dist/index.d.ts +4 -0
  26. package/dist/index.js +3 -0
  27. package/dist/internal/index-impl/bidirectionalExactSourceBackprojection.js +199 -0
  28. package/dist/internal/index-impl/bidirectionalSameLanguageSourceProjection.js +112 -0
  29. package/dist/internal/index-impl/bidirectionalSourceEditProjection.js +319 -0
  30. package/dist/internal/index-impl/bidirectionalSourceEditProjectionArtifacts.js +67 -0
  31. package/dist/internal/index-impl/bidirectionalTargetChangeRecordInternals.js +17 -5
  32. package/dist/internal/index-impl/bidirectionalTargetRoundtripEvidence.js +58 -20
  33. package/dist/internal/index-impl/createBidirectionalTargetChangeRecord.js +60 -7
  34. package/dist/internal/index-impl/createLightweightNativeImport.js +1 -0
  35. package/dist/internal/index-impl/createNativeSourcePreservation.js +28 -2
  36. package/dist/internal/index-impl/createProjectImportAdmissionRecord.js +14 -2
  37. package/dist/internal/index-impl/diffNativeSymbols.js +82 -1
  38. package/dist/internal/index-impl/nativeChangeProjectionSourceMapLinks.js +2 -0
  39. package/dist/internal/index-impl/projectImportAdmissionImportEvidence.js +1 -1
  40. package/dist/internal/index-impl/projectImportAdmissionSemanticWarnings.js +178 -0
  41. package/dist/internal/index-impl/projectImportAdmissionSummaries.js +22 -3
  42. package/dist/internal/index-impl/projectSemanticEditScriptToSource.js +54 -69
  43. package/dist/internal/index-impl/replaySemanticEditLineEndings.js +34 -0
  44. package/dist/internal/index-impl/replaySemanticEditProjection.js +78 -78
  45. package/dist/internal/index-impl/semanticEditBundleAdmission.js +7 -3
  46. package/dist/internal/index-impl/semanticEditBundleIndex.js +47 -1
  47. package/dist/internal/index-impl/semanticEditExplicitSourceReplacement.js +40 -0
  48. package/dist/internal/index-impl/semanticEditImportProjection.js +53 -0
  49. package/dist/internal/index-impl/semanticEditOperationCoverage.js +33 -3
  50. package/dist/internal/index-impl/semanticEditProjectionRecord.js +108 -0
  51. package/dist/internal/index-impl/semanticEditReplayAnchors.js +63 -0
  52. package/dist/internal/index-impl/semanticEditReplayDiagnostics.js +39 -0
  53. package/dist/internal/index-impl/semanticEditReplaySourceReplacement.js +85 -0
  54. package/dist/internal/index-impl/semanticEditScripts.js +4 -0
  55. package/dist/internal/index-impl/semanticEditSourceRanges.js +32 -0
  56. package/dist/internal/index-impl/semanticIndexFromNativeDeclarations.js +1 -0
  57. package/dist/internal/index-impl/semanticPatchBundleAdmission.js +92 -9
  58. package/dist/internal/index-impl/semanticPatchBundleOverlaps.js +33 -16
  59. package/dist/internal/index-impl/semanticPatchBundleRecords.js +16 -0
  60. package/dist/internal/index-impl/semanticPatchBundleSourceRecords.js +2 -0
  61. package/dist/internal/index-impl/semanticSidecarQuality.js +111 -0
  62. package/dist/internal/index-impl/semanticSourceEditDedupe.js +69 -9
  63. package/dist/internal/index-impl/semanticTransformIdentityRecords.js +85 -9
  64. package/dist/js-ts-safe-member-merge-result.js +158 -0
  65. package/dist/js-ts-safe-member-merge.js +202 -0
  66. package/dist/js-ts-safe-merge-analyze.js +279 -0
  67. package/dist/js-ts-safe-merge-constants.js +50 -0
  68. package/dist/js-ts-safe-merge-context.js +118 -0
  69. package/dist/js-ts-safe-merge-ledger-validation.js +92 -0
  70. package/dist/js-ts-safe-merge-ledger.js +85 -0
  71. package/dist/js-ts-safe-merge-parse-declarations.js +210 -0
  72. package/dist/js-ts-safe-merge-parse-statements.js +155 -0
  73. package/dist/js-ts-safe-merge-plan.js +190 -0
  74. package/dist/js-ts-safe-merge.js +175 -0
  75. package/dist/js-ts-semantic-conflict-sidecar-constants.js +77 -0
  76. package/dist/js-ts-semantic-conflict-sidecar-detectors.js +195 -0
  77. package/dist/js-ts-semantic-conflict-sidecar-normalize.js +203 -0
  78. package/dist/js-ts-semantic-conflict-sidecar-utils.js +190 -0
  79. package/dist/js-ts-semantic-conflict-sidecars.js +81 -0
  80. package/dist/js-ts-semantic-merge-contract-helpers.js +128 -0
  81. package/dist/js-ts-semantic-merge-contracts.js +217 -0
  82. package/dist/js-ts-semantic-merge-member-containers.js +100 -0
  83. package/dist/js-ts-semantic-merge-member-keys.js +142 -0
  84. package/dist/js-ts-semantic-merge-member-segments.js +185 -0
  85. package/dist/js-ts-semantic-merge-member-source.js +64 -0
  86. package/dist/js-ts-semantic-merge-member-utils.js +18 -0
  87. package/dist/js-ts-semantic-merge-parse.js +15 -0
  88. package/dist/js-ts-semantic-merge.js +21 -0
  89. package/dist/lightweight-dependency-effects.js +51 -0
  90. package/dist/lightweight-dependency-language.js +12 -1
  91. package/dist/lightweight-dependency-relations.js +14 -27
  92. package/dist/native-region-scanner-core.js +33 -1
  93. package/dist/native-region-scanner-csharp.js +151 -0
  94. package/dist/native-region-scanner-dart.js +91 -0
  95. package/dist/native-region-scanner-dynamic.js +21 -151
  96. package/dist/native-region-scanner-functional.js +40 -13
  97. package/dist/native-region-scanner-java.js +97 -0
  98. package/dist/native-region-scanner-js-class.js +100 -0
  99. package/dist/native-region-scanner-js-helpers.js +28 -86
  100. package/dist/native-region-scanner-js-imports.js +121 -1
  101. package/dist/native-region-scanner-js-nested.js +96 -8
  102. package/dist/native-region-scanner-js-structure.js +27 -0
  103. package/dist/native-region-scanner-js-types.js +99 -0
  104. package/dist/native-region-scanner-js.js +70 -118
  105. package/dist/native-region-scanner-kotlin.js +94 -0
  106. package/dist/native-region-scanner-main.js +15 -181
  107. package/dist/native-region-scanner-php.js +80 -0
  108. package/dist/native-region-scanner-python.js +62 -0
  109. package/dist/native-region-scanner-ruby.js +72 -0
  110. package/dist/native-region-scanner-scala.js +91 -0
  111. package/dist/native-region-scanner-spans.js +74 -0
  112. package/dist/native-region-scanner-swift.js +155 -0
  113. package/dist/native-region-scanner.js +14 -10
  114. package/dist/native-source-ledger-helpers.js +195 -0
  115. package/dist/native-source-ledger.js +306 -0
  116. package/dist/native-source-preservation-scanner.js +4 -0
  117. package/dist/semantic-import-callsite-regions.js +136 -0
  118. package/dist/semantic-import-effect-regions.js +283 -0
  119. package/dist/semantic-import-regions.js +11 -2
  120. package/dist/semantic-import-sidecar-entry.js +16 -2
  121. package/dist/semantic-import-sidecar-types.d.ts +2 -0
  122. package/dist/semantic-sidecar-example.js +68 -0
  123. package/dist/universal-capability-matrix.js +23 -0
  124. package/dist/universal-conversion-artifact-query.js +79 -2
  125. package/dist/universal-conversion-artifact-semantic-edit.js +103 -0
  126. package/dist/universal-conversion-artifact-summary.js +33 -1
  127. package/dist/universal-conversion-artifacts.js +13 -48
  128. package/dist/universal-conversion-plan-scoring.js +21 -1
  129. package/dist/universal-conversion-plan-summary.js +30 -0
  130. package/dist/universal-conversion-plan.js +25 -9
  131. package/dist/universal-conversion-route-metadata.js +96 -0
  132. package/dist/universal-conversion-route-operations.js +7 -0
  133. package/dist/universal-representation-coverage.js +193 -0
  134. package/package.json +1 -1
@@ -0,0 +1,155 @@
1
+ import { upperFirst } from './native-import-utils.js';
2
+ import { nativeDeclaration, nativeImportDeclaration, sourceLines, splitParameters, splitTypeParameters } from './native-region-scanner-core.js';
3
+ import { braceBlockSpan } from './native-region-scanner-spans.js';
4
+
5
+ function scanSwift(input) {
6
+ const declarations = [];
7
+ const protocols = new Set();
8
+ const blockStack = [];
9
+ const lines = sourceLines(input.sourceText);
10
+ let braceDepth = 0;
11
+ for (const [index, { line, number }] of lines.entries()) {
12
+ const trimmed = line.trim();
13
+ const declarationLine = trimmed.replace(/^(?:@[A-Za-z_][\w.]+(?:\([^)]*\))?\s+)*/, '');
14
+ const lineStartDepth = depthAfterLeadingClosers(declarationLine, braceDepth);
15
+ while (blockStack.length && blockStack[blockStack.length - 1].bodyDepth > lineStartDepth) blockStack.pop();
16
+
17
+ let match;
18
+ if ((match = declarationLine.match(/^import\s+(?:(?:struct|class|enum|protocol|func|var)\s+)?([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)/))) {
19
+ declarations.push(nativeImportDeclaration(input, number, match[1], 'ImportDecl', 'module'));
20
+ } else if ((match = declarationLine.match(/^((?:(?:public|private(?:\([^)]*\))?|fileprivate|internal|open|final|indirect)\s+)*)(struct|class|enum|protocol|actor)\s+([A-Za-z_]\w*)/))) {
21
+ const owner = nearestSwiftOwner(blockStack);
22
+ const name = owner ? `${owner.name}.${match[3]}` : match[3];
23
+ if (match[2] === 'protocol') protocols.add(name);
24
+ const hasBody = declarationLine.includes('{');
25
+ declarations.push(nativeDeclaration(input, number, `${upperFirst(match[2])}Decl`, swiftSymbolKind(match[2]), name, {
26
+ modifiers: swiftModifiers(match[1]),
27
+ ...(owner ? { owner: owner.name } : {})
28
+ }, hasBody, spanOptions(input, lines, index, hasBody)));
29
+ if (hasBody) blockStack.push({ kind: swiftTypeStackKind(match[2]), name, bodyDepth: braceDepth + 1 });
30
+ } else if ((match = declarationLine.match(/^((?:(?:public|private(?:\([^)]*\))?|fileprivate|internal|open)\s+)*)extension\s+([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)(.*)$/))) {
31
+ const extensionFields = parseSwiftExtensionTail(match[3]);
32
+ const isProtocolExtension = protocols.has(match[2]) || /Protocol$/.test(match[2]);
33
+ const receiverKind = isProtocolExtension ? 'protocolExtension' : 'extension';
34
+ const name = `${match[2]}.${receiverKind}`;
35
+ const hasBody = declarationLine.includes('{');
36
+ declarations.push(nativeDeclaration(input, number, isProtocolExtension ? 'ProtocolExtensionDecl' : 'ExtensionDecl', 'implementation', name, {
37
+ modifiers: swiftModifiers(match[1]),
38
+ extendedType: match[2],
39
+ receiverKind,
40
+ ...extensionFields
41
+ }, hasBody, spanOptions(input, lines, index, hasBody)));
42
+ if (hasBody) blockStack.push({ kind: 'extension', name, receiverKind, receiverType: match[2], bodyDepth: braceDepth + 1 });
43
+ } else if ((match = declarationLine.match(/^((?:(?:public|private(?:\([^)]*\))?|fileprivate|internal|open|static|class|mutating|nonmutating|override|required|convenience|isolated|nonisolated)\s+)*)(?:func\s+)([A-Za-z_]\w*|`[^`]+`)(?:\s*<([^>]+)>)?\s*\(([^)]*)\)/))) {
44
+ const owner = nearestSwiftOwner(blockStack);
45
+ const target = swiftMemberTarget(owner, match[1], unquoteSwiftIdentifier(match[2]));
46
+ const hasBody = declarationLine.includes('{');
47
+ declarations.push(nativeDeclaration(input, number, 'FunctionDecl', target.owner ? 'method' : 'function', target.name, {
48
+ methodName: unquoteSwiftIdentifier(match[2]),
49
+ modifiers: swiftModifiers(match[1]),
50
+ typeParameters: splitTypeParameters(match[3]),
51
+ parameters: splitParameters(match[4]),
52
+ ...(target.owner ? { owner: target.owner, receiverKind: target.receiverKind, receiverType: target.receiverType } : {})
53
+ }, hasBody, memberSpanOptions(input, lines, index, hasBody, target, unquoteSwiftIdentifier(match[2]), match[1])));
54
+ if (hasBody) blockStack.push({ kind: 'method', name: target.name, bodyDepth: braceDepth + 1 });
55
+ } else if ((match = declarationLine.match(/^((?:(?:public|private(?:\([^)]*\))?|fileprivate|internal|open|static|class|final|lazy|weak|unowned|override|required|nonisolated)\s+)*)(let|var)\s+([A-Za-z_]\w*)\b(?::\s*([^={]+))?/))) {
56
+ const owner = nearestSwiftOwner(blockStack);
57
+ const target = swiftMemberTarget(owner, match[1], match[3]);
58
+ const hasBody = declarationLine.includes('{') || declarationLine.includes('=>');
59
+ declarations.push(nativeDeclaration(input, number, 'PropertyDecl', 'property', target.name, {
60
+ binding: match[2],
61
+ modifiers: swiftModifiers(match[1]),
62
+ valueType: match[4]?.trim(),
63
+ ...(target.owner ? { owner: target.owner, receiverKind: target.receiverKind, receiverType: target.receiverType } : {})
64
+ }, hasBody, memberSpanOptions(input, lines, index, hasBody, target, match[3], match[1])));
65
+ } else if ((match = declarationLine.match(/^(?:(?:public|private(?:\([^)]*\))?|fileprivate|internal|open)\s+)*typealias\s+([A-Za-z_]\w*)\b(?:\s*=\s*(.+))?/))) {
66
+ const owner = nearestSwiftOwner(blockStack);
67
+ const name = owner ? `${owner.name}.${match[1]}` : match[1];
68
+ declarations.push(nativeDeclaration(input, number, 'TypealiasDecl', 'type', name, {
69
+ target: match[2]?.trim(),
70
+ ...(owner ? { owner: owner.name } : {})
71
+ }, false));
72
+ }
73
+ braceDepth = Math.max(0, braceDepth + braceDelta(line));
74
+ }
75
+ return declarations;
76
+ }
77
+
78
+ function spanOptions(input, lines, index, hasBraceBody) {
79
+ return hasBraceBody ? { span: braceBlockSpan(input, lines, index) } : {};
80
+ }
81
+
82
+ function memberSpanOptions(input, lines, index, hasBody, target, methodName, modifiers) {
83
+ return {
84
+ ...spanOptions(input, lines, index, hasBody),
85
+ metadata: {
86
+ methodName,
87
+ modifiers: swiftModifiers(modifiers),
88
+ ...(target.owner ? { owner: target.owner, receiverKind: target.receiverKind, receiverType: target.receiverType } : {})
89
+ }
90
+ };
91
+ }
92
+
93
+ function depthAfterLeadingClosers(trimmed, depth) {
94
+ const closers = String(trimmed).match(/^}+/)?.[0].length ?? 0;
95
+ return Math.max(0, depth - closers);
96
+ }
97
+
98
+ function nearestSwiftOwner(blockStack) {
99
+ for (let index = blockStack.length - 1; index >= 0; index -= 1) {
100
+ if (blockStack[index].kind === 'method') return undefined;
101
+ if (['actor', 'class', 'enum', 'extension', 'protocol', 'struct'].includes(blockStack[index].kind)) return blockStack[index];
102
+ }
103
+ return undefined;
104
+ }
105
+
106
+ function swiftMemberTarget(owner, modifiers, memberName) {
107
+ if (!owner) return { name: memberName };
108
+ if (owner.kind === 'extension') {
109
+ if (/\b(?:static|class)\b/.test(modifiers)) {
110
+ return { name: `${owner.name}.static.${memberName}`, owner: owner.name, receiverKind: 'static', receiverType: owner.receiverType };
111
+ }
112
+ return { name: `${owner.name}.${memberName}`, owner: owner.name, receiverKind: owner.receiverKind, receiverType: owner.receiverType };
113
+ }
114
+ const receiverKind = /\b(?:static|class)\b/.test(modifiers) ? 'static' : 'member';
115
+ return { name: receiverKind === 'static' ? `${owner.name}.static.${memberName}` : `${owner.name}.${memberName}`, owner: owner.name, receiverKind };
116
+ }
117
+
118
+ function swiftModifiers(raw) {
119
+ return splitParameters(String(raw ?? '').trim().replace(/\s+/g, ','));
120
+ }
121
+
122
+ function swiftTypeStackKind(kind) {
123
+ return String(kind).replace(/\s+/g, ' ');
124
+ }
125
+
126
+ function braceDelta(source) {
127
+ return [...String(source ?? '')].reduce((delta, char) => delta + (char === '{' ? 1 : char === '}' ? -1 : 0), 0);
128
+ }
129
+
130
+ function parseSwiftExtensionTail(rawTail) {
131
+ let tail = String(rawTail ?? '').split('{')[0].trim();
132
+ const fields = {};
133
+ const whereMatch = tail.match(/\bwhere\b(.+)$/);
134
+ if (whereMatch) {
135
+ fields.constraints = whereMatch[1].trim();
136
+ tail = tail.slice(0, whereMatch.index).trim();
137
+ }
138
+ if (tail.startsWith(':')) {
139
+ fields.conformances = tail.slice(1).split(',').map((part) => part.trim()).filter(Boolean);
140
+ }
141
+ return fields;
142
+ }
143
+
144
+ function unquoteSwiftIdentifier(identifier) {
145
+ return String(identifier).replace(/^`|`$/g, '');
146
+ }
147
+
148
+ function swiftSymbolKind(kind) {
149
+ if (kind === 'protocol') return 'protocol';
150
+ if (kind === 'extension') return 'implementation';
151
+ if (kind === 'struct' || kind === 'enum' || kind === 'actor') return 'type';
152
+ return 'class';
153
+ }
154
+
155
+ export { scanSwift };
@@ -1,24 +1,24 @@
1
1
  import { scanJavaScriptLike } from './native-region-scanner-js.js';
2
2
  import {
3
3
  scanCLike,
4
- scanCSharp,
5
4
  scanGo,
6
- scanJava,
7
- scanPython,
8
- scanRust,
9
- scanSwift
5
+ scanRust
10
6
  } from './native-region-scanner-main.js';
7
+ import { scanJava } from './native-region-scanner-java.js';
8
+ import { scanSwift } from './native-region-scanner-swift.js';
9
+ import { scanCSharp } from './native-region-scanner-csharp.js';
10
+ import { scanPython } from './native-region-scanner-python.js';
11
+ import { scanPhp } from './native-region-scanner-php.js';
12
+ import { scanKotlin } from './native-region-scanner-kotlin.js';
13
+ import { scanScala } from './native-region-scanner-scala.js';
14
+ import { scanDart } from './native-region-scanner-dart.js';
11
15
  import {
12
- scanDart,
13
- scanKotlin,
14
16
  scanLua,
15
- scanPhp,
16
- scanRuby,
17
- scanScala,
18
17
  scanShell,
19
18
  scanSql,
20
19
  scanZig
21
20
  } from './native-region-scanner-dynamic.js';
21
+ import { scanRuby } from './native-region-scanner-ruby.js';
22
22
  import {
23
23
  scanElixir,
24
24
  scanErlang,
@@ -33,6 +33,10 @@ export {
33
33
  scanPreservedSourceDirectives,
34
34
  scanPreservedSourceTokens
35
35
  } from './native-source-preservation-scanner.js';
36
+ export {
37
+ isJavaScriptTypeScriptSource,
38
+ scanJavaScriptTypeScriptSourceLedger
39
+ } from './native-source-ledger.js';
36
40
 
37
41
  function scanNativeDeclarations(input) {
38
42
  const language = normalizeNativeLanguageId(input.language) || String(input.language).toLowerCase();
@@ -0,0 +1,195 @@
1
+ const regexStartKeywords = new Set(['case', 'delete', 'else', 'in', 'instanceof', 'new', 'return', 'throw', 'typeof', 'void', 'yield']);
2
+
3
+ export function isSourceMapComment(text) {
4
+ return /^(?:\/\/|\/\*)[#@]\s*sourceMappingURL=/.test(String(text).trim());
5
+ }
6
+
7
+ export function readToLineEnd(text, start) {
8
+ let index = start;
9
+ while (index < text.length && text[index] !== '\n' && text[index] !== '\r') index += 1;
10
+ return index;
11
+ }
12
+
13
+ export function readBlockCommentEnd(text, start) {
14
+ const end = text.indexOf('*/', start + 2);
15
+ return end === -1 ? text.length : end + 2;
16
+ }
17
+
18
+ export function readQuotedEnd(text, start, quote) {
19
+ let escaped = false;
20
+ for (let index = start + 1; index < text.length; index += 1) {
21
+ const char = text[index];
22
+ if (escaped) {
23
+ escaped = false;
24
+ } else if (char === '\\') {
25
+ escaped = true;
26
+ } else if (char === quote) {
27
+ return index + 1;
28
+ } else if (char === '\n' || char === '\r') {
29
+ return index;
30
+ }
31
+ }
32
+ return text.length;
33
+ }
34
+
35
+ export function readTemplateEnd(text, start) {
36
+ let escaped = false;
37
+ for (let index = start + 1; index < text.length; index += 1) {
38
+ const char = text[index];
39
+ if (escaped) escaped = false;
40
+ else if (char === '\\') escaped = true;
41
+ else if (char === '`') return index + 1;
42
+ }
43
+ return text.length;
44
+ }
45
+
46
+ export function readRegexEnd(text, start) {
47
+ let escaped = false;
48
+ let inClass = false;
49
+ for (let index = start + 1; index < text.length; index += 1) {
50
+ const char = text[index];
51
+ if (char === '\n' || char === '\r') return undefined;
52
+ if (escaped) escaped = false;
53
+ else if (char === '\\') escaped = true;
54
+ else if (char === '[') inClass = true;
55
+ else if (char === ']') inClass = false;
56
+ else if (char === '/' && !inClass) return readWhile(text, index + 1, (value) => /[A-Za-z]/.test(value));
57
+ }
58
+ return undefined;
59
+ }
60
+
61
+ export function readJsxRegionEnd(text, start) {
62
+ let index = start;
63
+ let depth = 0;
64
+ while (index < text.length) {
65
+ if (text[index] === '{') {
66
+ index = readBalancedBraceEnd(text, index);
67
+ continue;
68
+ }
69
+ if (text[index] !== '<') {
70
+ index += 1;
71
+ continue;
72
+ }
73
+ const tag = readJsxTag(text, index);
74
+ if (!tag) return index > start ? index : start + 1;
75
+ if (tag.close) depth -= 1;
76
+ else if (!tag.selfClosing) depth += 1;
77
+ index = tag.end;
78
+ if (depth <= 0) return index;
79
+ }
80
+ return text.length;
81
+ }
82
+
83
+ export function readStatementEnd(text, start) {
84
+ const end = readToLineEnd(text, start);
85
+ const semicolon = text.indexOf(';', start);
86
+ return semicolon !== -1 && semicolon < end ? semicolon + 1 : end;
87
+ }
88
+
89
+ export function readWhile(text, start, predicate) {
90
+ let index = start;
91
+ while (index < text.length && predicate(text[index])) index += 1;
92
+ return index;
93
+ }
94
+
95
+ export function endPosition(start, text) {
96
+ let line = start.line;
97
+ let column = start.column;
98
+ for (let index = 0; index < text.length; index += 1) {
99
+ if (text[index] === '\r') {
100
+ if (text[index + 1] === '\n') index += 1;
101
+ line += 1;
102
+ column = 1;
103
+ } else if (text[index] === '\n') {
104
+ line += 1;
105
+ column = 1;
106
+ } else {
107
+ column += 1;
108
+ }
109
+ }
110
+ return { offset: start.offset + text.length, line, column };
111
+ }
112
+
113
+ export function looksLikeJsxStart(text, offset, previous) {
114
+ if (text[offset] !== '<' || !(isIdentifierStart(text[offset + 1]) || text[offset + 1] === '>')) return false;
115
+ if (!previous) return true;
116
+ if (previous.kind === 'operator' || ['(', '[', '{', ',', ':', '?', '=>'].includes(previous.text)) return true;
117
+ return previous.kind === 'keyword' && ['return', 'case', 'throw'].includes(previous.text);
118
+ }
119
+
120
+ export function mayStartRegex(previous) {
121
+ if (!previous) return true;
122
+ if (previous.kind === 'operator') return true;
123
+ if (previous.kind === 'keyword') return regexStartKeywords.has(previous.text);
124
+ return ['(', '[', '{', ',', ';', ':', '?'].includes(previous.text);
125
+ }
126
+
127
+ export function braceMetadata(char, stack, tokenId) {
128
+ const kind = char === '{' || char === '}' ? 'curly' : char === '(' || char === ')' ? 'paren' : 'bracket';
129
+ if (char === '{' || char === '(' || char === '[') {
130
+ stack.push({ char, tokenId, kind });
131
+ return { braceKind: kind, side: 'open', depth: stack.length };
132
+ }
133
+ const open = char === '}' ? '{' : char === ')' ? '(' : '[';
134
+ const matchIndex = stack.map((entry) => entry.char).lastIndexOf(open);
135
+ const matched = matchIndex >= 0 ? stack.splice(matchIndex, 1)[0] : undefined;
136
+ return { braceKind: kind, side: 'close', depth: stack.length + 1, openTokenId: matched?.tokenId };
137
+ }
138
+
139
+ export function isBrace(char) {
140
+ return char === '{' || char === '}' || char === '(' || char === ')' || char === '[' || char === ']';
141
+ }
142
+
143
+ export function isHorizontalWhitespace(char) {
144
+ return char === ' ' || char === '\t' || char === '\v' || char === '\f';
145
+ }
146
+
147
+ export function isIdentifierStart(char) {
148
+ return /[A-Za-z_$]/.test(char ?? '');
149
+ }
150
+
151
+ export function isIdentifierPart(char) {
152
+ return /[A-Za-z0-9_$]/.test(char ?? '');
153
+ }
154
+
155
+ function readJsxTag(text, start) {
156
+ if (text[start + 1] === '!' && text.startsWith('<!--', start)) {
157
+ const end = text.indexOf('-->', start + 4);
158
+ return { end: end === -1 ? text.length : end + 3, selfClosing: true, close: false };
159
+ }
160
+ let index = start + 1;
161
+ const close = text[index] === '/';
162
+ if (close) index += 1;
163
+ if (text[index] === '>') return { end: index + 1, selfClosing: false, close };
164
+ if (!isIdentifierStart(text[index])) return undefined;
165
+ let quote = undefined;
166
+ for (; index < text.length; index += 1) {
167
+ const char = text[index];
168
+ if (quote) {
169
+ if (char === '\\') index += 1;
170
+ else if (char === quote) quote = undefined;
171
+ } else if (char === '\'' || char === '"') {
172
+ quote = char;
173
+ } else if (char === '>') {
174
+ return { end: index + 1, selfClosing: text[index - 1] === '/', close };
175
+ }
176
+ }
177
+ return { end: text.length, selfClosing: true, close };
178
+ }
179
+
180
+ function readBalancedBraceEnd(text, start) {
181
+ let depth = 1;
182
+ for (let index = start + 1; index < text.length; index += 1) {
183
+ const char = text[index];
184
+ if (char === '\'' || char === '"') index = readQuotedEnd(text, index, char) - 1;
185
+ else if (char === '`') index = readTemplateEnd(text, index) - 1;
186
+ else if (char === '/' && text[index + 1] === '/') index = readToLineEnd(text, index) - 1;
187
+ else if (char === '/' && text[index + 1] === '*') index = readBlockCommentEnd(text, index) - 1;
188
+ else if (char === '{') depth += 1;
189
+ else if (char === '}') {
190
+ depth -= 1;
191
+ if (depth === 0) return index + 1;
192
+ }
193
+ }
194
+ return text.length;
195
+ }