Convert node types Set to type check function (#18149)
This commit is contained in:
1 parent
e51ff9ad41
commit
e5118b2650
6 files changed
+161
-18
No files matched your search
+117
-2
@@ -126,13 +126,27 @@ function isTopLevelFunction(node) {
|
||||
);
|
||||
}
|
||||
|
||||
const selector = [
|
||||
const functionSelector = [
|
||||
":function",
|
||||
"[params.length=1]",
|
||||
"[async!=true]",
|
||||
"[generator!=true]",
|
||||
].join("");
|
||||
|
||||
const setDeclareSelector = [
|
||||
"VariableDeclaration",
|
||||
'[kind="const"]',
|
||||
"[declarations.length=1]",
|
||||
" > ",
|
||||
"VariableDeclarator.declarations",
|
||||
'[init.type="NewExpression"]',
|
||||
'[init.callee.type="Identifier"]',
|
||||
'[init.callee.name="Set"]',
|
||||
"[init.arguments.length=1]",
|
||||
'[init.arguments.0.type="ArrayExpression"]',
|
||||
" > Identifier.id",
|
||||
].join("");
|
||||
|
||||
export default {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
@@ -165,7 +179,7 @@ export default {
|
||||
const sourceCode = context.getSourceCode();
|
||||
|
||||
return {
|
||||
[selector](functionNode) {
|
||||
[functionSelector](functionNode) {
|
||||
if (onlyTopLevelFunctions && !isTopLevelFunction(functionNode)) {
|
||||
return;
|
||||
}
|
||||
@@ -252,6 +266,107 @@ export default {
|
||||
|
||||
context.report(problem);
|
||||
},
|
||||
[setDeclareSelector](identifier) {
|
||||
const variable = sourceCode
|
||||
.getDeclaredVariables(identifier.parent)
|
||||
.find(
|
||||
(variable) =>
|
||||
variable.identifiers.length === 1 &&
|
||||
variable.identifiers[0] === identifier,
|
||||
);
|
||||
|
||||
if (!variable) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { references } = variable;
|
||||
|
||||
if (references.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const nodes = [];
|
||||
|
||||
for (const { identifier: referenceIdentifier } of references) {
|
||||
if (referenceIdentifier === identifier) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
!(
|
||||
referenceIdentifier.parent.type === "MemberExpression" &&
|
||||
referenceIdentifier.parent.object === referenceIdentifier &&
|
||||
!referenceIdentifier.parent.optional &&
|
||||
!referenceIdentifier.parent.computed &&
|
||||
referenceIdentifier.parent.property.type === "Identifier" &&
|
||||
referenceIdentifier.parent.property.name === "has" &&
|
||||
referenceIdentifier.parent.parent.type === "CallExpression" &&
|
||||
referenceIdentifier.parent.parent.callee ===
|
||||
referenceIdentifier.parent &&
|
||||
!referenceIdentifier.parent.parent.optional &&
|
||||
referenceIdentifier.parent.parent.arguments.length === 1
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const [typeNode] = referenceIdentifier.parent.parent.arguments;
|
||||
const memberExpression =
|
||||
typeNode.type === "ChainExpression"
|
||||
? typeNode.expression
|
||||
: typeNode;
|
||||
|
||||
if (
|
||||
!(
|
||||
memberExpression.type === "MemberExpression" &&
|
||||
!memberExpression.computed &&
|
||||
memberExpression.property.type === "Identifier" &&
|
||||
memberExpression.property.name === "type"
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
nodes.push({
|
||||
setHasNode: referenceIdentifier.parent,
|
||||
typeNode,
|
||||
nodeNode: memberExpression.object,
|
||||
});
|
||||
}
|
||||
|
||||
if (nodes.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
context.report({
|
||||
node: identifier,
|
||||
messageId: MESSAGE_ID,
|
||||
*fix(fixer) {
|
||||
const { name } = identifier;
|
||||
const replacement = `__please_rename_this_function_${name}`;
|
||||
|
||||
// Rename variable
|
||||
yield fixer.replaceText(identifier, replacement);
|
||||
|
||||
// `new Set()` -> `createTypeCheckFunction()`
|
||||
const newSet = identifier.parent.init;
|
||||
const newToken = sourceCode.getFirstToken(newSet);
|
||||
yield fixer.remove(newToken);
|
||||
yield fixer.replaceText(newSet.callee, "createTypeCheckFunction");
|
||||
|
||||
for (const { setHasNode, typeNode, nodeNode } of nodes) {
|
||||
// `set.has` -> `typeCheckFunction`
|
||||
yield fixer.replaceText(setHasNode, replacement);
|
||||
|
||||
// `foo.type` -> `foo`
|
||||
yield fixer.replaceText(
|
||||
typeNode,
|
||||
`(${sourceCode.getText(nodeNode)})`,
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -570,6 +570,19 @@ test("prefer-create-type-check-function", {
|
||||
'const isClassProperty = createTypeCheckFunction(["ClassProperty", "PropertyDefinition"]);',
|
||||
errors: 1,
|
||||
},
|
||||
{
|
||||
code: outdent`
|
||||
const types = new Set(["ClassProperty", "PropertyDefinition"]);
|
||||
if (types.has(node?.type)) {}
|
||||
if (types.has((0, foo).type)) {}
|
||||
`,
|
||||
output: outdent`
|
||||
const __please_rename_this_function_types = createTypeCheckFunction(["ClassProperty", "PropertyDefinition"]);
|
||||
if (__please_rename_this_function_types((node))) {}
|
||||
if (__please_rename_this_function_types((0, foo))) {}
|
||||
`,
|
||||
errors: 1,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
|
||||
Reference in new issue
Block a user