

/**
 * @fileoverview A Tsetse rule that checks the return value of certain functions
 * must be used.
 */

import * as tsutils from 'tsutils';
import * as ts from 'typescript';

import {Checker} from '../checker';
import {ErrorCode} from '../error_code';
import {AbstractRule} from '../rule';

const FAILURE_STRING = 'return value is unused.'
    + '\n\tSee http://tsetse.info/check-return-value';

// A list of well-known functions that the return value must be used. If unused
// then the function call is either a no-op (e.g. 'foo.trim()' foo is unchanged)
// or can be replaced by another (Array.map() should be replaced with a loop or
// Array.forEach() if the return value is unused).
const METHODS_TO_CHECK = new Set<string>([
  ['Array', 'concat'],
  ['Array', 'filter'],
  ['Array', 'map'],
  ['Array', 'slice'],
  ['Function', 'bind'],
  ['Object', 'create'],
  ['string', 'concat'],
  ['string', 'normalize'],
  ['string', 'padStart'],
  ['string', 'padEnd'],
  ['string', 'repeat'],
  ['string', 'slice'],
  ['string', 'split'],
  ['string', 'substr'],
  ['string', 'substring'],
  ['string', 'toLocaleLowerCase'],
  ['string', 'toLocaleUpperCase'],
  ['string', 'toLowerCase'],
  ['string', 'toUpperCase'],
  ['string', 'trim'],
].map(list => list.join('#')));

export class Rule extends AbstractRule {
  readonly ruleName = 'check-return-value';
  readonly code = ErrorCode.CHECK_RETURN_VALUE;

  // registers checkCallExpression() function on ts.CallExpression node.
  // TypeScript conformance will traverse the AST of each source file and run
  // checkCallExpression() every time it encounters a ts.CallExpression node.
  register(checker: Checker) {
    checker.on(ts.SyntaxKind.CallExpression, checkCallExpression, this.code);
  }
}

function checkCallExpression(checker: Checker, node: ts.CallExpression) {
  // Short-circuit before using the typechecker if possible, as its expensive.
  // Workaround for https://github.com/Microsoft/TypeScript/issues/27997
  if (tsutils.isExpressionValueUsed(node)) {
    return;
  }

  // Check if this CallExpression is one of the well-known functions and returns
  // a non-void value that is unused.
  const signature = checker.typeChecker.getResolvedSignature(node);
  if (signature !== undefined) {
    const returnType = checker.typeChecker.getReturnTypeOfSignature(signature);
    if (!!(returnType.flags & ts.TypeFlags.Void)) {
      return;
    }
    // Although hasCheckReturnValueJsDoc() is faster than isBlackListed(), it
    // returns false most of the time and thus isBlackListed() would have to run
    // anyway. Therefore we short-circuit hasCheckReturnValueJsDoc().
    if (!isBlackListed(node, checker.typeChecker) &&
        !hasCheckReturnValueJsDoc(node, checker.typeChecker)) {
      return;
    }

    checker.addFailureAtNode(node, FAILURE_STRING);
  }
}

function isBlackListed(node: ts.CallExpression, tc: ts.TypeChecker): boolean {
  type AccessExpression =
      ts.PropertyAccessExpression|ts.ElementAccessExpression;
  switch (node.expression.kind) {
    case ts.SyntaxKind.PropertyAccessExpression:
    case ts.SyntaxKind.ElementAccessExpression:
      // Example: foo.bar() or foo[bar]()
      // expressionNode is foo
      const nodeExpression = (node.expression as AccessExpression).expression;
      const nodeExpressionString = nodeExpression.getText();
      const nodeType = tc.getTypeAtLocation(nodeExpression);

      // nodeTypeString is the string representation of the type of foo
      let nodeTypeString = tc.typeToString(nodeType);
      if (nodeTypeString.endsWith('[]')) {
        nodeTypeString = 'Array';
      }
      if (nodeTypeString === 'ObjectConstructor') {
        nodeTypeString = 'Object';
      }
      if (tsutils.isTypeFlagSet(nodeType, ts.TypeFlags.StringLiteral)) {
        nodeTypeString = 'string';
      }

      // nodeFunction is bar
      let nodeFunction = '';
      if (tsutils.isPropertyAccessExpression(node.expression)) {
        nodeFunction = node.expression.name.getText();
      }
      if (tsutils.isElementAccessExpression(node.expression)) {
        const argument = node.expression.argumentExpression;
        if (argument !== undefined) {
          nodeFunction = argument.getText();
        }
      }

      // Check if 'foo#bar' or `${typeof foo}#bar` is in the blacklist.
      if (METHODS_TO_CHECK.has(`${nodeTypeString}#${nodeFunction}`) ||
          METHODS_TO_CHECK.has(`${nodeExpressionString}#${nodeFunction}`)) {
        return true;
      }

      // For 'str.replace(regexp|substr, newSubstr|function)' only check when
      // the second parameter is 'newSubstr'.
      if ((`${nodeTypeString}#${nodeFunction}` === 'string#replace') ||
          (`${nodeExpressionString}#${nodeFunction}` === 'string#replace')) {
        return node.arguments.length === 2 &&
            !tsutils.isFunctionWithBody(node.arguments[1]);
      }
      break;
    case ts.SyntaxKind.Identifier:
      // Example: foo()
      // We currently don't have functions of this kind in blacklist.
      const identifier = node.expression as ts.Identifier;
      if (METHODS_TO_CHECK.has(identifier.text)) {
        return true;
      }
      break;
    default:
      break;
  }
  return false;
}

function hasCheckReturnValueJsDoc(node: ts.CallExpression, tc: ts.TypeChecker) {
  let symbol = tc.getSymbolAtLocation(node.expression);
  if (symbol === undefined) {
    return false;
  }

  if (tsutils.isSymbolFlagSet(symbol, ts.SymbolFlags.Alias)) {
    symbol = tc.getAliasedSymbol(symbol);
  }

  for (const jsDocTagInfo of symbol.getJsDocTags()) {
    if (jsDocTagInfo.name === 'checkReturnValue') {
      return true;
    }
  }
  return false;
}
