From 06adff2d1a254cc4623d64765a142c15e28f0414 Mon Sep 17 00:00:00 2001 From: Eliaztray <944126009@qq.com> Date: Wed, 12 Jun 2019 00:02:46 +0800 Subject: [PATCH] feat: Add autofix to max-empty-lines --- lib/rules/max-empty-lines/__tests__/index.js | 64 ++++++++++++++ lib/rules/max-empty-lines/index.js | 88 +++++++++++++++++++- 2 files changed, 151 insertions(+), 1 deletion(-) diff --git a/lib/rules/max-empty-lines/__tests__/index.js b/lib/rules/max-empty-lines/__tests__/index.js index 51776dd32e..e5ea677b8f 100644 --- a/lib/rules/max-empty-lines/__tests__/index.js +++ b/lib/rules/max-empty-lines/__tests__/index.js @@ -6,6 +6,7 @@ const { messages, ruleName } = rule; testRule(rule, { ruleName, config: [0], + fix: true, accept: [ { @@ -15,6 +16,7 @@ testRule(rule, { reject: [ { code: "\na {}", + fixed: "a {}", message: messages.expected(0), line: 1, column: 1 @@ -25,6 +27,7 @@ testRule(rule, { testRule(rule, { ruleName, config: [1], + fix: true, accept: [ { @@ -68,60 +71,70 @@ testRule(rule, { reject: [ { code: "\n\na {}", + fixed: "\na {}", message: messages.expected(1), line: 2, column: 1 }, { code: "\r\n\r\na {}", + fixed: "\r\na {}", message: messages.expected(1), line: 2, column: 1 }, { code: "a {}\n\n", + fixed: "a {}\n", message: messages.expected(1), line: 3, column: 1 }, { code: "a {}\r\n\r\n", + fixed: "a {}\r\n", message: messages.expected(1), line: 3, column: 1 }, { code: "a {}\n\n\nb {}", + fixed: "a {}\n\nb {}", message: messages.expected(1), line: 3, column: 1 }, { code: "a {}\r\n\r\n\r\nb {}", + fixed: "a {}\r\n\r\nb {}", message: messages.expected(1), line: 3, column: 1 }, { code: "a {}\n\n/** horse */\n\n\nb {}", + fixed: "a {}\n\n/** horse */\n\nb {}", message: messages.expected(1), line: 5, column: 1 }, { code: "a {}\r\n\r\n/** horse */\r\n\r\n\r\nb {}", + fixed: "a {}\r\n\r\n/** horse */\r\n\r\nb {}", message: messages.expected(1), line: 5, column: 1 }, { code: "/* horse\n\n\n */\na {}", + fixed: "/* horse\n\n */\na {}", message: messages.expected(1), line: 3, column: 1 }, { code: "/* horse\r\n\r\n\r\n */\r\na {}", + fixed: "/* horse\r\n\r\n */\r\na {}", message: messages.expected(1), line: 3, column: 1 @@ -189,6 +202,12 @@ a {color: pink;} /* horse */ + +`, + fixed: `
+
`, message: messages.expected(1), @@ -200,6 +219,10 @@ a {color: pink;} code: `
+
`, + fixed: `
`, message: messages.expected(1), @@ -216,6 +239,16 @@ a {} a {} + +`, + fixed: `
+ +
`, message: messages.expected(1), @@ -280,6 +313,14 @@ export default styled.div\` /* horse */ + color: #00 +\`; +`, + fixed: ` +import styled from 'styled-components'; +export default styled.div\` + /* horse */ + color: #00 \`; `, @@ -300,6 +341,18 @@ export const style2 = styled.div\` color: #00 +\`;`, + fixed: ` +import styled from 'styled-components'; +// styled style1 +export const style1 = styled.div\` + color: #00 + +\`; +// styled style2 +export const style2 = styled.div\` + color: #00 + \`;`, message: messages.expected(1), line: 12, @@ -336,36 +389,42 @@ testRule(rule, { reject: [ { code: "a {}\n\n\n\nb {}", + fixed: "a {}\n\n\nb {}", message: messages.expected(2), line: 4, column: 1 }, { code: "a {}\r\n\r\n\r\n\r\nb {}", + fixed: "a {}\r\n\r\n\r\nb {}", message: messages.expected(2), line: 4, column: 1 }, { code: "a {}\n\n/** horse */\n\n\n\nb {}", + fixed: "a {}\n\n/** horse */\n\n\nb {}", message: messages.expected(2), line: 6, column: 1 }, { code: "a {}\r\n\r\n/** horse */\r\n\r\n\r\n\r\nb {}", + fixed: "a {}\r\n\r\n/** horse */\r\n\r\n\r\nb {}", message: messages.expected(2), line: 6, column: 1 }, { code: "/* horse\n\n\n\n */\na {}", + fixed: "/* horse\n\n\n */\na {}", message: messages.expected(2), line: 4, column: 1 }, { code: "/* horse\r\n\r\n\r\n\r\n */\r\na {}", + fixed: "/* horse\r\n\r\n\r\n */\r\na {}", message: messages.expected(2), line: 4, column: 1 @@ -394,18 +453,21 @@ testRule(rule, { reject: [ { code: "\n\n\n// one", + fixed: "\n\n// one", message: messages.expected(2), line: 3, column: 1 }, { code: "// one\n\n\n", + fixed: "// one\n\n", message: messages.expected(2), line: 4, column: 1 }, { code: "// one\n\n\n\n// two\n", + fixed: "// one\n\n\n// two\n", message: messages.expected(2), line: 4, column: 1 @@ -441,12 +503,14 @@ testRule(rule, { reject: [ { code: "a {}\n\n/*\n\n\n\n\n*/\n\n\n\nb {}", + fixed: "a {}\n\n/*\n\n\n\n\n*/\n\n\nb {}", message: messages.expected(2), line: 11, column: 1 }, { code: "a {}\r\n\r\n/**\r\n\r\n\r\n\r\n\r\n*/\r\n\r\n\r\n\r\nb {}", + fixed: "a {}\r\n\r\n/**\r\n\r\n\r\n\r\n\r\n*/\r\n\r\n\r\nb {}", message: messages.expected(2), line: 11, column: 1 diff --git a/lib/rules/max-empty-lines/index.js b/lib/rules/max-empty-lines/index.js index d32d07d065..92f6f5ccfd 100644 --- a/lib/rules/max-empty-lines/index.js +++ b/lib/rules/max-empty-lines/index.js @@ -14,7 +14,7 @@ const messages = ruleMessages(ruleName, { `Expected no more than ${max} empty ${max === 1 ? "line" : "lines"}` }); -const rule = function(max, options) { +const rule = function(max, options, context) { let emptyLines = 0; let lastIndex = -1; @@ -40,6 +40,59 @@ const rule = function(max, options) { } const ignoreComments = optionsMatches(options, "ignore", "comments"); + const getChars = _.partial(replaceEmptyLines, max); + + /** + * 1. walk nodes & replace enterchar + * 2. deal with special case. + */ + if (context.fix) { + root.walk(node => { + if (node.type === "comment") { + // for inline comments + if (node.raws.inline) { + node.raws.before = getChars(node.raws.before); + } + + if (!ignoreComments) { + node.raws.left = getChars(node.raws.left); + node.raws.right = getChars(node.raws.right); + } + } else { + if (node.raws.before) { + node.raws.before = getChars(node.raws.before); + } + + if (node.raws.after) { + node.raws.after = getChars(node.raws.after); + } + } + }); + + // first node + const firstNodeRawsBefore = _.get(root, "first.raws.before"); + + // not document node + if (_.get(root, "constructor.name") !== "Document") { + if (firstNodeRawsBefore) { + _.set(root, "first.raws.before", getChars(firstNodeRawsBefore, true)); + } + } + + // root raws + const rootRawsAfter = _.get(root, "raws.after"); + + if (rootRawsAfter) { + // when max setted 0, should be treated as 1 in this situation. + _.set( + root, + "raws.after", + replaceEmptyLines(max === 0 ? 1 : max, rootRawsAfter, true) + ); + } + + return; + } emptyLines = 0; lastIndex = -1; @@ -98,6 +151,39 @@ const rule = function(max, options) { } } } + + function replaceEmptyLines(max, str, isSpecialCase = false) { + const maxLength = isSpecialCase ? max : max + 1; + + if (maxLength === 0) { + return ""; + } + + const emptyLFLines = _.repeat("\n", maxLength); + const emptyCRLFLines = _.repeat("\r\n", maxLength); + + let result; + + if (/(\r\n)+/g.test(str)) { + result = str.replace(/(\r\n)+/g, $1 => { + if ($1.length > maxLength) { + return emptyCRLFLines; + } + + return $1; + }); + } else { + result = str.replace(/(\n)+/g, $1 => { + if ($1.length > maxLength) { + return emptyLFLines; + } + + return $1; + }); + } + + return result; + } }; };