You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

88 lines
3.0 KiB

/**
* @fileoverview Rule to flag fall-through cases in switch statements.
* @author Matt DuVall <http://mattduvall.com/>
*/
"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
var getLast = require("../util").getLast;
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
var FALLTHROUGH_COMMENT = /falls?\s?through/i;
/**
* Checks whether or not a given node has a fallthrough comment.
* @param {ASTNode} node - A SwitchCase node to get comments.
* @param {RuleContext} context - A rule context which stores comments.
* @returns {boolean} `true` if the node has a fallthrough comment.
*/
function hasFallthroughComment(node, context) {
var sourceCode = context.getSourceCode();
var comment = getLast(sourceCode.getComments(node).leading);
return Boolean(comment && FALLTHROUGH_COMMENT.test(comment.value));
}
/**
* Checks whether or not a given code path segment is reachable.
* @param {CodePathSegment} segment - A CodePathSegment to check.
* @returns {boolean} `true` if the segment is reachable.
*/
function isReachable(segment) {
return segment.reachable;
}
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
var currentCodePath = null;
// We need to use leading comments of the next SwitchCase node because
// trailing comments is wrong if semicolons are omitted.
var fallthroughCase = null;
return {
"onCodePathStart": function(codePath) {
currentCodePath = codePath;
},
"onCodePathEnd": function() {
currentCodePath = currentCodePath.upper;
},
"SwitchCase": function(node) {
// Checks whether or not there is a fallthrough comment.
// And reports the previous fallthrough node if that does not exist.
if (fallthroughCase && !hasFallthroughComment(node, context)) {
context.report({
message: "Expected a 'break' statement before '{{type}}'.",
data: {type: node.test ? "case" : "default"},
node: node
});
}
fallthroughCase = null;
},
"SwitchCase:exit": function(node) {
// `reachable` meant fall through because statements preceded by
// `break`, `return`, or `throw` are unreachable.
// And allows empty cases and the last case.
if (currentCodePath.currentSegments.some(isReachable) &&
node.consequent.length > 0 &&
getLast(node.parent.cases) !== node
) {
fallthroughCase = node;
}
}
};
};
module.exports.schema = [];