From 6f600290bb486aecacb9f9850c2c82f58a94f3cd Mon Sep 17 00:00:00 2001 From: Zubin Duggal Date: Mon, 11 Dec 2023 17:51:12 +0530 Subject: [PATCH 1/9] Exactprint plugins for 9.8 --- ghcide/src/Development/IDE/GHC/Compat/Core.hs | 5 ++ haskell-language-server.cabal | 12 ++-- .../hls-class-plugin/hls-class-plugin.cabal | 9 --- .../src/Ide/Plugin/Class/Types.hs | 7 ++- plugins/hls-gadt-plugin/hls-gadt-plugin.cabal | 9 --- plugins/hls-gadt-plugin/test/Main.hs | 8 +-- .../hls-refactor-plugin.cabal | 9 --- .../src/Development/IDE/GHC/Dump.hs | 4 ++ .../src/Development/IDE/Plugin/CodeAction.hs | 55 +++++++++++++------ .../IDE/Plugin/CodeAction/ExactPrint.hs | 32 ++++++++++- plugins/hls-refactor-plugin/test/Main.hs | 8 +++ .../hls-rename-plugin/hls-rename-plugin.cabal | 9 --- .../hls-retrie-plugin/hls-retrie-plugin.cabal | 9 --- .../hls-splice-plugin/hls-splice-plugin.cabal | 9 --- 14 files changed, 100 insertions(+), 85 deletions(-) diff --git a/ghcide/src/Development/IDE/GHC/Compat/Core.hs b/ghcide/src/Development/IDE/GHC/Compat/Core.hs index caee9d5685..9f35fb6bf6 100644 --- a/ghcide/src/Development/IDE/GHC/Compat/Core.hs +++ b/ghcide/src/Development/IDE/GHC/Compat/Core.hs @@ -408,6 +408,7 @@ module Development.IDE.GHC.Compat.Core ( #endif groupOrigin, isVisibleFunArg, + lookupGlobalRdrEnv, ) where import qualified GHC @@ -825,3 +826,7 @@ mkSimpleTarget df fp = Target (TargetFile fp Nothing) True (homeUnitId_ df) Noth #else mkSimpleTarget _ fp = Target (TargetFile fp Nothing) True Nothing #endif + +#if MIN_VERSION_ghc(9,7,0) +lookupGlobalRdrEnv gre_env occ = lookupGRE gre_env (LookupOccName occ AllRelevantGREs) +#endif diff --git a/haskell-language-server.cabal b/haskell-language-server.cabal index 43ee12e74b..cd347c5dd1 100644 --- a/haskell-language-server.cabal +++ b/haskell-language-server.cabal @@ -217,7 +217,7 @@ common cabal cpp-options: -Dhls_cabal common class - if flag(class) && (impl(ghc < 9.8.0) || flag(ignore-plugins-ghc-bounds)) + if flag(class) build-depends: hls-class-plugin == 2.6.0.0 cpp-options: -Dhls_class @@ -237,12 +237,12 @@ common importLens cpp-options: -Dhls_importLens common rename - if flag(rename) && (impl(ghc < 9.8.0) || flag(ignore-plugins-ghc-bounds)) + if flag(rename) build-depends: hls-rename-plugin == 2.6.0.0 cpp-options: -Dhls_rename common retrie - if flag(retrie) && (impl(ghc < 9.8.0) || flag(ignore-plugins-ghc-bounds)) + if flag(retrie) build-depends: hls-retrie-plugin == 2.6.0.0 cpp-options: -Dhls_retrie @@ -267,7 +267,7 @@ common pragmas cpp-options: -Dhls_pragmas common splice - if flag(splice) && (impl(ghc < 9.8.0) || flag(ignore-plugins-ghc-bounds)) + if flag(splice) build-depends: hls-splice-plugin == 2.6.0.0 cpp-options: -Dhls_splice @@ -292,7 +292,7 @@ common changeTypeSignature cpp-options: -Dhls_changeTypeSignature common gadt - if flag(gadt) && (impl(ghc < 9.8.0) || flag(ignore-plugins-ghc-bounds)) + if flag(gadt) build-depends: hls-gadt-plugin == 2.6.0.0 cpp-options: -Dhls_gadt @@ -334,7 +334,7 @@ common stylishHaskell cpp-options: -Dhls_stylishHaskell common refactor - if flag(refactor) && (impl(ghc < 9.8.0) || flag(ignore-plugins-ghc-bounds)) + if flag(refactor) build-depends: hls-refactor-plugin == 2.6.0.0 cpp-options: -Dhls_refactor diff --git a/plugins/hls-class-plugin/hls-class-plugin.cabal b/plugins/hls-class-plugin/hls-class-plugin.cabal index 3ff633fd47..096d63cae5 100644 --- a/plugins/hls-class-plugin/hls-class-plugin.cabal +++ b/plugins/hls-class-plugin/hls-class-plugin.cabal @@ -29,11 +29,6 @@ common warnings library import: warnings - -- Plugins that need exactprint have not been updated for 9.8 yet - if impl(ghc >= 9.8) - buildable: False - else - buildable: True exposed-modules: Ide.Plugin.Class other-modules: Ide.Plugin.Class.CodeAction , Ide.Plugin.Class.CodeLens @@ -66,10 +61,6 @@ library test-suite tests import: warnings - if impl(ghc >= 9.8) - buildable: False - else - buildable: True type: exitcode-stdio-1.0 default-language: Haskell2010 hs-source-dirs: test diff --git a/plugins/hls-class-plugin/src/Ide/Plugin/Class/Types.hs b/plugins/hls-class-plugin/src/Ide/Plugin/Class/Types.hs index 49d92b564b..a3f0110544 100644 --- a/plugins/hls-class-plugin/src/Ide/Plugin/Class/Types.hs +++ b/plugins/hls-class-plugin/src/Ide/Plugin/Class/Types.hs @@ -5,6 +5,7 @@ {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE ViewPatterns #-} +{-# LANGUAGE CPP #-} module Ide.Plugin.Class.Types where @@ -207,7 +208,11 @@ getInstanceBindTypeSigsRule recorder = do (hscEnv -> hsc) <- useMT GhcSession nfp let binds = collectHsBindsBinders $ tcg_binds gblEnv (_, maybe [] catMaybes -> instanceBinds) <- liftIO $ - initTcWithGbl hsc gblEnv ghostSpan $ traverse bindToSig binds + initTcWithGbl hsc gblEnv ghostSpan +#if MIN_VERSION_ghc(9,7,0) + $ liftZonkM +#endif + $ traverse bindToSig binds pure $ InstanceBindTypeSigsResult instanceBinds where bindToSig id = do diff --git a/plugins/hls-gadt-plugin/hls-gadt-plugin.cabal b/plugins/hls-gadt-plugin/hls-gadt-plugin.cabal index b92142cbd7..1c2c915c5d 100644 --- a/plugins/hls-gadt-plugin/hls-gadt-plugin.cabal +++ b/plugins/hls-gadt-plugin/hls-gadt-plugin.cabal @@ -20,11 +20,6 @@ source-repository head location: https://github.com/haskell/haskell-language-server.git library - -- Plugins that need exactprint have not been updated for 9.8 yet - if impl(ghc >= 9.8) - buildable: False - else - buildable: True exposed-modules: Ide.Plugin.GADT other-modules: Ide.Plugin.GHC @@ -55,10 +50,6 @@ library default-extensions: DataKinds test-suite tests - if impl(ghc >= 9.8) - buildable: False - else - buildable: True type: exitcode-stdio-1.0 default-language: Haskell2010 hs-source-dirs: test diff --git a/plugins/hls-gadt-plugin/test/Main.hs b/plugins/hls-gadt-plugin/test/Main.hs index e92296eb0d..984f715633 100644 --- a/plugins/hls-gadt-plugin/test/Main.hs +++ b/plugins/hls-gadt-plugin/test/Main.hs @@ -35,13 +35,13 @@ tests = testGroup "GADT" , runTest "ConstructorContext" "ConstructorContext" 2 0 2 38 , runTest "Context" "Context" 2 0 4 41 , runTest "Pragma" "Pragma" 2 0 3 29 - , onlyWorkForGhcVersions (`elem`[GHC92, GHC94, GHC96]) "Single deriving has different output on ghc9.2+" $ + , onlyWorkForGhcVersions (`elem`[GHC92, GHC94, GHC96, GHC98]) "Single deriving has different output on ghc9.2+" $ runTest "SingleDerivingGHC92" "SingleDerivingGHC92" 2 0 3 14 - , knownBrokenForGhcVersions [GHC92,GHC94,GHC96] "Single deriving has different output on ghc9.2+" $ + , knownBrokenForGhcVersions [GHC92,GHC94,GHC96, GHC98] "Single deriving has different output on ghc9.2+" $ runTest "SingleDeriving" "SingleDeriving" 2 0 3 14 - , onlyWorkForGhcVersions (`elem`[GHC92, GHC94, GHC96]) "only ghc-9.2+ enabled GADTs pragma implicitly" $ + , onlyWorkForGhcVersions (`elem`[GHC92, GHC94, GHC96, GHC98]) "only ghc-9.2+ enabled GADTs pragma implicitly" $ gadtPragmaTest "ghc-9.2 don't need to insert GADTs pragma" False - , knownBrokenForGhcVersions [GHC92,GHC94,GHC96] "ghc-9.2 has enabled GADTs pragma implicitly" $ + , knownBrokenForGhcVersions [GHC92,GHC94,GHC96, GHC98] "ghc-9.2 has enabled GADTs pragma implicitly" $ gadtPragmaTest "insert pragma" True ] diff --git a/plugins/hls-refactor-plugin/hls-refactor-plugin.cabal b/plugins/hls-refactor-plugin/hls-refactor-plugin.cabal index 8656d80fb3..7678c360c1 100644 --- a/plugins/hls-refactor-plugin/hls-refactor-plugin.cabal +++ b/plugins/hls-refactor-plugin/hls-refactor-plugin.cabal @@ -26,11 +26,6 @@ common warnings library import: warnings - -- Plugins that need exactprint have not been updated for 9.8 yet - if impl(ghc >= 9.8) - buildable: False - else - buildable: True exposed-modules: Development.IDE.GHC.ExactPrint Development.IDE.GHC.Compat.ExactPrint Development.IDE.Plugin.CodeAction @@ -102,10 +97,6 @@ library test-suite tests import: warnings - if impl(ghc >= 9.8) - buildable: False - else - buildable: True type: exitcode-stdio-1.0 default-language: Haskell2010 hs-source-dirs: test diff --git a/plugins/hls-refactor-plugin/src/Development/IDE/GHC/Dump.hs b/plugins/hls-refactor-plugin/src/Development/IDE/GHC/Dump.hs index 1d74197445..b19b972feb 100644 --- a/plugins/hls-refactor-plugin/src/Development/IDE/GHC/Dump.hs +++ b/plugins/hls-refactor-plugin/src/Development/IDE/GHC/Dump.hs @@ -123,7 +123,11 @@ showAstDataHtml a0 = html $ sourceText :: SourceText -> SDoc sourceText NoSourceText = text "NoSourceText" +#if MIN_VERSION_ghc(9,7,0) + sourceText (SourceText src) = text "SourceText" <+> ftext src +#else sourceText (SourceText src) = text "SourceText" <+> text src +#endif epaAnchor :: EpaLocation -> SDoc #if MIN_VERSION_ghc(9,5,0) diff --git a/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction.hs b/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction.hs index 8479d5803d..32db0f3d51 100644 --- a/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction.hs +++ b/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction.hs @@ -938,7 +938,11 @@ suggestExtendImport :: ExportsMap -> ParsedSource -> Diagnostic -> [(T.Text, Cod suggestExtendImport exportsMap (L _ HsModule {hsmodImports}) Diagnostic{_range=_range,..} | Just [binding, mod, srcspan] <- matchRegexUnifySpaces _message +#if MIN_VERSION_ghc(9,7,0) + "Add ‘([^’]*)’ to the import list in the import of ‘([^’]*)’ *\\(at (.*)\\)." +#else "Perhaps you want to add ‘([^’]*)’ to the import list in the import of ‘([^’]*)’ *\\((.*)\\)." +#endif = suggestions hsmodImports binding mod srcspan | Just (binding, mod_srcspan) <- matchRegExMultipleImports _message @@ -965,9 +969,13 @@ suggestExtendImport exportsMap (L _ HsModule {hsmodImports}) Diagnostic{_range=_ | otherwise = [] lookupExportMap binding mod | let em = getExportsMap exportsMap +#if MIN_VERSION_ghc(9,7,0) + match = mconcat $ lookupOccEnv_AllNameSpaces em (mkVarOrDataOcc binding) +#else match1 = lookupOccEnv em (mkVarOrDataOcc binding) match2 = lookupOccEnv em (mkTypeOcc binding) , Just match <- match1 <> match2 +#endif -- Only for the situation that data constructor name is same as type constructor name, -- let ident with parent be in front of the one without. , sortedMatch <- sortBy (\ident1 ident2 -> parent ident2 `compare` parent ident1) (Set.toList match) @@ -1165,9 +1173,20 @@ suggestFixConstructorImport Diagnostic{_range=_range,..} -- import Data.Aeson.Types( Result( Success ) ) -- or -- import Data.Aeson.Types( Result(..) ) (lsp-ui) + -- + -- On 9.8+ + -- + -- In the import of ‘ModuleA’: + -- an item called ‘Constructor’ + -- is exported, but it is a data constructor of + -- ‘A’. | Just [constructor, typ] <- matchRegexUnifySpaces _message +#if MIN_VERSION_ghc(9,7,0) + "an item called ‘([^’]*)’ is exported, but it is a data constructor of ‘([^’]*)’" +#else "‘([^’]*)’ is a data constructor of ‘([^’]*)’ To import it use" +#endif = let fixedImport = typ <> "(" <> constructor <> ")" in [("Fix import of " <> fixedImport, TextEdit _range fixedImport)] | otherwise = [] @@ -1952,30 +1971,32 @@ regexSingleMatch msg regex = case matchRegexUnifySpaces msg regex of Just (h:_) -> Just h _ -> Nothing --- | Parses tuples like (‘Data.Map’, (app/ModuleB.hs:2:1-18)) and --- | return (Data.Map, app/ModuleB.hs:2:1-18) -regExPair :: (T.Text, T.Text) -> Maybe (T.Text, T.Text) -regExPair (modname, srcpair) = do - x <- regexSingleMatch modname "‘([^’]*)’" - y <- regexSingleMatch srcpair "\\((.*)\\)" - return (x, y) - -- | Process a list of (module_name, filename:src_span) values -- | Eg. [(Data.Map, app/ModuleB.hs:2:1-18), (Data.HashMap.Strict, app/ModuleB.hs:3:1-29)] regExImports :: T.Text -> Maybe [(T.Text, T.Text)] -regExImports msg = result - where - parts = T.words msg - isPrefix = not . T.isPrefixOf "(" - (mod, srcspan) = partition isPrefix parts - -- check we have matching pairs like (Data.Map, (app/src.hs:1:2-18)) - result = if length mod == length srcspan then - regExPair `traverse` zip mod srcspan - else Nothing +regExImports msg + | Just mods' <- allMatchRegex msg "‘([^’]*)’" + , Just srcspans' <- allMatchRegex msg +#if MIN_VERSION_ghc(9,7,0) + "\\(at ([^)]*)\\)" +#else + "\\(([^)]*)\\)" +#endif + , mods <- [mod | [_,mod] <- mods'] + , srcspans <- [srcspan | [_,srcspan] <- srcspans'] + -- check we have matching pairs like (Data.Map, (app/src.hs:1:2-18)) + , let result = if length mods == length srcspans then + Just (zip mods srcspans) else Nothing + = result + | otherwise = Nothing matchRegExMultipleImports :: T.Text -> Maybe (T.Text, [(T.Text, T.Text)]) matchRegExMultipleImports message = do +#if MIN_VERSION_ghc(9,7,0) + let pat = T.pack "Add ‘([^’]*)’ to one of these import lists: *(‘.*\\))$" +#else let pat = T.pack "Perhaps you want to add ‘([^’]*)’ to one of these import lists: *(‘.*\\))$" +#endif (binding, imports) <- case matchRegexUnifySpaces message pat of Just [x, xs] -> Just (x, xs) _ -> Nothing diff --git a/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction/ExactPrint.hs b/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction/ExactPrint.hs index 4c07354295..98a79c9b66 100644 --- a/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction/ExactPrint.hs +++ b/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction/ExactPrint.hs @@ -253,7 +253,13 @@ extendImportTopLevel thing (L l it@ImportDecl{..}) noExtField #endif rdr - x = reLocA $ L top $ IEVar noExtField lie + x = reLocA $ L top $ IEVar +#if MIN_VERSION_ghc(9,8,0) + Nothing -- no deprecated +#else + noExtField +#endif + lie if x `elem` lies then TransformT $ lift (Left $ thing <> " already imported") @@ -311,7 +317,13 @@ extendImportViaParent df parent child (L l it@ImportDecl{..}) noExtField #endif childRdr - x :: LIE GhcPs = L ll' $ IEThingWith (addAnns mempty [AddEpAnn AnnOpenP (EpaDelta (SameLine 1) []), AddEpAnn AnnCloseP def] emptyComments) absIE NoIEWildcard [childLIE] + x :: LIE GhcPs = L ll' $ IEThingWith +#if MIN_VERSION_ghc(9,7,0) + (Nothing, addAnns mempty [AddEpAnn AnnOpenP (EpaDelta (SameLine 1) []), AddEpAnn AnnCloseP def] emptyComments) +#else + (addAnns mempty [AddEpAnn AnnOpenP (EpaDelta (SameLine 1) []), AddEpAnn AnnCloseP def] emptyComments) +#endif + absIE NoIEWildcard [childLIE] #if MIN_VERSION_ghc(9,5,0) return $ L l it{ideclImportList = Just (hide, L l' $ reverse pre ++ [x] ++ xs)} @@ -329,7 +341,11 @@ extendImportViaParent df parent child (L l it@ImportDecl{..}) let it' = it{ideclHiding = Just (hide, lies)} #endif thing = IEThingWith newl twIE (IEWildcard 2) [] +#if MIN_VERSION_ghc(9,7,0) + newl = fmap (\ann -> ann ++ [(AddEpAnn AnnDotdot d0)]) <$> l''' +#else newl = (\ann -> ann ++ [(AddEpAnn AnnDotdot d0)]) <$> l''' +#endif lies = L l' $ reverse pre ++ [L l'' thing] ++ xs return $ L l it' | parent == unIEWrappedName ie @@ -382,7 +398,11 @@ extendImportViaParent df parent child (L l it@ImportDecl{..}) noExtField #endif childRdr +#if MIN_VERSION_ghc(9,5,0) + listAnn = (Nothing, epAnn srcParent [AddEpAnn AnnOpenP (epl 1), AddEpAnn AnnCloseP (epl 0)]) +#else listAnn = epAnn srcParent [AddEpAnn AnnOpenP (epl 1), AddEpAnn AnnCloseP (epl 0)] +#endif x :: LIE GhcPs = reLocA $ L l'' $ IEThingWith listAnn parentLIE NoIEWildcard [childLIE] lies' = addCommaInImportList (reverse pre) x @@ -486,7 +506,13 @@ extendHiding symbol (L l idecls) mlies df = do noExtField #endif rdr - x = reLocA $ L top $ IEVar noExtField lie + x = reLocA $ L top $ IEVar +#if MIN_VERSION_ghc(9,7,0) + Nothing +#else + noExtField +#endif + lie x <- pure $ if hasSibling then first addComma x else x lies <- pure $ over _head (`setEntryDP` SameLine 1) lies #if MIN_VERSION_ghc(9,5,0) diff --git a/plugins/hls-refactor-plugin/test/Main.hs b/plugins/hls-refactor-plugin/test/Main.hs index 4b0c41e423..ad5e6453da 100644 --- a/plugins/hls-refactor-plugin/test/Main.hs +++ b/plugins/hls-refactor-plugin/test/Main.hs @@ -701,7 +701,11 @@ typeWildCardActionTests = testGroup "type wildcard actions" [ "func :: _" , "func x y = x + y" ] +#if MIN_VERSION_ghc(9,7,0) + [ "func :: a -> a -> a" -- 9.8 has a different suggestion +#else [ "func :: Integer -> Integer -> Integer" +#endif , "func x y = x + y" ] , testUseTypeSignature "type in parentheses" @@ -729,7 +733,11 @@ typeWildCardActionTests = testGroup "type wildcard actions" [ "func::_" , "func x y = x + y" ] +#if MIN_VERSION_ghc(9,7,0) + [ "func::a -> a -> a" -- 9.8 has a different suggestion +#else [ "func::Integer -> Integer -> Integer" +#endif , "func x y = x + y" ] , testGroup "add parens if hole is part of bigger type" diff --git a/plugins/hls-rename-plugin/hls-rename-plugin.cabal b/plugins/hls-rename-plugin/hls-rename-plugin.cabal index 31f04f4566..f78f7f96b9 100644 --- a/plugins/hls-rename-plugin/hls-rename-plugin.cabal +++ b/plugins/hls-rename-plugin/hls-rename-plugin.cabal @@ -21,11 +21,6 @@ source-repository head location: https://github.com/haskell/haskell-language-server.git library - -- Plugins that need exactprint have not been updated for 9.8 yet - if impl(ghc >= 9.8) - buildable: False - else - buildable: True exposed-modules: Ide.Plugin.Rename hs-source-dirs: src build-depends: @@ -53,10 +48,6 @@ library default-language: Haskell2010 test-suite tests - if impl(ghc >= 9.8) - buildable: False - else - buildable: True type: exitcode-stdio-1.0 default-language: Haskell2010 hs-source-dirs: test diff --git a/plugins/hls-retrie-plugin/hls-retrie-plugin.cabal b/plugins/hls-retrie-plugin/hls-retrie-plugin.cabal index 1409cccd81..20f4794c44 100644 --- a/plugins/hls-retrie-plugin/hls-retrie-plugin.cabal +++ b/plugins/hls-retrie-plugin/hls-retrie-plugin.cabal @@ -21,11 +21,6 @@ source-repository head location: https://github.com/haskell/haskell-language-server.git library - -- Plugins that need exactprint have not been updated for 9.8 yet - if impl(ghc >= 9.8) - buildable: False - else - buildable: True exposed-modules: Ide.Plugin.Retrie hs-source-dirs: src build-depends: @@ -60,10 +55,6 @@ library ghc-options: -Wno-unticked-promoted-constructors test-suite tests - if impl(ghc >= 9.8) - buildable: False - else - buildable: True type: exitcode-stdio-1.0 default-language: Haskell2010 hs-source-dirs: test diff --git a/plugins/hls-splice-plugin/hls-splice-plugin.cabal b/plugins/hls-splice-plugin/hls-splice-plugin.cabal index 1405219435..571fa43103 100644 --- a/plugins/hls-splice-plugin/hls-splice-plugin.cabal +++ b/plugins/hls-splice-plugin/hls-splice-plugin.cabal @@ -27,11 +27,6 @@ source-repository head location: https://github.com/haskell/haskell-language-server.git library - -- Plugins that need exactprint have not been updated for 9.8 yet - if impl(ghc >= 9.8) - buildable: False - else - buildable: True exposed-modules: Ide.Plugin.Splice Ide.Plugin.Splice.Types @@ -66,10 +61,6 @@ library TypeOperators test-suite tests - if impl(ghc >= 9.8) - buildable: False - else - buildable: True type: exitcode-stdio-1.0 default-language: Haskell2010 hs-source-dirs: test From ba5c16873695f22e5368e1f49bbaa0a4b57a0b23 Mon Sep 17 00:00:00 2001 From: Zubin Duggal Date: Thu, 18 Jan 2024 14:53:14 +0530 Subject: [PATCH 2/9] Fix last test --- plugins/hls-refactor-plugin/hls-refactor-plugin.cabal | 2 ++ .../src/Development/IDE/Plugin/CodeAction.hs | 4 ++++ plugins/hls-refactor-plugin/test/Main.hs | 1 + 3 files changed, 7 insertions(+) diff --git a/plugins/hls-refactor-plugin/hls-refactor-plugin.cabal b/plugins/hls-refactor-plugin/hls-refactor-plugin.cabal index 7678c360c1..3c816d616a 100644 --- a/plugins/hls-refactor-plugin/hls-refactor-plugin.cabal +++ b/plugins/hls-refactor-plugin/hls-refactor-plugin.cabal @@ -110,6 +110,8 @@ test-suite tests , hls-test-utils == 2.6.0.0 , lens , lsp-types + -- for MIN_VERSION_ghc + , ghc , text , hls-plugin-api , parser-combinators diff --git a/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction.hs b/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction.hs index 32db0f3d51..48c33ea07b 100644 --- a/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction.hs +++ b/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction.hs @@ -1453,7 +1453,11 @@ suggestNewImport df packageExportsMap ps fileContents Diagnostic{..} *> extractQualifiedModuleNameFromMissingName (extractTextInRange _range fileContents) , Just (range, indent) <- newImportInsertRange ps fileContents , extendImportSuggestions <- matchRegexUnifySpaces msg +#if MIN_VERSION_ghc(9,7,0) + "Add ‘[^’]*’ to the import list in the import of ‘([^’]*)’" +#else "Perhaps you want to add ‘[^’]*’ to the import list in the import of ‘([^’]*)’" +#endif = let qis = qualifiedImportStyle df -- FIXME: we can use thingMissing once the support for GHC 9.4 is dropped. -- In what fllows, @missing@ is assumed to be qualified name. diff --git a/plugins/hls-refactor-plugin/test/Main.hs b/plugins/hls-refactor-plugin/test/Main.hs index ad5e6453da..55eecfd633 100644 --- a/plugins/hls-refactor-plugin/test/Main.hs +++ b/plugins/hls-refactor-plugin/test/Main.hs @@ -1673,6 +1673,7 @@ suggestImportTests :: TestTree suggestImportTests = testGroup "suggest import actions" [ testGroup "Dont want suggestion" [ -- extend import + -- We don't want to suggest a new import, but extend existing imports test False ["Data.List.NonEmpty ()"] "f = nonEmpty" [] "import Data.List.NonEmpty (nonEmpty)" -- data constructor , test False [] "f = First" [] "import Data.Monoid (First)" From d3232e1a97459eb980892d32625c646e72fe8279 Mon Sep 17 00:00:00 2001 From: Zubin Duggal Date: Thu, 18 Jan 2024 14:54:14 +0530 Subject: [PATCH 3/9] comments --- plugins/hls-gadt-plugin/test/Main.hs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/plugins/hls-gadt-plugin/test/Main.hs b/plugins/hls-gadt-plugin/test/Main.hs index 984f715633..d36abc6347 100644 --- a/plugins/hls-gadt-plugin/test/Main.hs +++ b/plugins/hls-gadt-plugin/test/Main.hs @@ -35,14 +35,8 @@ tests = testGroup "GADT" , runTest "ConstructorContext" "ConstructorContext" 2 0 2 38 , runTest "Context" "Context" 2 0 4 41 , runTest "Pragma" "Pragma" 2 0 3 29 - , onlyWorkForGhcVersions (`elem`[GHC92, GHC94, GHC96, GHC98]) "Single deriving has different output on ghc9.2+" $ - runTest "SingleDerivingGHC92" "SingleDerivingGHC92" 2 0 3 14 - , knownBrokenForGhcVersions [GHC92,GHC94,GHC96, GHC98] "Single deriving has different output on ghc9.2+" $ - runTest "SingleDeriving" "SingleDeriving" 2 0 3 14 - , onlyWorkForGhcVersions (`elem`[GHC92, GHC94, GHC96, GHC98]) "only ghc-9.2+ enabled GADTs pragma implicitly" $ - gadtPragmaTest "ghc-9.2 don't need to insert GADTs pragma" False - , knownBrokenForGhcVersions [GHC92,GHC94,GHC96, GHC98] "ghc-9.2 has enabled GADTs pragma implicitly" $ - gadtPragmaTest "insert pragma" True + , runTest "SingleDerivingGHC92" "SingleDerivingGHC92" 2 0 3 14 + , gadtPragmaTest "ghc-9.2 don't need to insert GADTs pragma" False ] gadtPragmaTest :: TestName -> Bool -> TestTree From 5ed34eda15c1c45e6dbcd1cda0943075fd0c1855 Mon Sep 17 00:00:00 2001 From: Zubin Duggal Date: Thu, 18 Jan 2024 15:02:34 +0530 Subject: [PATCH 4/9] fix borked cpp --- .../src/Development/IDE/Plugin/CodeAction/ExactPrint.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction/ExactPrint.hs b/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction/ExactPrint.hs index 98a79c9b66..10327423e6 100644 --- a/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction/ExactPrint.hs +++ b/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction/ExactPrint.hs @@ -398,7 +398,7 @@ extendImportViaParent df parent child (L l it@ImportDecl{..}) noExtField #endif childRdr -#if MIN_VERSION_ghc(9,5,0) +#if MIN_VERSION_ghc(9,7,0) listAnn = (Nothing, epAnn srcParent [AddEpAnn AnnOpenP (epl 1), AddEpAnn AnnCloseP (epl 0)]) #else listAnn = epAnn srcParent [AddEpAnn AnnOpenP (epl 1), AddEpAnn AnnCloseP (epl 0)] From 3f40d60881dacc21ec5e58c5c84b5c1a2daf23b8 Mon Sep 17 00:00:00 2001 From: Zubin Duggal Date: Thu, 18 Jan 2024 15:05:37 +0530 Subject: [PATCH 5/9] Don't use CPP in refactor plugin tests --- .../hls-refactor-plugin.cabal | 2 -- plugins/hls-refactor-plugin/test/Main.hs | 17 ++++++----------- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/plugins/hls-refactor-plugin/hls-refactor-plugin.cabal b/plugins/hls-refactor-plugin/hls-refactor-plugin.cabal index 3c816d616a..7678c360c1 100644 --- a/plugins/hls-refactor-plugin/hls-refactor-plugin.cabal +++ b/plugins/hls-refactor-plugin/hls-refactor-plugin.cabal @@ -110,8 +110,6 @@ test-suite tests , hls-test-utils == 2.6.0.0 , lens , lsp-types - -- for MIN_VERSION_ghc - , ghc , text , hls-plugin-api , parser-combinators diff --git a/plugins/hls-refactor-plugin/test/Main.hs b/plugins/hls-refactor-plugin/test/Main.hs index 55eecfd633..3e3d6a9a19 100644 --- a/plugins/hls-refactor-plugin/test/Main.hs +++ b/plugins/hls-refactor-plugin/test/Main.hs @@ -1,5 +1,4 @@ {-# LANGUAGE AllowAmbiguousTypes #-} -{-# LANGUAGE CPP #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE GADTs #-} @@ -701,11 +700,9 @@ typeWildCardActionTests = testGroup "type wildcard actions" [ "func :: _" , "func x y = x + y" ] -#if MIN_VERSION_ghc(9,7,0) - [ "func :: a -> a -> a" -- 9.8 has a different suggestion -#else - [ "func :: Integer -> Integer -> Integer" -#endif + [ if ghcVersion >= GHC98 + then "func :: a -> a -> a" -- 9.8 has a different suggestion + else "func :: Integer -> Integer -> Integer" , "func x y = x + y" ] , testUseTypeSignature "type in parentheses" @@ -733,11 +730,9 @@ typeWildCardActionTests = testGroup "type wildcard actions" [ "func::_" , "func x y = x + y" ] -#if MIN_VERSION_ghc(9,7,0) - [ "func::a -> a -> a" -- 9.8 has a different suggestion -#else - [ "func::Integer -> Integer -> Integer" -#endif + [ if ghcVersion >= GHC98 + then "func::a -> a -> a" -- 9.8 has a different suggestion + else "func::Integer -> Integer -> Integer" , "func x y = x + y" ] , testGroup "add parens if hole is part of bigger type" From 32d2076b529c3986a64e3ae924ad8fd241bdbb90 Mon Sep 17 00:00:00 2001 From: Jan Hrcek <2716069+jhrcek@users.noreply.github.com> Date: Thu, 18 Jan 2024 10:48:37 +0100 Subject: [PATCH 6/9] Fix -Wall, -Wunused-packages and hlint warnings in call-hierarchy plugin (#3979) * Fix -Wall and -Wunused-packages in call-hierarchy plugin * Make tests more uniform --- .../hls-call-hierarchy-plugin.cabal | 6 +- .../src/Ide/Plugin/CallHierarchy/Internal.hs | 65 +++++++------ .../src/Ide/Plugin/CallHierarchy/Query.hs | 1 + .../hls-call-hierarchy-plugin/test/Main.hs | 97 +++++++------------ 4 files changed, 80 insertions(+), 89 deletions(-) diff --git a/plugins/hls-call-hierarchy-plugin/hls-call-hierarchy-plugin.cabal b/plugins/hls-call-hierarchy-plugin/hls-call-hierarchy-plugin.cabal index 61ad715478..151e5f020a 100644 --- a/plugins/hls-call-hierarchy-plugin/hls-call-hierarchy-plugin.cabal +++ b/plugins/hls-call-hierarchy-plugin/hls-call-hierarchy-plugin.cabal @@ -19,7 +19,11 @@ source-repository head type: git location: https://github.com/haskell/haskell-language-server.git +common warnings + ghc-options: -Wall -Wunused-packages + library + import: warnings buildable: True exposed-modules: Ide.Plugin.CallHierarchy other-modules: @@ -40,12 +44,12 @@ library , lsp >=2.3 , sqlite-simple , text - , unordered-containers default-language: Haskell2010 default-extensions: DataKinds test-suite tests + import: warnings type: exitcode-stdio-1.0 default-language: Haskell2010 hs-source-dirs: test diff --git a/plugins/hls-call-hierarchy-plugin/src/Ide/Plugin/CallHierarchy/Internal.hs b/plugins/hls-call-hierarchy-plugin/src/Ide/Plugin/CallHierarchy/Internal.hs index dcae70b249..9f34dbe27c 100644 --- a/plugins/hls-call-hierarchy-plugin/src/Ide/Plugin/CallHierarchy/Internal.hs +++ b/plugins/hls-call-hierarchy-plugin/src/Ide/Plugin/CallHierarchy/Internal.hs @@ -3,6 +3,7 @@ {-# LANGUAGE LambdaCase #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE Rank2Types #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving #-} @@ -13,43 +14,45 @@ module Ide.Plugin.CallHierarchy.Internal ( , outgoingCalls ) where -import Control.Lens ((^.)) +import Control.Lens (Lens', (^.)) import Control.Monad.IO.Class -import Data.Aeson as A -import Data.List (groupBy, sortBy) -import qualified Data.Map as M +import Data.Aeson as A +import Data.Functor ((<&>)) +import Data.List (groupBy, sortBy) +import qualified Data.Map as M import Data.Maybe -import qualified Data.Set as S -import qualified Data.Text as T +import Data.Ord (comparing) +import qualified Data.Set as S +import qualified Data.Text as T import Data.Tuple.Extra import Development.IDE -import qualified Development.IDE.Core.PluginUtils as PluginUtils import Development.IDE.Core.Shake -import Development.IDE.GHC.Compat as Compat +import Development.IDE.GHC.Compat as Compat import Development.IDE.Spans.AtPoint -import HieDb (Symbol (Symbol)) -import qualified Ide.Plugin.CallHierarchy.Query as Q +import HieDb (Symbol (Symbol)) +import qualified Ide.Plugin.CallHierarchy.Query as Q import Ide.Plugin.CallHierarchy.Types import Ide.Plugin.Error import Ide.Types -import qualified Language.LSP.Protocol.Lens as L +import qualified Language.LSP.Protocol.Lens as L import Language.LSP.Protocol.Message import Language.LSP.Protocol.Types -import Text.Read (readMaybe) +import Prelude hiding (mod, span) +import Text.Read (readMaybe) -- | Render prepare call hierarchy request. prepareCallHierarchy :: PluginMethodHandler IdeState Method_TextDocumentPrepareCallHierarchy prepareCallHierarchy state _ param = do - nfp <- getNormalizedFilePathE (param ^. L.textDocument ^. L.uri) + nfp <- getNormalizedFilePathE (param ^. (L.textDocument . L.uri)) items <- liftIO $ runAction "CallHierarchy.prepareHierarchy" state $ prepareCallHierarchyItem nfp (param ^. L.position) pure $ InL items prepareCallHierarchyItem :: NormalizedFilePath -> Position -> Action [CallHierarchyItem] -prepareCallHierarchyItem nfp pos = use GetHieAst nfp >>= \case - Nothing -> pure mempty - Just (HAR _ hf _ _ _) -> pure $ prepareByAst hf pos nfp +prepareCallHierarchyItem nfp pos = use GetHieAst nfp <&> \case + Nothing -> mempty + Just (HAR _ hf _ _ _) -> prepareByAst hf pos nfp prepareByAst :: HieASTs a -> Position -> NormalizedFilePath -> [CallHierarchyItem] prepareByAst hf pos nfp = @@ -173,7 +176,7 @@ deriving instance Ord Value -- | Render incoming calls request. incomingCalls :: PluginMethodHandler IdeState Method_CallHierarchyIncomingCalls -incomingCalls state pluginId param = do +incomingCalls state _pluginId param = do calls <- liftIO $ runAction "CallHierarchy.incomingCalls" state $ queryCalls @@ -181,14 +184,14 @@ incomingCalls state pluginId param = do Q.incomingCalls mkCallHierarchyIncomingCall (mergeCalls CallHierarchyIncomingCall L.from) - pure $ InL $ calls + pure $ InL calls where mkCallHierarchyIncomingCall :: Vertex -> Action (Maybe CallHierarchyIncomingCall) mkCallHierarchyIncomingCall = mkCallHierarchyCall CallHierarchyIncomingCall -- | Render outgoing calls request. outgoingCalls :: PluginMethodHandler IdeState Method_CallHierarchyOutgoingCalls -outgoingCalls state pluginId param = do +outgoingCalls state _pluginId param = do calls <- liftIO $ runAction "CallHierarchy.outgoingCalls" state $ queryCalls @@ -196,15 +199,22 @@ outgoingCalls state pluginId param = do Q.outgoingCalls mkCallHierarchyOutgoingCall (mergeCalls CallHierarchyOutgoingCall L.to) - pure $ InL $ calls + pure $ InL calls where mkCallHierarchyOutgoingCall :: Vertex -> Action (Maybe CallHierarchyOutgoingCall) mkCallHierarchyOutgoingCall = mkCallHierarchyCall CallHierarchyOutgoingCall + -- | Merge calls from the same place +mergeCalls :: + L.HasFromRanges s [Range] + => (CallHierarchyItem -> [Range] -> s) + -> Lens' s CallHierarchyItem + -> [s] + -> [s] mergeCalls constructor target = concatMap merge . groupBy (\a b -> a ^. target == b ^. target) - . sortBy (\a b -> (a ^. target) `compare` (b ^. target)) + . sortBy (comparing (^. target)) where merge [] = [] merge calls@(call:_) = @@ -235,7 +245,7 @@ mkCallHierarchyCall mk v@Vertex{..} = do case items of [item] -> pure $ Just $ mk item [range] _ -> pure Nothing - _ -> pure Nothing + [] -> pure Nothing -- | Unified queries include incoming calls and outgoing calls. queryCalls :: (Show a) @@ -257,7 +267,6 @@ queryCalls item queryFunc makeFunc merge | otherwise = pure mempty where uri = item ^. L.uri - xdata = item ^. L.data_ pos = item ^. (L.selectionRange . L.start) getSymbol nfp = case item ^. L.data_ of @@ -267,9 +276,9 @@ queryCalls item queryFunc makeFunc merge Nothing -> getSymbolFromAst nfp pos -- Fallback if xdata lost, some editor(VSCode) will drop it getSymbolFromAst :: NormalizedFilePath -> Position -> Action (Maybe Symbol) - getSymbolFromAst nfp pos = use GetHieAst nfp >>= \case - Nothing -> pure Nothing + getSymbolFromAst nfp pos_ = use GetHieAst nfp <&> \case + Nothing -> Nothing Just (HAR _ hf _ _ _) -> do - case listToMaybe $ pointCommand hf pos extract of - Just infos -> maybe (pure Nothing) pure $ mkSymbol . fst3 <$> listToMaybe infos - Nothing -> pure Nothing + case listToMaybe $ pointCommand hf pos_ extract of + Just infos -> mkSymbol . fst3 =<< listToMaybe infos + Nothing -> Nothing diff --git a/plugins/hls-call-hierarchy-plugin/src/Ide/Plugin/CallHierarchy/Query.hs b/plugins/hls-call-hierarchy-plugin/src/Ide/Plugin/CallHierarchy/Query.hs index 1eee277caf..30f85219bf 100644 --- a/plugins/hls-call-hierarchy-plugin/src/Ide/Plugin/CallHierarchy/Query.hs +++ b/plugins/hls-call-hierarchy-plugin/src/Ide/Plugin/CallHierarchy/Query.hs @@ -13,6 +13,7 @@ import Database.SQLite.Simple import Development.IDE.GHC.Compat import HieDb (HieDb (getConn), Symbol (..)) import Ide.Plugin.CallHierarchy.Types +import Prelude hiding (mod) incomingCalls :: HieDb -> Symbol -> IO [Vertex] incomingCalls (getConn -> conn) symbol = do diff --git a/plugins/hls-call-hierarchy-plugin/test/Main.hs b/plugins/hls-call-hierarchy-plugin/test/Main.hs index af51fdd04c..4e4db53087 100644 --- a/plugins/hls-call-hierarchy-plugin/test/Main.hs +++ b/plugins/hls-call-hierarchy-plugin/test/Main.hs @@ -1,8 +1,7 @@ -{-# LANGUAGE LambdaCase #-} -{-# LANGUAGE OverloadedStrings #-} -{-# LANGUAGE RankNTypes #-} -{-# LANGUAGE StandaloneDeriving #-} -{-# LANGUAGE TupleSections #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE RankNTypes #-} +{-# LANGUAGE TupleSections #-} module Main (main) where @@ -17,11 +16,8 @@ import Development.IDE.Test import Ide.Plugin.CallHierarchy import qualified Language.LSP.Protocol.Lens as L import qualified Language.LSP.Test as Test -import System.Directory.Extra import System.FilePath -import qualified System.IO.Extra import Test.Hls -import Test.Hls.Util (withCanonicalTempDir) plugin :: PluginTestDescriptor () plugin = mkPluginTestDescriptor' descriptor "call-hierarchy" @@ -196,20 +192,16 @@ incomingCallsTests :: TestTree incomingCallsTests = testGroup "Incoming Calls" [ testGroup "single file" - [ - testCase "xdata unavailable" $ + [ testCase "xdata unavailable" $ runSessionWithServer def plugin testDataDir $ do doc <- createDoc "A.hs" "haskell" $ T.unlines ["a=3", "b=a"] waitForIndex (testDataDir "A.hs") - [item] <- Test.prepareCallHierarchy (mkPrepareCallHierarchyParam doc 1 0) + item <- expectOneElement =<< Test.prepareCallHierarchy (mkPrepareCallHierarchyParam doc 1 0) let expected = [CallHierarchyIncomingCall item [mkRange 1 2 1 3]] - Test.prepareCallHierarchy (mkPrepareCallHierarchyParam doc 0 0) >>= - \case - [item] -> do - let itemNoData = set L.data_ Nothing item - Test.incomingCalls (mkIncomingCallsParam itemNoData) >>= - \res -> liftIO $ sort expected @=? sort res - _ -> liftIO $ assertFailure "Not exactly one element" + item' <- expectOneElement =<< Test.prepareCallHierarchy (mkPrepareCallHierarchyParam doc 0 0) + let itemNoData = set L.data_ Nothing item' + res <- Test.incomingCalls (mkIncomingCallsParam itemNoData) + liftIO $ sort expected @=? sort res closeDoc doc , testCase "xdata available" $ do let contents = T.unlines ["a=3","b=a"] @@ -321,20 +313,16 @@ outgoingCallsTests :: TestTree outgoingCallsTests = testGroup "Outgoing Calls" [ testGroup "single file" - [ - testCase "xdata unavailable" $ withCanonicalTempDir $ \dir -> + [ testCase "xdata unavailable" $ withCanonicalTempDir $ \dir -> runSessionWithServer def plugin dir $ do doc <- createDoc "A.hs" "haskell" $ T.unlines ["a=3", "b=a"] waitForIndex (dir "A.hs") - [item] <- Test.prepareCallHierarchy (mkPrepareCallHierarchyParam doc 0 1) + item <- expectOneElement =<< Test.prepareCallHierarchy (mkPrepareCallHierarchyParam doc 0 1) let expected = [CallHierarchyOutgoingCall item [mkRange 1 2 1 3]] - Test.prepareCallHierarchy (mkPrepareCallHierarchyParam doc 1 0) >>= - \case - [item] -> do - let itemNoData = set L.data_ Nothing item - Test.outgoingCalls (mkOutgoingCallsParam itemNoData) >>= - \res -> liftIO $ sort expected @=? sort res - _ -> liftIO $ assertFailure "Not exactly one element" + item' <- expectOneElement =<< Test.prepareCallHierarchy (mkPrepareCallHierarchyParam doc 1 0) + let itemNoData = set L.data_ Nothing item' + res <- Test.outgoingCalls (mkOutgoingCallsParam itemNoData) + liftIO $ sort expected @=? sort res closeDoc doc , testCase "xdata available" $ do let contents = T.unlines ["a=3", "b=a"] @@ -434,13 +422,9 @@ incomingCallTestCase contents queryX queryY positions ranges = withCanonicalTemp ) (zip positions ranges) let expected = map mkCallHierarchyIncomingCall items - -- liftIO delay - Test.prepareCallHierarchy (mkPrepareCallHierarchyParam doc queryX queryY) >>= - \case - [item] -> do - Test.incomingCalls (mkIncomingCallsParam item) >>= - \res -> liftIO $ sort expected @=? sort res - _ -> liftIO $ assertFailure "Not one element" + item <- expectOneElement =<< Test.prepareCallHierarchy (mkPrepareCallHierarchyParam doc queryX queryY) + res <- Test.incomingCalls (mkIncomingCallsParam item) + liftIO $ sort expected @=? sort res closeDoc doc incomingCallMultiFileTestCase :: FilePath -> Int -> Int -> M.Map FilePath [((Int, Int), Range)] -> Assertion @@ -456,13 +440,9 @@ incomingCallMultiFileTestCase filepath queryX queryY mp = <&> map (, range) ) pr) mp let expected = map mkCallHierarchyIncomingCall items - -- liftIO delay - Test.prepareCallHierarchy (mkPrepareCallHierarchyParam doc queryX queryY) >>= - \case - [item] -> do - Test.incomingCalls (mkIncomingCallsParam item) >>= - \res -> liftIO $ sort expected @=? sort res - _ -> liftIO $ assertFailure "Not one element" + item <- expectOneElement =<< Test.prepareCallHierarchy (mkPrepareCallHierarchyParam doc queryX queryY) + res <- Test.incomingCalls (mkIncomingCallsParam item) + liftIO $ sort expected @=? sort res closeDoc doc outgoingCallTestCase :: T.Text -> Int -> Int -> [(Int, Int)] -> [Range] -> Assertion @@ -476,12 +456,9 @@ outgoingCallTestCase contents queryX queryY positions ranges = withCanonicalTemp ) (zip positions ranges) let expected = map mkCallHierarchyOutgoingCall items - Test.prepareCallHierarchy (mkPrepareCallHierarchyParam doc queryX queryY) >>= - \case - [item] -> do - Test.outgoingCalls (mkOutgoingCallsParam item) >>= - \res -> liftIO $ sort expected @=? sort res - _ -> liftIO $ assertFailure "Not one element" + item <- expectOneElement =<< Test.prepareCallHierarchy (mkPrepareCallHierarchyParam doc queryX queryY) + res <- Test.outgoingCalls (mkOutgoingCallsParam item) + liftIO $ sort expected @=? sort res closeDoc doc outgoingCallMultiFileTestCase :: FilePath -> Int -> Int -> M.Map FilePath [((Int, Int), Range)] -> Assertion @@ -497,12 +474,9 @@ outgoingCallMultiFileTestCase filepath queryX queryY mp = <&> map (, range) ) pr) mp let expected = map mkCallHierarchyOutgoingCall items - Test.prepareCallHierarchy (mkPrepareCallHierarchyParam doc queryX queryY) >>= - \case - [item] -> do - Test.outgoingCalls (mkOutgoingCallsParam item) >>= - \res -> liftIO $ sort expected @=? sort res - _ -> liftIO $ assertFailure "Not one element" + item <- expectOneElement =<< Test.prepareCallHierarchy (mkPrepareCallHierarchyParam doc queryX queryY) + res <- Test.outgoingCalls (mkOutgoingCallsParam item) + liftIO $ sort expected @=? sort res closeDoc doc oneCaseWithCreate :: T.Text -> Int -> Int -> (Uri -> CallHierarchyItem -> Assertion) -> Assertion @@ -510,12 +484,15 @@ oneCaseWithCreate contents queryX queryY expected = withCanonicalTempDir $ \dir runSessionWithServer def plugin dir $ do doc <- createDoc "A.hs" "haskell" contents waitForIndex (dir "A.hs") - Test.prepareCallHierarchy (mkPrepareCallHierarchyParam doc queryX queryY) >>= - \case - [item] -> liftIO $ expected (doc ^. L.uri) item - res -> liftIO $ assertFailure "Not one element" + item <- expectOneElement =<< Test.prepareCallHierarchy (mkPrepareCallHierarchyParam doc queryX queryY) + liftIO $ expected (doc ^. L.uri) item closeDoc doc +expectOneElement :: [a] -> Session a +expectOneElement = \case + [x] -> pure x + xs -> liftIO . assertFailure $ "Expecting exactly one element, but got " ++ show (length xs) + mkCallHierarchyItem' :: String -> T.Text -> SymbolKind -> Range -> Range -> Uri -> CallHierarchyItem -> Assertion mkCallHierarchyItem' prefix name kind range selRange uri c@(CallHierarchyItem name' kind' tags' detail' uri' range' selRange' xdata') = do assertHierarchyItem name name' @@ -528,7 +505,7 @@ mkCallHierarchyItem' prefix name kind range selRange uri c@(CallHierarchyItem na case xdata' of Nothing -> assertFailure ("In " ++ show c ++ ", got Nothing for data but wanted " ++ show xdata) Just v -> case Aeson.fromJSON v of - Aeson.Success v -> assertBool ("In " ++ show c ++ " wanted data prefix: " ++ show xdata) (xdata `T.isPrefixOf` v) + Aeson.Success v' -> assertBool ("In " ++ show c ++ " wanted data prefix: " ++ show xdata) (xdata `T.isPrefixOf` v') Aeson.Error err -> assertFailure ("In " ++ show c ++ " wanted data prefix: " ++ show xdata ++ " but json parsing failed with " ++ show err) where tags = Nothing @@ -570,6 +547,6 @@ waitForIndex fp1 = skipManyTill anyMessage $ void $ referenceReady lenientEquals -- filepath from the message lenientEquals :: FilePath -> Bool lenientEquals fp2 - | isRelative fp1 = any (equalFilePath fp1) (map (foldr () "") $ tails $ splitDirectories fp2) + | isRelative fp1 = any (equalFilePath fp1 . joinPath) $ tails $ splitDirectories fp2 | otherwise = equalFilePath fp1 fp2 From c728986cb2a24e35591445e48ed06512943be2e7 Mon Sep 17 00:00:00 2001 From: Zubin Duggal Date: Thu, 18 Jan 2024 15:36:54 +0530 Subject: [PATCH 7/9] accept func test differences --- .../schema/ghc98/default-config.golden.json | 31 +++++++++ .../ghc98/vscode-extension-schema.golden.json | 66 +++++++++++++++++++ 2 files changed, 97 insertions(+) diff --git a/test/testdata/schema/ghc98/default-config.golden.json b/test/testdata/schema/ghc98/default-config.golden.json index 7e8aacb406..b42d8f4e51 100644 --- a/test/testdata/schema/ghc98/default-config.golden.json +++ b/test/testdata/schema/ghc98/default-config.golden.json @@ -18,6 +18,10 @@ "changeTypeSignature": { "globalOn": true }, + "class": { + "codeActionsOn": true, + "codeLensOn": true + }, "eval": { "config": { "diff": true, @@ -37,6 +41,21 @@ "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, @@ -81,6 +100,15 @@ "qualifyImportedNames": { "globalOn": true }, + "rename": { + "config": { + "crossModule": false + }, + "globalOn": true + }, + "retrie": { + "globalOn": true + }, "semanticTokens": { "config": { "classMethodToken": "method", @@ -97,6 +125,9 @@ }, "globalOn": false }, + "splice": { + "globalOn": true + }, "stan": { "globalOn": false } diff --git a/test/testdata/schema/ghc98/vscode-extension-schema.golden.json b/test/testdata/schema/ghc98/vscode-extension-schema.golden.json index 9987252694..861b8a37e0 100644 --- a/test/testdata/schema/ghc98/vscode-extension-schema.golden.json +++ b/test/testdata/schema/ghc98/vscode-extension-schema.golden.json @@ -35,6 +35,18 @@ "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.config.diff": { "default": true, "markdownDescription": "Enable the diff output (WAS/NOW) of eval lenses", @@ -77,6 +89,36 @@ "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", @@ -183,6 +225,24 @@ "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.retrie.globalOn": { + "default": true, + "description": "Enables retrie plugin", + "scope": "resource", + "type": "boolean" + }, "haskell.plugin.semanticTokens.config.classMethodToken": { "default": "method", "description": "LSP semantic token type to use for typeclass methods", @@ -805,6 +865,12 @@ "scope": "resource", "type": "boolean" }, + "haskell.plugin.splice.globalOn": { + "default": true, + "description": "Enables splice plugin", + "scope": "resource", + "type": "boolean" + }, "haskell.plugin.stan.globalOn": { "default": false, "description": "Enables stan plugin", From 71dce0b40fafdd49dd2a0325b61798142c5cc116 Mon Sep 17 00:00:00 2001 From: Zubin Duggal Date: Thu, 18 Jan 2024 17:17:39 +0530 Subject: [PATCH 8/9] Run tests for 9.8 plugins in CI --- .github/workflows/test.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 44d46d00d9..69b6856068 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -135,7 +135,7 @@ jobs: HLS_WRAPPER_TEST_EXE: hls-wrapper run: cabal test wrapper-test --test-options="$TEST_OPTS --rerun-log-file .tasty-rerun-log-wrapper" - - if: matrix.test && !startsWith(matrix.ghc,'9.8') + - if: matrix.test name: Test hls-refactor-plugin run: cabal test hls-refactor-plugin --test-options="$TEST_OPTS" || cabal test hls-refactor-plugin --test-options="$TEST_OPTS" @@ -143,7 +143,7 @@ jobs: name: Test hls-floskell-plugin run: cabal test hls-floskell-plugin --test-options="$TEST_OPTS" || cabal test hls-floskell-plugin --test-options="$TEST_OPTS" - - if: matrix.test && !startsWith(matrix.ghc,'9.8') + - if: matrix.test name: Test hls-class-plugin run: cabal test hls-class-plugin --test-options="$TEST_OPTS" || cabal test hls-class-plugin --test-options="$TEST_OPTS" @@ -155,7 +155,7 @@ jobs: name: Test hls-eval-plugin run: cabal test hls-eval-plugin --test-options="$TEST_OPTS" || cabal test hls-eval-plugin --test-options="$TEST_OPTS" - - if: matrix.test && !startsWith(matrix.ghc,'9.8') + - if: matrix.test name: Test hls-splice-plugin run: cabal test hls-splice-plugin --test-options="$TEST_OPTS" || cabal test hls-splice-plugin --test-options="$TEST_OPTS" @@ -183,7 +183,7 @@ jobs: name: Test hls-call-hierarchy-plugin test suite run: cabal test hls-call-hierarchy-plugin --test-options="$TEST_OPTS" || cabal test hls-call-hierarchy-plugin --test-options="$TEST_OPTS" - - if: matrix.test && matrix.os != 'windows-latest' && !startsWith(matrix.ghc,'9.8') + - if: matrix.test && matrix.os != 'windows-latest' name: Test hls-rename-plugin test suite run: cabal test hls-rename-plugin --test-options="$TEST_OPTS" || cabal test hls-rename-plugin --test-options="$TEST_OPTS" @@ -211,7 +211,7 @@ jobs: name: Test hls-change-type-signature test suite run: cabal test hls-change-type-signature-plugin --test-options="$TEST_OPTS" || cabal test hls-change-type-signature-plugin --test-options="$TEST_OPTS" - - if: matrix.test && !startsWith(matrix.ghc,'9.8') + - if: matrix.test name: Test hls-gadt-plugin test suit run: cabal test hls-gadt-plugin --test-options="$TEST_OPTS" || cabal test hls-gadt-plugin --test-options="$TEST_OPTS" @@ -232,7 +232,7 @@ jobs: name: Test hls-cabal-plugin test suite run: cabal test hls-cabal-plugin --test-options="$TEST_OPTS" || cabal test hls-cabal-plugin --test-options="$TEST_OPTS" - - if: matrix.test && !startsWith(matrix.ghc,'9.8') + - if: matrix.test name: Test hls-retrie-plugin test suite run: cabal test hls-retrie-plugin --test-options="$TEST_OPTS" || cabal test hls-retrie-plugin --test-options="$TEST_OPTS" From eccadedb2eb61018d26e80f8ab2ee85040cbdc07 Mon Sep 17 00:00:00 2001 From: Zubin Duggal Date: Thu, 18 Jan 2024 18:22:31 +0530 Subject: [PATCH 9/9] Fix another test --- plugins/hls-refactor-plugin/test/Main.hs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/hls-refactor-plugin/test/Main.hs b/plugins/hls-refactor-plugin/test/Main.hs index 3e3d6a9a19..28e163bc3f 100644 --- a/plugins/hls-refactor-plugin/test/Main.hs +++ b/plugins/hls-refactor-plugin/test/Main.hs @@ -3736,12 +3736,15 @@ extendImportTestsRegEx = testGroup "regex parsing" "\n\8226 Perhaps you want to add \8216fromList\8217 to one of these import lists:\n \8216Data.Map\8217)" Nothing , testCase "parse multiple imports" $ template - "\n\8226 Perhaps you want to add \8216fromList\8217 to one of these import lists:\n \8216Data.Map\8217 (app/testlsp.hs:7:1-18)\n \8216Data.HashMap.Strict\8217 (app/testlsp.hs:8:1-29)" + (if ghcVersion >= GHC98 + then "\n\8226 Add \8216fromList\8217 to one of these import lists:\n \8216Data.Map\8217 (at app/testlsp.hs:7:1-18)\n \8216Data.HashMap.Strict\8217 (at app/testlsp.hs:8:1-29)" + else "\n\8226 Perhaps you want to add \8216fromList\8217 to one of these import lists:\n \8216Data.Map\8217 (app/testlsp.hs:7:1-18)\n \8216Data.HashMap.Strict\8217 (app/testlsp.hs:8:1-29)" + ) $ Just ("fromList",[("Data.Map","app/testlsp.hs:7:1-18"),("Data.HashMap.Strict","app/testlsp.hs:8:1-29")]) ] where template message expected = do - liftIO $ matchRegExMultipleImports message @=? expected + liftIO $ expected @=? matchRegExMultipleImports message pickActionWithTitle :: T.Text -> [Command |? CodeAction] -> IO CodeAction pickActionWithTitle title actions = do