eslint-plugin-rxjs
Version:
ESLint rules for RxJS
188 lines (187 loc) • 7.2 kB
JavaScript
const eslint_etc_1 = require("eslint-etc");
const utils_1 = require("../utils");
const defaultOptions = [];
const rule = (0, utils_1.ruleCreator)({
defaultOptions,
meta: {
docs: {
description: "Enforces the use of a suffix in subject identifiers.",
recommended: false,
},
fixable: undefined,
hasSuggestions: false,
messages: {
forbidden: `Subject identifiers must end with "{{suffix}}".`,
},
schema: [
{
properties: {
parameters: { type: "boolean" },
properties: { type: "boolean" },
suffix: { type: "string" },
types: { type: "object" },
variables: { type: "boolean" },
},
type: "object",
},
],
type: "problem",
},
name: "suffix-subjects",
create: (context, unused) => {
const { esTreeNodeToTSNodeMap } = (0, eslint_etc_1.getParserServices)(context);
const { couldBeType } = (0, eslint_etc_1.getTypeServices)(context);
const [config = {}] = context.options;
const validate = {
parameters: true,
properties: true,
variables: true,
...config,
};
const types = [];
if (config.types) {
Object.entries(config.types).forEach(([key, validate]) => {
types.push({ regExp: new RegExp(key), validate });
});
}
else {
types.push({
regExp: /^EventEmitter$/,
validate: false,
});
}
const { suffix = "Subject" } = config;
const suffixRegex = new RegExp(String.raw `${(0, utils_1.escapeRegExp)(suffix)}\$?$`, "i");
function checkNode(nameNode, typeNode) {
let tsNode = esTreeNodeToTSNodeMap.get(nameNode);
const text = tsNode.getText();
if (!suffixRegex.test(text) &&
couldBeType(typeNode || nameNode, "Subject")) {
for (const type of types) {
const { regExp, validate } = type;
if (couldBeType(typeNode || nameNode, regExp) && !validate) {
return;
}
}
context.report({
data: { suffix },
loc: (0, eslint_etc_1.getLoc)(tsNode),
messageId: "forbidden",
});
}
}
return {
"ArrayPattern > Identifier": (node) => {
const found = (0, eslint_etc_1.findParent)(node, "ArrowFunctionExpression", "FunctionDeclaration", "FunctionExpression", "VariableDeclarator");
if (!found) {
return;
}
if (!validate.variables && found.type === "VariableDeclarator") {
return;
}
if (!validate.parameters) {
return;
}
checkNode(node);
},
"ArrowFunctionExpression > Identifier": (node) => {
if (validate.parameters) {
const parent = (0, eslint_etc_1.getParent)(node);
if (node !== parent.body) {
checkNode(node);
}
}
},
"PropertyDefinition[computed=false]": (node) => {
const anyNode = node;
if (validate.properties) {
checkNode(anyNode.key);
}
},
"FunctionDeclaration > Identifier": (node) => {
if (validate.parameters) {
const parent = (0, eslint_etc_1.getParent)(node);
if (node !== parent.id) {
checkNode(node);
}
}
},
"FunctionExpression > Identifier": (node) => {
if (validate.parameters) {
const parent = (0, eslint_etc_1.getParent)(node);
if (node !== parent.id) {
checkNode(node);
}
}
},
"MethodDefinition[kind='get'][computed=false]": (node) => {
if (validate.properties) {
checkNode(node.key, node);
}
},
"MethodDefinition[kind='set'][computed=false]": (node) => {
if (validate.properties) {
checkNode(node.key, node);
}
},
"ObjectExpression > Property[computed=false] > Identifier": (node) => {
if (validate.properties) {
const parent = (0, eslint_etc_1.getParent)(node);
if (node === parent.key) {
checkNode(node);
}
}
},
"ObjectPattern > Property > Identifier": (node) => {
const found = (0, eslint_etc_1.findParent)(node, "ArrowFunctionExpression", "FunctionDeclaration", "FunctionExpression", "VariableDeclarator");
if (!found) {
return;
}
if (!validate.variables && found.type === "VariableDeclarator") {
return;
}
if (!validate.parameters) {
return;
}
const parent = (0, eslint_etc_1.getParent)(node);
if (node === parent.value) {
checkNode(node);
}
},
"TSCallSignatureDeclaration > Identifier": (node) => {
if (validate.parameters) {
checkNode(node);
}
},
"TSConstructSignatureDeclaration > Identifier": (node) => {
if (validate.parameters) {
checkNode(node);
}
},
"TSMethodSignature > Identifier": (node) => {
if (validate.parameters) {
checkNode(node);
}
},
"TSParameterProperty > Identifier": (node) => {
if (validate.parameters || validate.properties) {
checkNode(node);
}
},
"TSPropertySignature[computed=false]": (node) => {
const anyNode = node;
if (validate.properties) {
checkNode(anyNode.key);
}
},
"VariableDeclarator > Identifier": (node) => {
const parent = (0, eslint_etc_1.getParent)(node);
if (validate.variables && node === parent.id) {
checkNode(node);
}
},
};
},
});
module.exports = rule;
;