branch: elpa/haskell-tng-mode commit cce466c4ec314ba4f18cd9256ed68f22cc49fa3a Author: Tseen She <ts33n....@gmail.com> Commit: Tseen She <ts33n....@gmail.com>
hsinspect now has a compiler plugin --- README.md | 14 ++---- cabal-ghcflags.sh | 113 ----------------------------------------------- haskell-tng-hsinspect.el | 27 +---------- 3 files changed, 6 insertions(+), 148 deletions(-) diff --git a/README.md b/README.md index 77ba24f..d532977 100644 --- a/README.md +++ b/README.md @@ -68,19 +68,15 @@ You must install `hsinspect` for every version of `ghc` that you plan to use, e. ``` rm -f ~/.cabal/bin/hsinspect for V in 8.4.4 8.6.5 ; do - cabal v2-install hsinspect -w ghc-$V -O2 && + cabal v2-install hsinspect-0.0.4 -w ghc-$V -O2 && mv -f ~/.cabal/bin/hsinspect ~/.cabal/bin/hsinspect-ghc-$V done ``` -<!-- -for V in 8.4.4 8.6.5 ; do - cabal v2-install exe:hsinspect -w ghc-$V -O2 && - mv -f ~/.cabal/bin/hsinspect ~/.cabal/bin/hsinspect-ghc-$V -done ---> +And add the compiler plugin to every project you plan to inspect: -To use `hsinspect` commands, generate `.ghc.flags` / `.ghc.version` files by running `M-x haskell-tng-hsinspect` for a project. This is only needed when the dependencies change. +1. add a dependency on `hsinspect` +2. add `-fplugin HsInspect.Plugin` to `ghc-options` `hsinspect` only works when the dependencies of the current file have been compiled (the current file doesn't need to be compilable). @@ -88,8 +84,6 @@ The `haskell-tng-extra-company` package will automatically complete symbols that To find out which module a symbol belongs to, use `M-x haskell-tng-fqn-at-point`. -The are some limitations to this tool in addition to known bugs. See [the gory details](https://gitlab.com/tseenshe/hsinspect) for more information. Hopefully there will be no need for `M-x haskell-tng-hsinspect` and the `.ghc.*` files in a future release. - ## Contrib Integrations are provided for common libraries and external applications. diff --git a/cabal-ghcflags.sh b/cabal-ghcflags.sh deleted file mode 100755 index 2a9c5f9..0000000 --- a/cabal-ghcflags.sh +++ /dev/null @@ -1,113 +0,0 @@ -#!/usr/bin/env bash - -# Dump the ghc flags that cabal-install uses to launch a repl session for -# all components into files named `.ghc.flags.component'. -# -# This is a partial workaround to https://github.com/haskell/cabal/issues/6203 -# -# Note that this flushes the build plan cache and only supports the default -# build flags. If users wish to include test phases they must add tests: True -# to their cabal.project.local - -set -e - -TMP="/tmp/cabal-ghcflags-$USER/$PWD" -mkdir -p "$TMP" 2> /dev/null || true - -# to ensure the json plan is in place -echo "Resolving dependencies" -# cabal v2-build -v0 :all --dry -# best just ensure deps are compiled otherwise the repl compiles them -cabal v2-build :all --only-dependencies - -if [ ! -f dist-newstyle/cache/plan.json ] ; then - echo "dist-newstyle/cache/plan.json not found" - exit 1 -fi - -# seems to be a bug in cabal... -mkdir dist-newstyle/tmp 2> /dev/null || true - -cabal v2-exec -v0 ghc -- --numeric-version > .ghc.version -GHC=$(cabal v2-exec -v2 ghc -- --numeric-version | tail -2 | head -1 | sed 's/ .*//') - -# ghc is called multiple times during the v2-repl startup. -# The only call that we're interested in is this one. -cat <<EOF > "$TMP/ghc" -#!/usr/bin/env bash -if [ "\$1" == "--interactive" ]; then - echo -n "\${@:2}" >> "\$OUTPUT" -else - exec "$GHC" "\$@" -fi -EOF -chmod 755 "$TMP/ghc" - -GHC_PKG=$(echo "$GHC" | rev | sed 's/chg/gkp-chg/' | rev) -cat <<EOF > "$TMP/ghc-pkg" -#!/usr/bin/env bash -exec "$GHC_PKG" "\$@" -EOF -chmod 755 "$TMP/ghc-pkg" - -HSC2HS=$(echo "$GHC" | rev | sed 's/chg/sh2csh/' | rev) -cat <<EOF > "$TMP/hsc2hs" -#!/usr/bin/env bash -exec "$HSC2HS" "\$@" -EOF -chmod 755 "$TMP/hsc2hs" - -create_ghcflags() { - LINE="$1" - - NAME=$(echo "$LINE" | jq -r '.[0]') - PART=$(echo "$LINE" | jq -r '.[1]') - ROOT=$(echo "$LINE" | jq -r '.[2]') - ID=$(echo "$LINE" | jq -r '.[3]') - - if [ "$PART" == "lib" ] ; then - COMPONENT="lib:$NAME" - elif [ "$PART" == "setup" ] || [ "$PART" == "test:doctests" ] ; then - echo " $NAME:$PART SKIPPED" - return 0; - else - COMPONENT="$PART" - fi - - echo " $NAME:$COMPONENT $ID" - - export OUTPUT="$TMP/out.$NAME:$COMPONENT" - - rm "$OUTPUT" 2> /dev/null || true - cabal v2-repl -v0 -w "$TMP/ghc" "$NAME:$COMPONENT" - - # TODO also need to provide the PATH, since it might include commands that - # are referred to from compiler plugins (e.g. tasty-discover). - - # extract all the source directories that use these flags - for D in $(cat "$OUTPUT" | tr ' ' '\n' | grep '^-i' | sed 's/^-i//' | sed '/^$/d') ; do - if [[ "$D" != /* ]] ; then - D="$ROOT/$D" - if [ -d "$D" ] ; then - # echo " $D/.ghc.flags" - cat "$OUTPUT" > "$D/.ghc.flags" - fi - fi - done -} - -echo "Inspecting build plan" -for LINE in $(jq -c '(."install-plan"[] | select(."pkg-src".type == "local") | select(."component-name" != null) | [ ."pkg-name", ."component-name", ."pkg-src".path, .id ] )' dist-newstyle/cache/plan.json) ; do - # NOTE: could be done in parallel, but I haven't measured it being faster - create_ghcflags "$LINE" -done -# and again for custom Setup.hs builds... -for LINE in $(jq -c '(."install-plan"[] | select(."pkg-src".type == "local") | select(."components" != null) | . as $p | .["components"] | keys[] | [ $p."pkg-name" , . , $p."pkg-src".path , $p.id] )' dist-newstyle/cache/plan.json) ; do - create_ghcflags "$LINE" -done - -wait - -if [ -d "$TMP" ] ; then - rm -rf "$TMP" -fi diff --git a/haskell-tng-hsinspect.el b/haskell-tng-hsinspect.el index 5e12793..b2602e2 100644 --- a/haskell-tng-hsinspect.el +++ b/haskell-tng-hsinspect.el @@ -31,29 +31,6 @@ name of the symbol at point in the minibuffer." (error "hsinspect is not available") (message "<not imported>")))) -(defvar haskell-tng-hsinspect - ;; NOTE in order for this hack to work, the user needs to have setup a - ;; cabal.project.local that contains their default options (optimisations, - ;; enabling tests, etc) otherwise it will (at best) invalidate the cache and - ;; (at worst) not find local projects. - (expand-file-name - "cabal-ghcflags.sh" - (when load-file-name - (file-name-directory load-file-name)))) -;;;###autoload -(defun haskell-tng-hsinspect () - "Required (for now) to initialise a project for use with `hsinspect'. -Only needs to be performed once every time the dependencies -change." - (interactive) - (when-let ((default-directory - (or - (haskell-tng--util-locate-dominating-file - haskell-tng--compile-dominating-project) - (haskell-tng--util-locate-dominating-file - haskell-tng--compile-dominating-package)))) - (async-shell-command haskell-tng-hsinspect))) - (defun haskell-tng--hsinspect-ghcflags () ;; https://github.com/haskell/cabal/issues/6203 "Obtain the ghc flags for the current buffer" @@ -62,7 +39,7 @@ change." (insert-file-contents (expand-file-name ".ghc.flags")) (split-string (buffer-substring-no-properties (point-min) (point-max)))) - (user-error "could not find `.ghc.flags'. Run `M-x haskell-tng-hsinspect'"))) + (user-error "could not find `.ghc.flags'."))) (defun haskell-tng--hsinspect-ghc () "Obtain the version of hsinspect that matches the project's compiler." @@ -72,7 +49,7 @@ change." (concat "hsinspect-ghc-" (string-trim (buffer-substring-no-properties (point-min) (point-max))))) - (user-error "could not find `.ghc.version'. Run `M-x haskell-tng-hsinspect'"))) + (user-error "could not find `.ghc.version'."))) ;; TODO invalidate cache when imports section has changed ;; TODO is there a way to tell Emacs not to render this in `C-h v'?