haskell-language-server 2.10.0.0 → 2.11.0.0
raw patch · 47 files changed
+3016/−1108 lines, 47 filesdep −monoid-subclassesdep ~fourmoludep ~ghcidedep ~hiedb
Dependencies removed: monoid-subclasses
Dependency ranges changed: fourmolu, ghcide, hiedb, hlint, hls-graph, hls-plugin-api, hls-test-utils, ormolu, stylish-haskell
Files
- ChangeLog.md +69/−0
- ghcide-test/data/watched-files/reload/reload.cabal +12/−0
- ghcide-test/data/watched-files/reload/src/MyLib.hs +6/−0
- ghcide-test/exe/FuzzySearch.hs +39/−117
- ghcide-test/exe/UnitTests.hs +0/−2
- ghcide-test/exe/WatchedFileTests.hs +16/−1
- haskell-language-server.cabal +149/−146
- plugins/hls-cabal-plugin/src/Ide/Plugin/Cabal/CabalAdd.hs +14/−3
- plugins/hls-cabal-plugin/src/Ide/Plugin/Cabal/Completion/Completer/Paths.hs +5/−0
- plugins/hls-cabal-plugin/src/Ide/Plugin/Cabal/Completion/Data.hs +42/−11
- plugins/hls-cabal-plugin/test/CabalAdd.hs +19/−0
- plugins/hls-cabal-plugin/test/Completer.hs +23/−1
- plugins/hls-cabal-plugin/test/Main.hs +0/−23
- plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-tests/cabal-add-tests.cabal +8/−0
- plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-tests/test/MainPackageImports.hs +8/−0
- plugins/hls-cabal-plugin/test/testdata/completion/autogen-completion.cabal +25/−0
- plugins/hls-eval-plugin/src/Ide/Plugin/Eval.hs +7/−4
- plugins/hls-eval-plugin/src/Ide/Plugin/Eval/CodeLens.hs +0/−675
- plugins/hls-eval-plugin/src/Ide/Plugin/Eval/Handlers.hs +695/−0
- plugins/hls-eval-plugin/test/Main.hs +26/−7
- plugins/hls-explicit-imports-plugin/src/Ide/Plugin/ExplicitImports.hs +12/−11
- plugins/hls-explicit-record-fields-plugin/src/Ide/Plugin/ExplicitFields.hs +20/−15
- plugins/hls-gadt-plugin/src/Ide/Plugin/GHC.hs +41/−5
- plugins/hls-hlint-plugin/test/Main.hs +18/−8
- plugins/hls-refactor-plugin/src/Development/IDE/GHC/ExactPrint.hs +42/−6
- plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction.hs +118/−19
- plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction/ExactPrint.hs +43/−7
- plugins/hls-refactor-plugin/src/Development/IDE/Plugin/Plugins/AddArgument.hs +17/−2
- plugins/hls-refactor-plugin/src/Development/IDE/Plugin/Plugins/Diagnostic.hs +3/−0
- plugins/hls-refactor-plugin/test/Main.hs +164/−10
- plugins/hls-refactor-plugin/test/Test/AddArgument.hs +1/−1
- plugins/hls-stylish-haskell-plugin/src/Ide/Plugin/StylishHaskell.hs +5/−0
- test/testdata/hieBiosError/hie.yaml +0/−0
- test/testdata/hieBiosMainIs/dist-newstyle/cache/plan.json +0/−1
- test/testdata/missingModuleTest/missingModule/dist-newstyle/cache/plan.json +0/−1
- test/testdata/missingModuleTest/noPrefixMatch/dist-newstyle/cache/plan.json +1/−0
- test/testdata/schema/ghc910/default-config.golden.json +151/−0
- test/testdata/schema/ghc910/vscode-extension-schema.golden.json +1028/−0
- test/testdata/schema/ghc912/default-config.golden.json +47/−2
- test/testdata/schema/ghc912/vscode-extension-schema.golden.json +96/−6
- test/testdata/schema/ghc94/default-config.golden.json +3/−2
- test/testdata/schema/ghc94/vscode-extension-schema.golden.json +12/−6
- test/testdata/schema/ghc96/default-config.golden.json +3/−2
- test/testdata/schema/ghc96/vscode-extension-schema.golden.json +12/−6
- test/testdata/schema/ghc98/default-config.golden.json +3/−2
- test/testdata/schema/ghc98/vscode-extension-schema.golden.json +12/−6
- test/testdata/wErrorTest/dist-newstyle/cache/plan.json +1/−0
ChangeLog.md view
@@ -1,5 +1,74 @@ # Changelog for haskell-language-server ++## 2.11.0.0++- Bindists for GHC 9.12.2+ - Full plugin support, inlcuding refactor plugin+- Bindists for GHC 9.10.2+- Bindists for GHC 9.8.4+- Bindists for GHC 9.6.7+- Bindists for GHC 9.4.8+- Dropped support for Centos 7 as this platform is no longer supported by ghc+- Improved import suggestions for contructors and OverloadedRecordDot fields++### Pull Requests++- Add doc for project-wide renaming+ ([#4584](https://github.com/haskell/haskell-language-server/pull/4584)) by @jian-lin+- Use hie-bios 0.15.0+ ([#4582](https://github.com/haskell/haskell-language-server/pull/4582)) by @fendor+- Allow building HLS with GHC 9.10.2+ ([#4581](https://github.com/haskell/haskell-language-server/pull/4581)) by @fendor+- Fix Plugin support table for 9.12.2+ ([#4580](https://github.com/haskell/haskell-language-server/pull/4580)) by @fendor+- Fix misplaced inlay hints by applying PositionMapping+ ([#4571](https://github.com/haskell/haskell-language-server/pull/4571)) by @jetjinser+- Enable hls-plugin-gadt for ghc-9.12+ ([#4568](https://github.com/haskell/haskell-language-server/pull/4568)) by @GuillaumedeVolpiano+- Remove no longer needed allow-newer+ ([#4566](https://github.com/haskell/haskell-language-server/pull/4566)) by @jhrcek+- Add missing golden files for GHC 9.10 config tests+ ([#4563](https://github.com/haskell/haskell-language-server/pull/4563)) by @jian-lin+- updating the plugins support table for refactor+ ([#4560](https://github.com/haskell/haskell-language-server/pull/4560)) by @GuillaumedeVolpiano+- Enable stylish-haskell for ghc-9.10 and ghc-9.12+ ([#4559](https://github.com/haskell/haskell-language-server/pull/4559)) by @GuillaumedeVolpiano+- Bump haskell-actions/setup from 2.7.10 to 2.7.11+ ([#4557](https://github.com/haskell/haskell-language-server/pull/4557)) by @dependabot[bot]+- Provide code action in hls-eval-plugin+ ([#4556](https://github.com/haskell/haskell-language-server/pull/4556)) by @jian-lin+- enable hlint for ghc-9.12+ ([#4555](https://github.com/haskell/haskell-language-server/pull/4555)) by @GuillaumedeVolpiano+- Enable fourmolu and ormolu for GHC 9.12+ ([#4554](https://github.com/haskell/haskell-language-server/pull/4554)) by @fendor+- Enable hls-cabal-gild-plugin for GHC 9.12.2+ ([#4553](https://github.com/haskell/haskell-language-server/pull/4553)) by @fendor+- Update plugin support table for GHC 9.12.2+ ([#4552](https://github.com/haskell/haskell-language-server/pull/4552)) by @fendor+- Remove allow-newer for hiedb+ ([#4551](https://github.com/haskell/haskell-language-server/pull/4551)) by @jhrcek+- Fix typo of rename plugin config+ ([#4546](https://github.com/haskell/haskell-language-server/pull/4546)) by @jian-lin+- Update the ghcup-metadata generation script+ ([#4545](https://github.com/haskell/haskell-language-server/pull/4545)) by @fendor+- porting hls-refactor to ghc-9.12+ ([#4543](https://github.com/haskell/haskell-language-server/pull/4543)) by @GuillaumedeVolpiano+- add ghcide-bench flag to .cabal file+ ([#4542](https://github.com/haskell/haskell-language-server/pull/4542)) by @juhp+- Revert "link executables dynamically to speed up linking (#4423)"+ ([#4541](https://github.com/haskell/haskell-language-server/pull/4541)) by @fendor+- Support PackageImports in hiddenPackageSuggestion+ ([#4537](https://github.com/haskell/haskell-language-server/pull/4537)) by @jian-lin+- Improve FreeBSD installation docs+ ([#4536](https://github.com/haskell/haskell-language-server/pull/4536)) by @arrowd+- reinstating ignore-plugins-ghc-bounds+ ([#4532](https://github.com/haskell/haskell-language-server/pull/4532)) by @GuillaumedeVolpiano+- Simplify FuzzySearch test (avoid dependency on /usr/share/dict/words)+ ([#4531](https://github.com/haskell/haskell-language-server/pull/4531)) by @jhrcek+- Import suggestion for missing newtype constructor, all types constructor and indirect overloadedrecorddot fields+ ([#4516](https://github.com/haskell/haskell-language-server/pull/4516)) by @guibou+ ## 2.10.0.0 - Bindists for GHC 9.12.2
+ ghcide-test/data/watched-files/reload/reload.cabal view
@@ -0,0 +1,12 @@+cabal-version: 2.4+name: reload+version: 0.1.0.0+author: Lin Jian+maintainer: me@linj.tech+build-type: Simple++library+ exposed-modules: MyLib+ build-depends: base+ hs-source-dirs: src+ default-language: Haskell2010
+ ghcide-test/data/watched-files/reload/src/MyLib.hs view
@@ -0,0 +1,6 @@+module MyLib (someFunc) where++import Data.List.Split++someFunc :: IO ()+someFunc = putStrLn "someFunc"
ghcide-test/exe/FuzzySearch.hs view
@@ -1,130 +1,52 @@ module FuzzySearch (tests) where -import Data.Char (toLower)-import Data.Maybe (catMaybes)-import qualified Data.Monoid.Textual as T-import Data.Text (Text, inits, pack)-import qualified Data.Text as Text-import Prelude hiding (filter)-import System.Directory (doesFileExist)-import System.IO.Unsafe (unsafePerformIO)-import Test.QuickCheck+import Data.Maybe (isJust, mapMaybe)+import Data.Text (Text)+import qualified Data.Text as Text+import Prelude hiding (filter) import Test.Tasty-import Test.Tasty.ExpectedFailure-import Test.Tasty.QuickCheck (testProperty)-import qualified Text.Fuzzy as Fuzzy-import Text.Fuzzy (Fuzzy (..))+import Test.Tasty.HUnit+import Test.Tasty.QuickCheck import Text.Fuzzy.Parallel tests :: TestTree tests = testGroup "Fuzzy search"- [ needDictionary $- testGroup- "match works as expected on the english dictionary"- [ testProperty "for legit words" propLegit,- testProperty "for prefixes" propPrefix,- testProperty "for typos" propTypo- ]+ [ testGroup "match"+ [ testCase "empty" $+ match "" "" @?= Just 0+ , testCase "camel case" $+ match "myImportantField" "myImportantField" @?= Just 262124+ , testCase "a" $+ mapMaybe (matchInput "a") ["", "a", "aa", "aaa", "A", "AA", "aA", "Aa"]+ @?= [("a",3),("aa",3),("aaa",3),("aA",3),("Aa",1)]+ , testCase "lowercase words" $+ mapMaybe (matchInput "abc") ["abc", "abcd", "axbc", "axbxc", "def"]+ @?= [("abc", 25), ("abcd", 25), ("axbc", 7), ("axbxc", 5)]+ , testCase "lower upper mix" $+ mapMaybe (matchInput "abc") ["abc", "aBc", "axbC", "axBxC", "def"]+ @?= [("abc", 25), ("aBc", 25), ("axbC", 7), ("axBxC", 5)]+ , testCase "prefixes" $+ mapMaybe (matchInput "alpha") (Text.inits "alphabet")+ @?= [("alpha", 119), ("alphab", 119), ("alphabe", 119), ("alphabet", 119)]+ , testProperty "x `isSubsequenceOf` y => match x y returns Just"+ prop_matchIfSubsequence+ ] ]--test :: Text -> Bool-test candidate = do- let previous =- catMaybes- [ (d,) . Fuzzy.score- <$> referenceImplementation candidate d "" "" id- | d <- dictionary- ]- new = catMaybes [(d,) <$> match candidate d | d <- dictionary]- previous == new--propLegit :: Property-propLegit = forAll (elements dictionary) test--propPrefix :: Property-propPrefix = forAll (elements dictionary >>= elements . inits) test--propTypo :: Property-propTypo = forAll typoGen test--typoGen :: Gen Text-typoGen = do- w <- elements dictionary- l <- elements [0 .. Text.length w -1]- let wl = Text.index w l- c <- elements [ c | c <- ['a' .. 'z'], c /= wl]- return $ replaceAt w l c--replaceAt :: Text -> Int -> Char -> Text-replaceAt t i c =- let (l, r) = Text.splitAt i t- in l <> Text.singleton c <> r--dictionaryPath :: FilePath-dictionaryPath = "/usr/share/dict/words"--{-# ANN dictionary ("HLint: ignore Avoid restricted function" :: String) #-}-{-# NOINLINE dictionary #-}-dictionary :: [Text]-dictionary = unsafePerformIO $ do- existsDictionary <- doesFileExist dictionaryPath- if existsDictionary- then map pack . words <$> readFile dictionaryPath- else pure []--referenceImplementation :: forall s t.- (T.TextualMonoid s) =>- -- | Pattern in lowercase except for first character- s ->- -- | The value containing the text to search in.- t ->- -- | The text to add before each match.- s ->- -- | The text to add after each match.- s ->- -- | The function to extract the text from the container.- (t -> s) ->- -- | The original value, rendered string and score.- Maybe (Fuzzy t s)-referenceImplementation pat' t pre post extract =- if null pat then Just (Fuzzy t result totalScore) else Nothing where- null :: (T.TextualMonoid s) => s -> Bool- null = not . T.any (const True)+ matchInput :: Text -> Text -> Maybe (Text, Int)+ matchInput needle candidate = (candidate,) <$> match needle candidate - s = extract t- (totalScore, _currScore, result, pat, _) =- T.foldl'- undefined- ( \(tot, cur, res, pat, isFirst) c ->- case T.splitCharacterPrefix pat of- Nothing -> (tot, 0, res <> T.singleton c, pat, isFirst)- Just (x, xs) ->- -- the case of the first character has to match- -- otherwise use lower case since the pattern is assumed lower- let !c' = if isFirst then c else toLower c- in if x == c'- then- let cur' = cur * 2 + 1- in ( tot + cur',- cur',- res <> pre <> T.singleton c <> post,- xs,- False- )- else (tot, 0, res <> T.singleton c, pat, isFirst)- )- ( 0,- 1, -- matching at the start gives a bonus (cur = 1)- mempty,- pat',- True- )- s+prop_matchIfSubsequence :: Property+prop_matchIfSubsequence =+ forAll genNonEmptyText $ \haystack ->+ forAll (genSubsequence haystack) $ \needle ->+ isJust (match needle haystack)+ where+ genNonEmptyText =+ Text.pack <$> listOf1 (elements $ ['a'..'z'] ++ ['A'..'Z'] ++ ['0'..'9']) -needDictionary :: TestTree -> TestTree-needDictionary- | null dictionary = ignoreTestBecause ("not found: " <> dictionaryPath)- | otherwise = id+ genSubsequence :: Text -> Gen Text+ genSubsequence =+ fmap Text.pack . sublistOf . Text.unpack
ghcide-test/exe/UnitTests.hs view
@@ -29,8 +29,6 @@ import System.IO.Extra hiding (withTempDir) import System.Mem (performGC) import Test.Hls (IdeState, def,- ignoreForGhcVersions,- GhcVersion(..), runSessionWithServerInTmpDir, waitForProgressDone) import Test.Tasty
ghcide-test/exe/WatchedFileTests.hs view
@@ -3,11 +3,14 @@ module WatchedFileTests (tests) where -import Config (testWithDummyPluginEmpty')+import Config (mkIdeTestFs,+ testWithDummyPlugin',+ testWithDummyPluginEmpty') import Control.Applicative.Combinators import Control.Monad.IO.Class (liftIO) import qualified Data.Aeson as A import qualified Data.Text as T+import qualified Data.Text.IO as T import Development.IDE.Test (expectDiagnostics) import Language.LSP.Protocol.Message import Language.LSP.Protocol.Types hiding@@ -18,6 +21,7 @@ import Language.LSP.Test import System.Directory import System.FilePath+import Test.Hls.FileSystem import Test.Tasty import Test.Tasty.HUnit @@ -69,6 +73,17 @@ sendNotification SMethod_WorkspaceDidChangeWatchedFiles $ DidChangeWatchedFilesParams [FileEvent (filePathToUri $ sessionDir </> "B.hs") FileChangeType_Changed ] expectDiagnostics [("A.hs", [(DiagnosticSeverity_Error, (3, 4), "Couldn't match expected type '()' with actual type 'Int'", Just "GHC-83865")])]+ , testWithDummyPlugin' "reload HLS after .cabal file changes" (mkIdeTestFs [copyDir ("watched-files" </> "reload")]) $ \sessionDir -> do+ let hsFile = "src" </> "MyLib.hs"+ _ <- openDoc hsFile "haskell"+ expectDiagnostics [(hsFile, [(DiagnosticSeverity_Error, (2, 7), "Could not load module \8216Data.List.Split\8217", Nothing)])]+ let cabalFile = "reload.cabal"+ cabalContent <- liftIO $ T.readFile cabalFile+ let fix = T.replace "build-depends: base" "build-depends: base, split"+ liftIO $ T.writeFile cabalFile (fix cabalContent)+ sendNotification SMethod_WorkspaceDidChangeWatchedFiles $ DidChangeWatchedFilesParams+ [ FileEvent (filePathToUri $ sessionDir </> cabalFile) FileChangeType_Changed ]+ expectDiagnostics [(hsFile, [])] ] ]
haskell-language-server.cabal view
@@ -1,7 +1,7 @@ cabal-version: 3.4 category: Development name: haskell-language-server-version: 2.10.0.0+version: 2.11.0.0 synopsis: LSP server for GHC description: Please see the README on GitHub at <https://github.com/haskell/haskell-language-server#readme>@@ -117,7 +117,7 @@ manual: True common cabalfmt- if flag(cabalfmt)+ if flag(cabalfmt) && flag(cabal) build-depends: haskell-language-server:hls-cabal-fmt-plugin cpp-options: -Dhls_cabalfmt @@ -129,15 +129,15 @@ library hls-cabal-fmt-plugin import: defaults, pedantic, warnings- if !flag(cabalfmt)+ if !flag(cabalfmt) || !flag(cabal) buildable: False exposed-modules: Ide.Plugin.CabalFmt hs-source-dirs: plugins/hls-cabal-fmt-plugin/src build-depends: , directory , filepath- , ghcide == 2.10.0.0- , hls-plugin-api == 2.10.0.0+ , ghcide == 2.11.0.0+ , hls-plugin-api == 2.11.0.0 , lens , lsp-types , mtl@@ -157,8 +157,8 @@ , filepath , haskell-language-server:hls-cabal-plugin , haskell-language-server:hls-cabal-fmt-plugin- , hls-plugin-api == 2.10.0.0- , hls-test-utils == 2.10.0.0+ , hls-plugin-api == 2.11.0.0+ , hls-test-utils == 2.11.0.0 if flag(isolateCabalfmtTests) build-tool-depends: cabal-fmt:cabal-fmt ^>=0.1.12@@ -174,7 +174,7 @@ manual: True common cabalgild- if flag(cabalgild) && impl(ghc < 9.11)+ if flag(cabalgild) && flag(cabal) build-depends: haskell-language-server:hls-cabal-gild-plugin cpp-options: -Dhls_cabalgild @@ -186,15 +186,15 @@ library hls-cabal-gild-plugin import: defaults, pedantic, warnings- if !flag(cabalgild) || impl(ghc > 9.11)+ if !flag(cabalgild) || !flag(cabal) buildable: False exposed-modules: Ide.Plugin.CabalGild hs-source-dirs: plugins/hls-cabal-gild-plugin/src build-depends: , directory , filepath- , ghcide == 2.10.0.0- , hls-plugin-api == 2.10.0.0+ , ghcide == 2.11.0.0+ , hls-plugin-api == 2.11.0.0 , lsp-types , text , mtl@@ -203,7 +203,7 @@ -- The `hls-cabal-plugin` is needed for tests, as we need to install notification handlers test-suite hls-cabal-gild-plugin-tests import: defaults, pedantic, test-defaults, warnings- if !flag(cabalgild) || !flag(cabal) || impl(ghc > 9.11)+ if !flag(cabalgild) || !flag(cabal) buildable: False type: exitcode-stdio-1.0 hs-source-dirs: plugins/hls-cabal-gild-plugin/test@@ -213,8 +213,8 @@ , filepath , haskell-language-server:hls-cabal-plugin , haskell-language-server:hls-cabal-gild-plugin- , hls-plugin-api == 2.10.0.0- , hls-test-utils == 2.10.0.0+ , hls-plugin-api == 2.11.0.0+ , hls-test-utils == 2.11.0.0 if flag(isolateCabalGildTests) -- https://github.com/tfausak/cabal-gild/issues/89@@ -269,10 +269,10 @@ , directory , filepath , extra >=1.7.4- , ghcide == 2.10.0.0+ , ghcide == 2.11.0.0 , hashable- , hls-plugin-api == 2.10.0.0- , hls-graph == 2.10.0.0+ , hls-plugin-api == 2.11.0.0+ , hls-graph == 2.11.0.0 , lens , lsp ^>=2.7 , lsp-types ^>=2.3@@ -311,7 +311,7 @@ , filepath , ghcide , haskell-language-server:hls-cabal-plugin- , hls-test-utils == 2.10.0.0+ , hls-test-utils == 2.11.0.0 , lens , lsp-types , text@@ -349,9 +349,9 @@ , extra , ghc , ghc-exactprint >= 1.5 && < 1.13.0.0- , ghcide == 2.10.0.0+ , ghcide == 2.11.0.0 , hls-graph- , hls-plugin-api == 2.10.0.0+ , hls-plugin-api == 2.11.0.0 , lens , lsp , mtl@@ -372,7 +372,7 @@ build-depends: , filepath , haskell-language-server:hls-class-plugin- , hls-test-utils == 2.10.0.0+ , hls-test-utils == 2.11.0.0 , lens , lsp-types , text@@ -406,9 +406,9 @@ , aeson , containers , extra- , ghcide == 2.10.0.0- , hiedb ^>= 0.6.0.0- , hls-plugin-api == 2.10.0.0+ , ghcide == 2.11.0.0+ , hiedb ^>= 0.6.0.2+ , hls-plugin-api == 2.11.0.0 , lens , lsp >=2.7 , sqlite-simple@@ -429,7 +429,7 @@ , extra , filepath , haskell-language-server:hls-call-hierarchy-plugin- , hls-test-utils == 2.10.0.0+ , hls-test-utils == 2.11.0.0 , lens , lsp , lsp-test@@ -460,9 +460,9 @@ hs-source-dirs: plugins/hls-eval-plugin/src other-modules: Ide.Plugin.Eval.Code- Ide.Plugin.Eval.CodeLens Ide.Plugin.Eval.Config Ide.Plugin.Eval.GHC+ Ide.Plugin.Eval.Handlers Ide.Plugin.Eval.Parse.Comments Ide.Plugin.Eval.Parse.Option Ide.Plugin.Eval.Rules@@ -479,9 +479,9 @@ , filepath , ghc , ghc-boot-th- , ghcide == 2.10.0.0+ , ghcide == 2.11.0.0 , hls-graph- , hls-plugin-api == 2.10.0.0+ , hls-plugin-api == 2.11.0.0 , lens , lsp , lsp-types@@ -512,7 +512,7 @@ , filepath , haskell-language-server:hls-eval-plugin , hls-plugin-api- , hls-test-utils == 2.10.0.0+ , hls-test-utils == 2.11.0.0 , lens , lsp-types , text@@ -542,9 +542,9 @@ , containers , deepseq , ghc- , ghcide == 2.10.0.0+ , ghcide == 2.11.0.0 , hls-graph- , hls-plugin-api == 2.10.0.0+ , hls-plugin-api == 2.11.0.0 , lens , lsp , mtl@@ -565,7 +565,7 @@ , extra , filepath , haskell-language-server:hls-explicit-imports-plugin- , hls-test-utils == 2.10.0.0+ , hls-test-utils == 2.11.0.0 , lens , lsp-types , text@@ -580,23 +580,23 @@ manual: True common rename- if flag(rename) && impl(ghc < 9.11)+ if flag(rename) build-depends: haskell-language-server:hls-rename-plugin cpp-options: -Dhls_rename library hls-rename-plugin import: defaults, pedantic, warnings- if !flag(rename) || impl(ghc > 9.11)+ if !flag(rename) buildable: False exposed-modules: Ide.Plugin.Rename hs-source-dirs: plugins/hls-rename-plugin/src build-depends: , containers- , ghcide == 2.10.0.0+ , ghcide == 2.11.0.0 , hashable- , hiedb ^>= 0.6.0.0+ , hiedb ^>= 0.6.0.2 , hie-compat- , hls-plugin-api == 2.10.0.0+ , hls-plugin-api == 2.11.0.0 , haskell-language-server:hls-refactor-plugin , lens , lsp-types@@ -610,7 +610,7 @@ test-suite hls-rename-plugin-tests import: defaults, pedantic, test-defaults, warnings- if !flag(rename) || impl(ghc > 9.11)+ if !flag(rename) buildable: False type: exitcode-stdio-1.0 hs-source-dirs: plugins/hls-rename-plugin/test@@ -621,7 +621,7 @@ , filepath , hls-plugin-api , haskell-language-server:hls-rename-plugin- , hls-test-utils == 2.10.0.0+ , hls-test-utils == 2.11.0.0 , lens , lsp-types , text@@ -636,13 +636,13 @@ manual: True common retrie- if flag(retrie) && impl(ghc < 9.10)+ if flag(retrie) && (impl(ghc < 9.10) || flag(ignore-plugins-ghc-bounds)) build-depends: haskell-language-server:hls-retrie-plugin cpp-options: -Dhls_retrie library hls-retrie-plugin import: defaults, pedantic, warnings- if !(flag(retrie) && impl(ghc < 9.10))+ if !(flag(retrie) && (impl(ghc < 9.10) || flag(ignore-plugins-ghc-bounds))) buildable: False exposed-modules: Ide.Plugin.Retrie hs-source-dirs: plugins/hls-retrie-plugin/src@@ -652,9 +652,9 @@ , containers , extra , ghc- , ghcide == 2.10.0.0+ , ghcide == 2.11.0.0 , hashable- , hls-plugin-api == 2.10.0.0+ , hls-plugin-api == 2.11.0.0 , haskell-language-server:hls-refactor-plugin , lens , lsp@@ -673,7 +673,7 @@ test-suite hls-retrie-plugin-tests import: defaults, pedantic, test-defaults, warnings- if !(flag(retrie) && impl(ghc < 9.10))+ if !(flag(retrie) && (impl(ghc < 9.10) || flag(ignore-plugins-ghc-bounds))) buildable: False type: exitcode-stdio-1.0 hs-source-dirs: plugins/hls-retrie-plugin/test@@ -683,7 +683,7 @@ , filepath , hls-plugin-api , haskell-language-server:{hls-refactor-plugin, hls-retrie-plugin}- , hls-test-utils == 2.10.0.0+ , hls-test-utils == 2.11.0.0 , text -----------------------------@@ -703,14 +703,14 @@ manual: True common hlint- if flag(hlint) && impl(ghc < 9.10)+ if flag(hlint) && ((impl(ghc < 9.10) || impl(ghc > 9.11)) || flag(ignore-plugins-ghc-bounds)) build-depends: haskell-language-server:hls-hlint-plugin cpp-options: -Dhls_hlint library hls-hlint-plugin import: defaults, pedantic, warnings -- https://github.com/ndmitchell/hlint/pull/1594- if !(flag(hlint)) || impl(ghc > 9.10)+ if !(flag(hlint)) || ((impl(ghc >= 9.10) && impl(ghc < 9.11)) && !flag(ignore-plugins-ghc-bounds)) buildable: False exposed-modules: Ide.Plugin.Hlint hs-source-dirs: plugins/hls-hlint-plugin/src@@ -720,10 +720,10 @@ , containers , deepseq , filepath- , ghcide == 2.10.0.0+ , ghcide == 2.11.0.0 , hashable- , hlint >= 3.5 && < 3.9- , hls-plugin-api == 2.10.0.0+ , hlint >= 3.5 && < 3.11+ , hls-plugin-api == 2.11.0.0 , lens , mtl , refact@@ -753,7 +753,7 @@ test-suite hls-hlint-plugin-tests import: defaults, pedantic, test-defaults, warnings- if (!flag(hlint)) || impl(ghc > 9.10)+ if !flag(hlint) || ((impl(ghc >= 9.10) && impl(ghc < 9.11)) && !flag(ignore-plugins-ghc-bounds)) buildable: False type: exitcode-stdio-1.0 hs-source-dirs: plugins/hls-hlint-plugin/test@@ -767,7 +767,7 @@ , filepath , haskell-language-server:hls-hlint-plugin , hls-plugin-api- , hls-test-utils == 2.10.0.0+ , hls-test-utils == 2.11.0.0 , lens , lsp-types , text@@ -782,13 +782,13 @@ manual: True common stan- if flag(stan) && impl(ghc < 9.11)+ if flag(stan) && (impl(ghc < 9.11) || flag(ignore-plugins-ghc-bounds)) build-depends: haskell-language-server:hls-stan-plugin cpp-options: -Dhls_stan library hls-stan-plugin import: defaults, pedantic, warnings- if !flag(stan) || impl(ghc > 9.11)+ if !flag(stan) || (impl(ghc > 9.11) && !flag(ignore-plugins-ghc-bounds)) buildable: False exposed-modules: Ide.Plugin.Stan hs-source-dirs: plugins/hls-stan-plugin/src@@ -813,7 +813,7 @@ test-suite hls-stan-plugin-tests import: defaults, pedantic, test-defaults, warnings- if !flag(stan) || impl(ghc > 9.11)+ if !flag(stan) || (impl(ghc > 9.11) && !flag(ignore-plugins-ghc-bounds)) buildable: False type: exitcode-stdio-1.0 hs-source-dirs: plugins/hls-stan-plugin/test@@ -822,7 +822,7 @@ , filepath , haskell-language-server:hls-stan-plugin , hls-plugin-api- , hls-test-utils == 2.10.0.0+ , hls-test-utils == 2.11.0.0 , lens , lsp-types , text@@ -853,8 +853,8 @@ , aeson , containers , filepath- , ghcide == 2.10.0.0- , hls-plugin-api == 2.10.0.0+ , ghcide == 2.11.0.0+ , hls-plugin-api == 2.11.0.0 , lsp , text , text-rope@@ -871,7 +871,7 @@ build-depends: , filepath , haskell-language-server:hls-module-name-plugin- , hls-test-utils == 2.10.0.0+ , hls-test-utils == 2.11.0.0 ----------------------------- -- pragmas plugin@@ -897,8 +897,8 @@ , aeson , extra , fuzzy- , ghcide == 2.10.0.0- , hls-plugin-api == 2.10.0.0+ , ghcide == 2.11.0.0+ , hls-plugin-api == 2.11.0.0 , lens , lens-aeson , lsp@@ -917,7 +917,7 @@ , aeson , filepath , haskell-language-server:hls-pragmas-plugin- , hls-test-utils == 2.10.0.0+ , hls-test-utils == 2.11.0.0 , lens , lsp-types , text@@ -932,13 +932,13 @@ manual: True common splice- if flag(splice) && impl(ghc < 9.10)+ if flag(splice) && (impl(ghc < 9.10) || flag(ignore-plugins-ghc-bounds)) build-depends: haskell-language-server:hls-splice-plugin cpp-options: -Dhls_splice library hls-splice-plugin import: defaults, pedantic, warnings- if !(flag(splice) && impl(ghc < 9.10))+ if !(flag(splice) && (impl(ghc < 9.10) || flag(ignore-plugins-ghc-bounds))) buildable: False exposed-modules: Ide.Plugin.Splice@@ -950,8 +950,8 @@ , extra , foldl , ghc- , ghcide == 2.10.0.0- , hls-plugin-api == 2.10.0.0+ , ghcide == 2.11.0.0+ , hls-plugin-api == 2.11.0.0 , haskell-language-server:hls-refactor-plugin , lens , lsp@@ -966,7 +966,7 @@ test-suite hls-splice-plugin-tests import: defaults, pedantic, test-defaults, warnings- if !(flag(splice) && impl(ghc < 9.10))+ if !(flag(splice) && (impl(ghc < 9.10) || flag(ignore-plugins-ghc-bounds))) buildable: False type: exitcode-stdio-1.0 hs-source-dirs: plugins/hls-splice-plugin/test@@ -974,7 +974,7 @@ build-depends: , filepath , haskell-language-server:hls-splice-plugin- , hls-test-utils == 2.10.0.0+ , hls-test-utils == 2.11.0.0 , text -----------------------------@@ -1001,10 +1001,10 @@ build-depends: , containers , extra- , ghcide == 2.10.0.0+ , ghcide == 2.11.0.0 , ghc-boot-th , hls-graph- , hls-plugin-api == 2.10.0.0+ , hls-plugin-api == 2.11.0.0 , lens , lsp ^>=2.7 , mtl@@ -1029,7 +1029,7 @@ build-depends: , filepath , haskell-language-server:hls-alternate-number-format-plugin- , hls-test-utils == 2.10.0.0+ , hls-test-utils == 2.11.0.0 , regex-tdfa , tasty-quickcheck , text@@ -1061,8 +1061,8 @@ hs-source-dirs: plugins/hls-qualify-imported-names-plugin/src build-depends: , containers- , ghcide == 2.10.0.0- , hls-plugin-api == 2.10.0.0+ , ghcide == 2.11.0.0+ , hls-plugin-api == 2.11.0.0 , lens , lsp , text@@ -1084,7 +1084,7 @@ , text , filepath , haskell-language-server:hls-qualify-imported-names-plugin- , hls-test-utils == 2.10.0.0+ , hls-test-utils == 2.11.0.0 ----------------------------- -- code range plugin@@ -1114,9 +1114,9 @@ , containers , deepseq , extra- , ghcide == 2.10.0.0+ , ghcide == 2.11.0.0 , hashable- , hls-plugin-api == 2.10.0.0+ , hls-plugin-api == 2.11.0.0 , lens , lsp , mtl@@ -1138,7 +1138,7 @@ , bytestring , filepath , haskell-language-server:hls-code-range-plugin- , hls-test-utils == 2.10.0.0+ , hls-test-utils == 2.11.0.0 , lens , lsp , lsp-test@@ -1166,8 +1166,8 @@ exposed-modules: Ide.Plugin.ChangeTypeSignature hs-source-dirs: plugins/hls-change-type-signature-plugin/src build-depends:- , ghcide == 2.10.0.0- , hls-plugin-api == 2.10.0.0+ , ghcide == 2.11.0.0+ , hls-plugin-api == 2.11.0.0 , lsp-types , regex-tdfa , syb@@ -1191,7 +1191,7 @@ build-depends: , filepath , haskell-language-server:hls-change-type-signature-plugin- , hls-test-utils == 2.10.0.0+ , hls-test-utils == 2.11.0.0 , regex-tdfa , text default-extensions:@@ -1208,13 +1208,13 @@ manual: True common gadt- if flag(gadt) && impl(ghc < 9.11)+ if flag(gadt) build-depends: haskell-language-server:hls-gadt-plugin cpp-options: -Dhls_gadt library hls-gadt-plugin import: defaults, pedantic, warnings- if !flag(gadt) || impl(ghc > 9.11)+ if !flag(gadt) buildable: False exposed-modules: Ide.Plugin.GADT other-modules: Ide.Plugin.GHC@@ -1224,9 +1224,9 @@ , containers , extra , ghc- , ghcide == 2.10.0.0+ , ghcide == 2.11.0.0 , ghc-exactprint- , hls-plugin-api == 2.10.0.0+ , hls-plugin-api == 2.11.0.0 , haskell-language-server:hls-refactor-plugin , lens , lsp >=2.7@@ -1238,7 +1238,7 @@ test-suite hls-gadt-plugin-tests import: defaults, pedantic, test-defaults, warnings- if !flag(gadt) || impl(ghc > 9.11)+ if !flag(gadt) buildable: False type: exitcode-stdio-1.0 hs-source-dirs: plugins/hls-gadt-plugin/test@@ -1246,7 +1246,7 @@ build-depends: , filepath , haskell-language-server:hls-gadt-plugin- , hls-test-utils == 2.10.0.0+ , hls-test-utils == 2.11.0.0 , text -----------------------------@@ -1273,9 +1273,9 @@ , containers , deepseq , extra- , ghcide == 2.10.0.0+ , ghcide == 2.11.0.0 , hashable- , hls-plugin-api == 2.10.0.0+ , hls-plugin-api == 2.11.0.0 , lsp >=2.7 , text @@ -1291,7 +1291,7 @@ build-depends: , filepath , haskell-language-server:hls-explicit-fixity-plugin- , hls-test-utils == 2.10.0.0+ , hls-test-utils == 2.11.0.0 , text -----------------------------@@ -1314,8 +1314,8 @@ buildable: False exposed-modules: Ide.Plugin.ExplicitFields build-depends:- , ghcide == 2.10.0.0- , hls-plugin-api == 2.10.0.0+ , ghcide == 2.11.0.0+ , hls-plugin-api == 2.11.0.0 , lsp , lens , hls-graph@@ -1341,7 +1341,7 @@ , text , ghcide , haskell-language-server:hls-explicit-record-fields-plugin- , hls-test-utils == 2.10.0.0+ , hls-test-utils == 2.11.0.0 ----------------------------- -- overloaded record dot plugin@@ -1387,7 +1387,7 @@ , filepath , text , haskell-language-server:hls-overloaded-record-dot-plugin- , hls-test-utils == 2.10.0.0+ , hls-test-utils == 2.11.0.0 -----------------------------@@ -1400,21 +1400,21 @@ manual: True common floskell- if flag(floskell) && impl(ghc < 9.10)+ if flag(floskell) && (impl(ghc < 9.10) || flag(ignore-plugins-ghc-bounds)) build-depends: haskell-language-server:hls-floskell-plugin cpp-options: -Dhls_floskell library hls-floskell-plugin import: defaults, pedantic, warnings -- https://github.com/ennocramer/floskell/pull/82- if !(flag(floskell) && impl(ghc < 9.10))+ if !(flag(floskell) && (impl(ghc < 9.10) || flag(ignore-plugins-ghc-bounds))) buildable: False exposed-modules: Ide.Plugin.Floskell hs-source-dirs: plugins/hls-floskell-plugin/src build-depends: , floskell ^>=0.11.0- , ghcide == 2.10.0.0- , hls-plugin-api == 2.10.0.0+ , ghcide == 2.11.0.0+ , hls-plugin-api == 2.11.0.0 , lsp-types ^>=2.3 , mtl , text@@ -1422,7 +1422,7 @@ test-suite hls-floskell-plugin-tests import: defaults, pedantic, test-defaults, warnings- if !(flag(floskell) && impl(ghc < 9.10))+ if !(flag(floskell) && (impl(ghc < 9.10) || flag(ignore-plugins-ghc-bounds))) buildable: False type: exitcode-stdio-1.0 hs-source-dirs: plugins/hls-floskell-plugin/test@@ -1430,7 +1430,7 @@ build-depends: , filepath , haskell-language-server:hls-floskell-plugin- , hls-test-utils == 2.10.0.0+ , hls-test-utils == 2.11.0.0 ----------------------------- -- fourmolu plugin@@ -1442,22 +1442,22 @@ manual: True common fourmolu- if flag(fourmolu) && impl(ghc < 9.11)+ if flag(fourmolu) build-depends: haskell-language-server:hls-fourmolu-plugin cpp-options: -Dhls_fourmolu library hls-fourmolu-plugin import: defaults, pedantic, warnings- if !flag(fourmolu) || impl(ghc > 9.11)+ if !flag(fourmolu) buildable: False exposed-modules: Ide.Plugin.Fourmolu hs-source-dirs: plugins/hls-fourmolu-plugin/src build-depends: , filepath- , fourmolu ^>= 0.14 || ^>= 0.15 || ^>= 0.16+ , fourmolu ^>= 0.14 || ^>= 0.15 || ^>= 0.16 || ^>=0.17 || ^>=0.18 , ghc-boot-th- , ghcide == 2.10.0.0- , hls-plugin-api == 2.10.0.0+ , ghcide == 2.11.0.0+ , hls-plugin-api == 2.11.0.0 , lens , lsp , mtl@@ -1468,7 +1468,7 @@ test-suite hls-fourmolu-plugin-tests import: defaults, pedantic, test-defaults, warnings- if !flag(fourmolu) || impl(ghc > 9.11)+ if !flag(fourmolu) buildable: False type: exitcode-stdio-1.0 hs-source-dirs: plugins/hls-fourmolu-plugin/test@@ -1483,7 +1483,7 @@ , filepath , haskell-language-server:hls-fourmolu-plugin , hls-plugin-api- , hls-test-utils == 2.10.0.0+ , hls-test-utils == 2.11.0.0 , lsp-test -----------------------------@@ -1496,13 +1496,13 @@ manual: True common ormolu- if flag(ormolu) && impl(ghc < 9.11)+ if flag(ormolu) build-depends: haskell-language-server:hls-ormolu-plugin cpp-options: -Dhls_ormolu library hls-ormolu-plugin import: defaults, pedantic, warnings- if !flag(ormolu) || impl(ghc > 9.11)+ if !flag(ormolu) buildable: False exposed-modules: Ide.Plugin.Ormolu hs-source-dirs: plugins/hls-ormolu-plugin/src@@ -1510,19 +1510,19 @@ , extra , filepath , ghc-boot-th- , ghcide == 2.10.0.0- , hls-plugin-api == 2.10.0.0+ , ghcide == 2.11.0.0+ , hls-plugin-api == 2.11.0.0 , lsp , mtl , process-extras >= 0.7.1- , ormolu ^>=0.1.2 || ^>= 0.2 || ^>= 0.3 || ^>= 0.5 || ^>= 0.6 || ^>= 0.7+ , ormolu ^>=0.5.3 || ^>= 0.6 || ^>= 0.7 || ^>=0.8 , text , transformers test-suite hls-ormolu-plugin-tests import: defaults, pedantic, test-defaults, warnings- if !flag(ormolu) || impl(ghc > 9.11)+ if !flag(ormolu) buildable: False type: exitcode-stdio-1.0 hs-source-dirs: plugins/hls-ormolu-plugin/test@@ -1537,7 +1537,7 @@ , filepath , haskell-language-server:hls-ormolu-plugin , hls-plugin-api- , hls-test-utils == 2.10.0.0+ , hls-test-utils == 2.11.0.0 , lsp-types , ormolu @@ -1551,14 +1551,14 @@ manual: True common stylishHaskell- if flag(stylishHaskell) && impl(ghc < 9.10)+ if flag(stylishHaskell) 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) && impl(ghc < 9.10))+ if !flag(stylishHaskell) buildable: False exposed-modules: Ide.Plugin.StylishHaskell hs-source-dirs: plugins/hls-stylish-haskell-plugin/src@@ -1566,17 +1566,17 @@ , directory , filepath , ghc-boot-th- , ghcide == 2.10.0.0- , hls-plugin-api == 2.10.0.0+ , ghcide == 2.11.0.0+ , hls-plugin-api == 2.11.0.0 , lsp-types , mtl- , stylish-haskell ^>=0.12 || ^>=0.13 || ^>=0.14+ , stylish-haskell >=0.12 && <0.16 , text test-suite hls-stylish-haskell-plugin-tests import: defaults, pedantic, test-defaults, warnings- if !(flag(stylishHaskell) && impl(ghc < 9.10))+ if !flag(stylishHaskell) buildable: False type: exitcode-stdio-1.0 hs-source-dirs: plugins/hls-stylish-haskell-plugin/test@@ -1584,7 +1584,7 @@ build-depends: , filepath , haskell-language-server:hls-stylish-haskell-plugin- , hls-test-utils == 2.10.0.0+ , hls-test-utils == 2.11.0.0 ----------------------------- -- refactor plugin@@ -1596,13 +1596,13 @@ manual: True common refactor- if flag(refactor) && impl(ghc < 9.11)+ if flag(refactor) build-depends: haskell-language-server:hls-refactor-plugin cpp-options: -Dhls_refactor library hls-refactor-plugin import: defaults, pedantic, warnings- if !flag(refactor) || impl(ghc > 9.11)+ if !flag(refactor) buildable: False exposed-modules: Development.IDE.GHC.ExactPrint Development.IDE.GHC.Compat.ExactPrint@@ -1636,8 +1636,8 @@ , bytestring , ghc-boot , regex-tdfa- , ghcide == 2.10.0.0- , hls-plugin-api == 2.10.0.0+ , ghcide == 2.11.0.0+ , hls-plugin-api == 2.11.0.0 , lsp , text , text-rope@@ -1661,7 +1661,7 @@ test-suite hls-refactor-plugin-tests import: defaults, pedantic, test-defaults, warnings- if !flag(refactor) || impl(ghc > 9.11)+ if !flag(refactor) buildable: False type: exitcode-stdio-1.0 hs-source-dirs: plugins/hls-refactor-plugin/test@@ -1675,7 +1675,7 @@ , filepath , ghcide:ghcide , haskell-language-server:hls-refactor-plugin- , hls-test-utils == 2.10.0.0+ , hls-test-utils == 2.11.0.0 , lens , lsp-test , lsp-types@@ -1722,8 +1722,8 @@ , extra , text-rope , mtl >= 2.2- , ghcide == 2.10.0.0- , hls-plugin-api == 2.10.0.0+ , ghcide == 2.11.0.0+ , hls-plugin-api == 2.11.0.0 , lens , lsp >=2.6 , text@@ -1733,7 +1733,7 @@ , array , deepseq , dlist- , hls-graph == 2.10.0.0+ , hls-graph == 2.11.0.0 , template-haskell , data-default , stm@@ -1754,10 +1754,10 @@ , containers , data-default , filepath- , ghcide == 2.10.0.0+ , ghcide == 2.11.0.0 , haskell-language-server:hls-semantic-tokens-plugin- , hls-plugin-api == 2.10.0.0- , hls-test-utils == 2.10.0.0+ , hls-plugin-api == 2.11.0.0+ , hls-test-utils == 2.11.0.0 , lens , lsp , lsp-test@@ -1787,9 +1787,9 @@ hs-source-dirs: plugins/hls-notes-plugin/src build-depends: , array- , ghcide == 2.10.0.0- , hls-graph == 2.10.0.0- , hls-plugin-api == 2.10.0.0+ , ghcide == 2.11.0.0+ , hls-graph == 2.11.0.0+ , hls-plugin-api == 2.11.0.0 , lens , lsp >=2.7 , mtl >= 2.2@@ -1815,7 +1815,7 @@ build-depends: , filepath , haskell-language-server:hls-notes-plugin- , hls-test-utils == 2.10.0.0+ , hls-test-utils == 2.11.0.0 default-extensions: OverloadedStrings ----------------------------@@ -1875,10 +1875,10 @@ , extra , filepath , ghc- , ghcide == 2.10.0.0+ , ghcide == 2.11.0.0 , githash >=0.1.6.1 , hie-bios- , hls-plugin-api == 2.10.0.0+ , hls-plugin-api == 2.11.0.0 , optparse-applicative , optparse-simple , prettyprinter >= 1.7@@ -1981,7 +1981,7 @@ , ghcide:ghcide , hashable , hls-plugin-api- , hls-test-utils == 2.10.0.0+ , hls-test-utils == 2.11.0.0 , lens , lsp-test , lsp-types@@ -2007,11 +2007,11 @@ if flag(eval) cpp-options: -Dhls_eval -- formatters- if flag(floskell) && impl(ghc < 9.10)+ if flag(floskell) && (impl(ghc < 9.10) || flag(ignore-plugins-ghc-bounds)) cpp-options: -Dhls_floskell- if flag(fourmolu) && impl(ghc < 9.11)+ if flag(fourmolu) cpp-options: -Dhls_fourmolu- if flag(ormolu) && impl(ghc < 9.11)+ if flag(ormolu) cpp-options: -Dhls_ormolu test-suite wrapper-test@@ -2025,7 +2025,7 @@ build-depends: , extra- , hls-test-utils == 2.10.0.0+ , hls-test-utils == 2.11.0.0 , process hs-source-dirs: test/wrapper@@ -2094,7 +2094,6 @@ , enummapset , extra , filepath- , fuzzy , ghcide , hls-plugin-api , lens@@ -2102,7 +2101,6 @@ , lsp , lsp-test ^>=0.17.1 , lsp-types- , monoid-subclasses , mtl , network-uri , QuickCheck@@ -2120,7 +2118,7 @@ , text , text-rope , unordered-containers- , hls-test-utils == 2.10.0.0+ , hls-test-utils == 2.11.0.0 if impl(ghc <9.3) build-depends: ghc-typelits-knownnat@@ -2174,9 +2172,14 @@ RecordWildCards ViewPatterns +flag ghcide-bench+ description: Build the ghcide-bench executable+ default: True executable ghcide-bench import: defaults+ if !flag(ghcide-bench)+ buildable: False build-depends: aeson, bytestring,
plugins/hls-cabal-plugin/src/Ide/Plugin/Cabal/CabalAdd.hs view
@@ -190,6 +190,12 @@ -- > It is a member of the hidden package ‘split-0.2.5’. -- > Perhaps you need to add ‘split’ to the build-depends in your .cabal file." --+-- or this if PackageImports extension is used:+--+-- > "Could not find module ‘Data.List.Split’+-- > Perhaps you meant+-- > Data.List.Split (needs flag -package-id split-0.2.5)"+-- -- It extracts mentioned package names and version numbers. -- In this example, it will be @[("split", "0.2.5")]@ --@@ -204,13 +210,18 @@ msg :: T.Text msg = _message diag regex :: T.Text -- TODO: Support multiple packages suggestion- regex = "It is a member of the hidden package [\8216']([a-zA-Z0-9-]*[a-zA-Z0-9])(-([0-9\\.]*))?[\8217']"+ regex =+ let regex' = "([a-zA-Z0-9-]*[a-zA-Z0-9])(-([0-9\\.]*))?"+ in "It is a member of the hidden package [\8216']" <> regex' <> "[\8217']"+ <> "|"+ <> "needs flag -package-id " <> regex' -- Have to do this matching because `Regex.TDFA` doesn't(?) support -- not-capturing groups like (?:message) getMatch :: (T.Text, T.Text, T.Text, [T.Text]) -> [(T.Text, T.Text)] getMatch (_, _, _, []) = []- getMatch (_, _, _, [dependency, _, cleanVersion]) = [(dependency, cleanVersion)]- getMatch (_, _, _, _) = error "Impossible pattern matching case"+ getMatch (_, _, _, [dependency, _, cleanVersion, "", "", ""]) = [(dependency, cleanVersion)]+ getMatch (_, _, _, ["", "", "", dependency, _, cleanVersion]) = [(dependency, cleanVersion)]+ getMatch (_, _, _, _) = [] command :: Recorder (WithPriority Log) -> CommandFunction IdeState CabalAddCommandParams command recorder state _ params@(CabalAddCommandParams {cabalPath = path, verTxtDocId = verTxtDocId, buildTarget = target, dependency = dep, version = mbVer}) = do
plugins/hls-cabal-plugin/src/Ide/Plugin/Cabal/Completion/Completer/Paths.hs view
@@ -7,6 +7,7 @@ BuildInfo (..), CondTree (condTreeData), Executable (..),+ ForeignLib (..), GenericPackageDescription (..), Library (..), UnqualComponentName,@@ -117,6 +118,10 @@ -- | Extracts the source directories of benchmark stanza with the given name. sourceDirsExtractionBenchmark :: Maybe StanzaName -> GenericPackageDescription -> [FilePath] sourceDirsExtractionBenchmark name gpd = extractRelativeDirsFromStanza name gpd condBenchmarks benchmarkBuildInfo++-- | Extracts the source directories of foreign-lib stanza with the given name.+sourceDirsExtractionForeignLib :: Maybe StanzaName -> GenericPackageDescription -> [FilePath]+sourceDirsExtractionForeignLib name gpd = extractRelativeDirsFromStanza name gpd condForeignLibs foreignLibBuildInfo {- | Takes a possible stanza name, a GenericPackageDescription, a function to access the stanza information we are interested in
plugins/hls-cabal-plugin/src/Ide/Plugin/Cabal/Completion/Data.hs view
@@ -1,8 +1,5 @@ {-# LANGUAGE OverloadedStrings #-}-{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-} -{-# HLINT ignore "Redundant bracket" #-}- module Ide.Plugin.Cabal.Completion.Data where import Data.Map (Map)@@ -19,6 +16,17 @@ import Ide.Plugin.Cabal.Completion.Types import Ide.Plugin.Cabal.LicenseSuggest (licenseNames) +-- | Ad-hoc data type for modelling the available top-level stanzas.+-- Not intended right now for anything else but to avoid string+-- comparisons in 'stanzaKeywordMap' and 'libExecTestBenchCommons'.+data TopLevelStanza+ = Library+ | Executable+ | TestSuite+ | Benchmark+ | ForeignLib+ | Common+ -- ---------------------------------------------------------------- -- Completion Data -- ----------------------------------------------------------------@@ -71,12 +79,13 @@ stanzaKeywordMap :: Map StanzaType (Map KeyWordName Completer) stanzaKeywordMap = Map.fromList- [ ("library", libraryFields <> libExecTestBenchCommons),- ("executable", executableFields <> libExecTestBenchCommons),- ("test-suite", testSuiteFields <> libExecTestBenchCommons),- ("benchmark", benchmarkFields <> libExecTestBenchCommons),- ("foreign-library", foreignLibraryFields <> libExecTestBenchCommons),- ("common", libExecTestBenchCommons),+ [ ("library", libraryFields <> libExecTestBenchCommons Library),+ ("executable", executableFields <> libExecTestBenchCommons Executable),+ ("test-suite", testSuiteFields <> libExecTestBenchCommons TestSuite),+ ("benchmark", benchmarkFields <> libExecTestBenchCommons Benchmark),+ ("foreign-library", foreignLibraryFields <> libExecTestBenchCommons ForeignLib),+ ("common", libExecTestBenchCommons Library),+ ("common", libExecTestBenchCommons Common), ("flag", flagFields), ("source-repository", sourceRepositoryFields) ]@@ -162,8 +171,8 @@ ("lib-version-linux:", noopCompleter) ] -libExecTestBenchCommons :: Map KeyWordName Completer-libExecTestBenchCommons =+libExecTestBenchCommons :: TopLevelStanza -> Map KeyWordName Completer+libExecTestBenchCommons st = Map.fromList [ ("import:", importCompleter), ("build-depends:", noopCompleter),@@ -183,6 +192,8 @@ ("includes:", filePathCompleter), ("install-includes:", filePathCompleter), ("include-dirs:", directoryCompleter),+ ("autogen-includes:", filePathCompleter),+ ("autogen-modules:", moduleCompleterByTopLevelStanza), ("c-sources:", filePathCompleter), ("cxx-sources:", filePathCompleter), ("asm-sources:", filePathCompleter),@@ -203,6 +214,26 @@ ("extra-framework-dirs:", directoryCompleter), ("mixins:", noopCompleter) ]+ where+ --+ moduleCompleterByTopLevelStanza = case st of+ Library -> modulesCompleter sourceDirsExtractionLibrary+ Executable -> modulesCompleter sourceDirsExtractionExecutable+ TestSuite -> modulesCompleter sourceDirsExtractionTestSuite+ Benchmark -> modulesCompleter sourceDirsExtractionBenchmark+ ForeignLib -> modulesCompleter sourceDirsExtractionForeignLib+ Common ->+ -- TODO: We can't provide a module completer because we provide+ -- module completions based on the "hs-source-dirs" after parsing the file,+ -- i.e. based on the 'PackageDescription'.+ -- "common" stanzas are erased in the 'PackageDescription' representation,+ -- thus we can't provide accurate module completers right now, as we don't+ -- know what the 'hs-source-dirs' in the "common" stanza are.+ --+ -- A potential fix would be to introduce an intermediate representation that+ -- parses the '.cabal' file s.t. that we have access to the 'hs-source-dirs',+ -- but not have erased the "common" stanza.+ noopCompleter -- | Contains a map of the most commonly used licenses, weighted by their popularity. --
plugins/hls-cabal-plugin/test/CabalAdd.hs view
@@ -33,6 +33,8 @@ (generateAddDependencyTestSession "cabal-add-lib.cabal" ("src" </> "MyLib.hs") "split" [348]) , runHaskellTestCaseSession "Code Actions - Can add hidden package to a test" ("cabal-add-testdata" </> "cabal-add-tests") (generateAddDependencyTestSession "cabal-add-tests.cabal" ("test" </> "Main.hs") "split" [478])+ , runHaskellTestCaseSession "Code Actions - Can add hidden package to a test with PackageImports" ("cabal-add-testdata" </> "cabal-add-tests")+ (generateAddDependencyTestSession "cabal-add-tests.cabal" ("test" </> "MainPackageImports.hs") "split" [731]) , runHaskellTestCaseSession "Code Actions - Can add hidden package to a benchmark" ("cabal-add-testdata" </> "cabal-add-bench") (generateAddDependencyTestSession "cabal-add-bench.cabal" ("bench" </> "Main.hs") "split" [403]) @@ -121,6 +123,23 @@ ] [ ("3d-graphics-examples", T.empty) , ("3d-graphics-examples", "1.1.6")+ ]+ , testHiddenPackageSuggestions "Check CabalAdd's parser, with version, with PackageImports"+ [ "(needs flag -package-id base-0.1.0.0)"+ , "(needs flag -package-id Blammo-wai-0.11.0)"+ , "(needs flag -package-id BlastHTTP-2.6.4.3)"+ , "(needs flag -package-id CC-delcont-ref-tf-0.0.0.2)"+ , "(needs flag -package-id 3d-graphics-examples-1.1.6)"+ , "(needs flag -package-id AAI-0.1)"+ , "(needs flag -package-id AWin32Console-1.19.1)"+ ]+ [ ("base","0.1.0.0")+ , ("Blammo-wai", "0.11.0")+ , ("BlastHTTP", "2.6.4.3")+ , ("CC-delcont-ref-tf", "0.0.0.2")+ , ("3d-graphics-examples", "1.1.6")+ , ("AAI", "0.1")+ , ("AWin32Console", "1.19.1") ] ] where
plugins/hls-cabal-plugin/test/Completer.hs view
@@ -7,6 +7,7 @@ import Control.Lens ((^.), (^?)) import Control.Lens.Prism+import Control.Monad (forM_) import qualified Data.ByteString as ByteString import qualified Data.ByteString.Char8 as BS8 import Data.Maybe (mapMaybe)@@ -40,7 +41,8 @@ completionHelperTests, filePathExposedModulesTests, exposedModuleCompleterTests,- importCompleterTests+ importCompleterTests,+ autogenFieldCompletionTests ] basicCompleterTests :: TestTree@@ -335,6 +337,26 @@ (Syntax.Name (Syntax.Position row col) "common") [Syntax.SecArgName (Syntax.Position row (col + 7)) (BS8.pack name)] []++autogenFieldCompletionTests :: TestTree+autogenFieldCompletionTests =+ testGroup "Autogen Field Completer Tests"+ [ testAutogenField "library" "completion/autogen-completion.cabal" (Position 6 9) ["autogen-modules:", "autogen-includes:"]+ , testAutogenField "executable" "completion/autogen-completion.cabal" (Position 11 9) ["autogen-modules:", "autogen-includes:"]+ , testAutogenField "test-suite" "completion/autogen-completion.cabal" (Position 16 9) ["autogen-modules:", "autogen-includes:"]+ , testAutogenField "benchmark" "completion/autogen-completion.cabal" (Position 21 9) ["autogen-modules:", "autogen-includes:"]+ , testAutogenField "common" "completion/autogen-completion.cabal" (Position 24 9) ["autogen-modules:", "autogen-includes:"]+ ]++ where+ testAutogenField :: String -> FilePath -> Position -> [T.Text] -> TestTree+ testAutogenField section file pos expected = runCabalTestCaseSession ("autogen-modules completion in " <> section) "" $ do+ doc <- openDoc file "cabal"+ items <- getCompletions doc pos+ let labels = map (^. L.label) items+ liftIO $ forM_ expected $ \expect ->+ assertBool (T.unpack expect <> " not found in " <> section) $+ any (expect `T.isInfixOf`) labels simpleCompleterData :: Maybe StanzaName -> FilePath -> T.Text -> CompleterData simpleCompleterData sName dir pref = do
plugins/hls-cabal-plugin/test/Main.hs view
@@ -131,29 +131,6 @@ expectNoMoreDiagnostics 1 hsDoc "typechecking" cabalDoc <- openDoc "simple-cabal.cabal" "cabal" expectNoMoreDiagnostics 1 cabalDoc "parsing"- , runCabalTestCaseSession "Diagnostics in .hs files from invalid .cabal file" "simple-cabal" $ do- hsDoc <- openDoc "A.hs" "haskell"- expectNoMoreDiagnostics 1 hsDoc "typechecking"- cabalDoc <- openDoc "simple-cabal.cabal" "cabal"- expectNoMoreDiagnostics 1 cabalDoc "parsing"- let theRange = Range (Position 3 20) (Position 3 23)- -- Invalid license- changeDoc- cabalDoc- [ TextDocumentContentChangeEvent $- InL TextDocumentContentChangePartial- { _range = theRange- , _rangeLength = Nothing- , _text = "MIT3"- }- ]- cabalDiags <- waitForDiagnosticsFrom cabalDoc- unknownLicenseDiag <- liftIO $ inspectDiagnostic cabalDiags ["Unknown SPDX license identifier: 'MIT3'"]- expectNoMoreDiagnostics 1 hsDoc "typechecking"- liftIO $ do- length cabalDiags @?= 1- unknownLicenseDiag ^. L.range @?= Range (Position 3 24) (Position 4 0)- unknownLicenseDiag ^. L.severity @?= Just DiagnosticSeverity_Error ] ] -- ----------------------------------------------------------------------------
plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-tests/cabal-add-tests.cabal view
@@ -16,3 +16,11 @@ hs-source-dirs: test main-is: Main.hs build-depends: base++test-suite cabal-add-tests-test-package-imports+ import: warnings+ default-language: Haskell2010+ type: exitcode-stdio-1.0+ hs-source-dirs: test+ main-is: MainPackageImports.hs+ build-depends: base
+ plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-tests/test/MainPackageImports.hs view
@@ -0,0 +1,8 @@+{-# LANGUAGE PackageImports #-}++module Main (main) where++import "split" Data.List.Split++main :: IO ()+main = putStrLn "Test suite not yet implemented."
+ plugins/hls-cabal-plugin/test/testdata/completion/autogen-completion.cabal view
@@ -0,0 +1,25 @@+cabal-version: 3.0+name: autogen-completion+version: 0.1.0.0++library+ hs-source-dirs: src+ autogen-++executable autoexe+ main-is: Main.hs+ hs-source-dirs: src+ autogen-++test-suite autotest+ type: exitcode-stdio-1.0+ hs-source-dirs: src+ autogen-++benchmark autobench+ type: exitcode-stdio-1.0+ hs-source-dirs: src+ autogen-++common defaults+ autogen-
plugins/hls-eval-plugin/src/Ide/Plugin/Eval.hs view
@@ -13,8 +13,8 @@ import Development.IDE (IdeState) import Ide.Logger (Recorder, WithPriority)-import qualified Ide.Plugin.Eval.CodeLens as CL import Ide.Plugin.Eval.Config+import qualified Ide.Plugin.Eval.Handlers as Handlers import Ide.Plugin.Eval.Rules (rules) import qualified Ide.Plugin.Eval.Types as Eval import Ide.Types (ConfigDescriptor (..),@@ -27,9 +27,12 @@ -- |Plugin descriptor descriptor :: Recorder (WithPriority Eval.Log) -> PluginId -> PluginDescriptor IdeState descriptor recorder plId =- (defaultPluginDescriptor plId "Provies a code lens to evaluate expressions in doctest comments")- { pluginHandlers = mkPluginHandler SMethod_TextDocumentCodeLens (CL.codeLens recorder)- , pluginCommands = [CL.evalCommand recorder plId]+ (defaultPluginDescriptor plId "Provies code action and lens to evaluate expressions in doctest comments")+ { pluginHandlers = mconcat+ [ mkPluginHandler SMethod_TextDocumentCodeAction (Handlers.codeAction recorder)+ , mkPluginHandler SMethod_TextDocumentCodeLens (Handlers.codeLens recorder)+ ]+ , pluginCommands = [Handlers.evalCommand recorder plId] , pluginRules = rules recorder , pluginConfigDescriptor = defaultConfigDescriptor { configCustomConfig = mkCustomConfig properties
− plugins/hls-eval-plugin/src/Ide/Plugin/Eval/CodeLens.hs
@@ -1,675 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE DuplicateRecordFields #-}-{-# LANGUAGE ExtendedDefaultRules #-}-{-# LANGUAGE NoMonomorphismRestriction #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ViewPatterns #-}-{-# OPTIONS_GHC -Wno-type-defaults #-}--{- |-A plugin inspired by the REPLoid feature of <https://github.com/jyp/dante Dante>, <https://www.haskell.org/haddock/doc/html/ch03s08.html#idm140354810775744 Haddock>'s Examples and Properties and <https://hackage.haskell.org/package/doctest Doctest>.--For a full example see the "Ide.Plugin.Eval.Tutorial" module.--}-module Ide.Plugin.Eval.CodeLens (- codeLens,- evalCommand,-) where--import Control.Applicative (Alternative ((<|>)))-import Control.Arrow (second)-import Control.Exception (bracket_)-import qualified Control.Exception as E-import Control.Lens (ix, (%~), (^.))-import Control.Monad (guard, void,- when)-import Control.Monad.IO.Class (MonadIO (liftIO))-import Control.Monad.Trans.Except (ExceptT (..),- runExceptT)-import Data.Aeson (toJSON)-import Data.Char (isSpace)-import Data.Foldable (toList)-import Data.List (dropWhileEnd,- find,- intercalate,- intersperse)-import qualified Data.Map as Map-import Data.Maybe (catMaybes)-import Data.String (IsString)-import Data.Text (Text)-import qualified Data.Text as T-import qualified Data.Text.Utf16.Rope.Mixed as Rope-import Development.IDE.Core.FileStore (getUriContents)-import Development.IDE.Core.Rules (IdeState,- runAction)-import Development.IDE.Core.RuleTypes (LinkableResult (linkableHomeMod),- TypeCheck (..),- tmrTypechecked)-import Development.IDE.Core.Shake (useNoFile_, use_,- uses_)-import Development.IDE.GHC.Compat hiding (typeKind,- unitState)-import Development.IDE.GHC.Compat.Util (OverridingBool (..))-import Development.IDE.GHC.Util (evalGhcEnv,- modifyDynFlags)-import Development.IDE.Import.DependencyInformation (transitiveDeps,- transitiveModuleDeps)-import Development.IDE.Types.Location (toNormalizedFilePath')-import GHC (ClsInst,- ExecOptions (execLineNumber, execSourceFile),- FamInst,- GhcMonad,- NamedThing (getName),- defaultFixity,- execOptions,- exprType,- getInfo,- getInteractiveDynFlags,- isImport, isStmt,- parseName,- pprFamInst,- pprInstance,- typeKind)---import Development.IDE.Core.RuleTypes (GetLinkable (GetLinkable),- GetModSummary (GetModSummary),- GetModuleGraph (GetModuleGraph),- GhcSessionDeps (GhcSessionDeps),- ModSummaryResult (msrModSummary))-import Development.IDE.Core.Shake (VFSModified (VFSUnmodified))-import qualified Development.IDE.GHC.Compat.Core as Compat (InteractiveImport (IIModule))-import qualified Development.IDE.GHC.Compat.Core as SrcLoc (unLoc)-import Development.IDE.Types.HscEnvEq (HscEnvEq (hscEnv))-import qualified GHC.LanguageExtensions.Type as LangExt (Extension (..))--import Development.IDE.Core.FileStore (setSomethingModified)-import Development.IDE.Core.PluginUtils-import Development.IDE.Types.Shake (toKey)-import GHC.Types.SrcLoc (UnhelpfulSpanReason (UnhelpfulInteractive))-import Ide.Logger (Priority (..),- Recorder,- WithPriority,- logWith)-import Ide.Plugin.Error (PluginError (PluginInternalError),- handleMaybeM)-import Ide.Plugin.Eval.Code (Statement,- asStatements,- myExecStmt,- propSetup,- resultRange,- testCheck,- testRanges)-import Ide.Plugin.Eval.Config (EvalConfig (..),- getEvalConfig)-import Ide.Plugin.Eval.GHC (addImport,- addPackages,- hasPackage,- setSessionAndInteractiveDynFlags)-import Ide.Plugin.Eval.Parse.Comments (commentsToSections)-import Ide.Plugin.Eval.Parse.Option (parseSetFlags)-import Ide.Plugin.Eval.Rules (queueForEvaluation,- unqueueForEvaluation)-import Ide.Plugin.Eval.Types-import Ide.Plugin.Eval.Util (gStrictTry,- isLiterate,- prettyWarnings,- response', timed)-import Ide.Types-import qualified Language.LSP.Protocol.Lens as L-import Language.LSP.Protocol.Message-import Language.LSP.Protocol.Types-import Language.LSP.Server-#if MIN_VERSION_ghc(9,11,0)-import GHC.Unit.Module.ModIface (IfaceTopEnv (..))-#endif---{- | Code Lens provider- NOTE: Invoked every time the document is modified, not just when the document is saved.--}-codeLens :: Recorder (WithPriority Log) -> PluginMethodHandler IdeState Method_TextDocumentCodeLens-codeLens recorder st plId CodeLensParams{_textDocument} =- let dbg = logWith recorder Debug- perf = timed (\lbl duration -> dbg $ LogExecutionTime lbl duration)- in perf "codeLens" $- do- let TextDocumentIdentifier uri = _textDocument- fp <- uriToFilePathE uri- let nfp = toNormalizedFilePath' fp- isLHS = isLiterate fp- dbg $ LogCodeLensFp fp- (comments, _) <-- runActionE "eval.GetParsedModuleWithComments" st $ useWithStaleE GetEvalComments nfp- dbg $ LogCodeLensComments comments-- -- Extract tests from source code- let Sections{..} = commentsToSections isLHS comments- tests = testsBySection nonSetupSections- cmd = mkLspCommand plId evalCommandName "Evaluate=..." (Just [])- let lenses =- [ CodeLens testRange (Just cmd') Nothing- | (section, ident, test) <- tests- , let (testRange, resultRange) = testRanges test- args = EvalParams (setupSections ++ [section]) _textDocument ident- cmd' =- (cmd :: Command)- { _arguments = Just [toJSON args]- , _title =- if trivial resultRange- then "Evaluate..."- else "Refresh..."- }- ]-- perf "tests" $- dbg $ LogTests- (length tests)- (length nonSetupSections)- (length setupSections)- (length lenses)-- return $ InL lenses- where- trivial (Range p p') = p == p'--evalCommandName :: CommandId-evalCommandName = "evalCommand"--evalCommand :: Recorder (WithPriority Log) -> PluginId -> PluginCommand IdeState-evalCommand recorder plId = PluginCommand evalCommandName "evaluate" (runEvalCmd recorder plId)--type EvalId = Int--runEvalCmd :: Recorder (WithPriority Log) -> PluginId -> CommandFunction IdeState EvalParams-runEvalCmd recorder plId st mtoken EvalParams{..} =- let dbg = logWith recorder Debug- perf = timed (\lbl duration -> dbg $ LogExecutionTime lbl duration)- cmd :: ExceptT PluginError (HandlerM Config) WorkspaceEdit- cmd = do- let tests = map (\(a,_,b) -> (a,b)) $ testsBySection sections-- let TextDocumentIdentifier{_uri} = module_- fp <- uriToFilePathE _uri- let nfp = toNormalizedFilePath' fp- mdlText <- moduleText st _uri-- -- enable codegen for the module which we need to evaluate.- final_hscEnv <- liftIO $ bracket_- (setSomethingModified VFSUnmodified st "Eval" $ do- queueForEvaluation st nfp- return [toKey IsEvaluating nfp]- )- (setSomethingModified VFSUnmodified st "Eval" $ do- unqueueForEvaluation st nfp- return [toKey IsEvaluating nfp]- )- (initialiseSessionForEval (needsQuickCheck tests) st nfp)-- evalCfg <- liftIO $ runAction "eval: config" st $ getEvalConfig plId-- -- Perform the evaluation of the command- edits <-- perf "edits" $- liftIO $- evalGhcEnv final_hscEnv $ do- runTests recorder evalCfg fp tests-- let workspaceEditsMap = Map.singleton _uri (addFinalReturn mdlText edits)- let workspaceEdits = WorkspaceEdit (Just workspaceEditsMap) Nothing Nothing-- return workspaceEdits- in perf "evalCmd" $ ExceptT $- pluginWithIndefiniteProgress "Evaluating" mtoken Cancellable $ \_updater ->- runExceptT $ response' cmd---- | Create an HscEnv which is suitable for performing interactive evaluation.--- All necessary home modules will have linkables and the current module will--- also be loaded into the environment.------ The interactive context and interactive dynamic flags are also set appropiately.-initialiseSessionForEval :: Bool -> IdeState -> NormalizedFilePath -> IO HscEnv-initialiseSessionForEval needs_quickcheck st nfp = do- (ms, env1) <- runAction "runEvalCmd" st $ do-- ms <- msrModSummary <$> use_ GetModSummary nfp- deps_hsc <- hscEnv <$> use_ GhcSessionDeps nfp-- linkables_needed <- transitiveDeps <$> useNoFile_ GetModuleGraph <*> pure nfp- linkables <- uses_ GetLinkable (nfp : maybe [] transitiveModuleDeps linkables_needed)- -- We unset the global rdr env in mi_globals when we generate interfaces- -- See Note [Clearing mi_globals after generating an iface]- -- However, the eval plugin (setContext specifically) requires the rdr_env- -- for the current module - so get it from the Typechecked Module and add- -- 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)- = 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 $!-#if MIN_VERSION_ghc(9,8,0)- forceGlobalRdrEnv-#endif- rdr_env- }}-#endif- | otherwise = hmi-- 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- setContext [Compat.IIModule (moduleName (ms_mod ms))]- let df = flip xopt_set LangExt.ExtendedDefaultRules- . flip xopt_unset LangExt.MonomorphismRestriction- . flip gopt_set Opt_ImplicitImportQualified- . flip gopt_unset Opt_DiagnosticsShowCaret- . setBackend ghciBackend- $ (ms_hspp_opts ms) {- useColor = Never- , canUseColor = False }- modifyDynFlags (const df)- when needs_quickcheck $ void $ addPackages ["QuickCheck"]- getSession- return env2--#if MIN_VERSION_ghc(9,11,0)-mkIfaceImports :: [ImportUserSpec] -> [IfaceImport]-mkIfaceImports = map go- where- go (ImpUserSpec decl ImpUserAll) = IfaceImport decl ImpIfaceAll- go (ImpUserSpec decl (ImpUserExplicit env)) = IfaceImport decl (ImpIfaceExplicit (forceGlobalRdrEnv env))- go (ImpUserSpec decl (ImpUserEverythingBut ns)) = IfaceImport decl (ImpIfaceEverythingBut ns)-#endif--addFinalReturn :: Text -> [TextEdit] -> [TextEdit]-addFinalReturn mdlText edits- | not (null edits) && not (T.null mdlText) && T.last mdlText /= '\n' =- finalReturn mdlText : edits- | otherwise = edits--finalReturn :: Text -> TextEdit-finalReturn txt =- let ls = T.lines txt- l = fromIntegral $ length ls -1- c = fromIntegral $ T.length . last $ ls- p = Position l c- in TextEdit (Range p p) "\n"--moduleText :: IdeState -> Uri -> ExceptT PluginError (HandlerM config) Text-moduleText state uri = do- contents <-- handleMaybeM (PluginInternalError "mdlText") $- liftIO $- runAction "eval.getUriContents" state $- getUriContents $- toNormalizedUri uri- pure $ Rope.toText contents--testsBySection :: [Section] -> [(Section, EvalId, Test)]-testsBySection sections =- [(section, ident, test)- | (ident, section) <- zip [0..] sections- , test <- sectionTests section- ]--type TEnv = String--- |GHC declarations required for expression evaluation-evalSetup :: Ghc ()-evalSetup = do- preludeAsP <- parseImportDecl "import qualified Prelude as P"- context <- getContext- setContext (IIDecl preludeAsP : context)--runTests :: Recorder (WithPriority Log) -> EvalConfig -> TEnv -> [(Section, Test)] -> Ghc [TextEdit]-runTests recorder EvalConfig{..} e tests = do- df <- getInteractiveDynFlags- evalSetup- when (hasQuickCheck df && needsQuickCheck tests) $ void $ evals recorder True e df propSetup-- mapM (processTest e df) tests- where- processTest :: TEnv -> DynFlags -> (Section, Test) -> Ghc TextEdit- processTest fp df (section, test) = do- let dbg = logWith recorder Debug- let pad = pad_ $ (if isLiterate fp then ("> " `T.append`) else id) $ padPrefix (sectionFormat section)- rs <- runTest e df test- dbg $ LogRunTestResults rs-- let checkedResult = testCheck eval_cfg_diff (section, test) rs- let resultLines = concatMap T.lines checkedResult-- let edit = asEdit (sectionFormat section) test (map pad resultLines)- dbg $ LogRunTestEdits edit- return edit-- -- runTest :: String -> DynFlags -> Loc Test -> Ghc [Text]- runTest _ df test- | not (hasQuickCheck df) && isProperty test =- return $- singleLine- "Add QuickCheck to your cabal dependencies to run this test."- runTest e df test = evals recorder (eval_cfg_exception && not (isProperty test)) e df (asStatements test)--asEdit :: Format -> Test -> [Text] -> TextEdit-asEdit (MultiLine commRange) test resultLines- -- A test in a block comment, ending with @-\}@ without newline in-between.- | testRange test ^. L.end . L.line == commRange ^. L.end . L.line- =- TextEdit- (Range- (testRange test ^. L.end)- (resultRange test ^. L.end)- )- ("\n" <> T.unlines (resultLines <> ["-}"]))-asEdit _ test resultLines =- TextEdit (resultRange test) (T.unlines resultLines)--{- |-The result of evaluating a test line can be:-* a value-* nothing-* a (possibly multiline) error message--A value is returned for a correct expression.--Either a pure value:->>> 'h' :"askell"-"haskell"--Or an 'IO a' (output on stdout/stderr is ignored):->>> print "OK" >> return "ABC"-"ABC"--Nothing is returned for a correct directive:-->>>:set -XFlexibleInstances->>> import Data.Maybe--Nothing is returned for a correct declaration (let..,x=, data, class)-->>> let x = 11->>> y = 22->>> data B = T | F->>> class C a--Nothing is returned for an empty line:-->>>--A, possibly multi line, error is returned for a wrong declaration, directive or value or an exception thrown by the evaluated code:-->>>:set -XNonExistent-Some flags have not been recognized: -XNonExistent-->>> cls C-Variable not in scope: cls :: t0 -> t-Data constructor not in scope: C-->>> "A-lexical error in string/character literal at end of input--Exceptions are shown as if printed, but it can be configured to include prefix like-in GHCi or doctest. This allows it to be used as a hack to simulate print until we-get proper IO support. See #1977-->>> 3 `div` 0-divide by zero-->>> error "Something went wrong\nbad times" :: E.SomeException-Something went wrong-bad times--Or for a value that does not have a Show instance and can therefore not be displayed:->>> data V = V->>> V-No instance for (Show V) arising from a use of ‘evalPrint’--}-evals :: Recorder (WithPriority Log) -> Bool -> TEnv -> DynFlags -> [Statement] -> Ghc [Text]-evals recorder mark_exception fp df stmts = do- er <- gStrictTry $ mapM eval stmts- return $ case er of- Left err -> errorLines err- Right rs -> concat . catMaybes $ rs- where- dbg = logWith recorder Debug- eval :: Statement -> Ghc (Maybe [Text])- eval (Located l stmt)- | -- GHCi flags- Just (words -> flags) <- parseSetFlags stmt = do- dbg $ LogEvalFlags flags- ndf <- getInteractiveDynFlags- dbg $ LogEvalPreSetDynFlags ndf- eans <-- liftIO $ try @GhcException $- parseDynamicFlagsCmdLine ndf- (map (L $ UnhelpfulSpan unhelpfulReason) flags)- dbg $ LogEvalParsedFlags eans- case eans of- Left err -> pure $ Just $ errorLines $ show err- Right (df', ignoreds, warns) -> do- let warnings = do- guard $ not $ null warns- pure $ errorLines $- prettyWarnings warns- igns = do- guard $ not $ null ignoreds- pure- ["Some flags have not been recognized: "- <> T.pack (intercalate ", " $ map SrcLoc.unLoc ignoreds)- ]- dbg $ LogEvalPostSetDynFlags df'- setSessionAndInteractiveDynFlags df'- pure $ warnings <> igns- | -- A type/kind command- Just (cmd, arg) <- parseGhciLikeCmd $ T.pack stmt =- evalGhciLikeCmd cmd arg- | -- A statement- isStmt pf stmt =- do- dbg $ LogEvalStmtStart stmt- res <- exec stmt l- let r = case res of- Left err -> Just . (if mark_exception then exceptionLines else errorLines) $ err- Right x -> singleLine <$> x- dbg $ LogEvalStmtResult r- return r- | -- An import- isImport pf stmt =- do- dbg $ LogEvalImport stmt- _ <- addImport stmt- return Nothing- | -- A declaration- otherwise =- do- dbg $ LogEvalDeclaration stmt- void $ runDecls stmt- return Nothing- pf = initParserOpts df- unhelpfulReason = UnhelpfulInteractive- exec stmt l =- let opts = execOptions{execSourceFile = fp, execLineNumber = l}- in myExecStmt stmt opts--needsQuickCheck :: [(Section, Test)] -> Bool-needsQuickCheck = any (isProperty . snd)--hasQuickCheck :: DynFlags -> Bool-hasQuickCheck df = hasPackage df "QuickCheck"--singleLine :: String -> [Text]-singleLine s = [T.pack s]--{- |- Convert error messages to a list of text lines- Remove unnecessary information.--}-errorLines :: String -> [Text]-errorLines =- dropWhileEnd T.null- . takeWhile (not . (\x -> "CallStack" `T.isPrefixOf` x || "HasCallStack" `T.isPrefixOf` x))- . T.lines- . T.pack--{- |- Convert exception messages to a list of text lines- Remove unnecessary information and mark it as exception.- We use '*** Exception:' to make it identical to doctest- output, see #2353.--}-exceptionLines :: String -> [Text]-exceptionLines = (ix 0 %~ ("*** Exception: " <>)) . errorLines--{- |->>> map (pad_ (T.pack "--")) (map T.pack ["2+2",""])-["--2+2","--<BLANKLINE>"]--}-pad_ :: Text -> Text -> Text-pad_ prefix = (prefix `T.append`) . convertBlank--convertBlank :: Text -> Text-convertBlank x- | T.null x = "<BLANKLINE>"- | otherwise = x--padPrefix :: IsString p => Format -> p-padPrefix SingleLine = "-- "-padPrefix _ = ""--{- | Resulting @Text@ MUST NOT prefix each line with @--@- Such comment-related post-process will be taken place- solely in 'evalGhciLikeCmd'.--}-type GHCiLikeCmd = DynFlags -> Text -> Ghc (Maybe Text)---- Should we use some sort of trie here?-ghciLikeCommands :: [(Text, GHCiLikeCmd)]-ghciLikeCommands =- [ ("info", doInfoCmd False)- , ("info!", doInfoCmd True)- , ("kind", doKindCmd False)- , ("kind!", doKindCmd True)- , ("type", doTypeCmd)- ]--evalGhciLikeCmd :: Text -> Text -> Ghc (Maybe [Text])-evalGhciLikeCmd cmd arg = do- df <- getSessionDynFlags- case lookup cmd ghciLikeCommands- <|> snd- <$> find (T.isPrefixOf cmd . fst) ghciLikeCommands of- Just hndler ->- fmap- T.lines- <$> hndler df arg- _ -> E.throw $ GhciLikeCmdNotImplemented cmd arg--doInfoCmd :: Bool -> DynFlags -> Text -> Ghc (Maybe Text)-doInfoCmd allInfo dflags s = do- sdocs <- mapM infoThing (T.words s)- pure $ Just $ T.pack $ showSDoc dflags (vcat sdocs)- where- infoThing :: GHC.GhcMonad m => Text -> m SDoc- infoThing (T.unpack -> str) = do- names <- GHC.parseName str- mb_stuffs <- mapM (GHC.getInfo allInfo) names- let filtered = filterOutChildren (\(t,_f,_ci,_fi,_sd) -> t)- (catMaybes $ toList mb_stuffs)- return $ vcat (intersperse (text "") $ map pprInfo filtered)-- filterOutChildren :: (a -> TyThing) -> [a] -> [a]- filterOutChildren get_thing xs- = filter (not . has_parent) xs- where- all_names = mkNameSet (map (getName . get_thing) xs)- has_parent x = case tyThingParent_maybe (get_thing x) of- Just p -> getName p `elemNameSet` all_names- Nothing -> False-- pprInfo :: (TyThing, Fixity, [GHC.ClsInst], [GHC.FamInst], SDoc) -> SDoc- pprInfo (thing, fixity, cls_insts, fam_insts, docs)- = docs- $$ pprTyThingInContextLoc thing- $$ showFixity thing fixity- $$ vcat (map GHC.pprInstance cls_insts)- $$ vcat (map GHC.pprFamInst fam_insts)-- pprTyThingInContextLoc :: TyThing -> SDoc- pprTyThingInContextLoc tyThing- = showWithLoc (pprDefinedAt (getName tyThing))- (pprTyThingInContext showToHeader tyThing)-- showWithLoc :: SDoc -> SDoc -> SDoc- showWithLoc loc doc- = hang doc 2 (text "\t--" <+> loc)-- showFixity :: TyThing -> Fixity -> SDoc- showFixity thing fixity- | fixity /= GHC.defaultFixity || isSymOcc (getOccName thing)- = ppr fixity <+> pprInfixName (GHC.getName thing)- | otherwise = empty--doKindCmd :: Bool -> DynFlags -> Text -> Ghc (Maybe Text)-doKindCmd False df arg = do- let input = T.strip arg- (_, kind) <- typeKind False $ T.unpack input- let kindText = text (T.unpack input) <+> "::" <+> pprSigmaType kind- pure $ Just $ T.pack (showSDoc df kindText)-doKindCmd True df arg = do- let input = T.strip arg- (ty, kind) <- typeKind True $ T.unpack input- let kindDoc = text (T.unpack input) <+> "::" <+> pprSigmaType kind- tyDoc = "=" <+> pprSigmaType ty- pure $ Just $ T.pack (showSDoc df $ kindDoc $$ tyDoc)--doTypeCmd :: DynFlags -> Text -> Ghc (Maybe Text)-doTypeCmd dflags arg = do- let (emod, expr) = parseExprMode arg- ty <- GHC.exprType emod $ T.unpack expr- let rawType = T.strip $ T.pack $ showSDoc dflags $ pprSigmaType ty- broken = T.any (\c -> c == '\r' || c == '\n') rawType- pure $- Just $- if broken- then- T.pack $- showSDoc dflags $- text (T.unpack expr)- $$ nest 2 ("::" <+> pprSigmaType ty)- else expr <> " :: " <> rawType <> "\n"--parseExprMode :: Text -> (TcRnExprMode, T.Text)-parseExprMode rawArg = case T.break isSpace rawArg of- ("+d", rest) -> (TM_Default, T.strip rest)- _ -> (TM_Inst, rawArg)--data GhciLikeCmdException = GhciLikeCmdNotImplemented- { ghciCmdName :: Text- , ghciCmdArg :: Text- }--instance Show GhciLikeCmdException where- showsPrec _ GhciLikeCmdNotImplemented{..} =- showString "unknown command '"- . showString (T.unpack ghciCmdName)- . showChar '\''--instance E.Exception GhciLikeCmdException--{-->>> parseGhciLikeCmd (T.pack ":kind! N + M + 1")-Just ("kind!","N + M + 1")->>> parseGhciLikeCmd (T.pack ":kind a")-Just ("kind","a")--}-parseGhciLikeCmd :: Text -> Maybe (Text, Text)-parseGhciLikeCmd input = do- (':', rest) <- T.uncons $ T.stripStart input- pure $ second T.strip $ T.break isSpace rest
+ plugins/hls-eval-plugin/src/Ide/Plugin/Eval/Handlers.hs view
@@ -0,0 +1,695 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DuplicateRecordFields #-}+{-# LANGUAGE ExtendedDefaultRules #-}+{-# LANGUAGE NoMonomorphismRestriction #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ViewPatterns #-}+{-# OPTIONS_GHC -Wno-type-defaults #-}++{- |+A plugin inspired by the REPLoid feature of <https://github.com/jyp/dante Dante>, <https://www.haskell.org/haddock/doc/html/ch03s08.html#idm140354810775744 Haddock>'s Examples and Properties and <https://hackage.haskell.org/package/doctest Doctest>.++For a full example see the "Ide.Plugin.Eval.Tutorial" module.+-}+module Ide.Plugin.Eval.Handlers (+ codeAction,+ codeLens,+ evalCommand,+) where++import Control.Applicative (Alternative ((<|>)))+import Control.Arrow (second)+import Control.Exception (bracket_)+import qualified Control.Exception as E+import Control.Lens (ix, (%~), (^.))+import Control.Monad (guard, void,+ when)+import Control.Monad.IO.Class (MonadIO (liftIO))+import Control.Monad.Trans.Except (ExceptT (..),+ runExceptT)+import Data.Aeson (toJSON)+import Data.Char (isSpace)+import Data.Foldable (toList)+import Data.List (dropWhileEnd,+ find,+ intercalate,+ intersperse)+import qualified Data.Map as Map+import Data.Maybe (catMaybes)+import Data.String (IsString)+import Data.Text (Text)+import qualified Data.Text as T+import qualified Data.Text.Utf16.Rope.Mixed as Rope+import Development.IDE.Core.FileStore (getUriContents)+import Development.IDE.Core.Rules (IdeState,+ runAction)+import Development.IDE.Core.RuleTypes (LinkableResult (linkableHomeMod),+ TypeCheck (..),+ tmrTypechecked)+import Development.IDE.Core.Shake (useNoFile_, use_,+ uses_)+import Development.IDE.GHC.Compat hiding (typeKind,+ unitState)+import Development.IDE.GHC.Compat.Util (OverridingBool (..))+import Development.IDE.GHC.Util (evalGhcEnv,+ modifyDynFlags)+import Development.IDE.Import.DependencyInformation (transitiveDeps,+ transitiveModuleDeps)+import Development.IDE.Types.Location (toNormalizedFilePath')+import GHC (ClsInst,+ ExecOptions (execLineNumber, execSourceFile),+ FamInst,+ GhcMonad,+ NamedThing (getName),+ defaultFixity,+ execOptions,+ exprType,+ getInfo,+ getInteractiveDynFlags,+ isImport, isStmt,+ parseName,+ pprFamInst,+ pprInstance,+ typeKind)+++import Development.IDE.Core.RuleTypes (GetLinkable (GetLinkable),+ GetModSummary (GetModSummary),+ GetModuleGraph (GetModuleGraph),+ GhcSessionDeps (GhcSessionDeps),+ ModSummaryResult (msrModSummary))+import Development.IDE.Core.Shake (VFSModified (VFSUnmodified))+import qualified Development.IDE.GHC.Compat.Core as Compat (InteractiveImport (IIModule))+import qualified Development.IDE.GHC.Compat.Core as SrcLoc (unLoc)+import Development.IDE.Types.HscEnvEq (HscEnvEq (hscEnv))+import qualified GHC.LanguageExtensions.Type as LangExt (Extension (..))++import Data.List.Extra (unsnoc)+import Development.IDE.Core.FileStore (setSomethingModified)+import Development.IDE.Core.PluginUtils+import Development.IDE.Types.Shake (toKey)+import GHC.Types.SrcLoc (UnhelpfulSpanReason (UnhelpfulInteractive))+import Ide.Logger (Priority (..),+ Recorder,+ WithPriority,+ logWith)+import Ide.Plugin.Error (PluginError (PluginInternalError),+ handleMaybeM)+import Ide.Plugin.Eval.Code (Statement,+ asStatements,+ myExecStmt,+ propSetup,+ resultRange,+ testCheck,+ testRanges)+import Ide.Plugin.Eval.Config (EvalConfig (..),+ getEvalConfig)+import Ide.Plugin.Eval.GHC (addImport,+ addPackages,+ hasPackage,+ setSessionAndInteractiveDynFlags)+import Ide.Plugin.Eval.Parse.Comments (commentsToSections)+import Ide.Plugin.Eval.Parse.Option (parseSetFlags)+import Ide.Plugin.Eval.Rules (queueForEvaluation,+ unqueueForEvaluation)+import Ide.Plugin.Eval.Types+import Ide.Plugin.Eval.Util (gStrictTry,+ isLiterate,+ prettyWarnings,+ response', timed)+import Ide.Types+import qualified Language.LSP.Protocol.Lens as L+import Language.LSP.Protocol.Message+import Language.LSP.Protocol.Types+import Language.LSP.Server+#if MIN_VERSION_ghc(9,11,0)+import GHC.Unit.Module.ModIface (IfaceTopEnv (..))+#endif++codeAction :: Recorder (WithPriority Log) -> PluginMethodHandler IdeState Method_TextDocumentCodeAction+codeAction recorder st plId CodeActionParams{_textDocument,_range} = do+ rangeCommands <- mkRangeCommands recorder st plId _textDocument+ pure+ $ InL+ [ InL command+ | (testRange, command) <- rangeCommands+ , _range `isSubrangeOf` testRange+ ]++{- | Code Lens provider+ NOTE: Invoked every time the document is modified, not just when the document is saved.+-}+codeLens :: Recorder (WithPriority Log) -> PluginMethodHandler IdeState Method_TextDocumentCodeLens+codeLens recorder st plId CodeLensParams{_textDocument} = do+ rangeCommands <- mkRangeCommands recorder st plId _textDocument+ pure+ $ InL+ [ CodeLens range (Just command) Nothing+ | (range, command) <- rangeCommands+ ]++mkRangeCommands :: Recorder (WithPriority Log) -> IdeState -> PluginId -> TextDocumentIdentifier -> ExceptT PluginError (HandlerM Config) [(Range, Command)]+mkRangeCommands recorder st plId textDocument =+ let dbg = logWith recorder Debug+ perf = timed (\lbl duration -> dbg $ LogExecutionTime lbl duration)+ in perf "evalMkRangeCommands" $+ do+ let TextDocumentIdentifier uri = textDocument+ fp <- uriToFilePathE uri+ let nfp = toNormalizedFilePath' fp+ isLHS = isLiterate fp+ dbg $ LogCodeLensFp fp+ (comments, _) <-+ runActionE "eval.GetParsedModuleWithComments" st $ useWithStaleE GetEvalComments nfp+ dbg $ LogCodeLensComments comments++ -- Extract tests from source code+ let Sections{..} = commentsToSections isLHS comments+ tests = testsBySection nonSetupSections+ cmd = mkLspCommand plId evalCommandName "Evaluate=..." (Just [])+ let rangeCommands =+ [ (testRange, cmd')+ | (section, ident, test) <- tests+ , let (testRange, resultRange) = testRanges test+ args = EvalParams (setupSections ++ [section]) textDocument ident+ cmd' =+ (cmd :: Command)+ { _arguments = Just [toJSON args]+ , _title =+ if trivial resultRange+ then "Evaluate..."+ else "Refresh..."+ }+ ]++ perf "tests" $+ dbg $ LogTests+ (length tests)+ (length nonSetupSections)+ (length setupSections)+ (length rangeCommands)++ pure rangeCommands+ where+ trivial (Range p p') = p == p'++evalCommandName :: CommandId+evalCommandName = "evalCommand"++evalCommand :: Recorder (WithPriority Log) -> PluginId -> PluginCommand IdeState+evalCommand recorder plId = PluginCommand evalCommandName "evaluate" (runEvalCmd recorder plId)++type EvalId = Int++runEvalCmd :: Recorder (WithPriority Log) -> PluginId -> CommandFunction IdeState EvalParams+runEvalCmd recorder plId st mtoken EvalParams{..} =+ let dbg = logWith recorder Debug+ perf = timed (\lbl duration -> dbg $ LogExecutionTime lbl duration)+ cmd :: ExceptT PluginError (HandlerM Config) WorkspaceEdit+ cmd = do+ let tests = map (\(a,_,b) -> (a,b)) $ testsBySection sections++ let TextDocumentIdentifier{_uri} = module_+ fp <- uriToFilePathE _uri+ let nfp = toNormalizedFilePath' fp+ mdlText <- moduleText st _uri++ -- enable codegen for the module which we need to evaluate.+ final_hscEnv <- liftIO $ bracket_+ (setSomethingModified VFSUnmodified st "Eval" $ do+ queueForEvaluation st nfp+ return [toKey IsEvaluating nfp]+ )+ (setSomethingModified VFSUnmodified st "Eval" $ do+ unqueueForEvaluation st nfp+ return [toKey IsEvaluating nfp]+ )+ (initialiseSessionForEval (needsQuickCheck tests) st nfp)++ evalCfg <- liftIO $ runAction "eval: config" st $ getEvalConfig plId++ -- Perform the evaluation of the command+ edits <-+ perf "edits" $+ liftIO $+ evalGhcEnv final_hscEnv $ do+ runTests recorder evalCfg fp tests++ let workspaceEditsMap = Map.singleton _uri (addFinalReturn mdlText edits)+ let workspaceEdits = WorkspaceEdit (Just workspaceEditsMap) Nothing Nothing++ return workspaceEdits+ in perf "evalCmd" $ ExceptT $+ pluginWithIndefiniteProgress "Evaluating" mtoken Cancellable $ \_updater ->+ runExceptT $ response' cmd++-- | Create an HscEnv which is suitable for performing interactive evaluation.+-- All necessary home modules will have linkables and the current module will+-- also be loaded into the environment.+--+-- The interactive context and interactive dynamic flags are also set appropiately.+initialiseSessionForEval :: Bool -> IdeState -> NormalizedFilePath -> IO HscEnv+initialiseSessionForEval needs_quickcheck st nfp = do+ (ms, env1) <- runAction "runEvalCmd" st $ do++ ms <- msrModSummary <$> use_ GetModSummary nfp+ deps_hsc <- hscEnv <$> use_ GhcSessionDeps nfp++ linkables_needed <- transitiveDeps <$> useNoFile_ GetModuleGraph <*> pure nfp+ linkables <- uses_ GetLinkable (nfp : maybe [] transitiveModuleDeps linkables_needed)+ -- We unset the global rdr env in mi_globals when we generate interfaces+ -- See Note [Clearing mi_globals after generating an iface]+ -- However, the eval plugin (setContext specifically) requires the rdr_env+ -- for the current module - so get it from the Typechecked Module and add+ -- 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)+ = 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 $!+#if MIN_VERSION_ghc(9,8,0)+ forceGlobalRdrEnv+#endif+ rdr_env+ }}+#endif+ | otherwise = hmi++ 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+ setContext [Compat.IIModule (moduleName (ms_mod ms))]+ let df = flip xopt_set LangExt.ExtendedDefaultRules+ . flip xopt_unset LangExt.MonomorphismRestriction+ . flip gopt_set Opt_ImplicitImportQualified+ . flip gopt_unset Opt_DiagnosticsShowCaret+ . setBackend ghciBackend+ $ (ms_hspp_opts ms) {+ useColor = Never+ , canUseColor = False }+ modifyDynFlags (const df)+ when needs_quickcheck $ void $ addPackages ["QuickCheck"]+ getSession+ return env2++#if MIN_VERSION_ghc(9,11,0)+mkIfaceImports :: [ImportUserSpec] -> [IfaceImport]+mkIfaceImports = map go+ where+ go (ImpUserSpec decl ImpUserAll) = IfaceImport decl ImpIfaceAll+ go (ImpUserSpec decl (ImpUserExplicit env)) = IfaceImport decl (ImpIfaceExplicit (forceGlobalRdrEnv env))+ go (ImpUserSpec decl (ImpUserEverythingBut ns)) = IfaceImport decl (ImpIfaceEverythingBut ns)+#endif++addFinalReturn :: Text -> [TextEdit] -> [TextEdit]+addFinalReturn mdlText edits+ | not (null edits) && not (T.null mdlText) && T.last mdlText /= '\n' =+ finalReturn mdlText : edits+ | otherwise = edits++finalReturn :: Text -> TextEdit+finalReturn txt =+ let ls = T.lines txt+ l = fromIntegral $ length ls -1+ c = fromIntegral $ T.length $ maybe T.empty snd (unsnoc ls)+ p = Position l c+ in TextEdit (Range p p) "\n"++moduleText :: IdeState -> Uri -> ExceptT PluginError (HandlerM config) Text+moduleText state uri = do+ contents <-+ handleMaybeM (PluginInternalError "mdlText") $+ liftIO $+ runAction "eval.getUriContents" state $+ getUriContents $+ toNormalizedUri uri+ pure $ Rope.toText contents++testsBySection :: [Section] -> [(Section, EvalId, Test)]+testsBySection sections =+ [(section, ident, test)+ | (ident, section) <- zip [0..] sections+ , test <- sectionTests section+ ]++type TEnv = String+-- |GHC declarations required for expression evaluation+evalSetup :: Ghc ()+evalSetup = do+ preludeAsP <- parseImportDecl "import qualified Prelude as P"+ context <- getContext+ setContext (IIDecl preludeAsP : context)++runTests :: Recorder (WithPriority Log) -> EvalConfig -> TEnv -> [(Section, Test)] -> Ghc [TextEdit]+runTests recorder EvalConfig{..} e tests = do+ df <- getInteractiveDynFlags+ evalSetup+ when (hasQuickCheck df && needsQuickCheck tests) $ void $ evals recorder True e df propSetup++ mapM (processTest e df) tests+ where+ processTest :: TEnv -> DynFlags -> (Section, Test) -> Ghc TextEdit+ processTest fp df (section, test) = do+ let dbg = logWith recorder Debug+ let pad = pad_ $ (if isLiterate fp then ("> " `T.append`) else id) $ padPrefix (sectionFormat section)+ rs <- runTest e df test+ dbg $ LogRunTestResults rs++ let checkedResult = testCheck eval_cfg_diff (section, test) rs+ let resultLines = concatMap T.lines checkedResult++ let edit = asEdit (sectionFormat section) test (map pad resultLines)+ dbg $ LogRunTestEdits edit+ return edit++ -- runTest :: String -> DynFlags -> Loc Test -> Ghc [Text]+ runTest _ df test+ | not (hasQuickCheck df) && isProperty test =+ return $+ singleLine+ "Add QuickCheck to your cabal dependencies to run this test."+ runTest e df test = evals recorder (eval_cfg_exception && not (isProperty test)) e df (asStatements test)++asEdit :: Format -> Test -> [Text] -> TextEdit+asEdit (MultiLine commRange) test resultLines+ -- A test in a block comment, ending with @-\}@ without newline in-between.+ | testRange test ^. L.end . L.line == commRange ^. L.end . L.line+ =+ TextEdit+ (Range+ (testRange test ^. L.end)+ (resultRange test ^. L.end)+ )+ ("\n" <> T.unlines (resultLines <> ["-}"]))+asEdit _ test resultLines =+ TextEdit (resultRange test) (T.unlines resultLines)++{- |+The result of evaluating a test line can be:+* a value+* nothing+* a (possibly multiline) error message++A value is returned for a correct expression.++Either a pure value:+>>> 'h' :"askell"+"haskell"++Or an 'IO a' (output on stdout/stderr is ignored):+>>> print "OK" >> return "ABC"+"ABC"++Nothing is returned for a correct directive:++>>>:set -XFlexibleInstances+>>> import Data.Maybe++Nothing is returned for a correct declaration (let..,x=, data, class)++>>> let x = 11+>>> y = 22+>>> data B = T | F+>>> class C a++Nothing is returned for an empty line:++>>>++A, possibly multi line, error is returned for a wrong declaration, directive or value or an exception thrown by the evaluated code:++>>>:set -XNonExistent+Some flags have not been recognized: -XNonExistent++>>> cls C+Variable not in scope: cls :: t0 -> t+Data constructor not in scope: C++>>> "A+lexical error in string/character literal at end of input++Exceptions are shown as if printed, but it can be configured to include prefix like+in GHCi or doctest. This allows it to be used as a hack to simulate print until we+get proper IO support. See #1977++>>> 3 `div` 0+divide by zero++>>> error "Something went wrong\nbad times" :: E.SomeException+Something went wrong+bad times++Or for a value that does not have a Show instance and can therefore not be displayed:+>>> data V = V+>>> V+No instance for (Show V) arising from a use of ‘evalPrint’+-}+evals :: Recorder (WithPriority Log) -> Bool -> TEnv -> DynFlags -> [Statement] -> Ghc [Text]+evals recorder mark_exception fp df stmts = do+ er <- gStrictTry $ mapM eval stmts+ return $ case er of+ Left err -> errorLines err+ Right rs -> concat . catMaybes $ rs+ where+ dbg = logWith recorder Debug+ eval :: Statement -> Ghc (Maybe [Text])+ eval (Located l stmt)+ | -- GHCi flags+ Just (words -> flags) <- parseSetFlags stmt = do+ dbg $ LogEvalFlags flags+ ndf <- getInteractiveDynFlags+ dbg $ LogEvalPreSetDynFlags ndf+ eans <-+ liftIO $ try @GhcException $+ parseDynamicFlagsCmdLine ndf+ (map (L $ UnhelpfulSpan unhelpfulReason) flags)+ dbg $ LogEvalParsedFlags eans+ case eans of+ Left err -> pure $ Just $ errorLines $ show err+ Right (df', ignoreds, warns) -> do+ let warnings = do+ guard $ not $ null warns+ pure $ errorLines $+ prettyWarnings warns+ igns = do+ guard $ not $ null ignoreds+ pure+ ["Some flags have not been recognized: "+ <> T.pack (intercalate ", " $ map SrcLoc.unLoc ignoreds)+ ]+ dbg $ LogEvalPostSetDynFlags df'+ setSessionAndInteractiveDynFlags df'+ pure $ warnings <> igns+ | -- A type/kind command+ Just (cmd, arg) <- parseGhciLikeCmd $ T.pack stmt =+ evalGhciLikeCmd cmd arg+ | -- A statement+ isStmt pf stmt =+ do+ dbg $ LogEvalStmtStart stmt+ res <- exec stmt l+ let r = case res of+ Left err -> Just . (if mark_exception then exceptionLines else errorLines) $ err+ Right x -> singleLine <$> x+ dbg $ LogEvalStmtResult r+ return r+ | -- An import+ isImport pf stmt =+ do+ dbg $ LogEvalImport stmt+ _ <- addImport stmt+ return Nothing+ | -- A declaration+ otherwise =+ do+ dbg $ LogEvalDeclaration stmt+ void $ runDecls stmt+ return Nothing+ pf = initParserOpts df+ unhelpfulReason = UnhelpfulInteractive+ exec stmt l =+ let opts = execOptions{execSourceFile = fp, execLineNumber = l}+ in myExecStmt stmt opts++needsQuickCheck :: [(Section, Test)] -> Bool+needsQuickCheck = any (isProperty . snd)++hasQuickCheck :: DynFlags -> Bool+hasQuickCheck df = hasPackage df "QuickCheck"++singleLine :: String -> [Text]+singleLine s = [T.pack s]++{- |+ Convert error messages to a list of text lines+ Remove unnecessary information.+-}+errorLines :: String -> [Text]+errorLines =+ dropWhileEnd T.null+ . takeWhile (not . (\x -> "CallStack" `T.isPrefixOf` x || "HasCallStack" `T.isPrefixOf` x))+ . T.lines+ . T.pack++{- |+ Convert exception messages to a list of text lines+ Remove unnecessary information and mark it as exception.+ We use '*** Exception:' to make it identical to doctest+ output, see #2353.+-}+exceptionLines :: String -> [Text]+exceptionLines = (ix 0 %~ ("*** Exception: " <>)) . errorLines++{- |+>>> map (pad_ (T.pack "--")) (map T.pack ["2+2",""])+["--2+2","--<BLANKLINE>"]+-}+pad_ :: Text -> Text -> Text+pad_ prefix = (prefix `T.append`) . convertBlank++convertBlank :: Text -> Text+convertBlank x+ | T.null x = "<BLANKLINE>"+ | otherwise = x++padPrefix :: IsString p => Format -> p+padPrefix SingleLine = "-- "+padPrefix _ = ""++{- | Resulting @Text@ MUST NOT prefix each line with @--@+ Such comment-related post-process will be taken place+ solely in 'evalGhciLikeCmd'.+-}+type GHCiLikeCmd = DynFlags -> Text -> Ghc (Maybe Text)++-- Should we use some sort of trie here?+ghciLikeCommands :: [(Text, GHCiLikeCmd)]+ghciLikeCommands =+ [ ("info", doInfoCmd False)+ , ("info!", doInfoCmd True)+ , ("kind", doKindCmd False)+ , ("kind!", doKindCmd True)+ , ("type", doTypeCmd)+ ]++evalGhciLikeCmd :: Text -> Text -> Ghc (Maybe [Text])+evalGhciLikeCmd cmd arg = do+ df <- getSessionDynFlags+ case lookup cmd ghciLikeCommands+ <|> snd+ <$> find (T.isPrefixOf cmd . fst) ghciLikeCommands of+ Just hndler ->+ fmap+ T.lines+ <$> hndler df arg+ _ -> E.throw $ GhciLikeCmdNotImplemented cmd arg++doInfoCmd :: Bool -> DynFlags -> Text -> Ghc (Maybe Text)+doInfoCmd allInfo dflags s = do+ sdocs <- mapM infoThing (T.words s)+ pure $ Just $ T.pack $ showSDoc dflags (vcat sdocs)+ where+ infoThing :: GHC.GhcMonad m => Text -> m SDoc+ infoThing (T.unpack -> str) = do+ names <- GHC.parseName str+ mb_stuffs <- mapM (GHC.getInfo allInfo) names+ let filtered = filterOutChildren (\(t,_f,_ci,_fi,_sd) -> t)+ (catMaybes $ toList mb_stuffs)+ return $ vcat (intersperse (text "") $ map pprInfo filtered)++ filterOutChildren :: (a -> TyThing) -> [a] -> [a]+ filterOutChildren get_thing xs+ = filter (not . has_parent) xs+ where+ all_names = mkNameSet (map (getName . get_thing) xs)+ has_parent x = case tyThingParent_maybe (get_thing x) of+ Just p -> getName p `elemNameSet` all_names+ Nothing -> False++ pprInfo :: (TyThing, Fixity, [GHC.ClsInst], [GHC.FamInst], SDoc) -> SDoc+ pprInfo (thing, fixity, cls_insts, fam_insts, docs)+ = docs+ $$ pprTyThingInContextLoc thing+ $$ showFixity thing fixity+ $$ vcat (map GHC.pprInstance cls_insts)+ $$ vcat (map GHC.pprFamInst fam_insts)++ pprTyThingInContextLoc :: TyThing -> SDoc+ pprTyThingInContextLoc tyThing+ = showWithLoc (pprDefinedAt (getName tyThing))+ (pprTyThingInContext showToHeader tyThing)++ showWithLoc :: SDoc -> SDoc -> SDoc+ showWithLoc loc doc+ = hang doc 2 (text "\t--" <+> loc)++ showFixity :: TyThing -> Fixity -> SDoc+ showFixity thing fixity+ | fixity /= GHC.defaultFixity || isSymOcc (getOccName thing)+ = ppr fixity <+> pprInfixName (GHC.getName thing)+ | otherwise = empty++doKindCmd :: Bool -> DynFlags -> Text -> Ghc (Maybe Text)+doKindCmd False df arg = do+ let input = T.strip arg+ (_, kind) <- typeKind False $ T.unpack input+ let kindText = text (T.unpack input) <+> "::" <+> pprSigmaType kind+ pure $ Just $ T.pack (showSDoc df kindText)+doKindCmd True df arg = do+ let input = T.strip arg+ (ty, kind) <- typeKind True $ T.unpack input+ let kindDoc = text (T.unpack input) <+> "::" <+> pprSigmaType kind+ tyDoc = "=" <+> pprSigmaType ty+ pure $ Just $ T.pack (showSDoc df $ kindDoc $$ tyDoc)++doTypeCmd :: DynFlags -> Text -> Ghc (Maybe Text)+doTypeCmd dflags arg = do+ let (emod, expr) = parseExprMode arg+ ty <- GHC.exprType emod $ T.unpack expr+ let rawType = T.strip $ T.pack $ showSDoc dflags $ pprSigmaType ty+ broken = T.any (\c -> c == '\r' || c == '\n') rawType+ pure $+ Just $+ if broken+ then+ T.pack $+ showSDoc dflags $+ text (T.unpack expr)+ $$ nest 2 ("::" <+> pprSigmaType ty)+ else expr <> " :: " <> rawType <> "\n"++parseExprMode :: Text -> (TcRnExprMode, T.Text)+parseExprMode rawArg = case T.break isSpace rawArg of+ ("+d", rest) -> (TM_Default, T.strip rest)+ _ -> (TM_Inst, rawArg)++data GhciLikeCmdException = GhciLikeCmdNotImplemented+ { ghciCmdName :: Text+ , ghciCmdArg :: Text+ }++instance Show GhciLikeCmdException where+ showsPrec _ GhciLikeCmdNotImplemented{..} =+ showString "unknown command '"+ . showString (T.unpack ghciCmdName)+ . showChar '\''++instance E.Exception GhciLikeCmdException++{-+>>> parseGhciLikeCmd (T.pack ":kind! N + M + 1")+Just ("kind!","N + M + 1")+>>> parseGhciLikeCmd (T.pack ":kind a")+Just ("kind","a")+-}+parseGhciLikeCmd :: Text -> Maybe (Text, Text)+parseGhciLikeCmd input = do+ (':', rest) <- T.uncons $ T.stripStart input+ pure $ second T.strip $ T.break isSpace rest
plugins/hls-eval-plugin/test/Main.hs view
@@ -6,13 +6,15 @@ ) where import Control.Lens (_Just, folded, preview, view, (^.),- (^..))+ (^..), (^?))+import Control.Monad (join) import Data.Aeson (Value (Object), fromJSON, object, (.=)) import Data.Aeson.Types (Pair, Result (Success)) import Data.List (isInfixOf) import Data.List.Extra (nubOrdOn) import qualified Data.Map as Map+import qualified Data.Maybe as Maybe import qualified Data.Text as T import Ide.Plugin.Config (Config) import qualified Ide.Plugin.Config as Plugin@@ -59,6 +61,9 @@ lenses <- getCodeLenses doc liftIO $ map (view range) lenses @?= [Range (Position 4 0) (Position 5 0)] + , goldenWithEvalForCodeAction "Evaluation of expressions via code action" "T1" "hs"+ , goldenWithEvalForCodeAction "Reevaluation of expressions via code action" "T2" "hs"+ , goldenWithEval "Evaluation of expressions" "T1" "hs" , goldenWithEval "Reevaluation of expressions" "T2" "hs" , goldenWithEval "Evaluation of expressions w/ imports" "T3" "hs"@@ -221,6 +226,10 @@ goldenWithEval title path ext = goldenWithHaskellDocInTmpDir def evalPlugin title (mkFs $ FS.directProject (path <.> ext)) path "expected" ext executeLensesBackwards +goldenWithEvalForCodeAction :: TestName -> FilePath -> FilePath -> TestTree+goldenWithEvalForCodeAction title path ext =+ goldenWithHaskellDocInTmpDir def evalPlugin title (mkFs $ FS.directProject (path <.> ext)) path "expected" ext executeCodeActionsBackwards+ goldenWithEvalAndFs :: TestName -> [FS.FileTree] -> FilePath -> FilePath -> TestTree goldenWithEvalAndFs title tree path ext = goldenWithHaskellDocInTmpDir def evalPlugin title (mkFs tree) path "expected" ext executeLensesBackwards@@ -239,14 +248,24 @@ -- | Execute lenses backwards, to avoid affecting their position in the source file executeLensesBackwards :: TextDocumentIdentifier -> Session () executeLensesBackwards doc = do- codeLenses <- reverse <$> getCodeLenses doc+ codeLenses <- getCodeLenses doc -- liftIO $ print codeLenses+ executeCmdsBackwards [c | CodeLens{_command = Just c} <- codeLenses] - -- Execute sequentially, nubbing elements to avoid- -- evaluating the same section with multiple tests- -- more than twice- mapM_ executeCmd $- nubOrdOn actSectionId [c | CodeLens{_command = Just c} <- codeLenses]+executeCodeActionsBackwards :: TextDocumentIdentifier -> Session ()+executeCodeActionsBackwards doc = do+ codeLenses <- getCodeLenses doc+ let ranges = [_range | CodeLens{_range} <- codeLenses]+ -- getAllCodeActions cannot get our code actions because they have no diagnostics+ codeActions <- join <$> traverse (getCodeActions doc) ranges+ let cmds = Maybe.mapMaybe (^? _L) codeActions+ executeCmdsBackwards cmds++-- Execute commands backwards, nubbing elements to avoid+-- evaluating the same section with multiple tests+-- more than twice+executeCmdsBackwards :: [Command] -> Session ()+executeCmdsBackwards = mapM_ executeCmd . nubOrdOn actSectionId . reverse actSectionId :: Command -> Int actSectionId Command{_arguments = Just [fromJSON -> Success EvalParams{..}]} = evalId
plugins/hls-explicit-imports-plugin/src/Ide/Plugin/ExplicitImports.hs view
@@ -25,7 +25,6 @@ import qualified Data.Aeson as A (ToJSON (toJSON)) import Data.Aeson.Types (FromJSON) import Data.Char (isSpace)-import Data.Functor ((<&>)) import qualified Data.IntMap as IM (IntMap, elems, fromList, (!?)) import Data.IORef (readIORef)@@ -218,16 +217,18 @@ -- |^-_paddingLeft -- ^-_position generateInlayHints :: Range -> ImportEdit -> PositionMapping -> Maybe InlayHint- generateInlayHints (Range _ end) ie pm = mkLabel ie <&> \label ->- InlayHint { _position = end- , _label = InL label- , _kind = Nothing -- neither a type nor a parameter- , _textEdits = fmap singleton $ toTEdit pm ie- , _tooltip = Just $ InL "Make this import explicit" -- simple enough, no need to resolve- , _paddingLeft = Just True -- show an extra space before the inlay hint- , _paddingRight = Nothing- , _data_ = Nothing- }+ generateInlayHints (Range _ end) ie pm = do+ label <- mkLabel ie+ currentEnd <- toCurrentPosition pm end+ return InlayHint { _position = currentEnd+ , _label = InL label+ , _kind = Nothing -- neither a type nor a parameter+ , _textEdits = fmap singleton $ toTEdit pm ie+ , _tooltip = Just $ InL "Make this import explicit" -- simple enough, no need to resolve+ , _paddingLeft = Just True -- show an extra space before the inlay hint+ , _paddingRight = Nothing+ , _data_ = Nothing+ } mkLabel :: ImportEdit -> Maybe T.Text mkLabel (ImportEdit{ieResType, ieText}) = let title ExplicitImport = Just $ abbreviateImportTitleWithoutModule ieText
plugins/hls-explicit-record-fields-plugin/src/Ide/Plugin/ExplicitFields.hs view
@@ -43,7 +43,9 @@ srcSpanToLocation, srcSpanToRange, viaShow) import Development.IDE.Core.PluginUtils-import Development.IDE.Core.PositionMapping (toCurrentRange)+import Development.IDE.Core.PositionMapping (PositionMapping,+ toCurrentPosition,+ toCurrentRange) import Development.IDE.Core.RuleTypes (TcModuleResult (..), TypeCheck (..)) import qualified Development.IDE.Core.Shake as Shake@@ -204,19 +206,19 @@ | record <- records , pos <- maybeToList $ fmap _start $ recordInfoToDotDotRange record ] defnLocsList <- lift $ sequence locations- pure $ InL $ mapMaybe (mkInlayHint crr pragma) defnLocsList+ pure $ InL $ mapMaybe (mkInlayHint crr pragma pm) defnLocsList where- mkInlayHint :: CollectRecordsResult -> NextPragmaInfo -> (Maybe [(Location, Identifier)], RecordInfo) -> Maybe InlayHint- mkInlayHint CRR {enabledExtensions, nameMap} pragma (defnLocs, record) =+ mkInlayHint :: CollectRecordsResult -> NextPragmaInfo -> PositionMapping -> (Maybe [(Location, Identifier)], RecordInfo) -> Maybe InlayHint+ mkInlayHint CRR {enabledExtensions, nameMap} pragma pm (defnLocs, record) = let range = recordInfoToDotDotRange record textEdits = maybeToList (renderRecordInfoAsTextEdit nameMap record) <> maybeToList (pragmaEdit enabledExtensions pragma) names = renderRecordInfoAsDotdotLabelName record in do- end <- fmap _end range+ currentEnd <- range >>= toCurrentPosition pm . _end names' <- names defnLocs' <- defnLocs- let excludeDotDot (Location _ (Range _ end')) = end' /= end+ let excludeDotDot (Location _ (Range _ end)) = end /= currentEnd -- find location from dotdot definitions that name equal to label name findLocation name locations = let -- filter locations not within dotdot range@@ -227,7 +229,7 @@ valueWithLoc = [ (T.pack $ printName name, findLocation name defnLocs') | name <- names' ] -- use `, ` to separate labels with definition location label = intersperse (mkInlayHintLabelPart (", ", Nothing)) $ fmap mkInlayHintLabelPart valueWithLoc- pure $ InlayHint { _position = end -- at the end of dotdot+ pure $ InlayHint { _position = currentEnd -- at the end of dotdot , _label = InR label , _kind = Nothing -- neither a type nor a parameter , _textEdits = Just textEdits -- same as CodeAction@@ -248,20 +250,22 @@ | Just range <- [toCurrentRange pm visibleRange] , uid <- RangeMap.elementsInRange range crCodeActions , Just record <- [IntMap.lookup uid crCodeActionResolve] ]- pure $ InL (concatMap (mkInlayHints nameMap) records)+ pure $ InL (concatMap (mkInlayHints nameMap pm) records) where- mkInlayHints :: UniqFM Name [Name] -> RecordInfo -> [InlayHint]- mkInlayHints nameMap record@(RecordInfoApp _ (RecordAppExpr _ fla)) =+ mkInlayHints :: UniqFM Name [Name] -> PositionMapping -> RecordInfo -> [InlayHint]+ mkInlayHints nameMap pm record@(RecordInfoApp _ (RecordAppExpr _ fla)) = let textEdits = renderRecordInfoAsTextEdit nameMap record- in mapMaybe (mkInlayHint textEdits) fla- mkInlayHints _ _ = []- mkInlayHint :: Maybe TextEdit -> (Located FieldLabel, HsExpr GhcTc) -> Maybe InlayHint- mkInlayHint te (label, _) =+ in mapMaybe (mkInlayHint textEdits pm) fla+ mkInlayHints _ _ _ = []++ mkInlayHint :: Maybe TextEdit -> PositionMapping -> (Located FieldLabel, HsExpr GhcTc) -> Maybe InlayHint+ mkInlayHint te pm (label, _) = let (name, loc) = ((flSelector . unLoc) &&& (srcSpanToLocation . getLoc)) label fieldDefLoc = srcSpanToLocation (nameSrcSpan name) in do (Location _ recRange) <- loc- pure InlayHint { _position = _start recRange+ currentStart <- toCurrentPosition pm (_start recRange)+ pure InlayHint { _position = currentStart , _label = InR $ pure (mkInlayHintLabelPart name fieldDefLoc) , _kind = Nothing -- neither a type nor a parameter , _textEdits = Just (maybeToList te) -- same as CodeAction@@ -270,6 +274,7 @@ , _paddingRight = Nothing , _data_ = Nothing }+ mkInlayHintLabelPart name loc = InlayHintLabelPart (printOutputable (pprNameUnqualified name) <> "=") Nothing loc Nothing mkTitle :: [Extension] -> Text
plugins/hls-gadt-plugin/src/Ide/Plugin/GHC.hs view
@@ -7,16 +7,20 @@ {-# OPTIONS_GHC -Wno-overlapping-patterns #-} module Ide.Plugin.GHC where +#if !MIN_VERSION_ghc(9,11,0) import Data.Functor ((<&>))+#endif import Data.List.Extra (stripInfix) import qualified Data.Text as T import Development.IDE import Development.IDE.GHC.Compat import Development.IDE.GHC.Compat.ExactPrint-import GHC.Parser.Annotation (AddEpAnn (..),- DeltaPos (..),+import GHC.Parser.Annotation (DeltaPos (..), EpAnn (..), EpAnnComments (EpaComments))+#if MIN_VERSION_ghc(9,11,0)+import GHC.Parser.Annotation (EpToken (..))+#endif import Ide.PluginUtils (subRange) import Language.Haskell.GHC.ExactPrint.Parsers (parseDecl) @@ -44,6 +48,11 @@ import Language.Haskell.GHC.ExactPrint.Utils (showAst) #endif +#if MIN_VERSION_ghc(9,11,0)+import GHC.Types.SrcLoc (UnhelpfulSpanReason (..))+#else+import GHC.Parser.Annotation (AddEpAnn (..))+#endif type GP = GhcPass Parsed @@ -97,7 +106,9 @@ h98ToGADTConDecl dataName tyVars ctxt = \case ConDeclH98{..} -> ConDeclGADT-#if MIN_VERSION_ghc(9,9,0)+#if MIN_VERSION_ghc(9,11,0)+ (AnnConDeclGADT [] [] NoEpUniTok)+#elif MIN_VERSION_ghc(9,9,0) (NoEpUniTok, con_ext) #else con_ext@@ -209,7 +220,11 @@ adjustDataDecl DataDecl{..} = DataDecl { tcdDExt = adjustWhere tcdDExt , tcdDataDefn = tcdDataDefn- { dd_cons =+ {+#if MIN_VERSION_ghc(9,11,0)+ dd_ext = adjustDefnWhere (dd_ext tcdDataDefn),+#endif+ dd_cons = fmap adjustCon (dd_cons tcdDataDefn) } , ..@@ -218,8 +233,12 @@ -- Make every data constructor start with a new line and 2 spaces adjustCon :: LConDecl GP -> LConDecl GP-#if MIN_VERSION_ghc(9,9,0)+#if MIN_VERSION_ghc(9,11,0) adjustCon (L _ r) =+ let delta = EpaDelta (UnhelpfulSpan UnhelpfulNoLocationInfo) (DifferentLine 1 2) []+ in L (EpAnn delta (AnnListItem []) (EpaComments [])) r+#elif MIN_VERSION_ghc(9,9,0)+ adjustCon (L _ r) = let delta = EpaDelta (DifferentLine 1 3) [] in L (EpAnn delta (AnnListItem []) (EpaComments [])) r #else@@ -229,6 +248,10 @@ #endif -- Adjust where annotation to the same line of the type constructor+#if MIN_VERSION_ghc(9,11,0)+ -- tcdDext is just a placeholder in ghc-9.12+ adjustWhere = id+#else adjustWhere tcdDExt = tcdDExt <&> #if !MIN_VERSION_ghc(9,9,0) map@@ -238,7 +261,16 @@ then AddEpAnn AnnWhere d1 else AddEpAnn ann l )+#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) [])+#endif -- Remove the first extra line if exist removeExtraEmptyLine s = case stripInfix "\n\n" s of Just (x, xs) -> x <> "\n" <> xs@@ -257,6 +289,10 @@ #endif pattern UserTyVar' :: LIdP pass -> HsTyVarBndr flag pass+#if MIN_VERSION_ghc(9,11,0)+pattern UserTyVar' s <- HsTvb _ _ (HsBndrVar _ s) _+#else pattern UserTyVar' s <- UserTyVar _ _ s+#endif implicitTyVars = wrapXRec @GP mkHsOuterImplicit
plugins/hls-hlint-plugin/test/Main.hs view
@@ -276,14 +276,24 @@ , "g = 2" , "#endif", "" ]- expectedComments = [ "-- comment before header"- , "module Comments where", ""- , "{-# standalone annotation #-}", ""- , "-- standalone comment", ""- , "-- | haddock comment"- , "f = {- inline comment -} {- inline comment inside refactored code -}1 -- ending comment", ""- , "-- final comment"- ]+ expectedComments = case ghcVersion of+ GHC912 -> [ "-- comment before header"+ , "module Comments where", ""+ , "{-# standalone annotation #-}", ""+ , "-- standalone comment", ""+ , "-- | haddock comment"+ , "f = {- inline comment -}{- inline comment inside refactored code -} 1 -- ending comment", ""+ , "-- final comment"+ ]++ _ -> [ "-- comment before header"+ , "module Comments where", ""+ , "{-# standalone annotation #-}", ""+ , "-- standalone comment", ""+ , "-- | haddock comment"+ , "f = {- inline comment -} {- inline comment inside refactored code -}1 -- ending comment", ""+ , "-- final comment"+ ] expectedComments2 = [ "module TwoHintsAndComment where" , "biggest = foldr1 max -- the line above will show two hlint hints, \"eta reduce\" and \"use maximum\"" ]
plugins/hls-refactor-plugin/src/Development/IDE/GHC/ExactPrint.hs view
@@ -106,6 +106,9 @@ deltaPos) import GHC.Types.SrcLoc (generatedSrcSpan) #endif+#if MIN_VERSION_ghc(9,11,0)+import GHC.Types.SrcLoc (UnhelpfulSpanReason(..))+#endif #if MIN_VERSION_ghc(9,9,0) import GHC (@@ -116,6 +119,9 @@ EpAnn (..), EpaLocation, EpaLocation' (..),+#if MIN_VERSION_ghc(9,11,0)+ EpToken (..),+#endif NameAdornment (..), NameAnn (..), SrcSpanAnnA,@@ -124,7 +130,6 @@ emptyComments, spanAsAnchor) #endif- setPrecedingLines :: #if !MIN_VERSION_ghc(9,9,0) Default t =>@@ -168,6 +173,10 @@ (makeDeltaAst ps) #endif +#if MIN_VERSION_ghc(9,11,0)+type Anchor = EpaLocation+#endif+ ------------------------------------------------------------------------------ {- | A transformation for grafting source trees together. Use the semigroup@@ -466,8 +475,11 @@ False -> first (DL.singleton ldecl <>) <$> modifyMatchingDecl rest modifyDeclsT' (fmap (first DL.toList) . modifyMatchingDecl) a -#if MIN_VERSION_ghc(9,9,0)+#if MIN_VERSION_ghc(9,11,0) generatedAnchor :: DeltaPos -> Anchor+generatedAnchor dp = EpaDelta (UnhelpfulSpan UnhelpfulNoLocationInfo) dp []+#elif MIN_VERSION_ghc(9,9,0)+generatedAnchor :: DeltaPos -> Anchor generatedAnchor dp = EpaDelta dp [] #else generatedAnchor :: AnchorOperation -> Anchor@@ -766,15 +778,28 @@ addParensToCtxt :: Maybe EpaLocation -> AnnContext -> AnnContext addParensToCtxt close_dp = addOpen . addClose where+#if MIN_VERSION_ghc(9,11,0)+ addOpen it@AnnContext{ac_open = []} = it{ac_open = [EpTok (epl 0)]}+#else addOpen it@AnnContext{ac_open = []} = it{ac_open = [epl 0]}+#endif addOpen other = other addClose it+#if MIN_VERSION_ghc(9,11,0)+ | Just c <- close_dp = it{ac_close = [EpTok c]}+ | AnnContext{ac_close = []} <- it = it{ac_close = [EpTok (epl 0)]}+#else | Just c <- close_dp = it{ac_close = [c]} | AnnContext{ac_close = []} <- it = it{ac_close = [epl 0]}+#endif | otherwise = it epl :: Int -> EpaLocation+#if MIN_VERSION_ghc(9,11,0)+epl n = EpaDelta (UnhelpfulSpan UnhelpfulNoLocationInfo) (SameLine n) []+#else epl n = EpaDelta (SameLine n) []+#endif epAnn :: SrcSpan -> ann -> EpAnn ann epAnn srcSpan anns = EpAnn (spanAsAnchor srcSpan) anns emptyComments@@ -803,14 +828,25 @@ #endif addParens :: Bool -> GHC.NameAnn -> GHC.NameAnn+#if MIN_VERSION_ghc(9,11,0) addParens True it@NameAnn{} =- it{nann_adornment = NameParens, nann_open = epl 0, nann_close = epl 0 }+ it{nann_adornment = NameParens (EpTok (epl 0)) (EpTok (epl 0)) } addParens True it@NameAnnCommas{} =- it{nann_adornment = NameParens, nann_open = epl 0, nann_close = epl 0 }+ it{nann_adornment = NameParens (EpTok (epl 0)) (EpTok (epl 0)) } addParens True it@NameAnnOnly{} =- it{nann_adornment = NameParens, nann_open = epl 0, nann_close = epl 0 }+ it{nann_adornment = NameParens (EpTok (epl 0)) (EpTok (epl 0)) }+addParens True it@NameAnnTrailing{} =+ NameAnn{nann_adornment = NameParens (EpTok (epl 0)) (EpTok (epl 0)), nann_name = epl 0, nann_trailing = nann_trailing it}+#else+addParens True it@NameAnn{} =+ it{nann_adornment = NameParens, nann_open=epl 0, nann_close=epl 0 }+addParens True it@NameAnnCommas{} =+ it{nann_adornment = NameParens, nann_open=epl 0, nann_close=epl 0 }+addParens True it@NameAnnOnly{} =+ it{nann_adornment = NameParens, nann_open=epl 0, nann_close=epl 0 } addParens True NameAnnTrailing{..} =- NameAnn{nann_adornment = NameParens, nann_open = epl 0, nann_close = epl 0, nann_name = epl 0, ..}+ NameAnn{nann_adornment = NameParens, nann_open=epl 0, nann_close=epl 0, nann_name = epl 0, ..}+#endif addParens _ it = it removeTrailingComma :: GenLocated SrcSpanAnnA ast -> GenLocated SrcSpanAnnA ast
plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction.hs view
@@ -12,7 +12,9 @@ fillHolePluginDescriptor, extendImportPluginDescriptor, -- * For testing- matchRegExMultipleImports+ matchRegExMultipleImports,+ extractNotInScopeName,+ NotInScope(..) ) where import Control.Applicative ((<|>))@@ -48,7 +50,9 @@ import Development.IDE.Core.Shake hiding (Log) import Development.IDE.GHC.Compat hiding (ImplicitPrelude)+#if !MIN_VERSION_ghc(9,11,0) import Development.IDE.GHC.Compat.Util+#endif import Development.IDE.GHC.Error import Development.IDE.GHC.ExactPrint import qualified Development.IDE.GHC.ExactPrint as E@@ -69,8 +73,7 @@ import Development.IDE.Types.Exports import Development.IDE.Types.Location import Development.IDE.Types.Options-import GHC (AddEpAnn (AddEpAnn),- AnnsModule (am_main),+import GHC ( DeltaPos (..), EpAnn (..), LEpaComment)@@ -105,18 +108,31 @@ #if !MIN_VERSION_ghc(9,9,0) import Development.IDE.GHC.Compat.ExactPrint (makeDeltaAst)-import GHC (Anchor (anchor_op),+import GHC (AddEpAnn (AddEpAnn),+ AnnsModule (am_main),+ Anchor (anchor_op), AnchorOperation (..), EpaLocation (..)) #endif -#if MIN_VERSION_ghc(9,9,0)-import GHC (EpaLocation,+#if MIN_VERSION_ghc(9,9,0) && !MIN_VERSION_ghc(9,11,0)+import GHC (AddEpAnn (AddEpAnn),+ AnnsModule (am_main),+ EpaLocation, EpaLocation' (..), HasLoc (..)) import GHC.Types.SrcLoc (srcSpanToRealSrcSpan) #endif+#if MIN_VERSION_ghc(9,11,0)+import GHC (EpaLocation,+ AnnsModule (am_where),+ EpaLocation' (..),+ HasLoc (..),+ EpToken (..))+import GHC.Types.SrcLoc (srcSpanToRealSrcSpan)+#endif + ------------------------------------------------------------------------------------------------- -- | Generate code actions.@@ -339,7 +355,11 @@ case unLoc <$> findDeclContainingLoc (_start range) lsigs of Just sig' -> Just sig' Nothing -> do+#if MIN_VERSION_ghc(9,11,0)+ lHsBindLR <- findDeclContainingLoc (_start range) binds+#else lHsBindLR <- findDeclContainingLoc (_start range) (bagToList binds)+#endif findSigOfBind range (unLoc lHsBindLR) go _ = Nothing @@ -420,7 +440,11 @@ modName importSpan | occ <- mkVarOcc identifier,+#if MIN_VERSION_ghc(9,11,0)+ impModsVals <- importedByUser . concat $ M.elems imp_mods,+#else impModsVals <- importedByUser . concat $ moduleEnvElts imp_mods,+#endif Just rdrEnv <- listToMaybe [ imv_all_exports@@ -659,7 +683,11 @@ name (L _ Match{m_grhss=GRHSs{grhssLocalBinds}}) = do let go bag lsigs =+#if MIN_VERSION_ghc(9,11,0)+ if null bag+#else if isEmptyBag bag+#endif then [] else concatMap (findRelatedSpanForHsBind indexedContent name lsigs) bag case grhssLocalBinds of@@ -1572,13 +1600,34 @@ modNameP = fmap snd $ RE.withMatched $ conIDP `sepBy1` RE.sym '.' +-- | A Backward compatible implementation of `lookupOccEnv_AllNameSpaces` for+-- GHC <=9.6+--+-- It looks for a symbol name in all known namespaces, including types,+-- variables, and fieldnames.+--+-- Note that on GHC >= 9.8, the record selectors are not in the `mkVarOrDataOcc`+-- anymore, but are in a custom namespace, see+-- https://gitlab.haskell.org/ghc/ghc/-/wikis/migration/9.8#new-namespace-for-record-fields,+-- hence we need to use this "AllNamespaces" implementation, otherwise we'll+-- miss them.+lookupOccEnvAllNamespaces :: ExportsMap -> T.Text -> [IdentInfo]+#if MIN_VERSION_ghc(9,7,0)+lookupOccEnvAllNamespaces exportsMap name = Set.toList $ mconcat (lookupOccEnv_AllNameSpaces (getExportsMap exportsMap) (mkTypeOcc name))+#else+lookupOccEnvAllNamespaces exportsMap name = maybe [] Set.toList $+ lookupOccEnv (getExportsMap exportsMap) (mkVarOrDataOcc name)+ <> lookupOccEnv (getExportsMap exportsMap) (mkTypeOcc name) -- look up the modified unknown name in the export map+#endif++ constructNewImportSuggestions :: ExportsMap -> (Maybe T.Text, NotInScope) -> Maybe [T.Text] -> QualifiedImportStyle -> [ImportSuggestion] constructNewImportSuggestions exportsMap (qual, thingMissing) notTheseModules qis = nubOrdBy simpleCompareImportSuggestion [ suggestion | Just name <- [T.stripPrefix (maybe "" (<> ".") qual) $ notInScope thingMissing] -- strip away qualified module names from the unknown name- , identInfo <- maybe [] Set.toList $ lookupOccEnv (getExportsMap exportsMap) (mkVarOrDataOcc name)- <> lookupOccEnv (getExportsMap exportsMap) (mkTypeOcc name) -- look up the modified unknown name in the export map++ , identInfo <- lookupOccEnvAllNamespaces exportsMap name -- look up the modified unknown name in the export map , canUseIdent thingMissing identInfo -- check if the identifier information retrieved can be used , moduleNameText identInfo `notElem` fromMaybe [] notTheseModules -- check if the module of the identifier is allowed , suggestion <- renderNewImport identInfo -- creates a list of import suggestions for the retrieved identifier information@@ -1700,13 +1749,22 @@ #endif EpAnn _ annsModule _ -> do -- Find the first 'where'+#if MIN_VERSION_ghc(9,11,0)+ whereLocation <- filterWhere $ am_where annsModule+#else whereLocation <- listToMaybe . mapMaybe filterWhere $ am_main annsModule+#endif epaLocationToLine whereLocation #if !MIN_VERSION_ghc(9,9,0) EpAnnNotUsed -> Nothing #endif+#if MIN_VERSION_ghc(9,11,0)+ filterWhere (EpTok loc) = Just loc+ filterWhere _ = Nothing+#else filterWhere (AddEpAnn AnnWhere loc) = Just loc filterWhere _ = Nothing+#endif epaLocationToLine :: EpaLocation -> Maybe Int #if MIN_VERSION_ghc(9,9,0)@@ -1719,12 +1777,19 @@ epaLocationToLine (EpaSpan sp) = Just . srcLocLine . realSrcSpanEnd $ sp #endif+#if MIN_VERSION_ghc(9,11,0)+ epaLocationToLine (EpaDelta _ (SameLine _) priorComments) = Just $ sumCommentsOffset priorComments+ -- 'priorComments' contains the comments right before the current EpaLocation+ -- Summing line offset of priorComments is necessary, as 'line' is the gap between the last comment and+ -- the current AST node+ epaLocationToLine (EpaDelta _ (DifferentLine line _) priorComments) = Just (line + sumCommentsOffset priorComments)+#else epaLocationToLine (EpaDelta (SameLine _) priorComments) = Just $ sumCommentsOffset priorComments -- 'priorComments' contains the comments right before the current EpaLocation -- Summing line offset of priorComments is necessary, as 'line' is the gap between the last comment and -- the current AST node epaLocationToLine (EpaDelta (DifferentLine line _) priorComments) = Just (line + sumCommentsOffset priorComments)-+#endif sumCommentsOffset :: [LEpaComment] -> Int #if MIN_VERSION_ghc(9,9,0) sumCommentsOffset = sum . fmap (\(L anchor _) -> anchorOpLine anchor)@@ -1732,9 +1797,14 @@ sumCommentsOffset = sum . fmap (\(L anchor _) -> anchorOpLine (anchor_op anchor)) #endif -#if MIN_VERSION_ghc(9,9,0)+#if MIN_VERSION_ghc(9,11,0) anchorOpLine :: EpaLocation' a -> Int anchorOpLine EpaSpan{} = 0+ anchorOpLine (EpaDelta _ (SameLine _) _) = 0+ anchorOpLine (EpaDelta _ (DifferentLine line _) _) = line+#elif MIN_VERSION_ghc(9,9,0)+ anchorOpLine :: EpaLocation' a -> Int+ anchorOpLine EpaSpan{} = 0 anchorOpLine (EpaDelta (SameLine _) _) = 0 anchorOpLine (EpaDelta (DifferentLine line _) _) = line #else@@ -1825,7 +1895,7 @@ = NotInScopeDataConstructor T.Text | NotInScopeTypeConstructorOrClass T.Text | NotInScopeThing T.Text- deriving Show+ deriving (Show, Eq) notInScope :: NotInScope -> T.Text notInScope (NotInScopeDataConstructor t) = t@@ -1840,6 +1910,38 @@ = Just $ NotInScopeDataConstructor name | Just [name] <- matchRegexUnifySpaces x "ot in scope: type constructor or class [^‘]*‘([^’]*)’" = Just $ NotInScopeTypeConstructorOrClass name+ | Just [name] <- matchRegexUnifySpaces x "The data constructors of ‘([^ ]+)’ are not all in scope"+ = Just $ NotInScopeDataConstructor name+ | Just [name] <- matchRegexUnifySpaces x "of newtype ‘([^’]*)’ is not in scope"+ = Just $ NotInScopeThing name+ -- Match for HasField "foo" Bar String in the context where, e.g. x.foo is+ -- used, and x :: Bar.+ --+ -- This usually mean that the field is not in scope and the correct fix is to+ -- import (Bar(foo)) or (Bar(..)).+ --+ -- However, it is more reliable to match for the type name instead of the field+ -- name, and most of the time you'll want to import the complete type with all+ -- their fields instead of the specific field.+ --+ -- The regex is convoluted because it accounts for:+ --+ -- - Qualified (or not) `HasField`+ -- - The type bar is always qualified. If it is unqualified, it means that the+ -- parent module is already imported, and in this context it uses an hint+ -- already available in the GHC error message. However this regex accounts for+ -- qualified or not, it does not cost much and should be more robust if the+ -- hint changes in the future+ -- - Next regex will account for polymorphic types, which appears as `HasField+ -- "foo" (Bar Int)...`, e.g. see the parenthesis+ | Just [_module, name] <- matchRegexUnifySpaces x "No instance for [‘(].*HasField \"[^\"]+\" ([^ (.]+\\.)*([^ (.]+).*[’)]"+ = Just $ NotInScopeThing name+ | Just [_module, name] <- matchRegexUnifySpaces x "No instance for [‘(].*HasField \"[^\"]+\" \\(([^ .]+\\.)*([^ .]+)[^)]*\\).*[’)]"+ = Just $ NotInScopeThing name+ -- The order of the "Not in scope" is important, for example, some of the+ -- matcher may catch the "record" value instead of the value later.+ | Just [name] <- matchRegexUnifySpaces x "Not in scope: record field ‘([^’]*)’"+ = Just $ NotInScopeThing name | Just [name] <- matchRegexUnifySpaces x "ot in scope: \\(([^‘ ]+)\\)" = Just $ NotInScopeThing name | Just [name] <- matchRegexUnifySpaces x "ot in scope: ([^‘ ]+)"@@ -1881,14 +1983,11 @@ -- ‘Data.Functor’ nor ‘Data.Text’ exports ‘putStrLn’. extractDoesNotExportModuleName :: T.Text -> Maybe T.Text extractDoesNotExportModuleName x- | Just [m] <--#if MIN_VERSION_ghc(9,4,0)- matchRegexUnifySpaces x "the module ‘([^’]*)’ does not export"- <|> matchRegexUnifySpaces x "nor ‘([^’]*)’ export"-#else- matchRegexUnifySpaces x "Module ‘([^’]*)’ does not export"- <|> matchRegexUnifySpaces x "nor ‘([^’]*)’ exports"-#endif+ | 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 | otherwise = Nothing
plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction/ExactPrint.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE TypeFamilies #-} module Development.IDE.Plugin.CodeAction.ExactPrint (@@ -35,10 +36,8 @@ import Data.Bifunctor (first) import Data.Maybe (fromMaybe, mapMaybe) import Development.IDE.Plugin.CodeAction.Util-import GHC (AddEpAnn (..),- AnnContext (..),+import GHC (AnnContext (..), AnnList (..),- AnnParen (..), DeltaPos (SameLine), EpAnn (..), IsUnicodeSyntax (NormalSyntax),@@ -46,8 +45,17 @@ TrailingAnn (AddCommaAnn), emptyComments, reAnnL) + -- See Note [Guidelines For Using CPP In GHCIDE Import Statements] +#if MIN_VERSION_ghc(9,11,0)+import GHC (EpToken (..)+ , AnnListBrackets (..)+ , EpUniToken (..))+#else+import GHC (AddEpAnn (..),+ AnnParen (..))+#endif #if !MIN_VERSION_ghc(9,9,0) import Data.Default (Default (..)) import GHC (addAnns, ann)@@ -179,7 +187,9 @@ -- For singleton constraints, the close Paren DP is attached to an HsPar wrapping the constraint -- we have to reposition it manually into the AnnContext close_dp = case ctxt of-#if MIN_VERSION_ghc(9,9,0)+#if MIN_VERSION_ghc(9,11,0)+ [L _ (HsParTy (_, (EpTok ap_close)) _)] -> Just ap_close+#elif MIN_VERSION_ghc(9,9,0) [L _ (HsParTy AnnParen{ap_close} _)] -> Just ap_close #else [L _ (HsParTy EpAnn{anns=AnnParen{ap_close}} _)] -> Just ap_close@@ -203,7 +213,11 @@ #else let context = Just $ reAnnL annCtxt emptyComments $ L lContext [resetEntryDP constraint] #endif+#if MIN_VERSION_ghc(9,11,0)+ annCtxt = AnnContext (Just (EpUniTok (epl 1) NormalSyntax)) [EpTok (epl 0) | needsParens] [EpTok (epl 0) | needsParens]+#else annCtxt = AnnContext (Just (NormalSyntax, epl 1)) [epl 0 | needsParens] [epl 0 | needsParens]+#endif needsParens = hsTypeNeedsParens sigPrec $ unLoc constraint ast <- pure $ setEntryDP (makeDeltaAst ast) (SameLine 1) @@ -346,7 +360,9 @@ #endif childRdr x :: LIE GhcPs = L ll' $ IEThingWith-#if MIN_VERSION_ghc(9,9,0)+#if MIN_VERSION_ghc(9,11,0)+ (Nothing, (EpTok d1, NoEpTok, NoEpTok, EpTok noAnn))+#elif MIN_VERSION_ghc(9,9,0) (Nothing, [AddEpAnn AnnOpenP d1, AddEpAnn AnnCloseP noAnn]) #elif MIN_VERSION_ghc(9,7,0) (Nothing, addAnns mempty [AddEpAnn AnnOpenP d1, AddEpAnn AnnCloseP def] emptyComments)@@ -384,6 +400,8 @@ #endif #if MIN_VERSION_ghc(9,7,0) && !MIN_VERSION_ghc(9,9,0) newl = fmap (\ann -> ann ++ [AddEpAnn AnnDotdot d0]) <$> l'''+#elif MIN_VERSION_ghc(9,11,0)+ newl = (\(open, _, comma, close) -> (open, EpTok d0, comma, close)) <$> l''' #else newl = (\ann -> ann ++ [AddEpAnn AnnDotdot d0]) <$> l''' #endif@@ -427,21 +445,31 @@ parentRdr <- liftParseAST df parent let childRdr = reLocA $ L srcChild $ mkRdrUnqual $ mkVarOcc child isParentOperator = hasParen parent+#if MIN_VERSION_ghc(9,11,0)+ let parentLIE = reLocA $ L srcParent $ if isParentOperator then IEType (EpTok (epl 0)) parentRdr'+#else let parentLIE = reLocA $ L srcParent $ if isParentOperator then IEType (epl 0) parentRdr'+#endif else IEName #if MIN_VERSION_ghc(9,5,0) noExtField #endif parentRdr' parentRdr' = modifyAnns parentRdr $ \case+#if MIN_VERSION_ghc(9,11,0)+ it@NameAnn{nann_adornment = NameParens _ _} -> it{nann_adornment=NameParens (EpTok (epl 1)) (EpTok (epl 0))}+#else it@NameAnn{nann_adornment = NameParens} -> it{nann_open = epl 1, nann_close = epl 0}+#endif other -> other childLIE = reLocA $ L srcChild $ IEName #if MIN_VERSION_ghc(9,5,0) noExtField #endif childRdr-#if MIN_VERSION_ghc(9,9,0)+#if MIN_VERSION_ghc(9,11,0)+ listAnn = (Nothing, (EpTok (epl 1), NoEpTok, NoEpTok, EpTok (epl 0)))+#elif MIN_VERSION_ghc(9,9,0) listAnn = (Nothing, [AddEpAnn AnnOpenP (epl 1), AddEpAnn AnnCloseP (epl 0)]) #elif MIN_VERSION_ghc(9,7,0) listAnn = (Nothing, epAnn srcParent [AddEpAnn AnnOpenP (epl 1), AddEpAnn AnnCloseP (epl 0)])@@ -538,7 +566,10 @@ extendHiding symbol (L l idecls) mlies df = do L l' lies <- case mlies of Nothing -> do-#if MIN_VERSION_ghc(9,9,0)+#if MIN_VERSION_ghc(9,11,0)+ let ann :: EpAnn (AnnList (EpToken "hiding", [EpToken ","]))+ ann = noAnnSrcSpanDP0 +#elif MIN_VERSION_ghc(9,9,0) let ann = noAnnSrcSpanDP0 #else src <- uniqueSrcSpanT@@ -549,9 +580,14 @@ #else ann' = flip (fmap.fmap) ann $ \x -> x #endif+#if MIN_VERSION_ghc(9,11,0)+ {al_rest = (EpTok (epl 1), [NoEpTok])+ ,al_brackets=ListParens (EpTok (epl 1)) (EpTok (epl 0))+#else {al_rest = [AddEpAnn AnnHiding (epl 1)] ,al_open = Just $ AddEpAnn AnnOpenP (epl 1) ,al_close = Just $ AddEpAnn AnnCloseP (epl 0)+#endif } return $ L ann' [] Just pr -> pure pr
plugins/hls-refactor-plugin/src/Development/IDE/Plugin/Plugins/AddArgument.hs view
@@ -50,7 +50,9 @@ IsUnicodeSyntax (NormalSyntax)) import Language.Haskell.GHC.ExactPrint (d1, setEntryDP) #endif-+#if MIN_VERSION_ghc(9,11,0)+import GHC.Parser.Annotation (EpToken(..))+#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@@ -77,19 +79,28 @@ -- addArgToMatch "foo" `bar arg1 arg2 = ...` -- => (`bar arg1 arg2 foo = ...`, 2) addArgToMatch :: T.Text -> GenLocated l (Match GhcPs (LocatedA (HsExpr GhcPs))) -> (GenLocated l (Match GhcPs (LocatedA (HsExpr GhcPs))), Int)+#if MIN_VERSION_ghc(9,11,0)+addArgToMatch name (L locMatch (Match xMatch ctxMatch (L l pats) rhs)) =+#else addArgToMatch name (L locMatch (Match xMatch ctxMatch pats rhs)) =- let unqualName = mkRdrUnqual $ mkVarOcc $ T.unpack name+#endif #if MIN_VERSION_ghc(9,9,0)+ let unqualName = mkRdrUnqual $ mkVarOcc $ T.unpack name newPat = L noAnnSrcSpanDP1 $ VarPat NoExtField $ L noAnn unqualName -- The intention is to move `= ...` (right-hand side with equals) to the right so there's 1 space between -- the newly added pattern and the rest indentRhs :: GRHSs GhcPs (LocatedA (HsExpr GhcPs)) -> GRHSs GhcPs (LocatedA (HsExpr GhcPs)) indentRhs rhs@GRHSs{grhssGRHSs} = rhs {grhssGRHSs = fmap (`setEntryDP` (SameLine 1)) grhssGRHSs } #else+ let unqualName = mkRdrUnqual $ mkVarOcc $ T.unpack name newPat = L (noAnnSrcSpanDP1 generatedSrcSpan) $ VarPat NoExtField (noLocA unqualName) indentRhs = id #endif+#if MIN_VERSION_ghc(9,11,0)+ in (L locMatch (Match xMatch ctxMatch (L l (pats <> [newPat])) (indentRhs rhs)), Prelude.length pats)+#else in (L locMatch (Match xMatch ctxMatch (pats <> [newPat]) (indentRhs rhs)), Prelude.length pats)+#endif -- Attempt to insert a binding pattern into each match for the given LHsDecl; succeeds only if the function is a FunBind. -- Also return:@@ -171,7 +182,11 @@ ( noAnn , noExtField , HsUnrestrictedArrow (EpUniTok d1 NormalSyntax)+#if MIN_VERSION_ghc(9,11,0)+ , L wildCardAnn $ HsWildCardTy NoEpTok+#else , L wildCardAnn $ HsWildCardTy noExtField+#endif ) #elif MIN_VERSION_ghc(9,4,0) wildCardAnn = SrcSpanAnn (EpAnn genAnchor1 (AnnListItem []) emptyComments) generatedSrcSpan
plugins/hls-refactor-plugin/src/Development/IDE/Plugin/Plugins/Diagnostic.hs view
@@ -21,6 +21,9 @@ Nothing -> Nothing -- | 'matchRegex' combined with 'unifySpaces'+--+-- >>> matchRegexUnifySpaces "hello I'm a cow" "he(ll)o"+-- Just ["ll"] matchRegexUnifySpaces :: T.Text -> T.Text -> Maybe [T.Text] matchRegexUnifySpaces message = matchRegex (unifySpaces message)
plugins/hls-refactor-plugin/test/Main.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE DuplicateRecordFields #-}@@ -46,6 +47,7 @@ import Test.Hls import qualified Development.IDE.GHC.ExactPrint+import Development.IDE.Plugin.CodeAction (NotInScope (..)) import qualified Development.IDE.Plugin.CodeAction as Refactor import qualified Test.AddArgument @@ -68,6 +70,7 @@ , codeActionTests , codeActionHelperFunctionTests , completionTests+ , extractNotInScopeNameTests ] initializeTests :: TestTree@@ -300,6 +303,8 @@ , suggestImportClassMethodTests , suggestImportTests , suggestAddRecordFieldImportTests+ , suggestAddCoerceMissingConstructorImportTests+ , suggestAddGenericMissingConstructorImportTests , suggestHideShadowTests , fixConstructorImportTests , fixModuleImportTypoTests@@ -316,6 +321,7 @@ , addImplicitParamsConstraintTests , removeExportTests , Test.AddArgument.tests+ , suggestAddRecordFieldUpdateImportTests ] insertImportTests :: TestTree@@ -1849,8 +1855,14 @@ suggestAddRecordFieldImportTests :: TestTree suggestAddRecordFieldImportTests = testGroup "suggest imports of record fields when using OverloadedRecordDot" [ testGroup "The field is suggested when an instance resolution failure occurs"- [ ignoreForGhcVersions [GHC94, GHC96] "Extension not present <9.2, and the assist is derived from the help message in >=9.4" theTest+ ([ ignoreForGhcVersions [GHC94, GHC96] "Extension not present <9.2, and the assist is derived from the help message in >=9.4" theTest ]+ ++ [+ theTestIndirect qualifiedGhcRecords polymorphicType+ |+ qualifiedGhcRecords <- [False, True]+ , polymorphicType <- [False, True]+ ]) ] where theTest = testSessionWithExtraFiles "hover" def $ \dir -> do@@ -1871,7 +1883,145 @@ contentAfterAction <- documentContents doc liftIO $ after @=? contentAfterAction + theTestIndirect qualifiedGhcRecords polymorphicType = testGroup+ ((if qualifiedGhcRecords then "qualified-" else "unqualified-")+ <> ("HasField " :: String)+ <>+ (if polymorphicType then "polymorphic-" else "monomorphic-")+ <> "type ")+ . (\x -> [x]) $ testSessionWithExtraFiles "hover" def $ \dir -> do+ -- Hopefully enable project indexing?+ configureCheckProject True + let+ before = T.unlines ["{-# LANGUAGE OverloadedRecordDot #-}", "module A where", if qualifiedGhcRecords then "" else "import GHC.Records", "import C (bar)", "spam = bar.foo"]+ after = T.unlines ["{-# LANGUAGE OverloadedRecordDot #-}", "module A where", if qualifiedGhcRecords then "" else "import GHC.Records", "import C (bar)", "import B (Foo(..))", "spam = bar.foo"]+ cradle = "cradle: {direct: {arguments: [-hide-all-packages, -package, base, -package, text, -package-env, -, A, B, C]}}"+ liftIO $ writeFileUTF8 (dir </> "hie.yaml") cradle+ liftIO $ writeFileUTF8 (dir </> "B.hs") $ unlines ["module B where", if polymorphicType then "data Foo x = Foo { foo :: x }" else "data Foo = Foo { foo :: Int }"]+ liftIO $ writeFileUTF8 (dir </> "C.hs") $ unlines ["module C where", "import B", "bar = Foo 10" ]+ doc <- createDoc "Test.hs" "haskell" before+ waitForProgressDone+ _ <- waitForDiagnostics+ let defLine = 4+ range = Range (Position defLine 0) (Position defLine maxBound)+ actions <- getCodeActions doc range+ action <- pickActionWithTitle "import B (Foo(..))" actions+ executeCodeAction action+ contentAfterAction <- documentContents doc+ liftIO $ after @=? contentAfterAction++suggestAddRecordFieldUpdateImportTests :: TestTree+suggestAddRecordFieldUpdateImportTests = testGroup "suggest imports of record fields in update"+ [ testGroup "implicit import of type" [theTest ] ]+ where+ theTest = testSessionWithExtraFiles "hover" def $ \dir -> do+ configureCheckProject True++ let+ before = T.unlines ["module C where", "import B", "biz = bar { foo = 100 }"]+ after = T.unlines ["module C where", "import B", "import A (Foo(..))", "biz = bar { foo = 100 }"]+ cradle = "cradle: {direct: {arguments: [-hide-all-packages, -package, base, -package, text, -package-env, -, A, B, C]}}"+ liftIO $ writeFileUTF8 (dir </> "hie.yaml") cradle+ liftIO $ writeFileUTF8 (dir </> "A.hs") $ unlines ["module A where", "data Foo = Foo { foo :: Int }"]+ liftIO $ writeFileUTF8 (dir </> "B.hs") $ unlines ["module B where", "import A", "bar = Foo 10" ]+ doc <- createDoc "Test.hs" "haskell" before+ waitForProgressDone+ diags <- waitForDiagnostics+ liftIO $ print diags+ let defLine = 2+ range = Range (Position defLine 0) (Position defLine maxBound)+ actions <- getCodeActions doc range+ liftIO $ print actions+ action <- pickActionWithTitle "import A (Foo(..))" actions+ executeCodeAction action+ contentAfterAction <- documentContents doc+ liftIO $ after @=? contentAfterAction++extractNotInScopeNameTests :: TestTree+extractNotInScopeNameTests =+ testGroup "extractNotInScopeName" [+ testGroup "record field" [+ testCase ">=ghc 910" $ Refactor.extractNotInScopeName "Not in scope: ‘foo’" @=? Just (NotInScopeThing "foo"),+ testCase "<ghc 910" $ Refactor.extractNotInScopeName "Not in scope: record field ‘foo’" @=? Just (NotInScopeThing "foo")+ ],+ testGroup "HasField" [+ testGroup "unqualified" [+ testGroup "nice ticks" [+ testCase "Simple type" $ Refactor.extractNotInScopeName "No instance for ‘HasField \"baz\" Cheval Bool’" @=? Just (NotInScopeThing "Cheval"),+ testCase "Parametric type" $ Refactor.extractNotInScopeName "No instance for ‘HasField \"bar\" (Hibou Int) a0’" @=? Just (NotInScopeThing "Hibou"),+ testCase "Parametric type" $ Refactor.extractNotInScopeName "No instance for ‘HasField \"foo\" (Tortue Int) Int’" @=? Just (NotInScopeThing "Tortue")+ ],+ testGroup "parenthesis" [+ testCase "Simple type" $ Refactor.extractNotInScopeName "No instance for ‘HasField \"blup\" Calamar Bool’" @=? Just (NotInScopeThing "Calamar"),+ testCase "Parametric type" $ Refactor.extractNotInScopeName "No instance for ‘HasField \"biz\" (Ornithorink Int) a0’" @=? Just (NotInScopeThing "Ornithorink"),+ testCase "Parametric type" $ Refactor.extractNotInScopeName "No instance for ‘HasField \"blork\" (Salamandre Int) Int’" @=? Just (NotInScopeThing "Salamandre")+ ]+ ],+ testGroup "qualified" [+ testGroup "nice ticks" [+ testCase "Simple type" $ Refactor.extractNotInScopeName "No instance for ‘GHC.HasField \"baz\" Cheval Bool’" @=? Just (NotInScopeThing "Cheval"),+ testCase "Parametric type" $ Refactor.extractNotInScopeName "No instance for ‘Record.HasField \"bar\" (Hibou Int) a0’" @=? Just (NotInScopeThing "Hibou"),+ testCase "Parametric type" $ Refactor.extractNotInScopeName "No instance for ‘Youpi.HasField \"foo\" (Tortue Int) Int’" @=? Just (NotInScopeThing "Tortue")+ ],+ testGroup "parenthesis" [+ testCase "Simple type" $ Refactor.extractNotInScopeName "No instance for ‘GHC.Tortue.HasField \"blup\" Calamar Bool’" @=? Just (NotInScopeThing "Calamar"),+ testCase "Parametric type" $ Refactor.extractNotInScopeName "No instance for ‘Youpi.Salamandre.HasField \"biz\" (Ornithorink Int) a0’" @=? Just (NotInScopeThing "Ornithorink"),+ testCase "Parametric type" $ Refactor.extractNotInScopeName "No instance for ‘Foo.Bar.HasField \"blork\" (Salamandre Int) Int’" @=? Just (NotInScopeThing "Salamandre")+ ]+ ]+ ]+ ]+suggestAddCoerceMissingConstructorImportTests :: TestTree+suggestAddCoerceMissingConstructorImportTests = testGroup "suggest imports of newtype constructor when using coerce"+ [ testGroup "The newtype constructor is suggested when a matching representation error"+ [ theTest+ ]+ ]+ where+ theTest = testSessionWithExtraFiles "hover" def $ \dir -> do+ configureCheckProject False+ let before = T.unlines ["module A where", "import Data.Coerce (coerce)", "import Data.Semigroup (Sum)", "bar = coerce (10 :: Int) :: Sum Int"]+ after = T.unlines ["module A where", "import Data.Coerce (coerce)", "import Data.Semigroup (Sum)", "import Data.Semigroup (Sum(..))", "bar = coerce (10 :: Int) :: Sum Int"]+ cradle = "cradle: {direct: {arguments: [-hide-all-packages, -package, base, -package, text, -package-env, -, A]}}"+ liftIO $ writeFileUTF8 (dir </> "hie.yaml") cradle+ doc <- createDoc "Test.hs" "haskell" before+ waitForProgressDone+ _ <- waitForDiagnostics+ let defLine = 3+ range = Range (Position defLine 0) (Position defLine maxBound)+ actions <- getCodeActions doc range+ action <- pickActionWithTitle "import Data.Semigroup (Sum(..))" actions+ executeCodeAction action+ contentAfterAction <- documentContents doc+ liftIO $ after @=? contentAfterAction++suggestAddGenericMissingConstructorImportTests :: TestTree+suggestAddGenericMissingConstructorImportTests = testGroup "suggest imports of type constructors when using generic deriving"+ [ testGroup "The type constructors are suggested when not in scope"+ [ theTest+ ]+ ]+ where+ theTest = testSessionWithExtraFiles "hover" def $ \dir -> do+ configureCheckProject False+ let+ before = T.unlines ["module A where", "import GHC.Generics", "import Data.Semigroup (Sum)", "deriving instance Generic (Sum Int)"]+ after = T.unlines ["module A where", "import GHC.Generics", "import Data.Semigroup (Sum)", "import Data.Semigroup (Sum(..))", "deriving instance Generic (Sum Int)"]+ cradle = "cradle: {direct: {arguments: [-hide-all-packages, -package, base, -package, text, -package-env, -, A]}}"+ liftIO $ writeFileUTF8 (dir </> "hie.yaml") cradle+ doc <- createDoc "Test.hs" "haskell" before+ waitForProgressDone+ _ <- waitForDiagnostics+ let defLine = 3+ range = Range (Position defLine 0) (Position defLine maxBound)+ actions <- getCodeActions doc range+ action <- pickActionWithTitle "import Data.Semigroup (Sum(..))" actions+ executeCodeAction action+ contentAfterAction <- documentContents doc+ liftIO $ after @=? contentAfterAction++ suggestImportDisambiguationTests :: TestTree suggestImportDisambiguationTests = testGroup "suggest import disambiguation actions" [ testGroup "Hiding strategy works"@@ -2538,14 +2688,14 @@ [ (DiagnosticSeverity_Warning, (6, 8), "Defaulting the following constraint", Nothing) , (DiagnosticSeverity_Warning, (6, 16), "Defaulting the following constraint", Nothing) ])- "Add type annotation ‘String’ to ‘\"debug\"’"+ ("Add type annotation ‘" <> stringLit <> "’ to ‘\"debug\"’") [ "{-# OPTIONS_GHC -Wtype-defaults #-}" , "{-# LANGUAGE OverloadedStrings #-}" , "module A (f) where" , "" , "import Debug.Trace" , ""- , "f = seq (\"debug\" :: String) traceShow \"debug\""+ , "f = seq (\"debug\" :: "<> stringLit <> ") traceShow \"debug\"" ] , testSession "add default type to satisfy two constraints" $ testFor@@ -2560,14 +2710,14 @@ (if ghcVersion >= GHC94 then [ (DiagnosticSeverity_Warning, (6, 6), "Defaulting the type variable", Nothing) ] else [ (DiagnosticSeverity_Warning, (6, 6), "Defaulting the following constraint", Nothing) ])- "Add type annotation ‘String’ to ‘\"debug\"’"+ ("Add type annotation ‘" <> stringLit <> "’ to ‘\"debug\"’") [ "{-# OPTIONS_GHC -Wtype-defaults #-}" , "{-# LANGUAGE OverloadedStrings #-}" , "module A (f) where" , "" , "import Debug.Trace" , ""- , "f a = traceShow (\"debug\" :: String) a"+ , "f a = traceShow (\"debug\" :: " <> stringLit <> ") a" ] , testSession "add default type to satisfy two constraints with duplicate literals" $ testFor@@ -2582,17 +2732,18 @@ (if ghcVersion >= GHC94 then [ (DiagnosticSeverity_Warning, (6, 54), "Defaulting the type variable", Nothing) ] else [ (DiagnosticSeverity_Warning, (6, 54), "Defaulting the following constraint", Nothing) ])- "Add type annotation ‘String’ to ‘\"debug\"’"+ ("Add type annotation ‘"<> stringLit <>"’ to ‘\"debug\"’") [ "{-# OPTIONS_GHC -Wtype-defaults #-}" , "{-# LANGUAGE OverloadedStrings #-}" , "module A (f) where" , "" , "import Debug.Trace" , ""- , "f = seq (\"debug\" :: [Char]) (seq (\"debug\" :: [Char]) (traceShow (\"debug\" :: String)))"+ , "f = seq (\"debug\" :: [Char]) (seq (\"debug\" :: [Char]) (traceShow (\"debug\" :: "<> stringLit <> ")))" ] ] where+ stringLit = if ghcVersion >= GHC912 then "[Char]" else "String" testFor sourceLines diag expectedTitle expectedLines = do docId <- createDoc "A.hs" "haskell" $ T.unlines sourceLines expectDiagnostics [ ("A.hs", diag) ]@@ -3208,6 +3359,10 @@ executeCodeAction chosenAction modifiedCode <- documentContents doc liftIO $ expectedCode @=? modifiedCode+ issue806 = if ghcVersion >= GHC912 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 in testGroup "add signature" [ "abc = True" >:: "abc :: Bool"@@ -3216,7 +3371,7 @@ , "(!!!) a b = a > b" >:: "(!!!) :: Ord a => a -> a -> Bool" , "a >>>> b = a + b" >:: "(>>>>) :: Num a => a -> a -> a" , "a `haha` b = a b" >:: "haha :: (t1 -> t2) -> t1 -> t2"- , "hello = print" >:: "hello :: GHC.Types.Any -> IO ()" -- Documents current behavior outlined in #806+ , issue806 , "pattern Some a = Just a" >:: "pattern Some :: a -> Maybe a" , "pattern Some a <- Just a" >:: "pattern Some :: a -> Maybe a" , "pattern Some a <- Just a\n where Some a = Just a" >:: "pattern Some :: a -> Maybe a"@@ -3893,8 +4048,7 @@ -- Which we need to do on macOS since the $TMPDIR can be in @/private/var@ or -- @/var@ withTempDir :: (FilePath -> IO a) -> IO a-withTempDir f = System.IO.Extra.withTempDir $ \dir ->- canonicalizePath dir >>= f+withTempDir f = System.IO.Extra.withTempDir $ (canonicalizePath >=> f) brokenForGHC94 :: String -> TestTree -> TestTree brokenForGHC94 = knownBrokenForGhcVersions [GHC94]
plugins/hls-refactor-plugin/test/Test/AddArgument.hs view
@@ -35,7 +35,7 @@ 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] "In GHC 9.10 end-of-line comment annotation is in different place" $+ knownBrokenForGhcVersions [GHC910, GHC912] "In GHC 9.10 and 9.12 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),
plugins/hls-stylish-haskell-plugin/src/Ide/Plugin/StylishHaskell.hs view
@@ -79,10 +79,15 @@ -- If no such file has been found, return default config. loadConfigFrom :: FilePath -> IO Config loadConfigFrom file = do+#if MIN_VERSION_stylish_haskell(0,15,0)+ let configSearchStrategy = SearchFromDirectory (takeDirectory file)+ config <- loadConfig (makeVerbose False) configSearchStrategy+#else currDir <- getCurrentDirectory setCurrentDirectory (takeDirectory file) config <- loadConfig (makeVerbose False) Nothing setCurrentDirectory currDir+#endif pure config -- | Run stylish-haskell on the given text with the given configuration.
+ test/testdata/hieBiosError/hie.yaml view
− test/testdata/hieBiosMainIs/dist-newstyle/cache/plan.json
@@ -1,1 +0,0 @@-{"cabal-version":"3.12.1.0","cabal-lib-version":"3.12.1.0","compiler-id":"ghc-9.12.2","os":"linux","arch":"x86_64","install-plan":[{"type":"pre-existing","id":"base-4.21.0.0-b7a5","pkg-name":"base","pkg-version":"4.21.0.0","depends":["ghc-internal-9.1202.0-7700","ghc-prim-0.13.0-00de"]},{"type":"pre-existing","id":"ghc-bignum-1.3-4dbb","pkg-name":"ghc-bignum","pkg-version":"1.3","depends":["ghc-prim-0.13.0-00de"]},{"type":"pre-existing","id":"ghc-internal-9.1202.0-7700","pkg-name":"ghc-internal","pkg-version":"9.1202.0","depends":["ghc-bignum-1.3-4dbb","ghc-prim-0.13.0-00de","rts-1.0.2"]},{"type":"pre-existing","id":"ghc-prim-0.13.0-00de","pkg-name":"ghc-prim","pkg-version":"0.13.0","depends":["rts-1.0.2"]},{"type":"configured","id":"hieBiosMainIs-0.1.0.0-inplace-hieBiosMainIs","pkg-name":"hieBiosMainIs","pkg-version":"0.1.0.0","flags":{},"style":"local","pkg-src":{"type":"local","path":"/home/hugin/Documents/haskell/hls/test/testdata/hieBiosMainIs/."},"dist-dir":"/home/hugin/Documents/haskell/hls/test/testdata/hieBiosMainIs/dist-newstyle/build/x86_64-linux/ghc-9.12.2/hieBiosMainIs-0.1.0.0/x/hieBiosMainIs","build-info":"/home/hugin/Documents/haskell/hls/test/testdata/hieBiosMainIs/dist-newstyle/build/x86_64-linux/ghc-9.12.2/hieBiosMainIs-0.1.0.0/x/hieBiosMainIs/build-info.json","depends":["base-4.21.0.0-b7a5"],"exe-depends":[],"component-name":"exe:hieBiosMainIs","bin-file":"/home/hugin/Documents/haskell/hls/test/testdata/hieBiosMainIs/dist-newstyle/build/x86_64-linux/ghc-9.12.2/hieBiosMainIs-0.1.0.0/x/hieBiosMainIs/build/hieBiosMainIs/hieBiosMainIs"},{"type":"pre-existing","id":"rts-1.0.2","pkg-name":"rts","pkg-version":"1.0.2","depends":[]}]}
− test/testdata/missingModuleTest/missingModule/dist-newstyle/cache/plan.json
@@ -1,1 +0,0 @@-{"cabal-version":"3.12.1.0","cabal-lib-version":"3.12.1.0","compiler-id":"ghc-9.12.2","os":"linux","arch":"x86_64","install-plan":[{"type":"pre-existing","id":"base-4.21.0.0-b7a5","pkg-name":"base","pkg-version":"4.21.0.0","depends":["ghc-internal-9.1202.0-7700","ghc-prim-0.13.0-00de"]},{"type":"pre-existing","id":"ghc-bignum-1.3-4dbb","pkg-name":"ghc-bignum","pkg-version":"1.3","depends":["ghc-prim-0.13.0-00de"]},{"type":"pre-existing","id":"ghc-internal-9.1202.0-7700","pkg-name":"ghc-internal","pkg-version":"9.1202.0","depends":["ghc-bignum-1.3-4dbb","ghc-prim-0.13.0-00de","rts-1.0.2"]},{"type":"pre-existing","id":"ghc-prim-0.13.0-00de","pkg-name":"ghc-prim","pkg-version":"0.13.0","depends":["rts-1.0.2"]},{"type":"configured","id":"missingModule-0.1.0.0-inplace","pkg-name":"missingModule","pkg-version":"0.1.0.0","flags":{},"style":"local","pkg-src":{"type":"local","path":"/home/hugin/Documents/haskell/hls/test/testdata/missingModuleTest/missingModule/."},"dist-dir":"/home/hugin/Documents/haskell/hls/test/testdata/missingModuleTest/missingModule/dist-newstyle/build/x86_64-linux/ghc-9.12.2/missingModule-0.1.0.0","build-info":"/home/hugin/Documents/haskell/hls/test/testdata/missingModuleTest/missingModule/dist-newstyle/build/x86_64-linux/ghc-9.12.2/missingModule-0.1.0.0/build-info.json","depends":["base-4.21.0.0-b7a5"],"exe-depends":[],"component-name":"lib"},{"type":"pre-existing","id":"rts-1.0.2","pkg-name":"rts","pkg-version":"1.0.2","depends":[]}]}
+ test/testdata/missingModuleTest/noPrefixMatch/dist-newstyle/cache/plan.json view
@@ -0,0 +1,1 @@+{"cabal-version":"3.10.1.0","cabal-lib-version":"3.10.1.0","compiler-id":"ghc-9.6.3","os":"linux","arch":"x86_64","install-plan":[{"type":"pre-existing","id":"base-4.18.1.0","pkg-name":"base","pkg-version":"4.18.1.0","depends":["ghc-bignum-1.3","ghc-prim-0.10.0","rts-1.0.2"]},{"type":"pre-existing","id":"ghc-bignum-1.3","pkg-name":"ghc-bignum","pkg-version":"1.3","depends":["ghc-prim-0.10.0"]},{"type":"pre-existing","id":"ghc-prim-0.10.0","pkg-name":"ghc-prim","pkg-version":"0.10.0","depends":["rts-1.0.2"]},{"type":"configured","id":"noPrefixMatch-0.1.0.0-inplace-testExe","pkg-name":"noPrefixMatch","pkg-version":"0.1.0.0","flags":{},"style":"local","pkg-src":{"type":"local","path":"/home/zubin/haskell-language-server-dist/test/testdata/missingModuleTest/noPrefixMatch/."},"dist-dir":"/home/zubin/haskell-language-server-dist/test/testdata/missingModuleTest/noPrefixMatch/dist-newstyle/build/x86_64-linux/ghc-9.6.3/noPrefixMatch-0.1.0.0/x/testExe","build-info":"/home/zubin/haskell-language-server-dist/test/testdata/missingModuleTest/noPrefixMatch/dist-newstyle/build/x86_64-linux/ghc-9.6.3/noPrefixMatch-0.1.0.0/x/testExe/build-info.json","depends":["base-4.18.1.0"],"exe-depends":[],"component-name":"exe:testExe","bin-file":"/home/zubin/haskell-language-server-dist/test/testdata/missingModuleTest/noPrefixMatch/dist-newstyle/build/x86_64-linux/ghc-9.6.3/noPrefixMatch-0.1.0.0/x/testExe/build/testExe/testExe"},{"type":"pre-existing","id":"rts-1.0.2","pkg-name":"rts","pkg-version":"1.0.2","depends":[]}]}
+ test/testdata/schema/ghc910/default-config.golden.json view
@@ -0,0 +1,151 @@+{+ "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+ },+ "fourmolu": {+ "config": {+ "external": false,+ "path": "fourmolu"+ }+ },+ "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+ },+ "ormolu": {+ "config": {+ "external": false+ }+ },+ "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+ },+ "stan": {+ "globalOn": false+ }+ },+ "sessionLoading": "singleComponent"+}
+ test/testdata/schema/ghc910/vscode-extension-schema.golden.json view
@@ -0,0 +1,1028 @@+{+ "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.fourmolu.config.external": {+ "default": false,+ "markdownDescription": "Call out to an external \"fourmolu\" executable, rather than using the bundled library.",+ "scope": "resource",+ "type": "boolean"+ },+ "haskell.plugin.fourmolu.config.path": {+ "default": "fourmolu",+ "markdownDescription": "Set path to executable (for \"external\" mode).",+ "scope": "resource",+ "type": "string"+ },+ "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.ormolu.config.external": {+ "default": false,+ "markdownDescription": "Call out to an external \"ormolu\" executable, rather than using the bundled library",+ "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.stan.globalOn": {+ "default": false,+ "description": "Enables stan plugin",+ "scope": "resource",+ "type": "boolean"+ }+}
test/testdata/schema/ghc912/default-config.golden.json view
@@ -20,6 +20,11 @@ "path": "cabal-fmt" } },+ "cabal-gild": {+ "config": {+ "path": "cabal-gild"+ }+ }, "cabalHaskellIntegration": { "globalOn": true },@@ -34,11 +39,12 @@ "codeLensOn": true }, "eval": {+ "codeActionsOn": true,+ "codeLensOn": true, "config": { "diff": true, "exception": false- },- "globalOn": true+ } }, "explicit-fields": { "codeActionsOn": true,@@ -47,6 +53,27 @@ "explicit-fixity": { "globalOn": true },+ "fourmolu": {+ "config": {+ "external": false,+ "path": "fourmolu"+ }+ },+ "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,@@ -64,6 +91,13 @@ }, "globalOn": true },+ "hlint": {+ "codeActionsOn": true,+ "config": {+ "flags": []+ },+ "diagnosticsOn": true+ }, "importLens": { "codeActionsOn": true, "codeLensOn": true,@@ -72,6 +106,11 @@ "moduleName": { "globalOn": true },+ "ormolu": {+ "config": {+ "external": false+ }+ }, "overloaded-record-dot": { "globalOn": true },@@ -85,6 +124,12 @@ "globalOn": true }, "qualifyImportedNames": {+ "globalOn": true+ },+ "rename": {+ "config": {+ "crossModule": false+ }, "globalOn": true }, "semanticTokens": {
test/testdata/schema/ghc912/vscode-extension-schema.golden.json view
@@ -11,6 +11,12 @@ "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",@@ -71,6 +77,18 @@ "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",@@ -83,12 +101,6 @@ "scope": "resource", "type": "boolean" },- "haskell.plugin.eval.globalOn": {- "default": true,- "description": "Enables eval plugin",- "scope": "resource",- "type": "boolean"- }, "haskell.plugin.explicit-fields.codeActionsOn": { "default": true, "description": "Enables explicit-fields code actions",@@ -107,6 +119,48 @@ "scope": "resource", "type": "boolean" },+ "haskell.plugin.fourmolu.config.external": {+ "default": false,+ "markdownDescription": "Call out to an external \"fourmolu\" executable, rather than using the bundled library.",+ "scope": "resource",+ "type": "boolean"+ },+ "haskell.plugin.fourmolu.config.path": {+ "default": "fourmolu",+ "markdownDescription": "Set path to executable (for \"external\" mode).",+ "scope": "resource",+ "type": "string"+ },+ "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",@@ -159,6 +213,24 @@ "scope": "resource", "type": "boolean" },+ "haskell.plugin.hlint.codeActionsOn": {+ "default": true,+ "description": "Enables hlint code actions",+ "scope": "resource",+ "type": "boolean"+ },+ "haskell.plugin.hlint.config.flags": {+ "default": [],+ "markdownDescription": "Flags used by hlint",+ "scope": "resource",+ "type": "array"+ },+ "haskell.plugin.hlint.diagnosticsOn": {+ "default": true,+ "description": "Enables hlint diagnostics",+ "scope": "resource",+ "type": "boolean"+ }, "haskell.plugin.importLens.codeActionsOn": { "default": true, "description": "Enables importLens code actions",@@ -183,6 +255,12 @@ "scope": "resource", "type": "boolean" },+ "haskell.plugin.ormolu.config.external": {+ "default": false,+ "markdownDescription": "Call out to an external \"ormolu\" executable, rather than using the bundled library",+ "scope": "resource",+ "type": "boolean"+ }, "haskell.plugin.overloaded-record-dot.globalOn": { "default": true, "description": "Enables overloaded-record-dot plugin",@@ -210,6 +288,18 @@ "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" },
test/testdata/schema/ghc94/default-config.golden.json view
@@ -39,11 +39,12 @@ "codeLensOn": true }, "eval": {+ "codeActionsOn": true,+ "codeLensOn": true, "config": { "diff": true, "exception": false- },- "globalOn": true+ } }, "explicit-fields": { "codeActionsOn": true,
test/testdata/schema/ghc94/vscode-extension-schema.golden.json view
@@ -77,6 +77,18 @@ "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",@@ -86,12 +98,6 @@ "haskell.plugin.eval.config.exception": { "default": false, "markdownDescription": "Enable marking exceptions with `*** Exception:` similarly to doctest and GHCi.",- "scope": "resource",- "type": "boolean"- },- "haskell.plugin.eval.globalOn": {- "default": true,- "description": "Enables eval plugin", "scope": "resource", "type": "boolean" },
test/testdata/schema/ghc96/default-config.golden.json view
@@ -39,11 +39,12 @@ "codeLensOn": true }, "eval": {+ "codeActionsOn": true,+ "codeLensOn": true, "config": { "diff": true, "exception": false- },- "globalOn": true+ } }, "explicit-fields": { "codeActionsOn": true,
test/testdata/schema/ghc96/vscode-extension-schema.golden.json view
@@ -77,6 +77,18 @@ "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",@@ -86,12 +98,6 @@ "haskell.plugin.eval.config.exception": { "default": false, "markdownDescription": "Enable marking exceptions with `*** Exception:` similarly to doctest and GHCi.",- "scope": "resource",- "type": "boolean"- },- "haskell.plugin.eval.globalOn": {- "default": true,- "description": "Enables eval plugin", "scope": "resource", "type": "boolean" },
test/testdata/schema/ghc98/default-config.golden.json view
@@ -39,11 +39,12 @@ "codeLensOn": true }, "eval": {+ "codeActionsOn": true,+ "codeLensOn": true, "config": { "diff": true, "exception": false- },- "globalOn": true+ } }, "explicit-fields": { "codeActionsOn": true,
test/testdata/schema/ghc98/vscode-extension-schema.golden.json view
@@ -77,6 +77,18 @@ "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",@@ -86,12 +98,6 @@ "haskell.plugin.eval.config.exception": { "default": false, "markdownDescription": "Enable marking exceptions with `*** Exception:` similarly to doctest and GHCi.",- "scope": "resource",- "type": "boolean"- },- "haskell.plugin.eval.globalOn": {- "default": true,- "description": "Enables eval plugin", "scope": "resource", "type": "boolean" },
+ test/testdata/wErrorTest/dist-newstyle/cache/plan.json view
@@ -0,0 +1,1 @@+{"cabal-version":"3.8.1.0","cabal-lib-version":"3.8.1.0","compiler-id":"ghc-9.2.4","os":"linux","arch":"x86_64","install-plan":[{"type":"pre-existing","id":"base-4.16.3.0","pkg-name":"base","pkg-version":"4.16.3.0","depends":["ghc-bignum-1.2","ghc-prim-0.8.0","rts"]},{"type":"pre-existing","id":"ghc-bignum-1.2","pkg-name":"ghc-bignum","pkg-version":"1.2","depends":["ghc-prim-0.8.0"]},{"type":"pre-existing","id":"ghc-prim-0.8.0","pkg-name":"ghc-prim","pkg-version":"0.8.0","depends":["rts"]},{"type":"pre-existing","id":"rts","pkg-name":"rts","pkg-version":"1.0.2","depends":[]},{"type":"configured","id":"test-0.1.0.0-inplace","pkg-name":"test","pkg-version":"0.1.0.0","flags":{},"style":"local","pkg-src":{"type":"local","path":"/home/zubin/haskell-language-server-dist/test/testdata/wErrorTest/."},"dist-dir":"/home/zubin/haskell-language-server-dist/test/testdata/wErrorTest/dist-newstyle/build/x86_64-linux/ghc-9.2.4/test-0.1.0.0","build-info":"/home/zubin/haskell-language-server-dist/test/testdata/wErrorTest/dist-newstyle/build/x86_64-linux/ghc-9.2.4/test-0.1.0.0/build-info.json","depends":["base-4.16.3.0"],"exe-depends":[],"component-name":"lib"}]}