All files / transpiler/logic/symbols/cnext/utils TypeUtils.ts

96.77% Statements 30/31
89.28% Branches 25/28
100% Functions 6/6
100% Lines 29/29

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 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113                            9x 9x             42x 42x             92x 78x   14x 10x     4x 4x 4x                                 2392x     2392x 9x         2383x 7x       2376x 7x 14x       2369x 195x       2174x 1033x       1141x 42x         1099x 92x       1007x                   37x          
/**
 * TypeUtils - Utilities for extracting and converting C-Next types.
 */
 
import * as Parser from "../../../parser/grammar/CNextParser";
import CNEXT_TO_C_TYPE_MAP from "../../../../../utils/constants/TypeMappings";
 
/**
 * Resolve scoped type (this.Type) to full name.
 */
function resolveScopedType(
  scopedTypeCtx: Parser.ScopedTypeContext,
  scopeName?: string,
): string {
  const typeName = scopedTypeCtx.IDENTIFIER().getText();
  return scopeName ? `${scopeName}_${typeName}` : typeName;
}
 
/**
 * Resolve string type with optional capacity.
 */
function resolveStringType(stringCtx: Parser.StringTypeContext): string {
  const intLiteral = stringCtx.INTEGER_LITERAL();
  return intLiteral ? `string<${intLiteral.getText()}>` : "string";
}
 
/**
 * Extract inner type from arrayType context.
 */
function resolveArrayInnerType(arrayTypeCtx: Parser.ArrayTypeContext): string {
  if (arrayTypeCtx.primitiveType()) {
    return arrayTypeCtx.primitiveType()!.getText();
  }
  if (arrayTypeCtx.userType()) {
    return arrayTypeCtx.userType()!.getText();
  }
  // Fallback for other nested types - strip the dimension part
  const text = arrayTypeCtx.getText();
  const bracketIdx = text.indexOf("[");
  return bracketIdx > 0 ? text.substring(0, bracketIdx) : text;
}
 
class TypeUtils {
  /**
   * Extract the type name from a type context.
   * Handles scoped types (this.Type), qualified types (Scope.Type),
   * and simple types.
   *
   * @param ctx The type context (may be null)
   * @param scopeName Optional current scope for this.Type resolution
   * @returns The resolved type name
   */
  static getTypeName(
    ctx: Parser.TypeContext | null,
    scopeName?: string,
  ): string {
    Iif (!ctx) return "void";
 
    // Handle this.Type for scoped types (e.g., this.State -> Motor_State)
    if (ctx.scopedType()) {
      return resolveScopedType(ctx.scopedType()!, scopeName);
    }
 
    // Issue #478: Handle global.Type for global types inside scope
    // global.ECategory -> ECategory (just the type name, no scope prefix)
    if (ctx.globalType()) {
      return ctx.globalType()!.IDENTIFIER().getText();
    }
 
    // Handle Scope.Type from outside scope (e.g., Motor.State -> Motor_State)
    if (ctx.qualifiedType()) {
      const identifiers = ctx.qualifiedType()!.IDENTIFIER();
      return identifiers.map((id) => id.getText()).join("_");
    }
 
    // Handle user-defined types
    if (ctx.userType()) {
      return ctx.userType()!.getText();
    }
 
    // Handle primitive types
    if (ctx.primitiveType()) {
      return ctx.primitiveType()!.getText();
    }
 
    // Handle string types - preserve capacity for validation (Issue #139)
    if (ctx.stringType()) {
      return resolveStringType(ctx.stringType()!);
    }
 
    // Handle arrayType: Type[size] - extract the inner type without dimension
    // The dimension is tracked separately in arrayDimensions
    if (ctx.arrayType()) {
      return resolveArrayInnerType(ctx.arrayType()!);
    }
 
    // Fallback
    return ctx.getText();
  }
 
  /**
   * Convert a C-Next type name to its C equivalent.
   *
   * @param typeName The C-Next type name
   * @returns The C type name
   */
  static cnextTypeToCType(typeName: string): string {
    return CNEXT_TO_C_TYPE_MAP[typeName] ?? typeName;
  }
}
 
export default TypeUtils;