eslint-plugin-budapestian
Version:
enforce budapestian style rules
153 lines (138 loc) • 4.04 kB
JavaScript
const decamelize = require("decamelize");
const {
getVariableDeclaratorName,
isConstDeclaration,
isExportNamedDeclaration,
} = require("./ast-utl");
const {
// getIdentifierReplacementPattern,
isNotAnException,
isOneOfValidPrefixedIdentifiers,
} = require("./pattern-utl");
const VALID_GLOBAL_CONSTANT_PATTERN = /^[\p{Lu}][\p{Lu}\p{N}_]*$/u;
/**
* @fileoverview Enforce global constants to adhere to a pattern
* @author sverweij
*/
function normalizeConstantName(pString) {
let lReturnValue = pString;
if (isOneOfValidPrefixedIdentifiers(pString, ["g", "l", "p"])) {
lReturnValue = pString.substring(1);
}
return decamelize(lReturnValue).toLocaleUpperCase();
}
function constantNameIsValid(pString) {
return VALID_GLOBAL_CONSTANT_PATTERN.test(pString);
}
// function getFixes(pContext, pNode, pProblematicConstantNames) {
// return (pFixer) => {
// let lBetterized = pProblematicConstantNames.reduce(
// (pSource, pProblematicConstantName) =>
// pSource.replace(
// getIdentifierReplacementPattern(pProblematicConstantName),
// `$1${normalizeConstantName(pProblematicConstantName)}$2`
// ),
// pContext.getSourceCode().getText(pNode)
// );
// return pFixer.replaceText(pNode, lBetterized);
// };
// }
function isProblematicConstDeclarator(pDeclarator) {
return (
!constantNameIsValid(getVariableDeclaratorName(pDeclarator)) &&
[
"Literal",
"BinaryExpression",
"Identifier",
"ArrayExpression",
"ObjectExpression",
].includes(pDeclarator.init.type)
);
}
function getProblematicGlobalConstantsFromBody(pBody, pAllowedConstantNames) {
const lExportConsts = pBody
.filter(isExportNamedDeclaration)
.map((pNode) => pNode.declaration)
.filter((pDeclaration) => pDeclaration !== null)
.filter(isConstDeclaration);
const lGlobaConsts = pBody.filter(isConstDeclaration);
return lExportConsts
.concat(lGlobaConsts)
.reduce(
(pAll, pConstantDeclaration) =>
pAll.concat(
pConstantDeclaration.declarations
.filter(isProblematicConstDeclarator)
.map(getVariableDeclaratorName)
.filter(isNotAnException(pAllowedConstantNames)),
),
[],
);
}
function reportProblematicGlobalConstants(
pNode,
pContext,
pProblematicConstants,
) {
pProblematicConstants.forEach(
// (pProblematicConstantName, _pIndex, pAllProblematicConstantNames) => {
(pProblematicConstantName) => {
pContext.report({
node: pNode,
message: `global constant '{{ identifier }}' should be snaked upper case: '{{ betterIdentifier }}'`,
data: {
identifier: pProblematicConstantName,
betterIdentifier: normalizeConstantName(pProblematicConstantName),
},
// fix: getFixes(pContext, pNode, pAllProblematicConstantNames),
});
},
);
}
module.exports = {
meta: {
type: "suggestion",
docs: {
description:
"Enforce global constants for literals to adhere to a pattern",
category: "Stylistic Issues",
recommended: false,
url: "https://sverweij.github.io/eslint-plugin-budapestian/rules/global-constant-pattern",
},
schema: {
type: "array",
items: {
type: "object",
properties: {
exceptions: {
type: "array",
items: {
type: "string",
},
},
},
additionalProperties: false,
},
minItems: 0,
maxItems: 1,
},
// fixable: "code",
fixable: false,
},
create: (pContext) => {
return {
Program(pNode) {
const lExceptions = pContext?.options[0]?.exceptions ?? [];
const lProblematicConstants = getProblematicGlobalConstantsFromBody(
pNode.body,
lExceptions,
);
reportProblematicGlobalConstants(
pNode,
pContext,
lProblematicConstants,
);
},
};
},
};