Skip to content

False negative with vue/no-unused-properties #1462

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
2 tasks done
dsl101 opened this issue Mar 22, 2021 · 8 comments
Closed
2 tasks done

False negative with vue/no-unused-properties #1462

dsl101 opened this issue Mar 22, 2021 · 8 comments

Comments

@dsl101
Copy link
Contributor

dsl101 commented Mar 22, 2021

Checklist

  • I have tried restarting my IDE and the issue persists.
  • I have read the FAQ and my problem is not listed.

Tell us about your environment

  • ESLint version: v7.16.0
  • eslint-plugin-vue version: 7.7.0
  • Node version: v14.16.0
  • Operating System: Windows 10 Pro

Please show your full configuration:

module.exports = {
  root: true,

  parserOptions: {
    parser: 'babel-eslint',
    ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features
    sourceType: 'module'
  },

  env: {
    browser: true
  },

  extends: [
    // https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
    // consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
    'eslint:recommended',
    'plugin:vue/recommended',
    'plugin:quasar/standard',
    'plugin:import/errors',
    'plugin:import/warnings',
    // '@vue/standard'
  ],

  // required to lint *.vue files
  plugins: [
    // 'vue',
    // 'quasar',
    // 'import',
  ],
  // "settings": {
  //   "import/resolver": {
  //     "webpack": {
  //       "config": "webpack.config-base.js"
  //     }
  //   }
  // },

  'settings': {
    'import/resolver': 'webpack'
    // 'import/resolver': {
    //   'webpack': {
    //     'config': 'build/webpack.base.conf.js'
    //   }
    // }
  },

  globals: {
    // '_': false,
    'APP_VERSION': 'readonly',
    '__dirname': 'readonly',
    'module': 'writable',
    // 'ga': true, // Google Analytics
    // 'cordova': true,
    // '__statics': true,
    'process': 'readonly',
    'require': 'readonly'
  },

  // add your custom rules here
  rules: {
    // Quasar
    'vue/order-in-components': 'off',
    'no-shadow': ['error', { 'builtinGlobals': true, 'hoist': 'functions', 'allow': [] }],
    // allow async-await
    'generator-star-spacing': 'off',
    // allow paren-less arrow functions
    'arrow-parens': 'off',
    'one-var': 'off',

    // 'import/first': 'off',
    // 'import/named': 'error',
    // 'import/namespace': 'error',
    // 'import/default': 'error',
    // 'import/export': 'error',
    // 'import/extensions': 'off',
    // 'import/no-unresolved': 'off',
    // 'import/no-extraneous-dependencies': 'off',
    'prefer-promise-reject-errors': 'off',

    // Allow v-for and v-if when not trivial to replace
    'vue/no-use-v-if-with-v-for': ['error', {
      'allowUsingIterationVar': true
    }],

    'vue/no-parsing-error': ['error', {
      // For {{ a < b ? 'thing1' : 'thing2' }}
      // See https://github.com/vuejs/eslint-plugin-vue/issues/370
      "invalid-first-character-of-tag-name": false
    }],
    'vue/mustache-interpolation-spacing': 'off',
    'vue/attributes-order': ['error', { order: [
      'DEFINITION',  // is
      'LIST_RENDERING',  // v-for
      'CONDITIONALS',  // v-if
      'RENDER_MODIFIERS',  // v-once
      'UNIQUE',  // ref
      'GLOBAL',  // id
      'SLOT',  // slot / v-slot
      'TWO_WAY_BINDING',  // v-model
      'OTHER_DIRECTIVES',  // v-close-overlay
      'OTHER_ATTR',  // class="xyz" / :prop
      'EVENTS',  // @event
      'CONTENT',  // v-html
    ]}],
    'vue/max-attributes-per-line': ['error', {
      'singleline': 6,
      'multiline': {
        'max': 3,
        'allowFirstLine': true
      }
    }],
    'vue/html-indent': ['warn', 2, {
      'attribute': 1,
      'closeBracket': 0,
      'alignAttributesVertically': false,
      'ignores': []
    }],
    'vue/singleline-html-element-content-newline': 'off',
    'vue/multiline-html-element-content-newline': ['error', {
        'ignoreWhenEmpty': true,
        'allowEmptyLines': true
    }],
    'vue/no-unused-properties': ['error', {
      'groups': [ 'props', 'data', 'computed', 'methods' ],
      'deepData': true,
      'ignorePublicMembers': true
    }],
    'no-multiple-empty-lines': ['warn', {
      'max': 2
    }],
    // "vue/multiline-html-element-content-newline": ["error", {
    //     "ignoreWhenEmpty": true,
    //     "ignores": ["pre", "textarea", ...INLINE_ELEMENTS],
    //     "allowEmptyLines": false
    // }],

    // 'quasar/check-valid-props': 2,
    // 'quasar/no-invalid-qfield-usage': 2,
    // 'quasar/no-legacy-directives': 2,

    'require-atomic-updates': 'off',

    // allow console.log during development only
    'no-console': process.env.NODE_ENV === 'production' ? 'error' : ["warn", { allow: ["warn", "error"] }],
    // allow debugger during development only
    'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'warn'
  }
}

What did you do?

I have a number of components using an event bus, which contain code such as this:

<script>
  export default {
    mounted () {
      const handlerName = 'eventHandler'
      // Event registration code ommitted, but would end up calling via:
      this[handlerName]
    },
    methods: {
      eventHandler () {
        // Used
      },
      notused () {
        // should show as error
      }
    }
  }
</script>

Note that neither of the methods are flagged as unused. One of them would be called via the event handler, but any use of this[variable] appears to completely defeat any unused method checking (i.e. all methods are assumed as used).

What did you expect to happen?
That any methods not explicitly called would be flagged as unused. Note, this may be the intended behaviour, but I couldn't find anything in the documentation about this use case, or if there was a configuration option for it.

What actually happened?
No output from eslint.

I am using /** @public */ to mark methods that are called externally, and was hoping that internal methods could be handled in the same way—i.e. that all methods used by this event handling approach would be flagged by eslint as unused, and I would manually label each one that is actually used by the event handling code.

@NeonWizard
Copy link

NeonWizard commented Apr 24, 2021

Same issue here - no-unused-properties is not detecting unused methods.

Rule configuration

"vue/no-unused-properties": ["warn", {
    "groups": ["props", "data", "computed", "methods"]
}]

Example

<template>
    <MyComponent @highlight="onHighlight" />
</template>
<script>
  export default {
    methods: {
      // No warning (expected)
      onHighlight () { },
      // No warning (unexpected)
      notused () { }
    }
  }
</script>

@IWANABETHATGUY
Copy link
Contributor

<script>
  export default {
    mounted () {
      const handlerName = 'eventHandler'
      // Event registration code ommitted, but would end up calling via:
      this[handlerName]
    },
    methods: {
      eventHandler () {
        // Used
      },
      notused () {
        // should show as error
      }
    }
  }
</script>

code like above is hard to static analyze, the handlerName is runtime determistic, for example , what if your handlerName is
concatenation during runtime like below.

<script>
  export default {
    mounted () {
      const handlerName = ''
      for(let i = 0; i < 5; i++) {
        handlerName += 'r';
      }
      // Event registration code ommitted, but would end up calling via:
      this[handlerName]
    },
    methods: {
      rrrrr() {
        // Used
      },
      notused () {
        // should show as error
      }
    }
  }
</script>

@dsl101
Copy link
Contributor Author

dsl101 commented May 29, 2021 via email

@IWANABETHATGUY
Copy link
Contributor

so this should be a feature request instead of a bug,

@IWANABETHATGUY
Copy link
Contributor

Currently, you could use eslint-plugin-vueunused with eslint-plugin-vue, eslint-plugin-vueunused more concentrate on deadcode detect, here you could see the difference
https://iwanabethatguy.github.io/eslint-plugin-vueunused/

@dsl101
Copy link
Contributor Author

dsl101 commented May 29, 2021

so this should be a feature request instead of a bug,

I will check out the -vuenotused plugin, but I still think the default behaviour is inconsistent—methods not explicitly called should be marked as not used, and just because a method might be called (with this[handler]), that should not cause every method to be considered 'used'. That seems more like a bug than a feature. Otherwise, every method which might be called externally should also be considered used, and there'd be no need for the JSDoc @public annotation.

@dsl101
Copy link
Contributor Author

dsl101 commented Jun 7, 2021

I tried the plugin you mentioned, but (a) I prefer the single underline warning of the method name over the large yellow 'block' highlight (and I couldn't see a way to configure this from the docs), and (b) it specifically does not appear to pick up /** @public */ decorations for externally called methods, leaving false positives.

@ota-meshi
Copy link
Member

I close this issue because #1636 was suggested to add an option.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants