dense-analysis / dense-analysis/ale

Missing completion options when parsed into deoplete

Open
#2,853 5 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
Vim Script
Stars
14k
Forks
1.5k
Avg merge
17h 49m
Merged PRs (30d)
1

Description

## Information

**VIM version**

```
NVIM v0.5.0-140-g402afb089
Build type: RelWithDebInfo
```

Operating System: Arch Linux (`uname -a: Linux ArchThinkPad 5.3.7-arch1-1-ARCH #1 SMP PREEMPT Fri Oct 18 00:17:03 UTC 2019 x86_64 GNU/Linux`)

## What went wrong

For the past couple of days I have been investigating a problem of some missing code completion options in my setup. I am still uncertain whether this is the correct repository to file the issue in but it appears to be the best way to start. I will try to provide detailed instructions on how to reproduce the issue. Let me start with an introduction.

### Problem Description
Lately I started some development work on [Qiskit](https://github.com/Qiskit). When I was initially getting started I noticed that some completions options were missing in neovim. Here are some screenshots:

IPython | Neovim
:-:|:-:
![ipython](https://user-images.githubusercontent.com/21973473/67162655-5cc2e100-f366-11e9-9c58-5832089d003b.png) | ![neovim](https://user-images.githubusercontent.com/21973473/67162657-60566800-f366-11e9-92cd-9522ec8b945a.png)

With a keen eye you will be able to notice that in neovim some functions like (`AND`, `OR`, `ch`, `cx`, etc.) are missing. Since IPython also uses [jedi](https://github.com/davidhalter/jedi) for its completion, I assume that the issue does not lie there.

### Setup description
Obviously, there are a large number of potential points of failure. Thus, I would like to first outline my neovim setup here, before going in some detail and minimal configuration to reproduce the issue.

**Disclaimer:** I did not yet observe a similar problem with other packages. However, lately my main Python development is in Qiskit. If anyone found a similar behavior for other packages, please feel free to let me know!

My neovim setup uses the following plugins: I use [deoplete](https://github.com/deoplete/deoplete.nvim) for completion. All sources are provided by ale which in turn uses [pyls](https://github.com/palantir/python-language-server) as its language server input.

Some python package versions:

- pynvim: 0.3.2
- jedi: 0.15.1
- python-language-server: 0.29.1

The most problematic point in my setup is (in my opinion) that I use virtual environments for all my projects. For this reason, I have a separate virtualenv just for neovim as suggested [here](https://neovim.io/doc/user/provider.html#python-virtualenv) which points to [here](https://github.com/deoplete-plugins/deoplete-jedi/wiki/Setting-up-Python-for-Neovim#using-virtual-environments) (I actually used [deoplete-jedi](https://github.com/deoplete-plugins/deoplete-jedi) before switching to this LSP setup with ale but I tried it out earlier and it also results in the issue described here).

### Problem Analysis and breakdown
In order to analyze this problem and potentially narrow down the problematic configuration aspect I started a clean virtualenv and tested with `nvim --noplugin -u ./init.vim` where `init.vim` will be provided in each subsection below for reproducability.

To test the completion I will be working with the file `test.py` which has the contents as below.

test.py

```
import qiskit
q = qiskit.QuantumRegister(2)
c = qiskit.ClassicalRegister(2)
circ = qiskit.QuantumCircuit(2)
circ
```

I will always jump to the last line and try to trigger the completion of `circ` as shown in the screenshots further up top.

#### venv setup

Setup a new/clean venv for debugging:

```
cd /tmp
virtualenenv jedi-qiskit
cd jedi-qiskit
source bin/activate
pip install ipython pynvim python-language-server
pip install qiskit
```

At this point in time, you should already be able to reproduce the properly function completion within ipython.

### tl;dr
In the following subsections I will iterate through several setups and tests to figure out where the problem lies. If this is too much to read, feel free to jump to [the heart of my problem](#the-heart-of-my-issue-is-combining-ale-with-deoplete)

#### First observations with vanilla neovim
`init.vim` is empty. Observation: omni completion works just as expected. (see collapsed screenshot)
Checking where the `omnifunc` was set with `:verbose set omnifunc?` results in
```
omnifunc=python3complete#Complete
Last set from /usr/share/nvim/runtime/ftplugin/python.vim line 41
```

Screenshot of vanilla omni completion

![screenshot_1571590064](https://user-images.githubusercontent.com/21973473/67162982-08216500-f36a-11e9-8e85-0831410af72c.png)

#### Overriding `python3_host_program`
Adding the single line to `init.vim`:
```
let g:python3_host_program = expand('/path/to/my/neovim/only/venv')
```
results in the omni completion breaking which is what I expect since Qiskit is not installed in that virtualenv. Hence, the need for a setup with a properly configured language server.

List of installed python packages in neovim-only venv

```
% pip list
Package Version
---------------------- -------
future 0.18.1
greenlet 0.4.15
importlib-metadata 0.23
jedi 0.15.1
more-itertools 7.2.0
msgpack 0.6.2
parso 0.5.1
pip 19.3.1
pluggy 0.13.0
pynvim 0.3.2
python-jsonrpc-server 0.2.0
python-language-server 0.29.1
setuptools 41.4.0
wheel 0.33.6
zipp 0.6.0
```

#### Trying ale with pyls

init.vim

```
let g:ale_completion_enabled = 1
let g:ale_linters_explicit = 1
let g:ale_linters = {'python': ['pyls']}
packadd ale
```
Again, `ale` has to be in the path and pyls needs to be installed in the current venv.

This config does actually work just as expected (albeit being a little slow on the first query which I assume is due to the init loading of the module). See also the collapsed screenshot below. Furthermore, omni completion remains working.

Screenshot of ale completion provided by pyls

![screenshot_1571592625](https://user-images.githubusercontent.com/21973473/67163677-15dae880-f372-11e9-928d-accfed9206b8.png)

ALEInfo

```
Current Filetype: python
Available Linters: ['bandit', 'flake8', 'mypy', 'prospector', 'pycodestyle', 'pydocstyle', 'pyflakes', 'pylama', 'pylint', 'pyls', 'pyre', 'vulture']
Enabled Linters: ['pyls']
Suggested Fixers:
'add_blank_lines_for_python_control_statements' - Add blank lines before control statements.
'autopep8' - Fix PEP8 issues with autopep8.
'black' - Fix PEP8 issues with black.
'isort' - Sort Python imports with isort.
'remove_trailing_lines' - Remove all blank lines at the end of a file.
'reorder-python-imports' - Sort Python imports with reorder-python-imports.
'trim_whitespace' - Remove all trailing whitespace characters at the end of every line.
'yapf' - Fix Python files with yapf.
Linter Variables:

let g:ale_python_auto_pipenv = 0
let g:ale_python_pyls_auto_pipenv = 0
let g:ale_python_pyls_config = {}
let g:ale_python_pyls_executable = 'pyls'
let g:ale_python_pyls_use_global = 0
Global Variables:

let g:ale_cache_executable_check_failures = v:null
let g:ale_change_sign_column_color = 0
let g:ale_command_wrapper = ''
let g:ale_completion_delay = 100
let g:ale_completion_enabled = 1
let g:ale_completion_max_suggestions = 50
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 = 0
let g:ale_fixers = {}
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 = 1
let g:ale_lint_on_text_changed = 'normal'
let g:ale_linter_aliases = {}
let g:ale_linters = {'python': ['pyls']}
let g:ale_linters_explicit = 1
let g:ale_list_vertical = 0
let g:ale_list_window_size = 10
let g:ale_loclist_msg_format = '%code: %%s'
let g:ale_lsp_root = {}
let g:ale_max_buffer_history_size = 20
let g:ale_max_signs = -1
let g:ale_maximum_file_size = v:null
let g:ale_open_list = 0
let g:ale_pattern_options = v:null
let g:ale_pattern_options_enabled = v:null
let g:ale_set_balloons = 0
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 = 0
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) /tmp/jedi-qiskit/bin/pyls
(started) ['/bin/zsh', '-c', '''/tmp/jedi-qiskit/bin/pyls''']
```

#### adding the neovim-only venv
If I try to use my neovim-only virtualenv, this breaks the setup. Sometimes I am able to obtain the limited completion options as shown in the collapsed screenshot below. Manually specifying the neovim-only based pyls binary does not fix the issue.

Details for using ale + neovim-only venv

#### the heart of my issue is combining ale with deoplete
Now this is where my actual problem lies: I want to continue using deoplete and use ale as the LSP backend for providing the completion sources. Thus, my `init.vim` looks like this:
```
let g:deoplete#enable_at_startup = 1
packadd deoplete.nvim
let g:ale_completion_enabled = 0
let g:ale_linters_explicit = 1
let g:ale_linters = {'python': ['pyls']}
packadd ale
```
This results in only a subset of the completions which I obtained with plain ale as shown in the collapsed screenshot below. The upside of this config is, that the completions remain unchanged w.r.t. using the python and pyls providers from the neovim-only venv.

Screenshot of completions from ale piped into deoplete

![screenshot_1571594009](https://user-images.githubusercontent.com/21973473/67163799-89312a00-f373-11e9-87cd-1f15b80b9566.png)

ALEInfo

```

Current Filetype: python
Available Linters: ['bandit', 'flake8', 'mypy', 'prospector', 'pycodestyle', 'pydocstyle', 'pyflakes', 'pylama', 'pylint', 'pyls', 'pyre', 'vulture']
Enabled Linters: ['pyls']
Suggested Fixers:
'add_blank_lines_for_python_control_statements' - Add blank lines before control statements.
'autopep8' - Fix PEP8 issues with autopep8.
'black' - Fix PEP8 issues with black.
'isort' - Sort Python imports with isort.
'remove_trailing_lines' - Remove all blank lines at the end of a file.
'reorder-python-imports' - Sort Python imports with reorder-python-imports.
'trim_whitespace' - Remove all trailing whitespace characters at the end of every line.
'yapf' - Fix Python files with yapf.
Linter Variables:

let g:ale_python_auto_pipenv = 0
let g:ale_python_pyls_auto_pipenv = 0
let g:ale_python_pyls_config = {}
let g:ale_python_pyls_executable = 'pyls'
let g:ale_python_pyls_use_global = 0
Global Variables:

let g:ale_cache_executable_check_failures = v:null
let g:ale_change_sign_column_color = 0
let g:ale_command_wrapper = ''
let g:ale_completion_delay = 100
let g:ale_completion_enabled = 0
let g:ale_completion_max_suggestions = 50
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 = 0
let g:ale_fixers = {}
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 = 1
let g:ale_lint_on_text_changed = 'normal'
let g:ale_linter_aliases = {}
let g:ale_linters = {'python': ['pyls']}
let g:ale_linters_explicit = 1
let g:ale_list_vertical = 0
let g:ale_list_window_size = 10
let g:ale_loclist_msg_format = '%code: %%s'
let g:ale_lsp_root = {}
let g:ale_max_buffer_history_size = 20
let g:ale_max_signs = -1
let g:ale_maximum_file_size = v:null
let g:ale_open_list = 0
let g:ale_pattern_options = v:null
let g:ale_pattern_options_enabled = v:null
let g:ale_set_balloons = 0
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 = 0
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) /tmp/jedi-qiskit/bin/pyls
(started) ['/bin/zsh', '-c', '''/tmp/jedi-qiskit/bin/pyls''']
```

**So my questions really is this:** Regardless of the neovim-only venv, _why do the completions offered by deoplete differ from the plain ale completions?_

#### trying out [jedi-vim](https://github.com/davidhalter/jedi-vim)

init.vim

```
packadd jedi-vim
```
Obviously, `jedi-vim` needs to be cloned into a correct path such as `~/.config/nvim/pack/minpac/start/jedi-vim`

Already fails to properly complete (see screenshot below). Also breaks omni completion since it is overwritten with
```
omnifunc=jedi#completions
Last set from ~/.config/nvim/pack/minpac/start/jedi-vim/autoload/jedi.vim line 740
```
Overriding the `python3_host_program` has no effect, as expected. I am not sure what to think of this, thus, tagging @davidhalter to let you know of this issue as well.

Screenshot of jedi-vim completion

![screenshot_1571590831](https://user-images.githubusercontent.com/21973473/67163186-43bd2e80-f36c-11e9-9fd6-4ab9edd56187.png)

#### trying out [deoplete-jedi](https://github.com/deoplete-plugins/deoplete-jedi)

init.vim

```
let g:deoplete#enable_at_startup = 1
packadd deoplete.nvim
packadd deoplete-jedi
```
Again, `deoplete` and `deoplete-nvim` have to be in the path.

Automatic completion by deoplete does not work (see collapsed screenshot; @deoplete-plugins). But, omni completion remains working because `omnifunc` is not overwritten. However, using the neovim-only venv will break this (again this is to be expected).

Screenshot of deoplete-jedi completion

![screenshot_1571591153](https://user-images.githubusercontent.com/21973473/67163254-0016f480-f36d-11e9-875d-8f4067ea762d.png)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.