All files / transpiler/output/codegen/helpers SymbolLookupHelper.ts

100% Statements 26/26
100% Branches 16/16
100% Functions 10/10
100% Lines 18/18

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                                                                        54x   47x 47x 41x                       18x                               4x                             292x   289x 289x                     25x                                 128x 19x                       389x 288x                           967x 782x 776x 765x          
/**
 * SymbolLookupHelper
 *
 * Helper class for symbol table lookup operations.
 * Extracts common lookup patterns for improved testability.
 */
 
import TSymbolKind from "../../../types/symbol-kinds/TSymbolKind.js";
import ESourceLanguage from "../../../../utils/types/ESourceLanguage.js";
 
/**
 * Symbol interface for lookups
 */
interface ISymbol {
  kind: TSymbolKind;
  sourceLanguage: ESourceLanguage;
}
 
/**
 * Symbol table interface
 */
interface ISymbolTable {
  getOverloads(name: string): ISymbol[];
  getStructFields?(name: string): unknown;
}
 
class SymbolLookupHelper {
  /**
   * Check if a symbol exists with the given kind and language.
   */
  static hasSymbolWithKindAndLanguage(
    symbolTable: ISymbolTable | null | undefined,
    name: string,
    kind: TSymbolKind,
    languages: ESourceLanguage[],
  ): boolean {
    if (!symbolTable) return false;
 
    const symbols = symbolTable.getOverloads(name);
    return symbols.some(
      (sym) => sym.kind === kind && languages.includes(sym.sourceLanguage),
    );
  }
 
  /**
   * Check if a type is a C++ enum class (scoped enum).
   * Issue #304: These require explicit casts to integer types in C++.
   */
  static isCppEnumClass(
    symbolTable: ISymbolTable | null | undefined,
    typeName: string,
  ): boolean {
    return SymbolLookupHelper.hasSymbolWithKindAndLanguage(
      symbolTable,
      typeName,
      "enum",
      [ESourceLanguage.Cpp],
    );
  }
 
  /**
   * Check if a function is an external C or C++ function.
   * External functions use pass-by-value semantics.
   */
  static isExternalCFunction(
    symbolTable: ISymbolTable | null | undefined,
    name: string,
  ): boolean {
    return SymbolLookupHelper.hasSymbolWithKindAndLanguage(
      symbolTable,
      name,
      "function",
      [ESourceLanguage.C, ESourceLanguage.Cpp],
    );
  }
 
  /**
   * Check if a name refers to a namespace/scope.
   */
  static isNamespace(
    symbolTable: ISymbolTable | null | undefined,
    name: string,
  ): boolean {
    if (!symbolTable) return false;
 
    const symbols = symbolTable.getOverloads(name);
    return symbols.some((sym) => sym.kind === "namespace");
  }
 
  /**
   * Check if a function is a C-Next function (uses pass-by-reference semantics).
   * Returns true if the function is found in symbol table as C-Next.
   */
  static isCNextFunction(
    symbolTable: ISymbolTable | null | undefined,
    name: string,
  ): boolean {
    return SymbolLookupHelper.hasSymbolWithKindAndLanguage(
      symbolTable,
      name,
      "function",
      [ESourceLanguage.CNext],
    );
  }
 
  /**
   * Check if a function is a C-Next function (combined local + symbol table lookup).
   * Checks local knownFunctions set first, then falls back to symbol table.
   */
  static isCNextFunctionCombined(
    knownFunctions: ReadonlySet<string> | undefined,
    symbolTable: ISymbolTable | null | undefined,
    name: string,
  ): boolean {
    if (knownFunctions?.has(name)) return true;
    return SymbolLookupHelper.isCNextFunction(symbolTable, name);
  }
 
  /**
   * Check if a name is a known scope (combined local + symbol table lookup).
   * Checks local knownScopes set first, then falls back to symbol table.
   */
  static isKnownScope(
    knownScopes: ReadonlySet<string> | undefined,
    symbolTable: ISymbolTable | null | undefined,
    name: string,
  ): boolean {
    if (knownScopes?.has(name)) return true;
    return SymbolLookupHelper.isNamespace(symbolTable, name);
  }
 
  /**
   * Check if a type is a known struct (combined local + symbol table lookup).
   * Checks local knownStructs and knownBitmaps, then falls back to symbol table.
   * Issue #551: Bitmaps are struct-like (use pass-by-reference with -> access).
   */
  static isKnownStruct(
    knownStructs: ReadonlySet<string> | undefined,
    knownBitmaps: ReadonlySet<string> | undefined,
    symbolTable: ISymbolTable | null | undefined,
    typeName: string,
  ): boolean {
    if (knownStructs?.has(typeName)) return true;
    if (knownBitmaps?.has(typeName)) return true;
    if (symbolTable?.getStructFields?.(typeName)) return true;
    return false;
  }
}
 
export default SymbolLookupHelper;