dense-analysis / ale

Check syntax in Vim/Neovim asynchronously and fix files, with Language Server Protocol (LSP) support
BSD 2-Clause "Simplified" License
13.52k stars 1.43k forks source link

add support for eslint installed by pnpm #4234

Open FuDesign2008 opened 2 years ago

FuDesign2008 commented 2 years ago

Information

VIM version

VIM - Vi IMproved 8.2 (2019 Dec 12, compiled Sep 24 2021 06:02:32) macOS version - arm64 Included patches: 1-3455 Compiled by Homebrew

Operating System: macOS version - arm64

What went wrong

WX20220615-232602@2x

When using ale + eslint (installed by pnpm), ale will report error

Parsing error: Cannot read file '/users/fuyg/workspace/gitlab/homework-fe-print-page/node_modules/.pnpm/eslint@7.32.0/tsconfig.json

Reproducing the bug

Sample Project

  1. git clone https://github.com/FuDesign2008/ale-eslint-bug-sample.git
  2. cd ale-eslint-bug-sample/src
  3. gvim ./test.tsx
  4. :ALEInfoToFile temp.txt

Those steps can not reproduce the bug, but can reproduce command like https://github.com/FuDesign2008/ale-eslint-bug-sample/blob/main/temp.txt#L80

# the right command should be
# 'cd ''/Users/fuyg/workspace/gitlab/sample'' && ....
'cd ''/Users/fuyg/workspace/gitlab/sample/node_modules/.pnpm/eslint@8.17.0'' && ....

:ALEInfo in the project that will cause error

  Current Filetype: typescriptreact
Available Linters: ['cspell', 'deno', 'eslint', 'standard', 'tslint', 'tsserver', 'typecheck', 'xo']
  Enabled Linters: ['eslint', 'tsserver']
  Ignored Linters: []
 Suggested Fixers: 
  'remove_trailing_lines' - Remove all blank lines at the end of a file.
  'trim_whitespace' - Remove all trailing whitespace characters at the end of every line.
 Linter Variables:

 Global Variables:

let g:ale_cache_executable_check_failures = 1
let g:ale_change_sign_column_color = 0
let g:ale_command_wrapper = ''
let g:ale_completion_delay = v:null
let g:ale_completion_enabled = 0
let g:ale_completion_max_suggestions = 5
let g:ale_disable_lsp = 0
let g:ale_echo_cursor = 1
let g:ale_echo_msg_error_str = 'Error'
let g:ale_echo_msg_format = '%code: %%s'
let g:ale_echo_msg_info_str = 'Info'
let g:ale_echo_msg_warning_str = 'Warning'
let g:ale_enabled = 1
let g:ale_fix_on_save = 1
let g:ale_fixers = {'yaml': ['yamlfix', 'prettier'], 'c': ['clang-format'], 'typescript': ['prettier'], 'markdown': ['prettier'], 'scss': ['stylelint', 'prettier'], 'typescriptreact': ['prettier'], 'json': ['prettier', 'fixjson'], 'javascript': ['prettier'], 'html': ['prettier'], 'less': ['stylelint', 'prettier'], 'css': ['stylelint', 'prettier'], 'vue': ['prettier', 'stylelint']}
let g:ale_history_enabled = 1
let g:ale_history_log_output = 1
let g:ale_keep_list_window_open = 0
let g:ale_lint_delay = 200
let g:ale_lint_on_enter = 1
let g:ale_lint_on_filetype_changed = 1
let g:ale_lint_on_insert_leave = 1
let g:ale_lint_on_save = 0
let g:ale_lint_on_text_changed = 1
let g:ale_linter_aliases = {'vue': ['vue', 'html', 'javascript', 'typescript', 'css', 'scss']}
let g:ale_linters = {'shell': ['shellcheck', 'language_server'], 'c': [], 'typescript': ['tsserver', 'eslint'], 'markdown': ['remark-lint', 'markdownlint'], 'vue': ['stylelint', 'vls', 'eslint'], 'typescriptreact': ['tsserver', 'eslint'], 'json': ['jsonlint'], 'dockerfile': ['hadolint'], 'yaml': ['yamllint', 'prettier'], 'java': ['javac', 'checkstyle'], 'javascript': ['eslint'], 'cpp': [], 'tex': []}
let g:ale_linters_explicit = 0
let g:ale_linters_ignore = {}
let g:ale_list_vertical = 0
let g:ale_list_window_size = 3
let g:ale_loclist_msg_format = '%code: %%s'
let g:ale_max_buffer_history_size = 20
let g:ale_max_signs = 5
let g:ale_maximum_file_size = 1048576
let g:ale_open_list = 0
let g:ale_pattern_options = {'\.min\.css$': {'ale_enabled': 0}, 'dist\/': {'ale_enabled': 0}, '\.min\.js$': {'ale_enabled': 0}}
let g:ale_pattern_options_enabled = v:null
let g:ale_root = {}
let g:ale_set_balloons = 1
let g:ale_set_highlights = 1
let g:ale_set_loclist = 1
let g:ale_set_quickfix = 0
let g:ale_set_signs = 1
let g:ale_sign_column_always = 1
let g:ale_sign_error = '✗'
let g:ale_sign_info = '!'
let g:ale_sign_offset = 1000000
let g:ale_sign_style_error = '✗'
let g:ale_sign_style_warning = '!'
let g:ale_sign_warning = '!'
let g:ale_sign_highlight_linenrs = 0
let g:ale_statusline_format = v:null
let g:ale_type_map = {}
let g:ale_use_global_executables = v:null
let g:ale_virtualtext_cursor = 0
let g:ale_warn_about_trailing_blank_lines = 1
let g:ale_warn_about_trailing_whitespace = 1
  Command History:

(executable check - success) /Users/fuyg/workspace/gitlab/homework-fe-print-page/node_modules/.pnpm/eslint@8.17.0/node_modules/eslint/bin/eslint.js
(finished - exit code 1) ['/bin/bash', '-c', 'cd ''/Users/fuyg/workspace/gitlab/homework-fe-print-page/node_modules/.pnpm/eslint@8.17.0'' && ''/Users/fuyg/workspace/gitlab/homework-fe-print-page/node_modules/.pnpm/eslint@8.17.0/node_modules/eslint/bin/eslint.js'' -f json --stdin --stdin-filename ''/Users/fuyg/workspace/gitlab/homework-fe-print-page/src/pages/serverMatchLines/views/MatchLines/MatchLines.tsx'' < ''/var/folders/ty/wqtsjfdn12j8w6yg9nlflgv80000gn/T/vXxHxxU/5/MatchLines.tsx''']

<<<OUTPUT STARTS>>>
[{"filePath":"/Users/fuyg/workspace/gitlab/homework-fe-print-page/src/pages/serverMatchLines/views/MatchLines/MatchLines.tsx","messages":[{"ruleId":null,"fatal":true,"severity":2,"message":"Parsing error: Cannot read file '/users/fuyg/workspace/gitlab/homework-fe-print-page/node_modules/.pnpm/eslint@8.17.0/tsconfig.json'."}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n *\n * @author fuyg\n * @date  2022-06-13\n */\n\nimport {\n  defineComponent,\n  // computed,\n  // toRefs,\n  ref,\n  // inject,\n  // PropType,\n  onUpdated,\n} from '@vue/composition-api'\nimport printBotBridge from '@/common/print/printBotBridge'\nimport styles from './MatchLines.module.scss'\nimport { drawLines } from './drawLines'\nimport { StyledMathFragment } from '@/math/StyledMathFragment'\n\nexport default defineComponent({\n  name: 'MatchLines',\n\n  props: {\n    // TODO\n  },\n\n  setup(_props, context) {\n    const questionHtml = ref<string>('')\n    const fetchData = async () => {\n      await printBotBridge.botRegisterNotifyPrint()\n      const html = (await printBotBridge.getValueFromRawData(\n        'questionHtml',\n      )) as string\n      questionHtml.value = html\n    }\n\n    const notifyAlive = printBotBridge.botNotifyAliveInterval()\n\n    onUpdated(() => {\n      const tableRect = drawLines(\n        context.refs.questionWrapper as HTMLElement,\n        context.refs.svgWrapper as HTMLElement,\n      )\n      if (!tableRect) {\n        return\n      }\n      setTimeout(() => {\n        if (notifyAlive) {\n          notifyAlive.cancel()\n        }\n        printBotBridge.botNotifyDoPrint(1000, {\n          clip: {\n            x: tableRect.left,\n            y: tableRect.top,\n            width: tableRect.width,\n            height: tableRect.height,\n          },\n        })\n      }, 0)\n    })\n\n    // init\n    void fetchData()\n\n    return {\n      questionHtml,\n      /** public data or methods **/\n      // TODO\n    }\n  },\n\n  render() {\n    return (\n      <div\n        class={{\n          'match-lines': true,\n          [styles.matchLines]: true,\n        }}\n      >\n        <div ref=\"questionWrapper\">\n          <StyledMathFragment part=\"question\" mathHtml={this.questionHtml} />\n        </div>\n        <div ref=\"svgWrapper\"></div>\n      </div>\n    )\n  },\n})\n","usedDeprecatedRules":[{"ruleId":"id-blacklist","replacedBy":["id-denylist"]}]}]
<<<OUTPUT ENDS>>>

(executable check - success) /Users/fuyg/workspace/gitlab/homework-fe-print-page/node_modules/.bin/tsserver
(started) ['/bin/bash', '-c', '''/Users/fuyg/workspace/gitlab/homework-fe-print-page/node_modules/.bin/tsserver''']
(finished - exit code 1) ['/bin/bash', '-c', 'cd ''/Users/fuyg/workspace/gitlab/homework-fe-print-page/node_modules/.pnpm/eslint@8.17.0'' && ''/Users/fuyg/workspace/gitlab/homework-fe-print-page/node_modules/.pnpm/eslint@8.17.0/node_modules/eslint/bin/eslint.js'' -f json --stdin --stdin-filename ''/Users/fuyg/workspace/gitlab/homework-fe-print-page/src/pages/serverMatchLines/views/MatchLines/MatchLines.tsx'' < ''/var/folders/ty/wqtsjfdn12j8w6yg9nlflgv80000gn/T/vXxHxxU/6/MatchLines.tsx''']

<<<OUTPUT STARTS>>>
[{"filePath":"/Users/fuyg/workspace/gitlab/homework-fe-print-page/src/pages/serverMatchLines/views/MatchLines/MatchLines.tsx","messages":[{"ruleId":null,"fatal":true,"severity":2,"message":"Parsing error: Cannot read file '/users/fuyg/workspace/gitlab/homework-fe-print-page/node_modules/.pnpm/eslint@8.17.0/tsconfig.json'."}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n *\n * @author fuyg\n * @date  2022-06-13\n */\n\nimport {\n  defineComponent,\n  // computed,\n  // toRefs,\n  ref,\n  // inject,\n  // PropType,\n  onUpdated,\n} from '@vue/composition-api'\nimport printBotBridge from '@/common/print/printBotBridge'\nimport styles from './MatchLines.module.scss'\nimport { drawLines } from './drawLines'\nimport { StyledMathFragment } from '@/math/StyledMathFragment'\n\nexport default defineComponent({\n  name: 'MatchLines',\n\n  props: {\n    // TODO\n  },\n\n  setup(_props, context) {\n    const questionHtml = ref<string>('')\n    const fetchData = async () => {\n      await printBotBridge.botRegisterNotifyPrint()\n      const html = (await printBotBridge.getValueFromRawData(\n        'questionHtml',\n      )) as string\n      questionHtml.value = html\n    }\n\n    const notifyAlive = printBotBridge.botNotifyAliveInterval()\n\n    onUpdated(() => {\n      const tableRect = drawLines(\n        context.refs.questionWrapper as HTMLElement,\n        context.refs.svgWrapper as HTMLElement,\n      )\n      if (!tableRect) {\n        return\n      }\n      setTimeout(() => {\n        if (notifyAlive) {\n          notifyAlive.cancel()\n        }\n        printBotBridge.botNotifyDoPrint(1000, {\n          clip: {\n            x: tableRect.left,\n            y: tableRect.top,\n            width: tableRect.width,\n            height: tableRect.height,\n          },\n        })\n      }, 0)\n    })\n\n    // init\n    void fetchData()\n\n    return {\n      questionHtml,\n      /** public data or methods **/\n      // TODO\n    }\n  },\n\n  render() {\n    return (\n      <div\n        class={{\n          'match-lines': true,\n          [styles.matchLines]: true,\n        }}\n      >\n        <div ref=\"questionWrapper\">\n          <StyledMathFragment part=\"question\" mathHtml={this.questionHtml} />\n        </div>\n        <div ref=\"svgWrapper\"></div>\n      </div>\n    )\n  },\n})\n","usedDeprecatedRules":[{"ruleId":"id-blacklist","replacedBy":["id-denylist"]}]}]
<<<OUTPUT ENDS>>>

Not Good Solution

I made a fix (see https://github.com/FuDesign2008/ale/pull/1/files ) in my forked ale.

It works, but I think it is not a good solution:

  1. ./node_modules/.pnpm/eslint@8.17.0 is not listed in s:executables (https://github.com/dense-analysis/ale/blob/f10349b48b173d50b523ce009934bb4bfba04f7f/autoload/ale/handlers/eslint.vim#L4 ), How it comes ?
  2. Some package like eslint may cause same error

Look forward to a good solution.

mgreystone commented 2 years ago

Using an absolute path for parserOptions.project in .eslintrc.js seems to be a workaround?

const path = require('path')

module.exports = {
  extends: 'standard-with-typescript',
  parserOptions: {
    project: path.join(__dirname, '/tsconfig.json')
  }
}