From bfc79bd2aafffc9b8590f9ffa68254243e3f808a Mon Sep 17 00:00:00 2001 From: w0rp Date: Sun, 12 May 2019 19:35:10 +0100 Subject: [PATCH] #2492 - Try to fix a deoplete bug again --- autoload/ale/completion.vim | 13 ++++ rplugin/python3/deoplete/sources/ale.py | 6 +- .../test_public_completion_api.vader | 63 +++++++++++++++++++ test/python/test_deoplete_source.py | 27 ++++++-- 4 files changed, 103 insertions(+), 6 deletions(-) create mode 100644 test/completion/test_public_completion_api.vader diff --git a/autoload/ale/completion.vim b/autoload/ale/completion.vim index 456fe68a..03cc6471 100644 --- a/autoload/ale/completion.vim +++ b/autoload/ale/completion.vim @@ -549,6 +549,19 @@ function! s:OnReady(linter, lsp_details) abort endif endfunction +" This function can be called to check if ALE can provide completion data for +" the current buffer. 1 will be returned if there's a potential source of +" completion data ALE can use, and 0 will be returned otherwise. +function! ale#completion#CanProvideCompletions() abort + for l:linter in ale#linter#Get(&filetype) + if !empty(l:linter.lsp) + return 1 + endif + endfor + + return 0 +endfunction + " This function can be used to manually trigger autocomplete, even when " g:ale_completion_enabled is set to false function! ale#completion#GetCompletions(source) abort diff --git a/rplugin/python3/deoplete/sources/ale.py b/rplugin/python3/deoplete/sources/ale.py index 55121d76..7ed2f6c0 100644 --- a/rplugin/python3/deoplete/sources/ale.py +++ b/rplugin/python3/deoplete/sources/ale.py @@ -30,6 +30,10 @@ class Source(Base): return self.vim.call('ale#completion#GetCompletionPosition') def gather_candidates(self, context): + # Stop early if ALE can't provide completion data for this buffer. + if not self.vim.call('ale#completion#CanProvideCompletions'): + return None + if context.get('is_refresh'): context['is_async'] = False @@ -47,4 +51,4 @@ class Source(Base): # Request some completion results. self.vim.call('ale#completion#GetCompletions', 'deoplete') - return None + return [] diff --git a/test/completion/test_public_completion_api.vader b/test/completion/test_public_completion_api.vader new file mode 100644 index 00000000..d4db2d6f --- /dev/null +++ b/test/completion/test_public_completion_api.vader @@ -0,0 +1,63 @@ +Before: + call ale#linter#Reset() + + unlet! b:ale_linters + unlet! b:ale_completion_info + unlet! b:ale_completion_response + unlet! b:ale_completion_parser + unlet! b:ale_completion_result + + function! Identity(x) abort + return a:x + endfunction + +After: + delfunction Identity + + call ale#linter#Reset() + + unlet! b:ale_linters + unlet! b:ale_completion_info + unlet! b:ale_completion_response + unlet! b:ale_completion_parser + unlet! b:ale_completion_result + +Execute(ale#completion#GetCompletionResult() should return v:null when there are no results): + AssertEqual v:null, ale#completion#GetCompletionResult() + +Execute(ale#completion#GetCompletionResult() should parse the result when it has yet to be parsed): + let b:ale_completion_response = [1] + let b:ale_completion_parser = 'Identity' + + AssertEqual [1], ale#completion#GetCompletionResult() + Assert !exists('b:ale_completion_response') + Assert !exists('b:ale_completion_parser') + AssertEqual [1], b:ale_completion_result + +Execute(ale#completion#GetCompletionResult() should return a result computed previously): + let b:ale_completion_result = [1] + + Assert !exists('b:ale_completion_response') + Assert !exists('b:ale_completion_parser') + AssertEqual [1], ale#completion#GetCompletionResult() + +Execute(ale#completion#GetCompletionPosition() should return 0 when there is no completion information): + AssertEqual 0, ale#completion#GetCompletionPosition() + +Given python(Some Python file): + foo bar + +Execute(ale#completion#GetCompletionPosition() should return the position in the file when information is available): + let b:ale_completion_info = {'line': 1, 'column': 6} + + " This is the first character of 'bar' + AssertEqual 4, ale#completion#GetCompletionPosition() + +Execute(ale#completion#CanProvideCompletions should return 0 when no completion sources are available): + AssertEqual 0, ale#completion#CanProvideCompletions() + +Execute(ale#completion#CanProvideCompletions should return 1 when at least one completion source is available): + runtime ale_linters/python/pyls.vim + let b:ale_linters = ['pyls'] + + AssertEqual 1, ale#completion#CanProvideCompletions() diff --git a/test/python/test_deoplete_source.py b/test/python/test_deoplete_source.py index 94fa66c2..28eec5cd 100644 --- a/test/python/test_deoplete_source.py +++ b/test/python/test_deoplete_source.py @@ -23,7 +23,7 @@ class DeopleteSourceTest(unittest.TestCase): super(DeopleteSourceTest, self).setUp() self.call_list = [] - self.call_results = {} + self.call_results = {'ale#completion#CanProvideCompletions': 1} self.source = ale_module.Source('vim') self.source.vim = VimMock(self.call_list, self.call_results) @@ -59,27 +59,41 @@ class DeopleteSourceTest(unittest.TestCase): def test_request_completion_results(self): context = {'is_async': False} - self.assertIsNone(self.source.gather_candidates(context)) + self.assertEqual(self.source.gather_candidates(context), []) self.assertEqual(context, {'is_async': True}) self.assertEqual(self.call_list, [ + ('ale#completion#CanProvideCompletions', ()), ('ale#completion#GetCompletions', ('deoplete',)), ]) + def test_request_completion_results_from_buffer_without_providers(self): + self.call_results['ale#completion#CanProvideCompletions'] = 0 + context = {'is_async': False} + + self.assertIsNone(self.source.gather_candidates(context), []) + self.assertEqual(context, {'is_async': False}) + self.assertEqual(self.call_list, [ + ('ale#completion#CanProvideCompletions', ()), + ]) + def test_refresh_completion_results(self): context = {'is_async': False} - self.assertIsNone(self.source.gather_candidates(context)) + self.assertEqual(self.source.gather_candidates(context), []) self.assertEqual(context, {'is_async': True}) self.assertEqual(self.call_list, [ + ('ale#completion#CanProvideCompletions', ()), ('ale#completion#GetCompletions', ('deoplete',)), ]) context = {'is_async': True, 'is_refresh': True} - self.assertIsNone(self.source.gather_candidates(context)) + self.assertEqual(self.source.gather_candidates(context), []) self.assertEqual(context, {'is_async': True, 'is_refresh': True}) self.assertEqual(self.call_list, [ + ('ale#completion#CanProvideCompletions', ()), ('ale#completion#GetCompletions', ('deoplete',)), + ('ale#completion#CanProvideCompletions', ()), ('ale#completion#GetCompletions', ('deoplete',)), ]) @@ -87,9 +101,10 @@ class DeopleteSourceTest(unittest.TestCase): context = {'is_async': True} self.call_results['ale#completion#GetCompletionResult'] = None - self.assertIsNone(self.source.gather_candidates(context)) + self.assertEqual(self.source.gather_candidates(context), []) self.assertEqual(context, {'is_async': True}) self.assertEqual(self.call_list, [ + ('ale#completion#CanProvideCompletions', ()), ('ale#completion#GetCompletionResult', ()), ]) @@ -100,6 +115,7 @@ class DeopleteSourceTest(unittest.TestCase): self.assertEqual(self.source.gather_candidates(context), []) self.assertEqual(context, {'is_async': False}) self.assertEqual(self.call_list, [ + ('ale#completion#CanProvideCompletions', ()), ('ale#completion#GetCompletionResult', ()), ]) @@ -126,5 +142,6 @@ class DeopleteSourceTest(unittest.TestCase): ]) self.assertEqual(context, {'is_async': False}) self.assertEqual(self.call_list, [ + ('ale#completion#CanProvideCompletions', ()), ('ale#completion#GetCompletionResult', ()), ])