// Requirements
//------------------------------------------------------------------------------
-const lodash = require("lodash");
const astUtils = require("./utils/ast-utils");
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+
+/**
+ * Creates an array of numbers from `start` up to, but not including, `end`
+ * @param {number} start The start of the range
+ * @param {number} end The end of the range
+ * @returns {number[]} The range of numbers
+ */
+function range(start, end) {
+ return [...Array(end - start).keys()].map(x => x + start);
+}
+
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
}
],
messages: {
- exceed: "File has too many lines ({{actual}}). Maximum allowed is {{max}}."
+ exceed:
+ "File has too many lines ({{actual}}). Maximum allowed is {{max}}."
}
},
const option = context.options[0];
let max = 300;
- if (typeof option === "object" && Object.prototype.hasOwnProperty.call(option, "max")) {
+ if (
+ typeof option === "object" &&
+ Object.prototype.hasOwnProperty.call(option, "max")
+ ) {
max = option.max;
} else if (typeof option === "number") {
max = option;
token = comment;
do {
- token = sourceCode.getTokenBefore(token, { includeComments: true });
+ token = sourceCode.getTokenBefore(token, {
+ includeComments: true
+ });
} while (isCommentNodeType(token));
if (token && astUtils.isTokenOnSameLine(token, comment)) {
token = comment;
do {
- token = sourceCode.getTokenAfter(token, { includeComments: true });
+ token = sourceCode.getTokenAfter(token, {
+ includeComments: true
+ });
} while (isCommentNodeType(token));
if (token && astUtils.isTokenOnSameLine(comment, token)) {
}
if (start <= end) {
- return lodash.range(start, end + 1);
+ return range(start, end + 1);
}
return [];
}
+ /**
+ * Returns a new array formed by applying a given callback function to each element of the array, and then flattening the result by one level.
+ * TODO(stephenwade): Replace this with array.flatMap when we drop support for Node v10
+ * @param {any[]} array The array to process
+ * @param {Function} fn The function to use
+ * @returns {any[]} The result array
+ */
+ function flatMap(array, fn) {
+ const mapped = array.map(fn);
+ const flattened = [].concat(...mapped);
+
+ return flattened;
+ }
+
return {
"Program:exit"() {
- let lines = sourceCode.lines.map((text, i) => ({ lineNumber: i + 1, text }));
+ let lines = sourceCode.lines.map((text, i) => ({
+ lineNumber: i + 1,
+ text
+ }));
+
+ /*
+ * If file ends with a linebreak, `sourceCode.lines` will have one extra empty line at the end.
+ * That isn't a real line, so we shouldn't count it.
+ */
+ if (lines.length > 1 && lines[lines.length - 1].text === "") {
+ lines.pop();
+ }
if (skipBlankLines) {
lines = lines.filter(l => l.text.trim() !== "");
if (skipComments) {
const comments = sourceCode.getAllComments();
- const commentLines = lodash.flatten(comments.map(comment => getLinesWithoutCode(comment)));
+ const commentLines = flatMap(comments, comment => getLinesWithoutCode(comment));
- lines = lines.filter(l => !lodash.includes(commentLines, l.lineNumber));
+ lines = lines.filter(
+ l => !commentLines.includes(l.lineNumber)
+ );
}
if (lines.length > max) {
+ const loc = {
+ start: {
+ line: lines[max].lineNumber,
+ column: 0
+ },
+ end: {
+ line: sourceCode.lines.length,
+ column: sourceCode.lines[sourceCode.lines.length - 1].length
+ }
+ };
+
context.report({
- loc: { line: 1, column: 0 },
+ loc,
messageId: "exceed",
data: {
max,