[AST ESlint] Prevent Console log, edge case, variable reference
For eslint prevent console plugin, we also want to prevent user do so:
var csl = console csl.log()
Code:
const disallowedMethods = [‘log‘, ‘info‘, ‘warn‘, ‘error‘, ‘dir‘]
module.exports = {
meta: {
docs: {
description: ‘Disallow use of console‘,
category: ‘Best Practices‘,
recommended: true,
},
schema: [
{
type: ‘object‘,
properties: {
allowedMethods: {
type: ‘array‘,
items: {
enum: [‘log‘, ‘info‘, ‘warn‘, ‘error‘, ‘dir‘],
},
minItems: 1,
uniqueItems: true,
},
},
},
],
},
create(context) {
const config = context.options[0] || {}
const allowedMethods = config.allowedMethods || []
const consoleUsage = []
return {
Identifier(node) {
if (node.name !== ‘console‘) {
return
}
consoleUsage.push(node)
},
/**
* By the time
* var csl = console
csl.log()
compiler hasn‘t exected csl.log
We have to do in ‘Program:exit‘
*/
‘Program:exit‘() {
consoleUsage.forEach(identifier => {
if (isDisallowedFunctionCall(identifier)) {
context.report({
node: identifier.parent.property,
message: ‘Using console is not allowed‘,
})
} else {
const variableDeclaratorParent = findParent(
identifier,
parent => parent.type === ‘VariableDeclarator‘,
)
if (variableDeclaratorParent) {
const references = context
.getDeclaredVariables(variableDeclaratorParent)[0]
.references.slice(1)
references.forEach(reference => {
if (
!looksLike(reference, {
identifier: {
parent: {
property: isDisallowedFunctionCall,
},
},
})
) {
return
}
context.report({
node: reference.identifier.parent.property,
message: ‘Using console is not allowed‘,
})
})
}
}
})
},
}
function isDisallowedFunctionCall(identifier) {
return looksLike(identifier, {
parent: {
type: ‘MemberExpression‘,
parent: {type: ‘CallExpression‘},
property: {
name: val =>
!allowedMethods.includes(val) && disallowedMethods.includes(val),
},
},
})
}
},
}
function findParent(node, test) {
if (test(node)) {
return node
} else if (node.parent) {
return findParent(node.parent, test)
}
return null
}
function looksLike(a, b) {
return (
a &&
b &&
Object.keys(b).every(bKey => {
const bVal = b[bKey]
const aVal = a[bKey]
if (typeof bVal === ‘function‘) {
return bVal(aVal)
}
return isPrimitive(bVal) ? bVal === aVal : looksLike(aVal, bVal)
})
)
}
function isPrimitive(val) {
return val == null || /^[sbn]/.test(typeof val)
}Test:
const {RuleTester} = require(‘eslint‘)
const rule = require(‘./no-console-5‘)
const ruleTester = new RuleTester()
ruleTester.run(‘no-console‘, rule, {
valid: [
‘info()‘,
‘console‘,
‘console.log‘,
‘console.baz()‘,
{code: ‘console.warn()‘, options: [{allowedMethods: [‘warn‘]}]},
],
invalid: [
invalid(‘console.log()‘),
invalid(‘console.info()‘),
invalid(‘console.warn()‘),
invalid(
`
var csl = console
csl.log()
`,
),
],
})
function invalid(code) {
return {
code,
errors: [{message: ‘Using console is not allowed‘}],
}
} 相关推荐
zhuxue 2020-10-14
zhangbingb 2020-09-21
HeronLinuxampARM 2020-09-14
美丽的泡沫 2020-09-08
goodstudy 2020-08-19
luvhl 2020-08-17
littleFatty 2020-08-16
gamestart0 2020-08-15
URML 2020-08-15
sfkong 2020-08-02
82941732 2020-07-27
偏头痛杨 2020-07-18
timewind 2020-07-04
89407707 2020-06-27
xiaoxiaoCNDS 2020-06-26
lyjava 2020-06-26
运算符用于执行程序代码运算,会针对一个以上操作数项目来进行运算。以上实例中 7、5 和 12 是操作数。关系运算符用于计算结果是否为 true 或者 false。逻辑运算符用于测定变量或值之间的逻辑。
ChaITSimpleLove 2020-06-25
Strongding 2020-06-25