dense-analysis / ale

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

Add support for ReScript #3335

Open fa7ad opened 4 years ago

fa7ad commented 4 years ago

Name: rescript URL: https://rescript-lang.org/

A little detail: ReScript is the new syntax for bucklescript (the compiler used by reasonml). reason-language-server is compatible with this new syntax. But the fixer is different, instead of refmt --in-place we need to run bsc -format % -o %.

Please let me know if I can be of any help, I'm not very familiar with the inner workings of ALE but I might be able to help with more details about rescript if needed.

ianchanning commented 4 years ago

If I try running :!bsc -format % -o % in the vim command line this shows the output of the formatted file but it doesn't put it into the buffer. You can however run :!bsrefmt --in-place %. bsrefmt also gets installed when you install bs-platform.

fa7ad commented 4 years ago

bsc is included with bs-platform as well. The problem here is that bsrefmt is meant for the reasonml syntax, bsc -format for the new/rescript syntax (and they are not compatible). You're right the command I provided doesn't seem to work as intended but, :%!bsc -format % -o - seems to do the trick.

ianchanning commented 4 years ago

Ah - thanks for that :%!bsc -format % -o - works.

I've just tested bsc and it starts giving reason-language-server linting errors for my Reason file (old style *.re).

I think there needs to be a new filetype rescript / ReScript that uses bsc and the current reason filetype should switch to bsrefmt.

joakin commented 4 years ago

I've made a post in the forum to reach more people. https://forum.rescript-lang.org/t/vim-ale-rescript-support/632

I've hacked together fixer support in my vim config:

let g:ale_fixers = {
\   'rescript': [
\     {buffers -> {
\       'command': 'bsc -color never -format %t'
\     }},
\   ],
\}

Works well but it doesn't have the fancy support like other fixers to find the right executables in node modules or globally.

Re: linter, like I mention in the post ryyppy’s vim-rescript fork has a function rescript#parsing#ParseCompilerErrorOutput(lines) that is supposed to parse errors into quickfix format. Maybe it could be a good start for making a linter.

joakin commented 3 years ago

With the latest changes to the editor plugins and the new rescript package, having vim-ale working with lsp with rescript is feasible.

See https://forum.rescript-lang.org/t/vim-ale-rescript-support/632/6 for more details. Example linter (with my very limited ale knowledge):

" Requirements: `rescript` npm package, `vim-rescript` installed in vim, and run `rescript build -w` to get up to date diagnostics

" Replace this with your path either in this file or in your vim config
call ale#Set('rescript_lsp_js_file', '~/.vim/plugged/vim-rescript/server/out/server.js')

" Give vim-ale the rescript executable to check because the LSP server is
" a non-executable JS file
call ale#Set('rescript_executable', 'rescript')
call ale#Set('rescript_use_global', get(g:, 'ale_use_global_executables', 1))

function! rescript_ale#GetRootDir(buffer) abort
    let l:config = ale#path#FindNearestFile(a:buffer, 'bsconfig.json')

    return !empty(l:config) ? fnamemodify(l:config, ':p:h') : ''
endfunction

function! FormatRescript(buffer) abort
  return {
  \   'command': 'rescript format -stdin .res'
  \}
endfunction

call ale#fix#registry#Add('rescript', 'FormatRescript', ['rescript'], 'rescript formatter')

call ale#linter#Define('rescript', {
\   'name': 'rescript',
\   'lsp': 'stdio',
\   'executable': {b -> ale#node#FindExecutable(b, 'rescript', [
\       'node_modules/.bin/rescript',
\       'rescript'
\   ])},
\   'command': {b -> 'node ' . ale#Var(b, 'rescript_lsp_js_file') . ' --stdio'},
\   'project_root': function('rescript_ale#GetRootDir'),
\   'language': 'rescript',
\})

On your vim configuration, init.vim or .vimrc for example, configure ale:

let g:ale_linters = {
\   'rescript': ['rescript'],
\}

let g:ale_fixers = {
\   'rescript': ['rescript'],
\}

And that’s it! Remember to run rescript build -w on your rescript project to get up to date diagnostics.