All files / transpiler/logic/analysis runAnalyzers.ts

92.5% Statements 37/40
86.36% Branches 19/22
100% Functions 5/5
92.3% Lines 36/39

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                                                                                                              1505x 1505x 9x             1505x                               155x 155x 7x     155x 155x 1x       154x 154x             154x   154x 155x             2x       152x 152x             1x       151x 151x 1x       150x 150x 2x       148x 148x 1x       147x 147x         147x 147x             147x 147x     1x     147x        
/**
 * Run all semantic analyzers on a parsed C-Next program
 *
 * Extracted from transpiler.ts for reuse in the unified pipeline.
 * All 10 analyzers run in sequence, each returning errors that block compilation.
 */
 
import { CommonTokenStream } from "antlr4ng";
import { ProgramContext } from "../parser/grammar/CNextParser";
import ParameterNamingAnalyzer from "./ParameterNamingAnalyzer";
import StructFieldAnalyzer from "./StructFieldAnalyzer";
import InitializationAnalyzer from "./InitializationAnalyzer";
import FunctionCallAnalyzer from "./FunctionCallAnalyzer";
import NullCheckAnalyzer from "./NullCheckAnalyzer";
import DivisionByZeroAnalyzer from "./DivisionByZeroAnalyzer";
import FloatModuloAnalyzer from "./FloatModuloAnalyzer";
import ArrayIndexTypeAnalyzer from "./ArrayIndexTypeAnalyzer";
import SignedShiftAnalyzer from "./SignedShiftAnalyzer";
import CommentExtractor from "./CommentExtractor";
import ITranspileError from "../../../lib/types/ITranspileError";
import SymbolTable from "../symbols/SymbolTable";
import CodeGenState from "../../state/CodeGenState";
 
/**
 * Options for running analyzers
 */
interface IAnalyzerOptions {
  /**
   * Symbol table containing external function definitions from C/C++ headers
   * Used by FunctionCallAnalyzer to recognize external functions.
   * Falls back to CodeGenState.symbolTable if not provided.
   */
  symbolTable?: SymbolTable;
}
 
/**
 * Generic analyzer error with common fields
 */
interface IAnalyzerError {
  line: number;
  column: number;
  message: string;
  code?: string;
  rule?: string;
}
 
/**
 * Convert analyzer errors to ITranspileError format and add to accumulator.
 * Returns true if any errors were added (for early return logic).
 */
function collectErrors(
  analyzerErrors: IAnalyzerError[],
  target: ITranspileError[],
  formatMessage?: (err: IAnalyzerError) => string,
): boolean {
  const formatter = formatMessage ?? ((e) => e.message);
  for (const err of analyzerErrors) {
    target.push({
      line: err.line,
      column: err.column,
      message: formatter(err),
      severity: "error",
    });
  }
  return analyzerErrors.length > 0;
}
 
/**
 * Run all semantic analyzers on a parsed program
 *
 * @param tree - The parsed program AST
 * @param tokenStream - Token stream for comment validation
 * @param options - Optional configuration including external struct info
 * @returns Array of errors (empty if all pass)
 */
function runAnalyzers(
  tree: ProgramContext,
  tokenStream: CommonTokenStream,
  options?: IAnalyzerOptions,
): ITranspileError[] {
  const errors: ITranspileError[] = [];
  const formatWithCode = (e: IAnalyzerError) =>
    `error[${e.code}]: ${e.message}`;
 
  // 1. Parameter naming validation (Issue #227: reserved naming patterns)
  const paramNamingAnalyzer = new ParameterNamingAnalyzer();
  if (collectErrors(paramNamingAnalyzer.analyze(tree), errors)) {
    return errors;
  }
 
  // 2. Struct field validation (reserved field names like 'length')
  const structFieldAnalyzer = new StructFieldAnalyzer();
  Iif (
    collectErrors(structFieldAnalyzer.analyze(tree), errors, formatWithCode)
  ) {
    return errors;
  }
 
  // 3. Initialization analysis (Rust-style use-before-init detection)
  const initAnalyzer = new InitializationAnalyzer();
  // External struct fields and symbolTable are read from CodeGenState directly
  const symbolTable = options?.symbolTable ?? CodeGenState.symbolTable;
  if (
    collectErrors(
      initAnalyzer.analyze(tree, symbolTable),
      errors,
      formatWithCode,
    )
  ) {
    return errors;
  }
 
  // 4. Call analysis (ADR-030: define-before-use)
  const callAnalyzer = new FunctionCallAnalyzer();
  if (
    collectErrors(
      callAnalyzer.analyze(tree, symbolTable),
      errors,
      formatWithCode,
    )
  ) {
    return errors;
  }
 
  // 5. NULL check analysis (ADR-047: C library interop)
  const nullAnalyzer = new NullCheckAnalyzer();
  if (collectErrors(nullAnalyzer.analyze(tree), errors, formatWithCode)) {
    return errors;
  }
 
  // 6. Division by zero analysis (ADR-051: compile-time detection)
  const divZeroAnalyzer = new DivisionByZeroAnalyzer();
  if (collectErrors(divZeroAnalyzer.analyze(tree), errors, formatWithCode)) {
    return errors;
  }
 
  // 7. Float modulo analysis (catch % with f32/f64 early)
  const floatModAnalyzer = new FloatModuloAnalyzer();
  if (collectErrors(floatModAnalyzer.analyze(tree), errors, formatWithCode)) {
    return errors;
  }
 
  // 8. Array index type validation (ADR-054: unsigned indexes only)
  const indexTypeAnalyzer = new ArrayIndexTypeAnalyzer();
  Iif (collectErrors(indexTypeAnalyzer.analyze(tree), errors, formatWithCode)) {
    return errors;
  }
 
  // 9. Signed shift validation (MISRA C:2012 Rule 10.1: no signed shifts)
  const signedShiftAnalyzer = new SignedShiftAnalyzer();
  Iif (
    collectErrors(signedShiftAnalyzer.analyze(tree), errors, formatWithCode)
  ) {
    return errors;
  }
 
  // 10. Comment validation (MISRA C:2012 Rules 3.1, 3.2) - ADR-043
  const commentExtractor = new CommentExtractor(tokenStream);
  collectErrors(
    commentExtractor.validate(),
    errors,
    (e) => `error[MISRA-${e.rule}]: ${e.message}`,
  );
 
  return errors;
}
 
export default runAnalyzers;