Fix using concat() on single Doc (#9994)

Co-authored-by: Sosuke Suzuki <aosukeke@gmail.com>
This commit is contained in:
fisker CheungandSosuke Suzuki authored and GitHub committed 2021-01-04 14:40:02 +08:00
1 parent 6c37b1979a
commit 7ec7a0f21f
11 files changed
+71 -13

No files matched your search

+1
View File
@@ -111,6 +111,7 @@ overrides:
- files: src/**/*.js
rules:
prettier-internal-rules/no-doc-builder-concat: off
prettier-internal-rules/no-single-doc-concat: error
prettier-internal-rules/prefer-fast-path-each: error
prettier-internal-rules/prefer-is-non-empty-array: error
- files: src/document/*.js
@@ -7,6 +7,7 @@ module.exports = {
"jsx-identifier-case": require("./jsx-identifier-case"),
"no-doc-builder-concat": require("./no-doc-builder-concat"),
"no-node-comments": require("./no-node-comments"),
"no-single-doc-concat": require("./no-single-doc-concat"),
"prefer-fast-path-each": require("./prefer-fast-path-each"),
"prefer-is-non-empty-array": require("./prefer-is-non-empty-array"),
"require-json-extensions": require("./require-json-extensions"),
@@ -0,0 +1,44 @@
"use strict";
// TODO: Remove this rule when deprecated `concat` is not using in codebase, #9993.
const selector = [
"CallExpression",
'[callee.type="Identifier"]',
'[callee.name="concat"]',
"[arguments.length=1]",
'[arguments.0.type="ArrayExpression"]',
"[arguments.0.elements.length=1]",
].join("");
const messageId = "no-single-doc-concat";
module.exports = {
meta: {
type: "suggestion",
docs: {
url:
"https://github.com/prettier/prettier/blob/master/scripts/eslint-plugin-prettier-internal-rules/no-single-doc-concat.js",
},
messages: {
[messageId]: "Do not use `concat()` to concat single `Doc`.",
},
fixable: "code",
},
create(context) {
const sourceCode = context.getSourceCode();
return {
[selector](node) {
context.report({
node,
messageId,
fix: (fixer) =>
fixer.replaceText(
node,
sourceCode.getText(node.arguments[0].elements[0])
),
});
},
};
},
};
@@ -144,6 +144,17 @@ test("no-node-comments", {
],
});
test("no-single-doc-concat", {
valid: [],
invalid: [
{
code: 'concat([path.call(print, "params")])',
output: 'path.call(print, "params")',
errors: 1,
},
],
});
test("prefer-fast-path-each", {
valid: ["const foo = path.map()"],
invalid: [
+2 -2
View File
@@ -213,7 +213,7 @@ function genericPrint(path, options, print) {
if (node.function) {
return concat([
node.name,
concat([path.call(print, "params")]),
path.call(print, "params"),
isTemplatePlaceholderNodeWithoutSemiColon ? "" : ";",
]);
}
@@ -223,7 +223,7 @@ function genericPrint(path, options, print) {
"@",
node.name,
": ",
node.value ? concat([path.call(print, "value")]) : "",
node.value ? path.call(print, "value") : "",
node.raws.between.trim() ? node.raws.between.trim() + " " : "",
node.nodes
? concat([
+1 -1
View File
@@ -21,7 +21,7 @@ function genericPrint(path, options, print) {
case "Document": {
const parts = [];
path.each((pathChild, index, definitions) => {
parts.push(concat([pathChild.call(print)]));
parts.push(pathChild.call(print));
if (index !== definitions.length - 1) {
parts.push(hardline);
if (
+7 -4
View File
@@ -138,11 +138,14 @@ function print(path, options, print) {
// same, there is no value for this AttrNode and it should be printed
// without the `=""`. Example: `<img data-test>` -> `<img data-test>`
if (isEmptyText && locStart(n.value) === locEnd(n.value)) {
return concat([n.name]);
return n.name;
}
const value = path.call(print, "value");
const quotedValue = isText
? printStringLiteral(getDocParts(value).join(), options)
? printStringLiteral(
typeof value === "string" ? value : getDocParts(value).join(),
options
)
: value;
return concat([n.name, "=", quotedValue]);
}
@@ -157,7 +160,7 @@ function print(path, options, print) {
}
case "Hash": {
return concat([join(line, path.map(print, "pairs"))]);
return join(line, path.map(print, "pairs"));
}
case "HashPair": {
return concat([n.key, "=", path.call(print, "value")]);
@@ -201,7 +204,7 @@ function print(path, options, print) {
// TODO: format style and srcset attributes
// and cleanup concat that is not necessary
if (!isInAttributeOfName(path, "class")) {
return concat([n.chars]);
return n.chars;
}
let leadingSpace = "";
+1 -1
View File
@@ -82,7 +82,7 @@ function printCallArguments(path, options, print) {
let shouldBreak = false;
iterateFunctionParametersPath(argPath, (parameterPath) => {
shouldBreak = shouldBreak || willBreak(concat([print(parameterPath)]));
shouldBreak = shouldBreak || willBreak(print(parameterPath));
});
return shouldBreak;
+1 -1
View File
@@ -118,7 +118,7 @@ function printJsxElementInternal(path, options, print) {
const rawJsxWhitespace = options.singleQuote ? "{' '}" : '{" "}';
const jsxWhitespace = isMdxBlock
? concat([" "])
? " "
: ifBreak(concat([rawJsxWhitespace, softline]), " ");
const isFacebookTranslationTag =
+1 -3
View File
@@ -488,9 +488,7 @@ function printPathNoParens(path, options, print, args) {
}, "expressions");
return group(concat(parts));
}
return group(
concat([join(concat([",", line]), path.map(print, "expressions"))])
);
return group(join(concat([",", line]), path.map(print, "expressions")));
}
case "ThisExpression":
return "this";
+1 -1
View File
@@ -23,7 +23,7 @@ function printMappingItem(node, parentNode, path, print, options) {
const isEmptyMappingValue = isEmptyNode(value);
if (isEmptyMappingKey && isEmptyMappingValue) {
return concat([": "]);
return ": ";
}
const printedKey = path.call(print, "key");