Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Standalone usage of haxe-languageserver (Sublime Text, Neovim...) #171

Closed
wighawag opened this issue Sep 18, 2017 · 32 comments

Comments

@wighawag
Copy link

commented Sep 18, 2017

You might be already aware of it and this might be out of scope but there is a language server protocol (LSP) plugin for sublime : https://github.com/tomv564/LSP

Sorry if it is the wrong repo to post about sublime but I wondered how easy would it be to reuse what you did here and hook it up with sublime.

For example according to sublime LSP plugin doc here : https://lsp.readthedocs.io/en/latest/ you need to specify the path to the LSP executable. Is it what https://github.com/vshaxe/haxe-languageserver produce ?

@nadako

This comment has been minimized.

Copy link
Member

commented Sep 18, 2017

Yes, haxe-languageserver compiles to the node.js (currently) stdio LSP server, so it should be usable already, but it might require some specific configuration (haxe executable path, etc). I don't have much time and motivation to support sublime plugin, but I'll be happy to help with haxe-ls integration to whoever would work on it.

@Alloyed

This comment has been minimized.

Copy link

commented Sep 26, 2017

I came here looking for roughly the same info for neovim, which also integrates LSP in a low-touch way.
All we need really is documentation on haxe-languageserver specifically, as an external tool.
This would include:

  • how to install it (haxelib? npm?)
  • what CLI options/transports it supports, if any
  • what settings it supports from didChangeConfiguration, if any
@nadako

This comment has been minimized.

Copy link
Member

commented Sep 26, 2017

I see, so now when there's clearly some demand for this. We have to do some organizational work wrt making haxe-ls a standalone tool as it was originally designed :)

@kLabz

This comment has been minimized.

Copy link

commented Apr 12, 2018

I use haxe-languageserver with neovim but it doesn't play too well with it (I may have messed up somewhere). I would love some documentation :)

My main issue was that I ended up with a lot of haxe-languageserver zombie processes.. But I had to go back to vscode recently (c# + haxe project) and I have the same issue with vscode so it's probably not related to neovim at all.

@Gama11

This comment has been minimized.

Copy link
Member

commented Apr 12, 2018

Hm, no idea what that would cause that issue, but that's quite cool to hear nevertheless! Could you share what you needed to do to set it up?

@kLabz

This comment has been minimized.

Copy link

commented Apr 13, 2018

Actually it's not bad at all, I commented out most of my hacks overtime and now the needed setup seems sane. I think this is what saved me in the end :)

init.vim

" Language Server Protocol (LSP) support for vim and neovim.
Plug 'autozimu/LanguageClient-neovim', {'do': ':UpdateRemotePlugins'}

" Language server protocol config
let g:LanguageClient_serverCommands = {
	\ 'haxe': ['node', '/git/haxe-languageserver/bin/server.js'],
	\ }
let g:LanguageClient_autoStart = 1
let g:LanguageClient_loadSettings = 1

" Language Server Protocol
nnoremap <silent> K :call LanguageClient_textDocument_hover()<CR>
nnoremap <silent> gd :call LanguageClient_textDocument_definition()<CR>
nnoremap <silent> <F2> :call LanguageClient_textDocument_rename()<CR> 

.vim/settings.json (no context switching between build and test.hxml here)

{
    "initializationOptions": {
        "displayServerConfig": {
            "env": {},
            "path": "/usr/bin/haxe",
            "arguments": []
        },
        "displayArguments": [
            "build.hxml"
        ]
    },
    "haxe": {
        "enableDiagnostics": false,
        "diagnosticsPathFilter": "",
        "enableCodeLens": false,
        "displayPort": null,
        "buildCompletionCache": false,
        "codeGeneration": {},
        "format": {}
    }
}

I added a build.hxml in haxe-languageserver:

-lib haxe-hxparser
-lib hxnodejs

-cp src
-cp protocol/src
-cp formatter/src

-D hxnodejs-no-version-warning
-D JSTACK_FORMAT=vscode

-js bin/server.js
-dce full
-debug
-main haxeLanguageServer.Main

And I added a nullcheck around options in Context.onInitialize(). The other checks/hacks have been removed and it still works, I'm not even sure this one is still necessary:

if (options != null) {
    displayServerConfig = options.displayServerConfig;
    displayArguments = options.displayArguments;
}

Gama11 added a commit to vshaxe/haxe-language-server that referenced this issue Apr 13, 2018

@Gama11

This comment has been minimized.

Copy link
Member

commented Apr 13, 2018

Thanks for sharing! Setting things up took a bit of trial-and-error, since I'm not familiar with Vim or NeoVim at all. I had to make some adjustments to your init.vim:

  • The Plug command needs to be surrounded by call plug#begin('plugged') and call plug#end()
  • I needed to associate .hx files with haxe (presumably you already have some Haxe plugin installed that does this?)
    au BufNewFile,BufRead *.hx setlocal ft=haxe

I also made a small patch for haxe-languageserver: vshaxe/haxe-language-server@95dfaa3 seems like LanguageClient-neovim doesn't like the use of workspaceFolders, which was a recent change. :)

Btw, you shouldn't need that build.hxml, you can build the language server as usual with vshaxe-build. We should probably make sure not to build it to ../bin/server.js so it works more smoothly when you've checked out the language server standalone.

That all being said, I still didn't get completion features to work so far, just getting messages like 'Unhandled method textDocument/definition' in the LanguageClient.log file so far. Have you had any luck getting any log output from the server (what you would normally see in the Haxe output channel in VSCode)? It seems it's supposed to go into LanguageServer.log, but that's just empty for me. I've tried a few different options like LanguageClient_loggingLevel and LanguageClient_windowLogMessageLevel. I guess I can work around it by writing logs to a file...

Also, it looks like Plug 'autozimu/LanguageClient-neovim', {'do': ':UpdateRemotePlugins'} installs the "legacy" version of LanguageClient-neovim - I wonder if that even has the settings.json support you linked to?

@kLabz

This comment has been minimized.

Copy link

commented Apr 13, 2018

Sorry the vim config was minimal and a lot of needed things were stripped off. I'll try to find some time to make a minimal working vim config with all other needed plugins/configs.

The Unhandled method textDocument/definition issue was what I had until I got the lsp to use my settings.json, btw. I don't remember where/how I got the logs, but I remember that I managed to get them after a while.

Gama11 added a commit to vshaxe/haxe-language-server that referenced this issue Apr 13, 2018

Build the server to bin/ instead of ../bin/
This simplifies standalone usage of the language server, see vshaxe/vshaxe#171

@Gama11 Gama11 changed the title Sublime Language Server Protocol plugin Standalone usage of haxe-languageserver (Sublime Text, Neovim...) Apr 13, 2018

Gama11 added a commit that referenced this issue Apr 13, 2018

Build the server to server/bin/ instead of bin/
This simplifies standalone usage of the language server, see #171
@kLabz

This comment has been minimized.

Copy link

commented Apr 13, 2018

Err, the haxe 4 dependency is really painful. Will do that later, if I find some time. Shouldn't need much more anyway, the legacy version works fine for me with these:

Plug 'roxma/nvim-completion-manager'
Plug 'jdonaldson/vaxe'

Will try the new versions of both LanguageClient-neovim and vshaxe-languageserver later to see if I see some improvements :) (and if they work together)

(as for the build.hxml, I made it because installing and using an undocumented build tool for something that could be handled by a hxml file wasn't something I wanted to do)

@kLabz

This comment has been minimized.

Copy link

commented Apr 13, 2018

I can't make it work with current master branch of vshaxe-languageserver, but it works with vshaxe/haxe-language-server@e119a7e

I'll try to find when things got wrong for LanguageClient-neovim support =/

@kLabz

This comment has been minimized.

Copy link

commented Apr 13, 2018

Got it to work (still on legacy LanguageClient-neovim) by reverting two commits:

I'll see what I can do with the latest LanguageClient-neovim version.

@kLabz

This comment has been minimized.

Copy link

commented Apr 13, 2018

Have you had any luck getting any log output from the server (what you would normally see in the Haxe output channel in VSCode)?

Yep.
LanguageClient-neovim logs will be in LanguageClient.log, and server stderr (so use console.error()) will be in LanguageServer.log.

I don't get what's wrong between LanguageClient-neovim next and current haxe-languageserver..

I see these in logs during initialization:

{
    "jsonrpc": "2.0",
    "method": "initialize",
    "params": {
        "capabilities": {
            "textDocument": {
                "completion": {
                    "completionItem": {
                        "commitCharactersSupport": null,
                        "documentationFormat": null,
                        "snippetSupport": false
                    },
                    "dynamicRegistration": null
                }
            }
        },
        "initializationOptions": {
            "displayArguments": [
                "build.hxml"
            ],
            "displayServerConfig": {
                "arguments": [],
                "env": {},
                "path": "/usr/bin/haxe"
            }
        },
        "processId": 9321,
        "rootPath": "/git/haxe-languageserver",
        "rootUri": "file:///git/haxe-languageserver",
        "trace": "off"
    },
    "id": 9
}
{
    "jsonrpc": "2.0",
    "id": 9,
    "result": {
        "capabilities": {
            "textDocumentSync": 2,
            "completionProvider": {
                "triggerCharacters": [
                    ".",
                    "@",
                    ":"
                ]
            },
            "signatureHelpProvider": {
                "triggerCharacters": [
                    "(",
                    ","
                ]
            },
            "definitionProvider": true,
            "hoverProvider": true,
            "referencesProvider": true,
            "documentSymbolProvider": true,
            "workspaceSymbolProvider": true,
            "codeActionProvider": true,
            "documentFormattingProvider": true,
            "codeLensProvider": {
                "resolveProvider": true
            },
            "renameProvider": true
        }
    }
}

And then when triggering autocompletion:

{
    "jsonrpc": "2.0",
    "method": "textDocument/completion",
    "params": {
        "position": {
            "character": 6,
            "line": 4
        },
        "textDocument": {
            "uri": "file:///git/haxe-languageserver/src/haxeLanguageServer/ApplyFixesCommand.hx"
        }
    },
    "id": 21
}
{
    "jsonrpc": "2.0",
    "id": 21,
    "error": {
        "code": -32601,
        "message": "Unhandled method textDocument/completion"
    }
}
@Gama11

This comment has been minimized.

Copy link
Member

commented Apr 13, 2018

and server stderr (so use console.error()) will be in LanguageServer.log

Oh, interesting. So I guess there's no support for thet LogMessage method that it uses by default for the output channel in VSCode?

Thanks for figuring out the problematic commits, I'll check if downgrading makes it work for me and if I can fix it so it works for both Neovim and VSCode. :)

@kLabz

This comment has been minimized.

Copy link

commented Apr 14, 2018

Ok, got "next" LanguageClient-neovim to work with haxe-languageserver, by doing two things:

  • revert vshaxe/haxe-language-server@0a0ef50 (this one is an issue with both legacy and next LanguageClient-neovim)
  • manually send onDidChangeConfiguration, seems like an issue to solve on the LanguageClient-neovim side

I used a custom function to send onDidChangeConfiguration:

function! DidChangeConfig()
	let config = json_decode(system("cat .vim/settings.json"))
	call LanguageClient#Notify('workspace/didChangeConfiguration', { 'settings': config })
endfunction

I'll see what can be done to send this automatically.

As for LogMessage, I have no idea =/

@Gama11

This comment has been minimized.

Copy link
Member

commented Apr 14, 2018

Regarding the "next" branch of LanguageClient-neovim - I guess you need to have Rust installed and build it from source? Or are there pre-built binaries anywhere?

@kLabz

This comment has been minimized.

Copy link

commented Apr 14, 2018

I added Plug 'autozimu/LanguageClient-neovim', {'branch': 'next', 'do': 'bash install.sh'} instead of the old one in my init.vim.

I also did :UpdateRemotePlugins after the :PlugInstall, not sure if it was useful.

@Gama11

This comment has been minimized.

Copy link
Member

commented Apr 14, 2018

Oh, I guess for Windows it needs to be install.ps1 instead: https://github.com/autozimu/LanguageClient-neovim/blob/next/install.ps1

Gama11 added a commit to vshaxe/haxe-language-server that referenced this issue Apr 14, 2018

Gama11 added a commit to vshaxe/haxe-language-server that referenced this issue Apr 14, 2018

Gama11 added a commit to vshaxe/haxe-language-server that referenced this issue Apr 14, 2018

Disable socket listener by default in standalone scenarios
The "auto" default probably only makes sense within vshaxe right now.
vshaxe/vshaxe#171

Gama11 added a commit to vshaxe/haxe-language-server that referenced this issue Apr 14, 2018

@Gama11

This comment has been minimized.

Copy link
Member

commented Apr 14, 2018

I made a few changes to check what features the language client actually supports (before we would just use new features without checking, which caused some of the issues you mentioned). I also added some default settings, so haxe-languageserver is now fine with getting nothing / null as its settings.

Anyway, I got completion / hover / document symbols working!

Still some issues with rename and goto defintion it appears.

@kLabz

This comment has been minimized.

Copy link

commented Apr 15, 2018

Nice! Thanks for your efforts on making haxe-languageserver work on non-vscode editors 👍

Still having some troubles though, as I want to be able to switch hxml files.

onDidChangeDisplayArguments and onDidChangeDisplayServerConfig don't seem to be available outside vscode, so onDidChangeConfiguration seemed to me to be a candidate to do that by handling initializationOptions if provided. Of course, if you have a better way to do that I'd be happy to change my nvim config to handle it.

The patch I am using:

diff --git a/src/haxeLanguageServer/Context.hx b/src/haxeLanguageServer/Context.hx
index d42fa89..cf2b31f 100644
--- a/src/haxeLanguageServer/Context.hx
+++ b/src/haxeLanguageServer/Context.hx
@@ -166,6 +166,19 @@ class Context {
 
         var newConfigJson = Json.stringify(newHaxeConfig);
         var configUnchanged = Json.stringify(unmodifiedConfig) == newConfigJson;
+
+        var initOptions = newConfig.settings.initializationOptions;
+        if (initOptions != null) {
+            if (initOptions.displayServerConfig != null) {
+                displayServerConfig = initOptions.displayServerConfig;
+                configUnchanged = false;
+            }
+            if (initOptions.displayArguments != null) {
+                displayArguments = initOptions.displayArguments;
+                configUnchanged = false;
+            }
+        }
+
         if (!firstInit && configUnchanged) {
             return;
         }

The relevant nvim config:

init.vim

" [...]
let g:LanguageClient_serverCommands = {
	\ 'haxe': ['node', '/git/haxe-languageserver/bin/server.js']
	\ }
let g:LanguageClient_autoStart = 1
let g:LanguageClient_loadSettings = 0
" let g:LanguageClient_loggingLevel = 'DEBUG'

" Auto config Haxe LSP
augroup LanguageClient_config
    autocmd!
    autocmd User LanguageClientStarted call k#haxelsp#SetConfig("build.hxml")
augroup END
" [...]

~/.config/nvim/autoload/k/haxelsp.vim

function! k#haxelsp#SetConfig(hxml)
	if &ft=="haxe"
		let haxeConfig = json_decode(system("cat ~/.config/nvim/haxelsp/haxe-settings.json"))
		let serverConfig = json_decode(system("cat ~/.config/nvim/haxelsp/server-config.json"))

		call LanguageClient#Notify('workspace/didChangeConfiguration', {'settings': {
			\ 'haxe': haxeConfig,
			\ 'initializationOptions': {
				\ 'displayServerConfig': serverConfig,
				\ 'displayArguments': [a:hxml]
			\ }
		\ }})
	endif
endfunction

~/.config/nvim/haxelsp/haxe-settings.json

{
	"enableDiagnostics": true,
	"diagnosticsPathFilter": "",
	"enableCodeLens": true,
	"displayPort": "auto",
	"buildCompletionCache": true,
	"codeGeneration": {},
	"format": {}
}

~/.config/nvim/haxelsp/server-config.json

{
	"env": {},
	"path": "/usr/bin/haxe",
	"arguments": []
}

Still some issues with rename and goto defintion it appears.

Works for me with this config :)

@Gama11

This comment has been minimized.

Copy link
Member

commented Apr 15, 2018

onDidChangeDisplayArguments and onDidChangeDisplayServerConfig don't seem to be available outside vscode

They're custom methods not defined in LSP, yes, but it should still be possible to call them I think? Your call to LanguageClient#Notify() there just seems to take an arbitrary string after all. The methods are defined here:

https://github.com/vshaxe/haxe-languageserver/blob/master/src/haxeLanguageServer/VshaxeMethods.hx

("vshaxe/didChangeDisplayArguments" and "vshaxe/didChangeDisplayServerConfig")

Still some issues with rename and goto defintion it appears.

Works for me with this config :)

Interesting, maybe some issue with LanguageClient-neovim legacy then. I should try the next branch.

@kLabz

This comment has been minimized.

Copy link

commented Apr 15, 2018

Indeed I can call them, I just had an issue with an early restartServer, so I modified the functions:

    function onDidChangeDisplayArguments(params:{arguments:Array<String>}) {
        displayArguments = params.arguments;
        if (config != null) restartServer("display arguments changed");
    }

    function onDidChangeDisplayServerConfig(config:DisplayServerConfig) {
        displayServerConfig = config;
        if (config != null) restartServer("display server configuration changed");
    }

Is this reasonable? I removed the previous patch and call these instead now.

@Gama11

This comment has been minimized.

Copy link
Member

commented Apr 15, 2018

Ah, yeah, I see the issue. Can't hurt to check for that. :)

I think I'm also going to rename the vshaxe methods to haxe, since the former doesn't make so much sense in a standalone context.

I'm not sure what the final UX should look like.. I guess some aspects of vshaxe's HXML-file auto-discovery could be moved into the server, so onDidChangeDisplayArguments() calls can be optional (at least in the case of there only being a single build.hxml in the root directory). But that requires to move HXML parsing etc too.. would need some thought.

@jdonaldson has expressed interest in a vaxe fork using haxe-languageserver, presumably that plugin would want to interface with onDidChangeDisplayArguments in some way too.

Gama11 added a commit to vshaxe/haxe-language-server that referenced this issue Apr 15, 2018

Gama11 added a commit to vshaxe/haxe-language-server that referenced this issue Apr 15, 2018

VshaxeMethods -> HaxeMethods
Makes more sense in standalone context (vshaxe/vshaxe#171).

Gama11 added a commit that referenced this issue Apr 15, 2018

VshaxeMethods -> HaxeMethods
Makes more sense in standalone context (#171).
@kLabz

This comment has been minimized.

Copy link

commented Apr 15, 2018

Looks good to me, thanks!

Indeed an integration within vaxe would be perfect. I am using some vimscript I created today, but nothing publishable and I have no experience in developing nvim plugins.

@kLabz

This comment has been minimized.

Copy link

commented Apr 15, 2018

Works for sublime text too:

// Settings in here override those in "LSP/LSP.sublime-settings",
{
	"clients": {
		"haxe": {
			"command": ["node", "/git/haxe-languageserver/bin/server.js"],
			"scopes": ["source.haxe"],
			"syntaxes": ["Packages/Haxe/Haxe.sublime-syntax"],
			"languageId": "haxe",
			"initializationOptions": {
				"displayServerConfig": {
					"env": {},
					"path": "/usr/bin/haxe",
					"arguments": []
				},
				"displayArguments": ["build.hxml"],
			},
			"settings": {
				"haxe": {
					"enableDiagnostics": true,
					"diagnosticsPathFilter": "",
					"enableCodeLens": true,
					"displayPort": "auto",
					"buildCompletionCache": true,
					"codeGeneration": {},
					"format": {}
				}
			}
		}
	}
}
@Gama11

This comment has been minimized.

Copy link
Member

commented Apr 15, 2018

That's great to hear. :) I don't think that "haxe" settings section should be needed anymore?

@kLabz

This comment has been minimized.

Copy link

commented Apr 15, 2018

Yep, works fine without the settings block too (just confirmed it), but I added it to show how to set these settings.

@jdonaldson

This comment has been minimized.

Copy link

commented Jun 15, 2018

I just spent some time messing around with the plugins. I can get the context server to start, but none of the config is sent to it successfully there are some other issues.

      let haxeConfig = json_decode(system("cat ~/haxe-settings.json"))
      let serverConfig = json_decode(system("cat ~/server-config.json"))

      echomsg string(haxeConfig)
      echomsg string(serverConfig)

      call LanguageClient#Notify('workspace/didChangeConfiguration', {
            \'settings': {
              \'haxe': haxeConfig,
              \'initializationOptions': {
                \'displayServerConfig': serverConfig,
                \'displayArguments': [a:hxml]
              \ }
            \}
            \})

Sanity checking the changeConfiguration object shows that everything is where it should be according to the notes here.

Some more initial notes...

  • It looks like the haxe language server is "pinged" immediately when g:LanguageClient_serverCommands are set. This is done before any of the config parameters are set, and the config options are an empty object.
  • There's a null check for options inside of the haxe server's start method. This null check will populate the config with standard options if the option object is null. However the options are not null (empty object), so the language server treats them as present, and fails subsequent configuration lookups.
@jdonaldson

This comment has been minimized.

Copy link

commented Jun 16, 2018

I'll put up a pull request over here with some more discussion : vshaxe/haxe-language-server#35

@nabezokodaikon

This comment has been minimized.

Copy link

commented May 11, 2019

In the end where is the right thing to do?

@Gama11

This comment has been minimized.

Copy link
Member

commented May 11, 2019

Here's the most up-to-date setup with Neovim: #328 (comment)

@nabezokodaikon

This comment has been minimized.

Copy link

commented May 11, 2019

thanks

@Gama11

This comment has been minimized.

Copy link
Member

commented May 20, 2019

Closing this in favor of the more up-to-date coc.nvim "guide" in #328. Eventually we should probably document this properly in a wiki page.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
7 participants
You can’t perform that action at this time.