mirror of
https://github.com/morluto/rea
synced 2026-10-27 06:33:32 -04:00
feat: complete REA remediation program
This commit is contained in:
@@ -0,0 +1,153 @@
|
||||
import { jsonObjectSchema, jsonValueSchema } from "../domain/jsonValue.js";
|
||||
import type {
|
||||
JavaScriptSemanticIr,
|
||||
JavaScriptSemanticCallable,
|
||||
JavaScriptSemanticModuleLink,
|
||||
} from "../domain/javascriptSemanticIr.js";
|
||||
import { flattenSemanticReturnValue } from "../domain/javascriptSemanticReturns.js";
|
||||
import type { JavaScriptSourceRange } from "../domain/javascriptStaticAnalysisTypes.js";
|
||||
import type { JavaScriptArtifactGraphCoverage } from "./JavaScriptArtifactGraphContext.js";
|
||||
import { partialReconstructionCoverage } from "./JavaScriptArtifactGraphEvidence.js";
|
||||
|
||||
const MAX_PROJECTED_RETURN_SHAPES = 32;
|
||||
const MAX_PROJECTED_RETURN_FIELDS = 64;
|
||||
const MAX_PROJECTED_PROPERTY_COVERAGE = 64;
|
||||
|
||||
export interface JavaScriptReturnShapeProjection {
|
||||
readonly properties: ReturnType<typeof jsonObjectSchema.parse>;
|
||||
readonly range: JavaScriptSourceRange;
|
||||
readonly coverage: JavaScriptArtifactGraphCoverage;
|
||||
readonly limitations: readonly string[];
|
||||
}
|
||||
|
||||
/** Project one exact export/callable link into shallow bounded graph values. */
|
||||
export const projectJavaScriptExportReturnShapes = (input: {
|
||||
readonly ir: JavaScriptSemanticIr;
|
||||
readonly link: JavaScriptSemanticModuleLink;
|
||||
readonly modulePath: string;
|
||||
readonly baseCoverage: JavaScriptArtifactGraphCoverage;
|
||||
}): JavaScriptReturnShapeProjection | null => {
|
||||
if (input.link.callableId === null || input.link.exportedName === null)
|
||||
return null;
|
||||
const callable = input.ir.callables.find(
|
||||
({ callableId }) => callableId === input.link.callableId,
|
||||
);
|
||||
if (callable === undefined) return null;
|
||||
const projection = projectReturnSites(callable);
|
||||
const projectionOmitted =
|
||||
projection.omittedSites +
|
||||
projection.omittedFields +
|
||||
projection.omittedCoverage;
|
||||
const semanticOmitted = callable.returnCoverage.omittedCount;
|
||||
const complete =
|
||||
input.baseCoverage.status === "complete" &&
|
||||
callable.returnCoverage.status === "complete" &&
|
||||
projectionOmitted === 0;
|
||||
const coverage = complete
|
||||
? input.baseCoverage
|
||||
: partialReconstructionCoverage(
|
||||
[
|
||||
...input.baseCoverage.limits,
|
||||
{
|
||||
name: "return-shape-sites",
|
||||
value: MAX_PROJECTED_RETURN_SHAPES,
|
||||
unit: "items",
|
||||
},
|
||||
{
|
||||
name: "return-shape-fields",
|
||||
value: MAX_PROJECTED_RETURN_FIELDS,
|
||||
unit: "items",
|
||||
},
|
||||
{
|
||||
name: "return-shape-property-coverage",
|
||||
value: MAX_PROJECTED_PROPERTY_COVERAGE,
|
||||
unit: "items",
|
||||
},
|
||||
],
|
||||
semanticOmitted === null ? null : semanticOmitted + projectionOmitted,
|
||||
callable.returnCoverage.status === "truncated" || projectionOmitted > 0,
|
||||
);
|
||||
const limitations = [
|
||||
...input.ir.limitations,
|
||||
"Return shapes are inferred from inert syntax and do not prove runtime behavior.",
|
||||
...(callable.returnSites.length === 0
|
||||
? [
|
||||
"No direct return value was retained; runtime return behavior remains unknown.",
|
||||
]
|
||||
: []),
|
||||
...(projectionOmitted > 0
|
||||
? ["Return-shape graph projection reached explicit retention limits."]
|
||||
: []),
|
||||
];
|
||||
return {
|
||||
properties: jsonObjectSchema.parse({
|
||||
semantic_role: "export-return-shapes",
|
||||
module_path: input.modulePath,
|
||||
exported_name: input.link.exportedName,
|
||||
callable_id: callable.callableId,
|
||||
callable_kind: callable.kind,
|
||||
static_return_shapes: projection.shapes,
|
||||
return_shape_coverage: {
|
||||
status: callable.returnCoverage.status,
|
||||
retained_return_sites: projection.shapes.length,
|
||||
omitted_return_sites:
|
||||
semanticOmitted === null
|
||||
? null
|
||||
: semanticOmitted + projection.omittedSites,
|
||||
omitted_fields: projection.omittedFields,
|
||||
omitted_property_coverage: projection.omittedCoverage,
|
||||
projection_complete: projectionOmitted === 0,
|
||||
},
|
||||
}),
|
||||
range: callable.location,
|
||||
coverage,
|
||||
limitations,
|
||||
};
|
||||
};
|
||||
|
||||
const projectReturnSites = (callable: JavaScriptSemanticCallable) => {
|
||||
let retainedFields = 0;
|
||||
let retainedCoverage = 0;
|
||||
let omittedFields = 0;
|
||||
let omittedCoverage = 0;
|
||||
const retainedSites = callable.returnSites.slice(
|
||||
0,
|
||||
MAX_PROJECTED_RETURN_SHAPES,
|
||||
);
|
||||
const shapes = retainedSites.map((site) => {
|
||||
const flattened = flattenSemanticReturnValue(site.value);
|
||||
const remainingFields = Math.max(
|
||||
0,
|
||||
MAX_PROJECTED_RETURN_FIELDS - retainedFields,
|
||||
);
|
||||
const fields = flattened.fields.slice(0, remainingFields).map((field) => ({
|
||||
...field,
|
||||
value: jsonValueSchema.parse(field.value),
|
||||
}));
|
||||
retainedFields += fields.length;
|
||||
omittedFields += flattened.fields.length - fields.length;
|
||||
const remainingCoverage = Math.max(
|
||||
0,
|
||||
MAX_PROJECTED_PROPERTY_COVERAGE - retainedCoverage,
|
||||
);
|
||||
const propertyCoverage = flattened.propertyCoverage.slice(
|
||||
0,
|
||||
remainingCoverage,
|
||||
);
|
||||
retainedCoverage += propertyCoverage.length;
|
||||
omittedCoverage +=
|
||||
flattened.propertyCoverage.length - propertyCoverage.length;
|
||||
return {
|
||||
source_range: site.location,
|
||||
value_status: site.value.status,
|
||||
fields,
|
||||
property_coverage: propertyCoverage,
|
||||
};
|
||||
});
|
||||
return {
|
||||
shapes,
|
||||
omittedSites: callable.returnSites.length - retainedSites.length,
|
||||
omittedFields,
|
||||
omittedCoverage,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user