@shapeshift-labs/frontier-lang-compiler 0.2.150 → 0.2.151

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 (276) hide show
  1. package/README.md +315 -9
  2. package/bench/real-repo-corpus-checkout-identity.mjs +134 -0
  3. package/bench/real-repo-corpus-checkout-proof.mjs +263 -0
  4. package/bench/real-repo-corpus-command-execution.mjs +314 -0
  5. package/bench/real-repo-corpus-evidence.mjs +165 -0
  6. package/bench/real-repo-corpus-suite.mjs +273 -0
  7. package/bench/smoke.mjs +109 -7
  8. package/dist/declarations/import-adapter-core.d.ts +4 -3
  9. package/dist/declarations/import-adapter-options-native.d.ts +21 -0
  10. package/dist/declarations/js-ts-project-merge-admission-routes.d.ts +35 -0
  11. package/dist/declarations/js-ts-project-merge-commonjs-interop.d.ts +29 -0
  12. package/dist/declarations/js-ts-project-merge-confidence.d.ts +64 -0
  13. package/dist/declarations/js-ts-project-merge-declaration-emit-parity.d.ts +37 -0
  14. package/dist/declarations/js-ts-project-merge-declarations.d.ts +65 -0
  15. package/dist/declarations/js-ts-project-merge-diagnostics.d.ts +97 -0
  16. package/dist/declarations/js-ts-project-merge-global-augmentation.d.ts +30 -0
  17. package/dist/declarations/js-ts-project-merge-jsx-render-branch.d.ts +48 -0
  18. package/dist/declarations/js-ts-project-merge-proof-levels.d.ts +109 -0
  19. package/dist/declarations/js-ts-project-merge-quality-gates.d.ts +38 -0
  20. package/dist/declarations/js-ts-project-merge-semantic-equivalence-proof.d.ts +45 -0
  21. package/dist/declarations/js-ts-project-merge-tsconfig.d.ts +43 -0
  22. package/dist/declarations/js-ts-safe-merge.d.ts +47 -0
  23. package/dist/declarations/js-ts-safe-project-merge.d.ts +120 -38
  24. package/dist/declarations/native-project-compiler-assignability-oracle.d.ts +41 -0
  25. package/dist/declarations/native-project-compiler-callable-signatures.d.ts +31 -0
  26. package/dist/declarations/native-project-compiler-class-member-runtime-proof.d.ts +87 -0
  27. package/dist/declarations/native-project-compiler-composite-types.d.ts +23 -0
  28. package/dist/declarations/native-project-compiler-enum-proof.d.ts +58 -0
  29. package/dist/declarations/native-project-compiler-index-signature.d.ts +7 -0
  30. package/dist/declarations/native-project-compiler-public-api-source-binding.d.ts +8 -0
  31. package/dist/declarations/native-project-compiler-scope.d.ts +37 -0
  32. package/dist/declarations/native-project-compiler-type-reference-targets.d.ts +38 -0
  33. package/dist/declarations/native-project-css-modules.d.ts +90 -0
  34. package/dist/declarations/native-project-decorator-metadata.d.ts +126 -0
  35. package/dist/declarations/native-project-jsx-graph.d.ts +313 -0
  36. package/dist/declarations/native-project-module-declarations.d.ts +52 -0
  37. package/dist/declarations/native-project-module-resolution.d.ts +76 -1
  38. package/dist/declarations/native-project-runtime-effect-target.d.ts +29 -0
  39. package/dist/declarations/native-project-runtime-executable-effect-evidence.d.ts +107 -0
  40. package/dist/declarations/native-project-runtime-mutation-target.d.ts +33 -0
  41. package/dist/declarations/native-project-runtime-promise-chain.d.ts +30 -0
  42. package/dist/declarations/native-project-runtime-promise-combinator.d.ts +22 -0
  43. package/dist/declarations/native-project-runtime-reachability.d.ts +30 -0
  44. package/dist/declarations/native-project-runtime-resource-management.d.ts +27 -0
  45. package/dist/declarations/native-project-runtime-yield-delegation.d.ts +10 -0
  46. package/dist/declarations/native-project-scope-template-reference.d.ts +13 -0
  47. package/dist/declarations/native-project-source-evidence.d.ts +8 -0
  48. package/dist/declarations/native-project.d.ts +40 -39
  49. package/dist/declarations/semantic-edit-script.d.ts +10 -8
  50. package/dist/declarations/semantic-graph-layers.d.ts +79 -0
  51. package/dist/declarations/semantic-sidecar.d.ts +3 -2
  52. package/dist/declarations/semantic-structural-diff.d.ts +94 -0
  53. package/dist/declarations/source-preservation.d.ts +32 -1
  54. package/dist/declarations/target-adapters.d.ts +22 -2
  55. package/dist/index.d.ts +31 -0
  56. package/dist/index.js +5 -0
  57. package/dist/internal/index-impl/compileNativeSource.js +53 -5
  58. package/dist/internal/index-impl/createLightweightNativeImport.js +58 -4
  59. package/dist/internal/index-impl/createNativeImportFromSyntaxAst.js +17 -1
  60. package/dist/internal/index-impl/createNativeImportFromTypeScriptAst.js +28 -4
  61. package/dist/internal/index-impl/createNativeProjectImportResult.js +31 -27
  62. package/dist/internal/index-impl/createNativeProjectModuleResolutionFromPackageManifests.js +145 -0
  63. package/dist/internal/index-impl/createNativeSourcePreservation.js +34 -7
  64. package/dist/internal/index-impl/createSemanticImportSidecar.js +27 -1
  65. package/dist/internal/index-impl/createTypeScriptCompilerNativeImporterAdapter.js +16 -5
  66. package/dist/internal/index-impl/dynamicImportExpressionMetadata.js +80 -0
  67. package/dist/internal/index-impl/importMetaUrlDependencyMetadata.js +176 -0
  68. package/dist/internal/index-impl/importNativeSource.js +2 -3
  69. package/dist/internal/index-impl/moduleImportAttributeMetadata.js +232 -0
  70. package/dist/internal/index-impl/projectSemanticEditScriptToSource.js +8 -1
  71. package/dist/internal/index-impl/projectSymbolGraphClassStaticBlocks.js +148 -0
  72. package/dist/internal/index-impl/projectSymbolGraphCompilerAdvancedTypeMetadata.js +45 -0
  73. package/dist/internal/index-impl/projectSymbolGraphCompilerCallableSignatureEquivalence.js +107 -0
  74. package/dist/internal/index-impl/projectSymbolGraphCompilerClassPrivateAccessorRuntimeProof.js +280 -0
  75. package/dist/internal/index-impl/projectSymbolGraphCompilerClassShapeEquivalence.js +103 -0
  76. package/dist/internal/index-impl/projectSymbolGraphCompilerConditionalTypeEquivalence.js +242 -0
  77. package/dist/internal/index-impl/projectSymbolGraphCompilerDecoratorRuntimeProof.js +197 -0
  78. package/dist/internal/index-impl/projectSymbolGraphCompilerEnumEquivalence.js +188 -0
  79. package/dist/internal/index-impl/projectSymbolGraphCompilerFacts.js +244 -0
  80. package/dist/internal/index-impl/projectSymbolGraphCompilerIndexSignatureEquivalence.js +58 -0
  81. package/dist/internal/index-impl/projectSymbolGraphCompilerMetadata.js +168 -0
  82. package/dist/internal/index-impl/projectSymbolGraphCompilerTypeEquivalence.js +199 -0
  83. package/dist/internal/index-impl/projectSymbolGraphCompilerTypeEquivalenceProof.js +204 -0
  84. package/dist/internal/index-impl/projectSymbolGraphCompilerTypeReferenceTargetEquivalence.js +99 -0
  85. package/dist/internal/index-impl/projectSymbolGraphCssModuleRecords.js +264 -0
  86. package/dist/internal/index-impl/projectSymbolGraphCssModuleScanners.js +242 -0
  87. package/dist/internal/index-impl/projectSymbolGraphCssModuleUtils.js +152 -0
  88. package/dist/internal/index-impl/projectSymbolGraphCssModules.js +82 -0
  89. package/dist/internal/index-impl/projectSymbolGraphJsxComponentImports.js +170 -0
  90. package/dist/internal/index-impl/projectSymbolGraphJsxComponentProviderLookup.js +167 -0
  91. package/dist/internal/index-impl/projectSymbolGraphJsxComponentWrappers.js +150 -0
  92. package/dist/internal/index-impl/projectSymbolGraphJsxContextTargets.js +71 -0
  93. package/dist/internal/index-impl/projectSymbolGraphJsxContextValues.js +212 -0
  94. package/dist/internal/index-impl/projectSymbolGraphJsxEventHandlers.js +172 -0
  95. package/dist/internal/index-impl/projectSymbolGraphJsxHookEffects.js +124 -0
  96. package/dist/internal/index-impl/projectSymbolGraphJsxHooks.js +281 -0
  97. package/dist/internal/index-impl/projectSymbolGraphJsxMemberComponents.js +139 -0
  98. package/dist/internal/index-impl/projectSymbolGraphJsxPropFlows.js +320 -0
  99. package/dist/internal/index-impl/projectSymbolGraphJsxPropValues.js +145 -0
  100. package/dist/internal/index-impl/projectSymbolGraphJsxProviderFlows.js +133 -0
  101. package/dist/internal/index-impl/projectSymbolGraphJsxRecords.js +315 -0
  102. package/dist/internal/index-impl/projectSymbolGraphJsxRenderCollections.js +155 -0
  103. package/dist/internal/index-impl/projectSymbolGraphJsxRenderReturns.js +291 -0
  104. package/dist/internal/index-impl/projectSymbolGraphJsxRenderRisk.js +279 -0
  105. package/dist/internal/index-impl/projectSymbolGraphModuleDeclarationShapes.js +138 -0
  106. package/dist/internal/index-impl/projectSymbolGraphModuleResolution.js +89 -87
  107. package/dist/internal/index-impl/projectSymbolGraphPackageConditions.js +314 -0
  108. package/dist/internal/index-impl/projectSymbolGraphReExportImportTargets.js +43 -0
  109. package/dist/internal/index-impl/projectSymbolGraphReExports.js +55 -1
  110. package/dist/internal/index-impl/projectSymbolGraphRuntimeRegions.js +108 -0
  111. package/dist/internal/index-impl/projectSymbolGraphScopeUseDefAliases.js +307 -0
  112. package/dist/internal/index-impl/projectSymbolGraphScopeUseDefLexical.js +320 -0
  113. package/dist/internal/index-impl/projectSymbolGraphScopeUseDefOwners.js +50 -0
  114. package/dist/internal/index-impl/projectSymbolGraphScopeUseDefRecordBuilders.js +112 -0
  115. package/dist/internal/index-impl/projectSymbolGraphScopeUseDefRecords.js +238 -0
  116. package/dist/internal/index-impl/projectSymbolGraphScopeUseDefStructural.js +104 -0
  117. package/dist/internal/index-impl/projectSymbolGraphScopeUseDefStructuralNormalize.js +242 -0
  118. package/dist/internal/index-impl/projectSymbolGraphScopeUseDefUseHashes.js +107 -0
  119. package/dist/internal/index-impl/projectSymbolGraphSourceMapGeneratedBoundary.js +111 -0
  120. package/dist/internal/index-impl/projectSymbolGraphSourceRecords.js +268 -0
  121. package/dist/internal/index-impl/projectSymbolGraphSourceRecordsOwnership.js +309 -0
  122. package/dist/internal/index-impl/replaySemanticEditProjection.js +53 -39
  123. package/dist/internal/index-impl/runtimeOrderEvidenceBinding.js +151 -0
  124. package/dist/internal/index-impl/runtimeOrderProofSurfaces.js +253 -0
  125. package/dist/internal/index-impl/semanticEditCallsiteArgumentMerge.js +319 -0
  126. package/dist/internal/index-impl/semanticEditExplicitSourceReplacement.js +7 -2
  127. package/dist/internal/index-impl/semanticEditProjectionRecord.js +8 -0
  128. package/dist/internal/index-impl/semanticEditReplayDiagnostics.js +7 -2
  129. package/dist/internal/index-impl/semanticEditReplayOutputBinding.js +61 -0
  130. package/dist/internal/index-impl/semanticEditReplayRerunRoute.js +27 -0
  131. package/dist/internal/index-impl/semanticEditReplaySourceReplacement.js +6 -1
  132. package/dist/internal/index-impl/semanticEditRuntimeOrderReasons.js +320 -0
  133. package/dist/internal/index-impl/semanticEditScriptClassification.js +90 -5
  134. package/dist/internal/index-impl/semanticEditScripts.js +42 -5
  135. package/dist/internal/index-impl/semanticEditTypeSyntaxReasons.js +134 -0
  136. package/dist/internal/index-impl/semanticIndexFromNativeDeclarations.js +11 -5
  137. package/dist/internal/index-impl/semanticStructuralDiffRecords.js +150 -0
  138. package/dist/internal/index-impl/sourceMapGeneratedBoundaryGate.js +185 -0
  139. package/dist/internal/index-impl/staticMemberLiteral.js +31 -0
  140. package/dist/internal/index-impl/staticOptionalMemberReference.js +22 -0
  141. package/dist/internal/index-impl/syntaxAstSourcePreservation.js +273 -0
  142. package/dist/internal/index-impl/syntaxCommonJsModuleDeclarationEntries.js +297 -0
  143. package/dist/internal/index-impl/syntaxModuleDeclarationEntries.js +56 -132
  144. package/dist/internal/index-impl/syntaxModuleEntryRecords.js +160 -0
  145. package/dist/internal/index-impl/typeScriptCompilerAdvancedTypeShapes.js +160 -0
  146. package/dist/internal/index-impl/typeScriptCompilerAssignabilityOracle.js +97 -0
  147. package/dist/internal/index-impl/typeScriptCompilerClassApi.js +238 -0
  148. package/dist/internal/index-impl/typeScriptCompilerDecoratorMetadata.js +290 -0
  149. package/dist/internal/index-impl/typeScriptCompilerEnumShape.js +279 -0
  150. package/dist/internal/index-impl/typeScriptCompilerFacts.js +294 -0
  151. package/dist/internal/index-impl/typeScriptCompilerInferenceSyntax.js +170 -0
  152. package/dist/internal/index-impl/typeScriptCompilerReferenceGraph.js +186 -0
  153. package/dist/internal/index-impl/typeScriptCompilerSymbolIdentity.js +294 -0
  154. package/dist/internal/index-impl/typeScriptCompilerTypeReferenceTargets.js +142 -0
  155. package/dist/internal/index-impl/typeScriptDeclaration.js +10 -38
  156. package/dist/internal/index-impl/typeScriptModuleDeclarationEntries.js +52 -15
  157. package/dist/internal/index-impl/typeScriptSourceFilePreservation.js +296 -0
  158. package/dist/js-ts-safe-member-class-invariants.js +247 -0
  159. package/dist/js-ts-safe-member-merge-result.js +23 -3
  160. package/dist/js-ts-safe-member-merge.js +28 -4
  161. package/dist/js-ts-safe-merge-binding-patterns.js +170 -0
  162. package/dist/js-ts-safe-merge-jsx-attribute-fallback.js +151 -157
  163. package/dist/js-ts-safe-merge-jsx-attribute-parser.js +277 -0
  164. package/dist/js-ts-safe-merge-jsx-child-expression-fallback.js +161 -0
  165. package/dist/js-ts-safe-merge-jsx-child-expression-merge.js +319 -0
  166. package/dist/js-ts-safe-merge-jsx-child-expression-parser.js +300 -0
  167. package/dist/js-ts-safe-merge-parse-declarations.js +46 -2
  168. package/dist/js-ts-safe-merge-parse-statements.js +8 -0
  169. package/dist/js-ts-safe-merge-semantic-edit-fallback.js +13 -5
  170. package/dist/js-ts-safe-merge-source-shape-fallbacks.js +3 -1
  171. package/dist/js-ts-safe-merge-top-level-rename-fallback.js +31 -5
  172. package/dist/js-ts-safe-merge-top-level-rename-result.js +7 -2
  173. package/dist/js-ts-safe-merge-variable-declarator-fallback.js +124 -6
  174. package/dist/js-ts-safe-merge-variable-declarator-parser.js +34 -4
  175. package/dist/js-ts-safe-merge.js +136 -0
  176. package/dist/js-ts-safe-project-merge-admission-routes.js +216 -0
  177. package/dist/js-ts-safe-project-merge-admission.js +161 -0
  178. package/dist/js-ts-safe-project-merge-ambient.js +110 -0
  179. package/dist/js-ts-safe-project-merge-core.js +85 -0
  180. package/dist/js-ts-safe-project-merge-css-module-conflicts.js +60 -0
  181. package/dist/js-ts-safe-project-merge-declaration-emit-parity.js +186 -0
  182. package/dist/js-ts-safe-project-merge-declarations.js +227 -0
  183. package/dist/js-ts-safe-project-merge-diagnostics-metadata.js +42 -0
  184. package/dist/js-ts-safe-project-merge-diagnostics-ts.js +73 -0
  185. package/dist/js-ts-safe-project-merge-diagnostics.js +283 -0
  186. package/dist/js-ts-safe-project-merge-evidence-routing.js +38 -0
  187. package/dist/js-ts-safe-project-merge-files.js +70 -0
  188. package/dist/js-ts-safe-project-merge-global-augmentation-compatibility.js +99 -0
  189. package/dist/js-ts-safe-project-merge-graph-conflicts.js +90 -2
  190. package/dist/js-ts-safe-project-merge-graph-delta-commonjs-interop.js +108 -0
  191. package/dist/js-ts-safe-project-merge-graph-delta-compiler-conflicts.js +179 -0
  192. package/dist/js-ts-safe-project-merge-graph-delta-compiler-details.js +189 -0
  193. package/dist/js-ts-safe-project-merge-graph-delta-conflicts.js +51 -184
  194. package/dist/js-ts-safe-project-merge-graph-delta-identity-conflicts.js +202 -0
  195. package/dist/js-ts-safe-project-merge-graph-delta-inference-syntax.js +80 -0
  196. package/dist/js-ts-safe-project-merge-graph-delta-module-declarations.js +155 -0
  197. package/dist/js-ts-safe-project-merge-graph-limits.js +16 -1
  198. package/dist/js-ts-safe-project-merge-graph.js +37 -5
  199. package/dist/js-ts-safe-project-merge-import-removal.js +292 -0
  200. package/dist/js-ts-safe-project-merge-jsx-graph-conflict-details.js +235 -0
  201. package/dist/js-ts-safe-project-merge-jsx-graph-conflicts.js +173 -0
  202. package/dist/js-ts-safe-project-merge-jsx-prop-contracts.js +86 -0
  203. package/dist/js-ts-safe-project-merge-jsx-render-branch-proof.js +189 -0
  204. package/dist/js-ts-safe-project-merge-missing-evidence.js +310 -0
  205. package/dist/js-ts-safe-project-merge-move-rename.js +209 -0
  206. package/dist/js-ts-safe-project-merge-proof-conflicts.js +44 -0
  207. package/dist/js-ts-safe-project-merge-proof-levels.js +320 -0
  208. package/dist/js-ts-safe-project-merge-quality-gates.js +140 -0
  209. package/dist/js-ts-safe-project-merge-routing-calibration.js +125 -0
  210. package/dist/js-ts-safe-project-merge-runtime-region-conflicts.js +156 -0
  211. package/dist/js-ts-safe-project-merge-scope-use-def-conflicts.js +292 -0
  212. package/dist/js-ts-safe-project-merge-semantic-equivalence-proof.js +175 -0
  213. package/dist/js-ts-safe-project-merge-semantic-replay-proof.js +311 -0
  214. package/dist/js-ts-safe-project-merge-semantic-replay-routes.js +179 -0
  215. package/dist/js-ts-safe-project-merge-source-span-conflicts.js +310 -0
  216. package/dist/js-ts-safe-project-merge-source-span-roundtrip-proof.js +172 -0
  217. package/dist/js-ts-safe-project-merge-split-merge-admission.js +96 -0
  218. package/dist/js-ts-safe-project-merge-split-merge-records.js +320 -0
  219. package/dist/js-ts-safe-project-merge-split-merge-shapes.js +234 -0
  220. package/dist/js-ts-safe-project-merge-split-merge.js +218 -0
  221. package/dist/js-ts-safe-project-merge-summary.js +320 -0
  222. package/dist/js-ts-safe-project-merge-symbol-move-admission.js +63 -0
  223. package/dist/js-ts-safe-project-merge-symbol-move-default-admission.js +143 -0
  224. package/dist/js-ts-safe-project-merge-symbol-move-risks.js +213 -0
  225. package/dist/js-ts-safe-project-merge-symbol-move.js +316 -0
  226. package/dist/js-ts-safe-project-merge-symbol-rename-admission.js +59 -0
  227. package/dist/js-ts-safe-project-merge-symbol-rename-default-admission.js +111 -0
  228. package/dist/js-ts-safe-project-merge-symbol-rename.js +319 -0
  229. package/dist/js-ts-safe-project-merge-ts-options.js +205 -0
  230. package/dist/js-ts-safe-project-merge-ts-program.js +268 -0
  231. package/dist/js-ts-safe-project-merge-typed-property-rename-rebase-utils.js +69 -0
  232. package/dist/js-ts-safe-project-merge-typed-property-rename-rebase.js +317 -0
  233. package/dist/js-ts-safe-project-merge-unsupported-surfaces.js +319 -0
  234. package/dist/js-ts-safe-project-merge.js +170 -171
  235. package/dist/js-ts-semantic-scope-use-def-bindings.js +287 -0
  236. package/dist/js-ts-semantic-scope-use-def-scan.js +241 -0
  237. package/dist/js-ts-semantic-scope-use-def-utils.js +132 -0
  238. package/dist/js-ts-semantic-scope-use-def.js +217 -0
  239. package/dist/lightweight-dependency-effects.js +28 -4
  240. package/dist/lightweight-dependency-relations.js +13 -7
  241. package/dist/lightweight-dependency-top-level.js +63 -0
  242. package/dist/native-import-language-profiles.js +27 -1
  243. package/dist/native-js-ts-importers.js +9 -5
  244. package/dist/native-parser-ast-format-profiles.js +12 -0
  245. package/dist/native-parser-html-css-format-profiles.js +85 -0
  246. package/dist/native-region-scanner-core.js +5 -3
  247. package/dist/native-region-scanner-js-commonjs.js +155 -0
  248. package/dist/native-region-scanner-js-imports.js +51 -13
  249. package/dist/native-region-scanner-js-reexports.js +79 -0
  250. package/dist/native-region-scanner-js-ts-helpers.js +23 -0
  251. package/dist/native-source-ledger-helpers.js +1 -1
  252. package/dist/native-source-ledger.js +24 -10
  253. package/dist/native-source-maps-ecma426.js +316 -0
  254. package/dist/native-source-maps.js +36 -6
  255. package/dist/native-source-preservation-ownership.js +292 -0
  256. package/dist/native-source-preservation-scanner.js +63 -25
  257. package/dist/native-source-preservation-types.d.ts +3 -0
  258. package/dist/semantic-import-effect-occurrences.js +242 -0
  259. package/dist/semantic-import-effect-regions.js +95 -58
  260. package/dist/semantic-import-graph-layers.js +224 -0
  261. package/dist/semantic-import-runtime-conditional-evidence.js +135 -0
  262. package/dist/semantic-import-runtime-effect-target-evidence.js +145 -0
  263. package/dist/semantic-import-runtime-exit-evidence.js +32 -0
  264. package/dist/semantic-import-runtime-import-meta-evidence.js +33 -0
  265. package/dist/semantic-import-runtime-mutation-evidence.js +155 -0
  266. package/dist/semantic-import-runtime-order-evidence.js +318 -0
  267. package/dist/semantic-import-runtime-promise-chain-evidence.js +103 -0
  268. package/dist/semantic-import-runtime-promise-combinator-evidence.js +166 -0
  269. package/dist/semantic-import-runtime-reachability-evidence.js +269 -0
  270. package/dist/semantic-import-runtime-resource-management-evidence.js +293 -0
  271. package/dist/semantic-import-runtime-switch-evidence.js +304 -0
  272. package/dist/semantic-import-runtime-throw-evidence.js +44 -0
  273. package/dist/semantic-import-runtime-try-finally-evidence.js +172 -0
  274. package/dist/semantic-import-sidecar-entry.js +4 -0
  275. package/dist/semantic-import-source-preservation.js +6 -2
  276. package/package.json +1 -1
@@ -0,0 +1,319 @@
1
+ import { hashSemanticValue } from '@shapeshift-labs/frontier-lang-kernel';
2
+ import { idFragment, uniqueStrings } from '../../native-import-utils.js';
3
+ import { nativeImportSourceText } from './nativeImportSourceText.js';
4
+ import { sourceTextForSpan } from './sourceTextForSpan.js';
5
+
6
+ export function callsiteArgumentAppendMergeClassification(input) {
7
+ if (input.region?.regionKind !== 'call') return undefined;
8
+ if (!input.baseSymbol || !input.workerSymbol || !input.headSymbol) return undefined;
9
+ const baseText = symbolSourceText(input.context.base, input.baseSymbol, input.region);
10
+ const workerText = symbolSourceText(input.context.worker, input.workerSymbol, input.region);
11
+ const headText = symbolSourceText(input.context.head, input.headSymbol, input.region);
12
+ const parsed = [baseText, workerText, headText].map(parseSimpleCallsite);
13
+ if (parsed.some((entry) => !entry.ok)) return undefined;
14
+ const [base, worker, head] = parsed.map((entry) => entry.value);
15
+ if (base.callee !== worker.callee || base.callee !== head.callee) return undefined;
16
+ if (!hasBaseArgumentPrefix(worker.args, base.args) || !hasBaseArgumentPrefix(head.args, base.args)) return undefined;
17
+ const workerTail = worker.args.slice(base.args.length);
18
+ const headTail = head.args.slice(base.args.length);
19
+ if (!workerTail.length || !headTail.length) return undefined;
20
+ if (!callsiteTargetHasRestParameter(input, base.callee)) return undefined;
21
+ if (![...workerTail, ...headTail].every(isPureAppendArgument)) return undefined;
22
+ if (duplicateArgumentHashes(workerTail, headTail).length) return undefined;
23
+
24
+ const sourceReplacementText = `${base.callee}(${[...base.args, ...workerTail, ...headTail].join(', ')})`;
25
+ return {
26
+ sourceBackprojection: {
27
+ mode: 'same-language-callsite-argument-append',
28
+ sourceEditSpan: input.headSymbol.sourceSpan,
29
+ sourceEditTextHash: hashSemanticValue(headText),
30
+ sourceReplacementText,
31
+ sourceReplacementTextHash: hashSemanticValue(sourceReplacementText),
32
+ lineEndingStable: true,
33
+ callsite: {
34
+ callee: base.callee,
35
+ baseArgumentCount: base.args.length,
36
+ workerAppendedArgumentCount: workerTail.length,
37
+ headAppendedArgumentCount: headTail.length,
38
+ mergedArgumentCount: base.args.length + workerTail.length + headTail.length
39
+ }
40
+ },
41
+ reasonCodes: uniqueStrings([
42
+ 'callsite-argument-append-rest-callee-signature-evidence',
43
+ 'callsite-argument-append-pure-argument-effect-evidence',
44
+ 'callsite-argument-append-order-evidence'
45
+ ]),
46
+ evidenceIds: [`evidence_${idFragment(input.anchorKey ?? base.callee)}_callsite_argument_append`]
47
+ };
48
+ }
49
+
50
+ function parseSimpleCallsite(text) {
51
+ const source = String(text ?? '').trim().replace(/;$/, '');
52
+ const open = source.indexOf('(');
53
+ if (open <= 0 || !source.endsWith(')')) return { ok: false };
54
+ const callee = source.slice(0, open).trim();
55
+ if (!/^[A-Za-z_$][\w$]*$/.test(callee)) return { ok: false };
56
+ const args = splitTopLevelComma(source.slice(open + 1, -1));
57
+ if (!args.ok) return { ok: false };
58
+ return { ok: true, value: { callee, args: args.items } };
59
+ }
60
+
61
+ function splitTopLevelComma(text) {
62
+ const items = [];
63
+ let start = 0;
64
+ let depth = 0;
65
+ let quote;
66
+ let comment;
67
+ let escaped = false;
68
+ for (let index = 0; index < text.length; index += 1) {
69
+ const char = text[index];
70
+ const next = text[index + 1];
71
+ if (comment === 'line') {
72
+ if (char === '\n' || char === '\r') comment = undefined;
73
+ continue;
74
+ }
75
+ if (comment === 'block') {
76
+ if (char === '*' && next === '/') {
77
+ index += 1;
78
+ comment = undefined;
79
+ }
80
+ continue;
81
+ }
82
+ if (quote) {
83
+ if (escaped) escaped = false;
84
+ else if (char === '\\') escaped = true;
85
+ else if (char === quote) quote = undefined;
86
+ continue;
87
+ }
88
+ if (char === '/' && next === '/') {
89
+ index += 1;
90
+ comment = 'line';
91
+ continue;
92
+ }
93
+ if (char === '/' && next === '*') {
94
+ index += 1;
95
+ comment = 'block';
96
+ continue;
97
+ }
98
+ if (char === '\'' || char === '"' || char === '`') {
99
+ quote = char;
100
+ continue;
101
+ }
102
+ if (char === '(' || char === '[' || char === '{') depth += 1;
103
+ else if (char === ')' || char === ']' || char === '}') depth -= 1;
104
+ else if (char === ',' && depth === 0) {
105
+ items.push(text.slice(start, index).trim());
106
+ start = index + 1;
107
+ }
108
+ if (depth < 0) return { ok: false };
109
+ }
110
+ if (quote || comment || depth !== 0) return { ok: false };
111
+ const tail = text.slice(start).trim();
112
+ if (tail) items.push(tail);
113
+ return { ok: true, items };
114
+ }
115
+
116
+ function hasBaseArgumentPrefix(args, baseArgs) {
117
+ if (args.length < baseArgs.length) return false;
118
+ return baseArgs.every((arg, index) => args[index] === arg);
119
+ }
120
+
121
+ function callsiteTargetHasRestParameter(input, callee) {
122
+ const symbolName = input.region?.symbolName ?? input.baseSymbol?.name ?? '';
123
+ const targetName = symbolName.includes('->') ? symbolName.split('->').pop() : callee;
124
+ if (!targetName || targetName !== callee) return false;
125
+ const sourceText = nativeImportSourceText(input.context.base);
126
+ return topLevelFunctionDeclarationHasRestParameter(String(sourceText ?? ''), targetName);
127
+ }
128
+
129
+ function isPureAppendArgument(argument) {
130
+ const text = String(argument ?? '').trim();
131
+ if (!text) return false;
132
+ if (/^(true|false|null|undefined|\d+(?:\.\d+)?|['"][^'"]*['"])$/.test(text)) return true;
133
+ if (/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*$/.test(text)) return true;
134
+ if (text.startsWith('{') && text.endsWith('}')) {
135
+ if (text.includes('`')) return false;
136
+ const codeText = maskNonCodeCharacters(text);
137
+ return !/[()=]|\.\.\.|=>|\b(await|new|yield|delete|throw|function|class)\b/.test(codeText);
138
+ }
139
+ return false;
140
+ }
141
+
142
+ function duplicateArgumentHashes(left, right) { const rightHashes = new Set(right.map(argumentIdentityHash)); return left.map(argumentIdentityHash).filter((hash) => rightHashes.has(hash)); }
143
+
144
+ function argumentIdentityHash(argument) { return hashSemanticValue(canonicalArgumentText(argument)); }
145
+
146
+ function canonicalArgumentText(argument) {
147
+ const source = String(argument ?? '').trim();
148
+ let result = '';
149
+ let quote;
150
+ let escaped = false;
151
+ for (let index = 0; index < source.length; index += 1) {
152
+ const char = source[index];
153
+ const next = source[index + 1];
154
+ if (quote) {
155
+ result += char;
156
+ if (escaped) escaped = false;
157
+ else if (char === '\\') escaped = true;
158
+ else if (char === quote) quote = undefined;
159
+ continue;
160
+ }
161
+ if (char === '/' && next === '/') {
162
+ index += 1;
163
+ while (index + 1 < source.length && source[index + 1] !== '\n' && source[index + 1] !== '\r') index += 1;
164
+ continue;
165
+ }
166
+ if (char === '/' && next === '*') {
167
+ index += 1;
168
+ while (index + 1 < source.length && !(source[index] === '*' && source[index + 1] === '/')) index += 1;
169
+ continue;
170
+ }
171
+ if (char === '\'' || char === '"' || char === '`') {
172
+ quote = char;
173
+ result += char;
174
+ continue;
175
+ }
176
+ if (/\s/.test(char)) continue;
177
+ result += char;
178
+ }
179
+ return result;
180
+ }
181
+
182
+ function topLevelFunctionDeclarationHasRestParameter(sourceText, targetName) {
183
+ const codeText = maskNonCodeCharacters(sourceText);
184
+ const pattern = new RegExp(`\\bfunction\\s*\\*?\\s*(${identifierPatternSource()})\\s*\\(`, 'g');
185
+ const matches = [];
186
+ for (let match = pattern.exec(codeText); match; match = pattern.exec(codeText)) {
187
+ if (match[1] !== targetName) continue;
188
+ if (braceDepthAt(codeText, match.index) !== 0) continue;
189
+ if (!hasDeclarationPrefix(codeText, match.index)) continue;
190
+ const open = codeText.indexOf('(', match.index + match[0].indexOf('('));
191
+ const close = matchingParen(codeText, open);
192
+ if (!Number.isFinite(close)) return false;
193
+ matches.push(/(?:^|,)\s*\.\.\.\s*[A-Za-z_$]/.test(codeText.slice(open + 1, close)));
194
+ }
195
+ return matches.length === 1 && matches[0] === true;
196
+ }
197
+
198
+ function maskNonCodeCharacters(value) {
199
+ const source = String(value ?? '');
200
+ let result = '';
201
+ let state = 'code';
202
+ for (let index = 0; index < source.length; index += 1) {
203
+ const char = source[index];
204
+ const next = source[index + 1];
205
+ if (state === 'line-comment') {
206
+ result += maskedChar(char);
207
+ if (char === '\n' || char === '\r') state = 'code';
208
+ continue;
209
+ }
210
+ if (state === 'block-comment') {
211
+ result += maskedChar(char);
212
+ if (char === '*' && next === '/') {
213
+ result += ' ';
214
+ index += 1;
215
+ state = 'code';
216
+ }
217
+ continue;
218
+ }
219
+ if (state === 'single' || state === 'double' || state === 'template') {
220
+ result += maskedChar(char);
221
+ if (char === '\\') {
222
+ if (index + 1 < source.length) {
223
+ result += maskedChar(source[index + 1]);
224
+ index += 1;
225
+ }
226
+ continue;
227
+ }
228
+ if ((state === 'single' && char === "'") || (state === 'double' && char === '"') || (state === 'template' && char === '`')) {
229
+ state = 'code';
230
+ }
231
+ continue;
232
+ }
233
+ if (char === '/' && next === '/') {
234
+ result += ' ';
235
+ index += 1;
236
+ state = 'line-comment';
237
+ } else if (char === '/' && next === '*') {
238
+ result += ' ';
239
+ index += 1;
240
+ state = 'block-comment';
241
+ } else if (char === "'") {
242
+ result += ' ';
243
+ state = 'single';
244
+ } else if (char === '"') {
245
+ result += ' ';
246
+ state = 'double';
247
+ } else if (char === '`') {
248
+ result += ' ';
249
+ state = 'template';
250
+ } else {
251
+ result += char;
252
+ }
253
+ }
254
+ return result;
255
+ }
256
+
257
+ function maskedChar(char) { return char === '\n' || char === '\r' ? char : ' '; }
258
+
259
+ function braceDepthAt(codeText, endIndex) {
260
+ let depth = 0;
261
+ for (let index = 0; index < endIndex; index += 1) {
262
+ if (codeText[index] === '{') depth += 1;
263
+ else if (codeText[index] === '}') depth = Math.max(0, depth - 1);
264
+ }
265
+ return depth;
266
+ }
267
+
268
+ function hasDeclarationPrefix(codeText, functionIndex) {
269
+ const allowedModifiers = new Set(['export', 'default', 'async', 'declare']);
270
+ let index = functionIndex;
271
+ const seen = new Set();
272
+ for (;;) {
273
+ index = skipWhitespaceBackward(codeText, index);
274
+ const word = wordBefore(codeText, index);
275
+ if (!word || !allowedModifiers.has(word.value)) break;
276
+ if (seen.has(word.value)) return false;
277
+ seen.add(word.value);
278
+ index = word.start;
279
+ }
280
+ index = skipWhitespaceBackward(codeText, index);
281
+ if (index === 0) return true;
282
+ const previous = codeText[index - 1];
283
+ return previous === ';' || previous === '{' || previous === '}';
284
+ }
285
+
286
+ function skipWhitespaceBackward(text, endIndex) {
287
+ let index = endIndex;
288
+ while (index > 0 && /\s/.test(text[index - 1])) index -= 1;
289
+ return index;
290
+ }
291
+
292
+ function wordBefore(text, endIndex) {
293
+ let index = endIndex;
294
+ while (index > 0 && /[A-Za-z0-9_$]/.test(text[index - 1])) index -= 1;
295
+ if (index === endIndex) return undefined;
296
+ const value = text.slice(index, endIndex);
297
+ if (!/^[A-Za-z_$][\w$]*$/.test(value)) return undefined;
298
+ return { value, start: index };
299
+ }
300
+
301
+ function matchingParen(codeText, open) {
302
+ if (open < 0 || codeText[open] !== '(') return undefined;
303
+ let depth = 0;
304
+ for (let index = open; index < codeText.length; index += 1) {
305
+ if (codeText[index] === '(') depth += 1;
306
+ else if (codeText[index] === ')') {
307
+ depth -= 1;
308
+ if (depth === 0) return index;
309
+ }
310
+ }
311
+ return undefined;
312
+ }
313
+
314
+ function identifierPatternSource() { return '[A-Za-z_$][\\w$]*'; }
315
+
316
+ function symbolSourceText(imported, symbol, region) {
317
+ const span = symbol?.sourceSpan ?? region?.metadata?.changedRegionProjection?.before?.sourceSpan ?? region?.sourceSpan;
318
+ return sourceTextForSpan(nativeImportSourceText(imported), span);
319
+ }
@@ -1,9 +1,14 @@
1
1
  import { hashSemanticValue } from '@shapeshift-labs/frontier-lang-kernel';
2
2
  import { spanOffsets } from './semanticEditSourceRanges.js';
3
3
 
4
+ const explicitSourceReplacementModes = new Set([
5
+ 'cross-language-explicit-source-replacement',
6
+ 'same-language-callsite-argument-append'
7
+ ]);
8
+
4
9
  export function explicitSourceReplacementEditForOperation(operation, identity, headSourceText, order) {
5
10
  const backprojection = operation.metadata?.sourceBackprojection;
6
- if (backprojection?.mode !== 'cross-language-explicit-source-replacement') return undefined;
11
+ if (!explicitSourceReplacementModes.has(backprojection?.mode)) return undefined;
7
12
  const replacement = backprojection.sourceReplacementText;
8
13
  const range = spanOffsets(headSourceText, backprojection.sourceEditSpan ?? operation.spans?.head ?? operation.spans?.base);
9
14
  const anchorRange = spanOffsets(headSourceText, operation.anchor?.sourceSpan);
@@ -27,7 +32,7 @@ export function explicitSourceReplacementEditForOperation(operation, identity, h
27
32
  order,
28
33
  ...identity,
29
34
  editKind: 'replace',
30
- sourceRangeKind: 'cross-language-explicit-source-replacement',
35
+ sourceRangeKind: backprojection.mode,
31
36
  start: range.start,
32
37
  end: range.end,
33
38
  headAnchorStart: anchorRange?.start,
@@ -29,12 +29,20 @@ export function projectionEditRecord(edit) {
29
29
  ...identity,
30
30
  ...sourceIdentity,
31
31
  operationContentHash: edit.operationContentHash,
32
+ structuralEditId: edit.structuralEditId,
33
+ structuralEditHash: edit.structuralEditHash,
34
+ structuralKind: edit.structuralKind,
35
+ structuralActions: edit.structuralActions,
32
36
  editContentHash: hashSemanticValue(compactRecord({
33
37
  semanticIdentityHash: identity.semanticIdentityHash,
34
38
  sourceIdentityHash: identity.sourceIdentityHash,
35
39
  sourceIdentityStatus: sourceIdentity.sourceIdentityStatus,
36
40
  sourceIdentityAnchorKey: sourceIdentity.sourceIdentityAnchorKey,
37
41
  targetIdentityAnchorKey: sourceIdentity.targetIdentityAnchorKey,
42
+ structuralEditId: edit.structuralEditId,
43
+ structuralEditHash: edit.structuralEditHash,
44
+ structuralKind: edit.structuralKind,
45
+ structuralActions: edit.structuralActions,
38
46
  sourceRangeKind: edit.sourceRangeKind,
39
47
  deletedTextHash,
40
48
  replacementTextHash,
@@ -23,13 +23,14 @@ export function replayEditDiagnostics(edit, status, range, reasonCodes, sourceTe
23
23
  export function replayEditsWithOverlapDiagnostics(edits) {
24
24
  const overlapDiagnostics = new Map();
25
25
  const ordered = edits
26
- .filter((edit) => edit.status === 'applied' && hasNumericReplayRange(edit))
26
+ .filter((edit) => replayOverlapParticipant(edit) && hasNumericReplayRange(edit))
27
27
  .sort((left, right) => left.start - right.start || left.end - right.end || (left.editOrder ?? 0) - (right.editOrder ?? 0));
28
28
  for (let leftIndex = 0; leftIndex < ordered.length; leftIndex += 1) {
29
29
  for (let rightIndex = leftIndex + 1; rightIndex < ordered.length; rightIndex += 1) {
30
30
  const left = ordered[leftIndex];
31
31
  const right = ordered[rightIndex];
32
32
  if (!rangesOverlap(left, right)) continue;
33
+ if (left.status !== 'applied' && right.status !== 'applied') continue;
33
34
  const operationIds = [left.operationId, right.operationId].filter(Boolean);
34
35
  const fallbackId = `${left.editOrder ?? leftIndex}:${right.editOrder ?? rightIndex}`;
35
36
  const code = `replay-edit-overlap:${operationIds.join(':') || fallbackId}`;
@@ -79,7 +80,7 @@ function appendOverlapDiagnostic(overlapDiagnostics, edit, code, operationIds) {
79
80
  function appendReplayEditDiagnostic(edit, diagnostic) {
80
81
  return compactRecord({
81
82
  ...edit,
82
- status: edit.status === 'applied' ? 'conflict' : edit.status,
83
+ status: replayOverlapParticipant(edit) ? 'conflict' : edit.status,
83
84
  reasonCodes: reasonList([...(edit.reasonCodes ?? []), diagnostic.code]),
84
85
  diagnostics: uniqueDiagnostics([...(edit.diagnostics ?? []), diagnostic])
85
86
  });
@@ -202,5 +203,9 @@ function hasNumericReplayRange(edit) {
202
203
  return typeof edit.start === 'number' && typeof edit.end === 'number';
203
204
  }
204
205
 
206
+ function replayOverlapParticipant(edit) {
207
+ return edit.status === 'applied' || edit.status === 'already-applied';
208
+ }
209
+
205
210
  function reasonList(values) { return uniqueStrings((values ?? []).filter(Boolean)); }
206
211
  function compactRecord(value) { return Object.fromEntries(Object.entries(value ?? {}).filter(([, entry]) => entry !== undefined && (!Array.isArray(entry) || entry.length > 0))); }
@@ -0,0 +1,61 @@
1
+ import { hashSemanticValue } from '@shapeshift-labs/frontier-lang-kernel';
2
+
3
+ function replayOutputBinding(input, outputSourceText, outputHash, options = {}) {
4
+ const expectedOutputSourceText = firstString(input.expectedOutputSourceText, input.outputSourceText);
5
+ const expectedOutputHash = firstString(
6
+ input.expectedOutputHash,
7
+ input.outputHash,
8
+ typeof expectedOutputSourceText === 'string' ? hashSemanticValue(expectedOutputSourceText) : undefined
9
+ );
10
+ if (typeof expectedOutputSourceText !== 'string' && typeof expectedOutputHash !== 'string') {
11
+ return { status: undefined, reasonCodes: [] };
12
+ }
13
+ if (options.replayStatus === 'stale' && typeof outputSourceText !== 'string' && typeof outputHash !== 'string') {
14
+ return compactRecord({
15
+ status: 'skipped',
16
+ reasonCodes: [],
17
+ expectedOutputHash,
18
+ replayedOutputHash: outputHash,
19
+ skippedReason: 'stale-current-source-requires-rerun'
20
+ });
21
+ }
22
+ const reasonCodes = [];
23
+ if (typeof expectedOutputSourceText === 'string') {
24
+ if (typeof outputSourceText !== 'string') reasonCodes.push('semantic-edit-replay-output-source-missing');
25
+ else if (outputSourceText !== expectedOutputSourceText) reasonCodes.push('semantic-edit-replay-output-source-mismatch');
26
+ }
27
+ if (typeof expectedOutputHash === 'string') {
28
+ if (typeof outputHash !== 'string') reasonCodes.push('semantic-edit-replay-output-hash-missing');
29
+ else if (outputHash !== expectedOutputHash) reasonCodes.push('semantic-edit-replay-output-hash-mismatch');
30
+ }
31
+ return compactRecord({
32
+ status: reasonCodes.length ? 'failed' : 'bound',
33
+ reasonCodes,
34
+ expectedOutputHash,
35
+ replayedOutputHash: outputHash
36
+ });
37
+ }
38
+
39
+ function replayOutputSource(status, sourceText, edits) {
40
+ if (typeof sourceText !== 'string') return undefined;
41
+ if (status === 'already-applied') return sourceText;
42
+ if (status !== 'accepted-clean') return undefined;
43
+ return edits.filter((edit) => edit.status === 'applied')
44
+ .sort(replaySourceEditSort)
45
+ .reduce((text, edit) => text.slice(0, edit.start) + editReplacement(edit, edits) + text.slice(edit.end), sourceText);
46
+ }
47
+
48
+ function replaySourceEditSort(left, right) {
49
+ return right.start - left.start || right.end - left.end || (right.editOrder ?? 0) - (left.editOrder ?? 0);
50
+ }
51
+
52
+ function editReplacement(edit, edits) {
53
+ return edits.find((candidate) => candidate.operationId === edit.operationId)?.replacementText ?? '';
54
+ }
55
+
56
+ function firstString(...values) { return values.find((value) => typeof value === 'string'); }
57
+ function compactRecord(value) {
58
+ return Object.fromEntries(Object.entries(value ?? {}).filter(([, entry]) => entry !== undefined && (!Array.isArray(entry) || entry.length > 0)));
59
+ }
60
+
61
+ export { replayOutputBinding, replayOutputSource };
@@ -0,0 +1,27 @@
1
+ function replayRerunRoute(status, reasonCodes, input, currentHash) {
2
+ const staleReasons = reasonList(reasonCodes.filter(isRerunnableStaleReasonCode));
3
+ return status === 'stale' && staleReasons.length ? compactRecord({
4
+ routeId: 'rerun-semantic-edit-replay-current-head',
5
+ routeLane: 'source-files',
6
+ routeNext: 'rerun-semantic-edit-replay-on-current-head',
7
+ action: 'rerun',
8
+ reasonCodes: staleReasons,
9
+ expectedCurrentHash: input.currentSourceHash,
10
+ observedCurrentHash: currentHash,
11
+ autoMergeClaim: false,
12
+ semanticEquivalenceClaim: false
13
+ }) : undefined;
14
+ }
15
+
16
+ function isRerunnableStaleReasonCode(code) {
17
+ return code === 'current-source-hash-mismatch';
18
+ }
19
+
20
+ function reasonList(values) {
21
+ return [...new Set((values ?? []).filter((value) => typeof value === 'string' && value.length > 0))];
22
+ }
23
+ function compactRecord(value) {
24
+ return Object.fromEntries(Object.entries(value ?? {}).filter(([, entry]) => entry !== undefined && (!Array.isArray(entry) || entry.length > 0)));
25
+ }
26
+
27
+ export { isRerunnableStaleReasonCode, replayRerunRoute };
@@ -1,5 +1,5 @@
1
1
  export function explicitSourceReplacementReplayRange(edit, symbolRange, sourceText) {
2
- if (edit.sourceRangeKind !== 'cross-language-explicit-source-replacement' || !symbolRange || typeof sourceText !== 'string') {
2
+ if (!explicitSourceReplacementMode(edit.sourceRangeKind) || !symbolRange || typeof sourceText !== 'string') {
3
3
  return undefined;
4
4
  }
5
5
  const deleted = uniqueTextRange(sourceText, symbolRange, edit.deletedText, 'deleted-text');
@@ -13,6 +13,11 @@ export function explicitSourceReplacementReplayRange(edit, symbolRange, sourceTe
13
13
  };
14
14
  }
15
15
 
16
+ function explicitSourceReplacementMode(mode) {
17
+ return mode === 'cross-language-explicit-source-replacement'
18
+ || mode === 'same-language-callsite-argument-append';
19
+ }
20
+
16
21
  function uniqueTextRange(sourceText, symbolRange, needle, label) {
17
22
  if (typeof needle !== 'string' || needle.length === 0) {
18
23
  return { status: 'missing', reasonCode: `current-symbol-explicit-source-replacement-${label}-missing` };