diff --git a/.github/actions/setup-build/action.yml b/.github/actions/setup-build/action.yml index c2d07d5228..eef0ed6ecb 100644 --- a/.github/actions/setup-build/action.yml +++ b/.github/actions/setup-build/action.yml @@ -7,7 +7,7 @@ inputs: cabal: description: "Cabal version" required: false - default: "3.14.2.0" + default: "3.16.1.0" os: description: "Operating system: Linux, Windows or macOS" required: true diff --git a/.github/workflows/supported-ghc-versions.json b/.github/workflows/supported-ghc-versions.json index 35a3bd4ac4..f5c1cc8a31 100644 --- a/.github/workflows/supported-ghc-versions.json +++ b/.github/workflows/supported-ghc-versions.json @@ -1 +1 @@ -["9.12", "9.10", "9.8", "9.6"] +["9.14", "9.12", "9.10", "9.8", "9.6"] diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index da40f259f1..e0eb8d5950 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -95,6 +95,12 @@ jobs: # 9.10.3 is broken on windows - os: windows-latest ghc: "9.10" + env: + # We choose a very short build directory, as we run into long path issues on windows. + # See cabal tracking issue https://github.com/haskell/cabal/issues/11395 + # We can't set the `--builddir` via `v2-configure` as cabal doesn't support this. + # https://github.com/haskell/cabal/issues/5271 + CABAL_ARGS: "--builddir b" steps: - uses: actions/checkout@v3 @@ -105,7 +111,7 @@ jobs: os: ${{ runner.os }} - name: Build - run: cabal build all + run: cabal build ${CABAL_ARGS} all - name: Set test options # See https://github.com/ocharles/tasty-rerun/issues/22 for why we need @@ -116,161 +122,161 @@ jobs: - if: matrix.test name: Test hls-graph - run: cabal test hls-graph + run: cabal test ${CABAL_ARGS} hls-graph - if: needs.pre_job.outputs.should_skip_ghcide != 'true' && matrix.test name: Test ghcide # run the tests without parallelism to avoid running out of memory - run: cabal test ghcide-tests || cabal test ghcide-tests + run: cabal test ${CABAL_ARGS} ghcide-tests || cabal test ${CABAL_ARGS} ghcide-tests - if: matrix.test name: Test hls-plugin-api - run: cabal test hls-plugin-api || cabal test hls-plugin-api + run: cabal test ${CABAL_ARGS} hls-plugin-api || cabal test ${CABAL_ARGS} hls-plugin-api - if: matrix.test name: Test func-test suite env: HLS_TEST_EXE: hls HLS_WRAPPER_TEST_EXE: hls-wrapper - run: cabal test func-test || cabal test func-test + run: cabal test ${CABAL_ARGS} func-test || cabal test ${CABAL_ARGS} func-test - if: matrix.test name: Test wrapper-test suite env: HLS_TEST_EXE: hls HLS_WRAPPER_TEST_EXE: hls-wrapper - run: cabal test wrapper-test + run: cabal test ${CABAL_ARGS} wrapper-test - if: matrix.test name: Test hls-refactor-plugin - run: cabal test hls-refactor-plugin-tests || cabal test hls-refactor-plugin-tests + run: cabal test ${CABAL_ARGS} hls-refactor-plugin-tests || cabal test ${CABAL_ARGS} hls-refactor-plugin-tests # TODO enable when it supports 9.10 - - if: matrix.test && matrix.ghc != '9.10' && matrix.ghc != '9.12' && matrix.ghc != '9.10.2' + - if: matrix.test && matrix.ghc != '9.10' && matrix.ghc != '9.12' && matrix.ghc != '9.14' && matrix.ghc != '9.10.2' name: Test hls-floskell-plugin - run: cabal test hls-floskell-plugin-tests || cabal test hls-floskell-plugin-tests + run: cabal test ${CABAL_ARGS} hls-floskell-plugin-tests || cabal test ${CABAL_ARGS} hls-floskell-plugin-tests - if: matrix.test name: Test hls-class-plugin - run: cabal test hls-class-plugin-tests || cabal test hls-class-plugin-tests + run: cabal test ${CABAL_ARGS} hls-class-plugin-tests || cabal test ${CABAL_ARGS} hls-class-plugin-tests - if: matrix.test name: Test hls-pragmas-plugin - run: cabal test hls-pragmas-plugin-tests || cabal test hls-pragmas-plugin-tests + run: cabal test ${CABAL_ARGS} hls-pragmas-plugin-tests || cabal test ${CABAL_ARGS} hls-pragmas-plugin-tests - if: matrix.test name: Test hls-eval-plugin - run: cabal test hls-eval-plugin-tests || cabal test hls-eval-plugin-tests + run: cabal test ${CABAL_ARGS} hls-eval-plugin-tests || cabal test ${CABAL_ARGS} hls-eval-plugin-tests # TODO enable when it supports 9.10 - - if: matrix.test && matrix.ghc != '9.10' && matrix.ghc != '9.12' && matrix.ghc != '9.10.2' + - if: matrix.test && matrix.ghc != '9.10' && matrix.ghc != '9.12' && matrix.ghc != '9.14' && matrix.ghc != '9.10.2' name: Test hls-splice-plugin - run: cabal test hls-splice-plugin-tests || cabal test hls-splice-plugin-tests + run: cabal test ${CABAL_ARGS} hls-splice-plugin-tests || cabal test ${CABAL_ARGS} hls-splice-plugin-tests - - if: matrix.test && matrix.ghc != '9.12' + - if: matrix.test && matrix.ghc != '9.12' && matrix.ghc != '9.14' name: Test hls-stan-plugin - run: cabal test hls-stan-plugin-tests || cabal test hls-stan-plugin-tests + run: cabal test ${CABAL_ARGS} hls-stan-plugin-tests || cabal test ${CABAL_ARGS} hls-stan-plugin-tests - - if: matrix.test + - if: matrix.test && matrix.ghc != '9.14' name: Test hls-stylish-haskell-plugin - run: cabal test hls-stylish-haskell-plugin-tests || cabal test hls-stylish-haskell-plugin-tests + run: cabal test ${CABAL_ARGS} hls-stylish-haskell-plugin-tests || cabal test ${CABAL_ARGS} hls-stylish-haskell-plugin-tests - - if: matrix.test + - if: matrix.test && matrix.ghc != '9.14' name: Test hls-ormolu-plugin - run: cabal test hls-ormolu-plugin-tests || cabal test hls-ormolu-plugin-tests + run: cabal test ${CABAL_ARGS} hls-ormolu-plugin-tests || cabal test ${CABAL_ARGS} hls-ormolu-plugin-tests - - if: matrix.test + - if: matrix.test && matrix.ghc != '9.14' name: Test hls-fourmolu-plugin - run: cabal test hls-fourmolu-plugin-tests || cabal test hls-fourmolu-plugin-tests + run: cabal test ${CABAL_ARGS} hls-fourmolu-plugin-tests || cabal test ${CABAL_ARGS} hls-fourmolu-plugin-tests - if: matrix.test name: Test hls-explicit-imports-plugin test suite - run: cabal test hls-explicit-imports-plugin-tests || cabal test hls-explicit-imports-plugin-tests + run: cabal test ${CABAL_ARGS} hls-explicit-imports-plugin-tests || cabal test ${CABAL_ARGS} hls-explicit-imports-plugin-tests - if: matrix.test name: Test hls-call-hierarchy-plugin test suite - run: cabal test hls-call-hierarchy-plugin-tests || cabal test hls-call-hierarchy-plugin-tests + run: cabal test ${CABAL_ARGS} hls-call-hierarchy-plugin-tests || cabal test ${CABAL_ARGS} hls-call-hierarchy-plugin-tests - if: matrix.test && matrix.os != 'windows-latest' name: Test hls-rename-plugin test suite - run: cabal test hls-rename-plugin-tests || cabal test hls-rename-plugin-tests + run: cabal test ${CABAL_ARGS} hls-rename-plugin-tests || cabal test ${CABAL_ARGS} hls-rename-plugin-tests - # TODO enable when it supports 9.10 - - if: matrix.test && matrix.ghc != '9.10' && matrix.ghc != '9.10.2' + # Hlint will never work on GHC 9.10 + - if: matrix.test && matrix.ghc != '9.10' && matrix.ghc != '9.14' && matrix.ghc != '9.10.2' name: Test hls-hlint-plugin test suite - run: cabal test hls-hlint-plugin-tests || cabal test hls-hlint-plugin-tests + run: cabal test ${CABAL_ARGS} hls-hlint-plugin-tests || cabal test ${CABAL_ARGS} hls-hlint-plugin-tests - if: matrix.test name: Test hls-module-name-plugin test suite - run: cabal test hls-module-name-plugin-tests || cabal test hls-module-name-plugin-tests + run: cabal test ${CABAL_ARGS} hls-module-name-plugin-tests || cabal test ${CABAL_ARGS} hls-module-name-plugin-tests - if: matrix.test name: Test hls-alternate-number-format-plugin test suite - run: cabal test hls-alternate-number-format-plugin-tests || cabal test hls-alternate-number-format-plugin-tests + run: cabal test ${CABAL_ARGS} hls-alternate-number-format-plugin-tests || cabal test ${CABAL_ARGS} hls-alternate-number-format-plugin-tests - if: matrix.test name: Test hls-qualify-imported-names-plugin test suite - run: cabal test hls-qualify-imported-names-plugin-tests || cabal test hls-qualify-imported-names-plugin-tests + run: cabal test ${CABAL_ARGS} hls-qualify-imported-names-plugin-tests || cabal test ${CABAL_ARGS} hls-qualify-imported-names-plugin-tests - if: matrix.test name: Test hls-code-range-plugin test suite - run: cabal test hls-code-range-plugin-tests || cabal test hls-code-range-plugin-tests + run: cabal test ${CABAL_ARGS} hls-code-range-plugin-tests || cabal test ${CABAL_ARGS} hls-code-range-plugin-tests - if: matrix.test name: Test hls-change-type-signature test suite - run: cabal test hls-change-type-signature-plugin-tests || cabal test hls-change-type-signature-plugin-tests + run: cabal test ${CABAL_ARGS} hls-change-type-signature-plugin-tests || cabal test ${CABAL_ARGS} hls-change-type-signature-plugin-tests - if: matrix.test name: Test hls-gadt-plugin test suit - run: cabal test hls-gadt-plugin-tests || cabal test hls-gadt-plugin-tests + run: cabal test ${CABAL_ARGS} hls-gadt-plugin-tests || cabal test ${CABAL_ARGS} hls-gadt-plugin-tests - if: matrix.test name: Test hls-explicit-fixity-plugin test suite - run: cabal test hls-explicit-fixity-plugin-tests || cabal test hls-explicit-fixity-plugin-tests + run: cabal test ${CABAL_ARGS} hls-explicit-fixity-plugin-tests || cabal test ${CABAL_ARGS} hls-explicit-fixity-plugin-tests - if: matrix.test name: Test hls-explicit-record-fields-plugin test suite - run: cabal test hls-explicit-record-fields-plugin-tests || cabal test hls-explicit-record-fields-plugin-tests + run: cabal test ${CABAL_ARGS} hls-explicit-record-fields-plugin-tests || cabal test ${CABAL_ARGS} hls-explicit-record-fields-plugin-tests # versions need to be limited since the tests depend on cabal-fmt which only builds with ghc <9.10 - - if: matrix.test && matrix.ghc != '9.10' && matrix.ghc != '9.12' && matrix.ghc != '9.10.2' + - if: matrix.test && matrix.ghc != '9.10' && matrix.ghc != '9.12' && matrix.ghc != '9.14' && matrix.ghc != '9.10.2' name: Test hls-cabal-fmt-plugin test suite - run: cabal test hls-cabal-fmt-plugin-tests --flag=isolateCabalfmtTests || cabal test hls-cabal-fmt-plugin-tests --flag=isolateCabalfmtTests + run: cabal test ${CABAL_ARGS} hls-cabal-fmt-plugin-tests --flag=isolateCabalfmtTests || cabal test ${CABAL_ARGS} hls-cabal-fmt-plugin-tests --flag=isolateCabalfmtTests - - if: matrix.test && matrix.ghc != '9.12' + - if: matrix.test && matrix.ghc != '9.12' && matrix.ghc != '9.14' name: Test hls-cabal-gild-plugin test suite - run: cabal test hls-cabal-gild-plugin-tests --flag=isolateCabalGildTests || cabal test hls-cabal-gild-plugin-tests --flag=isolateCabalGildTests + run: cabal test ${CABAL_ARGS} hls-cabal-gild-plugin-tests --flag=isolateCabalGildTests || cabal test ${CABAL_ARGS} hls-cabal-gild-plugin-tests --flag=isolateCabalGildTests - if: matrix.test name: Test hls-cabal-plugin test suite - run: cabal test hls-cabal-plugin-tests || cabal test hls-cabal-plugin-tests + run: cabal test ${CABAL_ARGS} hls-cabal-plugin-tests || cabal test ${CABAL_ARGS} hls-cabal-plugin-tests # TODO enable when it supports 9.10 - - if: matrix.test && matrix.ghc != '9.10' && matrix.ghc != '9.12' && matrix.ghc != '9.10.2' + - if: matrix.test && matrix.ghc != '9.10' && matrix.ghc != '9.12' && matrix.ghc != '9.14' && matrix.ghc != '9.10.2' name: Test hls-retrie-plugin test suite - run: cabal test hls-retrie-plugin-tests || cabal test hls-retrie-plugin-tests + run: cabal test ${CABAL_ARGS} hls-retrie-plugin-tests || cabal test ${CABAL_ARGS} hls-retrie-plugin-tests - if: matrix.test name: Test hls-overloaded-record-dot-plugin test suite - run: cabal test hls-overloaded-record-dot-plugin-tests || cabal test hls-overloaded-record-dot-plugin-tests + run: cabal test ${CABAL_ARGS} hls-overloaded-record-dot-plugin-tests || cabal test ${CABAL_ARGS} hls-overloaded-record-dot-plugin-tests - if: matrix.test name: Test hls-semantic-tokens-plugin test suite - run: cabal test hls-semantic-tokens-plugin-tests || cabal test hls-semantic-tokens-plugin-tests + run: cabal test ${CABAL_ARGS} hls-semantic-tokens-plugin-tests || cabal test ${CABAL_ARGS} hls-semantic-tokens-plugin-tests - if: matrix.test name: Test hls-notes-plugin test suite - run: cabal test hls-notes-plugin-tests || cabal test hls-notes-plugin-tests + run: cabal test ${CABAL_ARGS} hls-notes-plugin-tests || cabal test ${CABAL_ARGS} hls-notes-plugin-tests # The plugin tutorial is only compatible with 9.6 and 9.8. # No particular reason, just to avoid excessive CPP. - - if: matrix.test && matrix.ghc != '9.4' && matrix.ghc != '9.10' && matrix.ghc != '9.12' && matrix.ghc != '9.10.2' + - if: matrix.test && matrix.ghc != '9.4' && matrix.ghc != '9.10' && matrix.ghc != '9.12' && matrix.ghc != '9.14' && matrix.ghc != '9.10.2' name: Compile the plugin-tutorial - run: cabal build plugin-tutorial + run: cabal build ${CABAL_ARGS} plugin-tutorial - if: matrix.test name: Test hls-signature-help-plugin test suite - run: cabal test hls-signature-help-plugin-tests || cabal test hls-signature-help-plugin-tests + run: cabal test ${CABAL_ARGS} hls-signature-help-plugin-tests || cabal test ${CABAL_ARGS} hls-signature-help-plugin-tests test_post_job: if: always() diff --git a/cabal.project b/cabal.project index 8d8bd080af..e88910bffe 100644 --- a/cabal.project +++ b/cabal.project @@ -7,7 +7,12 @@ packages: ./hls-test-utils -index-state: 2025-08-08T12:31:54Z +index-state: 2026-01-01T00:00:00Z + +source-repository-package + type: git + location: https://github.com/snowleopard/alga + tag: d4e43fb42db05413459fb2df493361d5a666588a tests: True test-show-details: direct @@ -56,3 +61,81 @@ if impl(ghc >= 9.11) allow-newer: cabal-install-parsers:base, cabal-install-parsers:time, + +if impl(ghc >= 9.14) + allow-newer: + scientific:containers, + lsp-types:containers, + lsp:containers, + indexed-traversable:containers, + foldl:containers, + deferred-folds:containers, + quickcheck-instances:containers, + hashable:containers, + dependent-map:containers, + aeson:containers, + semialign:containers, + lsp-test:containers, + haddock-library:base, + hiedb:ghc, + hie-bios:ghc, + integer-logarithms:ghc-bignum, + hashable:ghc-bignum, + string-interpolate:template-haskell, + haskell-src-meta:template-haskell, + th-orphans:template-haskell, + th-lift:template-haskell, + th-expand-syns:template-haskell, + tasty-hspec:base, + hsc2hs:base, + primitive:base, + tagged:template-haskell, + indexed-traversable:base, + text-short:base, + text-short:template-haskell, + bifunctors:template-haskell, + th-abstraction:template-haskell, + scientific:base, + integer-logarithms:base, + splitmix:base, + quickcheck-instances:base, + time-compat:base, + time-compat:time, + these:base, + assoc:base, + data-fix:base, + OneTuple:base, + some:base, + boring:base, + indexed-traversable-instances:base, + lsp-types:template-haskell, + uuid-types:template-haskell, + parallel:base, + lens:template-haskell, + free:template-haskell, + hiedb:base, + hie-compat:base, + hie-bios:time, + hie-bios:template-haskell, + hashable:base, + unordered-containers:template-haskell, + ghc-trace-events:base, + constraints-extras:template-haskell, + co-log-core:base, + async:base, + aeson:time, + text-iso8601:time, + semialign:base, + integer-conversion:base, + generically:base, + aeson:template-haskell, + scientific:template-haskell, + th-compat:template-haskell, + lsp-test:time, + ghc-lib-parser:base, + lukko:base, + binary-instances:base, + binary-orphans:base, + generic-deriving:template-haskell, + generic-deriving:containers, + cabal-install-parsers:containers, diff --git a/ghcide-test/data/multi/cabal.project b/ghcide-test/data/multi/cabal.project index 317a89138e..d5f2532ba1 100644 --- a/ghcide-test/data/multi/cabal.project +++ b/ghcide-test/data/multi/cabal.project @@ -1,3 +1,6 @@ packages: a b c -allow-newer: base +allow-newer: async:base, + hashable:base, + hashable:template-haskell, + hashable:ghc-bignum, diff --git a/ghcide-test/exe/FindDefinitionAndHoverTests.hs b/ghcide-test/exe/FindDefinitionAndHoverTests.hs index 459fb5f6f7..05a129d983 100644 --- a/ghcide-test/exe/FindDefinitionAndHoverTests.hs +++ b/ghcide-test/exe/FindDefinitionAndHoverTests.hs @@ -151,7 +151,7 @@ tests = let aaaL11 = Position 11 1 ; aaaType = [ExpectHoverTextRegex "Go to \\[TypeConstructor\\]\\(.*GotoHover\\.hs#L8\\)"] dcL7 = Position 11 11 ; tcDC = [mkR 7 23 9 16] dcL12 = Position 16 11 ; - xtcL5 = Position 9 11 ; xtc = [ExpectHoverText ["Int", "Defined in ", "GHC.Types", "ghc-prim"]] + xtcL5 = Position 9 11 ; xtc = [ExpectHoverText ["Int", "Defined in ", if ghcVersion >= GHC914 then "GHC.Internal.Types" else "GHC.Types", if ghcVersion >= GHC914 then "ghc-internal" else "ghc-prim"]] tcL6 = Position 10 11 ; tcData = [mkR 7 0 9 16, ExpectHoverText ["TypeConstructor", "GotoHover.hs:8:1"]] vvL16 = Position 20 12 ; vv = [mkR 20 4 20 6] opL16 = Position 20 15 ; op = [mkR 21 2 21 4] @@ -188,7 +188,7 @@ tests = let innL48 = Position 52 5 ; innSig = [ExpectHoverText ["inner"], mkR 53 2 53 7]; innSig' = [ExpectHoverText ["inner", "Char"], mkR 49 2 49 7] holeL60 = Position 62 7 ; hleInfo = [ExpectHoverText ["_ ::"]] holeL65 = Position 65 8 ; hleInfo2 = [ExpectHoverText ["_ :: a -> Maybe a"]] - cccL17 = Position 17 16 ; docLink = [ExpectHoverTextRegex "\\*Defined in 'GHC.Types'\\* \\*\\(ghc-prim-[0-9.]+\\)\\*\n\n"] + cccL17 = Position 17 16 ; docLink = [ExpectHoverTextRegex $ if ghcVersion >= GHC914 then "\\*Defined in 'GHC.Internal.Types'\\* \\*\\(ghc-internal-[0-9.]+\\)\\*\n\n" else "\\*Defined in 'GHC.Types'\\* \\*\\(ghc-prim-[0-9.]+\\)\\*\n\n"] imported = Position 56 13 ; importedSig = getDocUri "Foo.hs" >>= \foo -> return [ExpectHoverText ["foo", "Foo", "Haddock"], mkL foo 5 0 5 3] reexported = Position 55 14 reexportedSig = getDocUri "Bar.hs" >>= \bar -> return [ExpectHoverText ["Bar", "Bar", "Haddock"], mkL bar 3 0 3 14] diff --git a/ghcide/session-loader/Development/IDE/Session.hs b/ghcide/session-loader/Development/IDE/Session.hs index dde1cfdea5..cfc5fc9654 100644 --- a/ghcide/session-loader/Development/IDE/Session.hs +++ b/ghcide/session-loader/Development/IDE/Session.hs @@ -885,7 +885,12 @@ newComponentCache recorder exts _cfp hsc_env old_cis new_cis = do hscEnv' <- -- Set up a multi component session with the other units on GHC 9.4 Compat.initUnits dfs hsc_env +#if MIN_VERSION_ghc(9,13,0) + let closure_errs_raw = checkHomeUnitsClosed' (hsc_unit_env hscEnv') (hsc_all_home_unit_ids hscEnv') + closure_errs = concatMap (Compat.bagToList . Compat.getMessages) closure_errs_raw +#else let closure_errs = maybeToList $ checkHomeUnitsClosed' (hsc_unit_env hscEnv') (hsc_all_home_unit_ids hscEnv') +#endif closure_err_to_multi_err err = ideErrorWithSource (Just "cradle") (Just DiagnosticSeverity_Warning) _cfp diff --git a/ghcide/src/Development/IDE/Core/Compile.hs b/ghcide/src/Development/IDE/Core/Compile.hs index 48439e2ff3..2806818b9c 100644 --- a/ghcide/src/Development/IDE/Core/Compile.hs +++ b/ghcide/src/Development/IDE/Core/Compile.hs @@ -149,6 +149,15 @@ import GHC.Driver.Env (hsc_all_home_unit import GHC.Iface.Ext.Types (NameEntityInfo) #endif +#if MIN_VERSION_ghc(9,13,0) +import GHC.Driver.Env (hscInsertHPT, setModuleGraph) +import GHC.Unit.Home.Graph (UnitEnvGraph(..), unitEnv_assocs) +import GHC.Unit.Home.PackageTable (hptInternalTableRef, hptInternalTableFromRef) +import GHC.Unit.Module.ModIface (IfaceTopEnv(..)) +import GHC.Types.Avail (emptyDetOrdAvails) +import GHC.Types.Basic (ImportLevel(..)) +#endif + #if MIN_VERSION_ghc(9,12,0) import Development.IDE.Import.FindImports #endif @@ -311,7 +320,11 @@ captureSplicesAndDeps TypecheckHelpers{..} env k = do , moduleUnitId mod `elem` home_unit_ids -- Only care about stuff from the home package set ] home_unit_ids = +#if MIN_VERSION_ghc(9,13,0) + map fst (unitEnv_assocs $ hsc_HUG hsc_env) +#else map fst (hugElts $ hsc_HUG hsc_env) +#endif mods_transitive = getTransitiveMods hsc_env needed_mods -- If we don't support multiple home units, ModuleNames are sufficient because all the units will be the same @@ -323,7 +336,11 @@ captureSplicesAndDeps TypecheckHelpers{..} env k = do | installedMod <- mods_transitive_list , let file = fromJust $ lookupModuleFile (installedMod { moduleUnit = RealUnit (Definite $ moduleUnit installedMod) }) moduleLocs ] +#if MIN_VERSION_ghc(9,13,0) + ; hsc_env' <- loadModulesHome (map linkableHomeMod lbs) hsc_env +#else ; let hsc_env' = loadModulesHome (map linkableHomeMod lbs) hsc_env +#endif {- load it -} #if MIN_VERSION_ghc(9,11,0) @@ -333,7 +350,11 @@ captureSplicesAndDeps TypecheckHelpers{..} env k = do #else ; (fv_hvs, lbss, pkgs) <- loadDecls (hscInterp hsc_env') hsc_env' srcspan bcos #endif +#if MIN_VERSION_ghc(9,13,0) + ; let hval = (expectJust $ lookup (idName binding_id) fv_hvs, lbss, pkgs) +#else ; let hval = (expectJust "hscCompileCoreExpr'" $ lookup (idName binding_id) fv_hvs, lbss, pkgs) +#endif ; modifyIORef' var (flip extendModuleEnvList [(mi_module $ hm_iface hm, linkableHash lb) | lb <- lbs, let hm = linkableHomeMod lb]) ; return hval } @@ -351,10 +372,19 @@ captureSplicesAndDeps TypecheckHelpers{..} env k = do -- Compute the transitive set of linkables required getTransitiveMods hsc_env needed_mods +#if MIN_VERSION_ghc(9,13,0) + = Set.unions (Set.fromList (map moduleToNodeKey mods) : [ Set.fromList $ map mkNodeKey dep + | m <- mods + , Just dep <- + [mgReachable (hsc_mod_graph hsc_env) (moduleToNodeKey m)] + ]) + where mods = nonDetEltsUniqSet needed_mods -- OK because we put them into a set immediately after +#else = Set.unions (Set.fromList (map moduleToNodeKey mods) : [ dep | m <- mods , Just dep <- [Map.lookup (moduleToNodeKey m) (mgTransDeps (hsc_mod_graph hsc_env))] ]) where mods = nonDetEltsUniqSet needed_mods -- OK because we put them into a set immediately after +#endif -- | Add a Hook to the DynFlags which captures and returns the -- typechecked splices before they are run. This information @@ -458,7 +488,9 @@ mkHiFileResultNoCompile session tcm = do iface' <- mkIfaceTc hsc_env_tmp sf details ms Nothing tcGblEnv -- See Note [Clearing mi_globals after generating an iface] let iface = iface' -#if MIN_VERSION_ghc(9,11,0) +#if MIN_VERSION_ghc(9,13,0) + & set_mi_top_env (IfaceTopEnv emptyDetOrdAvails []) +#elif MIN_VERSION_ghc(9,11,0) & set_mi_top_env Nothing & set_mi_usages (filterUsages (mi_usages iface')) #else @@ -483,6 +515,14 @@ mkHiFileResultCompile se session' tcm simplified_guts = catchErrs $ do (guts, details) <- tidyProgram tidy_opts simplified_guts pure (details, guts) +#if MIN_VERSION_ghc(9,13,0) + partial_iface <- mkPartialIface session + (cg_binds guts) + details + ms + (tcg_import_decls (tmrTypechecked tcm)) + simplified_guts +#else let !partial_iface = force $ mkPartialIface session (cg_binds guts) details @@ -491,6 +531,7 @@ mkHiFileResultCompile se session' tcm simplified_guts = catchErrs $ do (tcg_import_decls (tmrTypechecked tcm)) #endif simplified_guts +#endif final_iface' <- mkFullIface session partial_iface Nothing Nothing @@ -499,7 +540,9 @@ mkHiFileResultCompile se session' tcm simplified_guts = catchErrs $ do #endif -- See Note [Clearing mi_globals after generating an iface] let final_iface = final_iface' -#if MIN_VERSION_ghc(9,11,0) +#if MIN_VERSION_ghc(9,13,0) + & set_mi_top_env (IfaceTopEnv emptyDetOrdAvails []) +#elif MIN_VERSION_ghc(9,11,0) & set_mi_top_env Nothing & set_mi_usages (filterUsages (mi_usages final_iface')) #else @@ -532,9 +575,19 @@ mkHiFileResultCompile se session' tcm simplified_guts = catchErrs $ do traceIO $ "Verifying " ++ core_fp let CgGuts{cg_binds = unprep_binds, cg_tycons = tycons } = guts mod = ms_mod ms - data_tycons = filter isDataTyCon tycons + data_tycons = filter isAlgTyCon tycons CgGuts{cg_binds = unprep_binds'} <- coreFileToCgGuts session final_iface details core cp_cfg <- initCorePrepConfig session +#if MIN_VERSION_ghc(9,13,0) + let corePrep = corePrepPgm + (hsc_logger session) cp_cfg (initCorePrepPgmConfig (hsc_dflags session) (interactiveInScope $ hsc_IC session)) + mod + + -- Run corePrep first as we want to test the final version of the program that will + -- get translated to STG/Bytecode + prepd_binds + <- corePrep unprep_binds +#else let corePrep = corePrepPgm (hsc_logger session) cp_cfg (initCorePrepPgmConfig (hsc_dflags session) (interactiveInScope $ hsc_IC session)) mod (ms_location ms) @@ -543,8 +596,14 @@ mkHiFileResultCompile se session' tcm simplified_guts = catchErrs $ do -- get translated to STG/Bytecode prepd_binds <- corePrep unprep_binds data_tycons +#endif +#if MIN_VERSION_ghc(9,13,0) + prepd_binds' + <- corePrep unprep_binds' +#else prepd_binds' <- corePrep unprep_binds' data_tycons +#endif let binds = noUnfoldings $ (map flattenBinds . (:[])) prepd_binds binds' = noUnfoldings $ (map flattenBinds . (:[])) prepd_binds' @@ -987,6 +1046,31 @@ mergeEnvs :: HscEnv -> [HscEnv] -> IO HscEnv mergeEnvs env mg dep_info ms extraMods envs = do +#if MIN_VERSION_ghc(9,13,0) + newHug <- sequence $ foldl' mergeHUG (pure <$> hsc_HUG env) (map (fmap pure . hsc_HUG) envs) + let hsc_env' = setModuleGraph mg $ (hscUpdateHUG (const newHug) env){ + hsc_FC = (hsc_FC env) + { addToFinderCache = \im val -> + if moduleUnit im `elem` hsc_all_home_unit_ids env + then pure () + else addToFinderCache (hsc_FC env) im val + , lookupFinderCache = \im -> + if moduleUnit im `elem` hsc_all_home_unit_ids env + then case lookupModuleFile (im { moduleUnit = RealUnit (Definite $ moduleUnit im) }) dep_info of + Nothing -> pure Nothing + Just fs -> let ml = fromJust $ do + id <- lookupPathToId (depPathIdMap dep_info) fs + artifactModLocation (idToModLocation (depPathIdMap dep_info) id) +#if MIN_VERSION_ghc(9,13,0) + in pure $ Just $ InstalledFound ml +#else + in pure $ Just $ InstalledFound ml im +#endif + else lookupFinderCache (hsc_FC env) im + } + } + loadModulesHome extraMods hsc_env' +#else return $! loadModulesHome extraMods $ let newHug = foldl' mergeHUG (hsc_HUG env) (map hsc_HUG envs) in (hscUpdateHUG (const newHug) env){ @@ -1007,8 +1091,23 @@ mergeEnvs env mg dep_info ms extraMods envs = do else lookupFinderCache (hsc_FC env) gwib } } +#endif where +#if MIN_VERSION_ghc(9,13,0) + mergeHUG :: UnitEnvGraph (IO HomeUnitEnv) -> UnitEnvGraph (IO HomeUnitEnv) -> UnitEnvGraph (IO HomeUnitEnv) + mergeHUG (UnitEnvGraph a) (UnitEnvGraph b) = UnitEnvGraph $ Map.unionWith mergeHUE a b + mergeHUE a b = do + a_v <- a + hpt_b <- readIORef . hptInternalTableRef . homeUnitEnv_hpt =<< b + hpt_a <- readIORef . hptInternalTableRef . homeUnitEnv_hpt $ a_v + result <- hptInternalTableFromRef =<< (newIORef $! mergeUDFM hpt_a hpt_b) + return $! a_v { homeUnitEnv_hpt = result } + mergeUDFM = plusUDFM_C combineModules + combineModules a b + | HsSrcFile <- mi_hsc_src (hm_iface a) = a + | otherwise = b +#else mergeHUG (UnitEnvGraph a) (UnitEnvGraph b) = UnitEnvGraph $ Map.unionWith mergeHUE a b mergeHUE a b = a { homeUnitEnv_hpt = mergeUDFM (homeUnitEnv_hpt a) (homeUnitEnv_hpt b) } mergeUDFM = plusUDFM_C combineModules @@ -1016,6 +1115,7 @@ mergeEnvs env mg dep_info ms extraMods envs = do combineModules a b | HsSrcFile <- mi_hsc_src (hm_iface a) = a | otherwise = b +#endif #else mergeEnvs :: HscEnv @@ -1112,8 +1212,14 @@ getModSummaryFromImports env fp _modTime mContents = do rn_pkg_qual = renameRawPkgQual (hsc_unit_env ppEnv) rn_imps = fmap (\(pk, lmn@(L _ mn)) -> (rn_pkg_qual mn pk, lmn)) +#if MIN_VERSION_ghc(9,13,0) + -- In GHC 9.13+, ms_srcimps is just [Located ModuleName] and ms_textual_imps includes ImportLevel + srcImports = map snd $ rn_imps $ map convImport src_idecls + textualImports = map (\(pk, lmn) -> (NormalLevel, pk, lmn)) $ rn_imps $ map convImport (implicit_imports ++ ordinary_imps) +#else srcImports = rn_imps $ map convImport src_idecls textualImports = rn_imps $ map convImport (implicit_imports ++ ordinary_imps) +#endif ghc_prim_import = not (null _ghc_prim_imports) @@ -1135,7 +1241,9 @@ getModSummaryFromImports env fp _modTime mContents = do { ms_mod = modl , ms_hie_date = Nothing , ms_dyn_obj_date = Nothing +#if !MIN_VERSION_ghc(9,13,0) , ms_ghc_prim_import = ghc_prim_import +#endif , ms_hs_hash = _src_hash , ms_hsc_src = sourceType @@ -1160,12 +1268,24 @@ getModSummaryFromImports env fp _modTime mContents = do computeFingerprint opts ModSummary{..} = do fingerPrintImports <- fingerprintFromPut $ do put $ Util.uniq $ moduleNameFS $ moduleName ms_mod +#if MIN_VERSION_ghc(9,13,0) + -- In GHC 9.13+, ms_srcimps is [Located ModuleName] and ms_textual_imps is [(ImportLevel, PkgQual, Located ModuleName)] + forM_ ms_srcimps $ \m -> do + put $ Util.uniq $ moduleNameFS $ unLoc m + forM_ ms_textual_imps $ \(_lvl, mb_p, m) -> do + put $ Util.uniq $ moduleNameFS $ unLoc m + case mb_p of + G.NoPkgQual -> pure () + G.ThisPkg uid -> put $ getKey $ getUnique uid + G.OtherPkg uid -> put $ getKey $ getUnique uid +#else forM_ (ms_srcimps ++ ms_textual_imps) $ \(mb_p, m) -> do put $ Util.uniq $ moduleNameFS $ unLoc m case mb_p of G.NoPkgQual -> pure () G.ThisPkg uid -> put $ getKey $ getUnique uid G.OtherPkg uid -> put $ getKey $ getUnique uid +#endif return $! Util.fingerprintFingerprints $ [ Util.fingerprintString fp , fingerPrintImports @@ -1421,7 +1541,11 @@ loadInterface session ms linkableNeeded RecompilationInfo{..} = do -- ncu and read_dflags are only used in GHC >= 9.4 let _ncu = hsc_NC sessionWithMsDynFlags _read_dflags = hsc_dflags sessionWithMsDynFlags +#if MIN_VERSION_ghc(9,13,0) + read_result <- liftIO $ readIface (hsc_hooks sessionWithMsDynFlags) (hsc_logger sessionWithMsDynFlags) _read_dflags _ncu mod iface_file +#else read_result <- liftIO $ readIface _read_dflags _ncu mod iface_file +#endif case read_result of Util.Failed{} -> return Nothing -- important to call `shareUsages` here before checkOldIface @@ -1445,9 +1569,13 @@ loadInterface session ms linkableNeeded RecompilationInfo{..} = do (Just iface, UpToDate) -> do details <- liftIO $ mkDetailsFromIface sessionWithMsDynFlags iface -- parse the runtime dependencies from the annotations - let runtime_deps - | not (mi_used_th iface) = emptyModuleEnv - | otherwise = parseRuntimeDeps (md_anns details) + let runtime_deps = +#if MIN_VERSION_ghc(9,13,0) + parseRuntimeDeps (md_anns details) +#else + if not (mi_used_th iface) then emptyModuleEnv + else parseRuntimeDeps (md_anns details) +#endif -- Peform the fine grained recompilation check for TH maybe_recomp <- checkLinkableDependencies get_linkable_hashes get_module_graph runtime_deps case maybe_recomp of @@ -1517,18 +1645,30 @@ showReason (NeedsRecompile s) = printWithoutUniques s mkDetailsFromIface :: HscEnv -> ModIface -> IO ModDetails mkDetailsFromIface session iface = do fixIO $ \details -> do +#if MIN_VERSION_ghc(9,13,0) + hscInsertHPT (HomeModInfo iface details emptyHomeModInfoLinkable) session + initIfaceLoad session (typecheckIface iface) +#else let !hsc' = hscUpdateHPT (\hpt -> addToHpt hpt (moduleName $ mi_module iface) (HomeModInfo iface details emptyHomeModInfoLinkable)) session initIfaceLoad hsc' (typecheckIface iface) +#endif coreFileToCgGuts :: HscEnv -> ModIface -> ModDetails -> CoreFile -> IO CgGuts coreFileToCgGuts session iface details core_file = do + let this_mod = mi_module iface + types_var <- newIORef (md_types details) +#if MIN_VERSION_ghc(9,13,0) + let hsc_env' = session { + hsc_type_env_vars = knotVarsFromModuleEnv (mkModuleEnv [(this_mod, types_var)]) + } + hscInsertHPT (HomeModInfo iface details emptyHomeModInfoLinkable) hsc_env' +#else let act hpt = addToHpt hpt (moduleName this_mod) (HomeModInfo iface details emptyHomeModInfoLinkable) - this_mod = mi_module iface - types_var <- newIORef (md_types details) - let hsc_env' = hscUpdateHPT act (session { + hsc_env' = hscUpdateHPT act (session { hsc_type_env_vars = knotVarsFromModuleEnv (mkModuleEnv [(this_mod, types_var)]) }) +#endif core_binds <- initIfaceCheck (text "l") hsc_env' $ typecheckCoreFile this_mod types_var core_file -- Implicit binds aren't saved, so we need to regenerate them ourselves. let _implicit_binds = concatMap getImplicitBinds tyCons -- only used if GHC < 9.6 @@ -1615,7 +1755,15 @@ pathToModuleName = mkModuleName . map rep -- error out when we don't find it setNonHomeFCHook :: HscEnv -> HscEnv setNonHomeFCHook hsc_env = -#if MIN_VERSION_ghc(9,11,0) +#if MIN_VERSION_ghc(9,13,0) + hsc_env { hsc_FC = (hsc_FC hsc_env) + { lookupFinderCache = \im -> + if moduleUnit im `elem` hsc_all_home_unit_ids hsc_env + then pure (Just $ InstalledNotFound [] Nothing) + else lookupFinderCache (hsc_FC hsc_env) im + } + } +#elif MIN_VERSION_ghc(9,11,0) hsc_env { hsc_FC = (hsc_FC hsc_env) { lookupFinderCache = \m@(GWIB im _) -> if moduleUnit im `elem` hsc_all_home_unit_ids hsc_env diff --git a/ghcide/src/Development/IDE/Core/Preprocessor.hs b/ghcide/src/Development/IDE/Core/Preprocessor.hs index b3614d89ad..22e7b8a344 100644 --- a/ghcide/src/Development/IDE/Core/Preprocessor.hs +++ b/ghcide/src/Development/IDE/Core/Preprocessor.hs @@ -30,6 +30,9 @@ import Development.IDE.Types.Location import qualified GHC.LanguageExtensions as LangExt import qualified GHC.Runtime.Loader as Loader import GHC.Utils.Logger (LogFlags (..)) +#if MIN_VERSION_ghc(9,13,0) +import GHC.Driver.Config.Parser (supportedLanguagePragmas) +#endif import System.FilePath import System.IO.Extra @@ -144,12 +147,21 @@ parsePragmasIntoHscEnv -> Util.StringBuffer -> IO (Either [FileDiagnostic] ([String], HscEnv)) parsePragmasIntoHscEnv env fp contents = catchSrcErrors dflags0 "pragmas" $ do +#if MIN_VERSION_ghc(9,13,0) + let supportedExts = supportedLanguagePragmas dflags0 + let (_warns,opts) = getOptions (initParserOpts dflags0) supportedExts contents fp +#else let (_warns,opts) = getOptions (initParserOpts dflags0) contents fp +#endif -- Force bits that might keep the dflags and stringBuffer alive unnecessarily evaluate $ rnf opts +#if MIN_VERSION_ghc(9,13,0) + (dflags, _, _) <- parseDynamicFilePragma (hsc_logger env) dflags0 opts +#else (dflags, _, _) <- parseDynamicFilePragma dflags0 opts +#endif hsc_env' <- Loader.initializePlugins (hscSetFlags dflags env) return (map unLoc opts, hscSetFlags (disableWarningsAsErrors $ hsc_dflags hsc_env') hsc_env') where dflags0 = hsc_dflags env diff --git a/ghcide/src/Development/IDE/Core/Rules.hs b/ghcide/src/Development/IDE/Core/Rules.hs index 1e050d57b1..9825e135d7 100644 --- a/ghcide/src/Development/IDE/Core/Rules.hs +++ b/ghcide/src/Development/IDE/Core/Rules.hs @@ -141,6 +141,10 @@ import qualified Development.IDE.Types.Shake as Shake import GHC.Iface.Ext.Types (HieASTs (..)) import GHC.Iface.Ext.Utils (generateReferencesMap) import qualified GHC.LanguageExtensions as LangExt +#if MIN_VERSION_ghc(9,13,0) +import GHC.Types.PkgQual (PkgQual (NoPkgQual)) +import GHC.Types.Basic (ImportLevel (NormalLevel)) +#endif import HIE.Bios.Ghc.Gap (hostIsDynamic) import qualified HieDb import Ide.Logger (Pretty (pretty), @@ -315,7 +319,12 @@ getLocatedImportsRule recorder = define (cmapWithPrio LogShake recorder) $ \GetLocatedImports file -> do ModSummaryResult{msrModSummary = ms} <- use_ GetModSummaryWithoutTimestamps file (KnownTargets targets targetsMap) <- useNoFile_ GetKnownTargets +#if MIN_VERSION_ghc(9,13,0) + let imports = [(False, lvl, mbPkgName, modName) | (lvl, mbPkgName, modName) <- ms_textual_imps ms] + ++ [(True, NormalLevel, NoPkgQual, noLoc modName) | L _ modName <- ms_srcimps ms] +#else let imports = [(False, imp) | imp <- ms_textual_imps ms] ++ [(True, imp) | imp <- ms_srcimps ms] +#endif env_eq <- use_ GhcSession file let env = hscEnv env_eq let import_dirs = map (second homeUnitEnv_dflags) $ hugElts $ hsc_HUG env @@ -335,7 +344,11 @@ getLocatedImportsRule recorder = | otherwise = do itExists <- getFileExists nfp return $ if itExists then Just nfp else Nothing +#if MIN_VERSION_ghc(9,13,0) + (diags, imports') <- fmap unzip $ forM imports $ \(isSource, _lvl, mbPkgName, modName) -> do +#else (diags, imports') <- fmap unzip $ forM imports $ \(isSource, (mbPkgName, modName)) -> do +#endif diagOrImp <- locateModule (hscSetFlags dflags env) import_dirs (optExtensions opt) getTargetFor modName mbPkgName isSource case diagOrImp of Left diags -> pure (diags, Just (modName, Nothing)) @@ -635,10 +648,17 @@ dependencyInfoForFiles fs = do let deps = map (\i -> IM.lookup (getFilePathId i) (rawImports rawDepInfo)) _all_ids nodeKeys = IM.fromList $ catMaybes $ zipWith (\fi mms -> (getFilePathId fi,) . NodeKey_Module . msKey <$> mms) _all_ids mss mns = catMaybes $ zipWith go mss deps +#if MIN_VERSION_ghc(9,13,0) + go (Just ms) (Just (Right (ModuleImports xs))) = Just $ ModuleNode this_dep_edges (ModuleNodeCompile ms) + where this_dep_ids = mapMaybe snd xs + this_dep_edges = map mkNormalEdge $ mapMaybe (\fi -> IM.lookup (getFilePathId fi) nodeKeys) this_dep_ids + go (Just ms) _ = Just $ ModuleNode [] (ModuleNodeCompile ms) +#else go (Just ms) (Just (Right (ModuleImports xs))) = Just $ ModuleNode this_dep_keys ms where this_dep_ids = mapMaybe snd xs this_dep_keys = mapMaybe (\fi -> IM.lookup (getFilePathId fi) nodeKeys) this_dep_ids go (Just ms) _ = Just $ ModuleNode [] ms +#endif go _ _ = Nothing mg = mkModuleGraph mns let shallowFingers = IntMap.fromList $ foldr' (\(i, m) acc -> case m of @@ -773,8 +793,13 @@ ghcSessionDepsDefinition fullModSummary GhcSessionDepsConfig{..} hscEnvEq file = !final_deps <- do dep_mss <- map msrModSummary <$> uses_ GetModSummaryWithoutTimestamps deps return $!! map (NodeKey_Module . msKey) dep_mss +#if MIN_VERSION_ghc(9,13,0) + let module_graph_nodes = + nubOrdOn mkNodeKey (ModuleNode (map mkNormalEdge final_deps) (ModuleNodeCompile ms) : concatMap mgModSummaries' mgs) +#else let module_graph_nodes = nubOrdOn mkNodeKey (ModuleNode final_deps ms : concatMap mgModSummaries' mgs) +#endif liftIO $ evaluate $ liftRnf rwhnf module_graph_nodes return $ mkModuleGraph module_graph_nodes session' <- liftIO $ mergeEnvs env mg de ms inLoadOrder depSessions diff --git a/ghcide/src/Development/IDE/Core/Shake.hs b/ghcide/src/Development/IDE/Core/Shake.hs index 2fbaa892fa..c5a0a49134 100644 --- a/ghcide/src/Development/IDE/Core/Shake.hs +++ b/ghcide/src/Development/IDE/Core/Shake.hs @@ -133,10 +133,16 @@ import qualified Language.LSP.Server as LSP import Development.IDE.Core.Tracing import Development.IDE.Core.WorkerThread +#if MIN_VERSION_ghc(9,13,0) +import Development.IDE.GHC.Compat (NameCache, + NameCacheUpdater, + newNameCache) +#else import Development.IDE.GHC.Compat (NameCache, NameCacheUpdater, initNameCache, knownKeyNames) +#endif import Development.IDE.GHC.Orphans () import Development.IDE.Graph hiding (ShakeValue, action) @@ -666,7 +672,11 @@ shakeOpen recorder lspEnv defaultConfig idePlugins debouncer restartQueue = tRestartQueue threadQueue loaderQueue = tLoaderQueue threadQueue +#if MIN_VERSION_ghc(9,13,0) + ideNc <- newNameCache +#else ideNc <- initNameCache 'r' knownKeyNames +#endif shakeExtras <- do globals <- newTVarIO HMap.empty state <- STM.newIO diff --git a/ghcide/src/Development/IDE/GHC/Compat.hs b/ghcide/src/Development/IDE/GHC/Compat.hs index befd22c8de..c8f6282338 100644 --- a/ghcide/src/Development/IDE/GHC/Compat.hs +++ b/ghcide/src/Development/IDE/GHC/Compat.hs @@ -66,6 +66,7 @@ module Development.IDE.GHC.Compat( simplifyExpr, tidyExpr, emptyTidyEnv, + tidyOpenType, corePrepExpr, corePrepPgm, lintInteractiveExpr, @@ -73,6 +74,7 @@ module Development.IDE.GHC.Compat( HomePackageTable, lookupHpt, loadModulesHome, + hugElts, bcoFreeNames, ModIfaceAnnotation, pattern Annotation, @@ -87,7 +89,9 @@ module Development.IDE.GHC.Compat( emptyInScopeSet, Unfolding(..), noUnfolding, +#if !MIN_VERSION_ghc(9,13,0) loadExpr, +#endif byteCodeGen, bc_bcos, loadDecls, @@ -135,6 +139,7 @@ import Prelude hiding (mod) import qualified GHC.Core.Opt.Pipeline as GHC import GHC.Core.Tidy (tidyExpr) +import GHC.Core.TyCo.Tidy (tidyOpenType) import GHC.CoreToStg.Prep (corePrepPgm) import qualified GHC.CoreToStg.Prep as GHC import GHC.Driver.Hooks (hscCompileCoreExprHook) @@ -173,7 +178,11 @@ import GHC.Driver.Config.CoreToStg.Prep (initCorePrepConfig) import GHC.Driver.Config.Stg.Pipeline import GHC.Driver.Env as Env import GHC.Iface.Env -import GHC.Linker.Loader (loadDecls, loadExpr) +import GHC.Linker.Loader (loadDecls +#if !MIN_VERSION_ghc(9,13,0) + , loadExpr +#endif + ) import GHC.Runtime.Context (icInteractiveModule) import GHC.Stg.Pipeline import GHC.Stg.Syntax @@ -181,14 +190,23 @@ import GHC.StgToByteCode import GHC.Types.CostCentre import GHC.Types.IPE import GHC.Types.SrcLoc (combineRealSrcSpans) +#if MIN_VERSION_ghc(9,13,0) +import GHC.Unit.Home.PackageTable (HomePackageTable, + lookupHpt) +#else import GHC.Unit.Home.ModInfo (HomePackageTable, lookupHpt) +#endif import GHC.Unit.Module.Deps (Dependencies (dep_direct_mods), Usage (..)) import GHC.Unit.Module.ModIface -- See Note [Guidelines For Using CPP In GHCIDE Import Statements] +#if MIN_VERSION_ghc(9,13,0) +import GHC.Unit.Home.Graph (addHomeModInfoToHug, unitEnv_assocs) +#endif + #if MIN_VERSION_ghc(9,7,0) import GHC.Tc.Zonk.TcType (tcInitTidyEnv) #endif @@ -265,7 +283,11 @@ reLocA = reLoc #endif getDependentMods :: ModIface -> [ModuleName] +#if MIN_VERSION_ghc(9,13,0) +getDependentMods = map (gwib_mod . (\(_,_,x) -> x)) . S.toList . dep_direct_mods . mi_deps +#else getDependentMods = map (gwib_mod . snd) . S.toList . dep_direct_mods . mi_deps +#endif simplifyExpr :: DynFlags -> HscEnv -> CoreExpr -> IO CoreExpr simplifyExpr _ env = GHC.simplifyExpr (Development.IDE.GHC.Compat.Env.hsc_logger env) (ue_eps (Development.IDE.GHC.Compat.Env.hsc_unit_env env)) (initSimplifyExprOpts (hsc_dflags env) (hsc_IC env)) @@ -360,7 +382,11 @@ nameListFromAvails as = getModuleHash :: ModIface -> Fingerprint +#if MIN_VERSION_ghc(9,13,0) +getModuleHash = mi_mod_hash +#else getModuleHash = mi_mod_hash . mi_final_exts +#endif disableWarningsAsErrors :: DynFlags -> DynFlags @@ -411,13 +437,16 @@ data GhcVersion | GHC98 | GHC910 | GHC912 + | GHC914 deriving (Eq, Ord, Show, Enum) ghcVersionStr :: String ghcVersionStr = VERSION_ghc ghcVersion :: GhcVersion -#if MIN_VERSION_GLASGOW_HASKELL(9,12,0,0) +#if MIN_VERSION_GLASGOW_HASKELL(9,14,0,0) +ghcVersion = GHC914 +#elif MIN_VERSION_GLASGOW_HASKELL(9,12,0,0) ghcVersion = GHC912 #elif MIN_VERSION_GLASGOW_HASKELL(9,10,0,0) ghcVersion = GHC910 @@ -455,9 +484,22 @@ mkAstNode n = Node (SourcedNodeInfo $ Map.singleton GeneratedInfo n) loadModulesHome :: [HomeModInfo] -> HscEnv +#if MIN_VERSION_ghc(9,13,0) + -> IO HscEnv +loadModulesHome mod_infos e = do + let hug = hsc_HUG (e { hsc_type_env_vars = emptyKnotVars }) + mapM_ (`addHomeModInfoToHug` hug) mod_infos + pure (e { hsc_type_env_vars = emptyKnotVars }) +#else -> HscEnv loadModulesHome mod_infos e = hscUpdateHUG (\hug -> foldl' (flip addHomeModInfoToHug) hug mod_infos) (e { hsc_type_env_vars = emptyKnotVars }) +#endif + +#if MIN_VERSION_ghc(9,13,0) +hugElts :: HomeUnitGraph -> [(UnitId, HomeUnitEnv)] +hugElts = unitEnv_assocs +#endif recDotDot :: HsRecFields (GhcPass p) arg -> Maybe Int recDotDot x = diff --git a/ghcide/src/Development/IDE/GHC/Compat/Core.hs b/ghcide/src/Development/IDE/GHC/Compat/Core.hs index 42f654b609..93c860ac7b 100644 --- a/ghcide/src/Development/IDE/GHC/Compat/Core.hs +++ b/ghcide/src/Development/IDE/GHC/Compat/Core.hs @@ -72,7 +72,9 @@ module Development.IDE.GHC.Compat.Core ( #if MIN_VERSION_ghc(9,11,0) pattern ModIface, set_mi_top_env, +#if !MIN_VERSION_ghc(9,13,0) set_mi_usages, +#endif #endif HscSource(..), WhereFrom(..), @@ -522,6 +524,9 @@ import GHC.Unit.Finder hiding (mkHomeModLocation) import qualified GHC.Unit.Finder as GHC import GHC.Unit.Finder.Types import GHC.Unit.Home.ModInfo +#if MIN_VERSION_ghc(9,13,0) +import GHC.Unit.Home.PackageTable (addToHpt, addListToHpt) +#endif import GHC.Unit.Module.Graph import GHC.Unit.Module.Imported import GHC.Unit.Module.ModDetails @@ -534,7 +539,9 @@ import GHC.Unit.Module.ModIface (IfaceExport, ModIface, #if MIN_VERSION_ghc(9,11,0) , pattern ModIface , set_mi_top_env +#if !MIN_VERSION_ghc(9,13,0) , set_mi_usages +#endif #endif ) import GHC.Unit.Module.ModSummary (ModSummary (..)) @@ -550,6 +557,10 @@ import Language.Haskell.Syntax hiding (FunDep) import System.OsPath #endif +#if MIN_VERSION_ghc(9,13,0) +import qualified System.FilePath as FP +#endif + #if !MIN_VERSION_ghc(9,7,0) import GHC.Types.Avail (greNamePrintableName) #endif @@ -559,7 +570,17 @@ import GHC.Hs (SrcSpanAnn') #endif mkHomeModLocation :: DynFlags -> ModuleName -> FilePath -> IO Module.ModLocation -#if MIN_VERSION_ghc(9,11,0) +#if MIN_VERSION_ghc(9,13,0) +mkHomeModLocation df mn f = + let (basename, ext) = FP.splitExtension f + osBasename = unsafeEncodeUtf basename + osExt = unsafeEncodeUtf ext + hscSrc = case ext of + ".hs-boot" -> HsBootFile + ".hsig" -> HsigFile + _ -> HsSrcFile + in pure $ GHC.mkHomeModLocation (GHC.initFinderOpts df) mn osBasename osExt hscSrc +#elif MIN_VERSION_ghc(9,11,0) mkHomeModLocation df mn f = let osf = unsafeEncodeUtf f in pure $ GHC.mkHomeModLocation (GHC.initFinderOpts df) mn osf diff --git a/ghcide/src/Development/IDE/GHC/Compat/Env.hs b/ghcide/src/Development/IDE/GHC/Compat/Env.hs index cbccc1a3de..7a458f08ef 100644 --- a/ghcide/src/Development/IDE/GHC/Compat/Env.hs +++ b/ghcide/src/Development/IDE/GHC/Compat/Env.hs @@ -3,9 +3,10 @@ -- | Compat module for the main Driver types, such as 'HscEnv', -- 'UnitEnv' and some DynFlags compat functions. module Development.IDE.GHC.Compat.Env ( - Env.HscEnv(hsc_FC, hsc_NC, hsc_IC, hsc_mod_graph + Env.HscEnv(hsc_FC, hsc_NC, hsc_IC , hsc_type_env_vars ), + Env.hsc_mod_graph, Env.hsc_HPT, InteractiveContext(..), setInteractivePrintName, diff --git a/ghcide/src/Development/IDE/GHC/Compat/Units.hs b/ghcide/src/Development/IDE/GHC/Compat/Units.hs index f7f634e448..752e32d812 100644 --- a/ghcide/src/Development/IDE/GHC/Compat/Units.hs +++ b/ghcide/src/Development/IDE/GHC/Compat/Units.hs @@ -75,26 +75,40 @@ import GHC.Unit.State (LookupResult, UnitInfo, import qualified GHC.Unit.State as State import GHC.Unit.Types +#if MIN_VERSION_ghc(9,13,0) +import qualified Data.Set as Set +import GHC.Unit.Home.Graph +import GHC.Unit.Home.PackageTable (emptyHomePackageTable) +import GHC.Unit.Module.Graph (emptyMG) +#endif + type PreloadUnitClosure = UniqSet UnitId unitState :: HscEnv -> UnitState unitState = ue_units . hsc_unit_env -createUnitEnvFromFlags :: NE.NonEmpty DynFlags -> HomeUnitGraph -createUnitEnvFromFlags unitDflags = - let - newInternalUnitEnv dflags = mkHomeUnitEnv dflags emptyHomePackageTable Nothing - unitEnvList = NE.map (\dflags -> (homeUnitId_ dflags, newInternalUnitEnv dflags)) unitDflags - in - unitEnv_new (Map.fromList (NE.toList unitEnvList)) +createUnitEnvFromFlags :: NE.NonEmpty DynFlags -> IO HomeUnitGraph +createUnitEnvFromFlags unitDflags = do +#if MIN_VERSION_ghc(9,13,0) + let mkEntry dflags = do + hpt <- emptyHomePackageTable + let us = State.emptyUnitState -- placeholder UnitState + pure (homeUnitId_ dflags, mkHomeUnitEnv us Nothing dflags hpt Nothing) + unitEnvList <- mapM mkEntry (NE.toList unitDflags) + pure $ unitEnv_new (Map.fromList unitEnvList) +#else + let newInternalUnitEnv dflags = mkHomeUnitEnv dflags emptyHomePackageTable Nothing + unitEnvList = NE.map (\dflags -> (homeUnitId_ dflags, newInternalUnitEnv dflags)) unitDflags + pure $ unitEnv_new (Map.fromList (NE.toList unitEnvList)) +#endif initUnits :: [DynFlags] -> HscEnv -> IO HscEnv initUnits unitDflags env = do let dflags0 = hsc_dflags env -- additionally, set checked dflags so we don't lose fixes - let initial_home_graph = createUnitEnvFromFlags (dflags0 NE.:| unitDflags) - home_units = unitEnv_keys initial_home_graph + initial_home_graph <- createUnitEnvFromFlags (dflags0 NE.:| unitDflags) + let home_units = unitEnv_keys initial_home_graph home_unit_graph <- forM initial_home_graph $ \homeUnitEnv -> do let cached_unit_dbs = homeUnitEnv_unit_dbs homeUnitEnv dflags = homeUnitEnv_dflags homeUnitEnv @@ -118,6 +132,9 @@ initUnits unitDflags env = do , ue_home_unit_graph = home_unit_graph , ue_current_unit = homeUnitId_ dflags0 , ue_eps = ue_eps (hsc_unit_env env) +#if MIN_VERSION_ghc(9,13,0) + , ue_module_graph = emptyMG +#endif } pure $ hscSetFlags dflags1 $ hscSetUnitEnv unit_env env diff --git a/ghcide/src/Development/IDE/GHC/Orphans.hs b/ghcide/src/Development/IDE/GHC/Orphans.hs index 068ca6a78a..b3b59f5c1a 100644 --- a/ghcide/src/Development/IDE/GHC/Orphans.hs +++ b/ghcide/src/Development/IDE/GHC/Orphans.hs @@ -26,6 +26,9 @@ import GHC.Iface.Ext.Types import GHC.Parser.Annotation import GHC.Types.PkgQual import GHC.Types.SrcLoc +#if MIN_VERSION_ghc(9,13,0) +import GHC.Types.Basic (ImportLevel) +#endif -- See Note [Guidelines For Using CPP In GHCIDE Import Statements] @@ -44,7 +47,9 @@ instance Show CgGuts where show = unpack . printOutputable . cg_module instance NFData CgGuts where rnf = rwhnf instance Show ModDetails where show = const "" instance NFData ModDetails where rnf = rwhnf +#if !MIN_VERSION_ghc(9,13,0) instance NFData SafeHaskellMode where rnf = rwhnf +#endif instance Show Linkable where show = unpack . printOutputable #if MIN_VERSION_ghc(9,11,0) instance NFData Linkable where rnf (Linkable a b c) = rnf a `seq` rnf b `seq` rnf c @@ -136,8 +141,10 @@ instance Hashable ModuleName where instance NFData a => NFData (IdentifierDetails a) where rnf (IdentifierDetails a b) = rnf a `seq` rnf (length b) +#if !MIN_VERSION_ghc(9,13,0) instance NFData RealSrcSpan where rnf = rwhnf +#endif srcSpanFileTag, srcSpanStartLineTag, srcSpanStartColTag, srcSpanEndLineTag, srcSpanEndColTag :: String @@ -209,8 +216,10 @@ instance NFData PkgQual where rnf (ThisPkg uid) = rnf uid rnf (OtherPkg uid) = rnf uid +#if !MIN_VERSION_ghc(9,13,0) instance NFData UnitId where rnf = rwhnf +#endif instance NFData NodeKey where rnf = rwhnf @@ -235,3 +244,8 @@ instance NFData Extension where instance NFData (UniqFM Name [Name]) where rnf (ufmToIntMap -> m) = rnf m + +#if MIN_VERSION_ghc(9,13,0) +instance NFData ImportLevel where + rnf = rwhnf +#endif diff --git a/ghcide/src/Development/IDE/LSP/Outline.hs b/ghcide/src/Development/IDE/LSP/Outline.hs index af2a0f1c97..cec445601c 100644 --- a/ghcide/src/Development/IDE/LSP/Outline.hs +++ b/ghcide/src/Development/IDE/LSP/Outline.hs @@ -256,8 +256,14 @@ hsConDeclsBinders cons #endif get_flds_gadt _ = [] +#if MIN_VERSION_ghc(9,13,0) + get_flds :: Located [LHsConDeclRecField GhcPs] + -> [LFieldOcc GhcPs] + get_flds flds = concatMap (cdrf_names . unLoc) (unLoc flds) +#else get_flds :: Located [LConDeclField GhcPs] -> [LFieldOcc GhcPs] get_flds flds = concatMap (cd_fld_names . unLoc) (unLoc flds) +#endif diff --git a/ghcide/src/Development/IDE/Plugin/Completions/Logic.hs b/ghcide/src/Development/IDE/Plugin/Completions/Logic.hs index 018d08cb06..55ea002fc6 100644 --- a/ghcide/src/Development/IDE/Plugin/Completions/Logic.hs +++ b/ghcide/src/Development/IDE/Plugin/Completions/Logic.hs @@ -490,10 +490,17 @@ findRecordCompl uri mn DataDecl {tcdLName, tcdDataDefn} = result -- -- is encoded as @[[arg1, arg2], [arg3], [arg4]]@ -- Hence, we must concat nested arguments into one to get all the fields. +#if MIN_VERSION_ghc(9,13,0) + extract HsConDeclRecField{..} + = map (foLabel . unLoc) cdrf_names + -- XConDeclRecField + extract _ = [] +#else extract ConDeclField{..} = map (foLabel . unLoc) cd_fld_names -- XConDeclField extract _ = [] +#endif findRecordCompl _ _ _ = [] toggleSnippets :: ClientCapabilities -> CompletionsConfig -> CompletionItem -> CompletionItem diff --git a/ghcide/src/Development/IDE/Plugin/TypeLenses.hs b/ghcide/src/Development/IDE/Plugin/TypeLenses.hs index c596d1fb82..63a0a9a7fa 100644 --- a/ghcide/src/Development/IDE/Plugin/TypeLenses.hs +++ b/ghcide/src/Development/IDE/Plugin/TypeLenses.hs @@ -57,6 +57,7 @@ import Development.IDE.GHC.Util (printName) import Development.IDE.Graph.Classes import Development.IDE.Types.Location (Position (Position, _line), Range (Range, _end, _start)) +import GHC.Core.TyCo.Tidy (tidyOpenType) import GHC.Generics (Generic) import Ide.Logger (Pretty (pretty), Recorder, WithPriority, diff --git a/ghcide/src/Development/IDE/Types/HscEnvEq.hs b/ghcide/src/Development/IDE/Types/HscEnvEq.hs index 1c2ed1732f..293326c372 100644 --- a/ghcide/src/Development/IDE/Types/HscEnvEq.hs +++ b/ghcide/src/Development/IDE/Types/HscEnvEq.hs @@ -61,11 +61,19 @@ newHscEnvEq hscEnv' = do let hscEnv = hscEnv' { hsc_FC = FinderCache { flushFinderCaches = \_ -> error "GHC should never call flushFinderCaches outside the driver" +#if MIN_VERSION_ghc(9,13,0) + , addToFinderCache = \im val -> do +#else , addToFinderCache = \(GWIB im _) val -> do +#endif if moduleUnit im `elem` hsc_all_home_unit_ids hscEnv' then error "tried to add home module to FC" else atomicModifyIORef' mod_cache $ \c -> (extendInstalledModuleEnv c im val, ()) +#if MIN_VERSION_ghc(9,13,0) + , lookupFinderCache = \im -> do +#else , lookupFinderCache = \(GWIB im _) -> do +#endif if moduleUnit im `elem` hsc_all_home_unit_ids hscEnv' then error ("tried to lookup home module from FC" ++ showSDocUnsafe (ppr (im, hsc_all_home_unit_ids hscEnv'))) else lookupInstalledModuleEnv <$> readIORef mod_cache <*> pure im diff --git a/haskell-language-server.cabal b/haskell-language-server.cabal index 23260a5393..80979cdcd0 100644 --- a/haskell-language-server.cabal +++ b/haskell-language-server.cabal @@ -318,7 +318,6 @@ test-suite hls-cabal-plugin-tests , haskell-language-server:hls-cabal-plugin , hls-test-utils == 2.12.0.0 , lens - , lsp , lsp-types , text @@ -353,7 +352,7 @@ library hls-class-plugin , deepseq , extra , ghc - , ghc-exactprint >= 1.5 && < 1.13.0.0 + , ghc-exactprint >= 1.5 && < 1.15 , ghcide == 2.12.0.0 , hls-graph , hls-plugin-api == 2.12.0.0 @@ -712,7 +711,8 @@ common hlint -- Hlint isn't compatible with GHC 9.10, and crashes in subtle ways. -- See https://github.com/haskell/haskell-language-server/issues/4674 -- for its wake of destruction. - if flag(hlint) && !impl(ghc ==9.10.*) + -- hlint depends on ghc-lib-parser which doesn't support GHC 9.14 + if flag(hlint) && !impl(ghc ==9.10.*) && !impl(ghc >= 9.14) build-depends: haskell-language-server:hls-hlint-plugin cpp-options: -Dhls_hlint @@ -721,7 +721,8 @@ library hls-hlint-plugin -- Hlint isn't compatible with GHC 9.10, and crashes in subtle ways. -- See https://github.com/haskell/haskell-language-server/issues/4674 -- for its wake of destruction. - if !flag(hlint) || impl(ghc ==9.10.*) + -- hlint depends on ghc-lib-parser which doesn't support GHC 9.14 + if !flag(hlint) || impl(ghc ==9.10.*) || impl(ghc >= 9.14) buildable: False exposed-modules: Ide.Plugin.Hlint hs-source-dirs: plugins/hls-hlint-plugin/src @@ -771,7 +772,8 @@ test-suite hls-hlint-plugin-tests -- Hlint isn't compatible with GHC 9.10, and crashes in subtle ways. -- See https://github.com/haskell/haskell-language-server/issues/4674 -- for its wake of destruction. - if !flag(hlint) || impl(ghc ==9.10.*) + -- hlint depends on ghc-lib-parser which doesn't support GHC 9.14 + if !flag(hlint) || impl(ghc ==9.10.*) || impl(ghc >= 9.14) buildable: False type: exitcode-stdio-1.0 hs-source-dirs: plugins/hls-hlint-plugin/test @@ -1519,13 +1521,15 @@ flag fourmolu manual: True common fourmolu - if flag(fourmolu) + -- fourmolu depends on ghc-lib-parser which doesn't support GHC 9.14 + if flag(fourmolu) && !impl(ghc >= 9.14) build-depends: haskell-language-server:hls-fourmolu-plugin cpp-options: -Dhls_fourmolu library hls-fourmolu-plugin import: defaults, pedantic, warnings - if !flag(fourmolu) + -- fourmolu depends on ghc-lib-parser which doesn't support GHC 9.14 + if !flag(fourmolu) || impl(ghc >= 9.14) buildable: False exposed-modules: Ide.Plugin.Fourmolu hs-source-dirs: plugins/hls-fourmolu-plugin/src @@ -1545,7 +1549,8 @@ library hls-fourmolu-plugin test-suite hls-fourmolu-plugin-tests import: defaults, pedantic, test-defaults, warnings - if !flag(fourmolu) + -- fourmolu depends on ghc-lib-parser which doesn't support GHC 9.14 + if !flag(fourmolu) || impl(ghc >= 9.14) buildable: False type: exitcode-stdio-1.0 hs-source-dirs: plugins/hls-fourmolu-plugin/test @@ -1573,13 +1578,15 @@ flag ormolu manual: True common ormolu - if flag(ormolu) + -- ormolu depends on ghc-lib-parser which doesn't support GHC 9.14 + if flag(ormolu) && !impl(ghc >= 9.14) build-depends: haskell-language-server:hls-ormolu-plugin cpp-options: -Dhls_ormolu library hls-ormolu-plugin import: defaults, pedantic, warnings - if !flag(ormolu) + -- ormolu depends on ghc-lib-parser which doesn't support GHC 9.14 + if !flag(ormolu) || impl(ghc >= 9.14) buildable: False exposed-modules: Ide.Plugin.Ormolu hs-source-dirs: plugins/hls-ormolu-plugin/src @@ -1599,7 +1606,8 @@ library hls-ormolu-plugin test-suite hls-ormolu-plugin-tests import: defaults, pedantic, test-defaults, warnings - if !flag(ormolu) + -- ormolu depends on ghc-lib-parser which doesn't support GHC 9.14 + if !flag(ormolu) || impl(ghc >= 9.14) buildable: False type: exitcode-stdio-1.0 hs-source-dirs: plugins/hls-ormolu-plugin/test @@ -1628,14 +1636,16 @@ flag stylishHaskell manual: True common stylishHaskell - if flag(stylishHaskell) + -- stylish-haskell depends on ghc-lib-parser which doesn't support GHC 9.14 + if flag(stylishHaskell) && !impl(ghc >= 9.14) build-depends: haskell-language-server:hls-stylish-haskell-plugin cpp-options: -Dhls_stylishHaskell library hls-stylish-haskell-plugin import: defaults, pedantic, warnings -- https://github.com/haskell/stylish-haskell/issues/479 - if !flag(stylishHaskell) + -- stylish-haskell depends on ghc-lib-parser which doesn't support GHC 9.14 + if !flag(stylishHaskell) || impl(ghc >= 9.14) buildable: False exposed-modules: Ide.Plugin.StylishHaskell hs-source-dirs: plugins/hls-stylish-haskell-plugin/src @@ -1653,7 +1663,8 @@ library hls-stylish-haskell-plugin test-suite hls-stylish-haskell-plugin-tests import: defaults, pedantic, test-defaults, warnings - if !flag(stylishHaskell) + -- stylish-haskell depends on ghc-lib-parser which doesn't support GHC 9.14 + if !flag(stylishHaskell) || impl(ghc >= 9.14) buildable: False type: exitcode-stdio-1.0 hs-source-dirs: plugins/hls-stylish-haskell-plugin/test @@ -2088,9 +2099,9 @@ test-suite func-test -- formatters if flag(floskell) && (impl(ghc < 9.10) || flag(ignore-plugins-ghc-bounds)) cpp-options: -Dhls_floskell - if flag(fourmolu) + if flag(fourmolu) && (impl(ghc < 9.14) || flag(ignore-plugins-ghc-bounds)) cpp-options: -Dhls_fourmolu - if flag(ormolu) + if flag(ormolu) && (impl(ghc < 9.14) || flag(ignore-plugins-ghc-bounds)) cpp-options: -Dhls_ormolu test-suite wrapper-test diff --git a/plugins/hls-alternate-number-format-plugin/src/Ide/Plugin/Literals.hs b/plugins/hls-alternate-number-format-plugin/src/Ide/Plugin/Literals.hs index c26227d933..3768cb9767 100644 --- a/plugins/hls-alternate-number-format-plugin/src/Ide/Plugin/Literals.hs +++ b/plugins/hls-alternate-number-format-plugin/src/Ide/Plugin/Literals.hs @@ -66,17 +66,21 @@ getPattern :: LPat GhcPs -> Maybe Literal getPattern (L (locA -> (RealSrcSpan patSpan _)) pat) = case pat of LitPat _ lit -> case lit of HsInt _ val -> fromIntegralLit patSpan val +#if __GLASGOW_HASKELL__ < 913 HsRat _ val _ -> fromFractionalLit patSpan val +#endif _ -> Nothing NPat _ (L (locA -> (RealSrcSpan sSpan _)) overLit) _ _ -> fromOverLit overLit sSpan NPlusKPat _ _ (L (locA -> (RealSrcSpan sSpan _)) overLit1) _ _ _ -> fromOverLit overLit1 sSpan _ -> Nothing getPattern _ = Nothing -fromLit :: HsLit p -> RealSrcSpan -> Maybe Literal +fromLit :: HsLit GhcPs -> RealSrcSpan -> Maybe Literal fromLit lit sSpan = case lit of HsInt _ val -> fromIntegralLit sSpan val +#if __GLASGOW_HASKELL__ < 913 HsRat _ val _ -> fromFractionalLit sSpan val +#endif _ -> Nothing fromOverLit :: HsOverLit p -> RealSrcSpan -> Maybe Literal diff --git a/plugins/hls-cabal-plugin/src/Ide/Plugin/Cabal/Definition.hs b/plugins/hls-cabal-plugin/src/Ide/Plugin/Cabal/Definition.hs index 5f85151199..5137af2b08 100644 --- a/plugins/hls-cabal-plugin/src/Ide/Plugin/Cabal/Definition.hs +++ b/plugins/hls-cabal-plugin/src/Ide/Plugin/Cabal/Definition.hs @@ -198,9 +198,10 @@ lookupBuildTargetPackageDescription (PackageDescription {..}) (Just buildTargetN -- better ways to get the path. -- -- Examples: (output is system dependent) --- >>> toHaskellFile "My.Module.Lib" --- "My/Module/Lib.hs" --- >>> toHaskellFile "Main" --- "Main.hs" +-- +-- >>> toHaskellFile "My.Module.Lib" +-- "My/Module/Lib.hs" +-- >>> toHaskellFile "Main" +-- "Main.hs" toHaskellFile :: T.Text -> FilePath toHaskellFile moduleName = joinPath (map T.unpack $ T.splitOn "." moduleName) <.> ".hs" diff --git a/plugins/hls-cabal-plugin/test/Definition.hs b/plugins/hls-cabal-plugin/test/Definition.hs index 33163c03eb..08fc079410 100644 --- a/plugins/hls-cabal-plugin/test/Definition.hs +++ b/plugins/hls-cabal-plugin/test/Definition.hs @@ -6,8 +6,6 @@ module Definition ( import Control.Lens ((^.)) import Data.List.Extra (isSuffixOf) -import qualified Data.Text as T -import Ide.Plugin.Cabal.Definition (toHaskellFile) import qualified Language.LSP.Protocol.Lens as L import qualified Language.LSP.Protocol.Types as LSP import System.FilePath @@ -24,38 +22,35 @@ gotoDefinitionTests = testGroup "Goto Definition" gotoModuleDefinitionTests :: TestTree gotoModuleDefinitionTests = testGroup "Goto Module Definition" [ testGoToDefinitionLink "simple cabal test" "simple-cabal" "simple-cabal.cabal" - (Position 8 23) (toTestHaskellPath "" "A") + (Position 8 23) "A.hs" , testGoToDefinitionLink "library start of exposed-modules" ("goto-definition" "modules") "module-examples.cabal" - (Position 6 22) (toTestHaskellPath "src" "Library.Lib") + (Position 6 22) ("src" "Library" "Lib.hs") , testGoToDefinitionLink "library middle of exposed-modules" ("goto-definition" "modules") "module-examples.cabal" - (Position 6 29) (toTestHaskellPath "src" "Library.Lib") + (Position 6 29) ("src" "Library" "Lib.hs") , testGoToDefinitionLink "library end of exposed-modules" ("goto-definition" "modules") "module-examples.cabal" - (Position 6 33) (toTestHaskellPath "src" "Library.Lib") + (Position 6 33) ("src" "Library" "Lib.hs") , testGoToDefinitionLink "library start of other-modules" ("goto-definition" "modules") "module-examples.cabal" - (Position 9 22) (toTestHaskellPath "src" "Library.Other.OtherLib") + (Position 9 22) ("src" "Library" "Other" "OtherLib.hs") , testGoToDefinitionLink "library end of other-modules" ("goto-definition" "modules") "module-examples.cabal" - (Position 9 44) (toTestHaskellPath "src" "Library.Other.OtherLib") + (Position 9 44) ("src" "Library" "Other" "OtherLib.hs") , testGoToDefinitionLink "executable other-modules" ("goto-definition" "modules") "module-examples.cabal" - (Position 22 10) (toTestHaskellPath ("src" "exe") "Config") + (Position 22 10) ("src" "exe" "Config.hs") , testGoToDefinitionLink "test-suite other-modules Config" ("goto-definition" "modules") "module-examples.cabal" - (Position 31 10) (toTestHaskellPath ("src" "test") "Config") + (Position 31 10) ("src" "test" "Config.hs") , testGoToDefinitionLink "test-suite other-modules Library" ("goto-definition" "modules") "module-examples.cabal" - (Position 34 10) (toTestHaskellPath ("src" "test") "Library") + (Position 34 10) ("src" "test" "Library.hs") , testGoToDefinitionLink "benchmark other-modules Config" ("goto-definition" "modules") "module-examples.cabal" - (Position 45 30) (toTestHaskellPath ("src" "bench") "Config") + (Position 45 30) ("src" "bench" "Config.hs") , testGoToDefinitionLinkNoLocation "not existent module" ("goto-definition" "modules") "module-examples.cabal" (Position 48 25) , testGoToDefinitionLinkNoLocation "behind module" ("goto-definition" "modules") "module-examples.cabal" (Position 9 20) , testGoToDefinitionLinkNoLocation "after module" ("goto-definition" "modules") "module-examples.cabal" (Position 9 50) ] where - toTestHaskellPath :: FilePath -> T.Text -> FilePath - toTestHaskellPath dir moduleName = dir toHaskellFile moduleName - getUriFromDefinition :: Show b => (Definition |? b) -> Uri getUriFromDefinition (InL (Definition (InL loc))) = loc^.L.uri getUriFromDefinition unk = error $ "Unexpected pattern '" ++ show unk ++ "' , expected '(InL (Definition (InL loc))'" @@ -66,13 +61,12 @@ gotoModuleDefinitionTests = testGroup "Goto Module Definition" doc <- openDoc cabalFile "cabal" definitions <- getDefinitions doc cursorPos let uri = getUriFromDefinition definitions - mFilePath = (testDir ) <$> uriToFilePath uri - case mFilePath of + case uriToFilePath uri of Nothing -> error $ "Not possible to convert Uri " <> show uri <> " to FilePath" Just filePath -> do - let filePathWithDir = testDir expectedFilePath - isCorrectPath = filePathWithDir `isSuffixOf` filePath - liftIO $ isCorrectPath @? ("Absolute path expected to end on " <> filePathWithDir <> + let + isCorrectPath = expectedFilePath `isSuffixOf` filePath + liftIO $ isCorrectPath @? ("Absolute path expected to end on " <> filePath <> " but " <> filePath <> " was given.") testGoToDefinitionLinkNoLocation :: TestName -> FilePath -> FilePath -> Position -> TestTree diff --git a/plugins/hls-cabal-plugin/test/Utils.hs b/plugins/hls-cabal-plugin/test/Utils.hs index 0264fec2c6..3064497aab 100644 --- a/plugins/hls-cabal-plugin/test/Utils.hs +++ b/plugins/hls-cabal-plugin/test/Utils.hs @@ -14,7 +14,7 @@ import qualified Ide.Plugin.Cabal import Ide.Plugin.Cabal.Completion.Types import System.FilePath import Test.Hls -import Test.Hls.FileSystem (VirtualFileTree) +import qualified Test.Hls.FileSystem as FS cabalPlugin :: PluginTestDescriptor Ide.Plugin.Cabal.Log @@ -52,22 +52,22 @@ runCabalTestCaseSession :: TestName -> FilePath -> Session () -> TestTree runCabalTestCaseSession title subdir = testCase title . runCabalSession subdir runHaskellTestCaseSession :: TestName -> FilePath -> Session () -> TestTree -runHaskellTestCaseSession title subdir = testCase title . runHaskellAndCabalSession subdir +runHaskellTestCaseSession title subdir = testCase title . runHaskellAndCabalSession (FS.mkVirtualFileTree testDataDir [FS.copyDir subdir]) runCabalSession :: FilePath -> Session a -> IO a runCabalSession subdir = - failIfSessionTimeout . runSessionWithServer def cabalPlugin (testDataDir subdir) + failIfSessionTimeout . runSessionWithServerInTmpDir def cabalPlugin (FS.mkVirtualFileTree testDataDir [FS.copyDir subdir]) -runCabalTestCaseSessionVft :: TestName -> VirtualFileTree -> Session () -> TestTree +runCabalTestCaseSessionVft :: TestName -> FS.VirtualFileTree -> Session () -> TestTree runCabalTestCaseSessionVft title vft = testCase title . runCabalSessionVft vft -runCabalSessionVft :: VirtualFileTree -> Session a -> IO a +runCabalSessionVft :: FS.VirtualFileTree -> Session a -> IO a runCabalSessionVft vft = failIfSessionTimeout . runSessionWithServerInTmpDir def cabalPlugin vft -runHaskellAndCabalSession :: FilePath -> Session a -> IO a -runHaskellAndCabalSession subdir = - failIfSessionTimeout . runSessionWithServer def (cabalPlugin <> cabalHaskellPlugin) (testDataDir subdir) +runHaskellAndCabalSession :: FS.VirtualFileTree -> Session a -> IO a +runHaskellAndCabalSession vft = + failIfSessionTimeout . runSessionWithServerInTmpDir def (cabalPlugin <> cabalHaskellPlugin) vft runCabalGoldenSession :: TestName -> FilePath -> FilePath -> (TextDocumentIdentifier -> Session ()) -> TestTree runCabalGoldenSession title subdir fp act = goldenWithCabalDoc def cabalPlugin title testDataDir (subdir fp) "golden" "cabal" act diff --git a/plugins/hls-change-type-signature-plugin/src/Ide/Plugin/ChangeTypeSignature.hs b/plugins/hls-change-type-signature-plugin/src/Ide/Plugin/ChangeTypeSignature.hs index 8b8b7e7d3a..36795e6ddd 100644 --- a/plugins/hls-change-type-signature-plugin/src/Ide/Plugin/ChangeTypeSignature.hs +++ b/plugins/hls-change-type-signature-plugin/src/Ide/Plugin/ChangeTypeSignature.hs @@ -42,6 +42,10 @@ import Development.IDE.Types.Diagnostics (_SomeStructuredMessage) import Generics.SYB (extQ, something) import GHC.Tc.Errors.Types (ErrInfo (..), TcRnMessageDetailed (..)) +#if MIN_VERSION_ghc(9,13,0) +import GHC.Tc.Errors.Ppr (pprErrCtxtMsg) +import GHC.Utils.Outputable (vcat) +#endif import qualified Ide.Logger as Logger import Ide.Plugin.Error (PluginError, getNormalizedFilePathE) @@ -61,8 +65,13 @@ data Log instance Pretty Log where pretty = \case +#if MIN_VERSION_ghc(9,13,0) + LogErrInfoCtxt (ErrInfo ctxt _ _) -> + fromSDoc (vcat $ map pprErrCtxtMsg ctxt) +#else LogErrInfoCtxt (ErrInfo ctxt suppl) -> Logger.vcat [fromSDoc ctxt, fromSDoc suppl] +#endif LogFindSigLocFailure name -> pretty ("Lookup signature location failure: " <> name) where @@ -175,7 +184,11 @@ matchingDiagnostic ErrInfo{errInfoContext} = unwrapMatch (_, _, _, [name]) = Just name unwrapMatch _ = Nothing +#if MIN_VERSION_ghc(9,13,0) + errInfoTxt = printOutputable (vcat $ map pprErrCtxtMsg errInfoContext) +#else errInfoTxt = printOutputable errInfoContext +#endif -- | List of regexes that match various Error Messages errorMessageRegexes :: [Text] diff --git a/plugins/hls-change-type-signature-plugin/test/Main.hs b/plugins/hls-change-type-signature-plugin/test/Main.hs index 72a2ab780e..a3877679d2 100644 --- a/plugins/hls-change-type-signature-plugin/test/Main.hs +++ b/plugins/hls-change-type-signature-plugin/test/Main.hs @@ -41,7 +41,7 @@ test :: TestTree test = testGroup "changeTypeSignature" [ testRegexes , codeActionTest "TExpectedActual" 4 11 - , knownBrokenForGhcVersions [GHC96 .. GHC912] "Error Message in 9.6+ does not provide enough info" $ + , knownBrokenForGhcVersions [GHC96 .. GHC914] "Error Message in 9.6+ does not provide enough info" $ codeActionTest "TRigidType" 4 14 , codeActionTest "TRigidType2" 4 8 , codeActionTest "TLocalBinding" 7 22 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 3f902ef80c..959da19d3a 100644 --- a/plugins/hls-class-plugin/src/Ide/Plugin/Class/CodeAction.hs +++ b/plugins/hls-class-plugin/src/Ide/Plugin/Class/CodeAction.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE CPP #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedLists #-} @@ -225,14 +226,18 @@ signatureToName :: InstanceBindTypeSig -> T.Text signatureToName sig = T.drop (T.length bindingPrefix) (printOutputable (bindName sig)) -- Return [groupName text, [(methodName text, signature text)]] -minDefToMethodGroups :: HscEnv -> TcGblEnv -> Range -> [InstanceBindTypeSig] -> BooleanFormula Name -> [MethodGroup] +minDefToMethodGroups :: HscEnv -> TcGblEnv -> Range -> [InstanceBindTypeSig] -> ClassMinimalDef -> [MethodGroup] minDefToMethodGroups hsc gblEnv range sigs minDef = makeMethodGroup <$> go minDef where makeMethodGroup methodDefinitions = let name = mconcat $ intersperse "," $ (\x -> "'" <> x <> "'") . fst <$> methodDefinitions in (name, methodDefinitions) +#if __GLASGOW_HASKELL__ >= 913 + go (Var lmn) = pure $ makeMethodDefinitions hsc gblEnv range $ filter ((==) (printOutputable (unLoc lmn)) . signatureToName) sigs +#else go (Var mn) = pure $ makeMethodDefinitions hsc gblEnv range $ filter ((==) (printOutputable mn) . signatureToName) sigs +#endif go (Or ms) = concatMap (go . unLoc) ms go (And ms) = foldr (liftA2 (<>) . go . unLoc) [[]] ms go (Parens m) = go (unLoc m) diff --git a/plugins/hls-class-plugin/test/Main.hs b/plugins/hls-class-plugin/test/Main.hs index 7f1feddc11..3765ac29fc 100644 --- a/plugins/hls-class-plugin/test/Main.hs +++ b/plugins/hls-class-plugin/test/Main.hs @@ -11,6 +11,7 @@ import Control.Lens (Prism', prism', view, (^.), (^..), (^?)) import Control.Monad (void) import Data.Foldable (find) +import qualified Data.List as List import Data.Maybe import qualified Data.Text as T import qualified Ide.Plugin.Class as Class @@ -109,9 +110,9 @@ codeLensTests = testGroup doc <- openDoc "CodeLensSimple.hs" "haskell" lens <- getAndResolveCodeLenses doc let titles = map (^. L.title) $ mapMaybe (^. L.command) lens - liftIO $ titles @?= - [ "(==) :: B -> B -> Bool" - , "(==) :: A -> A -> Bool" + liftIO $ List.sort titles @?= + [ "(==) :: A -> A -> Bool" + , "(==) :: B -> B -> Bool" ] , testCase "No lens for TH" $ do runSessionWithServer def classPlugin testDataDir $ do @@ -129,7 +130,7 @@ codeLensTests = testGroup liftIO $ length lens > 0 @?= True `catch` \(e :: SessionException) -> do liftIO $ assertFailure $ "classPluginTestError: "++ show e - , goldenCodeLens "Apply code lens" "CodeLensSimple" 1 + , goldenCodeLens "Apply code lens" "CodeLensSimple" 0 , goldenCodeLens "Apply code lens for local class" "LocalClassDefine" 0 , goldenCodeLens "Apply code lens on the same line" "Inline" 0 , goldenCodeLens "Don't insert pragma while existing" "CodeLensWithPragma" 0 @@ -155,7 +156,7 @@ goldenCodeLens :: TestName -> FilePath -> Int -> TestTree goldenCodeLens title path idx = goldenWithHaskellDoc def classPlugin title testDataDir path "expected" "hs" $ \doc -> do lens <- getAndResolveCodeLenses doc - executeCommand $ fromJust $ (lens !! idx) ^. L.command + executeCommand $ fromJust $ (List.sort lens !! idx) ^. L.command void $ skipManyTill anyMessage (message SMethod_WorkspaceApplyEdit) goldenWithClass ::TestName -> FilePath -> FilePath -> ([CodeAction] -> Session CodeAction) -> TestTree diff --git a/plugins/hls-eval-plugin/src/Ide/Plugin/Eval/Handlers.hs b/plugins/hls-eval-plugin/src/Ide/Plugin/Eval/Handlers.hs index 1f19b5b476..6aa3b94dad 100644 --- a/plugins/hls-eval-plugin/src/Ide/Plugin/Eval/Handlers.hs +++ b/plugins/hls-eval-plugin/src/Ide/Plugin/Eval/Handlers.hs @@ -87,6 +87,12 @@ import Data.List.Extra (unsnoc) import Development.IDE.Core.PluginUtils import Development.IDE.Types.Shake (toKey) import GHC.Types.SrcLoc (UnhelpfulSpanReason (UnhelpfulInteractive)) +#if MIN_VERSION_ghc(9,13,0) +import GHC.Types.Avail (DetOrdAvails (DefinitelyDeterministicAvails), + sortAvails) +import GHC.Tc.Types (tcg_exports) +import GHC.Types.Name.Set (nameSetElemsStable) +#endif import Ide.Logger (Priority (..), Recorder, WithPriority, @@ -262,11 +268,12 @@ initialiseSessionForEval needs_quickcheck st nfp = do -- it back to the iface for the current module. tm <- tmrTypechecked <$> use_ TypeCheck nfp let rdr_env = tcg_rdr_env tm - let linkable_hsc = loadModulesHome (map (addRdrEnv . linkableHomeMod) linkables) deps_hsc addRdrEnv hmi | iface <- hm_iface hmi , ms_mod ms == mi_module iface -#if MIN_VERSION_ghc(9,11,0) +#if MIN_VERSION_ghc(9,13,0) + = hmi { hm_iface = set_mi_top_env (IfaceTopEnv (sortAvails $ gresToAvailInfo $ globalRdrEnvElts $ globalRdrEnvLocal rdr_env) (mkIfaceImports $ tcg_import_decls tm)) iface} +#elif MIN_VERSION_ghc(9,11,0) = hmi { hm_iface = set_mi_top_env (Just $ IfaceTopEnv (forceGlobalRdrEnv (globalRdrEnvLocal rdr_env)) (mkIfaceImports $ tcg_import_decls tm)) iface} #else = hmi { hm_iface = iface { mi_globals = Just $! @@ -277,12 +284,20 @@ initialiseSessionForEval needs_quickcheck st nfp = do }} #endif | otherwise = hmi - +#if MIN_VERSION_ghc(9,13,0) + linkable_hsc <- liftIO $ loadModulesHome (map (addRdrEnv . linkableHomeMod) linkables) deps_hsc +#else + let linkable_hsc = loadModulesHome (map (addRdrEnv . linkableHomeMod) linkables) deps_hsc +#endif return (ms, linkable_hsc) -- Bit awkward we need to use evalGhcEnv here but setContext requires to run -- in the Ghc monad env2 <- liftIO $ evalGhcEnv env1 $ do +#if MIN_VERSION_ghc(9,13,0) + setContext [Compat.IIModule (ms_mod ms)] +#else setContext [Compat.IIModule (moduleName (ms_mod ms))] +#endif let df = flip xopt_set LangExt.ExtendedDefaultRules . flip xopt_unset LangExt.MonomorphismRestriction . flip gopt_set Opt_ImplicitImportQualified @@ -296,7 +311,14 @@ initialiseSessionForEval needs_quickcheck st nfp = do getSession return env2 -#if MIN_VERSION_ghc(9,11,0) +#if MIN_VERSION_ghc(9,13,0) +mkIfaceImports :: [ImportUserSpec] -> [IfaceImport] +mkIfaceImports = map go + where + go (ImpUserSpec decl ImpUserAll) = IfaceImport decl ImpIfaceAll + go (ImpUserSpec decl (ImpUserExplicit avails parents)) = IfaceImport decl (ImpIfaceExplicit (DefinitelyDeterministicAvails avails) (nameSetElemsStable parents)) + go (ImpUserSpec decl (ImpUserEverythingBut ns)) = IfaceImport decl (ImpIfaceEverythingBut (nameSetElemsStable ns)) +#elif MIN_VERSION_ghc(9,11,0) mkIfaceImports :: [ImportUserSpec] -> [IfaceImport] mkIfaceImports = map go where @@ -463,10 +485,18 @@ evals recorder mark_exception fp df stmts = do dbg $ LogEvalFlags flags ndf <- getInteractiveDynFlags dbg $ LogEvalPreSetDynFlags ndf +#if MIN_VERSION_ghc(9,13,0) + hsc_env <- getSession + eans <- + liftIO $ try @GhcException $ + parseDynamicFlagsCmdLine (hsc_logger hsc_env) ndf + (map (L $ UnhelpfulSpan unhelpfulReason) flags) +#else eans <- liftIO $ try @GhcException $ parseDynamicFlagsCmdLine ndf (map (L $ UnhelpfulSpan unhelpfulReason) flags) +#endif dbg $ LogEvalParsedFlags eans case eans of Left err -> pure $ Just $ errorLines $ show err diff --git a/plugins/hls-eval-plugin/test/Main.hs b/plugins/hls-eval-plugin/test/Main.hs index 03416c6902..c00b6fcab7 100644 --- a/plugins/hls-eval-plugin/test/Main.hs +++ b/plugins/hls-eval-plugin/test/Main.hs @@ -133,6 +133,7 @@ tests = , knownBrokenInWindowsBeforeGHC912 "The output has path separators in it, which on Windows look different. Just skip it there" $ goldenWithEvalAndFs' "Property checking with exception" cabalProjectFS "TPropertyError" "hs" $ case ghcVersion of + GHC914 -> "ghc914.expected" GHC912 -> "ghc912.expected" GHC910 -> "ghc910.expected" GHC98 -> "ghc98.expected" diff --git a/plugins/hls-eval-plugin/test/testdata/TPropertyError.ghc914.expected.hs b/plugins/hls-eval-plugin/test/testdata/TPropertyError.ghc914.expected.hs new file mode 100644 index 0000000000..46359c86ab --- /dev/null +++ b/plugins/hls-eval-plugin/test/testdata/TPropertyError.ghc914.expected.hs @@ -0,0 +1,6 @@ +-- Support for property checking +module TProperty where + +-- prop> \(l::[Bool]) -> head l +-- *** Failed! Exception: 'Prelude.head: empty list' (after 1 test): +-- [] diff --git a/plugins/hls-explicit-fixity-plugin/src/Ide/Plugin/ExplicitFixity.hs b/plugins/hls-explicit-fixity-plugin/src/Ide/Plugin/ExplicitFixity.hs index 92bc37f743..af17f47096 100644 --- a/plugins/hls-explicit-fixity-plugin/src/Ide/Plugin/ExplicitFixity.hs +++ b/plugins/hls-explicit-fixity-plugin/src/Ide/Plugin/ExplicitFixity.hs @@ -75,8 +75,10 @@ instance Show FixityMap where instance NFData FixityMap where rnf (FixityMap xs) = rnf xs +#if __GLASGOW_HASKELL__ < 913 instance NFData Fixity where rnf = rwhnf +#endif newtype Log = LogShake Shake.Log diff --git a/plugins/hls-gadt-plugin/src/Ide/Plugin/GHC.hs b/plugins/hls-gadt-plugin/src/Ide/Plugin/GHC.hs index f5687a9db3..0042936e31 100644 --- a/plugins/hls-gadt-plugin/src/Ide/Plugin/GHC.hs +++ b/plugins/hls-gadt-plugin/src/Ide/Plugin/GHC.hs @@ -117,6 +117,9 @@ h98ToGADTConDecl dataName tyVars ctxt = \case #endif -- Ignore all existential type variable since GADT not needed implicitTyVars +#if MIN_VERSION_ghc(9,13,0) + [] -- con_inner_bndrs (new in 9.13) +#endif (mergeContext ctxt con_mb_cxt) (renderDetails con_args) renderResultTy @@ -125,19 +128,17 @@ h98ToGADTConDecl dataName tyVars ctxt = \case where -- Parameters in the data constructor renderDetails :: HsConDeclH98Details GP -> HsConDeclGADTDetails GP -#if MIN_VERSION_ghc(9,9,0) +#if MIN_VERSION_ghc(9,13,0) + renderDetails (PrefixCon args) = PrefixConGADT noExtField args + renderDetails (InfixCon arg1 arg2) = PrefixConGADT noExtField [arg1, arg2] + renderDetails (RecCon recs) = RecConGADT NoEpUniTok recs +#elif MIN_VERSION_ghc(9,9,0) renderDetails (PrefixCon _ args) = PrefixConGADT noExtField args -#else - renderDetails (PrefixCon _ args) = PrefixConGADT args -#endif -#if MIN_VERSION_ghc(9,9,0) renderDetails (InfixCon arg1 arg2) = PrefixConGADT noExtField [arg1, arg2] -#else - renderDetails (InfixCon arg1 arg2) = PrefixConGADT [arg1, arg2] -#endif -#if MIN_VERSION_ghc(9,9,0) renderDetails (RecCon recs) = RecConGADT NoEpUniTok recs #else + renderDetails (PrefixCon _ args) = PrefixConGADT args + renderDetails (InfixCon arg1 arg2) = PrefixConGADT [arg1, arg2] renderDetails (RecCon recs) = RecConGADT recs noHsUniTok #endif @@ -257,12 +258,10 @@ prettyGADTDecl df decl = #endif #if MIN_VERSION_ghc(9,11,0) - adjustDefnWhere annDataDefn - | andd_where annDataDefn == NoEpTok = annDataDefn - | otherwise = annDataDefn {andd_where = andd_where'} - where - (EpTok (EpaSpan aw)) = andd_where annDataDefn - andd_where' = EpTok (EpaDelta aw (SameLine 1) []) + adjustDefnWhere annDataDefn = case andd_where annDataDefn of + NoEpTok -> annDataDefn + EpTok (EpaSpan aw) -> annDataDefn {andd_where = EpTok (EpaDelta aw (SameLine 1) [])} + EpTok (EpaDelta {}) -> annDataDefn -- already adjusted #endif -- Remove the first extra line if exist removeExtraEmptyLine s = case stripInfix "\n\n" s of diff --git a/plugins/hls-overloaded-record-dot-plugin/src/Ide/Plugin/OverloadedRecordDot.hs b/plugins/hls-overloaded-record-dot-plugin/src/Ide/Plugin/OverloadedRecordDot.hs index 8ead286b67..f2f71956b8 100644 --- a/plugins/hls-overloaded-record-dot-plugin/src/Ide/Plugin/OverloadedRecordDot.hs +++ b/plugins/hls-overloaded-record-dot-plugin/src/Ide/Plugin/OverloadedRecordDot.hs @@ -47,7 +47,11 @@ import Development.IDE.GHC.Compat (Extension (OverloadedReco getLoc, hs_valds, parenthesizeHsExpr, pattern RealSrcSpan, - unLoc) + unLoc +#if __GLASGOW_HASKELL__ >= 913 + , unLocWithUserRdr +#endif + ) import Development.IDE.GHC.Util (getExtensions, printOutputable) import Development.IDE.Graph (RuleResult) @@ -300,14 +304,22 @@ getRecSels e@(unLoc -> HsApp _ se@(unLoc -> HsRecSel _ _) re) = | RealSrcSpan realSpan' _ <- [ getLoc e ] ], False ) -- Record selection where the field is being applied with the "$" operator: -- "selector $ record" -#if __GLASGOW_HASKELL__ >= 911 +#if __GLASGOW_HASKELL__ >= 913 +getRecSels e@(unLoc -> OpApp _ se@(unLoc -> XExpr (HsRecSelRn _)) + (unLoc -> HsVar _ (unLocWithUserRdr -> d)) re) | d == dollarName = + ( [ RecordSelectorExpr (realSrcSpanToRange realSpan') se re + | RealSrcSpan realSpan' _ <- [ getLoc e ] ], False ) +#elif __GLASGOW_HASKELL__ >= 911 getRecSels e@(unLoc -> OpApp _ se@(unLoc -> XExpr (HsRecSelRn _)) + (unLoc -> HsVar _ (unLoc -> d)) re) | d == dollarName = + ( [ RecordSelectorExpr (realSrcSpanToRange realSpan') se re + | RealSrcSpan realSpan' _ <- [ getLoc e ] ], False ) #else getRecSels e@(unLoc -> OpApp _ se@(unLoc -> HsRecSel _ _) -#endif (unLoc -> HsVar _ (unLoc -> d)) re) | d == dollarName = ( [ RecordSelectorExpr (realSrcSpanToRange realSpan') se re | RealSrcSpan realSpan' _ <- [ getLoc e ] ], False ) +#endif getRecSels _ = ([], False) collectRecSelResult :: MonadIO m => IdeState -> NormalizedFilePath diff --git a/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction.hs b/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction.hs index 1fba6b67e5..9f57bb185a 100644 --- a/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction.hs +++ b/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction.hs @@ -1872,11 +1872,11 @@ extractQualifiedModuleName x -- ‘Data.Functor’ nor ‘Data.Text’ exports ‘putStrLn’. extractDoesNotExportModuleName :: T.Text -> Maybe T.Text extractDoesNotExportModuleName x - | Just [m] <- case ghcVersion of - GHC912 -> matchRegexUnifySpaces x "The module ‘([^’]*)’ does not export" - <|> matchRegexUnifySpaces x "nor ‘([^’]*)’ export" - _ -> matchRegexUnifySpaces x "the module ‘([^’]*)’ does not export" - <|> matchRegexUnifySpaces x "nor ‘([^’]*)’ export" + | Just [m] <- if ghcVersion >= GHC912 + then matchRegexUnifySpaces x "The module ‘([^’]*)’ does not export" + <|> matchRegexUnifySpaces x "nor ‘([^’]*)’ export" + else matchRegexUnifySpaces x "the module ‘([^’]*)’ does not export" + <|> matchRegexUnifySpaces x "nor ‘([^’]*)’ export" = Just m | otherwise = Nothing diff --git a/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction/ExactPrint.hs b/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction/ExactPrint.hs index bffd2a611c..f46f2571d5 100644 --- a/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction/ExactPrint.hs +++ b/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction/ExactPrint.hs @@ -43,7 +43,11 @@ import GHC (AnnContext (..), IsUnicodeSyntax (NormalSyntax), NameAdornment (NameParens), TrailingAnn (AddCommaAnn), - emptyComments, reAnnL) + emptyComments +#if !MIN_VERSION_ghc(9,13,0) + , reAnnL +#endif + ) -- See Note [Guidelines For Using CPP In GHCIDE Import Statements] @@ -66,6 +70,13 @@ import GHC (NoAnn (..)) import GHC (EpAnnComments (..)) #endif +#if MIN_VERSION_ghc(9,13,0) +import GHC (spanAsAnchor) + +reAnnL :: ann -> EpAnnComments -> Located e -> GenLocated (EpAnn ann) e +reAnnL anns cs (L l a) = L (EpAnn (spanAsAnchor l) anns cs) a +#endif + ------------------------------------------------------------------------------ -- | Construct a 'Rewrite', replacing the node at the given 'SrcSpan' with the diff --git a/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/Plugins/AddArgument.hs b/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/Plugins/AddArgument.hs index aec82cb17f..e316dc005e 100644 --- a/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/Plugins/AddArgument.hs +++ b/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/Plugins/AddArgument.hs @@ -49,6 +49,11 @@ import Language.Haskell.GHC.ExactPrint (d1, setEntryDP) import GHC.Parser.Annotation (EpToken (..)) #endif +#if MIN_VERSION_ghc(9,13,0) +-- HsArrow was renamed to HsMultAnn in GHC 9.13 +type HsArrow pass = HsMultAnn pass +#endif + -- When GHC tells us that a variable is not bound, it will tell us either: -- - there is an unbound variable with a given type -- - there is an unbound variable (GHC provides no type suggestion) @@ -177,7 +182,15 @@ hsTypeFromFunTypeAsList (args, res) = addTyHoleToTySigArg :: Int -> LHsSigType GhcPs -> LHsSigType GhcPs addTyHoleToTySigArg loc (L annHsSig (HsSig xHsSig tyVarBndrs lsigTy)) = let (args, res) = hsTypeToFunTypeAsList lsigTy -#if MIN_VERSION_ghc(9,9,0) +#if MIN_VERSION_ghc(9,13,0) + wildCardAnn = noAnnSrcSpanDP1 + newArg = + ( noAnn + , noExtField + , HsUnannotated (EpArrow (EpUniTok d1 NormalSyntax)) + , L wildCardAnn $ HsWildCardTy NoEpTok + ) +#elif MIN_VERSION_ghc(9,9,0) wildCardAnn = noAnnSrcSpanDP1 newArg = ( noAnn diff --git a/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/Plugins/FillTypeWildcard.hs b/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/Plugins/FillTypeWildcard.hs index 0f06fff2f7..43a0c246cc 100644 --- a/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/Plugins/FillTypeWildcard.hs +++ b/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/Plugins/FillTypeWildcard.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE CPP #-} module Development.IDE.Plugin.Plugins.FillTypeWildcard ( suggestFillTypeWildcard ) where @@ -14,6 +15,10 @@ import Development.IDE.Types.Diagnostics (_SomeStructuredMessage) import GHC.Tc.Errors.Types (ErrInfo (..)) import Language.LSP.Protocol.Types (Diagnostic (..), TextEdit (TextEdit)) +#if MIN_VERSION_ghc(9,13,0) +import GHC.Tc.Errors.Ppr (pprErrCtxtMsg) +import GHC.Utils.Outputable (vcat) +#endif suggestFillTypeWildcard :: FileDiagnostic -> [(T.Text, TextEdit)] suggestFillTypeWildcard diag@FileDiagnostic{fdLspDiagnostic = Diagnostic {..}} @@ -83,9 +88,13 @@ diagErrInfoContext diag = do . _TcRnMessageWithCtx . _TcRnMessageWithInfo let TcRnMessageDetailed err _ = detailedMsg +#if MIN_VERSION_ghc(9,13,0) + ErrInfo errInfoCtx _ _ = err + Just (printOutputable (vcat $ map pprErrCtxtMsg errInfoCtx)) +#else ErrInfo errInfoCtx _ = err - Just (printOutputable errInfoCtx) +#endif -- | Detect whether user wrote something like @foo :: _@ or @foo :: Maybe _@. -- The former is considered toplevel case for which the function returns 'True', diff --git a/plugins/hls-refactor-plugin/test/Main.hs b/plugins/hls-refactor-plugin/test/Main.hs index 0fb8b61f83..42cea85818 100644 --- a/plugins/hls-refactor-plugin/test/Main.hs +++ b/plugins/hls-refactor-plugin/test/Main.hs @@ -3379,7 +3379,9 @@ addSigActionTests = let executeCodeAction chosenAction modifiedCode <- documentContents doc liftIO $ expectedCode @=? modifiedCode - issue806 = if ghcVersion >= GHC910 then + issue806 = if ghcVersion >= GHC914 then + "hello = print" >:: "hello :: GHC.Internal.Types.ZonkAny 0 -> IO ()" -- GHC 9.14 moved to GHC.Internal.Types + else if ghcVersion >= GHC910 then "hello = print" >:: "hello :: GHC.Types.ZonkAny 0 -> IO ()" -- GHC now returns ZonkAny 0 instead of Any. https://gitlab.haskell.org/ghc/ghc/-/issues/25895 else "hello = print" >:: "hello :: GHC.Types.Any -> IO ()" -- Documents current behavior outlined in #806 diff --git a/plugins/hls-refactor-plugin/test/Test/AddArgument.hs b/plugins/hls-refactor-plugin/test/Test/AddArgument.hs index a0bf8b004e..d612e356f1 100644 --- a/plugins/hls-refactor-plugin/test/Test/AddArgument.hs +++ b/plugins/hls-refactor-plugin/test/Test/AddArgument.hs @@ -34,8 +34,8 @@ tests = mkGoldenAddArgTest "AddArgWithSigAndDocs" (r 8 0 8 50), mkGoldenAddArgTest "AddArgFromLet" (r 2 0 2 50), mkGoldenAddArgTest "AddArgFromWhere" (r 3 0 3 50), - -- TODO can we make this work for GHC 9.10? - knownBrokenForGhcVersions [GHC910, GHC912] "In GHC 9.10 and 9.12 end-of-line comment annotation is in different place" $ + -- TODO can we make this work for GHC 9.10+? + knownBrokenForGhcVersions [GHC910, GHC912, GHC914] "In GHC 9.10+ end-of-line comment annotation is in different place" $ mkGoldenAddArgTest "AddArgFromWhereComments" (r 3 0 3 50), mkGoldenAddArgTest "AddArgWithTypeSynSig" (r 2 0 2 50), mkGoldenAddArgTest "AddArgWithTypeSynSigContravariant" (r 2 0 2 50), diff --git a/test/testdata/schema/ghc914/default-config.golden.json b/test/testdata/schema/ghc914/default-config.golden.json new file mode 100644 index 0000000000..1eb7dd5be3 --- /dev/null +++ b/test/testdata/schema/ghc914/default-config.golden.json @@ -0,0 +1,140 @@ +{ + "cabalFormattingProvider": "cabal-gild", + "checkParents": "CheckOnSave", + "checkProject": true, + "formattingProvider": "ormolu", + "maxCompletions": 40, + "plugin": { + "alternateNumberFormat": { + "globalOn": true + }, + "cabal": { + "codeActionsOn": true, + "completionOn": true, + "diagnosticsOn": true, + "hoverOn": true, + "symbolsOn": true + }, + "cabal-fmt": { + "config": { + "path": "cabal-fmt" + } + }, + "cabal-gild": { + "config": { + "path": "cabal-gild" + } + }, + "cabalHaskellIntegration": { + "globalOn": true + }, + "callHierarchy": { + "globalOn": true + }, + "changeTypeSignature": { + "globalOn": true + }, + "class": { + "codeActionsOn": true, + "codeLensOn": true + }, + "eval": { + "codeActionsOn": true, + "codeLensOn": true, + "config": { + "diff": true, + "exception": false + } + }, + "explicit-fields": { + "codeActionsOn": true, + "inlayHintsOn": true + }, + "explicit-fixity": { + "globalOn": true + }, + "gadt": { + "globalOn": true + }, + "ghcide-code-actions-bindings": { + "globalOn": true + }, + "ghcide-code-actions-fill-holes": { + "globalOn": true + }, + "ghcide-code-actions-imports-exports": { + "globalOn": true + }, + "ghcide-code-actions-type-signatures": { + "globalOn": true + }, + "ghcide-completions": { + "config": { + "autoExtendOn": true, + "snippetsOn": true + }, + "globalOn": true + }, + "ghcide-hover-and-symbols": { + "hoverOn": true, + "symbolsOn": true + }, + "ghcide-type-lenses": { + "config": { + "mode": "always" + }, + "globalOn": true + }, + "importLens": { + "codeActionsOn": true, + "codeLensOn": true, + "inlayHintsOn": true + }, + "moduleName": { + "globalOn": true + }, + "overloaded-record-dot": { + "globalOn": true + }, + "pragmas-completion": { + "globalOn": true + }, + "pragmas-disable": { + "globalOn": true + }, + "pragmas-suggest": { + "globalOn": true + }, + "qualifyImportedNames": { + "globalOn": true + }, + "rename": { + "config": { + "crossModule": false + }, + "globalOn": true + }, + "semanticTokens": { + "config": { + "classMethodToken": "method", + "classToken": "class", + "dataConstructorToken": "enumMember", + "functionToken": "function", + "moduleToken": "namespace", + "operatorToken": "operator", + "patternSynonymToken": "macro", + "recordFieldToken": "property", + "typeConstructorToken": "enum", + "typeFamilyToken": "interface", + "typeSynonymToken": "type", + "typeVariableToken": "typeParameter", + "variableToken": "variable" + }, + "globalOn": false + }, + "signatureHelp": { + "globalOn": true + } + }, + "sessionLoading": "singleComponent" +} diff --git a/test/testdata/schema/ghc914/markdown-reference.md b/test/testdata/schema/ghc914/markdown-reference.md new file mode 100644 index 0000000000..a15c707e2e --- /dev/null +++ b/test/testdata/schema/ghc914/markdown-reference.md @@ -0,0 +1,50 @@ +## cabal-fmt +| Property | Description | Default | Allowed values | +| --- | --- | --- | --- | +| `path` | Set path to 'cabal-fmt' executable | `"cabal-fmt"` |   | + +## ghcide-completions +| Property | Description | Default | Allowed values | +| --- | --- | --- | --- | +| `autoExtendOn` | Extends the import list automatically when completing a out-of-scope identifier | `True` |   | +| `snippetsOn` | Inserts snippets when using code completions | `True` |   | + +## eval +| Property | Description | Default | Allowed values | +| --- | --- | --- | --- | +| `exception` | Enable marking exceptions with `*** Exception:` similarly to doctest and GHCi. | `False` |   | +| `diff` | Enable the diff output (WAS/NOW) of eval lenses | `True` |   | + +## ghcide-type-lenses +| Property | Description | Default | Allowed values | +| --- | --- | --- | --- | +| `mode` | Control how type lenses are shown | `Always` | | + +## rename +| Property | Description | Default | Allowed values | +| --- | --- | --- | --- | +| `crossModule` | Enable experimental cross-module renaming | `False` |   | + +## semanticTokens +| Property | Description | Default | Allowed values | +| --- | --- | --- | --- | +| `variableToken` | LSP semantic token type to use for variables | `SemanticTokenTypes_Variable` | | +| `functionToken` | LSP semantic token type to use for functions | `SemanticTokenTypes_Function` | | +| `dataConstructorToken` | LSP semantic token type to use for data constructors | `SemanticTokenTypes_EnumMember` | | +| `typeVariableToken` | LSP semantic token type to use for type variables | `SemanticTokenTypes_TypeParameter` | | +| `classMethodToken` | LSP semantic token type to use for typeclass methods | `SemanticTokenTypes_Method` | | +| `patternSynonymToken` | LSP semantic token type to use for pattern synonyms | `SemanticTokenTypes_Macro` | | +| `typeConstructorToken` | LSP semantic token type to use for type constructors | `SemanticTokenTypes_Enum` | | +| `classToken` | LSP semantic token type to use for typeclasses | `SemanticTokenTypes_Class` | | +| `typeSynonymToken` | LSP semantic token type to use for type synonyms | `SemanticTokenTypes_Type` | | +| `typeFamilyToken` | LSP semantic token type to use for type families | `SemanticTokenTypes_Interface` | | +| `recordFieldToken` | LSP semantic token type to use for record fields | `SemanticTokenTypes_Property` | | +| `operatorToken` | LSP semantic token type to use for operators | `SemanticTokenTypes_Operator` | | +| `moduleToken` | LSP semantic token type to use for modules | `SemanticTokenTypes_Namespace` | | + +## cabal-gild +| Property | Description | Default | Allowed values | +| --- | --- | --- | --- | +| `path` | Set path to 'cabal-gild' executable | `"cabal-gild"` |   | + + diff --git a/test/testdata/schema/ghc914/vscode-extension-schema.golden.json b/test/testdata/schema/ghc914/vscode-extension-schema.golden.json new file mode 100644 index 0000000000..9e858ac0cb --- /dev/null +++ b/test/testdata/schema/ghc914/vscode-extension-schema.golden.json @@ -0,0 +1,1010 @@ +{ + "haskell.plugin.alternateNumberFormat.globalOn": { + "default": true, + "description": "Enables alternateNumberFormat plugin", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.cabal-fmt.config.path": { + "default": "cabal-fmt", + "markdownDescription": "Set path to 'cabal-fmt' executable", + "scope": "resource", + "type": "string" + }, + "haskell.plugin.cabal-gild.config.path": { + "default": "cabal-gild", + "markdownDescription": "Set path to 'cabal-gild' executable", + "scope": "resource", + "type": "string" + }, + "haskell.plugin.cabal.codeActionsOn": { + "default": true, + "description": "Enables cabal code actions", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.cabal.completionOn": { + "default": true, + "description": "Enables cabal completions", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.cabal.diagnosticsOn": { + "default": true, + "description": "Enables cabal diagnostics", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.cabal.hoverOn": { + "default": true, + "description": "Enables cabal hover", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.cabal.symbolsOn": { + "default": true, + "description": "Enables cabal symbols", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.cabalHaskellIntegration.globalOn": { + "default": true, + "description": "Enables cabalHaskellIntegration plugin", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.callHierarchy.globalOn": { + "default": true, + "description": "Enables callHierarchy plugin", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.changeTypeSignature.globalOn": { + "default": true, + "description": "Enables changeTypeSignature plugin", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.class.codeActionsOn": { + "default": true, + "description": "Enables class code actions", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.class.codeLensOn": { + "default": true, + "description": "Enables class code lenses", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.eval.codeActionsOn": { + "default": true, + "description": "Enables eval code actions", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.eval.codeLensOn": { + "default": true, + "description": "Enables eval code lenses", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.eval.config.diff": { + "default": true, + "markdownDescription": "Enable the diff output (WAS/NOW) of eval lenses", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.eval.config.exception": { + "default": false, + "markdownDescription": "Enable marking exceptions with `*** Exception:` similarly to doctest and GHCi.", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.explicit-fields.codeActionsOn": { + "default": true, + "description": "Enables explicit-fields code actions", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.explicit-fields.inlayHintsOn": { + "default": true, + "description": "Enables explicit-fields inlay hints", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.explicit-fixity.globalOn": { + "default": true, + "description": "Enables explicit-fixity plugin", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.gadt.globalOn": { + "default": true, + "description": "Enables gadt plugin", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.ghcide-code-actions-bindings.globalOn": { + "default": true, + "description": "Enables ghcide-code-actions-bindings plugin", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.ghcide-code-actions-fill-holes.globalOn": { + "default": true, + "description": "Enables ghcide-code-actions-fill-holes plugin", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.ghcide-code-actions-imports-exports.globalOn": { + "default": true, + "description": "Enables ghcide-code-actions-imports-exports plugin", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.ghcide-code-actions-type-signatures.globalOn": { + "default": true, + "description": "Enables ghcide-code-actions-type-signatures plugin", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.ghcide-completions.config.autoExtendOn": { + "default": true, + "markdownDescription": "Extends the import list automatically when completing a out-of-scope identifier", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.ghcide-completions.config.snippetsOn": { + "default": true, + "markdownDescription": "Inserts snippets when using code completions", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.ghcide-completions.globalOn": { + "default": true, + "description": "Enables ghcide-completions plugin", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.ghcide-hover-and-symbols.hoverOn": { + "default": true, + "description": "Enables ghcide-hover-and-symbols hover", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.ghcide-hover-and-symbols.symbolsOn": { + "default": true, + "description": "Enables ghcide-hover-and-symbols symbols", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.ghcide-type-lenses.config.mode": { + "default": "always", + "description": "Control how type lenses are shown", + "enum": [ + "always", + "exported", + "diagnostics" + ], + "enumDescriptions": [ + "Always displays type lenses of global bindings", + "Only display type lenses of exported global bindings", + "Follows error messages produced by GHC about missing signatures" + ], + "scope": "resource", + "type": "string" + }, + "haskell.plugin.ghcide-type-lenses.globalOn": { + "default": true, + "description": "Enables ghcide-type-lenses plugin", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.importLens.codeActionsOn": { + "default": true, + "description": "Enables importLens code actions", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.importLens.codeLensOn": { + "default": true, + "description": "Enables importLens code lenses", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.importLens.inlayHintsOn": { + "default": true, + "description": "Enables importLens inlay hints", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.moduleName.globalOn": { + "default": true, + "description": "Enables moduleName plugin", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.overloaded-record-dot.globalOn": { + "default": true, + "description": "Enables overloaded-record-dot plugin", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.pragmas-completion.globalOn": { + "default": true, + "description": "Enables pragmas-completion plugin", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.pragmas-disable.globalOn": { + "default": true, + "description": "Enables pragmas-disable plugin", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.pragmas-suggest.globalOn": { + "default": true, + "description": "Enables pragmas-suggest plugin", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.qualifyImportedNames.globalOn": { + "default": true, + "description": "Enables qualifyImportedNames plugin", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.rename.config.crossModule": { + "default": false, + "markdownDescription": "Enable experimental cross-module renaming", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.rename.globalOn": { + "default": true, + "description": "Enables rename plugin", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.semanticTokens.config.classMethodToken": { + "default": "method", + "description": "LSP semantic token type to use for typeclass methods", + "enum": [ + "namespace", + "type", + "class", + "enum", + "interface", + "struct", + "typeParameter", + "parameter", + "variable", + "property", + "enumMember", + "event", + "function", + "method", + "macro", + "keyword", + "modifier", + "comment", + "string", + "number", + "regexp", + "operator", + "decorator" + ], + "enumDescriptions": [ + "LSP Semantic Token Type: namespace", + "LSP Semantic Token Type: type", + "LSP Semantic Token Type: class", + "LSP Semantic Token Type: enum", + "LSP Semantic Token Type: interface", + "LSP Semantic Token Type: struct", + "LSP Semantic Token Type: typeParameter", + "LSP Semantic Token Type: parameter", + "LSP Semantic Token Type: variable", + "LSP Semantic Token Type: property", + "LSP Semantic Token Type: enumMember", + "LSP Semantic Token Type: event", + "LSP Semantic Token Type: function", + "LSP Semantic Token Type: method", + "LSP Semantic Token Type: macro", + "LSP Semantic Token Type: keyword", + "LSP Semantic Token Type: modifier", + "LSP Semantic Token Type: comment", + "LSP Semantic Token Type: string", + "LSP Semantic Token Type: number", + "LSP Semantic Token Type: regexp", + "LSP Semantic Token Type: operator", + "LSP Semantic Token Type: decorator" + ], + "scope": "resource", + "type": "string" + }, + "haskell.plugin.semanticTokens.config.classToken": { + "default": "class", + "description": "LSP semantic token type to use for typeclasses", + "enum": [ + "namespace", + "type", + "class", + "enum", + "interface", + "struct", + "typeParameter", + "parameter", + "variable", + "property", + "enumMember", + "event", + "function", + "method", + "macro", + "keyword", + "modifier", + "comment", + "string", + "number", + "regexp", + "operator", + "decorator" + ], + "enumDescriptions": [ + "LSP Semantic Token Type: namespace", + "LSP Semantic Token Type: type", + "LSP Semantic Token Type: class", + "LSP Semantic Token Type: enum", + "LSP Semantic Token Type: interface", + "LSP Semantic Token Type: struct", + "LSP Semantic Token Type: typeParameter", + "LSP Semantic Token Type: parameter", + "LSP Semantic Token Type: variable", + "LSP Semantic Token Type: property", + "LSP Semantic Token Type: enumMember", + "LSP Semantic Token Type: event", + "LSP Semantic Token Type: function", + "LSP Semantic Token Type: method", + "LSP Semantic Token Type: macro", + "LSP Semantic Token Type: keyword", + "LSP Semantic Token Type: modifier", + "LSP Semantic Token Type: comment", + "LSP Semantic Token Type: string", + "LSP Semantic Token Type: number", + "LSP Semantic Token Type: regexp", + "LSP Semantic Token Type: operator", + "LSP Semantic Token Type: decorator" + ], + "scope": "resource", + "type": "string" + }, + "haskell.plugin.semanticTokens.config.dataConstructorToken": { + "default": "enumMember", + "description": "LSP semantic token type to use for data constructors", + "enum": [ + "namespace", + "type", + "class", + "enum", + "interface", + "struct", + "typeParameter", + "parameter", + "variable", + "property", + "enumMember", + "event", + "function", + "method", + "macro", + "keyword", + "modifier", + "comment", + "string", + "number", + "regexp", + "operator", + "decorator" + ], + "enumDescriptions": [ + "LSP Semantic Token Type: namespace", + "LSP Semantic Token Type: type", + "LSP Semantic Token Type: class", + "LSP Semantic Token Type: enum", + "LSP Semantic Token Type: interface", + "LSP Semantic Token Type: struct", + "LSP Semantic Token Type: typeParameter", + "LSP Semantic Token Type: parameter", + "LSP Semantic Token Type: variable", + "LSP Semantic Token Type: property", + "LSP Semantic Token Type: enumMember", + "LSP Semantic Token Type: event", + "LSP Semantic Token Type: function", + "LSP Semantic Token Type: method", + "LSP Semantic Token Type: macro", + "LSP Semantic Token Type: keyword", + "LSP Semantic Token Type: modifier", + "LSP Semantic Token Type: comment", + "LSP Semantic Token Type: string", + "LSP Semantic Token Type: number", + "LSP Semantic Token Type: regexp", + "LSP Semantic Token Type: operator", + "LSP Semantic Token Type: decorator" + ], + "scope": "resource", + "type": "string" + }, + "haskell.plugin.semanticTokens.config.functionToken": { + "default": "function", + "description": "LSP semantic token type to use for functions", + "enum": [ + "namespace", + "type", + "class", + "enum", + "interface", + "struct", + "typeParameter", + "parameter", + "variable", + "property", + "enumMember", + "event", + "function", + "method", + "macro", + "keyword", + "modifier", + "comment", + "string", + "number", + "regexp", + "operator", + "decorator" + ], + "enumDescriptions": [ + "LSP Semantic Token Type: namespace", + "LSP Semantic Token Type: type", + "LSP Semantic Token Type: class", + "LSP Semantic Token Type: enum", + "LSP Semantic Token Type: interface", + "LSP Semantic Token Type: struct", + "LSP Semantic Token Type: typeParameter", + "LSP Semantic Token Type: parameter", + "LSP Semantic Token Type: variable", + "LSP Semantic Token Type: property", + "LSP Semantic Token Type: enumMember", + "LSP Semantic Token Type: event", + "LSP Semantic Token Type: function", + "LSP Semantic Token Type: method", + "LSP Semantic Token Type: macro", + "LSP Semantic Token Type: keyword", + "LSP Semantic Token Type: modifier", + "LSP Semantic Token Type: comment", + "LSP Semantic Token Type: string", + "LSP Semantic Token Type: number", + "LSP Semantic Token Type: regexp", + "LSP Semantic Token Type: operator", + "LSP Semantic Token Type: decorator" + ], + "scope": "resource", + "type": "string" + }, + "haskell.plugin.semanticTokens.config.moduleToken": { + "default": "namespace", + "description": "LSP semantic token type to use for modules", + "enum": [ + "namespace", + "type", + "class", + "enum", + "interface", + "struct", + "typeParameter", + "parameter", + "variable", + "property", + "enumMember", + "event", + "function", + "method", + "macro", + "keyword", + "modifier", + "comment", + "string", + "number", + "regexp", + "operator", + "decorator" + ], + "enumDescriptions": [ + "LSP Semantic Token Type: namespace", + "LSP Semantic Token Type: type", + "LSP Semantic Token Type: class", + "LSP Semantic Token Type: enum", + "LSP Semantic Token Type: interface", + "LSP Semantic Token Type: struct", + "LSP Semantic Token Type: typeParameter", + "LSP Semantic Token Type: parameter", + "LSP Semantic Token Type: variable", + "LSP Semantic Token Type: property", + "LSP Semantic Token Type: enumMember", + "LSP Semantic Token Type: event", + "LSP Semantic Token Type: function", + "LSP Semantic Token Type: method", + "LSP Semantic Token Type: macro", + "LSP Semantic Token Type: keyword", + "LSP Semantic Token Type: modifier", + "LSP Semantic Token Type: comment", + "LSP Semantic Token Type: string", + "LSP Semantic Token Type: number", + "LSP Semantic Token Type: regexp", + "LSP Semantic Token Type: operator", + "LSP Semantic Token Type: decorator" + ], + "scope": "resource", + "type": "string" + }, + "haskell.plugin.semanticTokens.config.operatorToken": { + "default": "operator", + "description": "LSP semantic token type to use for operators", + "enum": [ + "namespace", + "type", + "class", + "enum", + "interface", + "struct", + "typeParameter", + "parameter", + "variable", + "property", + "enumMember", + "event", + "function", + "method", + "macro", + "keyword", + "modifier", + "comment", + "string", + "number", + "regexp", + "operator", + "decorator" + ], + "enumDescriptions": [ + "LSP Semantic Token Type: namespace", + "LSP Semantic Token Type: type", + "LSP Semantic Token Type: class", + "LSP Semantic Token Type: enum", + "LSP Semantic Token Type: interface", + "LSP Semantic Token Type: struct", + "LSP Semantic Token Type: typeParameter", + "LSP Semantic Token Type: parameter", + "LSP Semantic Token Type: variable", + "LSP Semantic Token Type: property", + "LSP Semantic Token Type: enumMember", + "LSP Semantic Token Type: event", + "LSP Semantic Token Type: function", + "LSP Semantic Token Type: method", + "LSP Semantic Token Type: macro", + "LSP Semantic Token Type: keyword", + "LSP Semantic Token Type: modifier", + "LSP Semantic Token Type: comment", + "LSP Semantic Token Type: string", + "LSP Semantic Token Type: number", + "LSP Semantic Token Type: regexp", + "LSP Semantic Token Type: operator", + "LSP Semantic Token Type: decorator" + ], + "scope": "resource", + "type": "string" + }, + "haskell.plugin.semanticTokens.config.patternSynonymToken": { + "default": "macro", + "description": "LSP semantic token type to use for pattern synonyms", + "enum": [ + "namespace", + "type", + "class", + "enum", + "interface", + "struct", + "typeParameter", + "parameter", + "variable", + "property", + "enumMember", + "event", + "function", + "method", + "macro", + "keyword", + "modifier", + "comment", + "string", + "number", + "regexp", + "operator", + "decorator" + ], + "enumDescriptions": [ + "LSP Semantic Token Type: namespace", + "LSP Semantic Token Type: type", + "LSP Semantic Token Type: class", + "LSP Semantic Token Type: enum", + "LSP Semantic Token Type: interface", + "LSP Semantic Token Type: struct", + "LSP Semantic Token Type: typeParameter", + "LSP Semantic Token Type: parameter", + "LSP Semantic Token Type: variable", + "LSP Semantic Token Type: property", + "LSP Semantic Token Type: enumMember", + "LSP Semantic Token Type: event", + "LSP Semantic Token Type: function", + "LSP Semantic Token Type: method", + "LSP Semantic Token Type: macro", + "LSP Semantic Token Type: keyword", + "LSP Semantic Token Type: modifier", + "LSP Semantic Token Type: comment", + "LSP Semantic Token Type: string", + "LSP Semantic Token Type: number", + "LSP Semantic Token Type: regexp", + "LSP Semantic Token Type: operator", + "LSP Semantic Token Type: decorator" + ], + "scope": "resource", + "type": "string" + }, + "haskell.plugin.semanticTokens.config.recordFieldToken": { + "default": "property", + "description": "LSP semantic token type to use for record fields", + "enum": [ + "namespace", + "type", + "class", + "enum", + "interface", + "struct", + "typeParameter", + "parameter", + "variable", + "property", + "enumMember", + "event", + "function", + "method", + "macro", + "keyword", + "modifier", + "comment", + "string", + "number", + "regexp", + "operator", + "decorator" + ], + "enumDescriptions": [ + "LSP Semantic Token Type: namespace", + "LSP Semantic Token Type: type", + "LSP Semantic Token Type: class", + "LSP Semantic Token Type: enum", + "LSP Semantic Token Type: interface", + "LSP Semantic Token Type: struct", + "LSP Semantic Token Type: typeParameter", + "LSP Semantic Token Type: parameter", + "LSP Semantic Token Type: variable", + "LSP Semantic Token Type: property", + "LSP Semantic Token Type: enumMember", + "LSP Semantic Token Type: event", + "LSP Semantic Token Type: function", + "LSP Semantic Token Type: method", + "LSP Semantic Token Type: macro", + "LSP Semantic Token Type: keyword", + "LSP Semantic Token Type: modifier", + "LSP Semantic Token Type: comment", + "LSP Semantic Token Type: string", + "LSP Semantic Token Type: number", + "LSP Semantic Token Type: regexp", + "LSP Semantic Token Type: operator", + "LSP Semantic Token Type: decorator" + ], + "scope": "resource", + "type": "string" + }, + "haskell.plugin.semanticTokens.config.typeConstructorToken": { + "default": "enum", + "description": "LSP semantic token type to use for type constructors", + "enum": [ + "namespace", + "type", + "class", + "enum", + "interface", + "struct", + "typeParameter", + "parameter", + "variable", + "property", + "enumMember", + "event", + "function", + "method", + "macro", + "keyword", + "modifier", + "comment", + "string", + "number", + "regexp", + "operator", + "decorator" + ], + "enumDescriptions": [ + "LSP Semantic Token Type: namespace", + "LSP Semantic Token Type: type", + "LSP Semantic Token Type: class", + "LSP Semantic Token Type: enum", + "LSP Semantic Token Type: interface", + "LSP Semantic Token Type: struct", + "LSP Semantic Token Type: typeParameter", + "LSP Semantic Token Type: parameter", + "LSP Semantic Token Type: variable", + "LSP Semantic Token Type: property", + "LSP Semantic Token Type: enumMember", + "LSP Semantic Token Type: event", + "LSP Semantic Token Type: function", + "LSP Semantic Token Type: method", + "LSP Semantic Token Type: macro", + "LSP Semantic Token Type: keyword", + "LSP Semantic Token Type: modifier", + "LSP Semantic Token Type: comment", + "LSP Semantic Token Type: string", + "LSP Semantic Token Type: number", + "LSP Semantic Token Type: regexp", + "LSP Semantic Token Type: operator", + "LSP Semantic Token Type: decorator" + ], + "scope": "resource", + "type": "string" + }, + "haskell.plugin.semanticTokens.config.typeFamilyToken": { + "default": "interface", + "description": "LSP semantic token type to use for type families", + "enum": [ + "namespace", + "type", + "class", + "enum", + "interface", + "struct", + "typeParameter", + "parameter", + "variable", + "property", + "enumMember", + "event", + "function", + "method", + "macro", + "keyword", + "modifier", + "comment", + "string", + "number", + "regexp", + "operator", + "decorator" + ], + "enumDescriptions": [ + "LSP Semantic Token Type: namespace", + "LSP Semantic Token Type: type", + "LSP Semantic Token Type: class", + "LSP Semantic Token Type: enum", + "LSP Semantic Token Type: interface", + "LSP Semantic Token Type: struct", + "LSP Semantic Token Type: typeParameter", + "LSP Semantic Token Type: parameter", + "LSP Semantic Token Type: variable", + "LSP Semantic Token Type: property", + "LSP Semantic Token Type: enumMember", + "LSP Semantic Token Type: event", + "LSP Semantic Token Type: function", + "LSP Semantic Token Type: method", + "LSP Semantic Token Type: macro", + "LSP Semantic Token Type: keyword", + "LSP Semantic Token Type: modifier", + "LSP Semantic Token Type: comment", + "LSP Semantic Token Type: string", + "LSP Semantic Token Type: number", + "LSP Semantic Token Type: regexp", + "LSP Semantic Token Type: operator", + "LSP Semantic Token Type: decorator" + ], + "scope": "resource", + "type": "string" + }, + "haskell.plugin.semanticTokens.config.typeSynonymToken": { + "default": "type", + "description": "LSP semantic token type to use for type synonyms", + "enum": [ + "namespace", + "type", + "class", + "enum", + "interface", + "struct", + "typeParameter", + "parameter", + "variable", + "property", + "enumMember", + "event", + "function", + "method", + "macro", + "keyword", + "modifier", + "comment", + "string", + "number", + "regexp", + "operator", + "decorator" + ], + "enumDescriptions": [ + "LSP Semantic Token Type: namespace", + "LSP Semantic Token Type: type", + "LSP Semantic Token Type: class", + "LSP Semantic Token Type: enum", + "LSP Semantic Token Type: interface", + "LSP Semantic Token Type: struct", + "LSP Semantic Token Type: typeParameter", + "LSP Semantic Token Type: parameter", + "LSP Semantic Token Type: variable", + "LSP Semantic Token Type: property", + "LSP Semantic Token Type: enumMember", + "LSP Semantic Token Type: event", + "LSP Semantic Token Type: function", + "LSP Semantic Token Type: method", + "LSP Semantic Token Type: macro", + "LSP Semantic Token Type: keyword", + "LSP Semantic Token Type: modifier", + "LSP Semantic Token Type: comment", + "LSP Semantic Token Type: string", + "LSP Semantic Token Type: number", + "LSP Semantic Token Type: regexp", + "LSP Semantic Token Type: operator", + "LSP Semantic Token Type: decorator" + ], + "scope": "resource", + "type": "string" + }, + "haskell.plugin.semanticTokens.config.typeVariableToken": { + "default": "typeParameter", + "description": "LSP semantic token type to use for type variables", + "enum": [ + "namespace", + "type", + "class", + "enum", + "interface", + "struct", + "typeParameter", + "parameter", + "variable", + "property", + "enumMember", + "event", + "function", + "method", + "macro", + "keyword", + "modifier", + "comment", + "string", + "number", + "regexp", + "operator", + "decorator" + ], + "enumDescriptions": [ + "LSP Semantic Token Type: namespace", + "LSP Semantic Token Type: type", + "LSP Semantic Token Type: class", + "LSP Semantic Token Type: enum", + "LSP Semantic Token Type: interface", + "LSP Semantic Token Type: struct", + "LSP Semantic Token Type: typeParameter", + "LSP Semantic Token Type: parameter", + "LSP Semantic Token Type: variable", + "LSP Semantic Token Type: property", + "LSP Semantic Token Type: enumMember", + "LSP Semantic Token Type: event", + "LSP Semantic Token Type: function", + "LSP Semantic Token Type: method", + "LSP Semantic Token Type: macro", + "LSP Semantic Token Type: keyword", + "LSP Semantic Token Type: modifier", + "LSP Semantic Token Type: comment", + "LSP Semantic Token Type: string", + "LSP Semantic Token Type: number", + "LSP Semantic Token Type: regexp", + "LSP Semantic Token Type: operator", + "LSP Semantic Token Type: decorator" + ], + "scope": "resource", + "type": "string" + }, + "haskell.plugin.semanticTokens.config.variableToken": { + "default": "variable", + "description": "LSP semantic token type to use for variables", + "enum": [ + "namespace", + "type", + "class", + "enum", + "interface", + "struct", + "typeParameter", + "parameter", + "variable", + "property", + "enumMember", + "event", + "function", + "method", + "macro", + "keyword", + "modifier", + "comment", + "string", + "number", + "regexp", + "operator", + "decorator" + ], + "enumDescriptions": [ + "LSP Semantic Token Type: namespace", + "LSP Semantic Token Type: type", + "LSP Semantic Token Type: class", + "LSP Semantic Token Type: enum", + "LSP Semantic Token Type: interface", + "LSP Semantic Token Type: struct", + "LSP Semantic Token Type: typeParameter", + "LSP Semantic Token Type: parameter", + "LSP Semantic Token Type: variable", + "LSP Semantic Token Type: property", + "LSP Semantic Token Type: enumMember", + "LSP Semantic Token Type: event", + "LSP Semantic Token Type: function", + "LSP Semantic Token Type: method", + "LSP Semantic Token Type: macro", + "LSP Semantic Token Type: keyword", + "LSP Semantic Token Type: modifier", + "LSP Semantic Token Type: comment", + "LSP Semantic Token Type: string", + "LSP Semantic Token Type: number", + "LSP Semantic Token Type: regexp", + "LSP Semantic Token Type: operator", + "LSP Semantic Token Type: decorator" + ], + "scope": "resource", + "type": "string" + }, + "haskell.plugin.semanticTokens.globalOn": { + "default": false, + "description": "Enables semanticTokens plugin", + "scope": "resource", + "type": "boolean" + }, + "haskell.plugin.signatureHelp.globalOn": { + "default": true, + "description": "Enables signatureHelp plugin", + "scope": "resource", + "type": "boolean" + } +}