Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | 11x 17x 7x 1x 6x 6x 6x 4x 2x 2x 4x 4x | /**
* IntegerLiteralValidator - Validates integer literals and type conversions
*
* Issue #696: Extracted from CodeGenerator to reduce cognitive complexity.
*
* Handles:
* - Checking if an expression is an integer literal
* - Validating literals fit in target type
* - Validating type conversions for narrowing/sign
*/
import LiteralUtils from "../../../../utils/LiteralUtils.js";
/**
* Dependencies for validation operations.
*/
interface IValidatorDeps {
/** Check if a type name is an integer type */
isIntegerType: (typeName: string) => boolean;
/** Validate that a literal value fits in the target type */
validateLiteralFitsType: (literal: string, typeName: string) => void;
/** Get the inferred type of an expression */
getExpressionType: (exprText: string) => string | null;
/** Validate type conversion for narrowing/sign changes */
validateTypeConversion: (
targetType: string,
sourceType: string | null,
) => void;
}
/**
* Validates integer literals and type conversions for variable initialization.
*/
class IntegerLiteralValidator {
private readonly deps: IValidatorDeps;
constructor(deps: IValidatorDeps) {
this.deps = deps;
}
/**
* Check if the given text is an integer literal.
*
* Uses LiteralUtils to check for decimal, hex, and binary formats.
*/
isIntegerLiteral(text: string): boolean {
return LiteralUtils.parseIntegerLiteral(text) !== undefined;
}
/**
* Validate an expression being assigned to an integer type.
*
* If the expression is a literal, validates it fits in the type.
* Otherwise, validates the type conversion.
*
* @param typeName - The target type name
* @param exprText - The expression text
* @param line - Source line for error messages
* @param col - Source column for error messages
* @throws Error with location if validation fails
*/
validateIntegerAssignment(
typeName: string,
exprText: string,
line: number,
col: number,
): void {
if (!this.deps.isIntegerType(typeName)) {
return;
}
const trimmedExpr = exprText.trim();
try {
if (this.isIntegerLiteral(trimmedExpr)) {
// Direct literal - validate it fits in the target type
this.deps.validateLiteralFitsType(trimmedExpr, typeName);
} else {
// Not a literal - check for narrowing/sign conversions
const sourceType = this.deps.getExpressionType(exprText);
this.deps.validateTypeConversion(typeName, sourceType);
}
} catch (validationError) {
const msg =
validationError instanceof Error
? validationError.message
: String(validationError);
throw new Error(`${line}:${col} ${msg}`, { cause: validationError });
}
}
}
export default IntegerLiteralValidator;
|