diff --git a/.cirrus.yml b/.cirrus.yml index 1431f678e3..4f0b3fad09 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -21,9 +21,6 @@ build_task: GITHUB_WORKSPACE: ${CIRRUS_WORKING_DIR} CABAL_CACHE_NONFATAL: "yes" matrix: - - name: build-ghc-8.10.7 - env: - GHC_VERSION: 8.10.7 - name: build-ghc-9.0.2 env: GHC_VERSION: 9.0.2 @@ -46,7 +43,6 @@ build_task: bindist_task: name: bindist depends_on: - - build-ghc-8.10.7 - build-ghc-9.0.2 - build-ghc-9.2.5 - build-ghc-9.2.7 @@ -64,10 +60,6 @@ bindist_task: - tzsetup Etc/GMT - adjkerntz -a - - curl -o binaries-8.10.7.tar.xz -L https://api.cirrus-ci.com/v1/artifact/build/${CIRRUS_BUILD_ID}/build-ghc-8.10.7/binaries/out.tar.xz - - tar xvf binaries-8.10.7.tar.xz - - rm -f binaries-8.10.7.tar.xz - - curl -o binaries-9.0.2.tar.xz -L https://api.cirrus-ci.com/v1/artifact/build/${CIRRUS_BUILD_ID}/build-ghc-9.0.2/binaries/out.tar.xz - tar xvf binaries-9.0.2.tar.xz - rm -f binaries-9.0.2.tar.xz diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index 4bf2bedd27..66ceb25d17 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -56,7 +56,7 @@ jobs: # change of the strategy may require changing the bootstrapping/run code steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: # By default, the `pull_request` event has a `GITHUB_SHA` env variable diff --git a/.github/workflows/caching.yml b/.github/workflows/caching.yml index 76bf204d82..802bf6b267 100644 --- a/.github/workflows/caching.yml +++ b/.github/workflows/caching.yml @@ -58,7 +58,7 @@ jobs: should_skip: ${{ steps.skip_check.outputs.should_skip }} steps: # Need the repo checked out in order to read the file - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - id: ghcs run: echo "ghcs=$(cat ./.github/workflows/supported-ghc-versions.json)" >> $GITHUB_OUTPUT - id: skip_check @@ -91,7 +91,7 @@ jobs: - macOS-latest - windows-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: ./.github/actions/setup-build with: diff --git a/.github/workflows/flags.yml b/.github/workflows/flags.yml index f00af915f1..cfc3ef640f 100644 --- a/.github/workflows/flags.yml +++ b/.github/workflows/flags.yml @@ -22,7 +22,7 @@ jobs: should_skip: ${{ steps.skip_check.outputs.should_skip }} steps: # Need the repo checked out in order to read the file - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - id: ghcs run: echo "ghcs=$(cat ./.github/workflows/supported-ghc-versions.json)" >> $GITHUB_OUTPUT - id: skip_check @@ -54,7 +54,7 @@ jobs: - ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: # By default, the `pull_request` event has a `GITHUB_SHA` env variable diff --git a/.github/workflows/hlint.yml b/.github/workflows/hlint.yml index 62d8742039..109dbe3cb5 100644 --- a/.github/workflows/hlint.yml +++ b/.github/workflows/hlint.yml @@ -10,7 +10,7 @@ jobs: name: "Hlint check run" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: 'Installing' uses: rwe/actions-hlint-setup@v1 diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index 55edf99dc7..30b2ade3a8 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -53,9 +53,9 @@ jobs: os: [ubuntu-latest, macOS-latest] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v22 + - uses: cachix/install-nix-action@v23 with: extra_nix_config: | experimental-features = nix-command flakes @@ -85,9 +85,9 @@ jobs: os: [ubuntu-latest, macOS-latest] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v22 + - uses: cachix/install-nix-action@v23 with: extra_nix_config: | experimental-features = nix-command flakes diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 4a3ab9ff5a..6a054d9329 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -12,7 +12,7 @@ jobs: git-diff: ${{ steps.git-diff.outputs.diff }} steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Find changed files uses: technote-space/get-diff-action@v6.1.2 id: git-diff @@ -23,7 +23,7 @@ jobs: runs-on: ubuntu-latest needs: file-diff steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: ./.github/actions/setup-build with: # select a stable GHC version diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 5e791c0902..71cbc7ee6d 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -30,7 +30,7 @@ jobs: strategy: fail-fast: false matrix: - ghc: ["9.6.2", "9.4.7", "9.4.6", "9.4.5", "9.2.8", "9.0.2", "8.10.7"] + ghc: ["9.6.2", "9.4.7", "9.2.8", "9.0.2"] platform: [ { image: "debian:9" , installCmd: "sed -i s/deb.debian.org/archive.debian.org/g /etc/apt/sources.list && sed -i 's|security.debian.org|archive.debian.org/|g' /etc/apt/sources.list && sed -i /-updates/d /etc/apt/sources.list && apt-get update && apt-get install -y" , toolRequirements: "libnuma-dev zlib1g-dev libgmp-dev libgmp10 libssl-dev liblzma-dev libbz2-dev git wget lsb-release software-properties-common gnupg2 apt-transport-https gcc autoconf automake build-essential curl ghc gzip libffi-dev libncurses-dev libncurses5 libtinfo5 patchelf" @@ -118,15 +118,6 @@ jobs: # Perhaps we can migrate *all* unknown linux builds to a uniform # image. include: - - ghc: 8.10.7 - platform: - { image: "rockylinux:8" - , installCmd: "yum -y install epel-release && yum install -y --allowerasing" - , toolRequirements: "autoconf automake binutils bzip2 coreutils curl elfutils-devel elfutils-libs findutils gcc gcc-c++ git gmp gmp-devel jq lbzip2 make ncurses ncurses-compat-libs ncurses-devel openssh-clients patch perl pxz python3 sqlite sudo wget which xz zlib-devel patchelf" - , DISTRO: "Unknown" - , ARTIFACT: "x86_64-linux-unknown" - , ADD_CABAL_ARGS: "--enable-split-sections" - } - ghc: 9.0.2 platform: { image: "rockylinux:8" @@ -145,24 +136,6 @@ jobs: , ARTIFACT: "x86_64-linux-unknown" , ADD_CABAL_ARGS: "--enable-split-sections" } - - ghc: 9.4.5 - platform: - { image: "fedora:27" - , installCmd: "dnf install -y" - , toolRequirements: "autoconf automake binutils bzip2 coreutils curl elfutils-devel elfutils-libs findutils gcc gcc-c++ git gmp gmp-devel jq lbzip2 make ncurses ncurses-compat-libs ncurses-devel openssh-clients patch perl pxz python3 sqlite sudo wget which xz zlib-devel patchelf" - , DISTRO: "Unknown" - , ARTIFACT: "x86_64-linux-unknown" - , ADD_CABAL_ARGS: "--enable-split-sections" - } - - ghc: 9.4.6 - platform: - { image: "fedora:27" - , installCmd: "dnf install -y" - , toolRequirements: "autoconf automake binutils bzip2 coreutils curl elfutils-devel elfutils-libs findutils gcc gcc-c++ git gmp gmp-devel jq lbzip2 make ncurses ncurses-compat-libs ncurses-devel openssh-clients patch perl pxz python3 sqlite sudo wget which xz zlib-devel patchelf" - , DISTRO: "Unknown" - , ARTIFACT: "x86_64-linux-unknown" - , ADD_CABAL_ARGS: "--enable-split-sections" - } - ghc: 9.4.7 platform: { image: "fedora:27" @@ -195,7 +168,7 @@ jobs: echo "ID=linux" >> /etc/os-release echo "PRETTY_NAME=Linux" >> /etc/os-release - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Run build run: | @@ -240,7 +213,7 @@ jobs: strategy: fail-fast: true matrix: - ghc: ["9.6.2", "9.4.7", "9.4.6", "9.4.5", "9.2.8", "9.0.2", "8.10.7"] + ghc: ["9.6.2", "9.4.7", "9.2.8", "9.0.2"] steps: - uses: docker://arm64v8/ubuntu:focal name: Cleanup (aarch64 linux) @@ -253,7 +226,7 @@ jobs: shell: bash - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: docker://hasufell/arm64v8-ubuntu-haskell:focal name: Run build (aarch64 linux) @@ -300,10 +273,10 @@ jobs: strategy: fail-fast: false matrix: - ghc: ["9.6.2", "9.4.7", "9.4.6", "9.4.5", "9.2.8", "9.0.2", "8.10.7"] + ghc: ["9.6.2", "9.4.7", "9.2.8", "9.0.2"] steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Run build run: | @@ -345,26 +318,15 @@ jobs: strategy: fail-fast: false matrix: - ghc: ["9.6.2", "9.4.7", "9.4.6", "9.4.5", "9.2.8", "8.10.7"] + ghc: ["9.6.2", "9.4.7", "9.2.8"] steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Run build run: | - if test "${GHC_VERSION}" = "8.10.7"; then - bash .github/scripts/brew.sh git coreutils llvm@11 autoconf automake tree - export PATH="$HOME/.brew/bin:$HOME/.brew/sbin:$HOME/.brew/opt/llvm@11/bin:$PATH" - export CC="$HOME/.brew/opt/llvm@11/bin/clang" - export CXX="$HOME/.brew/opt/llvm@11/bin/clang++" - export AR="$HOME/.brew/opt/llvm@11/bin/llvm-ar" - export LLC="$HOME/.brew/opt/llvm@11/bin/llc" - export OPT="$HOME/.brew/opt/llvm@11/bin/opt" - export RANLIB="$HOME/.brew/opt/llvm@11/bin/llvm-ranlib" - else - bash .github/scripts/brew.sh git coreutils autoconf automake tree - export PATH="$HOME/.brew/bin:$HOME/.brew/sbin:$PATH" - fi + bash .github/scripts/brew.sh git coreutils autoconf automake tree + export PATH="$HOME/.brew/bin:$HOME/.brew/sbin:$PATH" export LD=ld bash .github/scripts/build.sh tar cf out-${ARTIFACT}-${GHC_VERSION}.tar out/ store/ @@ -401,7 +363,7 @@ jobs: strategy: fail-fast: false matrix: - ghc: ["9.6.2", "9.4.7", "9.4.6", "9.4.5", "9.2.8", "9.0.2", "8.10.7"] + ghc: ["9.6.2", "9.4.7", "9.2.8", "9.0.2"] steps: - name: install windows deps shell: pwsh @@ -412,7 +374,7 @@ jobs: taskkill /F /FI "MODULES eq msys-2.0.dll" - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Run build (windows) run: | @@ -521,7 +483,7 @@ jobs: echo "ID=linux" >> /etc/os-release echo "PRETTY_NAME=Linux" >> /etc/os-release - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/download-artifact@v3 with: @@ -573,7 +535,7 @@ jobs: git config --global --get-all safe.directory | grep '^\*$' || git config --global --add safe.directory "*" shell: bash - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/download-artifact@v3 with: @@ -612,7 +574,7 @@ jobs: ARCH: 64 ARTIFACT: "x86_64-apple-darwin" steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/download-artifact@v3 with: @@ -650,7 +612,7 @@ jobs: ARCH: ARM64 ARTIFACT: "aarch64-apple-darwin" steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/download-artifact@v3 with: @@ -702,7 +664,7 @@ jobs: C:\msys64\usr\bin\bash -lc "pacman --disable-download-timeout --noconfirm -S unzip zip git" taskkill /F /FI "MODULES eq msys-2.0.dll" - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/download-artifact@v3 with: @@ -816,7 +778,7 @@ jobs: echo "ID=linux" >> /etc/os-release echo "PRETTY_NAME=Linux" >> /etc/os-release - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/download-artifact@v3 with: @@ -852,7 +814,7 @@ jobs: shell: bash - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: actions/download-artifact@v3 with: @@ -876,7 +838,7 @@ jobs: DISTRO: na steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: actions/download-artifact@v3 with: @@ -901,7 +863,7 @@ jobs: HOMEBREW_CHANGE_ARCH_TO_ARM: 1 steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: actions/download-artifact@v3 with: @@ -940,7 +902,7 @@ jobs: taskkill /F /FI "MODULES eq msys-2.0.dll" - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: actions/download-artifact@v3 with: @@ -961,7 +923,7 @@ jobs: if: startsWith(github.ref, 'refs/tags/') steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: actions/download-artifact@v3 with: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ed63e13dfd..d5fb80d5c8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -23,7 +23,7 @@ jobs: ghcs: ${{ steps.ghcs.outputs.ghcs }} steps: # Need the repo checked out in order to read the file - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - id: ghcs run: echo "ghcs=$(cat ./.github/workflows/supported-ghc-versions.json)" >> $GITHUB_OUTPUT - id: skip_check @@ -83,7 +83,7 @@ jobs: test: true steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: ./.github/actions/setup-build with: diff --git a/RELEASING.md b/RELEASING.md index c1039dc668..bf740d716d 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -34,12 +34,11 @@ - this creates a draft release - `git push ` - [ ] run `sh scripts/release/download-gh-artifacts.sh ` - - downloads artifacts to `gh-release-artifacts//` + - downloads artifacts to `gh-release-artifacts/haskell-language-server-/` - also downloads FreeBSD bindist from circle CI - adds signatures -- [ ] upload artifacts to downloads.haskell.org manually from `gh-release-artifacts//` +- [ ] upload artifacts to downloads.haskell.org from `gh-release-artifacts/haskell-language-server-/` - You require sftp access, contact wz1000, bgamari or chreekat - - For uploading, rename `gh-release-artifacts/` to `gh-release-artifacts/haskell-language-server-` - `cd gh-release-artifacts/haskell-language-server-` - `SIGNING_KEY=... ../../release/upload.sh upload` - Your SIGNING_KEY can be obtained with `gpg --list-secret-keys --keyid-format=long` @@ -57,5 +56,9 @@ - [ ] upload hackage packages - requires credentials - [ ] update https://haskell-language-server.readthedocs.io/en/latest/support/ghc-version-support.html#current-ghc-version-support-status +- [ ] Supported tools table needs to be updated: + - https://www.haskell.org/ghcup/install/#supported-platforms + - https://github.com/haskell/ghcup-hs/blob/master/docs/install.md#supported-platforms + - https://github.com/haskell/ghcup-metadata/blob/44c6e2b5d0fcae15abeffff03e87544edf76dd7a/ghcup-gen/Main.hs#L67 - [ ] post release on discourse and reddit - [ ] merge release PR to master or forward port relevant changes diff --git a/bench/config.yaml b/bench/config.yaml index 04106b32b9..146c3876bf 100644 --- a/bench/config.yaml +++ b/bench/config.yaml @@ -126,6 +126,13 @@ versions: - HEAD # A list of plugin configurations to analyze +# WARNING: Currently bench versions later than e4234a3a5e347db249fccefb8e3fb36f89e8eafb +# will be unable to send plugin configurations to earlier HLS versions. This causes +# all plugins in those versions to always be enabled. +# In addition bench proactively disables all plugins it knows about besides the +# ones in the following list. However because it can only disable plugins it +# knows about, any plugins that are in old versions but were removed from HLS +# before the current bench will not be disabled. configurations: # A configuration contains one or more plugins: # - ConfigurationName: diff --git a/cabal.project b/cabal.project index 0c6bfba565..ce0bd46ef6 100644 --- a/cabal.project +++ b/cabal.project @@ -52,7 +52,7 @@ package * write-ghc-environment-files: never -index-state: 2023-08-25T00:00:00Z +index-state: 2023-09-08T00:00:00Z constraints: -- For GHC 9.4, older versions of entropy fail to build on Windows diff --git a/docs/installation.md b/docs/installation.md index 375dceb782..162903872a 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -154,7 +154,7 @@ Homebrew users can install `haskell-language-server` using the following command brew install haskell-language-server ``` -This formula contains HLS binaries compiled with GHC versions available via Homebrew; at the moment those are: 8.10.7. +This formula contains HLS binaries compiled with GHC versions available via Homebrew. You need to provide your own GHC/Cabal/Stack as required by your project, possibly via Homebrew. diff --git a/docs/support/ghc-version-support.md b/docs/support/ghc-version-support.md index a5cd049728..b6aaa00fba 100644 --- a/docs/support/ghc-version-support.md +++ b/docs/support/ghc-version-support.md @@ -19,6 +19,7 @@ Support status (see the support policy below for more details): |--------------|--------------------------------------------------------------------------------------|-----------------------------------------------------------------------------| | 9.6.2 | [latest](https://github.com/haskell/haskell-language-server/releases/latest) | basic support | | 9.6.1 | [2.0.0.0](https://github.com/haskell/haskell-language-server/releases/tag/2.0.0.0) | basic support | +| 9.4.7 | [latest](https://github.com/haskell/haskell-language-server/releases/latest) | full support | | 9.4.6 | [latest](https://github.com/haskell/haskell-language-server/releases/latest) | full support | | 9.4.5 | [latest](https://github.com/haskell/haskell-language-server/releases/latest) | full support | | 9.4.4 | [1.10.0.0](https://github.com/haskell/haskell-language-server/releases/tag/1.10.0.0) | deprecated | diff --git a/flake.lock b/flake.lock index c3d8f1b878..e64c8ea36e 100644 --- a/flake.lock +++ b/flake.lock @@ -134,37 +134,37 @@ "lsp": { "flake": false, "locked": { - "narHash": "sha256-Uq9OLBZFJvg8BM383++3o3s54Trho6gaYor+6EELV38=", + "narHash": "sha256-HcEfdYUrCHufEa+10M2wESjnK41xM/msd+t6r6JwQO0=", "type": "tarball", - "url": "https://hackage.haskell.org/package/lsp-2.1.0.0/lsp-2.1.0.0.tar.gz" + "url": "https://hackage.haskell.org/package/lsp-2.2.0.0/lsp-2.2.0.0.tar.gz" }, "original": { "type": "tarball", - "url": "https://hackage.haskell.org/package/lsp-2.1.0.0/lsp-2.1.0.0.tar.gz" + "url": "https://hackage.haskell.org/package/lsp-2.2.0.0/lsp-2.2.0.0.tar.gz" } }, "lsp-test": { "flake": false, "locked": { - "narHash": "sha256-48gVUVsDPR+RYl+K0ZN15N9EIdTQP8ma5nGPvzE6uoQ=", + "narHash": "sha256-E1D3X2+I9ZTZLpHDEDTXexQFYpyG5byOFRIvRTeBsn8=", "type": "tarball", - "url": "https://hackage.haskell.org/package/lsp-test-0.15.0.1/lsp-test-0.15.0.1.tar.gz" + "url": "https://hackage.haskell.org/package/lsp-test-0.16.0.0/lsp-test-0.16.0.0.tar.gz" }, "original": { "type": "tarball", - "url": "https://hackage.haskell.org/package/lsp-test-0.15.0.1/lsp-test-0.15.0.1.tar.gz" + "url": "https://hackage.haskell.org/package/lsp-test-0.16.0.0/lsp-test-0.16.0.0.tar.gz" } }, "lsp-types": { "flake": false, "locked": { - "narHash": "sha256-irO9uob1L10l1BoRC8F2lABqAzR5Z7mydyCZagMZZ2M=", + "narHash": "sha256-Oa5HuKdsdTSQUKtuSt06zVAq19Qxq5IJZObrnPwlB6s=", "type": "tarball", - "url": "https://hackage.haskell.org/package/lsp-types-2.0.1.0/lsp-types-2.0.1.0.tar.gz" + "url": "https://hackage.haskell.org/package/lsp-types-2.0.2.0/lsp-types-2.0.2.0.tar.gz" }, "original": { "type": "tarball", - "url": "https://hackage.haskell.org/package/lsp-types-2.0.1.0/lsp-types-2.0.1.0.tar.gz" + "url": "https://hackage.haskell.org/package/lsp-types-2.0.2.0/lsp-types-2.0.2.0.tar.gz" } }, "nixpkgs": { diff --git a/flake.nix b/flake.nix index 5556a81454..b68f43c2d1 100644 --- a/flake.nix +++ b/flake.nix @@ -51,15 +51,15 @@ # not sure if this is the correct way to get lsp* packages in lsp = { - url = "https://hackage.haskell.org/package/lsp-2.1.0.0/lsp-2.1.0.0.tar.gz"; + url = "https://hackage.haskell.org/package/lsp-2.2.0.0/lsp-2.2.0.0.tar.gz"; flake = false; }; lsp-types = { - url = "https://hackage.haskell.org/package/lsp-types-2.0.1.0/lsp-types-2.0.1.0.tar.gz"; + url = "https://hackage.haskell.org/package/lsp-types-2.0.2.0/lsp-types-2.0.2.0.tar.gz"; flake = false; }; lsp-test = { - url = "https://hackage.haskell.org/package/lsp-test-0.15.0.1/lsp-test-0.15.0.1.tar.gz"; + url = "https://hackage.haskell.org/package/lsp-test-0.16.0.0/lsp-test-0.16.0.0.tar.gz"; flake = false; }; @@ -244,8 +244,7 @@ # Theses programs are tools, used as binary, independently of the # version of GHC. # The drawback of this approach is that our shell may pull two GHC - # version in scope (the default one, and the one defined in - # `hpkgs`.) + # version in scope (the default one, an # The advantage is that we won't have to rebuild theses tools (and # dependencies) with a recent GHC which may not be supported by # them. diff --git a/ghcide-bench/src/Experiments.hs b/ghcide-bench/src/Experiments.hs index 552f400081..1a8614e1e9 100644 --- a/ghcide-bench/src/Experiments.hs +++ b/ghcide-bench/src/Experiments.hs @@ -29,7 +29,7 @@ import Control.Applicative.Combinators (skipManyTill) import Control.Concurrent.Async (withAsync) import Control.Exception.Safe (IOException, handleAny, try) -import Control.Lens ((^.)) +import Control.Lens (_Just, (&), (.~), (^.)) import Control.Lens.Extras (is) import Control.Monad.Extra (allM, forM, forM_, forever, unless, void, when, @@ -108,6 +108,22 @@ experiments = bench "hover" $ allWithIdentifierPos $ \DocumentPositions{..} -> isJust <$> getHover doc (fromJust identifierP), --------------------------------------------------------------------------------------- + bench "hover after edit" $ \docs -> do + forM_ docs $ \DocumentPositions{..} -> + changeDoc doc [charEdit stringLiteralP] + flip allWithIdentifierPos docs $ \DocumentPositions{..} -> + isJust <$> getHover doc (fromJust identifierP), + --------------------------------------------------------------------------------------- + bench + "hover after cradle edit" + (\docs -> do + hieYamlUri <- getDocUri "hie.yaml" + liftIO $ appendFile (fromJust $ uriToFilePath hieYamlUri) "##\n" + sendNotification SMethod_WorkspaceDidChangeWatchedFiles $ DidChangeWatchedFilesParams $ + [ FileEvent hieYamlUri FileChangeType_Changed ] + flip allWithIdentifierPos docs $ \DocumentPositions{..} -> isJust <$> getHover doc (fromJust identifierP) + ), + --------------------------------------------------------------------------------------- bench "edit" $ \docs -> do forM_ docs $ \DocumentPositions{..} -> do changeDoc doc [charEdit stringLiteralP] @@ -128,12 +144,6 @@ experiments = waitForProgressDone return True, --------------------------------------------------------------------------------------- - bench "hover after edit" $ \docs -> do - forM_ docs $ \DocumentPositions{..} -> - changeDoc doc [charEdit stringLiteralP] - flip allWithIdentifierPos docs $ \DocumentPositions{..} -> - isJust <$> getHover doc (fromJust identifierP), - --------------------------------------------------------------------------------------- bench "getDefinition" $ allWithIdentifierPos $ \DocumentPositions{..} -> hasDefinitions <$> getDefinitions doc (fromJust identifierP), --------------------------------------------------------------------------------------- @@ -162,30 +172,21 @@ experiments = flip allWithIdentifierPos docs $ \DocumentPositions{..} -> not . null <$> getCompletions doc (fromJust identifierP), --------------------------------------------------------------------------------------- - benchWithSetup + bench "code actions" ( \docs -> do unless (any (isJust . identifierP) docs) $ error "None of the example modules is suitable for this experiment" - forM_ docs $ \DocumentPositions{..} -> do - forM_ identifierP $ \p -> changeDoc doc [charEdit p] - waitForProgressStart - waitForProgressDone - ) - ( \docs -> not . null . catMaybes <$> forM docs (\DocumentPositions{..} -> - forM identifierP $ \p -> - getCodeActions doc (Range p p)) + not . null . catMaybes <$> forM docs (\DocumentPositions{..} -> do + forM identifierP $ \p -> + getCodeActions doc (Range p p)) ), --------------------------------------------------------------------------------------- - benchWithSetup + bench "code actions after edit" ( \docs -> do unless (any (isJust . identifierP) docs) $ error "None of the example modules is suitable for this experiment" - forM_ docs $ \DocumentPositions{..} -> - forM_ identifierP $ \p -> changeDoc doc [charEdit p] - ) - ( \docs -> do forM_ docs $ \DocumentPositions{..} -> do changeDoc doc [charEdit stringLiteralP] waitForProgressStart @@ -195,15 +196,8 @@ experiments = getCodeActions doc (Range p p)) ), --------------------------------------------------------------------------------------- - benchWithSetup + bench "code actions after cradle edit" - ( \docs -> do - forM_ docs $ \DocumentPositions{..} -> do - forM identifierP $ \p -> do - changeDoc doc [charEdit p] - waitForProgressStart - void waitForBuildQueue - ) ( \docs -> do hieYamlUri <- getDocUri "hie.yaml" liftIO $ appendFile (fromJust $ uriToFilePath hieYamlUri) "##\n" @@ -219,13 +213,20 @@ experiments = ), --------------------------------------------------------------------------------------- bench - "hover after cradle edit" - (\docs -> do - hieYamlUri <- getDocUri "hie.yaml" - liftIO $ appendFile (fromJust $ uriToFilePath hieYamlUri) "##\n" - sendNotification SMethod_WorkspaceDidChangeWatchedFiles $ DidChangeWatchedFilesParams $ - [ FileEvent hieYamlUri FileChangeType_Changed ] - flip allWithIdentifierPos docs $ \DocumentPositions{..} -> isJust <$> getHover doc (fromJust identifierP) + "code lens" + ( \docs -> not . null <$> forM docs (\DocumentPositions{..} -> + getCodeLenses doc) + ), + --------------------------------------------------------------------------------------- + bench + "code lens after edit" + ( \docs -> do + forM_ docs $ \DocumentPositions{..} -> do + changeDoc doc [charEdit stringLiteralP] + waitForProgressStart + waitForProgressDone + not . null <$> forM docs (\DocumentPositions{..} -> do + getCodeLenses doc) ), --------------------------------------------------------------------------------------- benchWithSetup @@ -483,7 +484,10 @@ runBenchmarksFun dir allBenchmarks = do ] ++ ["--ot-memory-profiling" | Just _ <- [otMemoryProfiling ?config]] lspTestCaps = - fullCaps {_window = Just $ WindowClientCapabilities (Just True) Nothing Nothing } + fullCaps + & (L.window . _Just) .~ WindowClientCapabilities (Just True) Nothing Nothing + & (L.textDocument . _Just . L.codeAction . _Just . L.resolveSupport . _Just) .~ (#properties .== ["edit"]) + & (L.textDocument . _Just . L.codeAction . _Just . L.dataSupport . _Just) .~ True showMs :: Seconds -> String showMs = printf "%.2f" @@ -512,7 +516,7 @@ waitForProgressStart :: Session () waitForProgressStart = void $ do skipManyTill anyMessage $ satisfy $ \case FromServerMess SMethod_WindowWorkDoneProgressCreate _ -> True - _ -> False + _ -> False -- | Wait for all progress to be done -- Needs at least one progress done notification to return @@ -542,11 +546,9 @@ runBench :: (Session BenchRun -> IO BenchRun) -> Bench -> IO BenchRun -runBench runSess b = handleAny (\e -> print e >> return badRun) +runBench runSess Bench{..} = handleAny (\e -> print e >> return badRun) $ runSess $ do - case b of - Bench{..} -> do (startup, docs) <- duration $ do (d, docs) <- duration $ setupDocumentContents ?config output $ "Setting up document contents took " <> showDuration d diff --git a/plugins/hls-class-plugin/src/Ide/Plugin/Class.hs b/plugins/hls-class-plugin/src/Ide/Plugin/Class.hs index 418f55a590..49abbe9710 100644 --- a/plugins/hls-class-plugin/src/Ide/Plugin/Class.hs +++ b/plugins/hls-class-plugin/src/Ide/Plugin/Class.hs @@ -10,9 +10,10 @@ import Language.LSP.Protocol.Message descriptor :: Recorder (WithPriority Log) -> PluginId -> PluginDescriptor IdeState descriptor recorder plId = (defaultPluginDescriptor plId) { pluginCommands = commands plId - , pluginRules = rules recorder + , pluginRules = getInstanceBindTypeSigsRule recorder >> getInstanceBindLensRule recorder , pluginHandlers = mkPluginHandler SMethod_TextDocumentCodeAction (codeAction recorder) <> mkPluginHandler SMethod_TextDocumentCodeLens codeLens + <> mkResolveHandler SMethod_CodeLensResolve codeLensResolve } commands :: PluginId -> [PluginCommand IdeState] @@ -20,5 +21,5 @@ commands plId = [ PluginCommand codeActionCommandId "add placeholders for minimal methods" (addMethodPlaceholders plId) , PluginCommand typeLensCommandId - "add type signatures for instance methods" codeLensCommandHandler + "add type signatures for instance methods" (codeLensCommandHandler plId) ] diff --git a/plugins/hls-class-plugin/src/Ide/Plugin/Class/CodeAction.hs b/plugins/hls-class-plugin/src/Ide/Plugin/Class/CodeAction.hs index 18accdbc6f..a3d75465bd 100644 --- a/plugins/hls-class-plugin/src/Ide/Plugin/Class/CodeAction.hs +++ b/plugins/hls-class-plugin/src/Ide/Plugin/Class/CodeAction.hs @@ -106,6 +106,8 @@ codeAction recorder state plId (CodeActionParams _ _ docId _ context) = do cls <- findClassFromIdentifier docPath ident InstanceBindTypeSigsResult sigs <- runActionE "classplugin.codeAction.GetInstanceBindTypeSigs" state $ useE GetInstanceBindTypeSigs docPath + (tmrTypechecked -> gblEnv ) <- runActionE "classplugin.codeAction.TypeCheck" state $ useE TypeCheck docPath + (hscEnv -> hsc) <- runActionE "classplugin.codeAction.GhcSession" state $ useE GhcSession docPath implemented <- findImplementedMethods ast instancePosition logWith recorder Info (LogImplementedMethods cls implemented) pure @@ -113,15 +115,15 @@ codeAction recorder state plId (CodeActionParams _ _ docId _ context) = do $ nubOrdOn snd $ filter ((/=) mempty . snd) $ fmap (second (filter (\(bind, _) -> bind `notElem` implemented))) - $ mkMethodGroups range sigs cls + $ mkMethodGroups hsc gblEnv range sigs cls where range = diag ^. L.range - mkMethodGroups :: Range -> [InstanceBindTypeSig] -> Class -> [MethodGroup] - mkMethodGroups range sigs cls = minimalDef <> [allClassMethods] + mkMethodGroups :: HscEnv -> TcGblEnv -> Range -> [InstanceBindTypeSig] -> Class -> [MethodGroup] + mkMethodGroups hsc gblEnv range sigs cls = minimalDef <> [allClassMethods] where - minimalDef = minDefToMethodGroups range sigs $ classMinimalDef cls - allClassMethods = ("all missing methods", makeMethodDefinitions range sigs) + minimalDef = minDefToMethodGroups hsc gblEnv range sigs $ classMinimalDef cls + allClassMethods = ("all missing methods", makeMethodDefinitions hsc gblEnv range sigs) mkAction :: MethodGroup -> [Command |? CodeAction] mkAction (name, methods) @@ -211,15 +213,15 @@ type MethodName = T.Text type MethodDefinition = (MethodName, MethodSignature) type MethodGroup = (T.Text, [MethodDefinition]) -makeMethodDefinition :: InstanceBindTypeSig -> MethodDefinition -makeMethodDefinition sig = (name, signature) +makeMethodDefinition :: HscEnv -> TcGblEnv -> InstanceBindTypeSig -> MethodDefinition +makeMethodDefinition hsc gblEnv sig = (name, signature) where name = T.drop (T.length bindingPrefix) (printOutputable (bindName sig)) - signature = bindRendered sig + signature = prettyBindingNameString (printOutputable (bindName sig)) <> " :: " <> T.pack (showDoc hsc gblEnv (bindType sig)) -makeMethodDefinitions :: Range -> [InstanceBindTypeSig] -> [MethodDefinition] -makeMethodDefinitions range sigs = - [ makeMethodDefinition sig +makeMethodDefinitions :: HscEnv -> TcGblEnv -> Range -> [InstanceBindTypeSig] -> [MethodDefinition] +makeMethodDefinitions hsc gblEnv range sigs = + [ makeMethodDefinition hsc gblEnv sig | sig <- sigs , inRange range (getSrcSpan $ bindName sig) ] @@ -228,14 +230,14 @@ signatureToName :: InstanceBindTypeSig -> T.Text signatureToName sig = T.drop (T.length bindingPrefix) (printOutputable (bindName sig)) -- Return [groupName text, [(methodName text, signature text)]] -minDefToMethodGroups :: Range -> [InstanceBindTypeSig] -> BooleanFormula Name -> [MethodGroup] -minDefToMethodGroups range sigs minDef = makeMethodGroup <$> go minDef +minDefToMethodGroups :: HscEnv -> TcGblEnv -> Range -> [InstanceBindTypeSig] -> BooleanFormula Name -> [MethodGroup] +minDefToMethodGroups hsc gblEnv range sigs minDef = makeMethodGroup <$> go minDef where makeMethodGroup methodDefinitions = let name = mconcat $ intersperse "," $ (\x -> "'" <> x <> "'") . fst <$> methodDefinitions in (name, methodDefinitions) - go (Var mn) = pure $ makeMethodDefinitions range $ filter ((==) (printOutputable mn) . signatureToName) sigs + go (Var mn) = pure $ makeMethodDefinitions hsc gblEnv range $ filter ((==) (printOutputable mn) . signatureToName) sigs go (Or ms) = concatMap (go . unLoc) ms go (And ms) = foldr (liftA2 (<>)) [[]] (fmap (go . unLoc) ms) go (Parens m) = go (unLoc m) diff --git a/plugins/hls-class-plugin/src/Ide/Plugin/Class/CodeLens.hs b/plugins/hls-class-plugin/src/Ide/Plugin/Class/CodeLens.hs index daf5f4e2bc..ab345b2171 100644 --- a/plugins/hls-class-plugin/src/Ide/Plugin/Class/CodeLens.hs +++ b/plugins/hls-class-plugin/src/Ide/Plugin/Class/CodeLens.hs @@ -1,20 +1,21 @@ {-# LANGUAGE GADTs #-} +{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedLists #-} -{-# LANGUAGE RecordWildCards #-} -{-# OPTIONS_GHC -Wno-overlapping-patterns #-} - +{-# LANGUAGE ViewPatterns #-} module Ide.Plugin.Class.CodeLens where -import Control.Lens ((^.)) +import Control.Lens ((&), (?~), (^.)) import Control.Monad.Trans.Class (MonadTrans (lift)) import Data.Aeson hiding (Null) +import qualified Data.IntMap.Strict as IntMap import Data.Maybe (mapMaybe, maybeToList) import qualified Data.Text as T import Development.IDE import Development.IDE.Core.PluginUtils import Development.IDE.Core.PositionMapping import Development.IDE.GHC.Compat -import Development.IDE.GHC.Compat.Util +import Development.IDE.Spans.Pragmas (getFirstPragma, + insertNewPragma) import Ide.Plugin.Class.Types import Ide.Plugin.Class.Utils import Ide.Plugin.Error @@ -25,118 +26,73 @@ import Language.LSP.Protocol.Message import Language.LSP.Protocol.Types import Language.LSP.Server (sendRequest) +-- The code lens method is only responsible for providing the ranges of the code +-- lenses matched to a unique id codeLens :: PluginMethodHandler IdeState Method_TextDocumentCodeLens -codeLens state plId CodeLensParams{..} = do +codeLens state _plId clp = do + nfp <- getNormalizedFilePathE $ clp ^. L.textDocument . L.uri + (InstanceBindLensResult (InstanceBindLens{lensRange}), pm) + <- runActionE "classplugin.GetInstanceBindLens" state + -- Using stale results means that we can almost always return a + -- value. In practice this means the lenses don't 'flicker' + $ useWithStaleE GetInstanceBindLens nfp + pure $ InL $ mapMaybe (toCodeLens pm) lensRange + where toCodeLens pm (range, int) = + let newRange = toCurrentRange pm range + in (\r -> CodeLens r Nothing (Just $ toJSON int)) <$> newRange + +-- The code lens resolve method matches a title to each unique id +codeLensResolve:: ResolveFunction IdeState Int Method_CodeLensResolve +codeLensResolve state plId cl uri uniqueID = do nfp <- getNormalizedFilePathE uri - (tmr, _) <- runActionE "classplugin.TypeCheck" state - -- Using stale results means that we can almost always return a value. In practice - -- this means the lenses don't 'flicker' - $ useWithStaleE TypeCheck nfp - - -- All instance binds - (InstanceBindTypeSigsResult allBinds, mp) <- runActionE "classplugin.GetInstanceBindTypeSigs" state - -- Using stale results means that we can almost always return a value. In practice - -- this means the lenses don't 'flicker' - $ useWithStaleE GetInstanceBindTypeSigs nfp - - pragmaInsertion <- insertPragmaIfNotPresent state nfp InstanceSigs - - let (hsGroup, _, _, _) = tmrRenamed tmr - tycls = hs_tyclds hsGroup - -- declared instance methods without signatures - bindInfos = [ bind - | instds <- map group_instds tycls -- class instance decls - , instd <- instds - , inst <- maybeToList $ getClsInstD (unLoc instd) - , bind <- getBindSpanWithoutSig inst - ] - targetSigs = matchBind bindInfos allBinds - makeLens (range, title) = - generateLens plId range title - $ workspaceEdit pragmaInsertion - $ makeEdit range title mp - codeLens = makeLens <$> mapMaybe getRangeWithSig targetSigs - - pure $ InL codeLens + (InstanceBindLensResult (InstanceBindLens{lensDetails}), pm) + <- runActionE "classplugin.GetInstanceBindLens" state + $ useWithStaleE GetInstanceBindLens nfp + (tmrTypechecked -> gblEnv, _) <- runActionE "classplugin.codeAction.TypeCheck" state $ useWithStaleE TypeCheck nfp + (hscEnv -> hsc, _) <- runActionE "classplugin.codeAction.GhcSession" state $ useWithStaleE GhcSession nfp + (range, name, typ) <- handleMaybe PluginStaleResolve + $ IntMap.lookup uniqueID lensDetails + let title = prettyBindingNameString (printOutputable name) <> " :: " <> T.pack (showDoc hsc gblEnv typ) + edit <- handleMaybe (PluginInvalidUserState "toCurrentRange") $ makeEdit range title pm + let command = mkLspCommand plId typeLensCommandId title (Just [toJSON $ InstanceBindLensCommand uri edit]) + pure $ cl & L.command ?~ command where - uri = _textDocument ^. L.uri - - -- Match Binds with their signatures - -- We try to give every `InstanceBindTypeSig` a `SrcSpan`, - -- hence we can display signatures for `InstanceBindTypeSig` with span later. - matchBind :: [BindInfo] -> [InstanceBindTypeSig] -> [InstanceBindTypeSig] - matchBind existedBinds allBindWithSigs = - [foldl go bindSig existedBinds | bindSig <- allBindWithSigs] - where - -- | The `bindDefSpan` of the bind is `Nothing` before, - -- we update it with the span where binding occurs. - -- Hence, we can infer the place to display the signature later. - update :: InstanceBindTypeSig -> SrcSpan -> InstanceBindTypeSig - update bind sp = bind {bindDefSpan = Just sp} - - go :: InstanceBindTypeSig -> BindInfo -> InstanceBindTypeSig - go bindSig bind = case (srcSpanToRange . bindNameSpan) bind of - Nothing -> bindSig - Just range -> - if inRange range (getSrcSpan $ bindName bindSig) - then update bindSig (bindSpan bind) - else bindSig - - getClsInstD (ClsInstD _ d) = Just d - getClsInstD _ = Nothing - - getSigName (ClassOpSig _ _ sigNames _) = Just $ map unLoc sigNames - getSigName _ = Nothing - - getBindSpanWithoutSig :: ClsInstDecl GhcRn -> [BindInfo] - getBindSpanWithoutSig ClsInstDecl{..} = - let bindNames = mapMaybe go (bagToList cid_binds) - go (L l bind) = case bind of - FunBind{..} - -- `Generated` tagged for Template Haskell, - -- here we filter out nonsence generated bindings - -- that are nonsense for displaying code lenses. - -- - -- See https://github.com/haskell/haskell-language-server/issues/3319 - | not $ isGenerated (groupOrigin fun_matches) - -> Just $ L l fun_id - _ -> Nothing - -- Existed signatures' name - sigNames = concat $ mapMaybe (\(L _ r) -> getSigName r) cid_sigs - toBindInfo (L l (L l' _)) = BindInfo - (locA l) -- bindSpan - (locA l') -- bindNameSpan - in toBindInfo <$> filter (\(L _ name) -> unLoc name `notElem` sigNames) bindNames - getBindSpanWithoutSig _ = [] - - -- Get bind definition range with its rendered signature text - getRangeWithSig :: InstanceBindTypeSig -> Maybe (Range, T.Text) - getRangeWithSig bind = do - span <- bindDefSpan bind - range <- srcSpanToRange span - pure (range, bindRendered bind) - - workspaceEdit pragmaInsertion edits = - WorkspaceEdit - (pure [(uri, edits ++ pragmaInsertion)]) - Nothing - Nothing - - generateLens :: PluginId -> Range -> T.Text -> WorkspaceEdit -> CodeLens - generateLens plId range title edit = - let cmd = mkLspCommand plId typeLensCommandId title (Just [toJSON edit]) - in CodeLens range (Just cmd) Nothing - - makeEdit :: Range -> T.Text -> PositionMapping -> [TextEdit] + makeEdit :: Range -> T.Text -> PositionMapping -> Maybe TextEdit makeEdit range bind mp = let startPos = range ^. L.start insertChar = startPos ^. L.character insertRange = Range startPos startPos in case toCurrentRange mp insertRange of - Just rg -> [TextEdit rg (bind <> "\n" <> T.replicate (fromIntegral insertChar) " ")] - Nothing -> [] + Just rg -> Just $ TextEdit rg (bind <> "\n" <> T.replicate (fromIntegral insertChar) " ") + Nothing -> Nothing + +-- Finally the command actually generates and applies the workspace edit for the +-- specified unique id. +codeLensCommandHandler :: PluginId -> CommandFunction IdeState InstanceBindLensCommand +codeLensCommandHandler plId state InstanceBindLensCommand{commandUri, commandEdit} = do + nfp <- getNormalizedFilePathE commandUri + (InstanceBindLensResult (InstanceBindLens{lensEnabledExtensions}), _) + <- runActionE "classplugin.GetInstanceBindLens" state + $ useWithStaleE GetInstanceBindLens nfp + -- We are only interested in the pragma information if the user does not + -- have the InstanceSigs extension enabled + mbPragma <- if InstanceSigs `elem` lensEnabledExtensions + then pure Nothing + else Just <$> getFirstPragma plId state nfp + let -- By mapping over our Maybe NextPragmaInfo value, we only compute this + -- edit if we actually need to. + pragmaInsertion = + maybeToList $ flip insertNewPragma InstanceSigs <$> mbPragma + wEdit = workspaceEdit pragmaInsertion + _ <- lift $ sendRequest SMethod_WorkspaceApplyEdit (ApplyWorkspaceEditParams Nothing wEdit) (\_ -> pure ()) + pure $ InR Null + where + workspaceEdit pragmaInsertion= + WorkspaceEdit + (pure [(commandUri, commandEdit : pragmaInsertion)]) + Nothing + Nothing + + + -codeLensCommandHandler :: CommandFunction IdeState WorkspaceEdit -codeLensCommandHandler _ wedit = do - _ <- lift $ sendRequest SMethod_WorkspaceApplyEdit (ApplyWorkspaceEditParams Nothing wedit) (\_ -> pure ()) - pure $ InR Null diff --git a/plugins/hls-class-plugin/src/Ide/Plugin/Class/Types.hs b/plugins/hls-class-plugin/src/Ide/Plugin/Class/Types.hs index 220682487c..9f4e5185a8 100644 --- a/plugins/hls-class-plugin/src/Ide/Plugin/Class/Types.hs +++ b/plugins/hls-class-plugin/src/Ide/Plugin/Class/Types.hs @@ -2,25 +2,34 @@ {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE LambdaCase #-} +{-# LANGUAGE RecordWildCards #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE ViewPatterns #-} module Ide.Plugin.Class.Types where -import Control.DeepSeq (rwhnf) -import Control.Monad.Extra (whenMaybe) -import Control.Monad.IO.Class (liftIO) +import Control.DeepSeq (rwhnf) +import Control.Monad.Extra (mapMaybeM, whenMaybe) +import Control.Monad.IO.Class (liftIO) +import Control.Monad.Trans.Maybe (MaybeT (MaybeT, runMaybeT)) import Data.Aeson -import Data.Maybe (catMaybes) -import qualified Data.Text as T +import qualified Data.IntMap as IntMap +import Data.List.Extra (firstJust) +import Data.Maybe (catMaybes, mapMaybe, + maybeToList) +import qualified Data.Text as T +import Data.Unique (hashUnique, newUnique) import Development.IDE -import qualified Development.IDE.Core.Shake as Shake -import Development.IDE.GHC.Compat hiding ((<+>)) +import Development.IDE.Core.PluginUtils (useMT) +import qualified Development.IDE.Core.Shake as Shake +import Development.IDE.GHC.Compat hiding (newUnique, (<+>)) +import Development.IDE.GHC.Compat.Util (bagToList) import Development.IDE.Graph.Classes import GHC.Generics import Ide.Plugin.Class.Utils import Ide.Types -import Language.LSP.Protocol.Types (VersionedTextDocumentIdentifier) +import Language.LSP.Protocol.Types (TextEdit, + VersionedTextDocumentIdentifier) typeLensCommandId :: CommandId typeLensCommandId = "classplugin.typelens" @@ -41,14 +50,15 @@ data AddMinimalMethodsParams = AddMinimalMethodsParams } deriving (Show, Eq, Generic, ToJSON, FromJSON) +-- |The InstanceBindTypeSigs Rule collects the instance bindings type +-- signatures (both name and type). It is used by both the code actions and the +-- code lenses data GetInstanceBindTypeSigs = GetInstanceBindTypeSigs deriving (Generic, Show, Eq, Ord, Hashable, NFData) data InstanceBindTypeSig = InstanceBindTypeSig - { bindName :: Name - , bindRendered :: !T.Text - , bindDefSpan :: Maybe SrcSpan - -- ^SrcSpan for the bind definition + { bindName :: Name + , bindType :: Type } newtype InstanceBindTypeSigsResult = @@ -62,6 +72,46 @@ instance NFData InstanceBindTypeSigsResult where type instance RuleResult GetInstanceBindTypeSigs = InstanceBindTypeSigsResult +-- |The necessary data to execute our code lens +data InstanceBindLensCommand = InstanceBindLensCommand + { -- |The URI needed to run actions in the command + commandUri :: Uri + -- |The specific TextEdit we want to apply. This does not include the + -- pragma edit which is computed in the command + , commandEdit :: TextEdit } + deriving (Generic, FromJSON, ToJSON) + +-- | The InstanceBindLens rule is specifically for code lenses. It relies on +-- the InstanceBindTypeSigs rule, filters out irrelevant matches and signatures +-- that can't be matched to a source span. It provides all the signatures linked +-- to a unique ID to aid in resolving. It also provides a list of enabled +-- extensions. +data GetInstanceBindLens = GetInstanceBindLens + deriving (Generic, Show, Eq, Ord, Hashable, NFData) + +data InstanceBindLens = InstanceBindLens + { -- |What we need to provide the code lens. The range linked with + -- a unique ID that will allow us to resolve the rest of the data later + lensRange :: [(Range, Int)] + -- |Provides the necessary data to allow us to display the + -- title of the lens and compute a TextEdit for it. + , lensDetails :: IntMap.IntMap (Range, Name, Type) + -- |Provides currently enabled extensions, allowing us to conditionally + -- insert needed extensions. + , lensEnabledExtensions :: [Extension] + } + +newtype InstanceBindLensResult = + InstanceBindLensResult InstanceBindLens + +instance Show InstanceBindLensResult where + show _ = "" + +instance NFData InstanceBindLensResult where + rnf = rwhnf + +type instance RuleResult GetInstanceBindLens = InstanceBindLensResult + data Log = LogImplementedMethods Class [T.Text] | LogShake Shake.Log @@ -81,30 +131,89 @@ data BindInfo = BindInfo -- ^ SrcSpan of the binding name } -rules :: Recorder (WithPriority Log) -> Rules () -rules recorder = do - define (cmapWithPrio LogShake recorder) $ \GetInstanceBindTypeSigs nfp -> do - tmr <- use TypeCheck nfp - hsc <- use GhcSession nfp - result <- liftIO $ instanceBindType (hscEnv <$> hsc) (tmrTypechecked <$> tmr) - pure ([], result) +getInstanceBindLensRule :: Recorder (WithPriority Log) -> Rules () +getInstanceBindLensRule recorder = do + defineNoDiagnostics (cmapWithPrio LogShake recorder) $ \GetInstanceBindLens nfp -> runMaybeT $ do + tmr@(tmrRenamed -> (hs_tyclds -> tycls, _, _, _)) <- useMT TypeCheck nfp + (InstanceBindTypeSigsResult allBinds) <- useMT GetInstanceBindTypeSigs nfp + + let -- declared instance methods without signatures + bindInfos = [ bind + | instds <- map group_instds tycls -- class instance decls + , instd <- instds + , inst <- maybeToList $ getClsInstD (unLoc instd) + , bind <- getBindSpanWithoutSig inst + ] + targetSigs = matchBind bindInfos allBinds + rangeIntNameType <- liftIO $ mapMaybeM getRangeWithSig targetSigs + let lensRange = (\(range, int, _, _) -> (range, int)) <$> rangeIntNameType + lensDetails = IntMap.fromList $ (\(range, int, name, typ) -> (int, (range, name, typ))) <$> rangeIntNameType + lensEnabledExtensions = getExtensions $ tmrParsed tmr + pure $ InstanceBindLensResult $ InstanceBindLens{..} where - instanceBindType :: Maybe HscEnv -> Maybe TcGblEnv -> IO (Maybe InstanceBindTypeSigsResult) - instanceBindType (Just hsc) (Just gblEnv) = do - let binds = collectHsBindsBinders $ tcg_binds gblEnv - (_, maybe [] catMaybes -> instanceBinds) <- - initTcWithGbl hsc gblEnv ghostSpan $ traverse bindToSig binds - pure $ Just $ InstanceBindTypeSigsResult instanceBinds + -- Match Binds with their signatures + -- We try to give every `InstanceBindTypeSig` a `SrcSpan`, + -- hence we can display signatures for `InstanceBindTypeSig` with span later. + matchBind :: [BindInfo] -> [InstanceBindTypeSig] -> [Maybe (InstanceBindTypeSig, SrcSpan)] + matchBind existedBinds allBindWithSigs = + [firstJust (go bindSig) existedBinds | bindSig <- allBindWithSigs] where - rdrEnv = tcg_rdr_env gblEnv - showDoc ty = showSDocForUser' hsc (mkPrintUnqualifiedDefault hsc rdrEnv) (pprSigmaType ty) - - bindToSig id = do - let name = idName id - whenMaybe (isBindingName name) $ do - env <- tcInitTidyEnv - let (_, ty) = tidyOpenType env (idType id) - pure $ InstanceBindTypeSig name - (prettyBindingNameString (printOutputable name) <> " :: " <> T.pack (showDoc ty)) - Nothing - instanceBindType _ _ = pure Nothing + go :: InstanceBindTypeSig -> BindInfo -> Maybe (InstanceBindTypeSig, SrcSpan) + go bindSig bind = do + range <- (srcSpanToRange . bindNameSpan) bind + if inRange range (getSrcSpan $ bindName bindSig) + then Just (bindSig, bindSpan bind) + else Nothing + + getClsInstD (ClsInstD _ d) = Just d + getClsInstD _ = Nothing + + getSigName (ClassOpSig _ _ sigNames _) = Just $ map unLoc sigNames + getSigName _ = Nothing + + getBindSpanWithoutSig :: ClsInstDecl GhcRn -> [BindInfo] + getBindSpanWithoutSig ClsInstDecl{..} = + let bindNames = mapMaybe go (bagToList cid_binds) + go (L l bind) = case bind of + FunBind{..} + -- `Generated` tagged for Template Haskell, + -- here we filter out nonsense generated bindings + -- that are nonsense for displaying code lenses. + -- + -- See https://github.com/haskell/haskell-language-server/issues/3319 + | not $ isGenerated (groupOrigin fun_matches) + -> Just $ L l fun_id + _ -> Nothing + -- Existed signatures' name + sigNames = concat $ mapMaybe (\(L _ r) -> getSigName r) cid_sigs + toBindInfo (L l (L l' _)) = BindInfo + (locA l) -- bindSpan + (locA l') -- bindNameSpan + in toBindInfo <$> filter (\(L _ name) -> unLoc name `notElem` sigNames) bindNames + getBindSpanWithoutSig _ = [] + + -- Get bind definition range with its rendered signature text + getRangeWithSig :: Maybe (InstanceBindTypeSig, SrcSpan) -> IO (Maybe (Range, Int, Name, Type)) + getRangeWithSig (Just (bind, span)) = runMaybeT $ do + range <- MaybeT . pure $ srcSpanToRange span + uniqueID <- liftIO $ hashUnique <$> newUnique + pure (range, uniqueID, bindName bind, bindType bind) + getRangeWithSig Nothing = pure Nothing + + +getInstanceBindTypeSigsRule :: Recorder (WithPriority Log) -> Rules () +getInstanceBindTypeSigsRule recorder = do + defineNoDiagnostics (cmapWithPrio LogShake recorder) $ \GetInstanceBindTypeSigs nfp -> runMaybeT $ do + (tmrTypechecked -> gblEnv ) <- useMT TypeCheck nfp + (hscEnv -> hsc) <- useMT GhcSession nfp + let binds = collectHsBindsBinders $ tcg_binds gblEnv + (_, maybe [] catMaybes -> instanceBinds) <- liftIO $ + initTcWithGbl hsc gblEnv ghostSpan $ traverse bindToSig binds + pure $ InstanceBindTypeSigsResult instanceBinds + where + bindToSig id = do + let name = idName id + whenMaybe (isBindingName name) $ do + env <- tcInitTidyEnv + let (_, ty) = tidyOpenType env (idType id) + pure $ InstanceBindTypeSig name ty diff --git a/plugins/hls-class-plugin/src/Ide/Plugin/Class/Utils.hs b/plugins/hls-class-plugin/src/Ide/Plugin/Class/Utils.hs index 164d75ddc4..129251ffe5 100644 --- a/plugins/hls-class-plugin/src/Ide/Plugin/Class/Utils.hs +++ b/plugins/hls-class-plugin/src/Ide/Plugin/Class/Utils.hs @@ -39,6 +39,10 @@ prettyBindingNameString name toMethodName $ T.drop (T.length bindingPrefix) name | otherwise = name +showDoc :: HscEnv -> TcGblEnv -> Type -> String +showDoc hsc gblEnv ty = showSDocForUser' hsc (mkPrintUnqualifiedDefault hsc (rdrEnv gblEnv)) (pprSigmaType ty) + where rdrEnv gblEnv = tcg_rdr_env gblEnv + -- | Paren the name for pretty display if necessary toMethodName :: T.Text -> T.Text toMethodName n diff --git a/plugins/hls-class-plugin/test/Main.hs b/plugins/hls-class-plugin/test/Main.hs index 7bcdafb33e..7274381544 100644 --- a/plugins/hls-class-plugin/test/Main.hs +++ b/plugins/hls-class-plugin/test/Main.hs @@ -10,8 +10,8 @@ module Main ( main ) where -import Control.Lens (Prism', prism', (^.), (^..), - (^?)) +import Control.Lens (Prism', prism', view, (^.), + (^..), (^?)) import Control.Monad (void) import Data.Maybe import Data.Row ((.==)) @@ -111,7 +111,7 @@ codeLensTests = testGroup [ testCase "Has code lens" $ do runSessionWithServer def classPlugin testDataDir $ do doc <- openDoc "CodeLensSimple.hs" "haskell" - lens <- getCodeLenses doc + lens <- getAndResolveCodeLenses doc let titles = map (^. L.title) $ mapMaybe (^. L.command) lens liftIO $ titles @?= [ "(==) :: B -> B -> Bool" @@ -120,7 +120,7 @@ codeLensTests = testGroup , testCase "No lens for TH" $ do runSessionWithServer def classPlugin testDataDir $ do doc <- openDoc "TH.hs" "haskell" - lens <- getCodeLenses doc + lens <- getAndResolveCodeLenses doc liftIO $ length lens @?= 0 , goldenCodeLens "Apply code lens" "CodeLensSimple" 1 , goldenCodeLens "Apply code lens for local class" "LocalClassDefine" 0 @@ -133,11 +133,11 @@ codeLensTests = testGroup , testCase "keep stale lens" $ do runSessionWithServer def classPlugin testDataDir $ do doc <- openDoc "Stale.hs" "haskell" - oldLens <- getCodeLenses doc + oldLens <- getAndResolveCodeLenses doc let edit = TextEdit (mkRange 4 11 4 12) "" -- Remove the `_` _ <- applyEdit doc edit - newLens <- getCodeLenses doc - liftIO $ newLens @?= oldLens + newLens <- getAndResolveCodeLenses doc + liftIO $ (view L.command <$> newLens ) @?= (view L.command <$> oldLens) ] _CACodeAction :: Prism' (Command |? CodeAction) CodeAction @@ -148,7 +148,7 @@ _CACodeAction = prism' InR $ \case goldenCodeLens :: TestName -> FilePath -> Int -> TestTree goldenCodeLens title path idx = goldenWithHaskellDoc def classPlugin title testDataDir path "expected" "hs" $ \doc -> do - lens <- getCodeLenses doc + lens <- getAndResolveCodeLenses doc executeCommand $ fromJust $ (lens !! idx) ^. L.command void $ skipManyTill anyMessage (message SMethod_WorkspaceApplyEdit) diff --git a/plugins/hls-fourmolu-plugin/hls-fourmolu-plugin.cabal b/plugins/hls-fourmolu-plugin/hls-fourmolu-plugin.cabal index 8944252459..53ce82fa26 100644 --- a/plugins/hls-fourmolu-plugin/hls-fourmolu-plugin.cabal +++ b/plugins/hls-fourmolu-plugin/hls-fourmolu-plugin.cabal @@ -26,13 +26,11 @@ library buildable: True exposed-modules: Ide.Plugin.Fourmolu - , Ide.Plugin.Fourmolu.Shim hs-source-dirs: src ghc-options: -Wall build-depends: , base >=4.12 && <5 , filepath - , fourmolu ^>=0.3 || ^>=0.4 || ^>= 0.6 || ^>= 0.7 || ^>= 0.8 || ^>= 0.9 || ^>= 0.10 || ^>= 0.11 || ^>= 0.12 || ^>= 0.13 , ghc , ghc-boot-th , ghcide == 2.2.0.0 @@ -44,6 +42,13 @@ library , text , transformers + if impl(ghc >= 9.0) && impl(ghc < 9.2) + build-depends: fourmolu ^>= 0.11 + elif impl(ghc >= 9.2) && impl(ghc < 9.8) + build-depends: fourmolu ^>= 0.14 + else + buildable: false + -- fourmolu 0.9.0 fails to build on Windows CI for reasons unknown if impl(ghc >= 9.2) && os(windows) && impl(ghc < 9.4) build-depends: fourmolu > 0.9.0.0 || < 0.9.0.0 diff --git a/plugins/hls-fourmolu-plugin/src/Ide/Plugin/Fourmolu.hs b/plugins/hls-fourmolu-plugin/src/Ide/Plugin/Fourmolu.hs index 3ae5baf1bc..68fd1b2017 100644 --- a/plugins/hls-fourmolu-plugin/src/Ide/Plugin/Fourmolu.hs +++ b/plugins/hls-fourmolu-plugin/src/Ide/Plugin/Fourmolu.hs @@ -5,6 +5,7 @@ {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedLabels #-} {-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE RecordWildCards #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeOperators #-} @@ -34,7 +35,6 @@ import Development.IDE.GHC.Compat as Compat hiding (Cpp, Warning, import qualified Development.IDE.GHC.Compat.Util as S import GHC.LanguageExtensions.Type (Extension (Cpp)) import Ide.Plugin.Error -import Ide.Plugin.Fourmolu.Shim import Ide.Plugin.Properties import Ide.PluginUtils (makeDiffTextEdit) import Ide.Types @@ -43,6 +43,7 @@ import Language.LSP.Protocol.Message import Language.LSP.Protocol.Types import Language.LSP.Server hiding (defaultConfig) import Ormolu +import Ormolu.Config import System.Exit import System.FilePath import System.Process.Run (cwd, proc) @@ -71,39 +72,19 @@ provider recorder plId ideState typ contents fp fo = ExceptT $ withIndefinitePro <$> liftIO (runAction "Fourmolu" ideState $ use GhcSession fp) useCLI <- liftIO $ runAction "Fourmolu" ideState $ usePropertyAction #external plId properties if useCLI - then mapExceptT liftIO $ ExceptT - $ handle @IOException - (pure . Left . PluginInternalError . T.pack . show) - $ runExceptT $ cliHandler fileOpts + then ExceptT . liftIO $ + handle @IOException (pure . Left . PluginInternalError . T.pack . show) $ + runExceptT (cliHandler fileOpts) else do logWith recorder Debug $ LogCompiledInVersion VERSION_fourmolu - let format fourmoluConfig = ExceptT $ - bimap (PluginInternalError . T.pack . show) (InL . makeDiffTextEdit contents) -#if MIN_VERSION_fourmolu(0,11,0) - <$> try @OrmoluException (ormolu config fp' contents) -#else - <$> try @OrmoluException (ormolu config fp' (T.unpack contents)) -#endif - where - printerOpts = cfgFilePrinterOpts fourmoluConfig - config = - addFixityOverrides (cfgFileFixities fourmoluConfig) $ - defaultConfig - { cfgDynOptions = map DynOption fileOpts - , cfgRegion = region - , cfgDebug = False - , cfgPrinterOpts = - fillMissingPrinterOpts - (printerOpts <> lspPrinterOpts) - defaultPrinterOpts - } - in liftIO (loadConfigFile fp') >>= \case + FourmoluConfig{..} <- + liftIO (loadConfigFile fp') >>= \case ConfigLoaded file opts -> do logWith recorder Info $ ConfigPath file - mapExceptT liftIO $ format opts + pure opts ConfigNotFound searchDirs -> do logWith recorder Info $ NoConfigPath searchDirs - mapExceptT liftIO $ format emptyConfig + pure emptyConfig ConfigParseError f err -> do lift $ sendNotification SMethod_WindowShowMessage $ ShowMessageParams @@ -112,7 +93,19 @@ provider recorder plId ideState typ contents fp fo = ExceptT $ withIndefinitePro } throwError $ PluginInternalError errorMessage where - errorMessage = "Failed to load " <> T.pack f <> ": " <> T.pack (showParseError err) + errorMessage = "Failed to load " <> T.pack f <> ": " <> T.pack (show err) + + let config = + defaultConfig + { cfgDynOptions = map DynOption fileOpts + , cfgFixityOverrides = cfgFileFixities + , cfgRegion = region + , cfgDebug = False + , cfgPrinterOpts = resolvePrinterOpts [lspPrinterOpts, cfgFilePrinterOpts] + } + ExceptT . liftIO $ + bimap (PluginInternalError . T.pack . show) (InL . makeDiffTextEdit contents) + <$> try @OrmoluException (ormolu config fp' contents) where fp' = fromNormalizedFilePath fp title = "Formatting " <> T.pack (takeFileName fp') @@ -200,3 +193,8 @@ newtype CLIVersionInfo = CLIVersionInfo mwhen :: Monoid a => Bool -> a -> a mwhen b x = if b then x else mempty + +#if !MIN_VERSION_fourmolu(0,14,0) +resolvePrinterOpts :: [PrinterOptsPartial] -> PrinterOptsTotal +resolvePrinterOpts = foldr fillMissingPrinterOpts defaultPrinterOpts +#endif diff --git a/plugins/hls-fourmolu-plugin/src/Ide/Plugin/Fourmolu/Shim.hs b/plugins/hls-fourmolu-plugin/src/Ide/Plugin/Fourmolu/Shim.hs deleted file mode 100644 index a97327cd7e..0000000000 --- a/plugins/hls-fourmolu-plugin/src/Ide/Plugin/Fourmolu/Shim.hs +++ /dev/null @@ -1,75 +0,0 @@ -{-# LANGUAGE CPP #-} - -module Ide.Plugin.Fourmolu.Shim ( - -- * FourmoluConfig - cfgFilePrinterOpts, - cfgFileFixities, - emptyConfig, - - -- * FixityMap - addFixityOverrides, - - -- * ConfigParseError - showParseError, -) where - -import Ormolu.Config - -#if MIN_VERSION_fourmolu(0,7,0) -import Ormolu.Fixity -#endif - -{-- Backport FourmoluConfig --} - -#if MIN_VERSION_fourmolu(0,7,0) --- these functions are now defined -#else -type FourmoluConfig = PrinterOptsPartial - -cfgFilePrinterOpts :: FourmoluConfig -> PrinterOptsPartial -cfgFilePrinterOpts = id - -cfgFileFixities :: FourmoluConfig -> FixityOverrides -cfgFileFixities _ = mempty -#endif - -#if MIN_VERSION_fourmolu(0,8,1) --- emptyConfig now provided -#elif MIN_VERSION_fourmolu(0,7,0) -emptyConfig :: FourmoluConfig -emptyConfig = - FourmoluConfig - { cfgFilePrinterOpts = mempty - , cfgFileFixities = mempty - } -#else -emptyConfig :: FourmoluConfig -emptyConfig = mempty -#endif - -{-- Backport FixityOverrides --} - -#if MIN_VERSION_fourmolu(0,13,0) -addFixityOverrides :: FixityOverrides -> Config region -> Config region -addFixityOverrides fixities cfg = cfg{cfgFixityOverrides = fixities} -#elif MIN_VERSION_fourmolu(0,7,0) -type FixityOverrides = FixityMap - -addFixityOverrides :: FixityOverrides -> Config region -> Config region -addFixityOverrides fixities cfg = cfg{cfgFixityOverrides = fixities} -#else -type FixityOverrides = () - -addFixityOverrides :: FixityOverrides -> Config region -> Config region -addFixityOverrides _ = id -#endif - -{-- Backport ConfigParseError --} - -#if MIN_VERSION_fourmolu(0,7,0) -showParseError :: Show parseException => parseException -> String -showParseError = show -#else -showParseError :: (pos, String) -> String -showParseError = snd -#endif diff --git a/plugins/hls-module-name-plugin/src/Ide/Plugin/ModuleName.hs b/plugins/hls-module-name-plugin/src/Ide/Plugin/ModuleName.hs index 6474a4c204..50264a68f1 100644 --- a/plugins/hls-module-name-plugin/src/Ide/Plugin/ModuleName.hs +++ b/plugins/hls-module-name-plugin/src/Ide/Plugin/ModuleName.hs @@ -25,11 +25,12 @@ import Control.Monad.Trans.Class (lift) import Control.Monad.Trans.Except import Control.Monad.Trans.Maybe import Data.Aeson (toJSON) -import Data.Char (isLower) -import Data.List (intercalate, isPrefixOf, - minimumBy) +import Data.Char (isLower, isUpper) +import Data.List (intercalate, minimumBy, + stripPrefix, uncons) import qualified Data.List.NonEmpty as NE import qualified Data.Map as Map +import Data.Maybe (mapMaybe) import Data.Ord (comparing) import Data.String (IsString) import qualified Data.Text as T @@ -154,15 +155,17 @@ pathModuleNames recorder state normFilePath filePath mdlPath <- liftIO $ makeAbsolute filePath logWith recorder Debug (AbsoluteFilePath mdlPath) - let prefixes = filter (`isPrefixOf` mdlPath) paths - pure (map (moduleNameFrom mdlPath) prefixes) + let suffixes = mapMaybe (`stripPrefix` mdlPath) paths + pure (map moduleNameFrom suffixes) where - moduleNameFrom mdlPath prefix = + moduleNameFrom = T.pack . intercalate "." + -- Do not suggest names whose components start from a lower-case char, + -- they are guaranteed to be malformed. + . filter (maybe False (isUpper . fst) . uncons) . splitDirectories - . drop (length prefix) - $ dropExtension mdlPath + . dropExtension -- | The module name, as stated in the module codeModuleName :: IdeState -> NormalizedFilePath -> IO (Maybe (Range, T.Text)) diff --git a/scripts/release/create-yaml-snippet.sh b/scripts/release/create-yaml-snippet.sh index d999ea3d92..2fb7413f82 100644 --- a/scripts/release/create-yaml-snippet.sh +++ b/scripts/release/create-yaml-snippet.sh @@ -5,7 +5,7 @@ set -o pipefail RELEASE=$1 -cd "gh-release-artifacts/${RELEASE}" +cd "gh-release-artifacts/haskell-language-server-${RELEASE}" cat < /dev/stdout $RELEASE: diff --git a/scripts/release/download-gh-artifacts.sh b/scripts/release/download-gh-artifacts.sh index b332464b15..fc6638f181 100644 --- a/scripts/release/download-gh-artifacts.sh +++ b/scripts/release/download-gh-artifacts.sh @@ -13,11 +13,11 @@ for com in gh gpg curl sha256sum ; do command -V ${com} >/dev/null 2>&1 done -[ ! -e "gh-release-artifacts/${RELEASE}" ] +[ ! -e "gh-release-artifacts/haskell-language-server-${RELEASE}" ] -mkdir -p "gh-release-artifacts/${RELEASE}" +mkdir -p "gh-release-artifacts/haskell-language-server-${RELEASE}" -cd "gh-release-artifacts/${RELEASE}" +cd "gh-release-artifacts/haskell-language-server-${RELEASE}" # github gh release download "$RELEASE" diff --git a/stack.yaml b/stack.yaml index d335049fca..7a0744226a 100644 --- a/stack.yaml +++ b/stack.yaml @@ -46,7 +46,6 @@ extra-deps: - hiedb-0.4.3.0 - implicit-hie-0.1.2.7 - implicit-hie-cradle-0.5.0.1 -- fourmolu-0.12.0.0 - algebraic-graphs-0.6.1 - retrie-1.2.2 - hw-fingertree-0.1.2.1