All files / transpiler/logic/symbols/cnext/collectors EnumCollector.ts

100% Statements 16/16
87.5% Branches 7/8
100% Functions 1/1
100% Lines 16/16

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                                                    106x 106x 106x     106x 106x   106x 277x   277x   28x 28x   28x 1x         27x     276x 276x     105x                            
/**
 * EnumCollector - Extracts enum type declarations from parse trees.
 * ADR-017: Enums provide named integer constants with auto-increment support.
 */
 
import * as Parser from "../../../parser/grammar/CNextParser";
import ESourceLanguage from "../../../../../utils/types/ESourceLanguage";
import ESymbolKind from "../../../../../utils/types/ESymbolKind";
import IEnumSymbol from "../../types/IEnumSymbol";
import ExpressionEvaluator from "../utils/ExpressionEvaluator";
 
class EnumCollector {
  /**
   * Collect an enum declaration and return an IEnumSymbol.
   *
   * @param ctx The enum declaration context
   * @param sourceFile Source file path
   * @param scopeName Optional scope name for nested enums
   * @returns The enum symbol
   * @throws Error if any member has a negative value
   */
  static collect(
    ctx: Parser.EnumDeclarationContext,
    sourceFile: string,
    scopeName?: string,
  ): IEnumSymbol {
    const name = ctx.IDENTIFIER().getText();
    const fullName = scopeName ? `${scopeName}_${name}` : name;
    const line = ctx.start?.line ?? 0;
 
    // Collect member values with auto-increment
    const members = new Map<string, number>();
    let currentValue = 0;
 
    for (const member of ctx.enumMember()) {
      const memberName = member.IDENTIFIER().getText();
 
      if (member.expression()) {
        // Explicit value with <-
        const valueText = member.expression()!.getText();
        const value = ExpressionEvaluator.evaluateConstant(valueText);
 
        if (value < 0) {
          throw new Error(
            `Error: Negative values not allowed in enum (found ${value} in ${fullName}.${memberName})`,
          );
        }
 
        currentValue = value;
      }
 
      members.set(memberName, currentValue);
      currentValue++;
    }
 
    return {
      name: fullName,
      parent: scopeName,
      sourceFile,
      sourceLine: line,
      sourceLanguage: ESourceLanguage.CNext,
      isExported: true,
      kind: ESymbolKind.Enum,
      members,
    };
  }
}
 
export default EnumCollector;