This repository contains an implementation of the Microsoft Language Server Protocol for Ada/SPARK.
Current features:
- GNAT project files support.
- Code completion for names, keywords, aggregates, etc.
- Code navigation, such as Go to Definition/Declaration, Find All References, Call Hierarchies, etc.
- Code refactoring like insert named associations, auto-add
with
-clauses, etc. - Document/Workspace symbol search.
- Code folding and formatting.
We also provide Visual Studio Code extension at the VS Marketplace and at the Open VSX Registry.
- Ada Language Server
- Table of Contents
- Install
- Usage
- Supported LSP Server Requests
- How to use the VScode extension
- Integration with Coc.NVim
- Integration with vim-lsp
- Integration with LanguageClient-Neovim
- Integration with Neovim's built-in LSP client
- Integration with QtCreator
- Refactoring Tools
- Authors & Contributors
- Contribute
- License
You can build language server from sources. To build it from sources install dependencies and run
make
It will build .obj/server/ada_language_server
file.
To build the language server you need:
- The GNAT compiler (at least GCC 11 or GNAT Community Edition 2021)
- The Libadalang library (it should be built)
- The Libadalang-tools library
- The VSS library
- The gnatdoc library
- The gpr library
- The a process spawn library
Project files of the libraries must be available via the GPR_PROJECT_PATH
environment variable.
To run the language server you need gnatls
(parts of GNAT installation)
somewhere in the path.
The ada_language_server
doesn't require any command line options,
but it understands these options:
--tracefile=<FILE>
- Full path to a file containing traces configuration--config=<FILE>
- Full path to a JSON file containing the server's configuration--help
- Display supported command like options and exit.
You can turn some debugging and experimental features trought the traces file.
The server also gets configuration via workspace/didChangeConfiguration
notification and initializationOptions
of initialize
request.
See more details here. Each LSP
client provides its-own way to set such settings. You can use the --config
option if you want to provide the configuration directly via a JSON file
instead of specifying it via the requests listed just above.
See WiKi page for the list of supported requests.
The Ada Language Server supports some features that are not in the official Language Server Protocol specification. See corresponding document.
The VSCode extension has a few limitations and some differences compared to GNAT Studio:
-
Indentation/formatting: it does not support automatic indentation when adding a newline and range/document formatting might no succeed on incomplete/illegal code.
-
Toooling support: we currently provide minimal support for SPARK (see Prove/Examine tasks in the Auto-detected tasks section), but there is no support for tools such as CodePeer, GNATcheck, GNATtest or GNATcoverage.
-
Project support: there is no
Scenario
view: users should configure scenarios via the ada.scenarioVariables setting (see the settings list available here). You can execute the Developper: Reload Window command to reload your project after saving the new scenario values (use the Ctrl+P shortcut to invoke the Command Palette, allowing you to execute commands).Source directories from imported projects should be added in a workspace file. If you already have a workspace file, the extension will propose you to automatically add all the source directories coming from imported projects to your workspace automatically at startup.
-
Debugging: some manual work is needed in order to debug Ada code. In particular, you will need a
launch.json
file that describes your debugging configuration. All the steps needed for debugging are described here.
Tutorial: Using Ada in VS Code.
See a dedicated document with the list of available refactorings.
The extension includes a task provider. It provides the following "auto-detected" tasks
(under /Terminal/Run Task...
menu):
- "ada: Build current project" - launch
gprbuild
to build the current GPR project - "ada: Check current file" - launch
gprbuild
to check errors in the current editor - "ada: Clean current project" - launch
gprclean
to clean the current GPR project - "ada: Examine project" - launch
gnatprove
in flow analysis mode on the current GPR project - "ada: Examine file" - launch
gnatprove
in flow analysis mode on the file in the current editor - "ada: Examine subprogram" - launch
gnatprove
in flow analysis mode on the current subprogram in the current editor - "ada: Prove project" - launch
gnatprove
on the current GPR project - "ada: Prove file" - launch
gnatprove
on the file in the current editor - "ada: Prove subprogram" - launch
gnatprove
on the current subprogram in the current editor - "ada: Prove selected region" - launch
gnatprove
on the selected region in the current editor - "ada: Prove line" - launch
gnatprove
on the cursor line in the current editor
You can bind keyboard shortcuts to them by adding to the keybindings.json
file:
{
"key": "alt+v",
"command": "workbench.action.tasks.runTask",
"args": "ada: Check current file",
"when": "editorLangId == ada"
}
A demo for auto-detected tasks
You can customize autodetected tasks
by providing extra tool command line options via args
property in the tasks.json
:
{
"version": "2.0.0",
"tasks": [
{
"type": "gnat",
"taskKind": "buildProject",
"problemMatcher": [
"$ada"
],
"group": "build",
"label": "ada: Build project",
"args": ["-gargs", "-vh"]
}
]
}
The extension contributes a few commands and corresponding key bindings.
This command switches between specification and implementation Ada files.
The default shortcut is Alt+O
.
This command inserts a comment box before the current subprogram body.
The default shortcut is Alt+Shift+B
.
This command reloads the current project.
The default shortcut is None
.
For the moment, this repository includes a vscode extension that is used as the reference extension for this implementation.
You can try it by running:
code --extensionDevelopmentPath=<path_to_this_repo>/integration/vscode/ada <workspace directory>
You can configure the extension via the .vscode/settings.json
settings file.
See the setting list here.
Here is an example config file from the gnatcov project:
{
"ada.projectFile": "gnatcov.gpr",
"ada.scenarioVariables": {
"BINUTILS_BUILD_DIR": "/null",
"BINUTILS_SRC_DIR": "/null"
},
"ada.defaultCharset": "utf-8",
"ada.enableDiagnostics": false,
"ada.renameInComments": false
}
If you want to use the Ada Language Server with Vim/Neovim, you can use the
Coc.NVim. You'll have to
install the Ada Language Server manually somewhere on your
computer. Follow installation instructions on Coc.NVim website and then
configure the Ada Language Server with :CocConfig
:
{
"languageserver": {
"ada": {
"settings": {
"ada": {
"projectFile": "gnat/vss_text.gpr"
}
},
"command": "<path>/ada_language_server",
"filetypes": [
"ads",
"adb",
"ada"
]
}
}
}
If you want to integrate the Ada Language Server into vim, you can use the vim-lsp.
You'll have to install the Ada Language Server manually somewhere on your
computer, and then you can add the following line to your .vimrc
file:
if executable('ada_language_server')
au User lsp_setup call lsp#register_server({
\ 'name': 'ada_language_server',
\ 'cmd': ['ada_language_server'],
\ 'allowlist': ['ada'],
\ 'workspace_config': {'ada': {
\ 'projectFile': "project.gpr",
\ 'scenarioVariables': {"ARCH": "x86_64-pc-linux-gnu"}}},
\ })
endif
If you want to integrate the Ada Language Server into Neovim, you can use the LanguageClient-neovim.
You'll have to install the Ada Language Server manually somewhere on your
computer, and then you can add the following line to your init.vim
file:
" replace the path below with the proper path to the ada_language_server executable
let g:LanguageClient_serverCommands = {
\ 'ada': ['path/to/ada_language_server'],
\ }
" if you already have LanguageClient_serverCommands, just add a line for ada.
To configure the Ada Language Server for a specific workspace/project, you can
use the .vim/settings.json
file. It is mandatory as soon as you want to use a
specific .gpr
project file.
This is the way to specify a project file, eg. you cannot open a project file another way. See the setting list here.
Here is an example of a settings file:
{
"ada.projectFile": "project.gpr",
"ada.scenarioVariables": {
"GLFW_Version": "3",
"GLFW_Lib": "-lglfw",
"Windowing_System": "x11"
}
}
The location where the .vim
folder is located will determine the relative
path of the project file (so no need to prefix with ..
). When vim is opened
in the folder containing this .vim
directory, it will use those settings for
the language server even for files which might have nothing to do with that
specific project, so this needs to be taken into account. Ultimately what this
means is that the configuration is determined by where you open vim.
Neovim 0.5.0 and later have a built-in LSP client which can be used with the Ada Language Server. In order to use it with minimal effort, follow these steps:
- Install the ada language server and make sure it's in your $PATH.
- Use your favorite Neovim plugin manager to add the default set of LSP configuration files to Neovim.
- Enable the Ada Language Server by adding
:lua require('lspconfig').als.setup{}
to your init.vim.
If you would rather not have the ada language server in your path, you can give the lsp client an absolute path to the ALS executable:
require('lspconfig').als.setup{ cmd = "/path/to/als/executable" }
Configuring the language server's settings can be achieved like this:
require('nvim_lsp').als.setup{
settings = {
ada = {
projectFile = "project.gpr";
scenarioVariables = { ... };
}
}
}
The Ada Language Server's settings are described here. Configuring neovim to use project-specific settings is described neovim's lspconfig wiki
The configuration for each project can be provided using a .dir-locals.el
file defined at the root of each project.
The scenario variables should be declared in your .emacs
or any loaded
Emacs configuration file.
(defgroup project-build nil
"LSP options for Project"
:group 'ada-mode)
(defcustom project-build-type "Debug"
"Controls the type of build of a project.
Default is Debug, other choices are Release and Coverage."
:type '(choice
(const "Debug")
(const "Coverage")
(const "Release"))
:group 'project-build)
Your .dir-locals.el
in the project root should be similar to:
((ada-mode .
((eval . (lsp-register-custom-settings
'(("ada.scenarioVariables.BINUTILS_SRC_DIR" project-binutils-dir)
("ada.scenarioVariables.BUILD_TYPE" project-build-type "Release"))))
(lsp-ada-project-file . "/home/username/project/project.gpr"))
))
The lsp-mode provides built-in support
for the ada_language_server
and defines default customizable configuration
values in the lsp-ada
group that can be edited similarly to
lsp-ada-project-file
in the example above.
Starting with version 4.9
, QtCreator supports a LSP plugin. Follow
the official documentation
to configure the Ada Language Server in this plugin. Make sure to set Startup behavior
to Start Server per Project
, otherwise QtCreator won't provide the project root to
the Ada Language Server. QtCreator doesn't send any configuration request to the language server, so the only
option to enable project support is to have a single .gpr
file in the QtCreator
project folder. For a projectless configuration, you could also place all Ada sources in
the project root folder, this should work as well.
- Maintained by AdaCore.
- Original author @MaximReznik.
- Support for the Visual Studio Code classifier and snippets contributed by @Entomy.
Feel free to dive in! Read the developer's guide.
Don't hesitate to open an issue or submit PRs.