diff --git a/src/application/JavaScriptSemanticGraphBuilder.ts b/src/application/JavaScriptSemanticGraphBuilder.ts index ccd9a88d4a..069cec254e 100644 --- a/src/application/JavaScriptSemanticGraphBuilder.ts +++ b/src/application/JavaScriptSemanticGraphBuilder.ts @@ -11,6 +11,7 @@ import type { JavaScriptSemanticCallArgument, JavaScriptSemanticIr, } from "../domain/javascriptSemanticIr.js"; +import { sourceRangesEqual as rangesEqual } from "../domain/javascriptStaticAnalysisHelpers.js"; import type { JavaScriptApplicationGraph } from "../domain/javascriptApplicationGraph.js"; import type { JavaScriptArtifactAnalysis } from "./JavaScriptArtifactAnalysisTypes.js"; import type { JavaScriptArtifactFile } from "./JavaScriptArtifactFiles.js"; @@ -41,7 +42,6 @@ import { owningSemanticCallableNode, semanticFamilyStatus, semanticNodesWithinRange, - semanticRangesEqual as rangesEqual, } from "./JavaScriptSemanticGraphProjection.js"; import { addSemanticFallbackRoot as addFallbackRoot, diff --git a/src/application/JavaScriptSemanticGraphFlowProjection.ts b/src/application/JavaScriptSemanticGraphFlowProjection.ts index 51f95d8004..0cb83605bc 100644 --- a/src/application/JavaScriptSemanticGraphFlowProjection.ts +++ b/src/application/JavaScriptSemanticGraphFlowProjection.ts @@ -1,6 +1,7 @@ import { createJavaScriptSemanticGraphUnknown } from "../domain/javascriptSemanticGraph.js"; import type { JavaScriptSemanticGraphNode } from "../domain/javascriptSemanticGraph.js"; import type { JavaScriptSemanticIr } from "../domain/javascriptSemanticIr.js"; +import { sourceRangesEqual } from "../domain/javascriptStaticAnalysisHelpers.js"; import type { JavaScriptSourceRange } from "../domain/javascriptStaticAnalysisTypes.js"; import type { JavaScriptArtifactAnalysis } from "./JavaScriptArtifactAnalysisTypes.js"; import type { JavaScriptArtifactFile } from "./JavaScriptArtifactFiles.js"; @@ -15,10 +16,7 @@ import { inferredSemanticEvidenceAt, unknownSemanticEvidence, } from "./JavaScriptSemanticGraphEvidence.js"; -import { - semanticNodesWithinRange, - semanticRangesEqual, -} from "./JavaScriptSemanticGraphProjection.js"; +import { semanticNodesWithinRange } from "./JavaScriptSemanticGraphProjection.js"; /** File-local graph state needed by return, capture, and frontier projection. */ export interface SemanticFlowProjectionContext { @@ -39,7 +37,7 @@ export const semanticCallSiteAt = ( location: JavaScriptSourceRange, ): JavaScriptSemanticGraphNode | undefined => { const call = context.ir.callSites.find(({ location: candidate }) => - semanticRangesEqual(candidate, location), + sourceRangesEqual(candidate, location), ); return call === undefined ? undefined @@ -231,7 +229,7 @@ export const projectSemanticReturnValues = ( relation: "aliases", resolution: site.identityReferenceLocation !== null && - semanticRangesEqual( + sourceRangesEqual( reference.identity.source_range, site.identityReferenceLocation, ) diff --git a/src/application/JavaScriptSemanticGraphProjection.ts b/src/application/JavaScriptSemanticGraphProjection.ts index fe6327e189..7a67f20501 100644 --- a/src/application/JavaScriptSemanticGraphProjection.ts +++ b/src/application/JavaScriptSemanticGraphProjection.ts @@ -62,17 +62,6 @@ export const semanticFamilyStatus = ( return analysis.truncated_scopes === 0 ? "partial" : "unknown"; }; -/** Compare two exact semantic source ranges. */ -export const semanticRangesEqual = ( - left: JavaScriptSourceRange | null, - right: JavaScriptSourceRange, -): boolean => - left !== null && - left.start.line === right.start.line && - left.start.column === right.start.column && - left.end.line === right.end.line && - left.end.column === right.end.column; - const contains = ( outer: JavaScriptSourceRange, inner: JavaScriptSourceRange, diff --git a/src/domain/javascriptSemanticPromises.ts b/src/domain/javascriptSemanticPromises.ts index 07c08b826e..fdb34c0962 100644 --- a/src/domain/javascriptSemanticPromises.ts +++ b/src/domain/javascriptSemanticPromises.ts @@ -15,7 +15,11 @@ import { type JavaScriptSemanticAnalysisState, } from "./javascriptSemanticState.js"; import { traverseJavaScriptAst } from "./javascriptSemanticTraversal.js"; -import { compareCodePoints, range } from "./javascriptStaticAnalysisHelpers.js"; +import { + compareCodePoints, + range, + sourceRangesEqual, +} from "./javascriptStaticAnalysisHelpers.js"; type PromiseMethod = JavaScriptSemanticPromiseOperation["method"]; type PromiseKind = JavaScriptSemanticPromiseOperation["kind"]; @@ -327,7 +331,7 @@ const matchingReturnSite = ( callables .find(({ callableId: candidate }) => candidate === callableId) ?.returnSites.find(({ location: candidate }) => - rangesEqual(candidate, location), + sourceRangesEqual(candidate, location), )?.returnSiteId ?? null; const promiseSources = ( @@ -467,12 +471,3 @@ const isObviouslyNonPromise = (node: t.Node): boolean => t.isObjectExpression(node) || t.isFunction(node) || t.isClassExpression(node); - -const rangesEqual = ( - left: JavaScriptSemanticPromiseOperation["location"], - right: JavaScriptSemanticPromiseOperation["location"], -): boolean => - left.start.line === right.start.line && - left.start.column === right.start.column && - left.end.line === right.end.line && - left.end.column === right.end.column; diff --git a/src/domain/javascriptStaticAnalysisHelpers.ts b/src/domain/javascriptStaticAnalysisHelpers.ts index 35371e3d36..fdfbd215eb 100644 --- a/src/domain/javascriptStaticAnalysisHelpers.ts +++ b/src/domain/javascriptStaticAnalysisHelpers.ts @@ -388,6 +388,17 @@ export const rangeForOffsets = ( end: pointForOffset(source, end), }); +/** Compare two exact source ranges. */ +export const sourceRangesEqual = ( + left: JavaScriptSourceRange | null, + right: JavaScriptSourceRange, +): boolean => + left !== null && + left.start.line === right.start.line && + left.start.column === right.start.column && + left.end.line === right.end.line && + left.end.column === right.end.column; + const pointForOffset = (source: string, offset: number) => { const before = source.slice(0, offset); const lines = before.split("\n");