zoukankan      html  css  js  c++  java
  • [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'}],
      }
    }
  • 相关阅读:
    留言板
    移动端开发
    css3的伪类
    JQuery移除事件
    关于offset,你知道多少?
    关于section-scroll插件:
    jQuery响应式弹出层和对话框插插件magnific-popup.css
    col-lg-8 col-lg-offset-2
    关于渐变属 gradient:
    关于 window.onresize
  • 原文地址:https://www.cnblogs.com/Answer1215/p/12323107.html
Copyright © 2011-2022 走看看