Repository: vuejs/eslint-plugin-vue (JavaScript)

Issue:
require-explicit-emits does not find 'emits' in quotes
<!--
  ❗Please don't ignore this template.❗

  If you ignore it, we're just going to respond asking you to fill it out, which wastes everyone's time.
  The more relevant information you can include, the faster we can find the issue and fix it without asking you for more info.
-->

<!--
  Before posting the issue, please confirm that the problem you're getting
  is not related with your code editor configuration.
  To make sure it's not, run: yarn eslint src/your-file.vue
-->

**Checklist**

- [x] I have tried restarting my IDE and the issue persists.
- [x] I have read the [FAQ](https://eslint.vuejs.org/user-guide/#faq) and my problem is not listed.
<!-- If you do not read the FAQ and open an issue that is listed in the FAQ, we may silently close the issue. -->

**Tell us about your environment**

- **ESLint version:**  7.18.0
- **eslint-plugin-vue version:** 7.4.1
- **Node version:** v14.15.4
- **Operating System:** macOS 11.1

**Please show your full configuration:**
<!-- Paste content of your .eslintrc file -->
```json5
module.exports = {
  'env': {
    'browser': true,
    'es6': true,
    'node': true,
  },
  'extends': [
    'airbnb-base',
    'plugin:vue/vue3-recommended',
  ],
  'plugins': [
    'vue',
  ],
  'rules': {
    'semi': 'error',
    'quotes': ['error', 'single'],
    'quote-props': ['error', 'always'],
    'no-multiple-empty-lines': ['error', { 'max': 1, 'maxEOF': 1 }],
    'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'warn',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'warn',
    'vue/no-unused-components': process.env.NODE_ENV === 'production' ? 'error' : 'warn',
    'vue/max-attributes-per-line': 'off',
    'vue/prop-name-casing': ['error', 'camelCase'],
    'max-len': ['error', {
      'code': 240, 'ignoreStrings': true, 'ignoreComments': true, 'ignoreTrailingComments': true, 'ignoreUrls': true,
    }],
    'indent': ['error', 2],
    'comma-dangle': ['error', {
      'arrays': 'only-multiline',
      'objects': 'always-multiline',
      'imports': 'only-multiline',
      'exports': 'only-multiline',
      'functions': 'never',
    }],
    'no-param-reassign': ['warn', { 'props': false }],
    'lines-between-class-members': 'off',
    'prefer-destructuring': ['error', { 'object': true, 'array': false }],
    'no-plusplus': ['error', { 'allowForLoopAfterthoughts': true }],
    'import/no-extraneous-dependencies': 'off',
  },
  'ignorePatterns': ['temp.js', '**/fontawesome-pro/**'],
  'settings': {
    'import/resolver': {
      'alias': {
        'map': [
          ['@', './src'],
        ],
        'extensions': ['.ts', '.js', '.jsx', '.json', '.vue'],
      },
    },
  },
};

```

**What did you do?**	
<!-- Please include the actual source code causing the issue. -->
```vue
<template>
  <div class="w-16 h-16 flex flex-wrap justify-center content-center">
    <span class="text-2xl" @click="$emit('actionclicked')"><i :class="`fal fa-${icon}`" /></span>
    <span v-if="label">{{ label }}</span>
  </div>
</template>

<script>
export default {
  'props': {
    'icon': { 'type': String, 'required': true },
    'label': { 'type': String, 'default': '' },
    'active': { 'type': Boolean, 'default': false },
  },
  'emits': ['actionclicked'],
};
</script>

```

**What did you expect to happen?**
No warning

**What actually happened?**
<!--
  Please include the actual, raw output from ESLint.
  If you are only looking at the results of your editor extension, also check the CLI results.
-->
/Users/ehutch79/Sites/Slate/slate-v4-testing/src/views/base/navbar/navbarAction.vue
  3:42  warning  The "actionclicked" event has been triggered but not declared on `emits` option  vue/require-explicit-emits

I have the 'quote-props' rule turned on, and with autofix in vscode, option properties like props and emits get quoted automatically.

```vue/require-explicit-emits``` works fine if I remove the quotes from from the emits property, and disable the 'quote-props' check for the line with  ```// eslint-disable-next-line quote-props```.

The issue is definitely that the rule check is not finding emits when declared with quotes.


Discussion:

Patch:
diff --git a/lib/utils/index.js b/lib/utils/index.js
index 35521255b..0bcf80169 100644
--- a/lib/utils/index.js
+++ b/lib/utils/index.js
@@ -544,8 +544,7 @@ module.exports = {
       (p) => {
         return (
           p.type === 'Property' &&
-          p.key.type === 'Identifier' &&
-          p.key.name === 'components' &&
+          getStaticPropertyName(p) === 'components' &&
           p.value.type === 'ObjectExpression'
         )
       }
@@ -677,8 +676,7 @@ module.exports = {
       (p) => {
         return (
           p.type === 'Property' &&
-          p.key.type === 'Identifier' &&
-          p.key.name === 'props' &&
+          getStaticPropertyName(p) === 'props' &&
           (p.value.type === 'ObjectExpression' ||
             p.value.type === 'ArrayExpression')
         )
@@ -748,8 +746,7 @@ module.exports = {
       (p) => {
         return (
           p.type === 'Property' &&
-          p.key.type === 'Identifier' &&
-          p.key.name === 'emits' &&
+          getStaticPropertyName(p) === 'emits' &&
           (p.value.type === 'ObjectExpression' ||
             p.value.type === 'ArrayExpression')
         )
@@ -819,8 +816,7 @@ module.exports = {
       (p) => {
         return (
           p.type === 'Property' &&
-          p.key.type === 'Identifier' &&
-          p.key.name === 'computed' &&
+          getStaticPropertyName(p) === 'computed' &&
           p.value.type === 'ObjectExpression'
         )
       }


Test patch:
diff --git a/tests/lib/rules/require-explicit-emits.js b/tests/lib/rules/require-explicit-emits.js
index 4f27563cd..31ad623a4 100644
--- a/tests/lib/rules/require-explicit-emits.js
+++ b/tests/lib/rules/require-explicit-emits.js
@@ -140,6 +140,20 @@ tester.run('require-explicit-emits', rule, {
       </script>
       `
     },
+    // quoted
+    {
+      filename: 'test.vue',
+      code: `
+      <template>
+        <div @click="$emit('welcome')"/>
+      </template>
+      <script>
+      export default {
+        'emits': ['welcome']
+      }
+      </script>
+      `
+    },
     // unknown
     {
       filename: 'test.vue',
diff --git a/tests/lib/rules/return-in-computed-property.js b/tests/lib/rules/return-in-computed-property.js
index df6b1b680..4a988e86b 100644
--- a/tests/lib/rules/return-in-computed-property.js
+++ b/tests/lib/rules/return-in-computed-property.js
@@ -394,6 +394,23 @@ ruleTester.run('return-in-computed-property', rule, {
           line: 5
         }
       ]
+    },
+    {
+      filename: 'test.vue',
+      code: `
+      export default {
+        'computed': {
+          foo() {
+          }
+        }
+      }`,
+      parserOptions,
+      errors: [
+        {
+          message: 'Expected to return a value in "foo" computed property.',
+          line: 4
+        }
+      ]
     }
   ]
 })