Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 70 additions & 7 deletions lib/rules/header.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ function excludeShebangs(comments) {
// hasHeader().
function getLeadingComments(context, node) {
var all = excludeShebangs(context.getSourceCode().getAllComments(node.body.length ? node.body[0] : node));

if (!all.length) {
return [];
}

if (all[0].type.toLowerCase() === "block") {
return [all[0]];
}
Expand Down Expand Up @@ -165,15 +170,73 @@ module.exports = {

return {
Program: function(node) {
var leadingComments = getLeadingComments(context, node);

if (!hasHeader(context.getSourceCode().getText())) {
context.report({
loc: node.loc,
message: "missing header",
fix: genPrependFixer(commentType, node, fixLines, eol, numNewlines)
});
} else {
var leadingComments = getLeadingComments(context, node);
var firstToken = context.getFirstToken(node);

if (!leadingComments.length) {
/**
* Calculate the number of lines we need to add so that the number of new lines to
* the first block is at least the configured amount
*/
var actualNumNewLines = firstToken
// Repeat throws if given a value < 0, so we should cap it here
? Math.max(0, numNewlines - firstToken.loc.start.line + 1)
: numNewlines;

/**
* If there are no leading comments we can just insert the header at the top of the
* file
*/
context.report({
loc: node.loc,
message: "missing header",
fix: function(fixer) {
/**
* Insert text at the top of the file always, so that any additional newlines will
* be preserved
*/
return fixer.insertTextAfterRange(
[0, 0],
genCommentBody(commentType, headerLines, eol, actualNumNewLines)
);
}
});
} else if (
/**
* If there is no non-comment node and the first comment is not at the top of the
* file we should remove the leading whitespace
*/
(!firstToken && leadingComments[0].range[0] !== 0)
/**
* Or if the first node is after the first comment but the first comment is not at
* the top of the file we should remove the leading whitespace
*/
|| (leadingComments[0].loc.start.line < firstToken.loc.start.line)
) {
/**
* This is done so that the next time this code is run we can run the regex's on
* the first couple lines of the file
*/
context.report({
loc: {
start: {
line: 1,
column: 0,
},
end: {
line: leadingComments[0].loc.start.line - 1,
column: 0,
},
},
message: "unexpected preceding whitespace",
fix: function(fixer) {
return fixer.removeRange([0, leadingComments[0].range[0]]);
},
});
}
} else {
if (!leadingComments.length) {
context.report({
loc: node.loc,
Expand Down
130 changes: 101 additions & 29 deletions tests/lib/rules/header.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,15 @@ ruleTester.run("header", rule, {
},
{
code: "// Copyright 2017",
options: ["line", {pattern: "^ Copyright \\d+$"}, 0]
options: ["line", { pattern: "^ Copyright \\d+$" }, 0]
},
{
code: "// Copyright 2017\n// Author: [email protected]",
options: ["line", [{pattern: "^ Copyright \\d+$"}, {pattern: "^ Author: \\w+@\\w+\\.\\w+$"}], 0]
options: ["line", [{ pattern: "^ Copyright \\d+$" }, { pattern: "^ Author: \\w+@\\w+\\.\\w+$" }], 0]
},
{
code: "/* Copyright 2017\n Author: [email protected] */",
options: ["block", {pattern: "^ Copyright \\d{4}\\n Author: \\w+@\\w+\\.\\w+ $"}, 0]
options: ["block", { pattern: "^ Copyright \\d{4}\\n Author: \\w+@\\w+\\.\\w+ $" }, 0]
},
{
code: "#!/usr/bin/env node\n/**\n * Copyright\n */",
Expand All @@ -81,11 +81,11 @@ ruleTester.run("header", rule, {
},
{
code: "/*Copyright 2018\r\nMy Company*/\r\nconsole.log(1)",
options: ["block", ["Copyright 2018", "My Company"], {"lineEndings": "windows"}]
options: ["block", ["Copyright 2018", "My Company"], { "lineEndings": "windows" }]
},
{
code: "/*Copyright 2018\nMy Company*/\nconsole.log(1)",
options: ["block", ["Copyright 2018", "My Company"], {"lineEndings": "unix"}]
options: ["block", ["Copyright 2018", "My Company"], { "lineEndings": "unix" }]
},
{
code: "/*************************\n * Copyright 2015\n * My Company\n *************************/\nconsole.log(1)",
Expand Down Expand Up @@ -130,31 +130,103 @@ ruleTester.run("header", rule, {
code: "console.log(1);",
options: ["block", "Copyright 2015, My Company"],
errors: [
{message: "missing header"}
{ message: "missing header" }
],
output: "/*Copyright 2015, My Company*/\nconsole.log(1);"
},
{
code: "\nconsole.log(1);",
options: ["block", "Copyright 2015, My Company"],
errors: [
{ message: "missing header" }
],
output: "/*Copyright 2015, My Company*/\nconsole.log(1);"
},
{
code: "\n\nconsole.log(1);",
options: ["block", "Copyright 2015, My Company"],
errors: [
{ message: "missing header" }
],
output: "/*Copyright 2015, My Company*/\n\nconsole.log(1);"
},
{
code: "\n\n\nconsole.log(1);",
options: ["block", "Copyright 2015, My Company"],
errors: [
{ message: "missing header" }
],
output: "/*Copyright 2015, My Company*/\n\n\nconsole.log(1);"
},
{
code: "\nconsole.log(1);",
options: ["block", "Copyright 2015, My Company", 2],
errors: [
{ message: "missing header" }
],
output: "/*Copyright 2015, My Company*/\n\nconsole.log(1);"
},
{
code: "\nconsole.log(1);",
options: ["block", "Copyright 2015, My Company", 3],
errors: [
{ message: "missing header" }
],
output: "/*Copyright 2015, My Company*/\n\n\nconsole.log(1);"
},
{
code: "\n/**\n * Copyright 2020\n * My Company\n **/\n\n/*Log number one*/\nconsole.log(1);",
options: ["block", "*\n * Copyright 2020\n * My Company\n *", 2],
errors: [
{ message: "unexpected preceding whitespace" }
],
output: "/**\n * Copyright 2020\n * My Company\n **/\n\n/*Log number one*/\nconsole.log(1);",
},
{
code: " /**\n * Copyright 2020\n * My Company\n **/\n\n/*Log number one*/\nconsole.log(1);",
options: ["block", "*\n * Copyright 2020\n * My Company\n *", 2],
errors: [
{ message: "unexpected preceding whitespace" }
],
output: "/**\n * Copyright 2020\n * My Company\n **/\n\n/*Log number one*/\nconsole.log(1);",
},
{
code: "\n /**\n * Copyright 2020\n * My Company\n **/\n\n/*Log number one*/\nconsole.log(1);",
options: ["block", "*\n * Copyright 2020\n * My Company\n *", 2],
errors: [
{ message: "unexpected preceding whitespace" }
],
output: "/**\n * Copyright 2020\n * My Company\n **/\n\n/*Log number one*/\nconsole.log(1);",
},
{
code: "\n//Copyright 2018\r\n//My Company\r\n/* DOCS */",
options: ["line", ["Copyright 2018", "My Company"]],
errors: [
{ message: "unexpected preceding whitespace" }
],
output: "//Copyright 2018\r\n//My Company\r\n/* DOCS */",
},
{
code: "//Copyright 2014, My Company\nconsole.log(1);",
options: ["block", "Copyright 2015, My Company"],
errors: [
{message: "header should be a block comment"}
{ message: "header should be a block comment" }
],
output: "/*Copyright 2015, My Company*/\nconsole.log(1);"
},
{
code: "/*Copyright 2014, My Company*/\nconsole.log(1);",
options: ["line", "Copyright 2015, My Company"],
errors: [
{message: "header should be a line comment"}
{ message: "header should be a line comment" }
],
output: "//Copyright 2015, My Company\nconsole.log(1);"
},
{
code: "/*Copyright 2014, My Company*/\nconsole.log(1);",
options: ["block", "Copyright 2015, My Company"],
errors: [
{message: "incorrect header"}
{ message: "incorrect header" }
],
output: "/*Copyright 2015, My Company*/\nconsole.log(1);"
},
Expand All @@ -163,69 +235,69 @@ ruleTester.run("header", rule, {
code: "/*Copyright 2015\nMy Company\nExtra*/\nconsole.log(1);",
options: ["block", ["Copyright 2015", "My Company"]],
errors: [
{message: "incorrect header"}
{ message: "incorrect header" }
],
output: "/*Copyright 2015\nMy Company*/\nconsole.log(1);"
},
{
code: "/*Copyright 2015\n*/\nconsole.log(1);",
options: ["block", ["Copyright 2015", "My Company"]],
errors: [
{message: "incorrect header"}
{ message: "incorrect header" }
],
output: "/*Copyright 2015\nMy Company*/\nconsole.log(1);"
},
{
code: "//Copyright 2014\n//My Company\nconsole.log(1)",
options: ["line", "Copyright 2015\nMy Company"],
errors: [
{message: "incorrect header"}
{ message: "incorrect header" }
],
output: "//Copyright 2015\n//My Company\nconsole.log(1)"
},
{
code: "//Copyright 2015",
options: ["line", "Copyright 2015\nMy Company"],
errors: [
{message: "incorrect header"}
{ message: "incorrect header" }
],
output: "//Copyright 2015\n//My Company\n"
},
{
code: "// Copyright 2017 trailing",
options: ["line", {pattern: "^ Copyright \\d+$"}],
options: ["line", { pattern: "^ Copyright \\d+$" }],
errors: [
{message: "incorrect header"}
{ message: "incorrect header" }
]
},
{
code: "// Copyright 2017 trailing",
options: ["line", {pattern: "^ Copyright \\d+$", template: " Copyright 2018"}],
options: ["line", { pattern: "^ Copyright \\d+$", template: " Copyright 2018" }],
errors: [
{message: "incorrect header"}
{ message: "incorrect header" }
],
output: "// Copyright 2018\n"
},
{
code: "// Copyright 2017 trailing\n// Someone",
options: ["line", [{pattern: "^ Copyright \\d+$", template: " Copyright 2018"}, " My Company"]],
options: ["line", [{ pattern: "^ Copyright \\d+$", template: " Copyright 2018" }, " My Company"]],
errors: [
{message: "incorrect header"}
{ message: "incorrect header" }
],
output: "// Copyright 2018\n// My Company\n"
},
{
code: "// Copyright 2017\n// Author: [email protected]",
options: ["line", [{pattern: "Copyright \\d+"}, {pattern: "^ Author: \\w+@\\w+\\.\\w+$"}]],
options: ["line", [{ pattern: "Copyright \\d+" }, { pattern: "^ Author: \\w+@\\w+\\.\\w+$" }]],
errors: [
{message: "incorrect header"}
{ message: "incorrect header" }
]
},
{
code: "/* Copyright 2017-01-02\n Author: [email protected] */",
options: ["block", {pattern: "^ Copyright \\d+\\n Author: \\w+@\\w+\\.\\w+ $"}],
options: ["block", { pattern: "^ Copyright \\d+\\n Author: \\w+@\\w+\\.\\w+ $" }],
errors: [
{message: "incorrect header"}
{ message: "incorrect header" }
]
},
{
Expand All @@ -237,47 +309,47 @@ ruleTester.run("header", rule, {
" ************************"
]],
errors: [
{message: "incorrect header"}
{ message: "incorrect header" }
],
output: "/*************************\n * Copyright 2019\n * My Company\n *************************/\nconsole.log(1)"
},
{
code: "/*Copyright 2020, My Company*/console.log(1);",
options: ["block", "Copyright 2020, My Company", 2],
errors: [
{message: "no newline after header"}
{ message: "no newline after header" }
],
output: "/*Copyright 2020, My Company*/\n\nconsole.log(1);"
},
{
code: "/*Copyright 2020, My Company*/console.log(1);",
options: ["block", "Copyright 2020, My Company", 1],
errors: [
{message: "no newline after header"}
{ message: "no newline after header" }
],
output: "/*Copyright 2020, My Company*/\nconsole.log(1);"
},
{
code: "//Copyright 2020\n//My Company\nconsole.log(1);",
options: ["line", ["Copyright 2020", "My Company"], 2],
errors: [
{message: "no newline after header"}
{ message: "no newline after header" }
],
output: "//Copyright 2020\n//My Company\n\nconsole.log(1);"
},
{
code: "/*Copyright 2020, My Company*/\nconsole.log(1);\n//Comment\nconsole.log(2);\n//Comment",
options: ["block", "Copyright 2020, My Company", 2],
errors: [
{message: "no newline after header"}
{ message: "no newline after header" }
],
output: "/*Copyright 2020, My Company*/\n\nconsole.log(1);\n//Comment\nconsole.log(2);\n//Comment"
},
{
code: "//Copyright 2020\n//My Company\nconsole.log(1);\n//Comment\nconsole.log(2);\n//Comment",
options: ["line", ["Copyright 2020", "My Company"], 2],
errors: [
{message: "no newline after header"}
{ message: "no newline after header" }
],
output: "//Copyright 2020\n//My Company\n\nconsole.log(1);\n//Comment\nconsole.log(2);\n//Comment"
}
Expand Down