noSwitchCaseFallThroughRule.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. "use strict";
  2. var __extends = (this && this.__extends) || function (d, b) {
  3. for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
  4. function __() { this.constructor = d; }
  5. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  6. };
  7. var ts = require("typescript");
  8. var Lint = require("../lint");
  9. var Rule = (function (_super) {
  10. __extends(Rule, _super);
  11. function Rule() {
  12. _super.apply(this, arguments);
  13. }
  14. Rule.prototype.apply = function (sourceFile) {
  15. return this.applyWithWalker(new NoSwitchCaseFallThroughWalker(sourceFile, this.getOptions()));
  16. };
  17. Rule.FAILURE_STRING_PART = "expected a 'break' before ";
  18. return Rule;
  19. }(Lint.Rules.AbstractRule));
  20. exports.Rule = Rule;
  21. var NoSwitchCaseFallThroughWalker = (function (_super) {
  22. __extends(NoSwitchCaseFallThroughWalker, _super);
  23. function NoSwitchCaseFallThroughWalker() {
  24. _super.apply(this, arguments);
  25. }
  26. NoSwitchCaseFallThroughWalker.prototype.visitSwitchStatement = function (node) {
  27. var _this = this;
  28. var isFallingThrough = false;
  29. var switchClauses = node.caseBlock.clauses;
  30. switchClauses.forEach(function (child, i) {
  31. var kind = child.kind;
  32. if (kind === ts.SyntaxKind.CaseClause) {
  33. var switchClause = child;
  34. isFallingThrough = fallsThrough(switchClause.statements);
  35. if (isFallingThrough && switchClause.statements.length > 0 && ((switchClauses.length - 1) > i)) {
  36. if (!isFallThroughAllowed(switchClauses[i + 1])) {
  37. _this.addFailure(_this.createFailure(child.getEnd(), 1, Rule.FAILURE_STRING_PART + "'case'"));
  38. }
  39. }
  40. }
  41. else {
  42. if (isFallingThrough && !isFallThroughAllowed(child)) {
  43. var failureString = Rule.FAILURE_STRING_PART + "'default'";
  44. _this.addFailure(_this.createFailure(switchClauses[i - 1].getEnd(), 1, failureString));
  45. }
  46. }
  47. });
  48. _super.prototype.visitSwitchStatement.call(this, node);
  49. };
  50. return NoSwitchCaseFallThroughWalker;
  51. }(Lint.RuleWalker));
  52. exports.NoSwitchCaseFallThroughWalker = NoSwitchCaseFallThroughWalker;
  53. function fallsThrough(statements) {
  54. return !statements.some(function (statement) {
  55. return statement.kind === ts.SyntaxKind.BreakStatement
  56. || statement.kind === ts.SyntaxKind.ThrowStatement
  57. || statement.kind === ts.SyntaxKind.ReturnStatement
  58. || statement.kind === ts.SyntaxKind.ContinueStatement;
  59. });
  60. }
  61. function isFallThroughAllowed(nextCaseOrDefaultStatement) {
  62. var sourceFileText = nextCaseOrDefaultStatement.getSourceFile().text;
  63. var firstChild = nextCaseOrDefaultStatement.getChildAt(0);
  64. var commentRanges = ts.getLeadingCommentRanges(sourceFileText, firstChild.getFullStart());
  65. if (commentRanges != null) {
  66. for (var _i = 0, commentRanges_1 = commentRanges; _i < commentRanges_1.length; _i++) {
  67. var commentRange = commentRanges_1[_i];
  68. var commentText = sourceFileText.substring(commentRange.pos, commentRange.end);
  69. if (commentText === "/* falls through */") {
  70. return true;
  71. }
  72. }
  73. }
  74. return false;
  75. }