NeoVim + LanguageServer -- Packages not being sourced

I’m using NeoVim with LSP and cmp. My configuration works correctly; cmp correctly sources all the language servers I require (Python, Julia, R…) and shows no problem at all. However, when I work with Python for example, the language server provides auto-completion and documentation features for both base Python functions and for Python libraries (such as pandas or numpy). On the contrary, the Julia language server seems to provide these features only for the base library. No features seem to be provided for, e.g., the LinearAlgebra or Distribution packages.

Is there a specific kind of configuration required for including packages in the language server or is this just a Julia limitation?

Sounds like you haven’t added those dependencies to your project environment.

Should have mentioned it in the post but but yes, I have. And they are being correctly imported, since the program runs correctly.

Hi @Santiago_Lopez and welcome to the Julia community! :wave:

You may also want to consider reading this Discourse post to see if it helps with setting up the Julia LSP within Neovim: Neovim + LanguageServer.jl - #83 by TheCedarPrince Please let me know if it doesn’t help and I can help to the best of my ability!

Hello! Thank you very much for your answer.

I followed the steps in the post you referenced. After make I got

/bin/sh: 8:  #: not found
make: *** [makefile:69: packagecompiler/precompile_statements.jl] Error 127

However, the LSP server seemed to work in the example file. I can retrieve documentation on hover via the lua command and such. Nonetheless, although nothing worsened, nothing improved either. For example, calling ::lua vim.lsp.buf.hover() on the mul!() function of the LinearAlgebra package returns No information available, and a diagnostic next to the function call reads Missing reference: mul!. Next to using LinearAlgebra it also reads Missing reference: LinearAlgebra. However, as stated earlier, the package LinearAlgebra is installed and upon execution all its functions (mul! included) work fine.

EDIT: To be clear, these comments on the Linear Algebra package are not in the example file after make but on a personal project of mine.

Ah there was a typo with the makefile:

# MIT License. Copyright (c) 2021 Fredrik Ekre
#
# This Makefile can be used to build a custom Julia system image for LanguageServer.jl to
# use with neovims built in LSP support. An up-to date version of this Makefile can be found
# at https://github.com/fredrikekre/.dotfiles/blob/master/.julia/environments/nvim-lspconfig/Makefile
#
# Usage instructions:
#
#   1. Update the neovim configuration to use a custom julia executable. If you use
#      nvim-lspconfig (recommended) you can modify the setup call to the following:
#
#          require("lspconfig").julials.setup({
#              on_new_config = function(new_config, _)
#                  local julia = vim.fn.expand("~/.julia/environments/nvim-lspconfig/bin/julia")
#                  if require("lspconfig").util.path.is_file(julia) then
#                      new_config.cmd[1] = julia
#                  end
#              end,
#              -- ...
#          })
#
#   2. Place this Makefile in ~/.julia/environments/nvim-lspconfig (create the directory if
#      it doesn't already exist).
#
#   3. Change directory to ~/.julia/environments/nvim-lspconfig and run `make`. This will
#      start up neovim in a custom project with a julia process that recods compiler
#      statements. Follow the instructions in the opened source file, and then exit neovim.
#
#   4. Upon exiting neovim PackageCompiler.jl will compile a custom system image which will
#      automatically be used whenever you work on Julia projects in neovim.
#
# Update instructions:
#
#  To update the system image (e.g. when upgrading Julia or upgrading LanguageServer.jl or
#  it's dependencies) run the following commands from the
#  ~/.julia/environments/nvim-lspconfig directory:
#
#      julia --project=. -e 'using Pkg; Pkg.update()'
#      make

JULIA=$(shell which julia)
JULIA_PROJECT=
SRCDIR:=$(shell dirname $(abspath $(firstword $(MAKEFILE_LIST))))
ifeq ($(shell uname -s),Linux)
	SYSIMAGE=languageserver.so
else
	SYSIMAGE=languageserver.dylib
endif

default: $(SYSIMAGE)

$(SYSIMAGE): Manifest.toml packagecompiler/Manifest.toml packagecompiler/precompile_statements.jl
	JULIA_LOAD_PATH=${PWD}:${PWD}/packagecompiler:@stdlib ${JULIA} -e 'using PackageCompiler; PackageCompiler.create_sysimage(:LanguageServer, sysimage_path="$(SYSIMAGE)", precompile_statements_file="packagecompiler/precompile_statements.jl")'

Manifest.toml: Project.toml
	JULIA_LOAD_PATH=${PWD}/Project.toml:@stdlib ${JULIA} -e 'using Pkg; Pkg.instantiate()'

Project.toml:
	JULIA_LOAD_PATH=${PWD}/Project.toml:@stdlib ${JULIA} -e 'using Pkg; Pkg.add("LanguageServer")'

packagecompiler/Manifest.toml: packagecompiler/Project.toml
	JULIA_LOAD_PATH=${PWD}/packagecompiler/Project.toml:@stdlib ${JULIA} -e 'using Pkg; Pkg.instantiate()'

packagecompiler/Project.toml:
	mkdir -p packagecompiler
	JULIA_LOAD_PATH=${PWD}/packagecompiler/Project.toml:@stdlib ${JULIA} -e 'using Pkg; Pkg.add("PackageCompiler")'

packagecompiler/precompile_statements.jl: Manifest.toml bin/julia
	TMPDIR=$(shell mktemp -d) && \
	cd $${TMPDIR} && \
	JULIA_LOAD_PATH=: ${JULIA} -e 'using Pkg; Pkg.generate("Example")' 2> /dev/null && \
	cd Example && \
	JULIA_LOAD_PATH=$${PWD}:@stdlib ${JULIA} -e 'using Pkg; Pkg.add(["JSON", "fzf_jll", "Random", "Zlib_jll"])' 2> /dev/null && \
	JULIA_LOAD_PATH=$${PWD}:@stdlib ${JULIA} -e 'using Pkg; Pkg.precompile()' 2> /dev/null && \
	echo "$$PACKAGE_CONTENT" > src/Example.jl && \
	JULIA_TRACE_COMPILE=1 nvim src/Example.jl && \ # NOTE: You may need to check that neovim is correctly on your path
	rm -rf $${TMPDIR}

bin/julia:
	mkdir -p bin
	echo "$$JULIA_SHIM" > $@
	chmod +x $@

clean:
	rm -rf $(SYSIMAGE) packagecompiler bin

.PHONY: clean default

export JULIA_SHIM
define JULIA_SHIM
#!/bin/bash
JULIA=${JULIA}
if [[ $${JULIA_TRACE_COMPILE} = "1" ]]; then
    exec $${JULIA} --trace-compile=${PWD}/packagecompiler/precompile_statements.jl "$$@"
elif [[ -f ${PWD}/$(SYSIMAGE) ]]; then
    exec $${JULIA} --sysimage=${PWD}/$(SYSIMAGE) "$$@"
else
    exec $${JULIA} "$$@"
fi
endef

export PACKAGE_CONTENT
define PACKAGE_CONTENT
# This file is opened in neovim with a LanguageServer.jl process that records Julia
# compilation statements for creating a custom sysimage.
#
# This file has a bunch of linter errors which will exercise the linter and record
# statements for that. When the diagnostic messages corresponding to those errors show up in
# the buffer the language server should be ready to accept other commands (note: this may
# take a while -- be patient). Here are some suggestions for various LSP functionality that
# can be exercised (your regular keybindings should work):
#
#  - :lua vim.lsp.buf.hover()
#  - :lua vim.lsp.buf.definition()
#  - :lua vim.lsp.buf.references()
#  - :lua vim.lsp.buf.rename()
#  - :lua vim.lsp.buf.formatting()
#  - :lua vim.lsp.buf.formatting_sync()
#  - :lua vim.lsp.buf.code_action()
#  - Tab completion (if you have set this up using LSP)
#  - ...
#
# When you are finished, simply exit neovim and PackageCompiler.jl will use all the recorded
# statements to create a custom sysimage. This sysimage will be used for the language server
# process in the future, and should result in almost instant response.

module Example

import JSON
import fzf_jll
using Random
using Zlib_jll

function hello(who, notused)
    println("hello", who)
    shuffle([1, 2, 3])
   shoffle([1, 2, 3])
    fzzf = fzf_jll.fzzf()
    fzf = fzf_jll.fzf(1)
    JSON.print(stdout, Dict("hello" => [1, 2, 3]), 2, 123)
    JSON.print(stdout, Dict("hello" => [1, 2, 3]))
    hi(who)
    return Zlib_jll.libz
end

function world(s)
    if s == nothing
      hello(s)
  else
      hello(s)
  end
    x = [1, 2, 3]
    for i in 1:length(x)
        println(x[i])
    end
end

end
endef

The makefile should work now. Try following the steps again I provided with this new makefile.

Also, did you update your Packer configuration? And restart neovim? Let me know if things get resolved or not.

Once more, I thank you for taking the time to help me out here. Unfortunately, the exact same error results from the makefile you pasted here.

I do not use packer, I use Plug, and yes I did restart NeoVim.

Oh dear. :frowning: Let me see if I can do some digging around to find what may be going wrong.

Okay, the error was on my end! My Julia path was correctly referenced in the Ubuntu terminal but not in my Zsh terminal, which resulted in some strange behavior when running NeoVim from Zsh. Sorry for having taken time of your day and thank you very much!

I tried to re-run your instructions with the path issue fixed and the same error appeared. Just letting you know that that wasn’t due to something off with my computer (apparently at least). However, even without that process working, the LSP is fully functional now. Thanks!!

4 Likes

Oh good! Glad to hear it is working properly! I will update instructions on what you encountered and try to reproduce that error. Have a great day and happy vimming! Plus, welcome to the Julia community! Hope you have a great time here!

2 Likes

Just an update, for you may find this information useful. I installed Julia on my notebook (yesterday I was on my PC). I used the exact same NeoVim configuration I have on the PC.

This time, the language server was not starting at all (not the same problem as in the PC, where just some functionalities were not working). After running the process referred by you, using the makefile sourced in this thread (not the other one), everything works correctly.

The point being, your process and your makefile seem to entirely fix a non-responsive language server. And it appears the error received on make is irrelevant.

Have a great day!

Hello!

Just adding, I installed julia via snap and that seems to be the problem when using julials. Now I have a Julia manual installation in /usr/local with a symlink to julia binary in /bin. Everything is working well now.