Skip to content

Commit

Permalink
Feature Request #3: Added support for onNonMatchingHeade
Browse files Browse the repository at this point in the history
  • Loading branch information
nickdeis committed Aug 26, 2017
1 parent b9b85ed commit 13d1b02
Show file tree
Hide file tree
Showing 9 changed files with 129 additions and 128 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
/node_modules/
/node_modules/
*.log
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,11 @@ or use a file
|template|A lodash template that will be used to fix files they don't contain mustMatch |**Optional**|string|
|templateFile|template will override this setting. A file which contains the template|**Optional**|string|
|templateVars|The variables to be used with the lodash template, always contains the variable YEAR|{YEAR}|object|
|[onNonMatchingHeader](#onNonMatchingHeader)|Action that should be taken when there is a header comment, but it does not match `mustMatch`|`"prepend"`|string|

### onNonMatchingHeader

* **prepend**: Prepends the fix template, if it exists, leaving the former header comment intact.
* **replace**: Replaces the former header comment with the fix template if it exists
* **report**: Does not apply fix, simply reports it based on the level assigned to the rule ("error" or "warn")

121 changes: 70 additions & 51 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,60 +6,79 @@
"use strict";

const fs = require("fs"),
_ = require("lodash");
_ = require("lodash");

const NON_MATCHING_HEADER_ACTIONS = ["prepend","replace","report"];

module.exports = {
rules: {
notice: {
meta: {
docs: {
description: "An eslint rule that checks the top of files and --fix them too!",
category: "Stylistic Issues"
},
fixable: "code"
},
create(context) {
let { mustMatch, templateFile, template, templateVars, chars } = context.options[0];
if (!(mustMatch instanceof RegExp)) {
mustMatch = new RegExp(mustMatch);
}
rules: {
notice: {
meta: {
docs: {
description: "An eslint rule that checks the top of files and --fix them too!",
category: "Stylistic Issues"
},
fixable: "code"
},
create(context) {
let { mustMatch, templateFile, template, templateVars, chars, onNonMatchingHeader } = context.options[0];
onNonMatchingHeader = onNonMatchingHeader || "prepend";
if (!(mustMatch instanceof RegExp)) {
mustMatch = new RegExp(mustMatch);
}

if (!template && templateFile) {
template = fs.readFileSync(templateFile, "utf8");
}
templateVars = templateVars || {};
chars = chars || 1000;
const YEAR = new Date().getFullYear();
const allVars = Object.assign({}, { YEAR }, templateVars);
const resolvedTemplate = _.template(template)(allVars);
const sourceCode = context.getSourceCode();
const text = sourceCode.getText().substring(0, chars);
const firstComment = sourceCode.getAllComments()[0];
return {
Program(node) {
function fix(fixer) {
let topNode;
if(!firstComment){
topNode=node;
}else if(firstComment.loc.start.line <= node.loc.start.line){
topNode=firstComment;
}else{
topNode=node;
}
return fixer.insertTextBefore(topNode, resolvedTemplate);
}
if (!String(text).match(mustMatch)) {
const report = { node, message: `Could not find a match for the mustMatch pattern` };
if (resolvedTemplate) {
report.fix = fix;
}
context.report(report);
return;
}
}
}
}
if (!template && templateFile) {
template = fs.readFileSync(templateFile, "utf8");
}
templateVars = templateVars || {};
chars = chars || 1000;
const YEAR = new Date().getFullYear();
const allVars = Object.assign({}, { YEAR }, templateVars);
const resolvedTemplate = _.template(template)(allVars);
const sourceCode = context.getSourceCode();
const text = sourceCode.getText().substring(0, chars);
const firstComment = sourceCode.getAllComments()[0];
return {
Program(node) {
let topNode;
let hasHeaderComment = false;
let applyFix = true;
if (!firstComment) {
topNode = node;
} else if (firstComment.loc.start.line <= node.loc.start.line) {
hasHeaderComment = true;
topNode = firstComment;
} else {
topNode = node;
}
//Select fixer based off onNonMatchingHeader
let fix;
//If there is no template, then there can be no fix.
if (!resolvedTemplate) {
fix = undefined;
//If it has no header comment or onNonMatchingHeader is set to prepend, prepend to the topNode
} else if (!hasHeaderComment || (hasHeaderComment && onNonMatchingHeader === "prepend")) {
fix = fixer => fixer.insertTextBefore(topNode, resolvedTemplate);
//replace header comment
} else if (hasHeaderComment && onNonMatchingHeader === "replace") {
fix = fixer => fixer.replaceText(topNode, resolvedTemplate);
//report and skip
} else if (hasHeaderComment && onNonMatchingHeader === "report") {
const report = {
node,
message: `Found a header comment which did not match the mustMatch pattern, skipping fix and reporting`
};
context.report(report);
return;
}
if (!String(text).match(mustMatch)) {
const report = { node, message: `Could not find a match for the mustMatch pattern`, fix };
context.report(report);
return;
}
}
};
}
}
}
}
};
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "eslint-plugin-notice",
"version": "0.2.3",
"version": "0.3.3",
"description": "An eslint rule that checks the top of files and --fix them too!",
"main": "index.js",
"directories": {
Expand Down
11 changes: 0 additions & 11 deletions tests/lib/rules/config-issue-2and3.js

This file was deleted.

9 changes: 9 additions & 0 deletions tests/lib/rules/fix-result-3.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

/**
* Copyright (c) 2017, Nick Deis
*/


function leastYouTried(){
return false;
}
72 changes: 40 additions & 32 deletions tests/lib/rules/notice.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,16 @@
* @author Nick Deis
*/
const RuleTester = require("eslint/lib/testers/rule-tester"),
rule = require("../../..").rules.notice,
fs = require("fs"),
path = require("path");
rule = require("../../..").rules.notice,
fs = require("fs"),
path = require("path");

const templateFile = path.join(__dirname,"../../test-template.js");
const templateFile = path.join(__dirname, "../../test-template.js");

const template = fs.readFileSync(templateFile,"utf8");
const template = fs.readFileSync(templateFile, "utf8");

const mustMatch = /Copyright \(c\) [0-9]{0,4}, Nick Deis/;


const ruleTester = new RuleTester();

const notExact = `
Expand All @@ -31,29 +30,38 @@ function noStyle(){
}
`;

const issue3options = require(`${__dirname}/config-issue-2and3`);
const issue3code = fs.readFileSync(`${__dirname}/sample-issue-3.js`,"utf8");

const issue3 = {options:[issue3options],code:issue3code};
const COULD_NOT_FIND = `Could not find a match for the mustMatch pattern`;
const REPORT_AND_SKIP = `Found a header comment which did not match the mustMatch pattern, skipping fix and reporting`;


ruleTester.run("notice",rule,{
invalid:[
{
code:noStyle,
options:[{mustMatch,template}],
errors: [{ message: `Could not find a match for the mustMatch pattern`}],
output:fs.readFileSync(__dirname+"/fix-result-1.js","utf8")
},
{
code:notExact,
options:[{mustMatch,template}],
errors:[{message:`Could not find a match for the mustMatch pattern`}],
output:fs.readFileSync(__dirname+"/fix-result-2.js","utf8")
}
],
valid:[{
code:`
ruleTester.run("notice", rule, {
invalid: [
{
code: noStyle,
options: [{ mustMatch, template }],
errors: [{ message: COULD_NOT_FIND }],
output: fs.readFileSync(__dirname + "/fix-result-1.js", "utf8")
},
{
code: notExact,
options: [{ mustMatch, template }],
errors: [{ message: COULD_NOT_FIND }],
output: fs.readFileSync(__dirname + "/fix-result-2.js", "utf8")
},
{
code: notExact,
options: [{ mustMatch, template, onNonMatchingHeader: "replace" }],
errors: [{ message: COULD_NOT_FIND }],
output: fs.readFileSync(__dirname + "/fix-result-3.js", "utf8")
},
{
code: notExact,
options: [{ mustMatch, template, onNonMatchingHeader: "report" }],
errors: [{ message: REPORT_AND_SKIP }]
}
],
valid: [
{
code: `
/**
* Copyright (c) 2017, Nick Deis
* All rights reserved.
Expand All @@ -62,7 +70,7 @@ ruleTester.run("notice",rule,{
return "I read the style guide, or eslint handled it for me";
}
`,
options:[{mustMatch,template}]
},
issue3]
});
options: [{ mustMatch, template }]
}
]
});
17 changes: 0 additions & 17 deletions tests/lib/rules/sample-issue-3.js

This file was deleted.

15 changes: 0 additions & 15 deletions tests/lib/rules/template-issue-3.js

This file was deleted.

0 comments on commit 13d1b02

Please sign in to comment.