@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.
- package/README.md +315 -9
- package/bench/real-repo-corpus-checkout-identity.mjs +134 -0
- package/bench/real-repo-corpus-checkout-proof.mjs +263 -0
- package/bench/real-repo-corpus-command-execution.mjs +314 -0
- package/bench/real-repo-corpus-evidence.mjs +165 -0
- package/bench/real-repo-corpus-suite.mjs +273 -0
- package/bench/smoke.mjs +109 -7
- package/dist/declarations/import-adapter-core.d.ts +4 -3
- package/dist/declarations/import-adapter-options-native.d.ts +21 -0
- package/dist/declarations/js-ts-project-merge-admission-routes.d.ts +35 -0
- package/dist/declarations/js-ts-project-merge-commonjs-interop.d.ts +29 -0
- package/dist/declarations/js-ts-project-merge-confidence.d.ts +64 -0
- package/dist/declarations/js-ts-project-merge-declaration-emit-parity.d.ts +37 -0
- package/dist/declarations/js-ts-project-merge-declarations.d.ts +65 -0
- package/dist/declarations/js-ts-project-merge-diagnostics.d.ts +97 -0
- package/dist/declarations/js-ts-project-merge-global-augmentation.d.ts +30 -0
- package/dist/declarations/js-ts-project-merge-jsx-render-branch.d.ts +48 -0
- package/dist/declarations/js-ts-project-merge-proof-levels.d.ts +109 -0
- package/dist/declarations/js-ts-project-merge-quality-gates.d.ts +38 -0
- package/dist/declarations/js-ts-project-merge-semantic-equivalence-proof.d.ts +45 -0
- package/dist/declarations/js-ts-project-merge-tsconfig.d.ts +43 -0
- package/dist/declarations/js-ts-safe-merge.d.ts +47 -0
- package/dist/declarations/js-ts-safe-project-merge.d.ts +120 -38
- package/dist/declarations/native-project-compiler-assignability-oracle.d.ts +41 -0
- package/dist/declarations/native-project-compiler-callable-signatures.d.ts +31 -0
- package/dist/declarations/native-project-compiler-class-member-runtime-proof.d.ts +87 -0
- package/dist/declarations/native-project-compiler-composite-types.d.ts +23 -0
- package/dist/declarations/native-project-compiler-enum-proof.d.ts +58 -0
- package/dist/declarations/native-project-compiler-index-signature.d.ts +7 -0
- package/dist/declarations/native-project-compiler-public-api-source-binding.d.ts +8 -0
- package/dist/declarations/native-project-compiler-scope.d.ts +37 -0
- package/dist/declarations/native-project-compiler-type-reference-targets.d.ts +38 -0
- package/dist/declarations/native-project-css-modules.d.ts +90 -0
- package/dist/declarations/native-project-decorator-metadata.d.ts +126 -0
- package/dist/declarations/native-project-jsx-graph.d.ts +313 -0
- package/dist/declarations/native-project-module-declarations.d.ts +52 -0
- package/dist/declarations/native-project-module-resolution.d.ts +76 -1
- package/dist/declarations/native-project-runtime-effect-target.d.ts +29 -0
- package/dist/declarations/native-project-runtime-executable-effect-evidence.d.ts +107 -0
- package/dist/declarations/native-project-runtime-mutation-target.d.ts +33 -0
- package/dist/declarations/native-project-runtime-promise-chain.d.ts +30 -0
- package/dist/declarations/native-project-runtime-promise-combinator.d.ts +22 -0
- package/dist/declarations/native-project-runtime-reachability.d.ts +30 -0
- package/dist/declarations/native-project-runtime-resource-management.d.ts +27 -0
- package/dist/declarations/native-project-runtime-yield-delegation.d.ts +10 -0
- package/dist/declarations/native-project-scope-template-reference.d.ts +13 -0
- package/dist/declarations/native-project-source-evidence.d.ts +8 -0
- package/dist/declarations/native-project.d.ts +40 -39
- package/dist/declarations/semantic-edit-script.d.ts +10 -8
- package/dist/declarations/semantic-graph-layers.d.ts +79 -0
- package/dist/declarations/semantic-sidecar.d.ts +3 -2
- package/dist/declarations/semantic-structural-diff.d.ts +94 -0
- package/dist/declarations/source-preservation.d.ts +32 -1
- package/dist/declarations/target-adapters.d.ts +22 -2
- package/dist/index.d.ts +31 -0
- package/dist/index.js +5 -0
- package/dist/internal/index-impl/compileNativeSource.js +53 -5
- package/dist/internal/index-impl/createLightweightNativeImport.js +58 -4
- package/dist/internal/index-impl/createNativeImportFromSyntaxAst.js +17 -1
- package/dist/internal/index-impl/createNativeImportFromTypeScriptAst.js +28 -4
- package/dist/internal/index-impl/createNativeProjectImportResult.js +31 -27
- package/dist/internal/index-impl/createNativeProjectModuleResolutionFromPackageManifests.js +145 -0
- package/dist/internal/index-impl/createNativeSourcePreservation.js +34 -7
- package/dist/internal/index-impl/createSemanticImportSidecar.js +27 -1
- package/dist/internal/index-impl/createTypeScriptCompilerNativeImporterAdapter.js +16 -5
- package/dist/internal/index-impl/dynamicImportExpressionMetadata.js +80 -0
- package/dist/internal/index-impl/importMetaUrlDependencyMetadata.js +176 -0
- package/dist/internal/index-impl/importNativeSource.js +2 -3
- package/dist/internal/index-impl/moduleImportAttributeMetadata.js +232 -0
- package/dist/internal/index-impl/projectSemanticEditScriptToSource.js +8 -1
- package/dist/internal/index-impl/projectSymbolGraphClassStaticBlocks.js +148 -0
- package/dist/internal/index-impl/projectSymbolGraphCompilerAdvancedTypeMetadata.js +45 -0
- package/dist/internal/index-impl/projectSymbolGraphCompilerCallableSignatureEquivalence.js +107 -0
- package/dist/internal/index-impl/projectSymbolGraphCompilerClassPrivateAccessorRuntimeProof.js +280 -0
- package/dist/internal/index-impl/projectSymbolGraphCompilerClassShapeEquivalence.js +103 -0
- package/dist/internal/index-impl/projectSymbolGraphCompilerConditionalTypeEquivalence.js +242 -0
- package/dist/internal/index-impl/projectSymbolGraphCompilerDecoratorRuntimeProof.js +197 -0
- package/dist/internal/index-impl/projectSymbolGraphCompilerEnumEquivalence.js +188 -0
- package/dist/internal/index-impl/projectSymbolGraphCompilerFacts.js +244 -0
- package/dist/internal/index-impl/projectSymbolGraphCompilerIndexSignatureEquivalence.js +58 -0
- package/dist/internal/index-impl/projectSymbolGraphCompilerMetadata.js +168 -0
- package/dist/internal/index-impl/projectSymbolGraphCompilerTypeEquivalence.js +199 -0
- package/dist/internal/index-impl/projectSymbolGraphCompilerTypeEquivalenceProof.js +204 -0
- package/dist/internal/index-impl/projectSymbolGraphCompilerTypeReferenceTargetEquivalence.js +99 -0
- package/dist/internal/index-impl/projectSymbolGraphCssModuleRecords.js +264 -0
- package/dist/internal/index-impl/projectSymbolGraphCssModuleScanners.js +242 -0
- package/dist/internal/index-impl/projectSymbolGraphCssModuleUtils.js +152 -0
- package/dist/internal/index-impl/projectSymbolGraphCssModules.js +82 -0
- package/dist/internal/index-impl/projectSymbolGraphJsxComponentImports.js +170 -0
- package/dist/internal/index-impl/projectSymbolGraphJsxComponentProviderLookup.js +167 -0
- package/dist/internal/index-impl/projectSymbolGraphJsxComponentWrappers.js +150 -0
- package/dist/internal/index-impl/projectSymbolGraphJsxContextTargets.js +71 -0
- package/dist/internal/index-impl/projectSymbolGraphJsxContextValues.js +212 -0
- package/dist/internal/index-impl/projectSymbolGraphJsxEventHandlers.js +172 -0
- package/dist/internal/index-impl/projectSymbolGraphJsxHookEffects.js +124 -0
- package/dist/internal/index-impl/projectSymbolGraphJsxHooks.js +281 -0
- package/dist/internal/index-impl/projectSymbolGraphJsxMemberComponents.js +139 -0
- package/dist/internal/index-impl/projectSymbolGraphJsxPropFlows.js +320 -0
- package/dist/internal/index-impl/projectSymbolGraphJsxPropValues.js +145 -0
- package/dist/internal/index-impl/projectSymbolGraphJsxProviderFlows.js +133 -0
- package/dist/internal/index-impl/projectSymbolGraphJsxRecords.js +315 -0
- package/dist/internal/index-impl/projectSymbolGraphJsxRenderCollections.js +155 -0
- package/dist/internal/index-impl/projectSymbolGraphJsxRenderReturns.js +291 -0
- package/dist/internal/index-impl/projectSymbolGraphJsxRenderRisk.js +279 -0
- package/dist/internal/index-impl/projectSymbolGraphModuleDeclarationShapes.js +138 -0
- package/dist/internal/index-impl/projectSymbolGraphModuleResolution.js +89 -87
- package/dist/internal/index-impl/projectSymbolGraphPackageConditions.js +314 -0
- package/dist/internal/index-impl/projectSymbolGraphReExportImportTargets.js +43 -0
- package/dist/internal/index-impl/projectSymbolGraphReExports.js +55 -1
- package/dist/internal/index-impl/projectSymbolGraphRuntimeRegions.js +108 -0
- package/dist/internal/index-impl/projectSymbolGraphScopeUseDefAliases.js +307 -0
- package/dist/internal/index-impl/projectSymbolGraphScopeUseDefLexical.js +320 -0
- package/dist/internal/index-impl/projectSymbolGraphScopeUseDefOwners.js +50 -0
- package/dist/internal/index-impl/projectSymbolGraphScopeUseDefRecordBuilders.js +112 -0
- package/dist/internal/index-impl/projectSymbolGraphScopeUseDefRecords.js +238 -0
- package/dist/internal/index-impl/projectSymbolGraphScopeUseDefStructural.js +104 -0
- package/dist/internal/index-impl/projectSymbolGraphScopeUseDefStructuralNormalize.js +242 -0
- package/dist/internal/index-impl/projectSymbolGraphScopeUseDefUseHashes.js +107 -0
- package/dist/internal/index-impl/projectSymbolGraphSourceMapGeneratedBoundary.js +111 -0
- package/dist/internal/index-impl/projectSymbolGraphSourceRecords.js +268 -0
- package/dist/internal/index-impl/projectSymbolGraphSourceRecordsOwnership.js +309 -0
- package/dist/internal/index-impl/replaySemanticEditProjection.js +53 -39
- package/dist/internal/index-impl/runtimeOrderEvidenceBinding.js +151 -0
- package/dist/internal/index-impl/runtimeOrderProofSurfaces.js +253 -0
- package/dist/internal/index-impl/semanticEditCallsiteArgumentMerge.js +319 -0
- package/dist/internal/index-impl/semanticEditExplicitSourceReplacement.js +7 -2
- package/dist/internal/index-impl/semanticEditProjectionRecord.js +8 -0
- package/dist/internal/index-impl/semanticEditReplayDiagnostics.js +7 -2
- package/dist/internal/index-impl/semanticEditReplayOutputBinding.js +61 -0
- package/dist/internal/index-impl/semanticEditReplayRerunRoute.js +27 -0
- package/dist/internal/index-impl/semanticEditReplaySourceReplacement.js +6 -1
- package/dist/internal/index-impl/semanticEditRuntimeOrderReasons.js +320 -0
- package/dist/internal/index-impl/semanticEditScriptClassification.js +90 -5
- package/dist/internal/index-impl/semanticEditScripts.js +42 -5
- package/dist/internal/index-impl/semanticEditTypeSyntaxReasons.js +134 -0
- package/dist/internal/index-impl/semanticIndexFromNativeDeclarations.js +11 -5
- package/dist/internal/index-impl/semanticStructuralDiffRecords.js +150 -0
- package/dist/internal/index-impl/sourceMapGeneratedBoundaryGate.js +185 -0
- package/dist/internal/index-impl/staticMemberLiteral.js +31 -0
- package/dist/internal/index-impl/staticOptionalMemberReference.js +22 -0
- package/dist/internal/index-impl/syntaxAstSourcePreservation.js +273 -0
- package/dist/internal/index-impl/syntaxCommonJsModuleDeclarationEntries.js +297 -0
- package/dist/internal/index-impl/syntaxModuleDeclarationEntries.js +56 -132
- package/dist/internal/index-impl/syntaxModuleEntryRecords.js +160 -0
- package/dist/internal/index-impl/typeScriptCompilerAdvancedTypeShapes.js +160 -0
- package/dist/internal/index-impl/typeScriptCompilerAssignabilityOracle.js +97 -0
- package/dist/internal/index-impl/typeScriptCompilerClassApi.js +238 -0
- package/dist/internal/index-impl/typeScriptCompilerDecoratorMetadata.js +290 -0
- package/dist/internal/index-impl/typeScriptCompilerEnumShape.js +279 -0
- package/dist/internal/index-impl/typeScriptCompilerFacts.js +294 -0
- package/dist/internal/index-impl/typeScriptCompilerInferenceSyntax.js +170 -0
- package/dist/internal/index-impl/typeScriptCompilerReferenceGraph.js +186 -0
- package/dist/internal/index-impl/typeScriptCompilerSymbolIdentity.js +294 -0
- package/dist/internal/index-impl/typeScriptCompilerTypeReferenceTargets.js +142 -0
- package/dist/internal/index-impl/typeScriptDeclaration.js +10 -38
- package/dist/internal/index-impl/typeScriptModuleDeclarationEntries.js +52 -15
- package/dist/internal/index-impl/typeScriptSourceFilePreservation.js +296 -0
- package/dist/js-ts-safe-member-class-invariants.js +247 -0
- package/dist/js-ts-safe-member-merge-result.js +23 -3
- package/dist/js-ts-safe-member-merge.js +28 -4
- package/dist/js-ts-safe-merge-binding-patterns.js +170 -0
- package/dist/js-ts-safe-merge-jsx-attribute-fallback.js +151 -157
- package/dist/js-ts-safe-merge-jsx-attribute-parser.js +277 -0
- package/dist/js-ts-safe-merge-jsx-child-expression-fallback.js +161 -0
- package/dist/js-ts-safe-merge-jsx-child-expression-merge.js +319 -0
- package/dist/js-ts-safe-merge-jsx-child-expression-parser.js +300 -0
- package/dist/js-ts-safe-merge-parse-declarations.js +46 -2
- package/dist/js-ts-safe-merge-parse-statements.js +8 -0
- package/dist/js-ts-safe-merge-semantic-edit-fallback.js +13 -5
- package/dist/js-ts-safe-merge-source-shape-fallbacks.js +3 -1
- package/dist/js-ts-safe-merge-top-level-rename-fallback.js +31 -5
- package/dist/js-ts-safe-merge-top-level-rename-result.js +7 -2
- package/dist/js-ts-safe-merge-variable-declarator-fallback.js +124 -6
- package/dist/js-ts-safe-merge-variable-declarator-parser.js +34 -4
- package/dist/js-ts-safe-merge.js +136 -0
- package/dist/js-ts-safe-project-merge-admission-routes.js +216 -0
- package/dist/js-ts-safe-project-merge-admission.js +161 -0
- package/dist/js-ts-safe-project-merge-ambient.js +110 -0
- package/dist/js-ts-safe-project-merge-core.js +85 -0
- package/dist/js-ts-safe-project-merge-css-module-conflicts.js +60 -0
- package/dist/js-ts-safe-project-merge-declaration-emit-parity.js +186 -0
- package/dist/js-ts-safe-project-merge-declarations.js +227 -0
- package/dist/js-ts-safe-project-merge-diagnostics-metadata.js +42 -0
- package/dist/js-ts-safe-project-merge-diagnostics-ts.js +73 -0
- package/dist/js-ts-safe-project-merge-diagnostics.js +283 -0
- package/dist/js-ts-safe-project-merge-evidence-routing.js +38 -0
- package/dist/js-ts-safe-project-merge-files.js +70 -0
- package/dist/js-ts-safe-project-merge-global-augmentation-compatibility.js +99 -0
- package/dist/js-ts-safe-project-merge-graph-conflicts.js +90 -2
- package/dist/js-ts-safe-project-merge-graph-delta-commonjs-interop.js +108 -0
- package/dist/js-ts-safe-project-merge-graph-delta-compiler-conflicts.js +179 -0
- package/dist/js-ts-safe-project-merge-graph-delta-compiler-details.js +189 -0
- package/dist/js-ts-safe-project-merge-graph-delta-conflicts.js +51 -184
- package/dist/js-ts-safe-project-merge-graph-delta-identity-conflicts.js +202 -0
- package/dist/js-ts-safe-project-merge-graph-delta-inference-syntax.js +80 -0
- package/dist/js-ts-safe-project-merge-graph-delta-module-declarations.js +155 -0
- package/dist/js-ts-safe-project-merge-graph-limits.js +16 -1
- package/dist/js-ts-safe-project-merge-graph.js +37 -5
- package/dist/js-ts-safe-project-merge-import-removal.js +292 -0
- package/dist/js-ts-safe-project-merge-jsx-graph-conflict-details.js +235 -0
- package/dist/js-ts-safe-project-merge-jsx-graph-conflicts.js +173 -0
- package/dist/js-ts-safe-project-merge-jsx-prop-contracts.js +86 -0
- package/dist/js-ts-safe-project-merge-jsx-render-branch-proof.js +189 -0
- package/dist/js-ts-safe-project-merge-missing-evidence.js +310 -0
- package/dist/js-ts-safe-project-merge-move-rename.js +209 -0
- package/dist/js-ts-safe-project-merge-proof-conflicts.js +44 -0
- package/dist/js-ts-safe-project-merge-proof-levels.js +320 -0
- package/dist/js-ts-safe-project-merge-quality-gates.js +140 -0
- package/dist/js-ts-safe-project-merge-routing-calibration.js +125 -0
- package/dist/js-ts-safe-project-merge-runtime-region-conflicts.js +156 -0
- package/dist/js-ts-safe-project-merge-scope-use-def-conflicts.js +292 -0
- package/dist/js-ts-safe-project-merge-semantic-equivalence-proof.js +175 -0
- package/dist/js-ts-safe-project-merge-semantic-replay-proof.js +311 -0
- package/dist/js-ts-safe-project-merge-semantic-replay-routes.js +179 -0
- package/dist/js-ts-safe-project-merge-source-span-conflicts.js +310 -0
- package/dist/js-ts-safe-project-merge-source-span-roundtrip-proof.js +172 -0
- package/dist/js-ts-safe-project-merge-split-merge-admission.js +96 -0
- package/dist/js-ts-safe-project-merge-split-merge-records.js +320 -0
- package/dist/js-ts-safe-project-merge-split-merge-shapes.js +234 -0
- package/dist/js-ts-safe-project-merge-split-merge.js +218 -0
- package/dist/js-ts-safe-project-merge-summary.js +320 -0
- package/dist/js-ts-safe-project-merge-symbol-move-admission.js +63 -0
- package/dist/js-ts-safe-project-merge-symbol-move-default-admission.js +143 -0
- package/dist/js-ts-safe-project-merge-symbol-move-risks.js +213 -0
- package/dist/js-ts-safe-project-merge-symbol-move.js +316 -0
- package/dist/js-ts-safe-project-merge-symbol-rename-admission.js +59 -0
- package/dist/js-ts-safe-project-merge-symbol-rename-default-admission.js +111 -0
- package/dist/js-ts-safe-project-merge-symbol-rename.js +319 -0
- package/dist/js-ts-safe-project-merge-ts-options.js +205 -0
- package/dist/js-ts-safe-project-merge-ts-program.js +268 -0
- package/dist/js-ts-safe-project-merge-typed-property-rename-rebase-utils.js +69 -0
- package/dist/js-ts-safe-project-merge-typed-property-rename-rebase.js +317 -0
- package/dist/js-ts-safe-project-merge-unsupported-surfaces.js +319 -0
- package/dist/js-ts-safe-project-merge.js +170 -171
- package/dist/js-ts-semantic-scope-use-def-bindings.js +287 -0
- package/dist/js-ts-semantic-scope-use-def-scan.js +241 -0
- package/dist/js-ts-semantic-scope-use-def-utils.js +132 -0
- package/dist/js-ts-semantic-scope-use-def.js +217 -0
- package/dist/lightweight-dependency-effects.js +28 -4
- package/dist/lightweight-dependency-relations.js +13 -7
- package/dist/lightweight-dependency-top-level.js +63 -0
- package/dist/native-import-language-profiles.js +27 -1
- package/dist/native-js-ts-importers.js +9 -5
- package/dist/native-parser-ast-format-profiles.js +12 -0
- package/dist/native-parser-html-css-format-profiles.js +85 -0
- package/dist/native-region-scanner-core.js +5 -3
- package/dist/native-region-scanner-js-commonjs.js +155 -0
- package/dist/native-region-scanner-js-imports.js +51 -13
- package/dist/native-region-scanner-js-reexports.js +79 -0
- package/dist/native-region-scanner-js-ts-helpers.js +23 -0
- package/dist/native-source-ledger-helpers.js +1 -1
- package/dist/native-source-ledger.js +24 -10
- package/dist/native-source-maps-ecma426.js +316 -0
- package/dist/native-source-maps.js +36 -6
- package/dist/native-source-preservation-ownership.js +292 -0
- package/dist/native-source-preservation-scanner.js +63 -25
- package/dist/native-source-preservation-types.d.ts +3 -0
- package/dist/semantic-import-effect-occurrences.js +242 -0
- package/dist/semantic-import-effect-regions.js +95 -58
- package/dist/semantic-import-graph-layers.js +224 -0
- package/dist/semantic-import-runtime-conditional-evidence.js +135 -0
- package/dist/semantic-import-runtime-effect-target-evidence.js +145 -0
- package/dist/semantic-import-runtime-exit-evidence.js +32 -0
- package/dist/semantic-import-runtime-import-meta-evidence.js +33 -0
- package/dist/semantic-import-runtime-mutation-evidence.js +155 -0
- package/dist/semantic-import-runtime-order-evidence.js +318 -0
- package/dist/semantic-import-runtime-promise-chain-evidence.js +103 -0
- package/dist/semantic-import-runtime-promise-combinator-evidence.js +166 -0
- package/dist/semantic-import-runtime-reachability-evidence.js +269 -0
- package/dist/semantic-import-runtime-resource-management-evidence.js +293 -0
- package/dist/semantic-import-runtime-switch-evidence.js +304 -0
- package/dist/semantic-import-runtime-throw-evidence.js +44 -0
- package/dist/semantic-import-runtime-try-finally-evidence.js +172 -0
- package/dist/semantic-import-sidecar-entry.js +4 -0
- package/dist/semantic-import-source-preservation.js +6 -2
- package/package.json +1 -1
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
function promiseCombinatorEvidenceRecords(line, start, end) {
|
|
2
|
+
const text = String(line ?? '');
|
|
3
|
+
return promiseCombinatorCalls(text)
|
|
4
|
+
.filter((call) => start >= call.open && end <= call.close + 1)
|
|
5
|
+
.sort((left, right) => right.open - left.open)
|
|
6
|
+
.slice(0, 1)
|
|
7
|
+
.map((call) => promiseCombinatorRecord(text, call, start, end))
|
|
8
|
+
.filter(Boolean);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function promiseCombinatorContextReasonCodes(record) {
|
|
12
|
+
return uniqueStrings([
|
|
13
|
+
'runtime-order-promise-combinator-merge-requires-concurrency-evidence',
|
|
14
|
+
record?.arrayElementOrdinal ? 'runtime-order-promise-combinator-merge-requires-element-order-evidence' : undefined,
|
|
15
|
+
record?.methodName === 'all' ? 'runtime-order-promise-all-merge-requires-all-settlement-evidence' : undefined,
|
|
16
|
+
record?.methodName === 'allSettled' ? 'runtime-order-promise-all-settled-merge-requires-settlement-record-evidence' : undefined,
|
|
17
|
+
record?.methodName === 'race' ? 'runtime-order-promise-race-merge-requires-first-settlement-evidence' : undefined,
|
|
18
|
+
record?.methodName === 'any' ? 'runtime-order-promise-any-merge-requires-first-fulfillment-evidence' : undefined,
|
|
19
|
+
record?.runtimeEquivalenceClaim === false ? 'runtime-order-promise-combinator-runtime-equivalence-not-proven' : undefined
|
|
20
|
+
]);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function promiseCombinatorCalls(text) {
|
|
24
|
+
const calls = [];
|
|
25
|
+
const state = scanState();
|
|
26
|
+
for (let index = 0; index < text.length; index += 1) {
|
|
27
|
+
const char = text[index], next = text[index + 1];
|
|
28
|
+
if (advanceIgnoredState(state, char, next)) { if (state.skipNext) { state.skipNext = false; index += 1; } continue; }
|
|
29
|
+
if (!wordAt(text, index, 'Promise')) continue;
|
|
30
|
+
const dot = skipSpaces(text, index + 'Promise'.length);
|
|
31
|
+
if (text[dot] !== '.') continue;
|
|
32
|
+
const methodStart = skipSpaces(text, dot + 1);
|
|
33
|
+
const methodName = promiseMethodNameAt(text, methodStart);
|
|
34
|
+
if (!methodName) continue;
|
|
35
|
+
const open = skipSpaces(text, methodStart + methodName.length);
|
|
36
|
+
if (text[open] !== '(') continue;
|
|
37
|
+
const close = matchingIndex(text, open, '(', ')');
|
|
38
|
+
if (close !== undefined) calls.push({ methodName, open, close, start: index });
|
|
39
|
+
}
|
|
40
|
+
return calls;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function promiseCombinatorRecord(text, call, start, end) {
|
|
44
|
+
const argument = segmentContaining(text, call.open + 1, call.close, start, end);
|
|
45
|
+
const array = arrayElementContaining(text, argument, start, end);
|
|
46
|
+
return compactRecord({
|
|
47
|
+
kind: 'promise-combinator',
|
|
48
|
+
methodName: call.methodName,
|
|
49
|
+
concurrencySemantics: promiseConcurrencySemantics(call.methodName),
|
|
50
|
+
settlementPolicy: promiseSettlementPolicy(call.methodName),
|
|
51
|
+
callText: normalizeOrderEvidenceText(text.slice(call.start, call.close + 1)),
|
|
52
|
+
argumentOrdinal: argument?.ordinal,
|
|
53
|
+
argumentText: argument ? normalizeOrderEvidenceText(text.slice(argument.start, argument.end)) : undefined,
|
|
54
|
+
directArrayArgument: array ? true : undefined,
|
|
55
|
+
arrayElementOrdinal: array?.ordinal,
|
|
56
|
+
arrayElementCount: array?.count,
|
|
57
|
+
arrayElementText: array?.text,
|
|
58
|
+
regionWithinCombinator: true,
|
|
59
|
+
runtimeEquivalenceClaim: false,
|
|
60
|
+
semanticEquivalenceClaim: false
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function arrayElementContaining(text, argument, start, end) {
|
|
65
|
+
if (!argument) return undefined;
|
|
66
|
+
const arrayStart = skipSpaces(text, argument.start);
|
|
67
|
+
if (text[arrayStart] !== '[') return undefined;
|
|
68
|
+
const arrayEnd = matchingIndex(text, arrayStart, '[', ']');
|
|
69
|
+
if (arrayEnd === undefined || start < arrayStart || end > arrayEnd + 1) return undefined;
|
|
70
|
+
const segment = segmentContaining(text, arrayStart + 1, arrayEnd, start, end);
|
|
71
|
+
return segment && { ...segment, count: topLevelSegments(text, arrayStart + 1, arrayEnd).length, text: normalizeOrderEvidenceText(text.slice(segment.start, segment.end)) };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function segmentContaining(text, start, end, targetStart, targetEnd) {
|
|
75
|
+
return topLevelSegments(text, start, end)
|
|
76
|
+
.find((segment) => targetStart >= segment.start && targetEnd <= segment.end + 1);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function topLevelSegments(text, start, end) {
|
|
80
|
+
const segments = [];
|
|
81
|
+
const state = scanState();
|
|
82
|
+
let segmentStart = start;
|
|
83
|
+
for (let index = start; index < end; index += 1) {
|
|
84
|
+
const char = text[index], next = text[index + 1];
|
|
85
|
+
if (advanceIgnoredState(state, char, next)) { if (state.skipNext) { state.skipNext = false; index += 1; } continue; }
|
|
86
|
+
if (char === '(') { state.parenDepth += 1; continue; }
|
|
87
|
+
if (char === ')') { state.parenDepth = Math.max(0, state.parenDepth - 1); continue; }
|
|
88
|
+
if (char === '[') { state.bracketDepth += 1; continue; }
|
|
89
|
+
if (char === ']') { state.bracketDepth = Math.max(0, state.bracketDepth - 1); continue; }
|
|
90
|
+
if (char === '{') { state.braceDepth += 1; continue; }
|
|
91
|
+
if (char === '}') { state.braceDepth = Math.max(0, state.braceDepth - 1); continue; }
|
|
92
|
+
if (char === ',' && !state.parenDepth && !state.bracketDepth && !state.braceDepth) {
|
|
93
|
+
segments.push({ start: skipSpaces(text, segmentStart), end: trimEnd(text, segmentStart, index), ordinal: segments.length + 1 });
|
|
94
|
+
segmentStart = index + 1;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
segments.push({ start: skipSpaces(text, segmentStart), end: trimEnd(text, segmentStart, end), ordinal: segments.length + 1 });
|
|
98
|
+
return segments.filter((segment) => segment.start <= segment.end);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function matchingIndex(text, open, openChar, closeChar) {
|
|
102
|
+
const state = scanState();
|
|
103
|
+
let depth = 0;
|
|
104
|
+
for (let index = open; index < text.length; index += 1) {
|
|
105
|
+
const char = text[index], next = text[index + 1];
|
|
106
|
+
if (advanceIgnoredState(state, char, next)) { if (state.skipNext) { state.skipNext = false; index += 1; } continue; }
|
|
107
|
+
if (char === openChar) depth += 1;
|
|
108
|
+
else if (char === closeChar && --depth === 0) return index;
|
|
109
|
+
}
|
|
110
|
+
return undefined;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function advanceIgnoredState(state, char, next) {
|
|
114
|
+
if (state.lineComment) return true;
|
|
115
|
+
if (state.blockComment) { if (char === '*' && next === '/') { state.blockComment = false; state.skipNext = true; } return true; }
|
|
116
|
+
if (state.quote) {
|
|
117
|
+
if (state.escaped) state.escaped = false;
|
|
118
|
+
else if (char === '\\') state.escaped = true;
|
|
119
|
+
else if (char === state.quote) state.quote = undefined;
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
if (char === '/' && next === '/') { state.lineComment = true; return true; }
|
|
123
|
+
if (char === '/' && next === '*') { state.blockComment = true; state.skipNext = true; return true; }
|
|
124
|
+
if (char === '\'' || char === '"' || char === '`') { state.quote = char; return true; }
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function promiseMethodNameAt(text, index) {
|
|
129
|
+
for (const name of ['allSettled', 'all', 'race', 'any']) {
|
|
130
|
+
if (wordAt(text, index, name)) return name;
|
|
131
|
+
}
|
|
132
|
+
return undefined;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function promiseConcurrencySemantics(methodName) {
|
|
136
|
+
return ({
|
|
137
|
+
all: 'concurrent-all-inputs',
|
|
138
|
+
allSettled: 'concurrent-all-settled-inputs',
|
|
139
|
+
race: 'concurrent-first-settled-input',
|
|
140
|
+
any: 'concurrent-first-fulfilled-input'
|
|
141
|
+
})[methodName];
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function promiseSettlementPolicy(methodName) {
|
|
145
|
+
return ({
|
|
146
|
+
all: 'fulfill-array-or-first-reject',
|
|
147
|
+
allSettled: 'settled-record-array',
|
|
148
|
+
race: 'first-settled-wins',
|
|
149
|
+
any: 'first-fulfilled-or-aggregate-reject'
|
|
150
|
+
})[methodName];
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function wordAt(text, index, word) {
|
|
154
|
+
return text.slice(index, index + word.length) === word
|
|
155
|
+
&& !isIdentifierPart(text[index - 1]) && !isIdentifierPart(text[index + word.length]);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function skipSpaces(text, index) { let cursor = index; while (/\s/.test(text[cursor] ?? '')) cursor += 1; return cursor; }
|
|
159
|
+
function trimEnd(text, start, end) { let cursor = end; while (cursor > start && /\s/.test(text[cursor - 1] ?? '')) cursor -= 1; return cursor; }
|
|
160
|
+
function scanState() { return { parenDepth: 0, bracketDepth: 0, braceDepth: 0 }; }
|
|
161
|
+
function normalizeOrderEvidenceText(value) { return String(value ?? '').replace(/\s+/g, ' ').trim(); }
|
|
162
|
+
function isIdentifierPart(char) { return /[A-Za-z0-9_$]/.test(char ?? ''); }
|
|
163
|
+
function uniqueStrings(values) { return [...new Set((values ?? []).filter(Boolean).map(String))]; }
|
|
164
|
+
function compactRecord(record) { return Object.fromEntries(Object.entries(record).filter(([, value]) => value !== undefined && (!Array.isArray(value) || value.length > 0))); }
|
|
165
|
+
|
|
166
|
+
export { promiseCombinatorContextReasonCodes, promiseCombinatorEvidenceRecords };
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
function reachabilityOrderEvidence(lines, lineNumber) {
|
|
2
|
+
if (!Array.isArray(lines) || lineNumber <= 1) return [];
|
|
3
|
+
const targetDepth = statementDepthBeforeLine(lines, lineNumber);
|
|
4
|
+
for (let index = lineNumber - 2; index >= 0; index -= 1) {
|
|
5
|
+
const line = lines[index] ?? '', depth = statementDepthBeforeLine(lines, index + 1);
|
|
6
|
+
if (depth < targetDepth) break;
|
|
7
|
+
if (depth > targetDepth || isIgnorableReachabilityLine(line)) continue;
|
|
8
|
+
if (sameDepthControlBoundary(line)) break;
|
|
9
|
+
const completion = unconditionalCompletionRecord(line, index + 1);
|
|
10
|
+
if (completion) return [compactRecord({ kind: 'same-block-unreachable-after-completion', status: 'unreachable', proofLevel: 'lexical-same-block-completion', targetLine: lineNumber, completionKind: completion.kind, completionLine: completion.line, completionText: completion.text, completionLabel: completion.label, staticReachabilityEvidence: true, fullPathReachabilityClaim: false, runtimeEquivalenceClaim: false, semanticEquivalenceClaim: false })];
|
|
11
|
+
}
|
|
12
|
+
const branch = exhaustiveIfElseCompletionRecord(lines, lineNumber, targetDepth);
|
|
13
|
+
if (branch) return [branch];
|
|
14
|
+
const switchCompletion = exhaustiveSwitchCompletionRecord(lines, lineNumber, targetDepth);
|
|
15
|
+
if (switchCompletion) return [switchCompletion];
|
|
16
|
+
const tryFinallyCompletion = tryFinallyCompletionRecord(lines, lineNumber, targetDepth);
|
|
17
|
+
if (tryFinallyCompletion) return [tryFinallyCompletion];
|
|
18
|
+
const nestedBlockCompletion = nestedBlockCompletionRecord(lines, lineNumber, targetDepth);
|
|
19
|
+
return nestedBlockCompletion ? [nestedBlockCompletion] : [];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const nestedPathCompletionMaxDepth = 2;
|
|
23
|
+
|
|
24
|
+
function unconditionalCompletionRecord(line, lineNumber) {
|
|
25
|
+
let text = stripLineCommentOutsideStrings(line).trim();
|
|
26
|
+
if (!text || text.startsWith('/*') || text.startsWith('*')) return undefined;
|
|
27
|
+
while (/^[A-Za-z_$][\w$]*\s*:\s*/.test(text) && !/^(?:case|default)\b/.test(text)) text = text.replace(/^[A-Za-z_$][\w$]*\s*:\s*/, '').trim();
|
|
28
|
+
const match = /^(return|throw|break|continue)\b\s*([A-Za-z_$][\w$]*)?/.exec(text);
|
|
29
|
+
return match ? compactRecord({ kind: match[1], line: lineNumber, label: (match[1] === 'break' || match[1] === 'continue') ? match[2] : undefined, text: normalizeOrderEvidenceText(text.slice(0, statementEnd(text, 0))) }) : undefined;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function exhaustiveIfElseCompletionRecord(lines, lineNumber, targetDepth, remainingDepth = nestedPathCompletionMaxDepth) {
|
|
33
|
+
const closeElseLine = previousCodeLine(lines, lineNumber - 1);
|
|
34
|
+
if (!closeElseLine || statementDepthBeforeLine(lines, closeElseLine.lineNumber) !== targetDepth || !/^\s*}\s*$/.test(stripLineCommentOutsideStrings(closeElseLine.text))) return undefined;
|
|
35
|
+
const elseStart = findBranchStartLine(lines, closeElseLine.lineNumber - 1, targetDepth, 'else');
|
|
36
|
+
if (!elseStart) return undefined;
|
|
37
|
+
const branches = [{ start: elseStart, closeLine: closeElseLine.lineNumber }];
|
|
38
|
+
let previousCloseLine = previousBranchCloseLine(lines, elseStart, targetDepth);
|
|
39
|
+
while (previousCloseLine) {
|
|
40
|
+
const start = findBranchStartLine(lines, previousCloseLine - 1, targetDepth);
|
|
41
|
+
if (!start) return undefined;
|
|
42
|
+
branches.unshift({ start, closeLine: previousCloseLine });
|
|
43
|
+
if (start.branchKind === 'if') break;
|
|
44
|
+
previousCloseLine = previousBranchCloseLine(lines, start, targetDepth);
|
|
45
|
+
}
|
|
46
|
+
if (branches[0]?.start.branchKind !== 'if') return undefined;
|
|
47
|
+
const completions = branches.map((branch) => lastTopLevelCompletionInBlock(lines, branch.start.lineNumber + 1, branch.closeLine - 1, targetDepth + 1, remainingDepth));
|
|
48
|
+
if (completions.some((completion) => !completion)) return undefined;
|
|
49
|
+
const elseIfLines = branches.filter((branch) => branch.start.branchKind === 'else-if').map((branch) => branch.start.lineNumber);
|
|
50
|
+
const completionKinds = completions.map(completionKind);
|
|
51
|
+
const completionTexts = completions.map(completionText);
|
|
52
|
+
const boundedNestedPathEvidence = completions.some(completionUsesBoundedNestedPath);
|
|
53
|
+
return compactRecord({ kind: elseIfLines.length ? 'exhaustive-if-chain-unreachable-after-completion' : 'exhaustive-if-else-unreachable-after-completion', status: 'unreachable', proofLevel: boundedNestedPathEvidence ? (elseIfLines.length ? 'lexical-if-chain-bounded-nested-completion' : 'lexical-if-else-bounded-nested-completion') : (elseIfLines.length ? 'lexical-if-chain-completion' : 'lexical-if-else-completion'), targetLine: lineNumber, ifLine: branches[0].start.lineNumber, elseLine: elseStart.lineNumber, elseIfLines: elseIfLines.length ? elseIfLines : undefined, branchLineNumbers: branches.map((branch) => branch.start.lineNumber), completionKind: completionKinds.every((kind) => kind === completionKinds[0]) ? completionKinds[0] : 'mixed', completionText: completionTexts.join(' | '), branchCompletionKinds: completionKinds, branchCompletionTexts: completionTexts, branchCompletionProofLevels: boundedNestedPathEvidence ? completions.map(completionProofLevel) : undefined, boundedNestedPathEvidence: boundedNestedPathEvidence || undefined, staticReachabilityEvidence: true, fullPathReachabilityClaim: false, runtimeEquivalenceClaim: false, semanticEquivalenceClaim: false });
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function findBranchStartLine(lines, startLineNumber, targetDepth, expectedKind) {
|
|
57
|
+
for (let lineNumber = startLineNumber; lineNumber >= 1; lineNumber -= 1) {
|
|
58
|
+
if (statementDepthBeforeLine(lines, lineNumber) < targetDepth) return undefined;
|
|
59
|
+
if (statementDepthBeforeLine(lines, lineNumber) !== targetDepth) continue;
|
|
60
|
+
const text = stripLineCommentOutsideStrings(lines[lineNumber - 1]).trim();
|
|
61
|
+
const branchKind = branchStartKind(text);
|
|
62
|
+
if (branchKind && (!expectedKind || branchKind === expectedKind)) return { lineNumber, text, branchKind };
|
|
63
|
+
}
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function branchStartKind(text) { if (!/[{]\s*$/.test(text)) return undefined; if (/^if\b/.test(text)) return 'if'; if (/^}?\s*else\s+if\b/.test(text)) return 'else-if'; if (/^}?\s*else\b/.test(text)) return 'else'; return undefined; }
|
|
68
|
+
|
|
69
|
+
function previousBranchCloseLine(lines, branchStart, targetDepth) {
|
|
70
|
+
if (/^\s*}/.test(stripLineCommentOutsideStrings(branchStart.text))) return branchStart.lineNumber;
|
|
71
|
+
const closeLine = previousCodeLine(lines, branchStart.lineNumber - 1);
|
|
72
|
+
return closeLine && statementDepthBeforeLine(lines, closeLine.lineNumber) === targetDepth && /^\s*}\s*$/.test(stripLineCommentOutsideStrings(closeLine.text)) ? closeLine.lineNumber : undefined;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function lastTopLevelCompletionInBlock(lines, startLineNumber, endLineNumber, depth, remainingDepth = nestedPathCompletionMaxDepth) {
|
|
76
|
+
const tail = previousCodeLineInRange(lines, startLineNumber, endLineNumber);
|
|
77
|
+
if (!tail || statementDepthBeforeLine(lines, tail.lineNumber) !== depth) return undefined;
|
|
78
|
+
const completion = unconditionalCompletionRecord(tail.text, tail.lineNumber);
|
|
79
|
+
if (completion) return completion;
|
|
80
|
+
return remainingDepth > 0 ? nestedTailCompletionRecord(lines, tail.lineNumber, depth, remainingDepth - 1) : undefined;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function nestedTailCompletionRecord(lines, closeLineNumber, targetDepth, remainingDepth) {
|
|
84
|
+
const closeLine = { lineNumber: closeLineNumber, text: lines[closeLineNumber - 1] };
|
|
85
|
+
if (!/^\s*}\s*$/.test(stripLineCommentOutsideStrings(closeLine.text))) return undefined;
|
|
86
|
+
return exhaustiveIfElseCompletionRecord(lines, closeLineNumber + 1, targetDepth, remainingDepth)
|
|
87
|
+
?? exhaustiveSwitchCompletionRecord(lines, closeLineNumber + 1, targetDepth, remainingDepth)
|
|
88
|
+
?? tryFinallyCompletionRecord(lines, closeLineNumber + 1, targetDepth, remainingDepth)
|
|
89
|
+
?? nestedBlockCompletionRecord(lines, closeLineNumber + 1, targetDepth, remainingDepth);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function exhaustiveSwitchCompletionRecord(lines, lineNumber, targetDepth, remainingDepth = nestedPathCompletionMaxDepth) {
|
|
93
|
+
const closeLine = previousCodeLine(lines, lineNumber - 1);
|
|
94
|
+
if (!closeLine || statementDepthBeforeLine(lines, closeLine.lineNumber) !== targetDepth || !/^\s*}\s*$/.test(stripLineCommentOutsideStrings(closeLine.text))) return undefined;
|
|
95
|
+
const switchStart = findMatchingSwitchStartLine(lines, closeLine.lineNumber, targetDepth);
|
|
96
|
+
if (!switchStart) return undefined;
|
|
97
|
+
|
|
98
|
+
const labels = switchCaseLabels(lines, switchStart.lineNumber + 1, closeLine.lineNumber - 1, targetDepth + 1);
|
|
99
|
+
if (!labels.length || !labels.some((label) => label.kind === 'default')) return undefined;
|
|
100
|
+
|
|
101
|
+
const completions = labels.map((label, index) => {
|
|
102
|
+
const nextLine = labels[index + 1]?.lineNumber ?? closeLine.lineNumber;
|
|
103
|
+
return lastTopLevelCompletionInBlock(lines, label.lineNumber + 1, nextLine - 1, targetDepth + 1, remainingDepth);
|
|
104
|
+
});
|
|
105
|
+
if (completions.some((completion) => !completion || !completionKindsAllowed(completion, switchExitCompletionKinds))) return undefined;
|
|
106
|
+
|
|
107
|
+
const defaultLabel = labels.find((label) => label.kind === 'default');
|
|
108
|
+
const completionKinds = completions.map(completionKind);
|
|
109
|
+
const completionTexts = completions.map(completionText);
|
|
110
|
+
const boundedNestedPathEvidence = completions.some(completionUsesBoundedNestedPath);
|
|
111
|
+
return compactRecord({ kind: 'exhaustive-switch-unreachable-after-completion', status: 'unreachable', proofLevel: boundedNestedPathEvidence ? 'lexical-switch-default-bounded-nested-completion' : 'lexical-switch-default-completion', targetLine: lineNumber, switchLine: switchStart.lineNumber, defaultLine: defaultLabel?.lineNumber, labelLineNumbers: labels.map((label) => label.lineNumber), caseLines: labels.filter((label) => label.kind === 'case').map((label) => label.lineNumber), completionKind: completionKinds.every((kind) => kind === completionKinds[0]) ? completionKinds[0] : 'mixed', completionText: completionTexts.join(' | '), branchCompletionKinds: completionKinds, branchCompletionTexts: completionTexts, branchCompletionProofLevels: boundedNestedPathEvidence ? completions.map(completionProofLevel) : undefined, boundedNestedPathEvidence: boundedNestedPathEvidence || undefined, staticReachabilityEvidence: true, fullPathReachabilityClaim: false, runtimeEquivalenceClaim: false, semanticEquivalenceClaim: false });
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const switchExitCompletionKinds = new Set(['return', 'throw']);
|
|
115
|
+
|
|
116
|
+
function tryFinallyCompletionRecord(lines, lineNumber, targetDepth, remainingDepth = nestedPathCompletionMaxDepth) {
|
|
117
|
+
const closeLine = previousCodeLine(lines, lineNumber - 1);
|
|
118
|
+
if (!closeLine || statementDepthBeforeLine(lines, closeLine.lineNumber) !== targetDepth || !/^\s*}\s*$/.test(stripLineCommentOutsideStrings(closeLine.text))) return undefined;
|
|
119
|
+
const finallyStart = findFinallyStartLine(lines, closeLine.lineNumber - 1, targetDepth);
|
|
120
|
+
if (!finallyStart) return undefined;
|
|
121
|
+
const tryStart = findTryStartLineBeforeFinally(lines, finallyStart, targetDepth);
|
|
122
|
+
if (!tryStart) return undefined;
|
|
123
|
+
|
|
124
|
+
const completion = lastTopLevelCompletionInBlock(lines, finallyStart.lineNumber + 1, closeLine.lineNumber - 1, targetDepth + 1, remainingDepth);
|
|
125
|
+
if (!completion || !completionKindsAllowed(completion, tryFinallyExitCompletionKinds)) return undefined;
|
|
126
|
+
const boundedNestedPathEvidence = completionUsesBoundedNestedPath(completion);
|
|
127
|
+
|
|
128
|
+
return compactRecord({ kind: 'try-finally-unreachable-after-finalizer-completion', status: 'unreachable', proofLevel: boundedNestedPathEvidence ? 'lexical-try-finally-finalizer-bounded-nested-completion' : 'lexical-try-finally-finalizer-completion', targetLine: lineNumber, tryLine: tryStart.lineNumber, catchLines: tryStart.catchLines.length ? tryStart.catchLines : undefined, finallyLine: finallyStart.lineNumber, completionKind: completionKind(completion), completionLine: completionLine(completion), completionText: completionText(completion), completionProofLevel: boundedNestedPathEvidence ? completionProofLevel(completion) : undefined, boundedNestedPathEvidence: boundedNestedPathEvidence || undefined, staticReachabilityEvidence: true, fullPathReachabilityClaim: false, runtimeEquivalenceClaim: false, semanticEquivalenceClaim: false });
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const tryFinallyExitCompletionKinds = new Set(['return', 'throw']);
|
|
132
|
+
|
|
133
|
+
function nestedBlockCompletionRecord(lines, lineNumber, targetDepth, remainingDepth = nestedPathCompletionMaxDepth) {
|
|
134
|
+
const closeLine = previousCodeLine(lines, lineNumber - 1);
|
|
135
|
+
if (!closeLine || statementDepthBeforeLine(lines, closeLine.lineNumber) !== targetDepth || !/^\s*}\s*$/.test(stripLineCommentOutsideStrings(closeLine.text))) return undefined;
|
|
136
|
+
const blockStart = findPlainBlockStartLine(lines, closeLine.lineNumber, targetDepth);
|
|
137
|
+
if (!blockStart) return undefined;
|
|
138
|
+
const completion = lastTopLevelCompletionInBlock(lines, blockStart.lineNumber + 1, closeLine.lineNumber - 1, targetDepth + 1, remainingDepth);
|
|
139
|
+
if (!completion) return undefined;
|
|
140
|
+
return compactRecord({ kind: 'nested-block-unreachable-after-completion', status: 'unreachable', proofLevel: completionUsesBoundedNestedPath(completion) ? 'lexical-bounded-nested-block-nested-completion' : 'lexical-bounded-nested-block-completion', targetLine: lineNumber, blockLine: blockStart.lineNumber, completionKind: completionKind(completion), completionLine: completionLine(completion), completionText: completionText(completion), completionProofLevel: completionProofLevel(completion), boundedNestedPathEvidence: true, staticReachabilityEvidence: true, fullPathReachabilityClaim: false, runtimeEquivalenceClaim: false, semanticEquivalenceClaim: false });
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function findFinallyStartLine(lines, startLineNumber, targetDepth) {
|
|
144
|
+
for (let lineNumber = startLineNumber; lineNumber >= 1; lineNumber -= 1) {
|
|
145
|
+
const depth = statementDepthBeforeLine(lines, lineNumber);
|
|
146
|
+
if (depth < targetDepth) return undefined;
|
|
147
|
+
if (depth !== targetDepth) continue;
|
|
148
|
+
const text = stripLineCommentOutsideStrings(lines[lineNumber - 1]).trim();
|
|
149
|
+
if (/^}?\s*finally\b.*[{]\s*$/.test(text)) return { lineNumber, text };
|
|
150
|
+
if (/[{]\s*$/.test(text)) return undefined;
|
|
151
|
+
}
|
|
152
|
+
return undefined;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function findTryStartLineBeforeFinally(lines, finallyStart, targetDepth) {
|
|
156
|
+
const catchLines = [];
|
|
157
|
+
for (let lineNumber = finallyStart.lineNumber - 1; lineNumber >= 1; lineNumber -= 1) {
|
|
158
|
+
const depth = statementDepthBeforeLine(lines, lineNumber);
|
|
159
|
+
if (depth < targetDepth) return undefined;
|
|
160
|
+
if (depth !== targetDepth) continue;
|
|
161
|
+
const text = stripLineCommentOutsideStrings(lines[lineNumber - 1]).trim();
|
|
162
|
+
if (/^try\b.*[{]\s*$/.test(text)) return { lineNumber, text, catchLines };
|
|
163
|
+
if (/^}?\s*catch\b.*[{]\s*$/.test(text)) {
|
|
164
|
+
catchLines.unshift(lineNumber);
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
if (/^\s*}\s*$/.test(text)) continue;
|
|
168
|
+
return undefined;
|
|
169
|
+
}
|
|
170
|
+
return undefined;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function findPlainBlockStartLine(lines, closeLineNumber, targetDepth) {
|
|
174
|
+
for (let lineNumber = closeLineNumber - 1; lineNumber >= 1; lineNumber -= 1) {
|
|
175
|
+
const depth = statementDepthBeforeLine(lines, lineNumber);
|
|
176
|
+
if (depth < targetDepth) return undefined;
|
|
177
|
+
if (depth !== targetDepth) continue;
|
|
178
|
+
const text = stripLineCommentOutsideStrings(lines[lineNumber - 1]).trim();
|
|
179
|
+
if (plainBlockStartLine(text)) return { lineNumber, text };
|
|
180
|
+
if (/[{]\s*$/.test(text)) return undefined;
|
|
181
|
+
}
|
|
182
|
+
return undefined;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function plainBlockStartLine(text) { return /^(?:[A-Za-z_$][\w$]*\s*:\s*)?\{\s*$/.test(text); }
|
|
186
|
+
|
|
187
|
+
function findMatchingSwitchStartLine(lines, closeLineNumber, targetDepth) {
|
|
188
|
+
for (let lineNumber = closeLineNumber - 1; lineNumber >= 1; lineNumber -= 1) {
|
|
189
|
+
const depth = statementDepthBeforeLine(lines, lineNumber);
|
|
190
|
+
if (depth < targetDepth) break;
|
|
191
|
+
if (depth !== targetDepth) continue;
|
|
192
|
+
const text = stripLineCommentOutsideStrings(lines[lineNumber - 1]).trim();
|
|
193
|
+
if (/[{]\s*$/.test(text)) return /^switch\b/.test(text) ? { lineNumber, text } : undefined;
|
|
194
|
+
}
|
|
195
|
+
return undefined;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function switchCaseLabels(lines, startLineNumber, endLineNumber, depth) {
|
|
199
|
+
const labels = [];
|
|
200
|
+
for (let lineNumber = startLineNumber; lineNumber <= endLineNumber; lineNumber += 1) {
|
|
201
|
+
if (statementDepthBeforeLine(lines, lineNumber) !== depth) continue;
|
|
202
|
+
const text = stripLineCommentOutsideStrings(lines[lineNumber - 1]).trim();
|
|
203
|
+
const kind = switchCaseLabelKind(text);
|
|
204
|
+
if (kind) labels.push({ kind, lineNumber, text });
|
|
205
|
+
}
|
|
206
|
+
return labels;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function switchCaseLabelKind(text) { if (/^case\b.*:\s*$/.test(text)) return 'case'; if (/^default\s*:\s*$/.test(text)) return 'default'; return undefined; }
|
|
210
|
+
|
|
211
|
+
function previousCodeLine(lines, lineNumber) { for (let index = lineNumber - 1; index >= 0; index -= 1) if (!isIgnorableReachabilityLine(lines[index])) return { lineNumber: index + 1, text: lines[index] }; return undefined; }
|
|
212
|
+
|
|
213
|
+
function previousCodeLineInRange(lines, startLineNumber, endLineNumber) { for (let index = endLineNumber - 1; index >= startLineNumber - 1; index -= 1) if (!isIgnorableReachabilityLine(lines[index])) return { lineNumber: index + 1, text: lines[index] }; return undefined; }
|
|
214
|
+
|
|
215
|
+
function completionKind(completion) { return completion?.completionKind ?? completion?.kind; }
|
|
216
|
+
|
|
217
|
+
function completionLine(completion) { return completion?.completionLine ?? completion?.line; }
|
|
218
|
+
|
|
219
|
+
function completionText(completion) { return completion?.completionText ?? completion?.text; }
|
|
220
|
+
|
|
221
|
+
function completionProofLevel(completion) { return completion?.proofLevel ?? 'lexical-same-block-completion'; }
|
|
222
|
+
|
|
223
|
+
function completionUsesBoundedNestedPath(completion) { return Boolean(completion) && (completion.boundedNestedPathEvidence === true || completion.line === undefined); }
|
|
224
|
+
|
|
225
|
+
function completionKindsAllowed(completion, allowedKinds) { const kinds = completionExitKinds(completion); return kinds.length > 0 && kinds.every((kind) => allowedKinds.has(kind)); }
|
|
226
|
+
|
|
227
|
+
function completionExitKinds(completion) {
|
|
228
|
+
const branchKinds = completion?.branchCompletionKinds;
|
|
229
|
+
if (Array.isArray(branchKinds) && branchKinds.length && branchKinds.every((kind) => kind !== 'mixed')) return branchKinds;
|
|
230
|
+
const kind = completionKind(completion);
|
|
231
|
+
return kind && kind !== 'mixed' ? [kind] : [];
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function statementDepthBeforeLine(lines, lineNumber) {
|
|
235
|
+
let depth = 0;
|
|
236
|
+
for (let index = 0; index < lineNumber - 1; index += 1) depth = statementDepthAfterLine(lines[index], depth);
|
|
237
|
+
return Math.max(0, depth - leadingCloseBraceCount(lines[lineNumber - 1] ?? ''));
|
|
238
|
+
}
|
|
239
|
+
function statementDepthAfterLine(line, depth) { const leadingClose = leadingCloseBraceCount(line), adjusted = Math.max(0, depth - leadingClose); return Math.max(0, adjusted + openBraceCount(line) - Math.max(0, closeBraceCount(line) - leadingClose)); }
|
|
240
|
+
function isIgnorableReachabilityLine(line) { const text = stripLineCommentOutsideStrings(line).trim(); return !text || text.startsWith('/*') || text.startsWith('*'); }
|
|
241
|
+
function sameDepthControlBoundary(line) { const text = stripLineCommentOutsideStrings(line).trim(); return /^(?:case\b|default\s*:|catch\b|finally\b|else\b)/.test(text) || /^}\s*(?:else|catch|finally)\b/.test(text); }
|
|
242
|
+
function stripLineCommentOutsideStrings(line) {
|
|
243
|
+
const text = String(line ?? '');
|
|
244
|
+
let quote, escaped = false;
|
|
245
|
+
for (let index = 0; index < text.length - 1; index += 1) {
|
|
246
|
+
const char = text[index], next = text[index + 1];
|
|
247
|
+
if (quote) { if (escaped) escaped = false; else if (char === '\\') escaped = true; else if (char === quote) quote = undefined; continue; }
|
|
248
|
+
if (char === '\'' || char === '"' || char === '`') { quote = char; continue; }
|
|
249
|
+
if (char === '/' && next === '/') return text.slice(0, index);
|
|
250
|
+
}
|
|
251
|
+
return text;
|
|
252
|
+
}
|
|
253
|
+
function leadingCloseBraceCount(line) { const match = String(line ?? '').match(/^\s*}+/); return match ? match[0].replace(/\s/g, '').length : 0; }
|
|
254
|
+
function openBraceCount(line) { return countCharsOutsideStrings(line, '{'); }
|
|
255
|
+
function closeBraceCount(line) { return countCharsOutsideStrings(line, '}'); }
|
|
256
|
+
function countCharsOutsideStrings(line, target) {
|
|
257
|
+
let count = 0, quote, escaped = false;
|
|
258
|
+
for (const char of String(line ?? '')) {
|
|
259
|
+
if (quote) { if (escaped) escaped = false; else if (char === '\\') escaped = true; else if (char === quote) quote = undefined; continue; }
|
|
260
|
+
if (char === '\'' || char === '"' || char === '`') { quote = char; continue; }
|
|
261
|
+
if (char === target) count += 1;
|
|
262
|
+
}
|
|
263
|
+
return count;
|
|
264
|
+
}
|
|
265
|
+
function normalizeOrderEvidenceText(value) { return String(value ?? '').replace(/\s+/g, ' ').trim(); }
|
|
266
|
+
function statementEnd(line, start) { const semicolon = String(line ?? '').indexOf(';', start); return semicolon === -1 ? String(line ?? '').length : semicolon + 1; }
|
|
267
|
+
function compactRecord(record) { return Object.fromEntries(Object.entries(record).filter(([, value]) => value !== undefined && value !== '')); }
|
|
268
|
+
|
|
269
|
+
export { reachabilityOrderEvidence };
|