Skip to content

⬅️ Back to Table of Contents

📄 assertionFunctionUtils

📊 Analysis Summary

Metric Count
🔧 Functions 2
📦 Imports 3

📚 Table of Contents

🛠️ File Location:

📂 packages/eslint-plugin/src/util/assertionFunctionUtils.ts

📦 Imports

Name Source
ParserServicesWithTypeInformation @typescript-eslint/utils
TSESTree @typescript-eslint/utils
AST_NODE_TYPES @typescript-eslint/utils

Functions

findTruthinessAssertedArgument(services: ParserServicesWithTypeInformation, node: TSESTree.CallExpression): TSESTree.Expression | undefined

Inspect a call expression to see if it's a call to an assertion function. If it is, return the node of the argument that is asserted.

Raw JSDoc
/**
 * Inspect a call expression to see if it's a call to an assertion function.
 * If it is, return the node of the argument that is asserted.
 */

Calls:

  • checkableArguments.push
  • services.program.getTypeChecker
  • services.getResolvedSignature
  • checker.getTypePredicateOfSignature
  • checkableArguments.at

Internal Comments:

// If the call looks like `assert(expr1, expr2, ...c, d, e, f)`, then we can (x2)
// only care if `expr1` or `expr2` is asserted, since anything that happens (x2)
// within or after a spread argument is out of scope to reason about. (x2)
// nothing to do

Code
export function findTruthinessAssertedArgument(
  services: ParserServicesWithTypeInformation,
  node: TSESTree.CallExpression,
): TSESTree.Expression | undefined {
  // If the call looks like `assert(expr1, expr2, ...c, d, e, f)`, then we can
  // only care if `expr1` or `expr2` is asserted, since anything that happens
  // within or after a spread argument is out of scope to reason about.
  const checkableArguments: TSESTree.Expression[] = [];
  for (const argument of node.arguments) {
    if (argument.type === AST_NODE_TYPES.SpreadElement) {
      break;
    }
    checkableArguments.push(argument);
  }

  // nothing to do
  if (checkableArguments.length === 0) {
    return undefined;
  }

  const checker = services.program.getTypeChecker();
  const signature = services.getResolvedSignature(node);

  if (signature == null) {
    return undefined;
  }

  const firstTypePredicateResult =
    checker.getTypePredicateOfSignature(signature);

  if (firstTypePredicateResult == null) {
    return undefined;
  }

  const { kind, parameterIndex, type } = firstTypePredicateResult;
  if (!(kind === ts.TypePredicateKind.AssertsIdentifier && type == null)) {
    return undefined;
  }

  return checkableArguments.at(parameterIndex);
}

findTypeGuardAssertedArgument(services: ParserServicesWithTypeInformation, node: TSESTree.CallExpression): | { argument: TSESTree.Expression; asserts: boolean; type: …

Inspect a call expression to see if it's a call to an assertion function. If it is, return the node of the argument that is asserted and other useful info.

Raw JSDoc
/**
 * Inspect a call expression to see if it's a call to an assertion function.
 * If it is, return the node of the argument that is asserted and other useful info.
 */

Calls:

  • checkableArguments.push
  • services.program.getTypeChecker
  • services.getResolvedSignature
  • checker.getTypePredicateOfSignature

Internal Comments:

// If the call looks like `assert(expr1, expr2, ...c, d, e, f)`, then we can (x2)
// only care if `expr1` or `expr2` is asserted, since anything that happens (x2)
// within or after a spread argument is out of scope to reason about. (x2)
// nothing to do

Code
export function findTypeGuardAssertedArgument(
  services: ParserServicesWithTypeInformation,
  node: TSESTree.CallExpression,
):
  | {
      argument: TSESTree.Expression;
      asserts: boolean;
      type: ts.Type;
    }
  | undefined {
  // If the call looks like `assert(expr1, expr2, ...c, d, e, f)`, then we can
  // only care if `expr1` or `expr2` is asserted, since anything that happens
  // within or after a spread argument is out of scope to reason about.
  const checkableArguments: TSESTree.Expression[] = [];
  for (const argument of node.arguments) {
    if (argument.type === AST_NODE_TYPES.SpreadElement) {
      break;
    }
    checkableArguments.push(argument);
  }

  // nothing to do
  if (checkableArguments.length === 0) {
    return undefined;
  }

  const checker = services.program.getTypeChecker();
  const callSignature = services.getResolvedSignature(node);

  if (callSignature == null) {
    return undefined;
  }

  const typePredicateInfo = checker.getTypePredicateOfSignature(callSignature);

  if (typePredicateInfo == null) {
    return undefined;
  }

  const { kind, parameterIndex, type } = typePredicateInfo;
  if (!(
    (kind === ts.TypePredicateKind.AssertsIdentifier ||
      kind === ts.TypePredicateKind.Identifier) &&
    type != null
  )) {
    return undefined;
  }

  if (parameterIndex >= checkableArguments.length) {
    return undefined;
  }

  return {
    argument: checkableArguments[parameterIndex],
    asserts: kind === ts.TypePredicateKind.AssertsIdentifier,
    type,
  };
}

Generated by Syntax Scribe