Skip to content
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

Parsing error on optional chaining (?.) token #1084

Closed
soullivaneuh opened this issue Mar 23, 2020 · 4 comments
Closed

Parsing error on optional chaining (?.) token #1084

soullivaneuh opened this issue Mar 23, 2020 · 4 comments

Comments

@soullivaneuh
Copy link

soullivaneuh commented Mar 23, 2020

Tell us about your environment

  • ESLint version: 6.6.0
  • eslint-plugin-vue version: 6.2.2
  • Node version: 12

Please show your full configuration:

const fs = require('fs');

// Import AirBNB base rules to wrap them onto framework specific configs.
const airbnbRulesStyle = require('eslint-config-airbnb-base/rules/style').rules;
const airbnbRulesES6 = require('eslint-config-airbnb-base/rules/es6').rules;
const airbnbRulesBestPractices = require('eslint-config-airbnb-base/rules/best-practices').rules;

const maxLenBaseRule = {
  code: 120,
  ignoreUrls: true,
};

const rules = {
  'object-property-newline': ['error', {
    allowAllPropertiesOnSameLine: false,
  }],
  'array-element-newline': ['error', 'consistent'],
  'array-bracket-newline': ['error', 'consistent'],
  'max-len': ['error', maxLenBaseRule],
  'no-param-reassign': ['error', {
    props: false,
  }],
  'no-plusplus': ['error', {
    allowForLoopAfterthoughts: true,
  }],
  'no-underscore-dangle': ['error', {
    allow: ['_id'],
  }],
  'import/extensions': ['error', 'always', {
    js: 'never',
    ts: 'never',
  }],
  'import/no-extraneous-dependencies': 'off',
};

const tsRules = {
  '@typescript-eslint/explicit-function-return-type': ['error', {
    allowExpressions: true,
  }],
  '@typescript-eslint/no-unused-vars': ['error', {
    args: 'none',
  }],
  '@typescript-eslint/no-explicit-any': 'off',
};

if (!fs.existsSync('node_modules')) {
  rules['import/no-unresolved'] = 'off';
}

const vueRules = {
  indent: 'off', // @see https://eslint.vuejs.org/rules/script-indent.html#options
  'vue/array-bracket-spacing': airbnbRulesStyle['array-bracket-spacing'],
  'vue/arrow-spacing': airbnbRulesES6['arrow-spacing'],
  'vue/block-spacing': airbnbRulesStyle['block-spacing'],
  'vue/brace-style': airbnbRulesStyle['brace-style'],
  'vue/camelcase': airbnbRulesStyle.camelcase,
  'vue/comma-dangle': airbnbRulesStyle['comma-dangle'],
  'vue/component-definition-name-casing': 'error',
  'vue/component-name-in-template-casing': 'error',
  'vue/component-tags-order': ['error', {
    order: ['script', 'style', 'template'],
  }],
  'vue/dot-location': airbnbRulesBestPractices['dot-location'],
  'vue/eqeqeq': airbnbRulesBestPractices.eqeqeq,
  'vue/key-spacing': airbnbRulesStyle['key-spacing'],
  'vue/keyword-spacing': airbnbRulesStyle['keyword-spacing'],
  'vue/match-component-file-name': ['error', {
    extensions: ['vue'],
    shouldMatchCase: true,
  }],
  'vue/max-len': ['error', maxLenBaseRule],
  'vue/no-empty-pattern': airbnbRulesBestPractices['no-empty-pattern'],
  'vue/no-irregular-whitespace': 'error',
  'vue/no-reserved-component-names': 'error',
  'vue/no-restricted-syntax': airbnbRulesStyle['no-restricted-syntax'],
  'vue/object-curly-spacing': airbnbRulesStyle['object-curly-spacing'],
  'vue/padding-line-between-blocks': 'error',
  'vue/script-indent': ['error', 2, {
    baseIndent: 1,
  }],
  'vue/space-infix-ops': airbnbRulesStyle['space-infix-ops'],
  'vue/space-unary-ops': airbnbRulesStyle['space-unary-ops'],
  'vue/v-on-function-call': 'error',
  'vue/v-slot-style': 'error',
  'vue/valid-v-slot': 'error',
};

module.exports = {
  env: {
    browser: true,
    commonjs: true,
    es6: true,
    node: true,
    jquery: true,
    'cypress/globals': true,
  },
  plugins: [
    'cypress',
    '@typescript-eslint',
  ],
  extends: [
    'eslint:recommended',
    'airbnb',
  ],
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaVersion: 2018,
    sourceType: 'module',
  },
  rules,
  overrides: [
    {
      files: ['*.ts'],
      extends: [
        'plugin:@typescript-eslint/eslint-recommended',
        'plugin:@typescript-eslint/recommended',
      ],
      rules: tsRules,
    },
    {
      files: ['*.vue'],
      extends: [
        'plugin:vue/recommended',
      ],
      rules: vueRules,
    },
  ],
  settings: {
    'import/resolver': {
      node: {
        extensions: [
          '.js',
          '.jsx',
          '.ts',
          '.d.ts',
          '.tsx',
        ],
      },
    },
  },
};

What did you do?

<script>
  const testObject = {};
  const test = testObject?.foo;
  console.log(test);

  export default {
    name: 'MyComponent',
    props: {
      title: {
        default: null,
        type: String,
      },
    },
  };
</script>

<template>
  <div class="panel panel-default">
    <div
      v-if="this.$slots.header || this.$slots.title || title"
      class="panel-heading"
    >
      <slot name="header">
        <h4 class="panel-title">
          <slot name="title">
            {{ title }}
          </slot>
        </h4>
      </slot>
    </div>
    <div class="panel-body">
      <slot />
    </div>
    <div
      v-if="this.$slots.footer"
      class="panel-footer"
    >
      <slot name="footer" />
    </div>

    <ul id="example-1">
      <li
        v-for="item in [1,2,3]"
        :key="item"
      >
        {{ item }}
      </li>
    </ul>
  </div>
</template>

What did you expect to happen?

Successful lint

What actually happened?

/code/fixtures/MyComponent.vue
  3:26  error  Parsing error: Unexpected token .

See also: https://gitlab.com/nexylan/pretty/-/merge_requests/89

Note: Optional chaining parsing works on eslint core, only the plugin parser crashes.

@soullivaneuh soullivaneuh changed the title Parsing error on ?. token Parsing error on optional chaining (?.) token Mar 23, 2020
@ota-meshi
Copy link
Member

Hi.

You may need to use babel-eslint or @typescript-eslint/parser for .vue to solve the problem.

    {
      files: ['*.vue'],
      extends: [
        'plugin:vue/recommended',
      ],
+      parserOptions: {
+        parser: '@typescript-eslint/parser',
+      },
      rules: vueRules,
    },

https://eslint.vuejs.org/user-guide/#how-to-use-a-custom-parser

The parser that eslint uses by default does not yet support Optional Chaining.

eslint/eslint#12642

@ota-meshi
Copy link
Member

If the problem persists, please reopen this issue.

@soullivaneuh
Copy link
Author

@ota-meshi Thanks for the answer, but that didn't help.

Using the parser now give me this error (with the same vue file):

/code/fixtures/MyComponent.vue
  7:8  error  Parsing error: '}' expected

But the file seems correct.

Also, this parser is already set globally and works with my *.ts override. Why not with the *.vue override? 🤔

@chenjiangui
Copy link

only support (?.), unsupport (!.)
image
image
my config

module.exports = {
  root: true,
  parser: 'vue-eslint-parser',
  parserOptions: {
    parser: '@typescript-eslint/parser',
    ecmaVersion: 2020,
    sourceType: 'module'
  },
  globals: {
    defineExpose: 'readonly',
    defineEmits: 'readonly',
    withDefaults: 'readonly',
    defineProps: 'readonly',
    Optional: 'readonly',
    Serialize: 'readonly'
  },
  env: {
    node: true
  },
  extends: [
    'plugin:vue/vue3-recommended',
    'eslint:recommended',
    '@vue/typescript/recommended',
    '@vue/prettier',
    '@vue/prettier/@typescript-eslint'
  ],
  rules: {
    '@typescript-eslint/ban-ts-comment': 'off',
    '@typescript-eslint/explicit-module-boundary-types': 'off',
    'prettier/prettier': 'error',
    '@typescript-eslint/no-explicit-any': 'error',
    '@typescript-eslint/no-unused-vars': 'error',
    '@typescript-eslint/no-non-null-assertion': 'off',
    'vue/require-default-prop': 'off'
  }
};

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

3 participants