| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 | /** * @fileoverview enforce usage of `this` in template. * @author Armano */'use strict'// ------------------------------------------------------------------------------// Requirements// ------------------------------------------------------------------------------const utils = require('../utils')const RESERVED_NAMES = new Set(require('../utils/js-reserved.json'))// ------------------------------------------------------------------------------// Rule Definition// ------------------------------------------------------------------------------module.exports = {  meta: {    docs: {      description: 'enforce usage of `this` in template',      category: 'recommended',      url: 'https://github.com/vuejs/eslint-plugin-vue/blob/v4.7.1/docs/rules/this-in-template.md'    },    fixable: null,    schema: [      {        enum: ['always', 'never']      }    ]  },  /**   * Creates AST event handlers for this-in-template.   *   * @param {RuleContext} context - The rule context.   * @returns {Object} AST event handlers.   */  create (context) {    const options = context.options[0] !== 'always' ? 'never' : 'always'    let scope = {      parent: null,      nodes: []    }    return utils.defineTemplateBodyVisitor(context, Object.assign({      VElement (node) {        scope = {          parent: scope,          nodes: scope.nodes.slice() // make copy        }        if (node.variables) {          for (const variable of node.variables) {            const varNode = variable.id            const name = varNode.name            if (!scope.nodes.some(node => node.name === name)) { // Prevent adding duplicates              scope.nodes.push(varNode)            }          }        }      },      'VElement:exit' (node) {        scope = scope.parent      }    }, options === 'never'      ? {        'VExpressionContainer MemberExpression > ThisExpression' (node) {          const propertyName = utils.getStaticPropertyName(node.parent.property)          if (!propertyName ||            scope.nodes.some(el => el.name === propertyName) ||            RESERVED_NAMES.has(propertyName) || // this.class | this['class']            /^[0-9].*$|[^a-zA-Z0-9_]/.test(propertyName) // this['0aaaa'] | this['foo-bar bas']          ) {            return          }          context.report({            node,            loc: node.loc,            message: "Unexpected usage of 'this'."          })        }      }      : {        'VExpressionContainer' (node) {          if (node.references) {            for (const reference of node.references) {              if (!scope.nodes.some(el => el.name === reference.id.name)) {                context.report({                  node: reference.id,                  loc: reference.id.loc,                  message: "Expected 'this'."                })              }            }          }        }      }    ))  }}
 |