/** * Guard info types, shared helpers, and utility functions for guard analysis. * * Contains: * - All guard info type definitions (GuardInfo, InstanceofGuardInfo, etc.) * - Shared helper functions (getGuardPropertyType, buildRenameNarrowedMap, etc.) * - Truthiness/termination analysis (isDefinitelyTerminating, isNullOrUndefined, etc.) * - resolveRuntimeUnionFrame alias */ import { IrExpression, IrStatement, IrType } from "@tsonic/frontend"; import { EmitterContext, NarrowedBinding } from "../../../types.js"; import { type NarrowedUnionMembers } from "../../../core/semantic/narrowed-union-resolution.js"; import type { CSharpExpressionAst, CSharpTypeAst } from "../../../core/format/backend-ast/types.js"; /** * Information extracted from a type predicate guard call. * Used to generate Union.IsN()/AsN() narrowing code. */ export type GuardInfo = { readonly originalName: string; readonly receiverAst: CSharpExpressionAst; readonly targetType: IrType; readonly memberN?: number; readonly memberNs: readonly number[]; readonly unionArity: number; readonly runtimeUnionArity: number; readonly candidateMemberNs: readonly number[]; readonly candidateMembers: readonly IrType[]; readonly ctxWithId: EmitterContext; readonly narrowedName: string; readonly escapedNarrow: string; readonly narrowedMap: Map; readonly sourceType?: IrType; readonly sourceMembers?: readonly IrType[]; readonly sourceCandidateMemberNs?: readonly number[]; }; /** * Information extracted from an `instanceof` condition. * Used to generate C# pattern variables for narrowing: * if (x is Foo x__is_1) { ... } */ export type InstanceofGuardInfo = { readonly originalName: string; readonly receiverAst: CSharpExpressionAst; readonly rhsTypeAst: CSharpTypeAst; readonly ctxWithId: EmitterContext; readonly ctxAfterRhs: EmitterContext; readonly narrowedName: string; readonly escapedOrig: string; readonly escapedNarrow: string; readonly narrowedMap: Map; readonly targetType?: IrType; readonly memberN?: number; readonly memberNeedsPatternCheck?: boolean; readonly receiverMayBeNullish?: boolean; readonly runtimeUnionArity?: number; readonly candidateMemberNs?: readonly number[]; readonly candidateMembers?: readonly IrType[]; }; /** * Information extracted from a discriminant literal equality check: * if (x.kind === "circle") { ... } * * Airplane-grade narrowing is only enabled when: * - x is a carried runtime union (2+ members) * - x is an identifier * - kind is a non-computed property name * - the compared value is a literal (string/number/boolean) * - exactly ONE union member's discriminant property type includes that literal * * Lowering uses union tags (not runtime property equality): * x.kind === "circle" -> x.IsN() * x.kind !== "circle" -> !x.IsN() */ export type DiscriminantEqualityGuardInfo = { readonly originalName: string; readonly propertyName: string; readonly literal: string | number | boolean; readonly operator: "===" | "!==" | "==" | "!="; readonly memberN: number; readonly unionArity: number; readonly runtimeUnionArity: number; readonly candidateMemberNs: readonly number[]; readonly candidateMembers: readonly IrType[]; readonly ctxWithId: EmitterContext; readonly narrowedName: string; readonly escapedOrig: string; readonly escapedNarrow: string; readonly narrowedMap: Map; }; /** * Information extracted from a truthy/falsy property guard: * if (result.success) { ... } * if (!result.success) { ... } * * Supports the airplane-grade case where a union member property is definitively * truthy or falsy by literal/nullish contract, and exactly one member matches the * condition branch. */ export type PropertyTruthinessGuardInfo = { readonly originalName: string; readonly propertyName: string; readonly wantTruthy: boolean; readonly memberN: number; readonly unionArity: number; readonly runtimeUnionArity: number; readonly candidateMemberNs: readonly number[]; readonly candidateMembers: readonly IrType[]; readonly ctxWithId: EmitterContext; readonly narrowedName: string; readonly escapedOrig: string; readonly escapedNarrow: string; readonly narrowedMap: Map; }; export type PropertyExistenceGuardInfo = { readonly originalName: string; readonly propertyName: string; readonly wantPresent: boolean; readonly memberN: number; readonly unionArity: number; readonly runtimeUnionArity: number; readonly candidateMemberNs: readonly number[]; readonly candidateMembers: readonly IrType[]; readonly ctxWithId: EmitterContext; readonly narrowedName: string; readonly escapedOrig: string; readonly escapedNarrow: string; readonly narrowedMap: Map; }; export type RuntimeUnionFrame = NarrowedUnionMembers; /** * Information extracted from a nullable guard condition. * Used to generate .Value access for narrowed nullable value types. */ export type NullableGuardInfo = { readonly key: string; readonly targetExpr: Extract; readonly sourceType: IrType; readonly strippedType: IrType; readonly narrowsInThen: boolean; readonly isValueType: boolean; }; /** * Check if a local nominal type (class/interface) has a property with the given TS name. */ export declare const getGuardPropertyType: (type: IrType, propertyName: string, context: EmitterContext) => IrType | undefined; export declare const extractTransparentIdentifierTarget: (expr: IrExpression) => Extract | undefined; export type PlainMemberAccessTarget = Extract & { readonly property: string; readonly isComputed: false; readonly isOptional: false; }; export declare const extractTransparentMemberAccessTarget: (expr: IrExpression) => { readonly access: PlainMemberAccessTarget; readonly receiver: Extract; } | undefined; export declare const resolveRuntimeUnionFrame: (originalName: string, unionSourceType: IrType, context: EmitterContext) => NarrowedUnionMembers | undefined; export declare const resolveGuardRuntimeUnionFrame: (originalName: string, effectiveType: IrType, identifierTarget: Extract | undefined, context: EmitterContext) => RuntimeUnionFrame | undefined; export declare const stripGlobalPrefix: (name: string) => string; export declare const buildRenameNarrowedMap: (originalName: string, narrowedName: string, memberType: IrType, sourceType: IrType | undefined, ctxWithId: EmitterContext) => Map; export declare const withoutNarrowedBinding: (context: EmitterContext, bindingKey: string) => EmitterContext; export declare const isDefinitelyTruthyLiteral: (value: string | number | boolean) => boolean; export declare const isDefinitelyFalsyType: (type: IrType, context: EmitterContext) => boolean; export declare const isDefinitelyTruthyType: (type: IrType, context: EmitterContext) => boolean; /** * Conservative check: does a statement definitely terminate control flow? * Used to apply post-if narrowing in patterns like: * if (guard(x)) return ...; * // x is now narrowed in the remainder of the block (2-member unions only) */ export declare const isDefinitelyTerminating: (stmt: IrStatement) => boolean; /** * Check if an expression represents null or undefined. * Handles both literal form (from null/undefined keyword) and identifier form * (when TypeScript parses "undefined" as an identifier rather than keyword). */ export declare const isNullOrUndefined: (expr: IrExpression) => boolean; /** * Try to extract nullable guard info from a simple comparison expression. * This is the core check for patterns like: id !== undefined, id !== null, id != null */ export declare const tryResolveSimpleNullableGuard: (condition: IrExpression, context: EmitterContext) => NullableGuardInfo | undefined; /** * Try to extract nullable guard info from a condition. * Detects patterns like: id !== undefined, id !== null, id != null * Also searches inside && (logical AND) conditions recursively. * * For compound conditions like `method === "GET" && id !== undefined`, * we search both sides of the && for a nullable guard pattern. * * Returns guard info if the condition is a null/undefined check on an identifier * with a nullable type that is a value type (needs .Value in C#). */ export declare const tryResolveNullableGuard: (condition: IrExpression, context: EmitterContext) => NullableGuardInfo | undefined; //# sourceMappingURL=guard-types.d.ts.map