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'}],
      }
    }
  • 相关阅读:
    智能移动机器人背后蕴含的技术——激光雷达
    Kalman Filters
    Fiddler抓HttpClient的包
    VSCode开发WebApi EFCore的坑
    WPF之小米Logo超圆角的实现
    windows react打包发布
    jenkins in docker踩坑汇总
    Using ML.NET in Jupyter notebooks 在jupyter notebook中使用ML.NET ——No design time or full build available
    【Linux知识点】CentOS7 更换阿里云源
    【Golang 报错】exec gcc executable file not found in %PATH%
  • 原文地址:https://www.cnblogs.com/Answer1215/p/12323107.html
Copyright © 2011-2022 走看看