From b25794e81b79d4ce1a6f2d9d0fbcc6876ecaa124 Mon Sep 17 00:00:00 2001 From: Jon Parise Date: Thu, 1 Nov 2018 13:35:18 -0700 Subject: elixir-ls now recognizes umbrella projects Previously, elixir-ls would treat each sub-project within an umbrella as standalone, which isn't desirable from a language server perspective. Added ale#handlers#elixir#FindMixUmbrellaRoot, which locates the current project's root and then continues searching upwards for a potential umbrella project root. This literally looks just two levels up to keep things simple while keeping in line with Elixir project conventions. Use this new function to determine elixir-ls's LSP project root. --- ale_linters/elixir/elixir_ls.vim | 2 +- autoload/ale/handlers/elixir.vim | 21 ++++++++++++++++++--- .../umbrella_project/apps/app1/lib/app.ex | 0 .../elixir_paths/umbrella_project/apps/app1/mix.exs | 0 .../umbrella_project/apps/app2/lib/app.ex | 0 .../elixir_paths/umbrella_project/apps/app2/mix.exs | 0 .../elixir_paths/umbrella_project/mix.exs | 0 .../test_elixir_ls_command_callbacks.vader | 4 ++-- .../test_elixir_mix_command_callbacks.vader | 15 +++++++++++---- 9 files changed, 32 insertions(+), 10 deletions(-) create mode 100644 test/command_callback/elixir_paths/umbrella_project/apps/app1/lib/app.ex create mode 100644 test/command_callback/elixir_paths/umbrella_project/apps/app1/mix.exs create mode 100644 test/command_callback/elixir_paths/umbrella_project/apps/app2/lib/app.ex create mode 100644 test/command_callback/elixir_paths/umbrella_project/apps/app2/mix.exs create mode 100644 test/command_callback/elixir_paths/umbrella_project/mix.exs diff --git a/ale_linters/elixir/elixir_ls.vim b/ale_linters/elixir/elixir_ls.vim index c1e8fdd6..3b299ec6 100644 --- a/ale_linters/elixir/elixir_ls.vim +++ b/ale_linters/elixir/elixir_ls.vim @@ -16,6 +16,6 @@ call ale#linter#Define('elixir', { \ 'lsp': 'stdio', \ 'executable_callback': 'ale_linters#elixir#elixir_ls#GetExecutable', \ 'command_callback': 'ale_linters#elixir#elixir_ls#GetExecutable', -\ 'project_root_callback': 'ale#handlers#elixir#FindMixProjectRoot', +\ 'project_root_callback': 'ale#handlers#elixir#FindMixUmbrellaRoot', \ 'lsp_config_callback': ale#VarFunc('elixir_elixir_ls_config'), \}) diff --git a/autoload/ale/handlers/elixir.vim b/autoload/ale/handlers/elixir.vim index 91b75aac..2fddf8e7 100644 --- a/autoload/ale/handlers/elixir.vim +++ b/autoload/ale/handlers/elixir.vim @@ -1,13 +1,28 @@ " Author: Matteo Centenaro (bugant) - https://github.com/bugant -" -" Description: find the root directory for an elixir project that uses mix +" Author: Jon Parise +" Description: Functions for working with Elixir projects +" Find the root directory for an elixir project that uses mix. function! ale#handlers#elixir#FindMixProjectRoot(buffer) abort let l:mix_file = ale#path#FindNearestFile(a:buffer, 'mix.exs') if !empty(l:mix_file) - return fnamemodify(l:mix_file, ':p:h') + return fnamemodify(l:mix_file, ':p:h') endif return '.' endfunction + +" Similar to ale#handlers#elixir#FindMixProjectRoot but also continue the +" search upward for a potential umbrella project root. If an umbrella root +" does not exist, the initial project root will be returned. +function! ale#handlers#elixir#FindMixUmbrellaRoot(buffer) abort + let l:app_root = ale#handlers#elixir#FindMixProjectRoot(a:buffer) + let l:umbrella_root = fnamemodify(l:app_root, ':h:h') + + if filereadable(l:umbrella_root . '/mix.exs') + return l:umbrella_root + endif + + return l:app_root +endfunction diff --git a/test/command_callback/elixir_paths/umbrella_project/apps/app1/lib/app.ex b/test/command_callback/elixir_paths/umbrella_project/apps/app1/lib/app.ex new file mode 100644 index 00000000..e69de29b diff --git a/test/command_callback/elixir_paths/umbrella_project/apps/app1/mix.exs b/test/command_callback/elixir_paths/umbrella_project/apps/app1/mix.exs new file mode 100644 index 00000000..e69de29b diff --git a/test/command_callback/elixir_paths/umbrella_project/apps/app2/lib/app.ex b/test/command_callback/elixir_paths/umbrella_project/apps/app2/lib/app.ex new file mode 100644 index 00000000..e69de29b diff --git a/test/command_callback/elixir_paths/umbrella_project/apps/app2/mix.exs b/test/command_callback/elixir_paths/umbrella_project/apps/app2/mix.exs new file mode 100644 index 00000000..e69de29b diff --git a/test/command_callback/elixir_paths/umbrella_project/mix.exs b/test/command_callback/elixir_paths/umbrella_project/mix.exs new file mode 100644 index 00000000..e69de29b diff --git a/test/command_callback/test_elixir_ls_command_callbacks.vader b/test/command_callback/test_elixir_ls_command_callbacks.vader index 5a8d8496..ca785054 100644 --- a/test/command_callback/test_elixir_ls_command_callbacks.vader +++ b/test/command_callback/test_elixir_ls_command_callbacks.vader @@ -22,12 +22,12 @@ Execute(should configure elixir-ls release location): AssertLinter 'boo/language_server.sh', 'boo/language_server.sh' Execute(should set correct LSP values): - call ale#test#SetFilename('mix_paths/wrapped_project/lib/app.ex') + call ale#test#SetFilename('elixir_paths/umbrella_project/apps/app1/lib/app.ex') AssertLSPLanguage 'elixir' AssertLSPOptions {} AssertLSPConfig {} - AssertLSPProject ale#path#Simplify(g:dir . '/mix_paths/wrapped_project') + AssertLSPProject ale#path#Simplify(g:dir . '/elixir_paths/umbrella_project') Execute(should accept configuration settings): AssertLSPConfig {} diff --git a/test/command_callback/test_elixir_mix_command_callbacks.vader b/test/command_callback/test_elixir_mix_command_callbacks.vader index 9315a850..ec7b9911 100644 --- a/test/command_callback/test_elixir_mix_command_callbacks.vader +++ b/test/command_callback/test_elixir_mix_command_callbacks.vader @@ -18,9 +18,16 @@ Execute(The default mix command should be correct): \ . g:env_prefix \ . 'mix compile %s' -Execute(The FindMixProjectRoot should detect the project root directory via mix.exs): - silent execute 'file ' . fnameescape(g:dir . '/elixir_paths/mix_project/lib/app.ex') +Execute(FindMixProjectRoot should detect the project root directory via mix.exs): + silent execute 'file ' . fnameescape(g:dir . '/elixir_paths/mix_project/lib/app.ex') - AssertEqual - \ ale#path#Simplify(g:dir . '/elixir_paths/mix_project'), + AssertEqual + \ ale#path#Simplify(g:dir . '/elixir_paths/mix_project'), \ ale#handlers#elixir#FindMixProjectRoot(bufnr('')) + +Execute(FindMixUmbrellaRoot should detect the umbrella root directory via mix.exs): + silent execute 'file ' . fnameescape(g:dir . '/elixir_paths/umbrella_project/apps/app1/lib/app.ex') + + AssertEqual + \ ale#path#Simplify(g:dir . '/elixir_paths/umbrella_project'), + \ ale#handlers#elixir#FindMixUmbrellaRoot(bufnr('')) -- cgit v1.2.3