Skip to content
The engine for haskell ide-integration. Not an IDE
Haskell Nix
Branch: master
Clone or download
DanielG tests: Remove 'functional' prefix from log file name
All tests use this log file, not just the func-test suite.
Latest commit 4e3f25d Jul 27, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.azure Avoid unnecessary error creating cache dir Jul 22, 2019
.circleci Drop 8.2.1 from CI too Jun 1, 2019
app Log OS in hie-wrapper Aug 1, 2019
docs Replace every occurrence of build-doc by build-data Jul 22, 2019
hie-plugin-api Preparing 0.12.0.0 July monthly release Aug 3, 2019
install Fix broken stack-build cmd and fix cabal run help msg Aug 18, 2019
licenses Add tests for ExtensibleState Dec 16, 2015
logos Closed #267 : added logos Jan 20, 2018
src/Haskell/Ide/Engine Fix completionItem/resolve sending snippets as plain text Jul 31, 2019
submodules Merge pull request #1299 from alanz/fix-ghc-mod-leak Jun 20, 2019
test tests: Remove 'functional' prefix from log file name Aug 22, 2019
.gitignore move shake.* files into install/ folder Jul 11, 2019
.gitmodules Remove brittany submodule in favour of hackage version Jun 19, 2019
.travis.yml Drop 8.2.1 from CI too Jun 1, 2019
Changelog.md Preparing 0.12.0.0 July monthly release Aug 3, 2019
LICENSE Just some textual improvements Jan 2, 2016
README.md Update vim links in TOC Jul 24, 2019
Setup.hs Breaking ground. Initial source template Oct 23, 2015
appveyor.yml Drop 8.2.1 from CI too Jun 1, 2019
azure-pipelines.yml add install.hs tests on more plattforms Jul 11, 2019
cabal.project Add test-show-details:direct to cabal.project Aug 22, 2019
haskell-ide-engine.cabal added hlint dependency condition based on ghc version. Aug 6, 2019
install.hs rename module Install to HieInstall in hie-install Jul 11, 2019
shell.nix adding nix shell for building and using HIE Nov 6, 2018
stack-8.2.2.yaml Upgrade to haskell-lsp 0.15 Jul 4, 2019
stack-8.4.2.yaml Reverting stack files changes. Aug 7, 2019
stack-8.4.3.yaml Added hlint-2.2.2 back into the stack files. Aug 5, 2019
stack-8.4.4.yaml Added hlint-2.2.2 back into the stack files. Aug 5, 2019
stack-8.6.1.yaml Added hlint-2.2.2 back into the stack files. Aug 5, 2019
stack-8.6.2.yaml Added hlint-2.2.2 back into the stack files. Aug 5, 2019
stack-8.6.3.yaml Added hlint-2.2.2 back into the stack files. Aug 5, 2019
stack-8.6.4.yaml Added hlint-2.2.2 back into the stack files. Aug 5, 2019
stack-8.6.5.yaml Reverting stack files changes. Aug 7, 2019
stack.yaml Monthly resolver bump Aug 1, 2019

README.md

Haskell IDE Engine (HIE)

License BSD3 CircleCI AppVeyor

This project aims to be the universal interface to a growing number of Haskell tools, providing a full-featured and easy to query backend for editors and IDEs that require Haskell-specific functionality.

We are currently focusing on using the Language Server Protocol as the interface via which we talk to clients.

Features

  • Supports plain GHC projects, cabal projects(sandboxed and non sandboxed) and stack projects

  • Fast due to caching of compile info

  • Uses LSP, so should be easy to integrate with a wide selection of editors

  • Diagnostics via hlint and GHC warnings/errors

    Diagnostics

  • Code actions and quick fixes via apply-refact

    Apply Refact

  • Type information and documentation(via haddock) on hover

    Hover

  • Jump to definition

    Find Def

  • List all top level definitions

    Doc Symbols

  • Highlight references in document

    Doc Highlight

  • Completion

    Completion

  • Formatting via brittany

    Formatting

  • Renaming via HaRe

    Renaming

  • Add packages to cabal and hpack package files

    Adding package to hpack Adding import & deps

  • Typo quick fixes

    Quick fixes

  • Add missing imports (via hsimport)

    Missing imports

Installation

Installation with Nix

Follow the instructions at https://github.com/Infinisil/all-hies

Installation on ArchLinux

An haskell-ide-engine package is available on the AUR.

Using Aura:

# aura -A haskell-ide-engine

Installation from source

To install HIE, you need stack version >= 1.7.1.

HIE builds from source code, so there's a couple of extra steps.

Common pre-requirements

  • stack must be in your PATH
  • git must be in your PATH
  • Stack local bin directory must be in your PATH. Get it with stack path --local-bin

Tip: you can quickly check if some command is in your path by running the command. If you receive some meaningful output instead of "command not found"-like message then it means you have the command in PATH.

Linux-specific pre-requirements

On Linux you will need install a couple of extra libraries (for Unicode (ICU) and NCURSES):

Debian/Ubuntu:

sudo apt install libicu-dev libtinfo-dev libgmp-dev

Fedora:

sudo dnf install libicu-devel ncurses-devel

Windows-specific pre-requirements (optional)

In order to avoid problems with long paths on Windows you can do the following:

  1. Edit the group policy: set "Enable Win32 long paths" to "Enabled" (Works only for Windows 10).

  2. Clone the haskell-ide-engine to the root of your logical drive (e.g. to C:\hie)

Download the source code

git clone https://github.com/haskell/haskell-ide-engine --recurse-submodules
cd haskell-ide-engine

Building

Uses the shake build system for predictable builds.

Note, on first invocation of the build script, a GHC is being installed for execution. The GHC used for the install.hs can be adjusted in shake.yaml by using a different resolver.

Available commands can be seen with:

stack ./install.hs help

Remember, this will take time to download a Stackage-LTS and an appropriate GHC. However, afterwards all commands should work as expected.

Install via cabal

The install-script can be invoked via cabal instead of stack with the command

cabal v2-run ./install.hs --project-file install/shake.project <target>

Running the script with cabal on windows seems to have some issues and is currently not fully supported.

Unfortunately, it is still required to have stack installed so that the install-script can locate the local-bin directory (on Linux ~/.local/bin) and copy the hie binaries to hie-x.y.z, which is required for the hie-wrapper to function as expected.

For brevity, only the stack-based commands are presented in the following sections.

Install specific GHC Version

Install Nightly (and hoogle docs):

stack ./install.hs hie-8.6.4
stack ./install.hs build-data

Install LTS (and hoogle docs):

stack ./install.hs hie-8.4.4
stack ./install.hs build-data

The Haskell IDE Engine can also be built with cabal new-build instead of stack build. This has the advantage that you can decide how the GHC versions have been installed. However, this approach does currently not work for windows due to a missing feature upstream. To see what GHC versions are available, the command stack install.hs cabal-ghcs can be used. It will list all GHC versions that are on the path and their respective installation directory. If you think, this list is incomplete, you can try to modify the PATH variable, such that the executables can be found. Note, that the targets cabal-build, cabal-build-data and cabal-build-all depend on the found GHC versions. They install Haskell IDE Engine only for the found GHC versions.

An example output is:

> stack install.hs cabal-ghcs
******************************************************************
Found the following GHC paths:
ghc-8.4.4: /opt/bin/ghc-8.4.4
ghc-8.6.2: /opt/bin/ghc-8.6.2

******************************************************************

If your desired ghc has been found, you use it to install Haskell IDE Engine.

stack install.hs cabal-hie-8.4.4
stack install.hs cabal-build-data

To install HIE for all GHC versions that are present on your system, use:

stack ./install.hs cabal-build-all

In general, targets that use cabal instead of stack are prefixed with cabal-* and are identical to their counterpart, except they do not install a GHC if it is missing but fail.

Multiple versions of HIE (optional)

If you installed multiple versions of HIE then you will need to use a wrapper script. Wrapper script will analyze your project, find suitable version of HIE and launch it. Enable it by editing VS Code settings like that:

"languageServerHaskell.useCustomHieWrapper": true,
"languageServerHaskell.useCustomHieWrapperPath": "hie-wrapper",

Configuration

There are some settings that can be configured via a settings.json file:

{
    "languageServerHaskell": {
        "hlintOn": Boolean,
        "maxNumberOfProblems": Number
        "diagnosticsDebounceDuration" : Number
        "liquidOn"                    : Bool (default False)
        "completionSnippetsOn"        : Bool (default True)
        "formatOnImportOn"            : Bool (default True)
        "formattingProvider"          : String (default "brittany",
                                                alternate "floskell")
    }
}
  • VS Code: These settings will show up in the settings window
  • LanguageClient-neovim: Create this file in $projectdir/.vim/settings.json or set g:LanguageClient_settingsPath

Editor Integration

Note to editor integrators: there is now a hie-wrapper executable, which is installed alongside the hie executable. When this is invoked in the project root directory, it attempts to work out the GHC version used in the project, and then launch the matching hie executable.

All of the editor integrations assume that you have already installed HIE (see above) and that stack put the hie binary in your path (usually ~/.local/bin on linux and macOS).

Using HIE with VS Code

Install from the VSCode marketplace, or manually from the repository vscode-hie-server.

Using VS Code with Nix

.config/nixpkgs/config.nix sample:

with import <nixpkgs> {};

let
  hie = (import (fetchFromGitHub {
                   owner="domenkozar";
                   repo="hie-nix";
                   rev="e3113da";
                   sha256="05rkzjvzywsg66iafm84xgjlkf27yfbagrdcb8sc9fd59hrzyiqk";
                 }) {}).hie84;
in
{
  allowUnfree = true;
  packageOverrides = pkgs: rec {

    vscode = pkgs.vscode.overrideDerivation (old: {
      postFixup = ''
        wrapProgram $out/bin/code --prefix PATH : ${lib.makeBinPath [hie]}
      '';
    });

  };
}

Using HIE with Sublime Text

  • Make sure HIE is installed (see above) and that the directory stack put the hie binary in is in your path
    • (usually ~/.local/bin on unix)
  • Install LSP using Package Control
  • From Sublime Text, press Command+Shift+P and search for Preferences: LSP Settings
  • Paste in these settings. Make sure to change the command path to your hie
{
"clients": {
  "haskell-ide-engine": {
    "command": ["hie"],
    "scopes": ["source.haskell"],
    "syntaxes": ["Packages/Haskell/Haskell.sublime-syntax"],
    "languageId": "haskell",
  },
},
}

Now open a Haskell project with Sublime Text. You should have these features available to you:

  1. Errors are underlined in red
  2. LSP: Show Diagnostics will show a list of hints and errors
  3. LSP: Format Document will prettify the file

Using HIE with Vim or Neovim

As above, make sure HIE is installed. These instructions are for using the LanguageClient-neovim client.

vim-plug

If you use vim-plug, then you can do this by e.g., including the following line in the Plug section of your init.vim or ~/.vimrc:

Plug 'autozimu/LanguageClient-neovim', {
    \ 'branch': 'next',
    \ 'do': './install.sh'
    \ }

and issuing a :PlugInstall command within Neovim or Vim.

Clone the LanguageClient-neovim repo

As an alternative to using vim-plug shown above, clone LanguageClient-neovim into ~/.vim/pack/XXX/start/, where XXX is just a name for your "plugin suite".

Sample ~/.vimrc

set rtp+=~/.vim/pack/XXX/start/LanguageClient-neovim
let g:LanguageClient_serverCommands = { 'haskell': ['hie-wrapper'] }

You'll probably want to add some mappings for common commands:

nnoremap <F5> :call LanguageClient_contextMenu()<CR>
map <Leader>lk :call LanguageClient#textDocument_hover()<CR>
map <Leader>lg :call LanguageClient#textDocument_definition()<CR>
map <Leader>lr :call LanguageClient#textDocument_rename()<CR>
map <Leader>lf :call LanguageClient#textDocument_formatting()<CR>
map <Leader>lb :call LanguageClient#textDocument_references()<CR>
map <Leader>la :call LanguageClient#textDocument_codeAction()<CR>
map <Leader>ls :call LanguageClient#textDocument_documentSymbol()<CR>

Use Ctrl+xCtrl+o (<C-x><C-o>) to open up the auto-complete menu, or for asynchronous auto-completion, follow the setup instructions on LanguageClient.

If you'd like diagnostics to be highlighted, add a highlight group for ALEError/ALEWarning/ALEInfo, or customize g:LanguageClient_diagnosticsDisplay:

hi link ALEError Error
hi Warning term=underline cterm=underline ctermfg=Yellow gui=undercurl guisp=Gold
hi link ALEWarning Warning
hi link ALEInfo SpellCap

If you're finding that the server isn't starting at the correct project root, it may also be helpful to also specify root markers:

let g:LanguageClient_rootMarkers = ['*.cabal', 'stack.yaml']

Using HIE with Atom

Make sure HIE is installed, then install the two Atom packages atom-ide-ui and ide-haskell-hie,

$ apm install language-haskell atom-ide-ui ide-haskell-hie

Using HIE with Emacs

Install HIE along with the following emacs packages:

lsp-mode lsp-ui lsp-haskell

Make sure to follow the instructions in the README of each of these packages.

Using HIE with Spacemacs

Install HIE, and then add the following to your .spacemacs config,

(defun dotspacemacs/layers ()
  "..."
  (setq-default
   ;; ...
   dotspacemacs-configuration-layers
   '(
     lsp
     (haskell :variables ;; Or optionally just haskell without the variables.
              haskell-completion-backend 'ghci
              haskell-process-type 'stack-ghci)
     )
   dotspacemacs-additional-packages '(
      (lsp-haskell :location (recipe :fetcher github :repo "emacs-lsp/lsp-haskell"))
      )
    ;; ...
    ))

and then activate lsp-haskell in your user-config section,

(defun dotspacemacs/user-config ()
  "..."
  (setq lsp-haskell-process-path-hie "hie-wrapper")
  (require 'lsp-haskell)
  (add-hook 'haskell-mode-hook #'lsp)
  )

Now you should be able to use HIE in Spacemacs. I still recommend checking out lsp-ui and lsp-mode.

Using HIE with Spacemacs on Nix Based Projects

If you use HIE with spacemacs on nix-built haskell projects, you may want to try out this spacemacs layer. It has installation instructions which includes a nix expression to install everything that hie needs in your environment. It wraps the hie binary calls to use nix-sandbox to find the closest ancestor directory that has nixfiles.

It is still pretty new and may change drastically as the author understands the lsp, lsp-ui, lsp-haskell, hie stack a bit better. PRs and feedback are very welcome on the layer's repo if you find it useful and/or lacking in some way.

Using HIE with Oni

Oni (a Neovim GUI) added built-in support for HIE, using stack, in #1918. If you need to change the configuration for HIE, you can overwrite the following settings in your ~/.config/oni/config.tsx file (accessible via the command palette and Configuration: Edit User Config),

export const configuration = {
  "language.haskell.languageServer.command": "stack",
  "language.haskell.languageServer.arguments": ["exec", "--", "hie"],
  "language.haskell.languageServer.rootFiles": [".git"],
  "language.haskell.languageServer.configuration": {},
}

Docs on hover/completion

HIE supports fetching docs from haddock on hover. It will fallback on using a hoogle db(generally located in ~/.hoogle on linux) if no haddock documentation is found.

To generate haddock documentation for stack projects:

$ cd your-project-directory
$ stack haddock --keep-going

To enable documentation generation for cabal projects, add the following to your ~/.cabal/config

documentation: True

To generate a hoogle database that hie can use

$ cd haskell-ide-engine
$ stack --stack-yaml=<stack.yaml you used to build hie> exec hoogle generate

Or you can set the environment variable HIE_HOOGLE_DATABASE to specify a specific database.

Contributing

Planned Features

  • Multiproject support
  • Project wide references
  • Cross project find definition
  • New-build support
  • HaRe refactorings
  • More code actions
  • Cross project/dependency Find Definition
  • Case splitting, type insertion etc.

This project is not started from scratch:

  1. See why we should supersede previous tools
  2. Check the list of existing tools and functionality
  3. See more other tools and IDEs for inspiration

It's time to join the project!

❤️ Haskell tooling dream is near, we need your help! ❤️

Documentation

All the documentation is in the docs folder at the root of this project.

Architecture

Have a look at

Troubleshooting

Emacs

Parse errors, file state going out of sync

With the lsp-mode client for Emacs, it seems that the document can very easily get out of sync between, which leads to parse errors being displayed. To fix this, enable full document synchronization with

(setq lsp-document-sync-method 'full)

emacs-direnv loads environment too late

emacs-direnv sometimes loads the environment too late, meaning lsp-mode won't be able to find correct GHC/cabal versions. To fix this, add a direnv update hook after adding the lsp hook for haskell-mode (meaning the direnv hook is executed first, because hooks are LIFO):

(add-hook 'haskell-mode-hook 'lsp)
(add-hook 'haskell-mode-hook 'direnv-update-environment)

DYLD on macOS

If you hit a problem that looks like can't load .so/.DLL for: libiconv.dylib (dlopen(libiconv.dylib, 5): image not found), it means that libraries cannot be found in the library path. We can hint where to look for them and append more paths to DYLD_LIBRARY_PATH.

export DYLD_LIBRARY_PATH="$DYLD_LIBRARY_PATH:/usr/lib:/usr/local/lib"

On practice /usr/local/lib is full of dylibs linked by brew. After you amend DYLD_LIBRARY_PATH, some of the previously compiled application might not work and yell about incorrect linking, for example, dyld: Symbol not found: __cg_jpeg_resync_to_restart. You may need to look up where it comes from and remove clashing links, in this case it were clashing images libs:

$ brew unlink libjpeg
$ brew unlink libtiff
$ brew unlink libpng

Recompile.

macOS: Got error while installing GHC 8.6.1 or 8.6.2 - dyld: Library not loaded: /usr/local/opt/gmp/lib/libgmp.10.dylib

These builds have a dependency on homebrew's gmp library. Install with brew: brew install gmp. Should be fixed in GHC 8.6.3.

macOS: Got error while processing diagnostics: unable to load package integer-gmp-1.0.2.0

Rename the file at ~/.stack/programs/x86_64-osx/ghc-8.4.3/lib/ghc-8.4.3/integer-gmp-1.0.2.0/HSinteger-gmp-1.0.2.0.o to a temporary name. Should be fixed in GHC 8.8.1.

cannot satisfy -package-id <package>

Is <package> base-x?

Make sure that you are running the correct version of hie for your version of ghc, or check out hie-wrapper.

Is there a hash (#) after <package>?

Delete any .ghc.environment* files in your project root and try again. (At the time of writing, cabal new-style projects are not supported with ghc-mod)

Otherwise

Try running cabal update.

Nix: cabal-helper, No such file or directory

An error on stderr like

cabal-helper-wrapper: /home/<...>/.cache/cabal-helper/cabal-helper<...>: createProcess: runInteractiveProcess:
  exec: does not exist (No such file or directory)

can happen because cabal-helper compiles and runs above executable at runtime without using nix-build, which means a Nix garbage collection can delete the paths it depends on. Delete ~/.cache/cabal-helper and restart HIE to fix this.

Liquid Haskell

Liquid Haskell requires an SMT solver on the path. We do not take care of installing one, thus, Liquid Haskell will not run until one is installed. The recommended SMT solver is z3. To run the tests, it is also required to have an SMT solver on the path, otherwise the tests will fail for Liquid Haskell.

You can’t perform that action at this time.