All files / transpiler/output/headers/adapters HeaderSymbolAdapter.ts

100% Statements 42/42
96% Branches 24/25
100% Functions 15/15
100% Lines 40/40

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 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223                                          225x   52x   86x   22x   18x   4x   2x   41x               8x                     52x     52x 52x     52x           1x           52x 27x   52x   52x                                 86x 86x     86x     86x 15x         86x                                     22x 22x   22x                           18x 18x   18x                           4x 4x   4x                             2x 2x   2x                         41x                                     2x 1x   1x          
/**
 * HeaderSymbolAdapter - Converts TSymbol to IHeaderSymbol.
 *
 * ADR-055 Phase 7: This adapter converts the TSymbol discriminated union
 * to IHeaderSymbol for header generation.
 */
 
import TSymbol from "../../../types/symbols/TSymbol";
import IHeaderSymbol from "../types/IHeaderSymbol";
import IParameterSymbol from "../../../../utils/types/IParameterSymbol";
import TypeResolver from "../../../../utils/TypeResolver";
import SymbolNameUtils from "../../../logic/symbols/cnext/utils/SymbolNameUtils";
 
/**
 * Adapter to convert TSymbol to IHeaderSymbol
 */
class HeaderSymbolAdapter {
  /**
   * Convert a TSymbol to IHeaderSymbol
   */
  static fromTSymbol(symbol: TSymbol): IHeaderSymbol {
    switch (symbol.kind) {
      case "function":
        return HeaderSymbolAdapter.convertFunction(symbol);
      case "variable":
        return HeaderSymbolAdapter.convertVariable(symbol);
      case "struct":
        return HeaderSymbolAdapter.convertStruct(symbol);
      case "enum":
        return HeaderSymbolAdapter.convertEnum(symbol);
      case "bitmap":
        return HeaderSymbolAdapter.convertBitmap(symbol);
      case "register":
        return HeaderSymbolAdapter.convertRegister(symbol);
      case "scope":
        return HeaderSymbolAdapter.convertScope(symbol);
    }
  }
 
  /**
   * Convert an array of TSymbols to IHeaderSymbols
   */
  static fromTSymbols(symbols: TSymbol[]): IHeaderSymbol[] {
    return symbols.map((s) => HeaderSymbolAdapter.fromTSymbol(s));
  }
 
  // ========================================================================
  // Private conversion methods for each TSymbol kind
  // ========================================================================
 
  private static convertFunction(
    func: import("../../../types/symbols/IFunctionSymbol").default,
  ): IHeaderSymbol {
    // Convert TType return type to string
    const returnTypeStr = TypeResolver.getTypeName(func.returnType);
 
    // Get transpiled C name (scope-prefixed)
    const cName = SymbolNameUtils.getTranspiledCName(func);
    const isGlobal = func.scope.name === "";
 
    // Convert parameters to IParameterSymbol[]
    const parameters: IParameterSymbol[] = func.parameters.map((p) => ({
      name: p.name,
      type: TypeResolver.getTypeName(p.type),
      isConst: p.isConst,
      isArray: p.isArray,
      arrayDimensions: p.arrayDimensions?.map((d) =>
        typeof d === "number" ? String(d) : d,
      ),
      isAutoConst: p.isAutoConst,
    }));
 
    // Build signature
    const paramTypes = func.parameters.map((p) =>
      TypeResolver.getTypeName(p.type),
    );
    const signature = `${returnTypeStr} ${cName}(${paramTypes.join(", ")})`;
 
    return {
      name: cName,
      kind: "function",
      type: returnTypeStr,
      isExported: func.isExported,
      parameters,
      signature,
      parent: isGlobal ? undefined : func.scope.name,
      sourceFile: func.sourceFile,
      sourceLine: func.sourceLine,
    };
  }
 
  private static convertVariable(
    variable: import("../../../types/symbols/IVariableSymbol").default,
  ): IHeaderSymbol {
    // Get transpiled C name (scope-prefixed)
    const cName = SymbolNameUtils.getTranspiledCName(variable);
    const isGlobal = variable.scope.name === "";
 
    // Convert TType to string
    const typeStr = TypeResolver.getTypeName(variable.type);
 
    // Convert dimensions to strings and resolve qualified enum access
    const arrayDimensions = variable.arrayDimensions?.map((d) =>
      typeof d === "number"
        ? String(d)
        : HeaderSymbolAdapter.resolveArrayDimension(d),
    );
 
    return {
      name: cName,
      kind: "variable",
      type: typeStr,
      isExported: variable.isExported,
      isConst: variable.isConst,
      isAtomic: variable.isAtomic,
      isArray: variable.isArray,
      arrayDimensions,
      parent: isGlobal ? undefined : variable.scope.name,
      sourceFile: variable.sourceFile,
      sourceLine: variable.sourceLine,
    };
  }
 
  private static convertStruct(
    struct: import("../../../types/symbols/IStructSymbol").default,
  ): IHeaderSymbol {
    // Get transpiled C name (scope-prefixed)
    const cName = SymbolNameUtils.getTranspiledCName(struct);
    const isGlobal = struct.scope.name === "";
 
    return {
      name: cName,
      kind: "struct",
      isExported: struct.isExported,
      parent: isGlobal ? undefined : struct.scope.name,
      sourceFile: struct.sourceFile,
      sourceLine: struct.sourceLine,
    };
  }
 
  private static convertEnum(
    enumSym: import("../../../types/symbols/IEnumSymbol").default,
  ): IHeaderSymbol {
    // Get transpiled C name (scope-prefixed)
    const cName = SymbolNameUtils.getTranspiledCName(enumSym);
    const isGlobal = enumSym.scope.name === "";
 
    return {
      name: cName,
      kind: "enum",
      isExported: enumSym.isExported,
      parent: isGlobal ? undefined : enumSym.scope.name,
      sourceFile: enumSym.sourceFile,
      sourceLine: enumSym.sourceLine,
    };
  }
 
  private static convertBitmap(
    bitmap: import("../../../types/symbols/IBitmapSymbol").default,
  ): IHeaderSymbol {
    // Get transpiled C name (scope-prefixed)
    const cName = SymbolNameUtils.getTranspiledCName(bitmap);
    const isGlobal = bitmap.scope.name === "";
 
    return {
      name: cName,
      kind: "bitmap",
      type: bitmap.backingType,
      isExported: bitmap.isExported,
      parent: isGlobal ? undefined : bitmap.scope.name,
      sourceFile: bitmap.sourceFile,
      sourceLine: bitmap.sourceLine,
    };
  }
 
  private static convertRegister(
    register: import("../../../types/symbols/IRegisterSymbol").default,
  ): IHeaderSymbol {
    // Get transpiled C name (scope-prefixed)
    const cName = SymbolNameUtils.getTranspiledCName(register);
    const isGlobal = register.scope.name === "";
 
    return {
      name: cName,
      kind: "register",
      isExported: register.isExported,
      parent: isGlobal ? undefined : register.scope.name,
      sourceFile: register.sourceFile,
      sourceLine: register.sourceLine,
    };
  }
 
  private static convertScope(
    scope: import("../../../types/symbols/IScopeSymbol").default,
  ): IHeaderSymbol {
    return {
      name: scope.name,
      kind: "scope",
      isExported: scope.isExported,
      sourceFile: scope.sourceFile,
      sourceLine: scope.sourceLine,
    };
  }
 
  /**
   * Convert an array dimension string to C-compatible format.
   * Converts qualified enum access (e.g., "EColor.COUNT") to C-style ("EColor_COUNT").
   * @param dim - The dimension string, may contain qualified enum access
   * @returns C-compatible dimension string with dots replaced by underscores
   * @example resolveArrayDimension("EColor.COUNT") => "EColor_COUNT"
   * @example resolveArrayDimension("10") => "10"
   */
  private static resolveArrayDimension(dim: string): string {
    // Qualified enum access (e.g., "EColor.COUNT") - convert dots to underscores
    if (dim.includes(".")) {
      return dim.replaceAll(".", "_");
    }
    return dim;
  }
}
 
export default HeaderSymbolAdapter;