All files / transpiler/data InputExpansion.ts

100% Statements 19/19
100% Branches 6/6
100% Functions 3/3
100% Lines 19/19

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                  13x             13x               5x   5x 7x   7x 1x     6x 6x     4x                       16x 16x     16x 8x       8x 5x     3x                         82x 82x          
import { resolve, extname, basename } from "node:path";
import { existsSync } from "node:fs";
 
/**
 * Input expansion for C-Next CLI
 *
 * Validates and resolves file paths for compilation.
 */
class InputExpansion {
  private static readonly CPP_EXTENSIONS = [
    ".c",
    ".cpp",
    ".cc",
    ".cxx",
    ".c++",
  ];
  private static readonly CNEXT_EXTENSIONS = [".cnx", ".cnext"];
  /**
   * Expand inputs (files) to list of .cnx files
   *
   * @param inputs - Array of file paths
   * @returns Array of .cnx file paths
   */
  static expandInputs(inputs: string[]): string[] {
    const files: string[] = [];
 
    for (const input of inputs) {
      const resolvedPath = resolve(input);
 
      if (!existsSync(resolvedPath)) {
        throw new Error(`Input not found: ${input}`);
      }
 
      this.validateFileExtension(resolvedPath);
      files.push(resolvedPath);
    }
 
    return Array.from(new Set(files));
  }
 
  /**
   * Validate file extension
   *
   * Accepts: .cnx, .cnext, .c, .cpp, .cc, .cxx, .c++
   *
   * @param path - File path to validate
   * @throws Error if extension is invalid
   */
  static validateFileExtension(path: string): void {
    const ext = extname(path);
    const fileName = basename(path);
 
    // Accept C-Next source files
    if (InputExpansion.CNEXT_EXTENSIONS.includes(ext)) {
      return;
    }
 
    // Accept C/C++ entry point files
    if (InputExpansion.CPP_EXTENSIONS.includes(ext)) {
      return;
    }
 
    throw new Error(
      `Invalid file extension '${ext}' for file '${fileName}'. ` +
        `C-Next only accepts .cnx, .cnext, .c, .cpp, .cc, .cxx, or .c++ files.`,
    );
  }
 
  /**
   * Check if a file is a C/C++ entry point
   *
   * @param path - File path to check
   * @returns true if the file has a C/C++ extension
   */
  static isCppEntryPoint(path: string): boolean {
    const ext = extname(path);
    return InputExpansion.CPP_EXTENSIONS.includes(ext);
  }
}
 
export default InputExpansion;