All files / TRANSPILE/1-Analyze/helpers EnclosingFunction.ts

100% Statements 10/10
100% Branches 4/4
100% Functions 4/4
100% Lines 9/9

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                                            14x 14x 231x 219x   2x               4x 4x       2x                               2x          
/**
 * The function a node sits in, and what its parameters say.
 *
 * #1322: two rules need "is this name a parameter of the function I am in?",
 * and they need different answers from it. ADR-013 asks so E0877 can say
 * "parameter" rather than "variable"; ADR-023 asks because `sizeof` on an
 * array PARAMETER returns a pointer's size, while `sizeof` on a local array
 * returns the array's -- the same spelling, opposite answers, and the
 * difference is exactly whether it is a parameter.
 *
 * Returning the parameter itself rather than a boolean is what lets one
 * lookup serve both: a caller that only needs to know THAT it is a parameter
 * checks for null, and a caller that needs to know what KIND reads it.
 */
 
import { ParserRuleContext } from "antlr4ng";
 
import * as Parser from "../../../PARSE/2-Parse/grammar/CNextParser";
 
class EnclosingFunction {
  /** The nearest enclosing function declaration, or null at file scope. */
  static of(at: ParserRuleContext): Parser.FunctionDeclarationContext | null {
    let cursor: ParserRuleContext | null = at.parent;
    while (cursor) {
      if (cursor instanceof Parser.FunctionDeclarationContext) return cursor;
      cursor = cursor.parent;
    }
    return null;
  }
 
  /** The enclosing function's parameter of this name, or null. */
  static parameterOf(
    name: string,
    at: ParserRuleContext,
  ): Parser.ParameterContext | null {
    const fn = EnclosingFunction.of(at);
    return (
      fn
        ?.parameterList()
        ?.parameter()
        .find((p) => p.IDENTIFIER().getText() === name) ?? null
    );
  }
 
  /**
   * Whether a parameter is declared as an array.
   *
   * Only the PREFIX form `u8[4] data`, which is the one ADR-036 allows. The
   * grammar still parses the trailing form `u8 data[4]`, and a second arm here
   * accepted it -- but E0874 rejects that spelling for every parameter and
   * runs first, so the arm could not fire for any program and reddened no
   * fixture when removed. Dead code that reads as a rule is worse than absent:
   * it says the trailing form is handled here, and the reason it never arrives
   * is somewhere else entirely.
   */
  static isArrayParameter(parameter: Parser.ParameterContext): boolean {
    return parameter.type().arrayType() !== null;
  }
}
 
export default EnclosingFunction;