eslint-plugin-t
Advanced tools
Comparing version 1.6.0 to 1.7.1
116
lib/index.js
@@ -1,12 +0,1 @@ | ||
function isGlobal(context, identifierName) { | ||
let scope = context.getScope(); | ||
while (scope && scope.type !== 'global') { | ||
if (scope.set.has(identifierName)) { | ||
return false; | ||
} | ||
scope = scope.upper; | ||
} | ||
return true; | ||
} | ||
function isStringLiteral(node) { | ||
@@ -28,9 +17,82 @@ // Not a literal | ||
/** | ||
* Checks to ensure that the source (where it is defined) of the given variable | ||
* is one of the following: | ||
* - An import, e.g. `import { t } from 'i18next'` | ||
* - A React hook, e.g. `const { t } = useTranslation()` | ||
* - A global | ||
*/ | ||
function isFromValidSource(context, identifierName) { | ||
const scope = getScopeForIdentifier(context.getScope(), identifierName); | ||
if (!scope || scope.type === 'global') { | ||
return true; | ||
} | ||
const variable = scope.set.get(identifierName); | ||
const def = | ||
variable === null || variable === void 0 ? void 0 : variable.defs[0]; | ||
if (def) { | ||
if (def.type === 'ImportBinding') { | ||
// TODO: Check `def.parent.source.value` (which is the package name, e.g. | ||
// 'i18next') against a configurable allowlist | ||
return true; | ||
} | ||
if (def.type === 'Variable') { | ||
const node = def.node; | ||
// Something like `const foo = ...` | ||
if (node.type === 'VariableDeclarator') { | ||
const init = node.init; | ||
// Something like `const foo = bar()` | ||
if ( | ||
(init === null || init === void 0 ? void 0 : init.type) === | ||
'CallExpression' | ||
) { | ||
const callee = init.callee; | ||
if (callee.type === 'Identifier') { | ||
// TODO: Check hook name against a configurable allowlist | ||
const isHook = callee.name.match(/^use[A-Z]/); | ||
if (isHook) { | ||
return true; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
return false; | ||
} | ||
function getScopeForIdentifier(scope, identifierName) { | ||
while (scope) { | ||
if (scope.set.has(identifierName)) { | ||
return scope; | ||
} | ||
scope = scope.upper; | ||
} | ||
return null; | ||
} | ||
const rule = { | ||
meta: { | ||
schema: [ | ||
{ | ||
type: 'object', | ||
properties: { | ||
propNames: { | ||
type: 'array', | ||
items: { | ||
type: 'string', | ||
}, | ||
}, | ||
}, | ||
additionalProperties: false, | ||
}, | ||
], | ||
}, | ||
create: (context) => { | ||
const options = context.options[0] || {}; | ||
const propNames = options.propNames || ['jsx', 'frag']; | ||
return { | ||
CallExpression(node) { | ||
let { callee } = node; | ||
let checkCallSignature = (expr) => { | ||
let args = node.arguments; | ||
const { callee } = node; | ||
const checkCallSignature = (expr) => { | ||
const args = node.arguments; | ||
if (!args[0]) { | ||
@@ -43,3 +105,3 @@ context.report({ | ||
} | ||
let arg = args[0]; | ||
const arg = args[0]; | ||
if (!isStringLiteral(arg)) { | ||
@@ -53,14 +115,18 @@ context.report({ | ||
if (callee.type === 'Identifier' && callee.name === 't') { | ||
if (isGlobal(context, 't')) { | ||
if (isFromValidSource(context, 't')) { | ||
checkCallSignature('t()'); | ||
} | ||
} else if ( | ||
callee.type === 'MemberExpression' && | ||
callee.object.type === 'Identifier' && | ||
callee.object.name === 't' && | ||
callee.property.type === 'Identifier' && | ||
callee.property.name === 'frag' | ||
) { | ||
if (isGlobal(context, 't')) { | ||
checkCallSignature('t.frag()'); | ||
} else if (callee.type === 'MemberExpression') { | ||
const object = callee.object; | ||
if (object.type === 'Identifier' && object.name === 't') { | ||
if (isFromValidSource(context, 't')) { | ||
const property = callee.property; | ||
if (property.type === 'Identifier') { | ||
for (const propName of propNames) { | ||
if (property.name === propName) { | ||
checkCallSignature(`t.${propName}()`); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
@@ -67,0 +133,0 @@ } |
{ | ||
"name": "eslint-plugin-t", | ||
"version": "1.6.0", | ||
"version": "1.7.1", | ||
"main": "./lib/index.js", | ||
@@ -5,0 +5,0 @@ "files": [ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
5909
136