All files noLetRule.ts

100% Statements 33/33
94.44% Branches 17/18
100% Functions 7/7
100% Lines 30/30
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 1031x 1x 1x   1x 1x 4x     4x       1x           358x 358x 358x             358x 29x 29x   329x             358x         18x       18x           18x 18x     340x             47x   44x             44x 50x 50x             36x                       36x     44x   3x    
import * as ts from "typescript";
import * as Lint from "tslint";
import * as Shared from "./readonly-shared";
 
export class Rule extends Lint.Rules.AbstractRule {
  public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
    return this.applyWithFunction(
      sourceFile,
      (ctx: Lint.WalkContext<Shared.Options>) =>
        Shared.walk(ctx, checkNode, "Unexpected let, use const instead."),
      Shared.parseOptions(this.ruleArguments)
    );
  }
}
 
function checkNode(
  node: ts.Node,
  ctx: Lint.WalkContext<Shared.Options>
): ReadonlyArray<Shared.InvalidNode> {
  const variableStatementFailures = chectVariableStatement(node, ctx);
  const forStatementsFailures = checkForStatements(node, ctx);
  return [...variableStatementFailures, ...forStatementsFailures];
}
 
function chectVariableStatement(
  node: ts.Node,
  ctx: Lint.WalkContext<Shared.Options>
): ReadonlyArray<Shared.InvalidNode> {
  if (node.kind === ts.SyntaxKind.VariableStatement) {
    const variableStatementNode: ts.VariableStatement = node as ts.VariableStatement;
    return checkDeclarationList(variableStatementNode.declarationList, ctx);
  }
  return [];
}
 
function checkForStatements(
  node: ts.Node,
  ctx: Lint.WalkContext<Shared.Options>
): ReadonlyArray<Shared.InvalidNode> {
  if (
    node.kind === ts.SyntaxKind.ForStatement ||
    node.kind === ts.SyntaxKind.ForInStatement ||
    node.kind === ts.SyntaxKind.ForOfStatement
  ) {
    const forStatmentNode = node as
      | ts.ForStatement
      | ts.ForInStatement
      | ts.ForOfStatement;
    Eif (
      forStatmentNode.initializer &&
      forStatmentNode.initializer.kind ===
        ts.SyntaxKind.VariableDeclarationList &&
      Lint.isNodeFlagSet(forStatmentNode.initializer, ts.NodeFlags.Let)
    ) {
      const declarationList = forStatmentNode.initializer as ts.VariableDeclarationList;
      return checkDeclarationList(declarationList, ctx);
    }
  }
  return [];
}
 
function checkDeclarationList(
  declarationList: ts.VariableDeclarationList,
  ctx: Lint.WalkContext<Shared.Options>
): ReadonlyArray<Shared.InvalidNode> {
  if (Lint.isNodeFlagSet(declarationList, ts.NodeFlags.Let)) {
    // It is a let declaration, now check each variable that is declared
    const invalidVariableDeclarationNodes = [];
    // If the declaration list contains multiple variables, eg. let x = 0, y = 1, mutableZ = 3; then
    // we should only provide one fix for the list even if two variables are invalid.
    // NOTE: When we have a mix of allowed and disallowed variables in the same DeclarationList
    // there is no sure way to know if we should do a fix or not, eg. if ignore-prefix=mutable
    // and the list is "let x, mutableZ", then "x" is invalid but "mutableZ" is valid, should we change
    // "let" to "const" or not? For now we change to const if at least one variable is invalid.
    let addFix = true;
    for (const variableDeclarationNode of declarationList.declarations) {
      if (
        !Shared.shouldIgnorePrefix(
          variableDeclarationNode,
          ctx.options,
          ctx.sourceFile
        )
      ) {
        invalidVariableDeclarationNodes.push(
          Shared.createInvalidNode(
            variableDeclarationNode,
            addFix
              ? new Lint.Replacement(
                  declarationList.getStart(ctx.sourceFile),
                  "let".length,
                  "const"
                )
              : undefined
          )
        );
        addFix = false;
      }
    }
    return invalidVariableDeclarationNodes;
  }
  return [];
}