Skip to content

Language servers

Matthieu Coudron edited this page May 21, 2019 · 79 revisions

Contents

Supported features

Check out the official specification at https://microsoft.github.io/language-server-protocol/specification.

  • General

    • initialize
    • initalized
    • shutdown
    • exit
    • $/cancelRequest
  • Window

    • showMessage
    • showMessageRequest
    • logMessage
  • Telemetry

    • event (just log the event)
  • Client

    • registerCapability
    • unregisterCapability
  • Workspace

    • workspaceFolders
    • didChangeWorkspaceFolders
    • didChangeConfiguration
    • configuration
    • didChangeWatchedFiles
    • symbol
    • executeCommand
    • applyEdit
    • resource operations
  • Text Synchronization

    • didOpen
    • didChange
    • willSave
    • willSaveWaitUntil
    • didSave
    • didClose
  • Diagnostics

    • publishDiagnostics
  • Language Features

    • completion
    • completion resolve
    • hover
    • signatureHelp
    • definition
    • typeDefinition
    • implementation
    • references
    • documentHighlight
    • documentSymbol
    • codeAction
    • codeLens
    • codeLens resolve
    • documentLink
    • documentLink resolve
    • documentColor
    • colorPresentation
    • formatting
    • rangeFormatting
    • onTypeFormatting
    • prepare rename
    • rename
    • foldingRange

Note: different servers can have different capabilities.

Register custom language servers

User defined language servers are configured in the languageserver field of the configuration file.

There're three types of language servers: module,executable and socket.

  • module type language servers are run by nodejs and using node IPC for connection.
  • executable type language servers are spawned with an executable command while using stdio for connection.
  • socket language servers are started in a separated process, normally used for debugging purpose.

Different language server types have different configuration schema.

An example of module language server:

  "languageserver": {
    "foo": {
      "module": "/usr/local/lib/node_modules/foo/index.js",
      "args": ["--node-ipc"],
      "filetypes": ["foo"],
      "trace.server": "verbose",
      "rootPatterns": ["root.yml"],
      // Used for debugging
      "execArgv": ["--nolazy", "--inspect-brk=6045"],
      "initializationOptions": {
      },
      "settings": {
        "validate": true
      }
    }
  }

module and filetypes are required for module language server.

An example of executable language server:

  "languageserver": {
    "bar": {
      "command": "bar",
      "args": ["--stdio"],
      "filetypes": ["bar"],
      "cwd": "./src",
      "initializationOptions": {
      },
      "settings": {
      }
    }
  }

command and filetypes are required for executable language server.

An example of socket language server:

"languageserver": {
    "socketserver": {
      "host": "127.0.0.1",
      "port": 9527
    }
  }

port is required for a socket service and user should start the socket server before coc starts.

  • initializationOptions is the json object that passed to language server on initialize.
  • settings contains specific configuration of the language server.
  • trace.server controls trace level of communication between server and client. The default is "off". Change to "verbose" if you want to checkout all communication.
  • rootPatterns is used to resolve the root path which should contain one of the patterns as a child directory or file, it will use "coc.preferences.rootPatterns" (default to [".vim", ".git", ".hg", ".projections.json"]) when not specified,
  • requireRootPattern when this is true, the language server will only start when any matched rootPatterns found.

Example configuration for custom language servers

Add languageserver section in your coc-settings.json for registering custom language servers.

Dart

Using natebosch/dart_language_server:

  "languageserver": {
    "dart": {
      "command": "dart_language_server", // in windows is dart_language_server.bat
      "args": [],
      "filetypes": ["dart"],
      "initializationOptions": {},
      "settings": {
        "dart": {
          "validation": {},
          "completion": {}
        }
      }
    }
  }

C/C++/Objective-C

Using ccls

  "languageserver": {
    "ccls": {
      "command": "ccls",
      "filetypes": ["c", "cpp", "objc", "objcpp"],
      "rootPatterns": [".ccls", "compile_commands.json", ".vim/", ".git/", ".hg/"],
      "initializationOptions": {
         "cache": {
           "directory": "/tmp/ccls"
         }
       }
    }
  }

Using cquery

  "languageserver": {
    "cquery": {
      "command": "cquery",
      "args": ["--log-file=/tmp/cq.log"],
      "filetypes": ["c", "cpp"],
      "rootPatterns": ["compile_flags.txt", "compile_commands.json", ".vim/", ".git/", ".hg/"],
      "initializationOptions": {
        "cacheDirectory": "/tmp/cquery"
      }
    }
  }

Using clangd

  "languageserver": {
    "clangd": {
      "command": "clangd",
      "rootPatterns": ["compile_flags.txt", "compile_commands.json", ".vim/", ".git/", ".hg/"],
      "filetypes": ["c", "cpp", "objc", "objcpp"]
    }
  }

Like many tools, clangd relies on the presence of a JSON compilation database

Go

Using gopls

  "languageserver": {
    "golang": {
      "command": "gopls",
      "rootPatterns": ["go.mod", ".vim/", ".git/", ".hg/"],
      "filetypes": ["go"]
    }
  }

Using saibing/bingo

  "languageserver": {
    "golang": {
      "command": "bingo",
      "args": ["--diagnostics-style=instant"],
      "rootPatterns": ["go.mod", ".vim/", ".git/", ".hg/"],
      "filetypes": ["go"]
    }
  }

Using sourcegraph/go-langserver

  "languageserver": {
    "golang": {
      "command": "go-langserver",
      "filetypes": ["go"],
      "initializationOptions": {
        "gocodeCompletionEnabled": true,
        "diagnosticsEnabled": true,
        "lintTool": "golint"
      }
    }
  }

PHP

Try marlonfan/coc-phpls or one of the following methods:

Using bmewburn/intelephense-docs

Recommended (way faster than php-language-server)

{
    "languageserver": {
        "intelephense": {
            "command": "intelephense",
            "args": ["--stdio"],
            "filetypes": ["php"],
            "initializationOptions": {
                "storagePath": "/tmp/intelephense"
            }
        }
    },
}

Using felixfbecker/php-language-server

  "languageserver": {
    "phplang": {
      "command": "php",
      "args": ["/path/to/vendor/felixfbecker/language-server/bin/php-language-server.php"],
      "filetypes": ["php"]
    }
  }

note: make sure you can start the server by use command and args.

Dockerfile

Using rcjsuen/dockerfile-language-server-nodejs

  "languageserver": {
    "dockerfile": {
      "command": "docker-langserver",
      "filetypes": ["dockerfile"],
      "args": ["--stdio"]
    }
  }

Bash

Using mads-hartmann/bash-language-server

  "languageserver": {
    "bash": {
      "command": "bash-language-server",
      "args": ["start"],
      "filetypes": ["sh"],
      "ignoredRootPaths": ["~"]
    }
  }

Lua

Using Alloyed/lua-lsp

  "languageserver": {
    "lua": {
      "command": "lua-lsp",
      "filetypes": ["lua"]
    }
  }

Using sumneko/lua-language-server on Windows, which can downloaded by the extension manager of VSCode.

let lua_lsp = glob('~/.vscode/extensions/sumneko.lua*', 0, 1)
if len(lua_lsp)
    let lua_lsp = lua_lsp[-1] . '\server'
    call coc#config('languageserver', {
        \ 'lua-language-server': {
        \     'cwd': lua_lsp,
        \     'command': lua_lsp . '\bin\lua-language-server.exe',
        \     'args': ['-E', '-e', 'LANG="zh-cn"', lua_lsp . '\main.lua'],
        \     'filetypes': ['lua'],
        \ }
    \ })
endif

OCaml and ReasonML

Using ocaml-language-server

  "languageserver": {
     "ocaml": {
       "command": "ocaml-language-server",
       "args": ["--stdio"],
       "filetypes": ["ocaml", "reason"]
     }
  }

Using reason-language-server

  "languageserver": {
     "reason": {
      "command": "/absolute/path/to/reason-language-server.exe",
      "filetypes": ["reason"]
     }
  }

PureScript

Using purescript-language-server

  "languageserver": {
     "purescript": {
       "command": "purescript-language-server",
       "args": ["--stdio"],
       "filetypes": ["purescript"],
       "rootPatterns": ["bower.json", "psc-package.json", "spago.dhall"]
     }
  }

Flow

Using flow-language-server, note: flow-language-server is no longer maintained

  // disable tsserver for javascript
  "tsserver.enableJavascript": true,
  "languageserver": {
    "flow": {
      "command": "flow-language-server",
      "args": ["--stdio"],
      "filetypes": ["javascript", "javascriptreact"],
      "rootPatterns": [".flowconfig"]
    },
  }

Using flow lsp

  "languageserver": {
    "flow": {
      "command": "flow",
      "args": ["lsp"],
      "filetypes": ["javascript", "javascriptreact"],
      "initializationOptions": {},
      "requireRootPattern": true,
      "settings": {},
      "rootPatterns": [".flowconfig"]
    }
  },

Haskell

Using Haskell IDE Engine

"languageserver": {
  "haskell": {
    "command": "hie-wrapper",
    "rootPatterns": [".stack.yaml", "cabal.config", "package.yaml"],
    "filetypes": ["hs", "lhs", "haskell"],
    "initializationOptions": {},
    "settings": {
	"languageServerHaskell": {
		"hlintOn": false,
		"maxNumberOfProblems": 10,
		"completionSnippetsOn": true
	}
     }
  }
}

vim/erb/markdown

Using efm-langserver

Location of efm-langserver config.yaml is:

  • UNIX: $HOME/.config/efm-langserver/config.yaml
  • Windows: %APPDATA%\efm-langserver\config.yaml

efm-langserver config:

languages:
  eruby:
    lint-command: 'erb -x -T - | ruby -c'
    lint-stdin: true
    lint-offset: 1
    format-command: 'htmlbeautifier'

  vim:
    lint-command: 'vint -'
    lint-stdin: true

  markdown:
    lint-command: 'markdownlint -s'
    lint-stdin: true
    lint-formats:
      - '%f: %l: %m'

coc-settings.json

  "languageserver": {
    "efm": {
      "command": "efm-langserver",
      "args": [],
      // custom config path
      // "args": ["-c", "/path/to/your/config.yaml"],
      "filetypes": ["vim", "eruby", "markdown"]
    }
  }

Elixir

Using elixir-ls

  "languageserver": {
     "elixirLS": {
      "command": "/absolute/path/to/elixir-ls/release/language_server.sh",
      "filetypes": ["elixir", "eelixir"]
     }
  }

Ruby

Use coc-solargraph extension is recommended.

Make sure solargraph is in your $PATH (sudo gem install solargraph) or use solargraph.commandPath to configure executable path of solargraph.

Scala

Using scalameta/metals:

Make sure the generated metals-vim binary is available on your $PATH. Installation instructions can be found on the Scalameta Metals website.

  "languageserver": {
    "metals": {
      "command": "metals-vim",
      "rootPatterns": ["build.sbt"],
      "filetypes": ["scala", "sbt"]
    }
  }

LaTeX

Using astoff/digestif:

Make sure the digestif executable is available on your $PATH or use absolute path as command. Installation instructions can be found here.

To correct filetype send to server, you may need add:

let g:coc_filetype_map = {
  \ 'tex': 'latext',
  \ 'plaintex': 'tex',
  \ }

to your vimrc.

  "languageserver": {
    "digestif": {
      "command": "digestif",
      "filetypes": ["tex", "plaintex", "context"]
    }
  }
You can’t perform that action at this time.