From ef51319b57bd23c8efe5978c5799729a3aca93c8 Mon Sep 17 00:00:00 2001 From: fendor Date: Thu, 23 May 2019 14:54:36 +0200 Subject: [PATCH 001/158] Support infix completions --- src/Haskell/Ide/Engine/Support/HieExtras.hs | 60 +++++++++++++++++---- 1 file changed, 51 insertions(+), 9 deletions(-) diff --git a/src/Haskell/Ide/Engine/Support/HieExtras.hs b/src/Haskell/Ide/Engine/Support/HieExtras.hs index 30aea954a..6ad6f016c 100644 --- a/src/Haskell/Ide/Engine/Support/HieExtras.hs +++ b/src/Haskell/Ide/Engine/Support/HieExtras.hs @@ -75,6 +75,7 @@ import SrcLoc import TcEnv import Type import Var +import System.IO (hPutStrLn, stderr) -- --------------------------------------------------------------------- @@ -103,13 +104,16 @@ data CompItem = CI , importedFrom :: T.Text , thingType :: Maybe Type , label :: T.Text + , isInfix :: Maybe Backtick } +data Backtick = Surrounded | LeftSide + instance Eq CompItem where - (CI n1 _ _ _) == (CI n2 _ _ _) = n1 == n2 + ci1 == ci2 = origName ci1 == origName ci2 instance Ord CompItem where - compare (CI n1 _ _ _) (CI n2 _ _ _) = compare n1 n2 + compare ci1 ci2 = origName ci1 `compare` origName ci2 occNameToComKind :: OccName -> J.CompletionItemKind occNameToComKind oc @@ -125,16 +129,21 @@ mkQuery name importedFrom = name <> " module:" <> importedFrom <> " is:exact" mkCompl :: CompItem -> J.CompletionItem -mkCompl CI{origName,importedFrom,thingType,label} = +mkCompl CI{origName,importedFrom,thingType,label,isInfix} = J.CompletionItem label kind (Just $ maybe "" (<>"\n") typeText <> importedFrom) Nothing Nothing Nothing Nothing Nothing (Just insertText) (Just J.Snippet) Nothing Nothing Nothing Nothing hoogleQuery where kind = Just $ occNameToComKind $ occName origName hoogleQuery = Just $ toJSON $ mkQuery label importedFrom argTypes = maybe [] getArgs thingType - insertText - | [] <- argTypes = label - | otherwise = label <> " " <> argText + insertText = case isInfix of + Nothing -> case argTypes of + [] -> label + _ -> label <> " " <> argText + Just LeftSide -> label <> "`" + + Just Surrounded -> label + argText :: T.Text argText = mconcat $ List.intersperse " " $ zipWith snippet [1..] argTypes stripForall t @@ -224,17 +233,20 @@ instance ModuleCache CachedCompletions where typeEnv = md_types $ snd $ tm_internals_ tm toplevelVars = mapMaybe safeTyThingId $ typeEnvElts typeEnv - varToCompl var = CI name (showModName curMod) typ label + + varToCompl :: Var -> CompItem + varToCompl var = CI name (showModName curMod) typ label Nothing where typ = Just $ varType var name = Var.varName var label = T.pack $ showGhc name + toplevelCompls :: [CompItem] toplevelCompls = map varToCompl toplevelVars toCompItem :: ModuleName -> Name -> CompItem toCompItem mn n = - CI n (showModName mn) Nothing (T.pack $ showGhc n) + CI n (showModName mn) Nothing (T.pack $ showGhc n) Nothing allImportsInfo :: [(Bool, T.Text, ModuleName, Maybe (Bool, [Name]))] allImportsInfo = map getImpInfo importDeclerations @@ -369,6 +381,26 @@ getCompletions uri prefixInfo (WithSnippets withSnippets) = d = T.length fullLine - T.length (stripTypeStuff partialLine) in Position l (c - d) + hasTrailingBacktick = + if T.length fullLine <= trailingBacktickIndex + then False + else (fullLine `T.index` trailingBacktickIndex) == '`' + + trailingBacktickIndex = let Position _ cursorColumn = VFS.cursorPos prefixInfo in cursorColumn + + isUsedAsInfix = if backtickIndex < 0 + then False + else (fullLine `T.index` backtickIndex) == '`' + + backtickIndex = + let Position _ cursorColumn = VFS.cursorPos prefixInfo + prefixLength = T.length prefixText + moduleLength = if prefixModule == "" + then 0 + else T.length prefixModule + 1 {- Because of "." -} + in + cursorColumn - (prefixLength + moduleLength) - 1 {- Points to the first letter of either the module or prefix text -} + filtModNameCompls = map mkModCompl $ mapMaybe (T.stripPrefix enteredQual) @@ -378,13 +410,23 @@ getCompletions uri prefixInfo (WithSnippets withSnippets) = where isTypeCompl = isTcOcc . occName . origName -- completions specific to the current context - ctxCompls = case context of + ctxCompls' = case context of TypeContext -> filter isTypeCompl compls ValueContext -> filter (not . isTypeCompl) compls + -- Add whether the text to insert has backticks + ctxCompls = map (\comp -> comp { isInfix = infixCompls }) ctxCompls' + + infixCompls :: Maybe Backtick + infixCompls = case (isUsedAsInfix, hasTrailingBacktick) of + (True, False) -> Just LeftSide + (True, True) -> Just Surrounded + _ -> Nothing + compls = if T.null prefixModule then unqualCompls else Map.findWithDefault [] prefixModule qualCompls + mkImportCompl label = (J.detail ?~ label) . mkModCompl $ fromMaybe "" (T.stripPrefix enteredQual label) From 3c8f462d6f402afbe3314a21332d36f630c25b94 Mon Sep 17 00:00:00 2001 From: fendor Date: Thu, 23 May 2019 15:04:42 +0200 Subject: [PATCH 002/158] Remove unused imports --- src/Haskell/Ide/Engine/Support/HieExtras.hs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Haskell/Ide/Engine/Support/HieExtras.hs b/src/Haskell/Ide/Engine/Support/HieExtras.hs index 6ad6f016c..c2cc1a085 100644 --- a/src/Haskell/Ide/Engine/Support/HieExtras.hs +++ b/src/Haskell/Ide/Engine/Support/HieExtras.hs @@ -75,7 +75,6 @@ import SrcLoc import TcEnv import Type import Var -import System.IO (hPutStrLn, stderr) -- --------------------------------------------------------------------- From 203846a616619340a80aa93b8c627768159eaa63 Mon Sep 17 00:00:00 2001 From: fendor Date: Mon, 27 May 2019 19:52:05 +0200 Subject: [PATCH 003/158] Add tests for infix completions --- test/functional/CompletionSpec.hs | 61 ++++++++++++++++++++++++++ test/testdata/completion/Completion.hs | 3 ++ 2 files changed, 64 insertions(+) diff --git a/test/functional/CompletionSpec.hs b/test/functional/CompletionSpec.hs index 26e127dec..b3ffa45e6 100644 --- a/test/functional/CompletionSpec.hs +++ b/test/functional/CompletionSpec.hs @@ -250,6 +250,67 @@ spec = describe "completions" $ do item ^. insertTextFormat `shouldBe` Just Snippet item ^. insertText `shouldBe` Just "mapM ${1:a -> m b} ${2:t a}" + it "work for infix functions" $ runSession hieCommand fullCaps "test/testdata/completion" $ do + doc <- openDoc "Completion.hs" "haskell" + _ <- skipManyTill loggingNotification (count 2 noDiagnostics) + + let te = TextEdit (Range (Position 5 7) (Position 5 24)) "even `filte" + _ <- applyEdit doc te + + compls <- getCompletions doc (Position 5 17) + let item = head $ filter ((== "filter") . (^. label)) compls + liftIO $ do + item ^. label `shouldBe` "filter" + item ^. kind `shouldBe` Just CiFunction + item ^. insertTextFormat `shouldBe` Just Snippet + item ^. insertText `shouldBe` Just "`filter`" + + it "work for infix functions in backticks" $ runSession hieCommand fullCaps "test/testdata/completion" $ do + doc <- openDoc "Completion.hs" "haskell" + _ <- skipManyTill loggingNotification (count 2 noDiagnostics) + + let te = TextEdit (Range (Position 5 7) (Position 5 24)) "even `filte`" + _ <- applyEdit doc te + + compls <- getCompletions doc (Position 5 17) + let item = head $ filter ((== "filter") . (^. label)) compls + liftIO $ do + item ^. label `shouldBe` "filter" + item ^. kind `shouldBe` Just CiFunction + item ^. insertTextFormat `shouldBe` Just Snippet + item ^. insertText `shouldBe` Just "`filter`" + + it "work for qualified infix functions" $ runSession hieCommand fullCaps "test/testdata/completion" $ do + doc <- openDoc "Completion.hs" "haskell" + _ <- skipManyTill loggingNotification (count 2 noDiagnostics) + + let te = TextEdit (Range (Position 5 7) (Position 5 24)) "\"\" `Data.List.interspe" + _ <- applyEdit doc te + + compls <- getCompletions doc (Position 5 34) + let item = head $ filter ((== "intersperse") . (^. label)) compls + liftIO $ do + item ^. label `shouldBe` "intersperse" + item ^. kind `shouldBe` Just CiFunction + item ^. insertTextFormat `shouldBe` Just Snippet + item ^. insertText `shouldBe` Just "`Data.List.intersperse`" + + it "work for qualified infix functions in backticks" $ runSession hieCommand fullCaps "test/testdata/completion" $ do + doc <- openDoc "Completion.hs" "haskell" + _ <- skipManyTill loggingNotification (count 2 noDiagnostics) + + let te = TextEdit (Range (Position 5 7) (Position 5 24)) "\"\" `Data.List.interspe`" + _ <- applyEdit doc te + + + compls <- getCompletions doc (Position 5 34) + let item = head $ filter ((== "intersperse") . (^. label)) compls + liftIO $ do + item ^. label `shouldBe` "intersperse" + item ^. kind `shouldBe` Just CiFunction + item ^. insertTextFormat `shouldBe` Just Snippet + item ^. insertText `shouldBe` Just "`Data.List.intersperse`" + it "respects lsp configuration" $ runSession hieCommand fullCaps "test/testdata/completion" $ do doc <- openDoc "Completion.hs" "haskell" _ <- skipManyTill loggingNotification (count 2 noDiagnostics) diff --git a/test/testdata/completion/Completion.hs b/test/testdata/completion/Completion.hs index 722de38d5..d6480903b 100644 --- a/test/testdata/completion/Completion.hs +++ b/test/testdata/completion/Completion.hs @@ -4,3 +4,6 @@ import qualified Data.List main :: IO () main = putStrLn "hello" + +foo :: Either a b -> Either a b +foo = id \ No newline at end of file From 742c7bebcbafc482fedd9c207a0902cb4370b82b Mon Sep 17 00:00:00 2001 From: fendor Date: Thu, 30 May 2019 17:00:41 +0200 Subject: [PATCH 004/158] Fix tests --- test/functional/CompletionSpec.hs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/functional/CompletionSpec.hs b/test/functional/CompletionSpec.hs index b3ffa45e6..e703b5923 100644 --- a/test/functional/CompletionSpec.hs +++ b/test/functional/CompletionSpec.hs @@ -257,13 +257,13 @@ spec = describe "completions" $ do let te = TextEdit (Range (Position 5 7) (Position 5 24)) "even `filte" _ <- applyEdit doc te - compls <- getCompletions doc (Position 5 17) + compls <- getCompletions doc (Position 5 18) let item = head $ filter ((== "filter") . (^. label)) compls liftIO $ do item ^. label `shouldBe` "filter" item ^. kind `shouldBe` Just CiFunction item ^. insertTextFormat `shouldBe` Just Snippet - item ^. insertText `shouldBe` Just "`filter`" + item ^. insertText `shouldBe` Just "filter`" it "work for infix functions in backticks" $ runSession hieCommand fullCaps "test/testdata/completion" $ do doc <- openDoc "Completion.hs" "haskell" @@ -272,13 +272,13 @@ spec = describe "completions" $ do let te = TextEdit (Range (Position 5 7) (Position 5 24)) "even `filte`" _ <- applyEdit doc te - compls <- getCompletions doc (Position 5 17) + compls <- getCompletions doc (Position 5 18) let item = head $ filter ((== "filter") . (^. label)) compls liftIO $ do item ^. label `shouldBe` "filter" item ^. kind `shouldBe` Just CiFunction item ^. insertTextFormat `shouldBe` Just Snippet - item ^. insertText `shouldBe` Just "`filter`" + item ^. insertText `shouldBe` Just "filter" it "work for qualified infix functions" $ runSession hieCommand fullCaps "test/testdata/completion" $ do doc <- openDoc "Completion.hs" "haskell" @@ -287,13 +287,13 @@ spec = describe "completions" $ do let te = TextEdit (Range (Position 5 7) (Position 5 24)) "\"\" `Data.List.interspe" _ <- applyEdit doc te - compls <- getCompletions doc (Position 5 34) + compls <- getCompletions doc (Position 5 29) let item = head $ filter ((== "intersperse") . (^. label)) compls liftIO $ do item ^. label `shouldBe` "intersperse" item ^. kind `shouldBe` Just CiFunction item ^. insertTextFormat `shouldBe` Just Snippet - item ^. insertText `shouldBe` Just "`Data.List.intersperse`" + item ^. insertText `shouldBe` Just "intersperse`" it "work for qualified infix functions in backticks" $ runSession hieCommand fullCaps "test/testdata/completion" $ do doc <- openDoc "Completion.hs" "haskell" @@ -303,13 +303,13 @@ spec = describe "completions" $ do _ <- applyEdit doc te - compls <- getCompletions doc (Position 5 34) + compls <- getCompletions doc (Position 5 29) let item = head $ filter ((== "intersperse") . (^. label)) compls liftIO $ do item ^. label `shouldBe` "intersperse" item ^. kind `shouldBe` Just CiFunction item ^. insertTextFormat `shouldBe` Just Snippet - item ^. insertText `shouldBe` Just "`Data.List.intersperse`" + item ^. insertText `shouldBe` Just "intersperse" it "respects lsp configuration" $ runSession hieCommand fullCaps "test/testdata/completion" $ do doc <- openDoc "Completion.hs" "haskell" From e1cdb90a4df9caddbda59ad1c7505523925b200d Mon Sep 17 00:00:00 2001 From: fendor Date: Thu, 30 May 2019 18:26:07 +0200 Subject: [PATCH 005/158] Bump shake resolver --- shake.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shake.yaml b/shake.yaml index b3698677f..e89f45704 100644 --- a/shake.yaml +++ b/shake.yaml @@ -1,5 +1,5 @@ # Used to provide a different environment for the shake build script -resolver: nightly-2018-12-15 # GHC 8.6.2 +resolver: lts-13.18 # GHC 8.6.4 packages: - . From a1ce73ea1797db8a536a26e3f00fb0b2817614f1 Mon Sep 17 00:00:00 2001 From: fendor Date: Thu, 30 May 2019 18:30:12 +0200 Subject: [PATCH 006/158] Avoid legacy warning --- install.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install.hs b/install.hs index bc8d79e4a..0e3c314c4 100755 --- a/install.hs +++ b/install.hs @@ -247,7 +247,7 @@ installCabal = do -- install `cabal-install` if not already installed when (isNothing cabalExe) $ execStackShake_ ["install", "cabal-install"] - execCabal_ ["update"] + execCabal_ ["v1-update"] checkStack :: Action () From bd929c16bd95c13c2eef7050fa35fee03eeaf4b1 Mon Sep 17 00:00:00 2001 From: Alan Zimmerman Date: Fri, 31 May 2019 20:14:37 +0200 Subject: [PATCH 007/158] Bump resolvers and hoogle --- stack-8.2.2.yaml | 2 +- stack-8.4.2.yaml | 2 +- stack-8.4.3.yaml | 2 +- stack-8.4.4.yaml | 2 +- stack-8.6.1.yaml | 2 +- stack-8.6.2.yaml | 2 +- stack-8.6.3.yaml | 2 +- stack-8.6.4.yaml | 2 +- stack-8.6.5.yaml | 7 +++---- stack.yaml | 7 +++---- 10 files changed, 14 insertions(+), 16 deletions(-) diff --git a/stack-8.2.2.yaml b/stack-8.2.2.yaml index 0bf0d54be..b1177fe3c 100644 --- a/stack-8.2.2.yaml +++ b/stack-8.2.2.yaml @@ -26,7 +26,7 @@ extra-deps: - haskell-src-exts-1.21.0 - haskell-src-exts-util-0.2.5 - hlint-2.1.17 # last hlint supporting GHC 8.2 -- hoogle-5.0.17.6 +- hoogle-5.0.17.9 - hsimport-0.8.8 - lsp-test-0.5.2.3 - monad-dijkstra-0.1.1.2 diff --git a/stack-8.4.2.yaml b/stack-8.4.2.yaml index c632c5085..7ce199b53 100644 --- a/stack-8.4.2.yaml +++ b/stack-8.4.2.yaml @@ -25,7 +25,7 @@ extra-deps: - haskell-src-exts-1.21.0 - haskell-src-exts-util-0.2.5 - hlint-2.1.22 -- hoogle-5.0.17.6 +- hoogle-5.0.17.9 - hsimport-0.10.0 - lsp-test-0.5.2.3 - monad-dijkstra-0.1.1.2 diff --git a/stack-8.4.3.yaml b/stack-8.4.3.yaml index d4205ed3e..751c676cd 100644 --- a/stack-8.4.3.yaml +++ b/stack-8.4.3.yaml @@ -24,7 +24,7 @@ extra-deps: - haskell-src-exts-1.21.0 - haskell-src-exts-util-0.2.5 - hlint-2.1.22 -- hoogle-5.0.17.6 +- hoogle-5.0.17.9 - hsimport-0.10.0 - lsp-test-0.5.2.3 - monad-dijkstra-0.1.1.2 diff --git a/stack-8.4.4.yaml b/stack-8.4.4.yaml index 59ad0ef54..227e85c83 100644 --- a/stack-8.4.4.yaml +++ b/stack-8.4.4.yaml @@ -24,7 +24,7 @@ extra-deps: - haskell-src-exts-1.21.0 - haskell-src-exts-util-0.2.5 - hlint-2.1.22 -- hoogle-5.0.17.6 +- hoogle-5.0.17.9 - hsimport-0.10.0 - lsp-test-0.5.2.3 - monad-dijkstra-0.1.1.2 diff --git a/stack-8.6.1.yaml b/stack-8.6.1.yaml index 3e399bcc9..570450183 100644 --- a/stack-8.6.1.yaml +++ b/stack-8.6.1.yaml @@ -26,7 +26,7 @@ extra-deps: - haskell-src-exts-1.21.0 - haskell-src-exts-util-0.2.5 - hlint-2.1.22 -- hoogle-5.0.17.6 +- hoogle-5.0.17.9 - hsimport-0.10.0 - lsp-test-0.5.2.3 - monad-dijkstra-0.1.1.2 diff --git a/stack-8.6.2.yaml b/stack-8.6.2.yaml index 8058dad86..7b8022099 100644 --- a/stack-8.6.2.yaml +++ b/stack-8.6.2.yaml @@ -22,7 +22,7 @@ extra-deps: - haskell-src-exts-1.21.0 - haskell-src-exts-util-0.2.5 - hlint-2.1.22 -- hoogle-5.0.17.6 +- hoogle-5.0.17.9 - hsimport-0.10.0 - lsp-test-0.5.2.3 - monad-dijkstra-0.1.1.2 diff --git a/stack-8.6.3.yaml b/stack-8.6.3.yaml index 438cf8f7c..097e54547 100644 --- a/stack-8.6.3.yaml +++ b/stack-8.6.3.yaml @@ -22,7 +22,7 @@ extra-deps: - haskell-src-exts-1.21.0 - haskell-src-exts-util-0.2.5 - hlint-2.1.22 -- hoogle-5.0.17.6 +- hoogle-5.0.17.9 - hsimport-0.10.0 - lsp-test-0.5.2.3 - monad-dijkstra-0.1.1.2 diff --git a/stack-8.6.4.yaml b/stack-8.6.4.yaml index 0a8d744a6..ec39ae099 100644 --- a/stack-8.6.4.yaml +++ b/stack-8.6.4.yaml @@ -21,7 +21,7 @@ extra-deps: - haskell-lsp-types-0.13.0.0 - haskell-src-exts-1.21.0 - hlint-2.1.22 -- hoogle-5.0.17.6 +- hoogle-5.0.17.9 - hsimport-0.10.0 - lsp-test-0.5.2.3 - monad-dijkstra-0.1.1.2@rev:1 diff --git a/stack-8.6.5.yaml b/stack-8.6.5.yaml index 5e8eeeb11..a27bc7c46 100644 --- a/stack-8.6.5.yaml +++ b/stack-8.6.5.yaml @@ -1,4 +1,4 @@ -resolver: nightly-2019-04-30 # First GHC 8.6.5 +resolver: lts-13.23 # First GHC 8.6.5 packages: - . - hie-plugin-api @@ -11,19 +11,18 @@ extra-deps: - ./submodules/ghc-mod/core - ./submodules/ghc-mod/ghc-project-types -- ansi-terminal-0.8.2 - butcher-1.3.2.1 - cabal-plan-0.4.0.0 - constrained-dynamic-0.1.0.0 -- deque-0.2.7 - floskell-0.10.0 -- ghc-exactprint-0.5.8.2 - ghc-lib-parser-0.20190523 - haddock-api-2.22.0 - haskell-lsp-0.13.0.0 - haskell-lsp-types-0.13.0.0 +- haskell-src-exts-1.21.0 - hlint-2.1.22 - hsimport-0.10.0 +- hoogle-5.0.17.9 - lsp-test-0.5.2.3 - monad-dijkstra-0.1.1.2@rev:1 - monad-memo-0.4.1 diff --git a/stack.yaml b/stack.yaml index 5e8eeeb11..e8de1bccd 100644 --- a/stack.yaml +++ b/stack.yaml @@ -1,4 +1,4 @@ -resolver: nightly-2019-04-30 # First GHC 8.6.5 +resolver: nightly-2019-05-31 # GHC 8.6.5 packages: - . - hie-plugin-api @@ -12,13 +12,13 @@ extra-deps: - ./submodules/ghc-mod/ghc-project-types - ansi-terminal-0.8.2 +- ansi-wl-pprint-0.6.8.2 - butcher-1.3.2.1 - cabal-plan-0.4.0.0 - constrained-dynamic-0.1.0.0 - deque-0.2.7 -- floskell-0.10.0 +- floskell-0.10.1 - ghc-exactprint-0.5.8.2 -- ghc-lib-parser-0.20190523 - haddock-api-2.22.0 - haskell-lsp-0.13.0.0 - haskell-lsp-types-0.13.0.0 @@ -28,7 +28,6 @@ extra-deps: - monad-dijkstra-0.1.1.2@rev:1 - monad-memo-0.4.1 - multistate-0.8.0.1 -- rope-utf16-splay-0.3.1.0 - syz-0.2.0.0 - temporary-1.2.1.1 - yaml-0.8.32 From 3352088a2f0d193699fc0c5ccacd52c389f3bf14 Mon Sep 17 00:00:00 2001 From: Alan Zimmerman Date: Sat, 1 Jun 2019 09:29:26 +0200 Subject: [PATCH 008/158] Drop GHC 8.2.1 support Closes #1249 --- stack-8.2.1.yaml | 45 --------------------------------------------- 1 file changed, 45 deletions(-) delete mode 100644 stack-8.2.1.yaml diff --git a/stack-8.2.1.yaml b/stack-8.2.1.yaml deleted file mode 100644 index 02ca606bc..000000000 --- a/stack-8.2.1.yaml +++ /dev/null @@ -1,45 +0,0 @@ -resolver: nightly-2017-11-24 # Last one for GHC 8.2.1 -packages: -- . -- hie-plugin-api - -extra-deps: -- ./submodules/HaRe -- ./submodules/brittany -- ./submodules/cabal-helper -- ./submodules/ghc-mod -- ./submodules/ghc-mod/core -- ./submodules/ghc-mod/ghc-project-types - -# - brittany-0.11.0.0 -- butcher-1.3.1.1 -- cabal-plan-0.3.0.0 -- constrained-dynamic-0.1.0.0 -- czipwith-1.0.1.0 -- floskell-0.10.0 -- ghc-exactprint-0.5.8.2 -- haddock-api-2.18.1 -- haddock-library-1.4.4 -- haskell-lsp-0.13.0.0 -- haskell-lsp-types-0.13.0.0@rev:2 -- hlint-2.0.11 -- hsimport-0.10.0 -- lsp-test-0.5.2.3 -- monad-dijkstra-0.1.1.2 -- mtl-2.2.2 -- pretty-show-1.8.2 -- rope-utf16-splay-0.3.1.0 -- sorted-list-0.2.1.0 -- syz-0.2.0.0 -- yaml-0.8.32 - -flags: - haskell-ide-engine: - pedantic: true - hie-plugin-api: - pedantic: true - -nix: - packages: [ icu libcxx zlib ] - -concurrent-tests: false From e0c3518e014405d51ce3e60df40e79a0e8382cad Mon Sep 17 00:00:00 2001 From: Alan Zimmerman Date: Sat, 1 Jun 2019 11:12:11 +0200 Subject: [PATCH 009/158] Preparing for 0.10 May monthly release --- Changelog.md | 104 ++++++++++++++++++++++++++++ haskell-ide-engine.cabal | 2 +- hie-plugin-api/hie-plugin-api.cabal | 2 +- 3 files changed, 106 insertions(+), 2 deletions(-) diff --git a/Changelog.md b/Changelog.md index d61ab8e1d..f432c960a 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,107 @@ +# 0.10.0.0 + +- Bump resolvers and hoogle, LTS 13.23 for GHC 8.6.5, + nightly-2019-05-31 for stack.yaml and hoogle version 5.0.17.9 + ([#1277](https://github.com/haskell/haskell-ide-engine/pull/1277), + @alanz) + +- HsImport importlist, Offers code action to add a function to import list. + ([#1170](https://github.com/haskell/haskell-ide-engine/pull/1170), @fendor) + +- Typemap reimplementation + ([#1186](https://github.com/haskell/haskell-ide-engine/pull/1186), @fendor) + +- Add window/progress reporting for typechecking. Note: needs LSP + client to support a recent spec change. + ([#1190](https://github.com/haskell/haskell-ide-engine/pull/1190), + @bubba) + +- Add package to library component in package.yaml + ([#1237](https://github.com/haskell/haskell-ide-engine/pull/1237), @fendor) + +- hie sends invalid message on hover +([#1246](https://github.com/haskell/haskell-ide-engine/pull/1246), @Hogeyama) + +- Use floskell from hackage +([#1242](https://github.com/haskell/haskell-ide-engine/pull/1242), @bubba) + +- Adapting to new haskell-lsp +([#1247](https://github.com/haskell/haskell-ide-engine/pull/1247), @alanz) + +- Remove HoverContentsEmpty +([#1251](https://github.com/haskell/haskell-ide-engine/pull/1251), @alanz) + +- Use lsp-test-0.5.2.2 from hackage +([#1252](https://github.com/haskell/haskell-ide-engine/pull/1252), @bubba) + +- Use haskell-lsp-12.1.0 from hackage +([#1253](https://github.com/haskell/haskell-ide-engine/pull/1253), @alanz) + +- Bump haskell-lsp to 0.13.0.0 +([#1260](https://github.com/haskell/haskell-ide-engine/pull/1260), @alanz) + +- Bump version for hsimport to 0.10.0 +([#1265](https://github.com/haskell/haskell-ide-engine/pull/1265), @fendor) + +- Revert "Revert "Merge pull request #1237 from fendor/add-package-tests"" +([#1268](https://github.com/haskell/haskell-ide-engine/pull/1268), @alanz) + +- Hlint 2.1.22 +([#1270](https://github.com/haskell/haskell-ide-engine/pull/1270), @alanz) + +- Documentation + + - Add Nix cabal-helper fix to troubleshooting section + ([#1231](https://github.com/haskell/haskell-ide-engine/pull/1231), + @Infinisil) + + - Troubleshooting for emacs + ([#1240](https://github.com/haskell/haskell-ide-engine/pull/1240), + @Infinisil) + + - Change url for nix installation instructions + ([#1258](https://github.com/haskell/haskell-ide-engine/pull/1258), + @malob) + +- Preparations for hie-bios + + - HaRe hie plugin api + ([#1215](https://github.com/haskell/haskell-ide-engine/pull/1215), + @alanz) + + - Narrow ghc mod core + ([#1255](https://github.com/haskell/haskell-ide-engine/pull/1255), + @alanz) + +- Build system (install.hs) + + - Extra argument causes cabal-build-doc to fail + ([#1239](https://github.com/haskell/haskell-ide-engine/pull/1239), + @bflyblue) + + - Add an explicit stack file for GHC 8.6.5 + ([#1241](https://github.com/haskell/haskell-ide-engine/pull/1241), + @alanz) + + - Bump shake resolver + ([#1272](https://github.com/haskell/haskell-ide-engine/pull/1272), + @fendor) + + - Avoid legacy warning + ([#1273](https://github.com/haskell/haskell-ide-engine/pull/1273), + @fendor) + + + + + + + + + + + + # 0.9.0.0 - GHC 8.6.5 preliminary support added via the nightly build (@alanz) diff --git a/haskell-ide-engine.cabal b/haskell-ide-engine.cabal index 14957b932..e1efc3fe4 100644 --- a/haskell-ide-engine.cabal +++ b/haskell-ide-engine.cabal @@ -1,5 +1,5 @@ name: haskell-ide-engine -version: 0.9.0.0 +version: 0.10.0.0 synopsis: Provide a common engine to power any Haskell IDE description: Please see README.md homepage: http://github.com/githubuser/haskell-ide-engine#readme diff --git a/hie-plugin-api/hie-plugin-api.cabal b/hie-plugin-api/hie-plugin-api.cabal index c33932f93..7d6a96321 100644 --- a/hie-plugin-api/hie-plugin-api.cabal +++ b/hie-plugin-api/hie-plugin-api.cabal @@ -1,5 +1,5 @@ name: hie-plugin-api -version: 0.9.0.0 +version: 0.10.0.0 synopsis: Haskell IDE API for plugin communication license: BSD3 license-file: LICENSE From 1f7d3fa4c58056742e87feaf5db51033c9e5a213 Mon Sep 17 00:00:00 2001 From: Alan Zimmerman Date: Sat, 1 Jun 2019 11:19:04 +0200 Subject: [PATCH 010/158] Drop 8.2.1 from CI too --- .circleci/config.yml | 1 - .travis.yml | 17 ----------------- appveyor.yml | 1 - 3 files changed, 19 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 9f27f1370..798cdf129 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -195,7 +195,6 @@ workflows: version: 2 multiple-ghcs: jobs: - - ghc-8.2.1 - ghc-8.2.2 - ghc-8.4.2 - ghc-8.4.3 diff --git a/.travis.yml b/.travis.yml index 67a0719c3..bf6fb26c6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -54,10 +54,6 @@ jobs: env: GHC_VER="8.2.2" script: *setup - - stage: setup - env: GHC_VER="8.2.1" - script: *setup - - stage: dependencies env: GHC_VER="8.4.4" script: &dependencies @@ -75,10 +71,6 @@ jobs: env: GHC_VER="8.2.2" script: *dependencies - - stage: dependencies - env: GHC_VER="8.2.1" - script: *dependencies - - stage: test env: GHC_VER="8.4.4" script: &test @@ -96,10 +88,6 @@ jobs: env: GHC_VER="8.2.2" script: *test - - stage: test - env: GHC_VER="8.2.1" - script: *test - - stage: deploy env: GHC_VER="8.4.4" script: &deploy @@ -135,8 +123,3 @@ jobs: env: GHC_VER="8.2.2" script: *deploy deploy: *upload - - - stage: deploy - env: GHC_VER="8.2.1" - script: *deploy - deploy: *upload diff --git a/appveyor.yml b/appveyor.yml index 172f301f9..88165d419 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -8,7 +8,6 @@ environment: - GHCVER: 8.4.3 - GHCVER: 8.4.2 - GHCVER: 8.2.2 - - GHCVER: 8.2.1 install: - cmd: >- git submodule update --init --recursive From 89b809a95a6bf42e1bb901c2a54d0803e75ad803 Mon Sep 17 00:00:00 2001 From: Alan Zimmerman Date: Sat, 1 Jun 2019 15:07:43 +0200 Subject: [PATCH 011/158] Include dropping GHC 8.2.1 --- Changelog.md | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/Changelog.md b/Changelog.md index f432c960a..b4bbbc868 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,9 @@ # 0.10.0.0 +- Drop GHC 8.2.1 support. + ([#1279](https://github.com/haskell/haskell-ide-engine/pull/1279), + @alanz) + - Bump resolvers and hoogle, LTS 13.23 for GHC 8.6.5, nightly-2019-05-31 for stack.yaml and hoogle version 5.0.17.9 ([#1277](https://github.com/haskell/haskell-ide-engine/pull/1277), @@ -91,17 +95,6 @@ ([#1273](https://github.com/haskell/haskell-ide-engine/pull/1273), @fendor) - - - - - - - - - - - # 0.9.0.0 - GHC 8.6.5 preliminary support added via the nightly build (@alanz) From 7f90421a0fc200f47ffd731e1c09a5e98f28b68c Mon Sep 17 00:00:00 2001 From: fendor Date: Sun, 2 Jun 2019 15:29:44 +0200 Subject: [PATCH 012/158] Add liquid haskell smt solver to README --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 78504f791..4fc8addd2 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,7 @@ we talk to clients.__ - [Is there a hash (#) after \?](#is-there-a-hash--after-package) - [Otherwise](#otherwise) - [Nix: cabal-helper, No such file or directory](#nix-cabal-helper-no-such-file-or-directory) + - [Liquid Haskell](#liquid-haskell) ## Features @@ -629,4 +630,7 @@ cabal-helper-wrapper: /home/<...>/.cache/cabal-helper/cabal-helper<...>: createP can happen because cabal-helper compiles and runs above executable at runtime without using nix-build, which means a Nix garbage collection can delete the paths it depends on. Delete ~/.cache/cabal-helper and restart HIE to fix this. +### Liquid Haskell +Liquid Haskell requires an SMT solver on the path. We do not take care of installing one, thus, Liquid Haskell will not run until one is installed. +The recommended SMT solver is [z3](https://github.com/Z3Prover/z3). To run the tests, it is also required to have an SMT solver on the path, otherwise the tests will fail for Liquid Haskell. From 3350686dc36c9ed012a817b6806ec1a34c4b2d05 Mon Sep 17 00:00:00 2001 From: fendor Date: Mon, 3 Jun 2019 13:09:45 +0200 Subject: [PATCH 013/158] Clone HsImport API for more fine grained control Enables to use imports of constructors --- src/Haskell/Ide/Engine/Plugin/Hoogle.hs | 4 +- src/Haskell/Ide/Engine/Plugin/HsImport.hs | 236 ++++++++++++++++------ 2 files changed, 180 insertions(+), 60 deletions(-) diff --git a/src/Haskell/Ide/Engine/Plugin/Hoogle.hs b/src/Haskell/Ide/Engine/Plugin/Hoogle.hs index 2dd279ab1..de8401cc5 100644 --- a/src/Haskell/Ide/Engine/Plugin/Hoogle.hs +++ b/src/Haskell/Ide/Engine/Plugin/Hoogle.hs @@ -44,10 +44,10 @@ hoogleDescriptor plId = PluginDescriptor -- --------------------------------------------------------------------- -data HoogleError +data HoogleError = NoDb | DbFail T.Text - | NoResults + | NoResults deriving (Eq,Ord,Show) newtype HoogleDb = HoogleDb (Maybe FilePath) diff --git a/src/Haskell/Ide/Engine/Plugin/HsImport.hs b/src/Haskell/Ide/Engine/Plugin/HsImport.hs index 1737e66f9..0a5a663f6 100644 --- a/src/Haskell/Ide/Engine/Plugin/HsImport.hs +++ b/src/Haskell/Ide/Engine/Plugin/HsImport.hs @@ -1,7 +1,6 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DeriveAnyClass #-} -{-# LANGUAGE TupleSections #-} {-# LANGUAGE LambdaCase #-} module Haskell.Ide.Engine.Plugin.HsImport where @@ -9,8 +8,6 @@ import Control.Lens.Operators import Control.Monad.IO.Class import Control.Monad import Data.Aeson -import Data.Bitraversable -import Data.Bifunctor import Data.Foldable import Data.Maybe import Data.Monoid ( (<>) ) @@ -18,7 +15,7 @@ import qualified Data.Text as T import qualified Data.Text.IO as T import qualified GHC.Generics as Generics import qualified GhcModCore as GM ( mkRevRedirMapFunc, withMappedFile ) -import HsImport +import qualified HsImport import Haskell.Ide.Engine.Config import Haskell.Ide.Engine.MonadTypes import qualified Haskell.Ide.Engine.Support.HieExtras as Hie @@ -29,6 +26,7 @@ import qualified Haskell.Ide.Engine.Plugin.Hoogle as Hoogle import System.Directory import System.IO +import qualified Safe as S hsimportDescriptor :: PluginId -> PluginDescriptor hsimportDescriptor plId = PluginDescriptor @@ -43,19 +41,61 @@ hsimportDescriptor plId = PluginDescriptor , pluginFormattingProvider = Nothing } +data SymbolType + = Symbol + | Constructor + | Type + deriving (Show, Eq, Generics.Generic, ToJSON, FromJSON) + + +-- | What of the symbol should be taken. +data SymbolKind + = Only SymbolName -- ^ only the symbol should be taken + | AllOf DatatypeName -- ^ all constructors or methods of the symbol should be taken: Symbol(..) + | OneOf DatatypeName SymbolName -- ^ some constructors or methods of the symbol should be taken: Symbol(X, Y) + deriving (Show, Eq, Generics.Generic, ToJSON, FromJSON) + +-- | The imported or from the import hidden symbol. +data SymbolImport a + = Import a -- ^ the symbol to import + | Hiding a -- ^ the symbol to hide from the import + deriving (Show, Eq, Generics.Generic, ToJSON, FromJSON) + + +extractSymbolImport :: SymbolImport a -> a +extractSymbolImport (Hiding s) = s +extractSymbolImport (Import s) = s + +type ModuleName = T.Text +type SymbolName = T.Text +type DatatypeName = T.Text + +data ImportStyle + = Simple -- ^ Import the whole module + | Complex (SymbolImport SymbolKind) -- ^ Complex operation, import module hiding symbols or import only selected symbols. + deriving (Show, Eq, Generics.Generic, ToJSON, FromJSON) + +data ImportDiagnostic = ImportDiagnostic + { diagnostic :: J.Diagnostic + , term :: SymbolName + , termType :: SymbolImport SymbolType + } + deriving (Show, Eq, Generics.Generic, ToJSON, FromJSON) + + -- | Import Parameters for Modules. -- Can be used to import every symbol from a module, -- or to import only a specific function from a module. data ImportParams = ImportParams - { file :: Uri -- ^ Uri to the file to import the module to. - , addToImportList :: Maybe T.Text -- ^ If set, an import-list will be created. - , moduleToImport :: T.Text -- ^ Name of the module to import. + { file :: Uri -- ^ Uri to the file to import the module to. + , importStyle :: ImportStyle -- ^ How to import the module + , moduleToImport :: ModuleName -- ^ Name of the module to import. } deriving (Show, Eq, Generics.Generic, ToJSON, FromJSON) importCmd :: CommandFunc ImportParams J.WorkspaceEdit -importCmd = CmdSync $ \(ImportParams uri importList modName) -> - importModule uri importList modName +importCmd = CmdSync $ \(ImportParams uri style modName) -> + importModule uri style modName -- | Import the given module for the given file. -- May take an explicit function name to perform an import-list import. @@ -63,8 +103,8 @@ importCmd = CmdSync $ \(ImportParams uri importList modName) -> -- e.g. two consecutive imports for the same module will result in a single -- import line. importModule - :: Uri -> Maybe T.Text -> T.Text -> IdeGhcM (IdeResult J.WorkspaceEdit) -importModule uri importList modName = + :: Uri -> ImportStyle -> ModuleName -> IdeGhcM (IdeResult J.WorkspaceEdit) +importModule uri impStyle modName = pluginGetFile "hsimport cmd: " uri $ \origInput -> do shouldFormat <- formatOnImportOn <$> getConfig fileMap <- GM.mkRevRedirMapFunc @@ -73,13 +113,9 @@ importModule uri importList modName = tmpDir <- liftIO getTemporaryDirectory (output, outputH) <- liftIO $ openTempFile tmpDir "hsimportOutput" liftIO $ hClose outputH - let args = defaultArgs { moduleName = T.unpack modName - , inputSrcFile = input - , symbolName = T.unpack $ fromMaybe "" importList - , outputSrcFile = output - } + let args = importStyleToHsImportArgs input output modName impStyle -- execute hsimport on the given file and write into a temporary file. - maybeErr <- liftIO $ hsimportWithArgs defaultConfig args + maybeErr <- liftIO $ HsImport.hsimportWithArgs HsImport.defaultConfig args case maybeErr of Just err -> do liftIO $ removeFile output @@ -153,6 +189,29 @@ importModule uri importList modName = $ IdeResultOk (J.WorkspaceEdit newChanges newDocChanges) else return $ IdeResultOk (J.WorkspaceEdit mChanges mDocChanges) +importStyleToHsImportArgs + :: FilePath -> FilePath -> ModuleName -> ImportStyle -> HsImport.HsImportArgs +importStyleToHsImportArgs input output modName style = + let defaultArgs = + HsImport.defaultArgs { HsImport.moduleName = T.unpack modName + , HsImport.inputSrcFile = input + , HsImport.outputSrcFile = output + } + kindToArgs kind = case kind of + Only sym -> defaultArgs { HsImport.symbolName = T.unpack sym } + OneOf dt sym -> defaultArgs { HsImport.symbolName = T.unpack dt + , HsImport.with = [T.unpack sym] + } + AllOf dt -> defaultArgs { HsImport.symbolName = T.unpack dt + , HsImport.all = True + } + in case style of + Simple -> defaultArgs + Complex s -> case s of + Hiding kind -> kindToArgs kind {- TODO: wait for hsimport version bump -} + Import kind -> kindToArgs kind + + -- | Search style for Hoogle. -- Can be used to look either for the exact term, -- only the exact name or a relaxed form of the term. @@ -188,28 +247,23 @@ codeActionProvider plId docId _ context = do -- -- Result may produce several import actions, or none. importActionsForTerms - :: SearchStyle -> [(J.Diagnostic, T.Text)] -> IdeM [J.CodeAction] - importActionsForTerms style terms = do - let searchTerms = map (bimap id (applySearchStyle style)) terms - -- Get the function names for a nice import-list title. - let functionNames = map (head . T.words . snd) terms - searchResults' <- mapM (bimapM return Hoogle.searchModules) searchTerms - let searchResults = zip functionNames searchResults' - let normalise = - concatMap (\(a, b) -> zip (repeat a) (concatTerms b)) searchResults - - concat <$> mapM (uncurry (termToActions style)) normalise + :: SearchStyle -> [ImportDiagnostic] -> IdeM [J.CodeAction] + importActionsForTerms style importDiagnostics = do + let searchTerms = map (applySearchStyle style . term) importDiagnostics + searchResults <- mapM Hoogle.searchModules searchTerms + let importTerms = zip searchResults importDiagnostics + concat <$> mapM (uncurry (termToActions style)) importTerms -- | Apply the search style to given term. -- Can be used to look for a term that matches exactly the search term, -- or one that matches only the exact name. -- At last, a custom relaxation function can be passed for more control. applySearchStyle :: SearchStyle -> T.Text -> T.Text - applySearchStyle Exact term = "is:exact " <> term - applySearchStyle ExactName term = case T.words term of - [] -> term + applySearchStyle Exact termName = "is:exact " <> termName + applySearchStyle ExactName termName = case T.words termName of + [] -> termName (x : _) -> "is:exact " <> x - applySearchStyle (Relax relax) term = relax term + applySearchStyle (Relax relax) termName = relax termName -- | Turn a search term with function name into Import Actions. -- Function name may be of only the exact phrase to import. @@ -224,55 +278,121 @@ codeActionProvider plId docId _ context = do -- no import list can be offered, since the function name -- may be not the one we expect. termToActions - :: SearchStyle -> T.Text -> (J.Diagnostic, T.Text) -> IdeM [J.CodeAction] - termToActions style functionName (diagnostic, termName) = do - let useImportList = case style of - Relax _ -> Nothing - _ -> Just (mkImportAction (Just functionName) diagnostic termName) - catMaybes <$> sequenceA - (mkImportAction Nothing diagnostic termName : maybeToList useImportList) + :: SearchStyle -> [ModuleName] -> ImportDiagnostic -> IdeM [J.CodeAction] + termToActions style modules impDiagnostic = + concat <$> mapM (importModuleAction style impDiagnostic) modules + + importModuleAction + :: SearchStyle -> ImportDiagnostic -> ModuleName -> IdeM [J.CodeAction] + importModuleAction searchStyle impDiagnostic moduleName = + catMaybes <$> sequenceA codeActions + where + importListActions :: [IdeM (Maybe J.CodeAction)] + importListActions = case searchStyle of + Relax _ -> [] + _ -> catMaybes + $ case extractSymbolImport $ termType impDiagnostic of + Symbol + -> [ mkImportAction moduleName impDiagnostic . Just . Only + <$> symName (term impDiagnostic) + ] + Constructor + -> [ mkImportAction moduleName impDiagnostic . Just . AllOf + <$> datatypeName (term impDiagnostic) + , (\dt sym -> mkImportAction moduleName impDiagnostic . Just + $ OneOf dt sym) + <$> datatypeName (term impDiagnostic) + <*> symName (term impDiagnostic) + ] + Type + -> [ mkImportAction moduleName impDiagnostic . Just . Only + <$> symName (term impDiagnostic)] + + codeActions :: [IdeM (Maybe J.CodeAction)] + codeActions = case termType impDiagnostic of + Hiding _ -> [] + Import _ -> [mkImportAction moduleName impDiagnostic Nothing] + ++ importListActions + + signatureOf :: T.Text -> Maybe T.Text + signatureOf sig = do + let parts = T.splitOn "::" sig + typeSig <- S.tailMay parts + S.headMay typeSig + + datatypeName :: T.Text -> Maybe T.Text + datatypeName sig = do + sig_ <- signatureOf sig + let sigParts = T.splitOn "->" sig_ + lastPart <- S.lastMay sigParts + let dtNameSig = T.words lastPart + qualifiedDtName <- S.headMay dtNameSig + let qualifiedDtNameParts = T.splitOn "." qualifiedDtName + S.lastMay qualifiedDtNameParts + + symName :: T.Text -> Maybe SymbolName + symName = S.headMay . T.words - concatTerms :: (a, [b]) -> [(a, b)] - concatTerms (a, b) = zip (repeat a) b --TODO: Check if package is already installed mkImportAction - :: Maybe T.Text -> J.Diagnostic -> T.Text -> IdeM (Maybe J.CodeAction) - mkImportAction importList diag modName = do + :: ModuleName -> ImportDiagnostic -> Maybe SymbolKind -> IdeM (Maybe J.CodeAction) + mkImportAction modName importDiagnostic symbolType = do cmd <- mkLspCommand plId "import" title (Just cmdParams) return (Just (codeAction cmd)) where codeAction cmd = J.CodeAction title (Just J.CodeActionQuickFix) - (Just (J.List [diag])) + (Just (J.List [diagnostic importDiagnostic])) Nothing (Just cmd) - title = - "Import module " - <> modName - <> maybe "" (\name -> " (" <> name <> ")") importList - cmdParams = [toJSON (ImportParams (docId ^. J.uri) importList modName)] + title = "Import module " + <> modName + <> case termType importDiagnostic of + Hiding _ -> "hiding " + Import _ -> "" + <> case symbolType of + Just s -> case s of + Only sym -> "(" <> sym <> ")" + AllOf dt -> "(" <> dt <> " (..))" + OneOf dt sym -> "(" <> dt <> " (" <> sym <> "))" + Nothing -> "" + + importStyleParam :: ImportStyle + importStyleParam = case symbolType of + Nothing -> Simple + Just k -> case termType importDiagnostic of + Hiding _ -> Complex (Hiding k) + Import _ -> Complex (Import k) + + cmdParams = [toJSON (ImportParams (docId ^. J.uri) importStyleParam modName)] -- | For a Diagnostic, get an associated function name. -- If Ghc-Mod can not find any candidates, Nothing is returned. - getImportables :: J.Diagnostic -> Maybe (J.Diagnostic, T.Text) + getImportables :: J.Diagnostic -> Maybe ImportDiagnostic getImportables diag@(J.Diagnostic _ _ _ (Just "ghcmod") msg _) = - (diag, ) <$> extractImportableTerm msg + uncurry (ImportDiagnostic diag) <$> extractImportableTerm msg getImportables _ = Nothing -- | Extract from an error message an appropriate term to search for. -- This looks at the error message and tries to extract the expected -- signature of an unknown function. -- If this is not possible, Nothing is returned. -extractImportableTerm :: T.Text -> Maybe T.Text -extractImportableTerm dirtyMsg = T.strip <$> asum - [ T.stripPrefix "Variable not in scope: " msg - , T.init <$> T.stripPrefix "Not in scope: type constructor or class ‘" msg - , T.stripPrefix "Data constructor not in scope: " msg - ] +extractImportableTerm :: T.Text -> Maybe (T.Text, (SymbolImport SymbolType) ) +extractImportableTerm dirtyMsg = + let extractedTerm = + asum + [ (\name -> (name, Import Symbol)) <$> T.stripPrefix "Variable not in scope: " importMsg + , (\name -> (T.init name, Import Type)) <$> T.stripPrefix "Not in scope: type constructor or class ‘" importMsg + , (\name -> (name, Import Constructor)) <$> T.stripPrefix "Data constructor not in scope: " importMsg + ] + in do + (n, s) <- extractedTerm + let n' = T.strip n + return (n', s) where - msg = + importMsg = head -- Get rid of the rename suggestion parts $ T.splitOn "Perhaps you meant " From 07822b472e0495a1819008362e53ad07e670fdc6 Mon Sep 17 00:00:00 2001 From: fendor Date: Tue, 4 Jun 2019 13:25:30 +0200 Subject: [PATCH 014/158] Add documentation for hsimport plugin --- src/Haskell/Ide/Engine/Plugin/HsImport.hs | 87 +++++++++++++++++++---- 1 file changed, 75 insertions(+), 12 deletions(-) diff --git a/src/Haskell/Ide/Engine/Plugin/HsImport.hs b/src/Haskell/Ide/Engine/Plugin/HsImport.hs index 0a5a663f6..bfdf77ec4 100644 --- a/src/Haskell/Ide/Engine/Plugin/HsImport.hs +++ b/src/Haskell/Ide/Engine/Plugin/HsImport.hs @@ -41,27 +41,35 @@ hsimportDescriptor plId = PluginDescriptor , pluginFormattingProvider = Nothing } +-- | Type of the symbol to import. +-- Important to offer the correct import list, or hiding code action. data SymbolType - = Symbol - | Constructor - | Type + = Symbol -- ^ Symbol is a simple function + | Constructor -- ^ Symbol is a constructor + | Type -- ^ Symbol is a type deriving (Show, Eq, Generics.Generic, ToJSON, FromJSON) -- | What of the symbol should be taken. +-- Import a simple symbol, or a value constructor. data SymbolKind - = Only SymbolName -- ^ only the symbol should be taken - | AllOf DatatypeName -- ^ all constructors or methods of the symbol should be taken: Symbol(..) - | OneOf DatatypeName SymbolName -- ^ some constructors or methods of the symbol should be taken: Symbol(X, Y) + = Only SymbolName -- ^ Only the symbol should be taken + | OneOf DatatypeName SymbolName -- ^ Some constructors or methods of the symbol should be taken: Symbol(X) + | AllOf DatatypeName -- ^ All constructors or methods of the symbol should be taken: Symbol(..) deriving (Show, Eq, Generics.Generic, ToJSON, FromJSON) --- | The imported or from the import hidden symbol. +-- | Disambiguates between an import action and an hiding action. +-- Can be used to determine suggestion tpye from ghc-mod, +-- e.g. whether ghc-mod suggests to hide an identifier or to import an identifier. +-- Also important later, to know how the symbol shall be imported. data SymbolImport a = Import a -- ^ the symbol to import | Hiding a -- ^ the symbol to hide from the import deriving (Show, Eq, Generics.Generic, ToJSON, FromJSON) +-- | Utility to retrieve the contents of the 'SymbolImport'. +-- May never fail. extractSymbolImport :: SymbolImport a -> a extractSymbolImport (Hiding s) = s extractSymbolImport (Import s) = s @@ -70,11 +78,19 @@ type ModuleName = T.Text type SymbolName = T.Text type DatatypeName = T.Text +-- | How to import a module. +-- Can be used to express to import a whole module or only specific symbols +-- from a module. +-- Is used to either hide symbols from an import or use an import-list to +-- import only a specific symbol. data ImportStyle = Simple -- ^ Import the whole module | Complex (SymbolImport SymbolKind) -- ^ Complex operation, import module hiding symbols or import only selected symbols. deriving (Show, Eq, Generics.Generic, ToJSON, FromJSON) +-- | Contains information about the diagnostic, the symbol ghc-mod +-- complained about and what the kind of the symbol is and whether +-- to import or hide the symbol as suggested by ghc-mod. data ImportDiagnostic = ImportDiagnostic { diagnostic :: J.Diagnostic , term :: SymbolName @@ -82,7 +98,6 @@ data ImportDiagnostic = ImportDiagnostic } deriving (Show, Eq, Generics.Generic, ToJSON, FromJSON) - -- | Import Parameters for Modules. -- Can be used to import every symbol from a module, -- or to import only a specific function from a module. @@ -189,23 +204,31 @@ importModule uri impStyle modName = $ IdeResultOk (J.WorkspaceEdit newChanges newDocChanges) else return $ IdeResultOk (J.WorkspaceEdit mChanges mDocChanges) +-- | Convert the import style arguments into HsImport arguments. +-- Takes an input and an output file as well as a module name. importStyleToHsImportArgs :: FilePath -> FilePath -> ModuleName -> ImportStyle -> HsImport.HsImportArgs importStyleToHsImportArgs input output modName style = - let defaultArgs = + let defaultArgs = -- Default args, must be set every time. HsImport.defaultArgs { HsImport.moduleName = T.unpack modName , HsImport.inputSrcFile = input , HsImport.outputSrcFile = output } + + kindToArgs :: SymbolKind -> HsImport.HsImportArgs kindToArgs kind = case kind of + -- Only import a single symbol e.g. Data.Text (isPrefixOf) Only sym -> defaultArgs { HsImport.symbolName = T.unpack sym } + -- Import a constructor e.g. Data.Mabye (Maybe(Just)) OneOf dt sym -> defaultArgs { HsImport.symbolName = T.unpack dt , HsImport.with = [T.unpack sym] } + -- Import all constructors e.g. Data.Maybe (Maybe(..)) AllOf dt -> defaultArgs { HsImport.symbolName = T.unpack dt , HsImport.all = True } in case style of + -- If the import style is simple, import thw whole module Simple -> defaultArgs Complex s -> case s of Hiding kind -> kindToArgs kind {- TODO: wait for hsimport version bump -} @@ -265,8 +288,8 @@ codeActionProvider plId docId _ context = do (x : _) -> "is:exact " <> x applySearchStyle (Relax relax) termName = relax termName - -- | Turn a search term with function name into Import Actions. - -- Function name may be of only the exact phrase to import. + -- | Turn a search term with function name into an Import Actions. + -- The function name may be of only the exact phrase to import. -- The resulting CodeAction's contain a general import of a module or -- uses an Import-List. -- @@ -282,6 +305,12 @@ codeActionProvider plId docId _ context = do termToActions style modules impDiagnostic = concat <$> mapM (importModuleAction style impDiagnostic) modules + -- | Creates various import actions for a module and the diagnostic. + -- Possible import actions depend on the type of the symbol to import. + -- It may be a 'Constructor', so the import actions need to be different + -- to a simple function symbol. + -- Thus, it may return zero, one or multiple import actions for a module. + -- List of import actions does contain no duplicates. importModuleAction :: SearchStyle -> ImportDiagnostic -> ModuleName -> IdeM [J.CodeAction] importModuleAction searchStyle impDiagnostic moduleName = @@ -289,13 +318,22 @@ codeActionProvider plId docId _ context = do where importListActions :: [IdeM (Maybe J.CodeAction)] importListActions = case searchStyle of + -- If the search has been relaxed by a custom function, + -- we cant know how much the search query has been altered + -- and how close the result terms are to the initial diagnostic. + -- Thus, we cant offer more specific imports. Relax _ -> [] _ -> catMaybes $ case extractSymbolImport $ termType impDiagnostic of + -- If the term to import is a simple symbol, such as a function, + -- import only this function Symbol -> [ mkImportAction moduleName impDiagnostic . Just . Only <$> symName (term impDiagnostic) ] + -- Constructors can be imported in two ways, either all + -- constructors of a type or only a subset. + -- We can only import a single constructor at a time though. Constructor -> [ mkImportAction moduleName impDiagnostic . Just . AllOf <$> datatypeName (term impDiagnostic) @@ -304,22 +342,43 @@ codeActionProvider plId docId _ context = do <$> datatypeName (term impDiagnostic) <*> symName (term impDiagnostic) ] + -- If we are looking for a type, import it as just a symbol Type -> [ mkImportAction moduleName impDiagnostic . Just . Only <$> symName (term impDiagnostic)] + -- | All code actions that may be available + -- Currently, omits all codeActions :: [IdeM (Maybe J.CodeAction)] codeActions = case termType impDiagnostic of - Hiding _ -> [] + Hiding _ -> [] {- If we are hiding an import, we can not import + a module hiding everything from it. -} Import _ -> [mkImportAction moduleName impDiagnostic Nothing] + -- ^ Simple import, import the whole module ++ importListActions + -- | Retrieve the function signature of a term such as + -- >>> signatureOf "take :: Int -> [a] -> [a]" + -- Just " Int -> [a] -> [a]" signatureOf :: T.Text -> Maybe T.Text signatureOf sig = do let parts = T.splitOn "::" sig typeSig <- S.tailMay parts S.headMay typeSig + -- | Retrieve the datatype name of a Constructor. + -- + -- >>> datatypeName "Null :: Data.Aeson.Internal.Types.Value" + -- Just "Value" + -- + -- >>> datatypeName "take :: Int -> [a] -> [a]" -- Not a constructor + -- Just "[a]" + -- + -- >>> datatypeName "Just :: a -> Maybe a" + -- Just "Maybe" + -- + -- Thus, the result of this function only makes sense, + -- if the symbol kind of the diagnostic term is of type 'Constructor' datatypeName :: T.Text -> Maybe T.Text datatypeName sig = do sig_ <- signatureOf sig @@ -330,6 +389,10 @@ codeActionProvider plId docId _ context = do let qualifiedDtNameParts = T.splitOn "." qualifiedDtName S.lastMay qualifiedDtNameParts + -- | Name of a symbol. May contain a function signature. + -- + -- >>> symName "take :: Int -> [a] -> [a]" + -- Just "take" symName :: T.Text -> Maybe SymbolName symName = S.headMay . T.words From 3835a09db92c3a3c4f0761e50cd22e70f191c603 Mon Sep 17 00:00:00 2001 From: fendor Date: Tue, 4 Jun 2019 17:55:33 +0200 Subject: [PATCH 015/158] Fix tests, add documentation and add newtypes --- src/Haskell/Ide/Engine/Plugin/HsImport.hs | 57 +++++++++++++++-------- test/unit/CodeActionsSpec.hs | 15 +++--- 2 files changed, 46 insertions(+), 26 deletions(-) diff --git a/src/Haskell/Ide/Engine/Plugin/HsImport.hs b/src/Haskell/Ide/Engine/Plugin/HsImport.hs index bfdf77ec4..8827bc7f8 100644 --- a/src/Haskell/Ide/Engine/Plugin/HsImport.hs +++ b/src/Haskell/Ide/Engine/Plugin/HsImport.hs @@ -78,6 +78,12 @@ type ModuleName = T.Text type SymbolName = T.Text type DatatypeName = T.Text +-- | Wrapper for a FilePath that is used as an Input file for HsImport +newtype InputFilePath = MkInputFilePath { getInput :: FilePath } + +-- | Wrapper for a FilePath that is used as an Output file for HsImport +newtype OutputFilePath = MkOutputFilePath { getOutput :: FilePath } + -- | How to import a module. -- Can be used to express to import a whole module or only specific symbols -- from a module. @@ -128,7 +134,11 @@ importModule uri impStyle modName = tmpDir <- liftIO getTemporaryDirectory (output, outputH) <- liftIO $ openTempFile tmpDir "hsimportOutput" liftIO $ hClose outputH - let args = importStyleToHsImportArgs input output modName impStyle + let args = importStyleToHsImportArgs + (MkInputFilePath input) + (MkOutputFilePath output) + modName + impStyle -- execute hsimport on the given file and write into a temporary file. maybeErr <- liftIO $ HsImport.hsimportWithArgs HsImport.defaultConfig args case maybeErr of @@ -207,12 +217,12 @@ importModule uri impStyle modName = -- | Convert the import style arguments into HsImport arguments. -- Takes an input and an output file as well as a module name. importStyleToHsImportArgs - :: FilePath -> FilePath -> ModuleName -> ImportStyle -> HsImport.HsImportArgs + :: InputFilePath -> OutputFilePath -> ModuleName -> ImportStyle -> HsImport.HsImportArgs importStyleToHsImportArgs input output modName style = let defaultArgs = -- Default args, must be set every time. HsImport.defaultArgs { HsImport.moduleName = T.unpack modName - , HsImport.inputSrcFile = input - , HsImport.outputSrcFile = output + , HsImport.inputSrcFile = getInput input + , HsImport.outputSrcFile = getOutput output } kindToArgs :: SymbolKind -> HsImport.HsImportArgs @@ -393,6 +403,9 @@ codeActionProvider plId docId _ context = do -- -- >>> symName "take :: Int -> [a] -> [a]" -- Just "take" + -- + -- >>> symName "take" + -- Just "take" symName :: T.Text -> Maybe SymbolName symName = S.headMay . T.words @@ -403,7 +416,7 @@ codeActionProvider plId docId _ context = do mkImportAction modName importDiagnostic symbolType = do cmd <- mkLspCommand plId "import" title (Just cmdParams) return (Just (codeAction cmd)) - where + where codeAction cmd = J.CodeAction title (Just J.CodeActionQuickFix) (Just (J.List [diagnostic importDiagnostic])) @@ -413,6 +426,8 @@ codeActionProvider plId docId _ context = do <> modName <> case termType importDiagnostic of Hiding _ -> "hiding " + -- ^ Note, that it must never happen + -- in combination with `symbolType == Nothing` Import _ -> "" <> case symbolType of Just s -> case s of @@ -442,25 +457,27 @@ codeActionProvider plId docId _ context = do -- This looks at the error message and tries to extract the expected -- signature of an unknown function. -- If this is not possible, Nothing is returned. -extractImportableTerm :: T.Text -> Maybe (T.Text, (SymbolImport SymbolType) ) +extractImportableTerm :: T.Text -> Maybe (T.Text, SymbolImport SymbolType) extractImportableTerm dirtyMsg = - let extractedTerm = - asum - [ (\name -> (name, Import Symbol)) <$> T.stripPrefix "Variable not in scope: " importMsg - , (\name -> (T.init name, Import Type)) <$> T.stripPrefix "Not in scope: type constructor or class ‘" importMsg - , (\name -> (name, Import Constructor)) <$> T.stripPrefix "Data constructor not in scope: " importMsg - ] + let extractedTerm = asum + [ (\name -> (name, Import Symbol)) + <$> T.stripPrefix "Variable not in scope: " importMsg + , (\name -> (T.init name, Import Type)) + <$> T.stripPrefix + "Not in scope: type constructor or class ‘" + importMsg + , (\name -> (name, Import Constructor)) + <$> T.stripPrefix "Data constructor not in scope: " importMsg] in do - (n, s) <- extractedTerm - let n' = T.strip n - return (n', s) - where - importMsg = - head - -- Get rid of the rename suggestion parts + (n, s) <- extractedTerm + let n' = T.strip n + return (n', s) + where + importMsg = head + -- Get rid of the rename suggestion parts $ T.splitOn "Perhaps you meant " $ T.replace "\n" " " - -- Get rid of trailing/leading whitespace on each individual line + -- Get rid of trailing/leading whitespace on each individual line $ T.unlines $ map T.strip $ T.lines diff --git a/test/unit/CodeActionsSpec.hs b/test/unit/CodeActionsSpec.hs index 2c5738cdb..73c2347eb 100644 --- a/test/unit/CodeActionsSpec.hs +++ b/test/unit/CodeActionsSpec.hs @@ -15,19 +15,22 @@ spec = do describe "import code actions" $ do it "pick up variable not in scope" $ let msg = "Variable not in scope: fromJust :: Maybe Integer -> t" - in extractImportableTerm msg `shouldBe` Just "fromJust :: Maybe Integer -> t" + in extractImportableTerm msg `shouldBe` Just ("fromJust :: Maybe Integer -> t", Import Symbol) it "pick up variable not in scope with 'perhaps you meant'" $ let msg = "• Variable not in scope: msgs :: T.Text\n• Perhaps you meant ‘msg’ (line 90)" - in extractImportableTerm msg `shouldBe` Just "msgs :: T.Text" + in extractImportableTerm msg `shouldBe` Just ("msgs :: T.Text", Import Symbol) it "pick up multi-line variable not in scope" $ let msg = "Variable not in scope:\nliftIO\n:: IO [FilePath]\n-> GhcMod.Monad.Newtypes.GmT\n (GhcMod.Monad.Newtypes.GmOutT IdeM) [[t0]]" - in extractImportableTerm msg `shouldBe` Just "liftIO :: IO [FilePath] -> GhcMod.Monad.Newtypes.GmT (GhcMod.Monad.Newtypes.GmOutT IdeM) [[t0]]" + in extractImportableTerm msg `shouldBe` Just ("liftIO :: IO [FilePath] -> GhcMod.Monad.Newtypes.GmT (GhcMod.Monad.Newtypes.GmOutT IdeM) [[t0]]", Import Symbol) it "pick up when" $ let msg = "Variable not in scope: when :: Bool -> IO () -> t" - in extractImportableTerm msg `shouldBe` Just "when :: Bool -> IO () -> t" + in extractImportableTerm msg `shouldBe` Just ("when :: Bool -> IO () -> t", Import Symbol) it "pick up data constructors" $ let msg = "Data constructor not in scope: ExitFailure :: Integer -> t" - in extractImportableTerm msg `shouldBe` Just "ExitFailure :: Integer -> t" + in extractImportableTerm msg `shouldBe` Just ("ExitFailure :: Integer -> t", Import Constructor) + it "pick up type" $ + let msg = "Not in scope: type constructor or class ‘Text" + in extractImportableTerm msg `shouldBe` Just ("Text", Import Type) describe "rename code actions" $ do it "pick up variable not in scope perhaps you meant" $ @@ -146,7 +149,7 @@ spec = do \ Text.Megaparsec.Error.ShowErrorComponent e, Ord t) =>\n\ \ OutputFormat -> Format.Result t e -> IO b" in extractMissingSignature msg `shouldBe` Just expected - + describe "unused term code actions" $ do it "pick up unused term" $ let msg = " Defined but not used: ‘imUnused’" From 25cb23801697b6a8f96c87c6d7d58194e421584e Mon Sep 17 00:00:00 2001 From: fendor Date: Tue, 4 Jun 2019 19:09:33 +0200 Subject: [PATCH 016/158] Use correct datatype --- src/Haskell/Ide/Engine/Plugin/Hoogle.hs | 14 +++++++++++++- src/Haskell/Ide/Engine/Plugin/HsImport.hs | 20 ++++++++++---------- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/Haskell/Ide/Engine/Plugin/Hoogle.hs b/src/Haskell/Ide/Engine/Plugin/Hoogle.hs index de8401cc5..81d356897 100644 --- a/src/Haskell/Ide/Engine/Plugin/Hoogle.hs +++ b/src/Haskell/Ide/Engine/Plugin/Hoogle.hs @@ -152,7 +152,19 @@ renderTarget t = T.intercalate "\n" $ -- If an error occurs, such as no hoogle database has been found, -- or the search term has no match, an empty list will be returned. searchModules :: T.Text -> IdeM [T.Text] -searchModules = fmap (nub . take 5) . searchTargets (fmap (T.pack . fst) . targetModule) +searchModules = fmap (map fst) . searchModules' + +-- | Just like 'searchModules', but includes the signature of the search term +-- that has been found in the module. +searchModules' :: T.Text -> IdeM [(T.Text, T.Text)] +searchModules' = fmap (nub . take 5) + . searchTargets + (\target + -> (\modTarget -> (T.pack $ fst modTarget, normaliseItem . T.pack $ targetItem target)) + <$> targetModule target) + where + normaliseItem :: T.Text -> T.Text + normaliseItem = innerText . parseTags -- | Search for packages that satisfy the given search text. -- Will return at most five, unique results. diff --git a/src/Haskell/Ide/Engine/Plugin/HsImport.hs b/src/Haskell/Ide/Engine/Plugin/HsImport.hs index 8827bc7f8..b2f901e51 100644 --- a/src/Haskell/Ide/Engine/Plugin/HsImport.hs +++ b/src/Haskell/Ide/Engine/Plugin/HsImport.hs @@ -283,7 +283,7 @@ codeActionProvider plId docId _ context = do :: SearchStyle -> [ImportDiagnostic] -> IdeM [J.CodeAction] importActionsForTerms style importDiagnostics = do let searchTerms = map (applySearchStyle style . term) importDiagnostics - searchResults <- mapM Hoogle.searchModules searchTerms + searchResults <- mapM Hoogle.searchModules' searchTerms let importTerms = zip searchResults importDiagnostics concat <$> mapM (uncurry (termToActions style)) importTerms @@ -311,9 +311,9 @@ codeActionProvider plId docId _ context = do -- no import list can be offered, since the function name -- may be not the one we expect. termToActions - :: SearchStyle -> [ModuleName] -> ImportDiagnostic -> IdeM [J.CodeAction] + :: SearchStyle -> [(ModuleName, SymbolName)] -> ImportDiagnostic -> IdeM [J.CodeAction] termToActions style modules impDiagnostic = - concat <$> mapM (importModuleAction style impDiagnostic) modules + concat <$> mapM (uncurry (importModuleAction style impDiagnostic)) modules -- | Creates various import actions for a module and the diagnostic. -- Possible import actions depend on the type of the symbol to import. @@ -322,8 +322,8 @@ codeActionProvider plId docId _ context = do -- Thus, it may return zero, one or multiple import actions for a module. -- List of import actions does contain no duplicates. importModuleAction - :: SearchStyle -> ImportDiagnostic -> ModuleName -> IdeM [J.CodeAction] - importModuleAction searchStyle impDiagnostic moduleName = + :: SearchStyle -> ImportDiagnostic -> ModuleName -> SymbolName -> IdeM [J.CodeAction] + importModuleAction searchStyle impDiagnostic moduleName symbolTerm = catMaybes <$> sequenceA codeActions where importListActions :: [IdeM (Maybe J.CodeAction)] @@ -339,23 +339,23 @@ codeActionProvider plId docId _ context = do -- import only this function Symbol -> [ mkImportAction moduleName impDiagnostic . Just . Only - <$> symName (term impDiagnostic) + <$> symName symbolTerm ] -- Constructors can be imported in two ways, either all -- constructors of a type or only a subset. -- We can only import a single constructor at a time though. Constructor -> [ mkImportAction moduleName impDiagnostic . Just . AllOf - <$> datatypeName (term impDiagnostic) + <$> datatypeName symbolTerm , (\dt sym -> mkImportAction moduleName impDiagnostic . Just $ OneOf dt sym) - <$> datatypeName (term impDiagnostic) - <*> symName (term impDiagnostic) + <$> datatypeName symbolTerm + <*> symName symbolTerm ] -- If we are looking for a type, import it as just a symbol Type -> [ mkImportAction moduleName impDiagnostic . Just . Only - <$> symName (term impDiagnostic)] + <$> symName symbolTerm] -- | All code actions that may be available -- Currently, omits all From 3fe7f872cd1938c6d53404e969f32129dba3771c Mon Sep 17 00:00:00 2001 From: fendor Date: Tue, 4 Jun 2019 19:44:40 +0200 Subject: [PATCH 017/158] Remove parenthesis for hsimport --- src/Haskell/Ide/Engine/Plugin/HsImport.hs | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/Haskell/Ide/Engine/Plugin/HsImport.hs b/src/Haskell/Ide/Engine/Plugin/HsImport.hs index b2f901e51..04edcb508 100644 --- a/src/Haskell/Ide/Engine/Plugin/HsImport.hs +++ b/src/Haskell/Ide/Engine/Plugin/HsImport.hs @@ -225,16 +225,28 @@ importStyleToHsImportArgs input output modName style = , HsImport.outputSrcFile = getOutput output } + -- | Remove parenthesis for operators and infix operator cosntructors. + -- HsImport demands it. E.g. + -- > hsimport -m Data.Array.Repa -s :. -w :. + -- import Data.Array.Repa ((:.)((:.))) + -- + -- > hsimport -m Data.Function -s $ + -- import Data.Function (($)) + trimParenthesis :: T.Text -> T.Text + trimParenthesis = T.dropAround isParenthesis + + isParenthesis = (`elem` ['(', ')']) + kindToArgs :: SymbolKind -> HsImport.HsImportArgs kindToArgs kind = case kind of -- Only import a single symbol e.g. Data.Text (isPrefixOf) - Only sym -> defaultArgs { HsImport.symbolName = T.unpack sym } + Only sym -> defaultArgs { HsImport.symbolName = T.unpack $ trimParenthesis sym } -- Import a constructor e.g. Data.Mabye (Maybe(Just)) - OneOf dt sym -> defaultArgs { HsImport.symbolName = T.unpack dt - , HsImport.with = [T.unpack sym] + OneOf dt sym -> defaultArgs { HsImport.symbolName = T.unpack $ trimParenthesis dt + , HsImport.with = [T.unpack $ trimParenthesis sym] } -- Import all constructors e.g. Data.Maybe (Maybe(..)) - AllOf dt -> defaultArgs { HsImport.symbolName = T.unpack dt + AllOf dt -> defaultArgs { HsImport.symbolName = T.unpack $ trimParenthesis dt , HsImport.all = True } in case style of From a1f0bed59dc78c70dc343e11f57bd53d5ae16c94 Mon Sep 17 00:00:00 2001 From: fendor Date: Tue, 4 Jun 2019 19:45:00 +0200 Subject: [PATCH 018/158] Add testdata file --- test/testdata/CodeActionImportListElaborate.hs | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 test/testdata/CodeActionImportListElaborate.hs diff --git a/test/testdata/CodeActionImportListElaborate.hs b/test/testdata/CodeActionImportListElaborate.hs new file mode 100644 index 000000000..1cf149fd2 --- /dev/null +++ b/test/testdata/CodeActionImportListElaborate.hs @@ -0,0 +1,8 @@ +{-# LANGUAGE NoImplicitPrelude #-} +import System.IO (IO) +-- | Main entry point to the program +main :: IO () +main = + when True + $ hPutStrLn stdout + $ fromMaybe "Good night, World!" (Just "Hello, World!") \ No newline at end of file From 988dcff2eb18edcee0bbed5a10e597f9ca9d1ad9 Mon Sep 17 00:00:00 2001 From: fendor Date: Tue, 4 Jun 2019 19:47:26 +0200 Subject: [PATCH 019/158] Add space to code action title --- src/Haskell/Ide/Engine/Plugin/HsImport.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Haskell/Ide/Engine/Plugin/HsImport.hs b/src/Haskell/Ide/Engine/Plugin/HsImport.hs index 04edcb508..ec0026496 100644 --- a/src/Haskell/Ide/Engine/Plugin/HsImport.hs +++ b/src/Haskell/Ide/Engine/Plugin/HsImport.hs @@ -440,7 +440,7 @@ codeActionProvider plId docId _ context = do Hiding _ -> "hiding " -- ^ Note, that it must never happen -- in combination with `symbolType == Nothing` - Import _ -> "" + Import _ -> " " <> case symbolType of Just s -> case s of Only sym -> "(" <> sym <> ")" From bcac2b52cbcbf3fe4b03ccdb866e830c8f384cc9 Mon Sep 17 00:00:00 2001 From: fendor Date: Tue, 4 Jun 2019 20:04:10 +0200 Subject: [PATCH 020/158] Implement tests for importing constructors --- test/functional/FunctionalCodeActionsSpec.hs | 94 +++++++++++++++++++- 1 file changed, 92 insertions(+), 2 deletions(-) diff --git a/test/functional/FunctionalCodeActionsSpec.hs b/test/functional/FunctionalCodeActionsSpec.hs index 07ab9d6ff..ca2df3d10 100644 --- a/test/functional/FunctionalCodeActionsSpec.hs +++ b/test/functional/FunctionalCodeActionsSpec.hs @@ -153,6 +153,25 @@ spec = describe "code actions" $ do , " $ hPutStrLn stdout" , " $ fromMaybe \"Good night, World!\" (Just \"Hello, World!\")" ] + , -- Complex imports for Constructos and functions + [ "{-# LANGUAGE NoImplicitPrelude #-}" + , "import System.IO ( IO" + , " , hPutStrLn" + , " , stdout" + , " )" + , "import Prelude ( Bool(..) )" + , "import Control.Monad ( when )" + , "import Data.Maybe ( fromMaybe" + , " , Maybe(Just)" + , " )" + , "import Data.Function ( ($) )" + , "-- | Main entry point to the program" + , "main :: IO ()" + , "main =" + , " when True" + , " $ hPutStrLn stdout" + , " $ fromMaybe \"Good night, World!\" (Just \"Hello, World!\")" + ] ] hsImportSpec "floskell" [ -- Expected output for simple format. @@ -178,6 +197,20 @@ spec = describe "code actions" $ do , " $ hPutStrLn stdout" , " $ fromMaybe \"Good night, World!\" (Just \"Hello, World!\")" ] + , -- Complex imports for Constructos and functions + [ "{-# LANGUAGE NoImplicitPrelude #-}" + , "import System.IO (IO, hPutStrLn, stdout)" + , "import Prelude (Bool(..))" + , "import Control.Monad (when)" + , "import Data.Maybe (fromMaybe, Maybe(Just))" + , "import Data.Function (($))" + , "-- | Main entry point to the program" + , "main :: IO ()" + , "main =" + , " when True" + , " $ hPutStrLn stdout" + , " $ fromMaybe \"Good night, World!\" (Just \"Hello, World!\")" + ] ] describe "add package suggestions" $ do -- Only execute this test with ghc 8.4.4, below seems to be broken in the package. @@ -504,7 +537,7 @@ spec = describe "code actions" $ do -- Parameterized HsImport Spec. -- --------------------------------------------------------------------- hsImportSpec :: T.Text -> [[T.Text]]-> Spec -hsImportSpec formatterName [e1, e2, e3] = +hsImportSpec formatterName [e1, e2, e3, e4] = describe ("Execute HsImport with formatter " <> T.unpack formatterName) $ do it "works with 3.8 code action kinds" $ runSession hieCommand fullCaps "test/testdata" $ do doc <- openDoc "CodeActionImport.hs" "haskell" @@ -626,7 +659,7 @@ hsImportSpec formatterName [e1, e2, e3] = l3 `shouldBe` "main :: IO ()" l4 `shouldBe` "main = when True $ putStrLn \"hello\"" - it ("import-list respects format config with " <> T.unpack formatterName) $ runSession hieCommand fullCaps "test/testdata" $ do + it "import-list respects format config" $ runSession hieCommand fullCaps "test/testdata" $ do doc <- openDoc "CodeActionImportBrittany.hs" "haskell" _ <- waitForDiagnosticsSource "ghcmod" @@ -644,6 +677,63 @@ hsImportSpec formatterName [e1, e2, e3] = l2 `shouldBe` "import Control.Monad (when)" l3 `shouldBe` "main :: IO ()" l4 `shouldBe` "main = when True $ putStrLn \"hello\"" + + it "complex import-list" $ runSession hieCommand fullCaps "test/testdata" $ do + doc <- openDoc "CodeActionImportListElaborate.hs" "haskell" + _ <- waitForDiagnosticsSource "ghcmod" + + let config = def { formatOnImportOn = False, formattingProvider = formatterName } + sendNotification WorkspaceDidChangeConfiguration (DidChangeConfigurationParams (toJSON config)) + + let wantedCodeActionTitles = [ "Import module System.IO (hPutSetrLn)" + , "Import module System.IO (stdout)" + , "Import module Control.Monad (when)" + , "Import module Data.Maybe (fromMaybe)" + , "Import module Data.Function (($))" + , "Import module Data.Maybe (Maybe(Just))" + , "Import module Prelude (Bool(..))" + ] + + executeAllCodeActions doc wantedCodeActionTitles + + contents <- getDocumentEdit doc + liftIO $ + T.lines contents `shouldBe` e4 + + it "complex import-list respects format config" $ runSession hieCommand fullCaps "test/testdata" $ do + doc <- openDoc "CodeActionImportListElaborate.hs" "haskell" + _ <- waitForDiagnosticsSource "ghcmod" + + let config = def { formatOnImportOn = False, formattingProvider = formatterName } + sendNotification WorkspaceDidChangeConfiguration (DidChangeConfigurationParams (toJSON config)) + + let wantedCodeActionTitles = [ "Import module System.IO (hPutStrLn)" + , "Import module System.IO (stdout)" + , "Import module Control.Monad (when)" + , "Import module Data.Maybe (fromMaybe)" + , "Import module Data.Function (($))" + , "Import module Data.Maybe (Maybe(Just))" + , "Import module Prelude (Bool(..))" + ] + + executeAllCodeActions doc wantedCodeActionTitles + + contents <- getDocumentEdit doc + liftIO $ do + let [l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12] = T.lines contents + l1 `shouldBe` "{-# LANGUAGE NoImplicitPrelude #-}" + l2 `shouldBe` "import System.IO (IO, hPutStrLn, stdout)" + l3 `shouldBe` "import Prelude (Bool(..))" + l4 `shouldBe` "import Control.Monad (when)" + l5 `shouldBe` "import Data.Maybe (fromMaybe, Maybe(Just))" + l6 `shouldBe` "import Data.Function (($))" + l7 `shouldBe` "-- | Main entry point to the program" + l8 `shouldBe` "main :: IO ()" + l9 `shouldBe` "main =" + l10 `shouldBe` " when True" + l11 `shouldBe` " $ hPutStrLn stdout" + l12 `shouldBe` " $ fromMaybe \"Good night, World!\" (Just \"Hello, World!\")" + where executeAllCodeActions :: TextDocumentIdentifier -> [T.Text] -> Session () executeAllCodeActions doc names = From 8e24b1293f8fe80961cb2bcf44b3b7dd1ecb3db9 Mon Sep 17 00:00:00 2001 From: fendor Date: Tue, 4 Jun 2019 20:59:09 +0200 Subject: [PATCH 021/158] Add spaces to the correct positions --- src/Haskell/Ide/Engine/Plugin/HsImport.hs | 10 +++---- test/functional/FunctionalCodeActionsSpec.hs | 28 +++++++++---------- .../testdata/CodeActionImportListElaborate.hs | 2 +- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/Haskell/Ide/Engine/Plugin/HsImport.hs b/src/Haskell/Ide/Engine/Plugin/HsImport.hs index ec0026496..3ead8eefd 100644 --- a/src/Haskell/Ide/Engine/Plugin/HsImport.hs +++ b/src/Haskell/Ide/Engine/Plugin/HsImport.hs @@ -437,15 +437,15 @@ codeActionProvider plId docId _ context = do title = "Import module " <> modName <> case termType importDiagnostic of - Hiding _ -> "hiding " + Hiding _ -> "hiding" -- ^ Note, that it must never happen -- in combination with `symbolType == Nothing` - Import _ -> " " + Import _ -> "" <> case symbolType of Just s -> case s of - Only sym -> "(" <> sym <> ")" - AllOf dt -> "(" <> dt <> " (..))" - OneOf dt sym -> "(" <> dt <> " (" <> sym <> "))" + Only sym -> " (" <> sym <> ")" + AllOf dt -> " (" <> dt <> " (..))" + OneOf dt sym -> " (" <> dt <> " (" <> sym <> "))" Nothing -> "" importStyleParam :: ImportStyle diff --git a/test/functional/FunctionalCodeActionsSpec.hs b/test/functional/FunctionalCodeActionsSpec.hs index ca2df3d10..0c0fa5103 100644 --- a/test/functional/FunctionalCodeActionsSpec.hs +++ b/test/functional/FunctionalCodeActionsSpec.hs @@ -157,7 +157,7 @@ spec = describe "code actions" $ do [ "{-# LANGUAGE NoImplicitPrelude #-}" , "import System.IO ( IO" , " , hPutStrLn" - , " , stdout" + , " , stderr" , " )" , "import Prelude ( Bool(..) )" , "import Control.Monad ( when )" @@ -169,7 +169,7 @@ spec = describe "code actions" $ do , "main :: IO ()" , "main =" , " when True" - , " $ hPutStrLn stdout" + , " $ hPutStrLn stderr" , " $ fromMaybe \"Good night, World!\" (Just \"Hello, World!\")" ] ] @@ -199,7 +199,7 @@ spec = describe "code actions" $ do ] , -- Complex imports for Constructos and functions [ "{-# LANGUAGE NoImplicitPrelude #-}" - , "import System.IO (IO, hPutStrLn, stdout)" + , "import System.IO (IO, hPutStrLn, stderr)" , "import Prelude (Bool(..))" , "import Control.Monad (when)" , "import Data.Maybe (fromMaybe, Maybe(Just))" @@ -208,7 +208,7 @@ spec = describe "code actions" $ do , "main :: IO ()" , "main =" , " when True" - , " $ hPutStrLn stdout" + , " $ hPutStrLn stderr" , " $ fromMaybe \"Good night, World!\" (Just \"Hello, World!\")" ] ] @@ -685,13 +685,13 @@ hsImportSpec formatterName [e1, e2, e3, e4] = let config = def { formatOnImportOn = False, formattingProvider = formatterName } sendNotification WorkspaceDidChangeConfiguration (DidChangeConfigurationParams (toJSON config)) - let wantedCodeActionTitles = [ "Import module System.IO (hPutSetrLn)" - , "Import module System.IO (stdout)" + let wantedCodeActionTitles = [ "Import module System.IO (hPutStrLn)" , "Import module Control.Monad (when)" , "Import module Data.Maybe (fromMaybe)" , "Import module Data.Function (($))" - , "Import module Data.Maybe (Maybe(Just))" - , "Import module Prelude (Bool(..))" + , "Import module Data.Maybe (Maybe (Just))" + , "Import module Prelude (Bool (..))" + , "Import module System.IO (stderr)" ] executeAllCodeActions doc wantedCodeActionTitles @@ -708,12 +708,12 @@ hsImportSpec formatterName [e1, e2, e3, e4] = sendNotification WorkspaceDidChangeConfiguration (DidChangeConfigurationParams (toJSON config)) let wantedCodeActionTitles = [ "Import module System.IO (hPutStrLn)" - , "Import module System.IO (stdout)" , "Import module Control.Monad (when)" , "Import module Data.Maybe (fromMaybe)" , "Import module Data.Function (($))" - , "Import module Data.Maybe (Maybe(Just))" - , "Import module Prelude (Bool(..))" + , "Import module Data.Maybe (Maybe (Just))" + , "Import module Prelude (Bool (..))" + , "Import module System.IO (stderr)" ] executeAllCodeActions doc wantedCodeActionTitles @@ -722,7 +722,7 @@ hsImportSpec formatterName [e1, e2, e3, e4] = liftIO $ do let [l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12] = T.lines contents l1 `shouldBe` "{-# LANGUAGE NoImplicitPrelude #-}" - l2 `shouldBe` "import System.IO (IO, hPutStrLn, stdout)" + l2 `shouldBe` "import System.IO (IO, hPutStrLn, stderr)" l3 `shouldBe` "import Prelude (Bool(..))" l4 `shouldBe` "import Control.Monad (when)" l5 `shouldBe` "import Data.Maybe (fromMaybe, Maybe(Just))" @@ -731,7 +731,7 @@ hsImportSpec formatterName [e1, e2, e3, e4] = l8 `shouldBe` "main :: IO ()" l9 `shouldBe` "main =" l10 `shouldBe` " when True" - l11 `shouldBe` " $ hPutStrLn stdout" + l11 `shouldBe` " $ hPutStrLn stderr" l12 `shouldBe` " $ fromMaybe \"Good night, World!\" (Just \"Hello, World!\")" where @@ -754,7 +754,7 @@ hsImportSpec formatterName [e1, e2, e3, e4] = error $ "Found an unexpected amount of action. Expected 1, but got: " ++ show (length xs) - ++ "\n. Titles: " ++ show (map (^. L.title) allActions) + ++ ".\n Titles: " ++ show (map (^. L.title) allActions) -- Silence warnings hsImportSpec formatter args = diff --git a/test/testdata/CodeActionImportListElaborate.hs b/test/testdata/CodeActionImportListElaborate.hs index 1cf149fd2..587f9c042 100644 --- a/test/testdata/CodeActionImportListElaborate.hs +++ b/test/testdata/CodeActionImportListElaborate.hs @@ -4,5 +4,5 @@ import System.IO (IO) main :: IO () main = when True - $ hPutStrLn stdout + $ hPutStrLn stderr $ fromMaybe "Good night, World!" (Just "Hello, World!") \ No newline at end of file From 1c573a07d25e4fc3cb7198e8821df863a8f6f360 Mon Sep 17 00:00:00 2001 From: fendor Date: Sat, 8 Jun 2019 15:22:18 +0200 Subject: [PATCH 022/158] Implement suggestions --- src/Haskell/Ide/Engine/Plugin/Hoogle.hs | 29 +++++++++++++------- src/Haskell/Ide/Engine/Plugin/HsImport.hs | 32 +++++++++++------------ 2 files changed, 36 insertions(+), 25 deletions(-) diff --git a/src/Haskell/Ide/Engine/Plugin/Hoogle.hs b/src/Haskell/Ide/Engine/Plugin/Hoogle.hs index 81d356897..eea4e2fca 100644 --- a/src/Haskell/Ide/Engine/Plugin/Hoogle.hs +++ b/src/Haskell/Ide/Engine/Plugin/Hoogle.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE TupleSections #-} {-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-} module Haskell.Ide.Engine.Plugin.Hoogle where @@ -5,6 +6,7 @@ module Haskell.Ide.Engine.Plugin.Hoogle where import Control.Monad.IO.Class import Control.Monad (join) import Control.Exception +import Control.Applicative (liftA2) import Data.Aeson import Data.Bifunctor import Data.Maybe @@ -157,14 +159,23 @@ searchModules = fmap (map fst) . searchModules' -- | Just like 'searchModules', but includes the signature of the search term -- that has been found in the module. searchModules' :: T.Text -> IdeM [(T.Text, T.Text)] -searchModules' = fmap (nub . take 5) - . searchTargets - (\target - -> (\modTarget -> (T.pack $ fst modTarget, normaliseItem . T.pack $ targetItem target)) - <$> targetModule target) - where - normaliseItem :: T.Text -> T.Text - normaliseItem = innerText . parseTags +searchModules' = fmap (take 5 . nub) . searchTargets retrieveModuleAndSignature + where + -- | Hoogle results contain html like tags. + -- We remove them with `tagsoup` here. + -- So, if something hoogle related shows html tags, + -- then maybe this function is responsible. + normaliseItem :: T.Text -> T.Text + normaliseItem = innerText . parseTags + + retrieveModuleAndSignature :: Target -> Maybe (T.Text, T.Text) + retrieveModuleAndSignature target = liftA2 (,) (packModuleName target) (packSymbolSignature target) + + packModuleName :: Target -> Maybe T.Text + packModuleName = fmap (T.pack . fst) . targetModule + + packSymbolSignature :: Target -> Maybe T.Text + packSymbolSignature = Just . normaliseItem . T.pack . targetItem -- | Search for packages that satisfy the given search text. -- Will return at most five, unique results. @@ -172,7 +183,7 @@ searchModules' = fmap (nub . take 5) -- If an error occurs, such as no hoogle database has been found, -- or the search term has no match, an empty list will be returned. searchPackages :: T.Text -> IdeM [T.Text] -searchPackages = fmap (nub . take 5) . searchTargets (fmap (T.pack . fst) . targetPackage) +searchPackages = fmap (take 5 . nub) . searchTargets (fmap (T.pack . fst) . targetPackage) -- | Search for Targets that fit to the given Text and satisfy the given predicate. -- Limits the amount of matches to at most ten. diff --git a/src/Haskell/Ide/Engine/Plugin/HsImport.hs b/src/Haskell/Ide/Engine/Plugin/HsImport.hs index 3ead8eefd..f19bcfaa9 100644 --- a/src/Haskell/Ide/Engine/Plugin/HsImport.hs +++ b/src/Haskell/Ide/Engine/Plugin/HsImport.hs @@ -470,27 +470,27 @@ codeActionProvider plId docId _ context = do -- signature of an unknown function. -- If this is not possible, Nothing is returned. extractImportableTerm :: T.Text -> Maybe (T.Text, SymbolImport SymbolType) -extractImportableTerm dirtyMsg = - let extractedTerm = asum - [ (\name -> (name, Import Symbol)) - <$> T.stripPrefix "Variable not in scope: " importMsg - , (\name -> (T.init name, Import Type)) - <$> T.stripPrefix - "Not in scope: type constructor or class ‘" - importMsg - , (\name -> (name, Import Constructor)) - <$> T.stripPrefix "Data constructor not in scope: " importMsg] - in do - (n, s) <- extractedTerm - let n' = T.strip n - return (n', s) +extractImportableTerm dirtyMsg = do + (n, s) <- extractedTerm + let n' = T.strip n + return (n', s) where importMsg = head - -- Get rid of the rename suggestion parts + -- Get rid of the rename suggestion parts $ T.splitOn "Perhaps you meant " $ T.replace "\n" " " - -- Get rid of trailing/leading whitespace on each individual line + -- Get rid of trailing/leading whitespace on each individual line $ T.unlines $ map T.strip $ T.lines $ T.replace "• " "" dirtyMsg + + extractedTerm = asum + [ (\name -> (name, Import Symbol)) + <$> T.stripPrefix "Variable not in scope: " importMsg + , (\name -> (T.init name, Import Type)) + <$> T.stripPrefix + "Not in scope: type constructor or class ‘" + importMsg + , (\name -> (name, Import Constructor)) + <$> T.stripPrefix "Data constructor not in scope: " importMsg] From 1a59411c7688ceab2163f855cf22a5a94216e2a2 Mon Sep 17 00:00:00 2001 From: fendor Date: Sat, 8 Jun 2019 16:22:08 +0200 Subject: [PATCH 023/158] Fix hsimport tests --- test/functional/FunctionalCodeActionsSpec.hs | 87 ++++++++++---------- 1 file changed, 44 insertions(+), 43 deletions(-) diff --git a/test/functional/FunctionalCodeActionsSpec.hs b/test/functional/FunctionalCodeActionsSpec.hs index 0c0fa5103..1bd5d3747 100644 --- a/test/functional/FunctionalCodeActionsSpec.hs +++ b/test/functional/FunctionalCodeActionsSpec.hs @@ -127,7 +127,7 @@ spec = describe "code actions" $ do liftIO $ x `shouldBe` "foo = putStrLn \"world\"" describe "import suggestions" $ do - hsImportSpec "brittany" + describe "formats with brittany" $ hsImportSpec "brittany" [ -- Expected output for simple format. [ "import qualified Data.Maybe" , "import Control.Monad" @@ -155,16 +155,16 @@ spec = describe "code actions" $ do ] , -- Complex imports for Constructos and functions [ "{-# LANGUAGE NoImplicitPrelude #-}" - , "import System.IO ( IO" - , " , hPutStrLn" - , " , stderr" - , " )" - , "import Prelude ( Bool(..) )" - , "import Control.Monad ( when )" - , "import Data.Maybe ( fromMaybe" - , " , Maybe(Just)" - , " )" - , "import Data.Function ( ($) )" + , "import System.IO ( IO" + , " , hPutStrLn" + , " , stderr" + , " )" + , "import Prelude ( Bool(..) )" + , "import Control.Monad ( when )" + , "import Data.Function ( ($) )" + , "import Data.Maybe ( fromMaybe" + , " , Maybe(Just)" + , " )" , "-- | Main entry point to the program" , "main :: IO ()" , "main =" @@ -173,7 +173,7 @@ spec = describe "code actions" $ do , " $ fromMaybe \"Good night, World!\" (Just \"Hello, World!\")" ] ] - hsImportSpec "floskell" + describe "formats with floskell" $ hsImportSpec "floskell" [ -- Expected output for simple format. [ "import qualified Data.Maybe" , "import Control.Monad" @@ -202,8 +202,8 @@ spec = describe "code actions" $ do , "import System.IO (IO, hPutStrLn, stderr)" , "import Prelude (Bool(..))" , "import Control.Monad (when)" - , "import Data.Maybe (fromMaybe, Maybe(Just))" , "import Data.Function (($))" + , "import Data.Maybe (fromMaybe, Maybe(Just))" , "-- | Main entry point to the program" , "main :: IO ()" , "main =" @@ -609,9 +609,8 @@ hsImportSpec formatterName [e1, e2, e3, e4] = , "Import module Data.Maybe (fromMaybe)" ] - executeAllCodeActions doc wantedCodeActionTitles + contents <- executeAllCodeActions doc wantedCodeActionTitles - contents <- documentContents doc liftIO $ Set.fromList (T.lines contents) `shouldBe` Set.fromList e3 it "respects format config, multiple import-list" $ runSession hieCommand fullCaps "test/testdata" $ do @@ -626,8 +625,7 @@ hsImportSpec formatterName [e1, e2, e3, e4] = , "Import module Data.Maybe (fromMaybe)" ] - executeAllCodeActions doc wantedCodeActionTitles - contents <- documentContents doc + contents <- executeAllCodeActions doc wantedCodeActionTitles liftIO $ Set.fromList (T.lines contents) `shouldBe` Set.fromList [ "import System.IO (stdout, hPutStrLn)" @@ -682,7 +680,7 @@ hsImportSpec formatterName [e1, e2, e3, e4] = doc <- openDoc "CodeActionImportListElaborate.hs" "haskell" _ <- waitForDiagnosticsSource "ghcmod" - let config = def { formatOnImportOn = False, formattingProvider = formatterName } + let config = def { formatOnImportOn = True, formattingProvider = formatterName } sendNotification WorkspaceDidChangeConfiguration (DidChangeConfigurationParams (toJSON config)) let wantedCodeActionTitles = [ "Import module System.IO (hPutStrLn)" @@ -694,9 +692,8 @@ hsImportSpec formatterName [e1, e2, e3, e4] = , "Import module System.IO (stderr)" ] - executeAllCodeActions doc wantedCodeActionTitles + contents <- executeAllCodeActions doc wantedCodeActionTitles - contents <- getDocumentEdit doc liftIO $ T.lines contents `shouldBe` e4 @@ -716,32 +713,36 @@ hsImportSpec formatterName [e1, e2, e3, e4] = , "Import module System.IO (stderr)" ] - executeAllCodeActions doc wantedCodeActionTitles + contents <- executeAllCodeActions doc wantedCodeActionTitles - contents <- getDocumentEdit doc - liftIO $ do - let [l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12] = T.lines contents - l1 `shouldBe` "{-# LANGUAGE NoImplicitPrelude #-}" - l2 `shouldBe` "import System.IO (IO, hPutStrLn, stderr)" - l3 `shouldBe` "import Prelude (Bool(..))" - l4 `shouldBe` "import Control.Monad (when)" - l5 `shouldBe` "import Data.Maybe (fromMaybe, Maybe(Just))" - l6 `shouldBe` "import Data.Function (($))" - l7 `shouldBe` "-- | Main entry point to the program" - l8 `shouldBe` "main :: IO ()" - l9 `shouldBe` "main =" - l10 `shouldBe` " when True" - l11 `shouldBe` " $ hPutStrLn stderr" - l12 `shouldBe` " $ fromMaybe \"Good night, World!\" (Just \"Hello, World!\")" + liftIO $ + T.lines contents `shouldBe` + [ "{-# LANGUAGE NoImplicitPrelude #-}" + , "import System.IO (IO, hPutStrLn, stderr)" + , "import Prelude (Bool(..))" + , "import Control.Monad (when)" + , "import Data.Function (($))" + , "import Data.Maybe (fromMaybe, Maybe(Just))" + , "-- | Main entry point to the program" + , "main :: IO ()" + , "main =" + , " when True" + , " $ hPutStrLn stderr" + , " $ fromMaybe \"Good night, World!\" (Just \"Hello, World!\")" + ] where - executeAllCodeActions :: TextDocumentIdentifier -> [T.Text] -> Session () + executeAllCodeActions :: TextDocumentIdentifier -> [T.Text] -> Session T.Text executeAllCodeActions doc names = - replicateM_ (length names) $ do - _ <- waitForDiagnosticsSource "ghcmod" - executeCodeActionByName doc names - _ <- skipManyTill publishDiagnosticsNotification $ getDocumentEdit doc - waitForDiagnosticsSource "ghcmod" + foldM (\_ _ -> do + _ <- waitForDiagnosticsSource "ghcmod" + executeCodeActionByName doc names + content <- skipManyTill publishDiagnosticsNotification $ getDocumentEdit doc + _ <- waitForDiagnosticsSource "ghcmod" + return content + ) + (T.pack "") + [ 1 .. length names ] executeCodeActionByName :: TextDocumentIdentifier -> [T.Text] -> Session () executeCodeActionByName doc names = do @@ -760,7 +761,7 @@ hsImportSpec formatterName [e1, e2, e3, e4] = hsImportSpec formatter args = error $ "Not the right amount of arguments for \"hsImportSpec (" ++ T.unpack formatter - ++ ")\", expected 3, got " + ++ ")\", expected 4, got " ++ show (length args) -- --------------------------------------------------------------------- From ab4e54e21211337e80e36ba3625ef15560b54bb1 Mon Sep 17 00:00:00 2001 From: Alan Zimmerman Date: Tue, 11 Jun 2019 22:39:59 +0200 Subject: [PATCH 024/158] Upgrade to hlint-2.1.24 Still using Hlint3 API though --- stack-8.4.2.yaml | 4 ++-- stack-8.4.3.yaml | 4 ++-- stack-8.4.4.yaml | 4 ++-- stack-8.6.1.yaml | 4 ++-- stack-8.6.2.yaml | 4 ++-- stack-8.6.3.yaml | 4 ++-- stack-8.6.4.yaml | 4 ++-- stack-8.6.5.yaml | 4 ++-- stack.yaml | 3 ++- test/unit/ApplyRefactPluginSpec.hs | 6 +++--- 10 files changed, 21 insertions(+), 20 deletions(-) diff --git a/stack-8.4.2.yaml b/stack-8.4.2.yaml index 7ce199b53..32b25b961 100644 --- a/stack-8.4.2.yaml +++ b/stack-8.4.2.yaml @@ -17,14 +17,14 @@ extra-deps: - constrained-dynamic-0.1.0.0 - floskell-0.10.0 - ghc-exactprint-0.5.8.2 -- ghc-lib-parser-0.20190523 +- ghc-lib-parser-8.8.0.20190424 - haddock-api-2.20.0 - haddock-library-1.6.0 - haskell-lsp-0.13.0.0 - haskell-lsp-types-0.13.0.0@rev:2 - haskell-src-exts-1.21.0 - haskell-src-exts-util-0.2.5 -- hlint-2.1.22 +- hlint-2.1.24 - hoogle-5.0.17.9 - hsimport-0.10.0 - lsp-test-0.5.2.3 diff --git a/stack-8.4.3.yaml b/stack-8.4.3.yaml index 751c676cd..00cc9c1ea 100644 --- a/stack-8.4.3.yaml +++ b/stack-8.4.3.yaml @@ -16,14 +16,14 @@ extra-deps: - constrained-dynamic-0.1.0.0 - floskell-0.10.0 - ghc-exactprint-0.5.8.2 -- ghc-lib-parser-0.20190523 +- ghc-lib-parser-8.8.0.20190424 - haddock-api-2.20.0 - haddock-library-1.6.0 - haskell-lsp-0.13.0.0 - haskell-lsp-types-0.13.0.0@rev:2 - haskell-src-exts-1.21.0 - haskell-src-exts-util-0.2.5 -- hlint-2.1.22 +- hlint-2.1.24 - hoogle-5.0.17.9 - hsimport-0.10.0 - lsp-test-0.5.2.3 diff --git a/stack-8.4.4.yaml b/stack-8.4.4.yaml index 227e85c83..c22097ae3 100644 --- a/stack-8.4.4.yaml +++ b/stack-8.4.4.yaml @@ -16,14 +16,14 @@ extra-deps: - constrained-dynamic-0.1.0.0 - floskell-0.10.0 - ghc-exactprint-0.5.8.2 -- ghc-lib-parser-0.20190523 +- ghc-lib-parser-8.8.0.20190424 - haddock-api-2.20.0 - haddock-library-1.6.0 - haskell-lsp-0.13.0.0 - haskell-lsp-types-0.13.0.0 - haskell-src-exts-1.21.0 - haskell-src-exts-util-0.2.5 -- hlint-2.1.22 +- hlint-2.1.24 - hoogle-5.0.17.9 - hsimport-0.10.0 - lsp-test-0.5.2.3 diff --git a/stack-8.6.1.yaml b/stack-8.6.1.yaml index 570450183..8b84a4cef 100644 --- a/stack-8.6.1.yaml +++ b/stack-8.6.1.yaml @@ -19,13 +19,13 @@ extra-deps: - czipwith-1.0.1.1 - data-tree-print-0.1.0.2 - floskell-0.10.0 -- ghc-lib-parser-0.20190523 +- ghc-lib-parser-8.8.0.20190424 - haddock-api-2.21.0 - haskell-lsp-0.13.0.0 - haskell-lsp-types-0.13.0.0 - haskell-src-exts-1.21.0 - haskell-src-exts-util-0.2.5 -- hlint-2.1.22 +- hlint-2.1.24 - hoogle-5.0.17.9 - hsimport-0.10.0 - lsp-test-0.5.2.3 diff --git a/stack-8.6.2.yaml b/stack-8.6.2.yaml index 7b8022099..3d4f72956 100644 --- a/stack-8.6.2.yaml +++ b/stack-8.6.2.yaml @@ -15,13 +15,13 @@ extra-deps: - cabal-plan-0.4.0.0 - constrained-dynamic-0.1.0.0 - floskell-0.10.0 -- ghc-lib-parser-0.20190523 +- ghc-lib-parser-8.8.0.20190424 - haddock-api-2.21.0 - haskell-lsp-0.13.0.0 - haskell-lsp-types-0.13.0.0 - haskell-src-exts-1.21.0 - haskell-src-exts-util-0.2.5 -- hlint-2.1.22 +- hlint-2.1.24 - hoogle-5.0.17.9 - hsimport-0.10.0 - lsp-test-0.5.2.3 diff --git a/stack-8.6.3.yaml b/stack-8.6.3.yaml index 097e54547..a52c8e4f4 100644 --- a/stack-8.6.3.yaml +++ b/stack-8.6.3.yaml @@ -15,13 +15,13 @@ extra-deps: - cabal-plan-0.4.0.0 - constrained-dynamic-0.1.0.0 - floskell-0.10.0 -- ghc-lib-parser-0.20190523 +- ghc-lib-parser-8.8.0.20190424 - haddock-api-2.21.0 - haskell-lsp-0.13.0.0 - haskell-lsp-types-0.13.0.0 - haskell-src-exts-1.21.0 - haskell-src-exts-util-0.2.5 -- hlint-2.1.22 +- hlint-2.1.24 - hoogle-5.0.17.9 - hsimport-0.10.0 - lsp-test-0.5.2.3 diff --git a/stack-8.6.4.yaml b/stack-8.6.4.yaml index ec39ae099..723ac9418 100644 --- a/stack-8.6.4.yaml +++ b/stack-8.6.4.yaml @@ -15,12 +15,12 @@ extra-deps: - cabal-plan-0.4.0.0 - constrained-dynamic-0.1.0.0 - floskell-0.10.0 -- ghc-lib-parser-0.20190523 +- ghc-lib-parser-8.8.0.20190424 - haddock-api-2.22.0 - haskell-lsp-0.13.0.0 - haskell-lsp-types-0.13.0.0 - haskell-src-exts-1.21.0 -- hlint-2.1.22 +- hlint-2.1.24 - hoogle-5.0.17.9 - hsimport-0.10.0 - lsp-test-0.5.2.3 diff --git a/stack-8.6.5.yaml b/stack-8.6.5.yaml index a27bc7c46..891a32b0c 100644 --- a/stack-8.6.5.yaml +++ b/stack-8.6.5.yaml @@ -15,12 +15,12 @@ extra-deps: - cabal-plan-0.4.0.0 - constrained-dynamic-0.1.0.0 - floskell-0.10.0 -- ghc-lib-parser-0.20190523 +- ghc-lib-parser-8.8.0.20190424 - haddock-api-2.22.0 - haskell-lsp-0.13.0.0 - haskell-lsp-types-0.13.0.0 - haskell-src-exts-1.21.0 -- hlint-2.1.22 +- hlint-2.1.24 - hsimport-0.10.0 - hoogle-5.0.17.9 - lsp-test-0.5.2.3 diff --git a/stack.yaml b/stack.yaml index e8de1bccd..5cb33b797 100644 --- a/stack.yaml +++ b/stack.yaml @@ -19,10 +19,11 @@ extra-deps: - deque-0.2.7 - floskell-0.10.1 - ghc-exactprint-0.5.8.2 +- ghc-lib-parser-8.8.0.20190424 - haddock-api-2.22.0 - haskell-lsp-0.13.0.0 - haskell-lsp-types-0.13.0.0 -- hlint-2.1.22 +- hlint-2.1.24 - hsimport-0.10.0 - lsp-test-0.5.2.3 - monad-dijkstra-0.1.1.2@rev:1 diff --git a/test/unit/ApplyRefactPluginSpec.hs b/test/unit/ApplyRefactPluginSpec.hs index 7ba72f09e..4a91d0fee 100644 --- a/test/unit/ApplyRefactPluginSpec.hs +++ b/test/unit/ApplyRefactPluginSpec.hs @@ -100,12 +100,12 @@ applyRefactSpec = do { _uri = filePath , _diagnostics = List #if (defined(MIN_VERSION_GLASGOW_HASKELL) && (MIN_VERSION_GLASGOW_HASKELL(8,4,0,0))) - [Diagnostic {_range = Range { _start = Position {_line = 13, _character = 0} - , _end = Position {_line = 13, _character = 100000}} + [Diagnostic {_range = Range { _start = Position {_line = 12, _character = 23} + , _end = Position {_line = 12, _character = 100000}} , _severity = Just DsInfo , _code = Just "parser" , _source = Just "hlint" - , _message = T.pack filePathNoUri <> ":13:24: error:\n Operator applied to too few arguments: +\n data instance Sing (z :: (a :~: b)) where\n SRefl :: Sing Refl +\n> \n\n" + , _message = T.pack filePathNoUri <> ":13:24: error:\n Operator applied to too few arguments: +\n data instance Sing (z :: (a :~: b)) where\n> SRefl :: Sing Refl +\n\n" , _relatedInformation = Nothing }]} #elif (defined(MIN_VERSION_GLASGOW_HASKELL) && (MIN_VERSION_GLASGOW_HASKELL(8,2,2,0))) [Diagnostic {_range = Range { _start = Position {_line = 13, _character = 0} From 96df5ad9e54fd2a934cc06132304e2c84de2c05d Mon Sep 17 00:00:00 2001 From: Alan Zimmerman Date: Tue, 11 Jun 2019 22:53:50 +0200 Subject: [PATCH 025/158] Use Hlint4 for hlint-2.1.24 API --- src/Haskell/Ide/Engine/Plugin/ApplyRefact.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Haskell/Ide/Engine/Plugin/ApplyRefact.hs b/src/Haskell/Ide/Engine/Plugin/ApplyRefact.hs index 3b7cd5e02..920436bdc 100644 --- a/src/Haskell/Ide/Engine/Plugin/ApplyRefact.hs +++ b/src/Haskell/Ide/Engine/Plugin/ApplyRefact.hs @@ -26,7 +26,7 @@ import Haskell.Ide.Engine.PluginUtils import Language.Haskell.Exts.SrcLoc import Language.Haskell.Exts.Parser import Language.Haskell.Exts.Extension -import Language.Haskell.HLint3 as Hlint +import Language.Haskell.HLint4 as Hlint import qualified Language.Haskell.LSP.Types as LSP import qualified Language.Haskell.LSP.Types.Lens as LSP import Refact.Apply From a254e72b2070620266df1f32f9ac39fe06e529d8 Mon Sep 17 00:00:00 2001 From: Alan Zimmerman Date: Wed, 12 Jun 2019 08:26:38 +0200 Subject: [PATCH 026/158] Use Hlint3 API for GHC 8.2.2 --- src/Haskell/Ide/Engine/Plugin/ApplyRefact.hs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Haskell/Ide/Engine/Plugin/ApplyRefact.hs b/src/Haskell/Ide/Engine/Plugin/ApplyRefact.hs index 920436bdc..6589bc276 100644 --- a/src/Haskell/Ide/Engine/Plugin/ApplyRefact.hs +++ b/src/Haskell/Ide/Engine/Plugin/ApplyRefact.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DuplicateRecordFields #-} @@ -26,7 +27,11 @@ import Haskell.Ide.Engine.PluginUtils import Language.Haskell.Exts.SrcLoc import Language.Haskell.Exts.Parser import Language.Haskell.Exts.Extension +#if (defined(MIN_VERSION_GLASGOW_HASKELL) && (MIN_VERSION_GLASGOW_HASKELL(8,4,0,0))) import Language.Haskell.HLint4 as Hlint +#else +import Language.Haskell.HLint3 as Hlint +#endif import qualified Language.Haskell.LSP.Types as LSP import qualified Language.Haskell.LSP.Types.Lens as LSP import Refact.Apply From 40918950533e8138d3424019175def7121f88617 Mon Sep 17 00:00:00 2001 From: fendor Date: Wed, 12 Jun 2019 22:24:21 +0200 Subject: [PATCH 027/158] Use total function --- src/Haskell/Ide/Engine/Plugin/HsImport.hs | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/Haskell/Ide/Engine/Plugin/HsImport.hs b/src/Haskell/Ide/Engine/Plugin/HsImport.hs index f19bcfaa9..ea28eef27 100644 --- a/src/Haskell/Ide/Engine/Plugin/HsImport.hs +++ b/src/Haskell/Ide/Engine/Plugin/HsImport.hs @@ -475,7 +475,7 @@ extractImportableTerm dirtyMsg = do let n' = T.strip n return (n', s) where - importMsg = head + importMsg = S.headMay -- Get rid of the rename suggestion parts $ T.splitOn "Perhaps you meant " $ T.replace "\n" " " @@ -486,11 +486,14 @@ extractImportableTerm dirtyMsg = do $ T.replace "• " "" dirtyMsg extractedTerm = asum - [ (\name -> (name, Import Symbol)) - <$> T.stripPrefix "Variable not in scope: " importMsg - , (\name -> (T.init name, Import Type)) - <$> T.stripPrefix - "Not in scope: type constructor or class ‘" - importMsg - , (\name -> (name, Import Constructor)) - <$> T.stripPrefix "Data constructor not in scope: " importMsg] + [ importMsg + >>= T.stripPrefix "Variable not in scope: " + >>= \name -> Just (name, Import Symbol) + , importMsg + >>= T.stripPrefix "Not in scope: type constructor or class ‘" + >>= \name -> Just (T.init name, Import Type) + , importMsg + >>= T.stripPrefix "Data constructor not in scope: " + >>= \name -> Just (name, Import Constructor)] + + From d32113accf48ad23f9a5351818a2e51c2ed01c33 Mon Sep 17 00:00:00 2001 From: Alan Zimmerman Date: Thu, 13 Jun 2019 15:49:00 +0200 Subject: [PATCH 028/158] Trying out haskell-lsp 0.14 Tests failing, suspect a JSON encoding problem. ping @cocreature, see the circle logs --- haskell-ide-engine.cabal | 8 ++++---- hie-plugin-api/hie-plugin-api.cabal | 2 +- stack-8.2.2.yaml | 6 +++--- stack-8.4.2.yaml | 6 +++--- stack-8.4.3.yaml | 6 +++--- stack-8.4.4.yaml | 6 +++--- stack-8.6.1.yaml | 6 +++--- stack-8.6.2.yaml | 6 +++--- stack-8.6.3.yaml | 6 +++--- stack-8.6.4.yaml | 6 +++--- stack-8.6.5.yaml | 6 +++--- stack.yaml | 6 +++--- 12 files changed, 35 insertions(+), 35 deletions(-) diff --git a/haskell-ide-engine.cabal b/haskell-ide-engine.cabal index e1efc3fe4..d30b060a0 100644 --- a/haskell-ide-engine.cabal +++ b/haskell-ide-engine.cabal @@ -70,8 +70,8 @@ library , gitrev >= 1.1 , haddock-api , haddock-library - , haskell-lsp == 0.13.* - , haskell-lsp-types == 0.13.* + , haskell-lsp == 0.14.* + , haskell-lsp-types == 0.14.* , haskell-src-exts , hie-plugin-api , hlint (>= 2.0.11 && < 2.1.18) || >= 2.1.22 @@ -278,8 +278,8 @@ test-suite func-test , filepath , lsp-test >= 0.5.2 , haskell-ide-engine - , haskell-lsp-types == 0.13.* - , haskell-lsp == 0.13.* + , haskell-lsp-types == 0.14.* + , haskell-lsp == 0.14.* , hie-test-utils , hie-plugin-api , hspec diff --git a/hie-plugin-api/hie-plugin-api.cabal b/hie-plugin-api/hie-plugin-api.cabal index 7d6a96321..e09f4a525 100644 --- a/hie-plugin-api/hie-plugin-api.cabal +++ b/hie-plugin-api/hie-plugin-api.cabal @@ -45,7 +45,7 @@ library , ghc , ghc-mod-core >= 5.9.0.0 , ghc-project-types >= 5.9.0.0 - , haskell-lsp == 0.13.* + , haskell-lsp == 0.14.* , hslogger , monad-control , mtl diff --git a/stack-8.2.2.yaml b/stack-8.2.2.yaml index b1177fe3c..2ebcc6d44 100644 --- a/stack-8.2.2.yaml +++ b/stack-8.2.2.yaml @@ -21,14 +21,14 @@ extra-deps: - ghc-exactprint-0.5.8.2 - haddock-api-2.18.1 - haddock-library-1.4.4 -- haskell-lsp-0.13.0.0 -- haskell-lsp-types-0.13.0.0@rev:2 +- haskell-lsp-0.14.0.0 +- haskell-lsp-types-0.14.0.1 - haskell-src-exts-1.21.0 - haskell-src-exts-util-0.2.5 - hlint-2.1.17 # last hlint supporting GHC 8.2 - hoogle-5.0.17.9 - hsimport-0.8.8 -- lsp-test-0.5.2.3 +- lsp-test-0.5.4.0 - monad-dijkstra-0.1.1.2 - pretty-show-1.8.2 - rope-utf16-splay-0.3.1.0 diff --git a/stack-8.4.2.yaml b/stack-8.4.2.yaml index 32b25b961..2dccd4d5d 100644 --- a/stack-8.4.2.yaml +++ b/stack-8.4.2.yaml @@ -20,14 +20,14 @@ extra-deps: - ghc-lib-parser-8.8.0.20190424 - haddock-api-2.20.0 - haddock-library-1.6.0 -- haskell-lsp-0.13.0.0 -- haskell-lsp-types-0.13.0.0@rev:2 +- haskell-lsp-0.14.0.0 +- haskell-lsp-types-0.14.0.1 - haskell-src-exts-1.21.0 - haskell-src-exts-util-0.2.5 - hlint-2.1.24 - hoogle-5.0.17.9 - hsimport-0.10.0 -- lsp-test-0.5.2.3 +- lsp-test-0.5.4.0 - monad-dijkstra-0.1.1.2 - pretty-show-1.8.2 - rope-utf16-splay-0.3.1.0 diff --git a/stack-8.4.3.yaml b/stack-8.4.3.yaml index 00cc9c1ea..8fc7c5bc5 100644 --- a/stack-8.4.3.yaml +++ b/stack-8.4.3.yaml @@ -19,14 +19,14 @@ extra-deps: - ghc-lib-parser-8.8.0.20190424 - haddock-api-2.20.0 - haddock-library-1.6.0 -- haskell-lsp-0.13.0.0 -- haskell-lsp-types-0.13.0.0@rev:2 +- haskell-lsp-0.14.0.0 +- haskell-lsp-types-0.14.0.1 - haskell-src-exts-1.21.0 - haskell-src-exts-util-0.2.5 - hlint-2.1.24 - hoogle-5.0.17.9 - hsimport-0.10.0 -- lsp-test-0.5.2.3 +- lsp-test-0.5.4.0 - monad-dijkstra-0.1.1.2 - pretty-show-1.8.2 - rope-utf16-splay-0.3.1.0 diff --git a/stack-8.4.4.yaml b/stack-8.4.4.yaml index c22097ae3..b77dd3d33 100644 --- a/stack-8.4.4.yaml +++ b/stack-8.4.4.yaml @@ -19,14 +19,14 @@ extra-deps: - ghc-lib-parser-8.8.0.20190424 - haddock-api-2.20.0 - haddock-library-1.6.0 -- haskell-lsp-0.13.0.0 -- haskell-lsp-types-0.13.0.0 +- haskell-lsp-0.14.0.0 +- haskell-lsp-types-0.14.0.1 - haskell-src-exts-1.21.0 - haskell-src-exts-util-0.2.5 - hlint-2.1.24 - hoogle-5.0.17.9 - hsimport-0.10.0 -- lsp-test-0.5.2.3 +- lsp-test-0.5.4.0 - monad-dijkstra-0.1.1.2 - optparse-simple-0.1.0 - pretty-show-1.9.5 diff --git a/stack-8.6.1.yaml b/stack-8.6.1.yaml index 8b84a4cef..6c7e43ccb 100644 --- a/stack-8.6.1.yaml +++ b/stack-8.6.1.yaml @@ -21,14 +21,14 @@ extra-deps: - floskell-0.10.0 - ghc-lib-parser-8.8.0.20190424 - haddock-api-2.21.0 -- haskell-lsp-0.13.0.0 -- haskell-lsp-types-0.13.0.0 +- haskell-lsp-0.14.0.0 +- haskell-lsp-types-0.14.0.1 - haskell-src-exts-1.21.0 - haskell-src-exts-util-0.2.5 - hlint-2.1.24 - hoogle-5.0.17.9 - hsimport-0.10.0 -- lsp-test-0.5.2.3 +- lsp-test-0.5.4.0 - monad-dijkstra-0.1.1.2 - monad-memo-0.4.1 - monoid-subclasses-0.4.6.1 diff --git a/stack-8.6.2.yaml b/stack-8.6.2.yaml index 3d4f72956..c0424c775 100644 --- a/stack-8.6.2.yaml +++ b/stack-8.6.2.yaml @@ -17,14 +17,14 @@ extra-deps: - floskell-0.10.0 - ghc-lib-parser-8.8.0.20190424 - haddock-api-2.21.0 -- haskell-lsp-0.13.0.0 -- haskell-lsp-types-0.13.0.0 +- haskell-lsp-0.14.0.0 +- haskell-lsp-types-0.14.0.1 - haskell-src-exts-1.21.0 - haskell-src-exts-util-0.2.5 - hlint-2.1.24 - hoogle-5.0.17.9 - hsimport-0.10.0 -- lsp-test-0.5.2.3 +- lsp-test-0.5.4.0 - monad-dijkstra-0.1.1.2 - monad-memo-0.4.1 - multistate-0.8.0.1 diff --git a/stack-8.6.3.yaml b/stack-8.6.3.yaml index a52c8e4f4..0af5b4a14 100644 --- a/stack-8.6.3.yaml +++ b/stack-8.6.3.yaml @@ -17,14 +17,14 @@ extra-deps: - floskell-0.10.0 - ghc-lib-parser-8.8.0.20190424 - haddock-api-2.21.0 -- haskell-lsp-0.13.0.0 -- haskell-lsp-types-0.13.0.0 +- haskell-lsp-0.14.0.0 +- haskell-lsp-types-0.14.0.1 - haskell-src-exts-1.21.0 - haskell-src-exts-util-0.2.5 - hlint-2.1.24 - hoogle-5.0.17.9 - hsimport-0.10.0 -- lsp-test-0.5.2.3 +- lsp-test-0.5.4.0 - monad-dijkstra-0.1.1.2 - monad-memo-0.4.1 - multistate-0.8.0.1 diff --git a/stack-8.6.4.yaml b/stack-8.6.4.yaml index 723ac9418..b1087ee4f 100644 --- a/stack-8.6.4.yaml +++ b/stack-8.6.4.yaml @@ -17,13 +17,13 @@ extra-deps: - floskell-0.10.0 - ghc-lib-parser-8.8.0.20190424 - haddock-api-2.22.0 -- haskell-lsp-0.13.0.0 -- haskell-lsp-types-0.13.0.0 +- haskell-lsp-0.14.0.0 +- haskell-lsp-types-0.14.0.1 - haskell-src-exts-1.21.0 - hlint-2.1.24 - hoogle-5.0.17.9 - hsimport-0.10.0 -- lsp-test-0.5.2.3 +- lsp-test-0.5.4.0 - monad-dijkstra-0.1.1.2@rev:1 - monad-memo-0.4.1 - multistate-0.8.0.1 diff --git a/stack-8.6.5.yaml b/stack-8.6.5.yaml index 891a32b0c..149f26a17 100644 --- a/stack-8.6.5.yaml +++ b/stack-8.6.5.yaml @@ -17,13 +17,13 @@ extra-deps: - floskell-0.10.0 - ghc-lib-parser-8.8.0.20190424 - haddock-api-2.22.0 -- haskell-lsp-0.13.0.0 -- haskell-lsp-types-0.13.0.0 +- haskell-lsp-0.14.0.0 +- haskell-lsp-types-0.14.0.1 - haskell-src-exts-1.21.0 - hlint-2.1.24 - hsimport-0.10.0 - hoogle-5.0.17.9 -- lsp-test-0.5.2.3 +- lsp-test-0.5.4.0 - monad-dijkstra-0.1.1.2@rev:1 - monad-memo-0.4.1 - multistate-0.8.0.1 diff --git a/stack.yaml b/stack.yaml index 5cb33b797..49a947db9 100644 --- a/stack.yaml +++ b/stack.yaml @@ -21,11 +21,11 @@ extra-deps: - ghc-exactprint-0.5.8.2 - ghc-lib-parser-8.8.0.20190424 - haddock-api-2.22.0 -- haskell-lsp-0.13.0.0 -- haskell-lsp-types-0.13.0.0 +- haskell-lsp-0.14.0.0 +- haskell-lsp-types-0.14.0.1 - hlint-2.1.24 - hsimport-0.10.0 -- lsp-test-0.5.2.3 +- lsp-test-0.5.4.0 - monad-dijkstra-0.1.1.2@rev:1 - monad-memo-0.4.1 - multistate-0.8.0.1 From 919b04625eaad1b75c11738bd2ceb2169f686cea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Avi=20=D7=93?= Date: Fri, 14 Jun 2019 11:52:07 -0400 Subject: [PATCH 029/158] Render completion doc markdown --- src/Haskell/Ide/Engine/Plugin/Hoogle.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Haskell/Ide/Engine/Plugin/Hoogle.hs b/src/Haskell/Ide/Engine/Plugin/Hoogle.hs index eea4e2fca..d1b26c994 100644 --- a/src/Haskell/Ide/Engine/Plugin/Hoogle.hs +++ b/src/Haskell/Ide/Engine/Plugin/Hoogle.hs @@ -103,7 +103,7 @@ infoCmd' expr = do if null res then Left NoResults else - return $ T.pack $ targetInfo $ head res + return $ renderTarget $ head res -- | Command to get the prettified documentation of an hoogle identifier. -- Identifier should be understandable for hoogle. @@ -128,7 +128,7 @@ infoCmdFancyRender expr = do renderTarget :: Target -> T.Text -- renderTarget t = T.intercalate "\n\n" $ renderTarget t = T.intercalate "\n" $ - ["```haskell\n" <> unHTML (T.pack $ targetItem t) <> "```"] + ["```haskell\n" <> unHTML (T.pack $ targetItem t) <> "\n```"] ++ [T.pack $ unwords mdl | not $ null mdl] ++ [renderDocs $ targetDocs t] ++ [T.pack $ curry annotate "More info" $ targetURL t] From 4d664292a9211440b500b6d70b208d10627844be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Avi=20=D7=93?= Date: Fri, 14 Jun 2019 14:44:43 -0400 Subject: [PATCH 030/158] Fix test, only show one link --- src/Haskell/Ide/Engine/Plugin/Hoogle.hs | 42 ++++++++++++++++--------- test/unit/HooglePluginSpec.hs | 2 +- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/src/Haskell/Ide/Engine/Plugin/Hoogle.hs b/src/Haskell/Ide/Engine/Plugin/Hoogle.hs index d1b26c994..31cf4b5b4 100644 --- a/src/Haskell/Ide/Engine/Plugin/Hoogle.hs +++ b/src/Haskell/Ide/Engine/Plugin/Hoogle.hs @@ -103,7 +103,14 @@ infoCmd' expr = do if null res then Left NoResults else - return $ renderTarget $ head res + return $ renderTargetInfo $ head res + +renderTargetInfo :: Target -> T.Text +renderTargetInfo t = + T.intercalate "\n" + $ ["```haskell\n" <> unHTML (T.pack $ targetItem t) <> "\n```"] + ++ [renderDocs $ targetDocs t] + ++ [T.pack $ curry annotate "More info" $ targetURL t] -- | Command to get the prettified documentation of an hoogle identifier. -- Identifier should be understandable for hoogle. @@ -128,23 +135,30 @@ infoCmdFancyRender expr = do renderTarget :: Target -> T.Text -- renderTarget t = T.intercalate "\n\n" $ renderTarget t = T.intercalate "\n" $ - ["```haskell\n" <> unHTML (T.pack $ targetItem t) <> "\n```"] + ["```haskell\n" <> unHTML (T.pack $ targetItem t) <> "```"] ++ [T.pack $ unwords mdl | not $ null mdl] ++ [renderDocs $ targetDocs t] ++ [T.pack $ curry annotate "More info" $ targetURL t] where mdl = map annotate $ catMaybes [targetPackage t, targetModule t] - annotate (thing,url) = "["<>thing++"]"++"("++url++")" - unHTML = T.replace "<0>" "" . innerText . parseTags - renderDocs = T.concat . map htmlToMarkDown . parseTree . T.pack - htmlToMarkDown :: TagTree T.Text -> T.Text - htmlToMarkDown (TagLeaf x) = fromMaybe "" $ maybeTagText x - htmlToMarkDown (TagBranch "i" _ tree) = "*" <> T.concat (map htmlToMarkDown tree) <> "*" - htmlToMarkDown (TagBranch "b" _ tree) = "**" <> T.concat (map htmlToMarkDown tree) <> "**" - htmlToMarkDown (TagBranch "a" _ tree) = "`" <> T.concat (map htmlToMarkDown tree) <> "`" - htmlToMarkDown (TagBranch "li" _ tree) = "- " <> T.concat (map htmlToMarkDown tree) - htmlToMarkDown (TagBranch "tt" _ tree) = "`" <> innerText (flattenTree tree) <> "`" - htmlToMarkDown (TagBranch "pre" _ tree) = "```haskell\n" <> T.concat (map htmlToMarkDown tree) <> "```" - htmlToMarkDown (TagBranch _ _ tree) = T.concat $ map htmlToMarkDown tree + +annotate :: (String, String) -> String +annotate (thing,url) = "["<>thing<>"]"<>"("<>url<>")" + +unHTML :: T.Text -> T.Text +unHTML = T.replace "<0>" "" . innerText . parseTags + +renderDocs :: String -> T.Text +renderDocs = T.concat . map htmlToMarkDown . parseTree . T.pack + +htmlToMarkDown :: TagTree T.Text -> T.Text +htmlToMarkDown (TagLeaf x) = fromMaybe "" $ maybeTagText x +htmlToMarkDown (TagBranch "i" _ tree) = "*" <> T.concat (map htmlToMarkDown tree) <> "*" +htmlToMarkDown (TagBranch "b" _ tree) = "**" <> T.concat (map htmlToMarkDown tree) <> "**" +htmlToMarkDown (TagBranch "a" _ tree) = "`" <> T.concat (map htmlToMarkDown tree) <> "`" +htmlToMarkDown (TagBranch "li" _ tree) = "- " <> T.concat (map htmlToMarkDown tree) +htmlToMarkDown (TagBranch "tt" _ tree) = "`" <> innerText (flattenTree tree) <> "`" +htmlToMarkDown (TagBranch "pre" _ tree) = "```haskell\n" <> T.concat (map htmlToMarkDown tree) <> "```" +htmlToMarkDown (TagBranch _ _ tree) = T.concat $ map htmlToMarkDown tree ------------------------------------------------------------------------ diff --git a/test/unit/HooglePluginSpec.hs b/test/unit/HooglePluginSpec.hs index 18fcc89fb..ca4fc8837 100644 --- a/test/unit/HooglePluginSpec.hs +++ b/test/unit/HooglePluginSpec.hs @@ -48,7 +48,7 @@ hoogleSpec = do it "runs the info command" $ do let req = liftToGhc $ infoCmd' "head" r <- dispatchRequestP $ initializeHoogleDb >> req - r `shouldBe` Right "head :: [a] -> a\nbase Prelude\nExtract the first element of a list, which must be non-empty.\n\n" + r `shouldBe` Right "```haskell\nhead :: [a] -> a\n```\nExtract the first element of a list, which must be non-empty.\n\n[More info](https://hackage.haskell.org/package/base/docs/Prelude.html#v:head)" -- --------------------------------- From 1d0024e6de1743f3b9cd8e3bf87bf95714ac783e Mon Sep 17 00:00:00 2001 From: Alan Zimmerman Date: Sat, 15 Jun 2019 10:15:47 +0200 Subject: [PATCH 031/158] Fix the HieWrapper tests for stack 2.1.1 --- .gitignore | 5 +++- test/testdata/wrapper/8.2.1/Setup.hs | 2 ++ test/testdata/wrapper/8.2.1/cabal.project | 1 + test/testdata/wrapper/8.2.1/cabal1.cabal | 25 +++++++++++++++++++ test/testdata/wrapper/8.2.1/src/Foo/Bar.hs | 3 +++ test/testdata/wrapper/8.2.1/src/main.hs | 7 ++++++ test/testdata/wrapper/lts-11.14/Setup.hs | 2 ++ test/testdata/wrapper/lts-11.14/cabal.project | 1 + test/testdata/wrapper/lts-11.14/cabal1.cabal | 25 +++++++++++++++++++ .../testdata/wrapper/lts-11.14/src/Foo/Bar.hs | 3 +++ test/testdata/wrapper/lts-11.14/src/main.hs | 7 ++++++ test/wrapper/HieWrapper.hs | 2 +- 12 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 test/testdata/wrapper/8.2.1/Setup.hs create mode 100644 test/testdata/wrapper/8.2.1/cabal.project create mode 100644 test/testdata/wrapper/8.2.1/cabal1.cabal create mode 100644 test/testdata/wrapper/8.2.1/src/Foo/Bar.hs create mode 100644 test/testdata/wrapper/8.2.1/src/main.hs create mode 100644 test/testdata/wrapper/lts-11.14/Setup.hs create mode 100644 test/testdata/wrapper/lts-11.14/cabal.project create mode 100644 test/testdata/wrapper/lts-11.14/cabal1.cabal create mode 100644 test/testdata/wrapper/lts-11.14/src/Foo/Bar.hs create mode 100644 test/testdata/wrapper/lts-11.14/src/main.hs diff --git a/.gitignore b/.gitignore index 8b4bf35b5..90a09f165 100644 --- a/.gitignore +++ b/.gitignore @@ -69,4 +69,7 @@ test-results/ .vscode # shake build information -_build/ \ No newline at end of file +_build/ + +# stack 2.1 stack.yaml lock files +stack*.yaml.lock diff --git a/test/testdata/wrapper/8.2.1/Setup.hs b/test/testdata/wrapper/8.2.1/Setup.hs new file mode 100644 index 000000000..9a994af67 --- /dev/null +++ b/test/testdata/wrapper/8.2.1/Setup.hs @@ -0,0 +1,2 @@ +import Distribution.Simple +main = defaultMain diff --git a/test/testdata/wrapper/8.2.1/cabal.project b/test/testdata/wrapper/8.2.1/cabal.project new file mode 100644 index 000000000..e6fdbadb4 --- /dev/null +++ b/test/testdata/wrapper/8.2.1/cabal.project @@ -0,0 +1 @@ +packages: . diff --git a/test/testdata/wrapper/8.2.1/cabal1.cabal b/test/testdata/wrapper/8.2.1/cabal1.cabal new file mode 100644 index 000000000..f599b3df0 --- /dev/null +++ b/test/testdata/wrapper/8.2.1/cabal1.cabal @@ -0,0 +1,25 @@ +-- Initial cabal1.cabal generated by cabal init. For further +-- documentation, see http://haskell.org/cabal/users-guide/ + +name: cabal1 +version: 0.1.0.0 +-- synopsis: +-- description: +license: PublicDomain +-- license-file: LICENSE +author: Alan Zimmerman +maintainer: alan.zimm@gmail.com +-- copyright: +-- category: +build-type: Simple +-- extra-source-files: +-- cabal-helper for cabal 2.2/GHC 8.4 needs a cabal version >= 2 +cabal-version: >=2.0 + +executable cabal1 + main-is: main.hs + -- other-modules: + -- other-extensions: + build-depends: base >=4.6 && <5 + hs-source-dirs: src + default-language: Haskell2010 \ No newline at end of file diff --git a/test/testdata/wrapper/8.2.1/src/Foo/Bar.hs b/test/testdata/wrapper/8.2.1/src/Foo/Bar.hs new file mode 100644 index 000000000..ceb08691b --- /dev/null +++ b/test/testdata/wrapper/8.2.1/src/Foo/Bar.hs @@ -0,0 +1,3 @@ +module Foo.Bar where + +baz = 6 diff --git a/test/testdata/wrapper/8.2.1/src/main.hs b/test/testdata/wrapper/8.2.1/src/main.hs new file mode 100644 index 000000000..839d10429 --- /dev/null +++ b/test/testdata/wrapper/8.2.1/src/main.hs @@ -0,0 +1,7 @@ +-- | Testing that HaRe can find source files from a cabal file + +import qualified Foo.Bar as B + +main = putStrLn "foo" + +baz = 3 + B.baz diff --git a/test/testdata/wrapper/lts-11.14/Setup.hs b/test/testdata/wrapper/lts-11.14/Setup.hs new file mode 100644 index 000000000..9a994af67 --- /dev/null +++ b/test/testdata/wrapper/lts-11.14/Setup.hs @@ -0,0 +1,2 @@ +import Distribution.Simple +main = defaultMain diff --git a/test/testdata/wrapper/lts-11.14/cabal.project b/test/testdata/wrapper/lts-11.14/cabal.project new file mode 100644 index 000000000..e6fdbadb4 --- /dev/null +++ b/test/testdata/wrapper/lts-11.14/cabal.project @@ -0,0 +1 @@ +packages: . diff --git a/test/testdata/wrapper/lts-11.14/cabal1.cabal b/test/testdata/wrapper/lts-11.14/cabal1.cabal new file mode 100644 index 000000000..f599b3df0 --- /dev/null +++ b/test/testdata/wrapper/lts-11.14/cabal1.cabal @@ -0,0 +1,25 @@ +-- Initial cabal1.cabal generated by cabal init. For further +-- documentation, see http://haskell.org/cabal/users-guide/ + +name: cabal1 +version: 0.1.0.0 +-- synopsis: +-- description: +license: PublicDomain +-- license-file: LICENSE +author: Alan Zimmerman +maintainer: alan.zimm@gmail.com +-- copyright: +-- category: +build-type: Simple +-- extra-source-files: +-- cabal-helper for cabal 2.2/GHC 8.4 needs a cabal version >= 2 +cabal-version: >=2.0 + +executable cabal1 + main-is: main.hs + -- other-modules: + -- other-extensions: + build-depends: base >=4.6 && <5 + hs-source-dirs: src + default-language: Haskell2010 \ No newline at end of file diff --git a/test/testdata/wrapper/lts-11.14/src/Foo/Bar.hs b/test/testdata/wrapper/lts-11.14/src/Foo/Bar.hs new file mode 100644 index 000000000..ceb08691b --- /dev/null +++ b/test/testdata/wrapper/lts-11.14/src/Foo/Bar.hs @@ -0,0 +1,3 @@ +module Foo.Bar where + +baz = 6 diff --git a/test/testdata/wrapper/lts-11.14/src/main.hs b/test/testdata/wrapper/lts-11.14/src/main.hs new file mode 100644 index 000000000..839d10429 --- /dev/null +++ b/test/testdata/wrapper/lts-11.14/src/main.hs @@ -0,0 +1,7 @@ +-- | Testing that HaRe can find source files from a cabal file + +import qualified Foo.Bar as B + +main = putStrLn "foo" + +baz = 3 + B.baz diff --git a/test/wrapper/HieWrapper.hs b/test/wrapper/HieWrapper.hs index ba18ccf79..f17e4cf49 100644 --- a/test/wrapper/HieWrapper.hs +++ b/test/wrapper/HieWrapper.hs @@ -18,4 +18,4 @@ main = hspec $ withCurrentDirectory "test/testdata/wrapper/ghc" $ do ghcDisplayVer <- readCreateProcess (shell "ghc --version") "" ghcVer <- getProjectGhcVersion - init ghcDisplayVer `shouldEndWith` ghcVer \ No newline at end of file + init ghcDisplayVer `shouldEndWith` ghcVer From 426712a2398d02127888438e77d0ce1f5345255e Mon Sep 17 00:00:00 2001 From: Alan Zimmerman Date: Sat, 15 Jun 2019 12:48:07 +0200 Subject: [PATCH 032/158] More tests pass --- test/functional/FunctionalCodeActionsSpec.hs | 2 +- test/testdata/addPackageTest/hybrid-exe/package.yaml | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/test/functional/FunctionalCodeActionsSpec.hs b/test/functional/FunctionalCodeActionsSpec.hs index 1bd5d3747..f25345d88 100644 --- a/test/functional/FunctionalCodeActionsSpec.hs +++ b/test/functional/FunctionalCodeActionsSpec.hs @@ -293,7 +293,7 @@ spec = describe "code actions" $ do contents <- getDocumentEdit . TextDocumentIdentifier =<< getDocUri "package.yaml" liftIO $ - T.lines contents !! 21 `shouldSatisfy` T.isSuffixOf "zlib" + T.lines contents !! 23 `shouldSatisfy` T.isSuffixOf "zlib" -- ----------------------------------- diff --git a/test/testdata/addPackageTest/hybrid-exe/package.yaml b/test/testdata/addPackageTest/hybrid-exe/package.yaml index 8d9524972..8a03b67e9 100644 --- a/test/testdata/addPackageTest/hybrid-exe/package.yaml +++ b/test/testdata/addPackageTest/hybrid-exe/package.yaml @@ -21,6 +21,8 @@ description: Please see the README on GitHub at Date: Sat, 15 Jun 2019 18:42:53 +0200 Subject: [PATCH 033/158] Tests still pass with stack 1.9.3 --- haskell-ide-engine.cabal | 1 + src/Haskell/Ide/Engine/Plugin/Base.hs | 25 +++++++- test/unit/PackagePluginSpec.hs | 92 +++++++++++++++++++-------- 3 files changed, 88 insertions(+), 30 deletions(-) diff --git a/haskell-ide-engine.cabal b/haskell-ide-engine.cabal index d30b060a0..8c98c9fd8 100644 --- a/haskell-ide-engine.cabal +++ b/haskell-ide-engine.cabal @@ -95,6 +95,7 @@ library , transformers , unordered-containers , vector + , versions , yaml >= 0.8.31 ghc-options: -Wall -Wredundant-constraints if flag(pedantic) diff --git a/src/Haskell/Ide/Engine/Plugin/Base.hs b/src/Haskell/Ide/Engine/Plugin/Base.hs index cfc544047..0d6ac7f98 100644 --- a/src/Haskell/Ide/Engine/Plugin/Base.hs +++ b/src/Haskell/Ide/Engine/Plugin/Base.hs @@ -15,6 +15,7 @@ import Data.Maybe import Data.Semigroup #endif import qualified Data.Text as T +import qualified Data.Versions as V import Development.GitRev (gitCommitCount) import Distribution.System (buildArch) import Distribution.Text (display) @@ -126,14 +127,34 @@ getProjectGhcVersion = do then tryCommand "ghc --numeric-version" else return "No System GHC found" - tryCommand cmd = - init <$> readCreateProcess (shell cmd) "" + +tryCommand :: String -> IO String +tryCommand cmd = + init <$> readCreateProcess (shell cmd) "" hieGhcVersion :: String hieGhcVersion = VERSION_ghc -- --------------------------------------------------------------------- +getStackVersion :: IO (Maybe V.Version) +getStackVersion = do + isStackInstalled <- isJust <$> findExecutable "stack" + if isStackInstalled + then do + versionStr <- tryCommand "stack --numeric-version" + case V.version (T.pack versionStr) of + Left _err -> return Nothing + Right v -> return (Just v) + else return Nothing + +stack193Version :: V.Version +stack193Version = case V.version "1.9.3" of + Left err -> error $ "stack193Version:err=" ++ show err + Right v -> v + +-- --------------------------------------------------------------------- + checkCabalInstall :: IO Bool checkCabalInstall = isJust <$> findExecutable "cabal" diff --git a/test/unit/PackagePluginSpec.hs b/test/unit/PackagePluginSpec.hs index cc220ef22..be46bdbc0 100644 --- a/test/unit/PackagePluginSpec.hs +++ b/test/unit/PackagePluginSpec.hs @@ -9,6 +9,7 @@ import qualified Data.Aeson as Json import qualified Data.Text as T import qualified Data.HashMap.Strict as H import Haskell.Ide.Engine.MonadTypes +import Haskell.Ide.Engine.Plugin.Base import Haskell.Ide.Engine.Plugin.Package import System.FilePath import System.Directory @@ -243,6 +244,7 @@ packageSpec = do "Add package to package.yaml in hpack project with generated cabal to executable component" $ withCurrentDirectory (testdata "hybrid-exe") $ do + Just stackVersion <- getStackVersion let fp = cwd testdata "hybrid-exe" uri = filePathToUri $ fp "package.yaml" @@ -250,34 +252,68 @@ packageSpec = do act = addCmd' args res = IdeResultOk $ WorkspaceEdit (Just $ H.singleton uri textEdits) Nothing - textEdits = List - [ TextEdit (Range (Position 0 0) (Position 34 0)) $ T.concat - [ "library:\n" - , " source-dirs: src\n" - , "copyright: 2018 Author name here\n" - , "maintainer: example@example.com\n" - , "name: asdf\n" - , "version: 0.1.0.0\n" - , "extra-source-files:\n" - , "- README.md\n" - , "- ChangeLog.md\n" - , "author: Author name here\n" - , "github: githubuser/asdf\n" - , "license: BSD3\n" - , "executables:\n" - , " asdf-exe:\n" - , " source-dirs: app\n" - , " main: Main.hs\n" - , " ghc-options:\n" - , " - -threaded\n" - , " - -rtsopts\n" - , " - -with-rtsopts=-N\n" - , " dependencies:\n" - , " - zlib\n" - , " - asdf\n" - , "description: Please see the README on GitHub at \n" - ] - ] + textEdits = if stackVersion <= stack193Version + then + List + [ TextEdit (Range (Position 0 0) (Position 37 0)) $ T.concat + [ "library:\n" + , " source-dirs: src\n" + , " dependencies:\n" + , " - base\n" + , "copyright: 2018 Author name here\n" + , "maintainer: example@example.com\n" + , "name: asdf\n" + , "version: 0.1.0.0\n" + , "extra-source-files:\n" + , "- README.md\n" + , "- ChangeLog.md\n" + , "author: Author name here\n" + , "github: githubuser/asdf\n" + , "license: BSD3\n" + , "executables:\n" + , " asdf-exe:\n" + , " source-dirs: app\n" + , " main: Main.hs\n" + , " ghc-options:\n" + , " - -threaded\n" + , " - -rtsopts\n" + , " - -with-rtsopts=-N\n" + , " dependencies:\n" + , " - zlib\n" + , " - base\n" + , " - asdf\n" + , "description: Please see the README on GitHub at \n" + ] + ] + else + List + [ TextEdit (Range (Position 0 0) (Position 34 0)) $ T.concat + [ "library:\n" + , " source-dirs: src\n" + , "copyright: 2018 Author name here\n" + , "maintainer: example@example.com\n" + , "name: asdf\n" + , "version: 0.1.0.0\n" + , "extra-source-files:\n" + , "- README.md\n" + , "- ChangeLog.md\n" + , "author: Author name here\n" + , "github: githubuser/asdf\n" + , "license: BSD3\n" + , "executables:\n" + , " asdf-exe:\n" + , " source-dirs: app\n" + , " main: Main.hs\n" + , " ghc-options:\n" + , " - -threaded\n" + , " - -rtsopts\n" + , " - -with-rtsopts=-N\n" + , " dependencies:\n" + , " - zlib\n" + , " - asdf\n" + , "description: Please see the README on GitHub at \n" + ] + ] testCommand testPlugins act "package" "add" args res it "Add package to package.yaml in hpack project with generated cabal to library component" $ withCurrentDirectory (testdata "hybrid-lib") From 0e7f9864c83f92f11b2d2be20c3d648aa1ca5f55 Mon Sep 17 00:00:00 2001 From: Alan Zimmerman Date: Sat, 15 Jun 2019 21:07:32 +0200 Subject: [PATCH 034/158] Fix package plugin test, for old and new stack --- test/unit/PackagePluginSpec.hs | 35 +--------------------------------- 1 file changed, 1 insertion(+), 34 deletions(-) diff --git a/test/unit/PackagePluginSpec.hs b/test/unit/PackagePluginSpec.hs index be46bdbc0..e1a0fdbc6 100644 --- a/test/unit/PackagePluginSpec.hs +++ b/test/unit/PackagePluginSpec.hs @@ -9,7 +9,6 @@ import qualified Data.Aeson as Json import qualified Data.Text as T import qualified Data.HashMap.Strict as H import Haskell.Ide.Engine.MonadTypes -import Haskell.Ide.Engine.Plugin.Base import Haskell.Ide.Engine.Plugin.Package import System.FilePath import System.Directory @@ -244,7 +243,6 @@ packageSpec = do "Add package to package.yaml in hpack project with generated cabal to executable component" $ withCurrentDirectory (testdata "hybrid-exe") $ do - Just stackVersion <- getStackVersion let fp = cwd testdata "hybrid-exe" uri = filePathToUri $ fp "package.yaml" @@ -252,9 +250,7 @@ packageSpec = do act = addCmd' args res = IdeResultOk $ WorkspaceEdit (Just $ H.singleton uri textEdits) Nothing - textEdits = if stackVersion <= stack193Version - then - List + textEdits = List [ TextEdit (Range (Position 0 0) (Position 37 0)) $ T.concat [ "library:\n" , " source-dirs: src\n" @@ -285,35 +281,6 @@ packageSpec = do , "description: Please see the README on GitHub at \n" ] ] - else - List - [ TextEdit (Range (Position 0 0) (Position 34 0)) $ T.concat - [ "library:\n" - , " source-dirs: src\n" - , "copyright: 2018 Author name here\n" - , "maintainer: example@example.com\n" - , "name: asdf\n" - , "version: 0.1.0.0\n" - , "extra-source-files:\n" - , "- README.md\n" - , "- ChangeLog.md\n" - , "author: Author name here\n" - , "github: githubuser/asdf\n" - , "license: BSD3\n" - , "executables:\n" - , " asdf-exe:\n" - , " source-dirs: app\n" - , " main: Main.hs\n" - , " ghc-options:\n" - , " - -threaded\n" - , " - -rtsopts\n" - , " - -with-rtsopts=-N\n" - , " dependencies:\n" - , " - zlib\n" - , " - asdf\n" - , "description: Please see the README on GitHub at \n" - ] - ] testCommand testPlugins act "package" "add" args res it "Add package to package.yaml in hpack project with generated cabal to library component" $ withCurrentDirectory (testdata "hybrid-lib") From c25ab7f96c2309c50b82f5b99faf2424199b30ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Avi=20=D7=93?= Date: Sat, 15 Jun 2019 20:27:03 -0400 Subject: [PATCH 035/158] Remove partial function --- src/Haskell/Ide/Engine/Plugin/Hoogle.hs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/Haskell/Ide/Engine/Plugin/Hoogle.hs b/src/Haskell/Ide/Engine/Plugin/Hoogle.hs index 31cf4b5b4..018ccbbf9 100644 --- a/src/Haskell/Ide/Engine/Plugin/Hoogle.hs +++ b/src/Haskell/Ide/Engine/Plugin/Hoogle.hs @@ -1,4 +1,5 @@ {-# LANGUAGE TupleSections #-} +{-# LANGUAGE LambdaCase #-} {-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-} module Haskell.Ide.Engine.Plugin.Hoogle where @@ -99,11 +100,9 @@ infoCmd = CmdSync $ \expr -> do infoCmd' :: T.Text -> IdeM (Either HoogleError T.Text) infoCmd' expr = do HoogleDb mdb <- get - liftIO $ runHoogleQuery mdb expr $ \res -> - if null res then - Left NoResults - else - return $ renderTargetInfo $ head res + liftIO $ runHoogleQuery mdb expr $ \case + [] -> Left NoResults + h:_ -> return $ renderTargetInfo h renderTargetInfo :: Target -> T.Text renderTargetInfo t = @@ -124,11 +123,9 @@ renderTargetInfo t = infoCmdFancyRender :: T.Text -> IdeM (Either HoogleError T.Text) infoCmdFancyRender expr = do HoogleDb mdb <- get - liftIO $ runHoogleQuery mdb expr $ \res -> - if null res then - Left NoResults - else - return $ renderTarget $ head res + liftIO $ runHoogleQuery mdb expr $ \case + [] -> Left NoResults + h:_ -> return $ renderTarget h -- | Render the target in valid markdown. -- Transform haddock documentation into markdown. From 96550a7814d06ce9bac65da1aa0c98f0cf264ee8 Mon Sep 17 00:00:00 2001 From: Alan Zimmerman Date: Sun, 16 Jun 2019 10:31:38 +0200 Subject: [PATCH 036/158] Hacky way to bring in the expected GHC environment file result --- test/unit/GhcModPluginSpec.hs | 10 ++++++++-- test/utils/TestUtils.hs | 4 ++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/test/unit/GhcModPluginSpec.hs b/test/unit/GhcModPluginSpec.hs index 0a413d652..6a87d0e25 100644 --- a/test/unit/GhcModPluginSpec.hs +++ b/test/unit/GhcModPluginSpec.hs @@ -9,7 +9,7 @@ import qualified Data.Map as Map -- import Data.Monoid #endif import qualified Data.Set as S --- import qualified Data.Text as T +import qualified Data.Text as T import Haskell.Ide.Engine.Ghc import Haskell.Ide.Engine.MonadTypes import Haskell.Ide.Engine.Plugin.GhcMod @@ -44,8 +44,14 @@ ghcmodSpec = fp <- makeAbsolute "./FileWithWarning.hs" let act = setTypecheckedModule arg arg = filePathToUri fp + IdeResultOk (_,env) <- runSingle testPlugins act + case env of + [] -> return () + [s] -> T.unpack s `shouldStartWith` "Loaded package environment from" + ss -> fail $ "got:" ++ show ss + let res = IdeResultOk $ - (Map.singleton arg (S.singleton diag), []) + (Map.singleton arg (S.singleton diag), env) diag = Diagnostic (Range (toPos (4,7)) (toPos (4,8))) (Just DsError) diff --git a/test/utils/TestUtils.hs b/test/utils/TestUtils.hs index 91ffc3203..f1137f2f2 100644 --- a/test/utils/TestUtils.hs +++ b/test/utils/TestUtils.hs @@ -5,6 +5,7 @@ module TestUtils , withFileLogging , setupStackFiles , testCommand + , runSingle , runSingleReq , makeRequest , runIGM @@ -60,6 +61,9 @@ testCommand testPlugins act plugin cmd arg res = do newApiRes `shouldBe` res fmap fromDynJSON oldApiRes `shouldBe` fmap Just res +runSingle :: IdePlugins -> IdeGhcM (IdeResult b) -> IO (IdeResult b) +runSingle testPlugins act = runIGM testPlugins act + runSingleReq :: ToJSON a => IdePlugins -> PluginId -> CommandName -> a -> IO (IdeResult DynamicJSON) runSingleReq testPlugins plugin com arg = runIGM testPlugins (makeRequest plugin com arg) From 837983ee9c7f3f396863aa58a71a2966c7618cca Mon Sep 17 00:00:00 2001 From: Alan Zimmerman Date: Sun, 16 Jun 2019 13:27:32 +0200 Subject: [PATCH 037/158] Only run the 'liquid' exe during func-tests Otherwise it fails when running with stack > 2.1 --- src/Haskell/Ide/Engine/Plugin/Liquid.hs | 7 ++++--- test/unit/LiquidSpec.hs | 25 ++++++++++++++----------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/Haskell/Ide/Engine/Plugin/Liquid.hs b/src/Haskell/Ide/Engine/Plugin/Liquid.hs index d46606254..5d01c854d 100644 --- a/src/Haskell/Ide/Engine/Plugin/Liquid.hs +++ b/src/Haskell/Ide/Engine/Plugin/Liquid.hs @@ -156,7 +156,7 @@ generateDiagnosics cb uri file = do -- --------------------------------------------------------------------- --- Find and run the liquid haskell executable +-- | Find and run the liquid haskell executable runLiquidHaskell :: FilePath -> IO (Maybe (ExitCode,[String])) runLiquidHaskell fp = do mexe <- findExecutable "liquid" @@ -168,13 +168,14 @@ runLiquidHaskell fp = do let cmd = lh ++ " --json \"" ++ fp ++ "\"" dir = takeDirectory fp cp = (shell cmd) { cwd = Just dir } - logm $ "runLiquidHaskell:cmd=[" ++ cmd ++ "]" + -- logm $ "runLiquidHaskell:cmd=[" ++ cmd ++ "]" mpp <- lookupEnv "GHC_PACKAGE_PATH" + -- logm $ "runLiquidHaskell:mpp=[" ++ show mpp ++ "]" (ec,o,e) <- bracket (unsetEnv "GHC_PACKAGE_PATH") (\_ -> mapM_ (setEnv "GHC_PACKAGE_PATH") mpp) (\_ -> readCreateProcessWithExitCode cp "") - logm $ "runLiquidHaskell:v=" ++ show (ec,o,e) + -- logm $ "runLiquidHaskell:v=" ++ show (ec,o,e) return $ Just (ec,[o,e]) -- --------------------------------------------------------------------- diff --git a/test/unit/LiquidSpec.hs b/test/unit/LiquidSpec.hs index 1945c89c2..763ff967a 100644 --- a/test/unit/LiquidSpec.hs +++ b/test/unit/LiquidSpec.hs @@ -4,7 +4,6 @@ module LiquidSpec where import Data.Aeson import qualified Data.ByteString.Lazy as BS -import Data.List import qualified Data.Text as T import qualified Data.Text.IO as T import Data.Monoid ((<>)) @@ -12,7 +11,6 @@ import Data.Maybe (isJust) import Haskell.Ide.Engine.MonadTypes import Haskell.Ide.Engine.Plugin.Liquid import System.Directory -import System.Exit import System.FilePath import Test.Hspec @@ -25,18 +23,23 @@ spec = do cwd <- runIO getCurrentDirectory -- --------------------------------- + it "finds liquid haskell exe in $PATH" $ findExecutable "liquid" >>= (`shouldSatisfy` isJust) -- --------------------------------- - -- This produces some products in /test/testdata/liquid/.liquid/ that is used in subsequent test - it "runs the liquid haskell exe" $ do - let - fp = cwd "test/testdata/liquid/Evens.hs" - -- fp = "/home/alanz/tmp/haskell-proc-play/Evens.hs" - -- uri = filePathToUri fp - Just (ef, (msg:_)) <- runLiquidHaskell fp - msg `shouldSatisfy` isPrefixOf "RESULT\n[{\"start\":{\"line\":9,\"column\":1},\"stop\":{\"line\":9,\"column\":8},\"message\":\"Error: Liquid Type Mismatch\\n Inferred type\\n VV : {v : Int | v == (7 : int)}\\n \\n not a subtype of Required type\\n VV : {VV : Int | VV mod 2 == 0}\\n" - ef `shouldBe` ExitFailure 1 + + -- AZ: this test has been moved to func-tests, stack > 2.1 sets + -- its own package environment, we can't run it from here. + + -- -- This produces some products in /test/testdata/liquid/.liquid/ that is used in subsequent test + -- it "runs the liquid haskell exe" $ do + -- let + -- fp = cwd "test/testdata/liquid/Evens.hs" + -- -- fp = "/home/alanz/tmp/haskell-proc-play/Evens.hs" + -- -- uri = filePathToUri fp + -- Just (ef, (msg:_)) <- runLiquidHaskell fp + -- msg `shouldSatisfy` isPrefixOf "RESULT\n[{\"start\":{\"line\":9,\"column\":1},\"stop\":{\"line\":9,\"column\":8},\"message\":\"Error: Liquid Type Mismatch\\n Inferred type\\n VV : {v : Int | v == (7 : int)}\\n \\n not a subtype of Required type\\n VV : {VV : Int | VV mod 2 == 0}\\n" + -- ef `shouldBe` ExitFailure 1 -- --------------------------------- it "gets annot file paths" $ do From 4d179a9efcaf7b4d378d69c4ba976435ac565096 Mon Sep 17 00:00:00 2001 From: Luke Lau Date: Sun, 16 Jun 2019 00:53:37 +0200 Subject: [PATCH 038/158] Fix UriCaches being leaked MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes UriCaches from being leaked via GhcModuleCaches. This is the result of 72 hours at ZuriHac between 3 people and a lot of time spent in gdb. Blog post coming soon Co-Authored-By: Matthew Pickering Co-Authored-By: Daniel Gröber --- hie-plugin-api/Haskell/Ide/Engine/PluginsIdeMonads.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hie-plugin-api/Haskell/Ide/Engine/PluginsIdeMonads.hs b/hie-plugin-api/Haskell/Ide/Engine/PluginsIdeMonads.hs index 0be920042..468d9cbce 100644 --- a/hie-plugin-api/Haskell/Ide/Engine/PluginsIdeMonads.hs +++ b/hie-plugin-api/Haskell/Ide/Engine/PluginsIdeMonads.hs @@ -455,7 +455,7 @@ withIndefiniteProgress t c f = do Just wp -> control $ \run -> wp t c (run f) data IdeState = IdeState - { moduleCache :: GhcModuleCache + { moduleCache :: !GhcModuleCache -- | A queue of requests to be performed once a module is loaded , requestQueue :: Map.Map FilePath [UriCacheResult -> IdeM ()] , extensibleState :: !(Map.Map TypeRep Dynamic) From 98cdef2da9c3a5e71c6ad6a65020d1dd27013dea Mon Sep 17 00:00:00 2001 From: Alan Zimmerman Date: Sun, 16 Jun 2019 15:34:00 +0200 Subject: [PATCH 039/158] Use ghc-mod which loads ghc plugins via https://github.com/alanz/ghc-mod/pull/20 --- submodules/ghc-mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/submodules/ghc-mod b/submodules/ghc-mod index 43476965b..d050fac99 160000 --- a/submodules/ghc-mod +++ b/submodules/ghc-mod @@ -1 +1 @@ -Subproject commit 43476965b5d715f7fcdadd9e14d5e0c53cdb9385 +Subproject commit d050fac998b58fb807e3f95ee7a502d79d566aa2 From ddb5b906b779b8af410bdca53341cf04f162166a Mon Sep 17 00:00:00 2001 From: Zubin Duggal Date: Mon, 17 Jun 2019 00:35:24 +0530 Subject: [PATCH 040/158] Fix file mapping state when we have a parsed module but not a typechecked module --- hie-plugin-api/Haskell/Ide/Engine/ModuleCache.hs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hie-plugin-api/Haskell/Ide/Engine/ModuleCache.hs b/hie-plugin-api/Haskell/Ide/Engine/ModuleCache.hs index d23f975de..aa80778d2 100644 --- a/hie-plugin-api/Haskell/Ide/Engine/ModuleCache.hs +++ b/hie-plugin-api/Haskell/Ide/Engine/ModuleCache.hs @@ -225,7 +225,11 @@ cacheModule uri modul = do let defInfo = CachedInfo mempty mempty mempty mempty rfm return return return $ case muc of Just (UriCacheSuccess uc) -> - let newCI = (cachedInfo uc) { revMap = rfm } + let newCI = oldCI { revMap = rfm . revMap oldCI } + -- ^^^^^^^^^^^^ + -- We have to retain the old mapping state, since the + -- old TypecheckedModule still contains spans relative to that + oldCI = cachedInfo uc in uc { cachedPsMod = pm, cachedInfo = newCI } _ -> UriCache defInfo pm Nothing mempty From f9e15e8b801c552cddaa43c22fc667dbd0f64845 Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Fri, 3 May 2019 14:14:33 +0200 Subject: [PATCH 041/158] Set up CI with Azure Pipelines --- .azure/linux-stack.yml | 37 +++++++++++++++++++++++++++++++++++++ azure-pipelines.yml | 5 +++++ 2 files changed, 42 insertions(+) create mode 100644 .azure/linux-stack.yml create mode 100644 azure-pipelines.yml diff --git a/.azure/linux-stack.yml b/.azure/linux-stack.yml new file mode 100644 index 000000000..7579b0e0d --- /dev/null +++ b/.azure/linux-stack.yml @@ -0,0 +1,37 @@ +jobs: +- job: ${{ parameters.name }} + pool: + vmImage: ${{ parameters.vmImage }} + strategy: + matrix: + stack-def: + BUILD: stack + STACK_YAML: stack.yaml + steps: + - script: | + git submodule sync + git submodule update --init + displayName: Sync submodules + - script: | + export STACK_ROOT="$(Build.SourcesDirectory)"/.stack-root + mkdir -p ~/.local/bin + curl -L https://get.haskellstack.org/stable/linux-x86_64.tar.gz | \ + tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack' + displayName: Install stack + - script: | + export PATH=$HOME/.local/bin:$PATH + stack --install-ghc build --only-dependencies + displayName: Build dependencies + - script: | + export PATH=$HOME/.local/bin:$PATH + stack build + displayName: Build `hie` + - script: | + export PATH=$HOME/.local/bin:$PATH + stack build --test --bench --only-dependencies + stack install # `hie` binary required for tests + displayName: Build Test-dependencies + - script: | + export PATH=$HOME/.local/bin:$PATH + stack test + displayName: Run Test diff --git a/azure-pipelines.yml b/azure-pipelines.yml new file mode 100644 index 000000000..2c68270a3 --- /dev/null +++ b/azure-pipelines.yml @@ -0,0 +1,5 @@ +jobs: +- template: ./.azure/linux-stack.yml + parameters: + name: Linux_Stack + vmImage: ubuntu-16.04 From f347b82a3fc65db8b73f9943661cd3fddb934252 Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Sat, 4 May 2019 23:50:35 +0200 Subject: [PATCH 042/158] install liquidhaskell in azure-ci --- .azure/linux-stack.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.azure/linux-stack.yml b/.azure/linux-stack.yml index 7579b0e0d..35f2b9197 100644 --- a/.azure/linux-stack.yml +++ b/.azure/linux-stack.yml @@ -30,6 +30,10 @@ jobs: export PATH=$HOME/.local/bin:$PATH stack build --test --bench --only-dependencies stack install # `hie` binary required for tests + # TODO: get `cabal` binary from somewhere else? + stack install cabal-install + cabal v1-update + cabal v1-install liquidhaskell displayName: Build Test-dependencies - script: | export PATH=$HOME/.local/bin:$PATH From 1a26d73037e3a78a232949f6c686fa101f9f74ab Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Sun, 5 May 2019 08:25:43 +0200 Subject: [PATCH 043/158] increase job timeout in azure-ci --- .azure/linux-stack.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.azure/linux-stack.yml b/.azure/linux-stack.yml index 35f2b9197..fa275e7a7 100644 --- a/.azure/linux-stack.yml +++ b/.azure/linux-stack.yml @@ -1,5 +1,6 @@ jobs: - job: ${{ parameters.name }} + timeoutInMinutes: 0 pool: vmImage: ${{ parameters.vmImage }} strategy: From 54d543cb0f1e01548a5627bc601c361c58af7f1c Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Sun, 5 May 2019 09:39:54 +0200 Subject: [PATCH 044/158] install liquidhaskell to .local/bin by cabal --- .azure/linux-stack.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.azure/linux-stack.yml b/.azure/linux-stack.yml index fa275e7a7..7c63161e5 100644 --- a/.azure/linux-stack.yml +++ b/.azure/linux-stack.yml @@ -34,7 +34,7 @@ jobs: # TODO: get `cabal` binary from somewhere else? stack install cabal-install cabal v1-update - cabal v1-install liquidhaskell + cabal v1-install liquidhaskell --symlink-bindir=$HOME/.local/bin displayName: Build Test-dependencies - script: | export PATH=$HOME/.local/bin:$PATH From 000f637b12571edc06abf9efeaa096717a9244ba Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Sun, 5 May 2019 17:39:29 +0200 Subject: [PATCH 045/158] generate hoogle-db before azure-ci test --- .azure/linux-stack.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.azure/linux-stack.yml b/.azure/linux-stack.yml index 7c63161e5..f02a19fd9 100644 --- a/.azure/linux-stack.yml +++ b/.azure/linux-stack.yml @@ -33,6 +33,7 @@ jobs: stack install # `hie` binary required for tests # TODO: get `cabal` binary from somewhere else? stack install cabal-install + stack exec hoogle generate cabal v1-update cabal v1-install liquidhaskell --symlink-bindir=$HOME/.local/bin displayName: Build Test-dependencies From f29f87a8f364ede35c1e972fabca87e077d271f8 Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Fri, 10 May 2019 10:33:54 +0200 Subject: [PATCH 046/158] try to use latest liquidhaskell in ci-test --- .azure/linux-stack.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.azure/linux-stack.yml b/.azure/linux-stack.yml index f02a19fd9..e63ee9043 100644 --- a/.azure/linux-stack.yml +++ b/.azure/linux-stack.yml @@ -35,7 +35,7 @@ jobs: stack install cabal-install stack exec hoogle generate cabal v1-update - cabal v1-install liquidhaskell --symlink-bindir=$HOME/.local/bin + cabal v1-install liquidhaskell-0.8.2.4 --symlink-bindir=$HOME/.local/bin displayName: Build Test-dependencies - script: | export PATH=$HOME/.local/bin:$PATH From 61b727392973dea11940385ee6c91d722c6cc965 Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Fri, 10 May 2019 12:02:26 +0200 Subject: [PATCH 047/158] install liuidhaskell with ghc-8.2.2 in ci --- .azure/linux-stack.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.azure/linux-stack.yml b/.azure/linux-stack.yml index e63ee9043..4c990af4d 100644 --- a/.azure/linux-stack.yml +++ b/.azure/linux-stack.yml @@ -35,7 +35,8 @@ jobs: stack install cabal-install stack exec hoogle generate cabal v1-update - cabal v1-install liquidhaskell-0.8.2.4 --symlink-bindir=$HOME/.local/bin + stack setup --stack-yaml=stack-8.2.2.yaml + cabal new-install liquidhaskell-0.8.2.4 --symlink-bindir=$HOME/.local/bin -w $(stack path --stack-yaml=stack-8.2.2.yaml --compiler-exe) displayName: Build Test-dependencies - script: | export PATH=$HOME/.local/bin:$PATH From 2996d19c09664764decfffc2668fb7a814285ca7 Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Fri, 10 May 2019 12:10:41 +0200 Subject: [PATCH 048/158] add own step to install the ghc in azure-ci --- .azure/linux-stack.yml | 12 ++++++++---- .azure/linux.bashrc | 1 + 2 files changed, 9 insertions(+), 4 deletions(-) create mode 100644 .azure/linux.bashrc diff --git a/.azure/linux-stack.yml b/.azure/linux-stack.yml index 4c990af4d..483376224 100644 --- a/.azure/linux-stack.yml +++ b/.azure/linux-stack.yml @@ -20,15 +20,19 @@ jobs: tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack' displayName: Install stack - script: | - export PATH=$HOME/.local/bin:$PATH + source .azure/linux.bashrc + stack setup + displayName: Install GHC + - script: | + source .azure/linux.bashrc stack --install-ghc build --only-dependencies displayName: Build dependencies - script: | - export PATH=$HOME/.local/bin:$PATH + source .azure/linux.bashrc stack build displayName: Build `hie` - script: | - export PATH=$HOME/.local/bin:$PATH + source .azure/linux.bashrc stack build --test --bench --only-dependencies stack install # `hie` binary required for tests # TODO: get `cabal` binary from somewhere else? @@ -39,6 +43,6 @@ jobs: cabal new-install liquidhaskell-0.8.2.4 --symlink-bindir=$HOME/.local/bin -w $(stack path --stack-yaml=stack-8.2.2.yaml --compiler-exe) displayName: Build Test-dependencies - script: | - export PATH=$HOME/.local/bin:$PATH + source .azure/linux.bashrc stack test displayName: Run Test diff --git a/.azure/linux.bashrc b/.azure/linux.bashrc new file mode 100644 index 000000000..61f790fa8 --- /dev/null +++ b/.azure/linux.bashrc @@ -0,0 +1 @@ +export PATH=$HOME/.local/bin:$PATH From bb5b7686481a83095629cdd6511d424d8b1e454c Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Sat, 1 Jun 2019 16:59:29 +0200 Subject: [PATCH 049/158] try install liquidhaskell in old-style for azure-ci --- .azure/linux-stack.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.azure/linux-stack.yml b/.azure/linux-stack.yml index 483376224..89c85c0ea 100644 --- a/.azure/linux-stack.yml +++ b/.azure/linux-stack.yml @@ -40,7 +40,7 @@ jobs: stack exec hoogle generate cabal v1-update stack setup --stack-yaml=stack-8.2.2.yaml - cabal new-install liquidhaskell-0.8.2.4 --symlink-bindir=$HOME/.local/bin -w $(stack path --stack-yaml=stack-8.2.2.yaml --compiler-exe) + cabal v1-install liquidhaskell-0.8.2.4 --symlink-bindir=$HOME/.local/bin -w $(stack path --stack-yaml=stack-8.2.2.yaml --compiler-exe) displayName: Build Test-dependencies - script: | source .azure/linux.bashrc From 615eb1155b06ea1334a2836527ac8e7656540e7b Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Mon, 3 Jun 2019 11:47:11 +0200 Subject: [PATCH 050/158] install smt-solver in azure-ci --- .azure/linux-stack.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.azure/linux-stack.yml b/.azure/linux-stack.yml index 89c85c0ea..70571ce34 100644 --- a/.azure/linux-stack.yml +++ b/.azure/linux-stack.yml @@ -39,6 +39,8 @@ jobs: stack install cabal-install stack exec hoogle generate cabal v1-update + sudo apt update + sudo apt install z3 stack setup --stack-yaml=stack-8.2.2.yaml cabal v1-install liquidhaskell-0.8.2.4 --symlink-bindir=$HOME/.local/bin -w $(stack path --stack-yaml=stack-8.2.2.yaml --compiler-exe) displayName: Build Test-dependencies From 424f743ff00068fc3d6ba561791ca8c6761f0450 Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Mon, 3 Jun 2019 13:09:49 +0200 Subject: [PATCH 051/158] test all versions in azure-ci --- .azure/linux-stack.yml | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/.azure/linux-stack.yml b/.azure/linux-stack.yml index 70571ce34..5f1ad3056 100644 --- a/.azure/linux-stack.yml +++ b/.azure/linux-stack.yml @@ -6,8 +6,23 @@ jobs: strategy: matrix: stack-def: - BUILD: stack STACK_YAML: stack.yaml + stack-8.6.4: + STACK_YAML: stack-8.6.4.yaml + stack-8.6.3: + STACK_YAML: stack-8.6.3.yaml + stack-8.6.2: + STACK_YAML: stack-8.6.2.yaml + stack-8.6.1: + STACK_YAML: stack-8.6.1.yaml + stack-8.4.4: + STACK_YAML: stack-8.4.4.yaml + stack-8.4.3: + STACK_YAML: stack-8.4.3.yaml + stack-8.4.2: + STACK_YAML: stack-8.4.2.yaml + stack-8.2.2: + STACK_YAML: stack-8.4.2.yaml steps: - script: | git submodule sync From f07582823a82a85c8dafb2d2f096ed0da5bdff61 Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Mon, 3 Jun 2019 13:54:42 +0200 Subject: [PATCH 052/158] other platforms for azure-ci --- .azure/linux-stack.yml | 18 +++++------ .azure/macos-stack.yml | 65 ++++++++++++++++++++++++++++++++++++++++ .azure/macos.bashrc | 1 + .azure/windows-stack.yml | 64 +++++++++++++++++++++++++++++++++++++++ .azure/windows.bashrc | 1 + azure-pipelines.yml | 5 ++-- 6 files changed, 142 insertions(+), 12 deletions(-) create mode 100644 .azure/macos-stack.yml create mode 100644 .azure/macos.bashrc create mode 100644 .azure/windows-stack.yml create mode 100644 .azure/windows.bashrc diff --git a/.azure/linux-stack.yml b/.azure/linux-stack.yml index 5f1ad3056..7187b679a 100644 --- a/.azure/linux-stack.yml +++ b/.azure/linux-stack.yml @@ -1,8 +1,8 @@ jobs: -- job: ${{ parameters.name }} +- job: Linux_Stack timeoutInMinutes: 0 pool: - vmImage: ${{ parameters.vmImage }} + vmImage: ubuntu-16.04 strategy: matrix: stack-def: @@ -24,29 +24,29 @@ jobs: stack-8.2.2: STACK_YAML: stack-8.4.2.yaml steps: - - script: | + - bash: | git submodule sync git submodule update --init displayName: Sync submodules - - script: | + - bash: | export STACK_ROOT="$(Build.SourcesDirectory)"/.stack-root mkdir -p ~/.local/bin curl -L https://get.haskellstack.org/stable/linux-x86_64.tar.gz | \ tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack' displayName: Install stack - - script: | + - bash: | source .azure/linux.bashrc stack setup displayName: Install GHC - - script: | + - bash: | source .azure/linux.bashrc stack --install-ghc build --only-dependencies displayName: Build dependencies - - script: | + - bash: | source .azure/linux.bashrc stack build displayName: Build `hie` - - script: | + - bash: | source .azure/linux.bashrc stack build --test --bench --only-dependencies stack install # `hie` binary required for tests @@ -59,7 +59,7 @@ jobs: stack setup --stack-yaml=stack-8.2.2.yaml cabal v1-install liquidhaskell-0.8.2.4 --symlink-bindir=$HOME/.local/bin -w $(stack path --stack-yaml=stack-8.2.2.yaml --compiler-exe) displayName: Build Test-dependencies - - script: | + - bash: | source .azure/linux.bashrc stack test displayName: Run Test diff --git a/.azure/macos-stack.yml b/.azure/macos-stack.yml new file mode 100644 index 000000000..a553ff272 --- /dev/null +++ b/.azure/macos-stack.yml @@ -0,0 +1,65 @@ +jobs: +- job: MacOs_Stack + timeoutInMinutes: 0 + pool: + vmImage: macOS-10.13 + strategy: + matrix: + stack-def: + STACK_YAML: stack.yaml + stack-8.6.4: + STACK_YAML: stack-8.6.4.yaml + stack-8.6.3: + STACK_YAML: stack-8.6.3.yaml + stack-8.6.2: + STACK_YAML: stack-8.6.2.yaml + stack-8.6.1: + STACK_YAML: stack-8.6.1.yaml + stack-8.4.4: + STACK_YAML: stack-8.4.4.yaml + stack-8.4.3: + STACK_YAML: stack-8.4.3.yaml + stack-8.4.2: + STACK_YAML: stack-8.4.2.yaml + stack-8.2.2: + STACK_YAML: stack-8.4.2.yaml + steps: + - bash: | + git submodule sync + git submodule update --init + displayName: Sync submodules + - bash: | + export STACK_ROOT="$(Build.SourcesDirectory)"/.stack-root + mkdir -p ~/.local/bin + curl -skL https://get.haskellstack.org/stable/osx-x86_64.tar.gz | \ + tar xz --strip-components=1 --include '*/stack' -C ~/.local/bin; + displayName: Install stack + - bash: | + source .azure/macos.bashrc + stack setup + displayName: Install GHC + - bash: | + source .azure/macos.bashrc + stack --install-ghc build --only-dependencies + displayName: Build dependencies + - bash: | + source .azure/macos.bashrc + stack build + displayName: Build `hie` + - bash: | + source .azure/macos.bashrc + stack build --test --bench --only-dependencies + stack install # `hie` binary required for tests + # TODO: get `cabal` binary from somewhere else? + stack install cabal-install + stack exec hoogle generate + cabal v1-update + curl -skL https://github.com/Z3Prover/z3/releases/download/Z3-4.8.5/z3-4.8.5-x64-osx-10.14.2.zip | \ + tar xz -C ~/.local; + stack setup --stack-yaml=stack-8.2.2.yaml + cabal v1-install liquidhaskell-0.8.2.4 --symlink-bindir=$HOME/.local/bin -w $(stack path --stack-yaml=stack-8.2.2.yaml --compiler-exe) + displayName: Build Test-dependencies + - bash: | + source .azure/macos.bashrc + stack test + displayName: Run Test diff --git a/.azure/macos.bashrc b/.azure/macos.bashrc new file mode 100644 index 000000000..61f790fa8 --- /dev/null +++ b/.azure/macos.bashrc @@ -0,0 +1 @@ +export PATH=$HOME/.local/bin:$PATH diff --git a/.azure/windows-stack.yml b/.azure/windows-stack.yml new file mode 100644 index 000000000..a5870fa1c --- /dev/null +++ b/.azure/windows-stack.yml @@ -0,0 +1,64 @@ +jobs: +- job: Windows_Stack + timeoutInMinutes: 0 + pool: + vmImage: vs2017-win2016 + strategy: + matrix: + stack-def: + STACK_YAML: stack.yaml + stack-8.6.4: + STACK_YAML: stack-8.6.4.yaml + stack-8.6.3: + STACK_YAML: stack-8.6.3.yaml + stack-8.6.2: + STACK_YAML: stack-8.6.2.yaml + stack-8.6.1: + STACK_YAML: stack-8.6.1.yaml + stack-8.4.4: + STACK_YAML: stack-8.4.4.yaml + stack-8.4.3: + STACK_YAML: stack-8.4.3.yaml + stack-8.4.2: + STACK_YAML: stack-8.4.2.yaml + stack-8.2.2: + STACK_YAML: stack-8.4.2.yaml + steps: + - bash: | + git submodule sync + git submodule update --init + displayName: Sync submodules + - bash: | + export STACK_ROOT="$(Build.SourcesDirectory)"/.stack-root + curl -sSkL http://www.stackage.org/stack/windows-i386 -o /usr/bin/stack.zip + unzip -o /usr/bin/stack.zip -d /usr/bin/ + displayName: Install stack + - bash: | + source .azure/windows.bashrc + stack setup + displayName: Install GHC + - bash: | + source .azure/linux.bashrc + stack --install-ghc build --only-dependencies + displayName: Build dependencies + - bash: | + source .azure/windows.bashrc + stack build + displayName: Build `hie` + - bash: | + source .azure/windows.bashrc + stack build --test --bench --only-dependencies + stack install # `hie` binary required for tests + # TODO: get `cabal` binary from somewhere else? + stack install cabal-install + stack exec hoogle generate + cabal v1-update + curl -L https://github.com/Z3Prover/z3/releases/download/Z3-4.8.5/z3-4.8.5-x64-win.zip -o /usr/local/z3.zip + unzip -o /usr/local/z3.zip -d /usr/local/ + stack setup --stack-yaml=stack-8.2.2.yaml + cabal v1-install liquidhaskell-0.8.2.4 --symlink-bindir=$HOME/.local/bin -w $(stack path --stack-yaml=stack-8.2.2.yaml --compiler-exe) + displayName: Build Test-dependencies + - bash: | + source .azure/windows.bashrc + stack test + displayName: Run Test diff --git a/.azure/windows.bashrc b/.azure/windows.bashrc new file mode 100644 index 000000000..61f790fa8 --- /dev/null +++ b/.azure/windows.bashrc @@ -0,0 +1 @@ +export PATH=$HOME/.local/bin:$PATH diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 2c68270a3..a78fae1c9 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -1,5 +1,4 @@ jobs: - template: ./.azure/linux-stack.yml - parameters: - name: Linux_Stack - vmImage: ubuntu-16.04 +- template: ./.azure/windows-stack.yml +- template: ./.azure/macos-stack.yml From 19389f543e9a339968ed1f24857dba11a8b77a71 Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Mon, 3 Jun 2019 14:22:42 +0200 Subject: [PATCH 053/158] install new version of cabal-install in azure-ci --- .azure/linux-stack.yml | 4 ++-- .azure/macos-stack.yml | 4 ++-- .azure/windows-stack.yml | 3 ++- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.azure/linux-stack.yml b/.azure/linux-stack.yml index 7187b679a..de6e08ee7 100644 --- a/.azure/linux-stack.yml +++ b/.azure/linux-stack.yml @@ -50,8 +50,8 @@ jobs: source .azure/linux.bashrc stack build --test --bench --only-dependencies stack install # `hie` binary required for tests - # TODO: get `cabal` binary from somewhere else? - stack install cabal-install + stack setup --stack-yaml=stack-8.6.5.yaml + stack install --stack-yaml=stack-8.6.5.yaml cabal-install stack exec hoogle generate cabal v1-update sudo apt update diff --git a/.azure/macos-stack.yml b/.azure/macos-stack.yml index a553ff272..41fc6fde8 100644 --- a/.azure/macos-stack.yml +++ b/.azure/macos-stack.yml @@ -50,8 +50,8 @@ jobs: source .azure/macos.bashrc stack build --test --bench --only-dependencies stack install # `hie` binary required for tests - # TODO: get `cabal` binary from somewhere else? - stack install cabal-install + stack setup --stack-yaml=stack-8.6.5.yaml + stack install --stack-yaml=stack-8.6.5.yaml cabal-install stack exec hoogle generate cabal v1-update curl -skL https://github.com/Z3Prover/z3/releases/download/Z3-4.8.5/z3-4.8.5-x64-osx-10.14.2.zip | \ diff --git a/.azure/windows-stack.yml b/.azure/windows-stack.yml index a5870fa1c..ce378b645 100644 --- a/.azure/windows-stack.yml +++ b/.azure/windows-stack.yml @@ -50,7 +50,8 @@ jobs: stack build --test --bench --only-dependencies stack install # `hie` binary required for tests # TODO: get `cabal` binary from somewhere else? - stack install cabal-install + stack setup --stack-yaml=stack-8.6.5.yaml + stack install --stack-yaml=stack-8.6.5.yaml cabal-install stack exec hoogle generate cabal v1-update curl -L https://github.com/Z3Prover/z3/releases/download/Z3-4.8.5/z3-4.8.5-x64-win.zip -o /usr/local/z3.zip From 72600025722dd5c455e3d2e91fce09817f85a5fd Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Thu, 6 Jun 2019 14:56:10 +0200 Subject: [PATCH 054/158] install cabal-install with different ghc in azure-ci --- .azure/linux-stack.yml | 6 ++++-- .azure/macos-stack.yml | 6 ++++-- .azure/windows-stack.yml | 6 ++++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.azure/linux-stack.yml b/.azure/linux-stack.yml index de6e08ee7..051a034be 100644 --- a/.azure/linux-stack.yml +++ b/.azure/linux-stack.yml @@ -7,6 +7,8 @@ jobs: matrix: stack-def: STACK_YAML: stack.yaml + stack-8.6.5: + STACK_YAML: stack-8.6.5.yaml stack-8.6.4: STACK_YAML: stack-8.6.4.yaml stack-8.6.3: @@ -50,8 +52,8 @@ jobs: source .azure/linux.bashrc stack build --test --bench --only-dependencies stack install # `hie` binary required for tests - stack setup --stack-yaml=stack-8.6.5.yaml - stack install --stack-yaml=stack-8.6.5.yaml cabal-install + stack setup --stack-yaml=stack-8.4.4.yaml + stack install --stack-yaml=stack-8.4.4.yaml cabal-install stack exec hoogle generate cabal v1-update sudo apt update diff --git a/.azure/macos-stack.yml b/.azure/macos-stack.yml index 41fc6fde8..9b513863b 100644 --- a/.azure/macos-stack.yml +++ b/.azure/macos-stack.yml @@ -7,6 +7,8 @@ jobs: matrix: stack-def: STACK_YAML: stack.yaml + stack-8.6.5: + STACK_YAML: stack-8.6.5.yaml stack-8.6.4: STACK_YAML: stack-8.6.4.yaml stack-8.6.3: @@ -50,8 +52,8 @@ jobs: source .azure/macos.bashrc stack build --test --bench --only-dependencies stack install # `hie` binary required for tests - stack setup --stack-yaml=stack-8.6.5.yaml - stack install --stack-yaml=stack-8.6.5.yaml cabal-install + stack setup --stack-yaml=stack-8.4.4.yaml + stack install --stack-yaml=stack-8.4.4.yaml cabal-install stack exec hoogle generate cabal v1-update curl -skL https://github.com/Z3Prover/z3/releases/download/Z3-4.8.5/z3-4.8.5-x64-osx-10.14.2.zip | \ diff --git a/.azure/windows-stack.yml b/.azure/windows-stack.yml index ce378b645..c831f78e0 100644 --- a/.azure/windows-stack.yml +++ b/.azure/windows-stack.yml @@ -7,6 +7,8 @@ jobs: matrix: stack-def: STACK_YAML: stack.yaml + stack-8.6.5: + STACK_YAML: stack-8.6.5.yaml stack-8.6.4: STACK_YAML: stack-8.6.4.yaml stack-8.6.3: @@ -50,8 +52,8 @@ jobs: stack build --test --bench --only-dependencies stack install # `hie` binary required for tests # TODO: get `cabal` binary from somewhere else? - stack setup --stack-yaml=stack-8.6.5.yaml - stack install --stack-yaml=stack-8.6.5.yaml cabal-install + stack setup --stack-yaml=stack-8.4.4.yaml + stack install --stack-yaml=stack-8.4.4.yaml cabal-install stack exec hoogle generate cabal v1-update curl -L https://github.com/Z3Prover/z3/releases/download/Z3-4.8.5/z3-4.8.5-x64-win.zip -o /usr/local/z3.zip From 72c3ceabb0b9ed8e9a023141c440b590c36fd15b Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Thu, 6 Jun 2019 15:14:27 +0200 Subject: [PATCH 055/158] install cabal-install with different ghc on azure-ci --- .azure/linux-stack.yml | 4 ++-- .azure/macos-stack.yml | 4 ++-- .azure/windows-stack.yml | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.azure/linux-stack.yml b/.azure/linux-stack.yml index 051a034be..e8325602b 100644 --- a/.azure/linux-stack.yml +++ b/.azure/linux-stack.yml @@ -52,8 +52,8 @@ jobs: source .azure/linux.bashrc stack build --test --bench --only-dependencies stack install # `hie` binary required for tests - stack setup --stack-yaml=stack-8.4.4.yaml - stack install --stack-yaml=stack-8.4.4.yaml cabal-install + stack setup --stack-yaml=stack-8.6.4.yaml + stack install --stack-yaml=stack-8.6.4.yaml cabal-install-2.4.1.0 stack exec hoogle generate cabal v1-update sudo apt update diff --git a/.azure/macos-stack.yml b/.azure/macos-stack.yml index 9b513863b..1583ece31 100644 --- a/.azure/macos-stack.yml +++ b/.azure/macos-stack.yml @@ -52,8 +52,8 @@ jobs: source .azure/macos.bashrc stack build --test --bench --only-dependencies stack install # `hie` binary required for tests - stack setup --stack-yaml=stack-8.4.4.yaml - stack install --stack-yaml=stack-8.4.4.yaml cabal-install + stack setup --stack-yaml=stack-8.6.4.yaml + stack install --stack-yaml=stack-8.6.4.yaml cabal-install-2.4.1.0 stack exec hoogle generate cabal v1-update curl -skL https://github.com/Z3Prover/z3/releases/download/Z3-4.8.5/z3-4.8.5-x64-osx-10.14.2.zip | \ diff --git a/.azure/windows-stack.yml b/.azure/windows-stack.yml index c831f78e0..09e7b7ffc 100644 --- a/.azure/windows-stack.yml +++ b/.azure/windows-stack.yml @@ -52,8 +52,8 @@ jobs: stack build --test --bench --only-dependencies stack install # `hie` binary required for tests # TODO: get `cabal` binary from somewhere else? - stack setup --stack-yaml=stack-8.4.4.yaml - stack install --stack-yaml=stack-8.4.4.yaml cabal-install + stack setup --stack-yaml=stack-8.6.4.yaml + stack install --stack-yaml=stack-8.6.4.yaml cabal-install-2.4.1.0 stack exec hoogle generate cabal v1-update curl -L https://github.com/Z3Prover/z3/releases/download/Z3-4.8.5/z3-4.8.5-x64-win.zip -o /usr/local/z3.zip From d9cddf26ba8f35bd7e68f89844cffced7786fcea Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 10 Jun 2019 18:52:45 +0200 Subject: [PATCH 056/158] Fix stack version --- .azure/linux-stack.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.azure/linux-stack.yml b/.azure/linux-stack.yml index e8325602b..7eddada2d 100644 --- a/.azure/linux-stack.yml +++ b/.azure/linux-stack.yml @@ -24,7 +24,7 @@ jobs: stack-8.4.2: STACK_YAML: stack-8.4.2.yaml stack-8.2.2: - STACK_YAML: stack-8.4.2.yaml + STACK_YAML: stack-8.2.2.yaml steps: - bash: | git submodule sync From 2f1cba25d88a99ee50607e555c502c67af10a5af Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 10 Jun 2019 21:31:27 +0200 Subject: [PATCH 057/158] Use more explicit yaml files --- .azure/linux-stack.yml | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/.azure/linux-stack.yml b/.azure/linux-stack.yml index 7eddada2d..e4b456356 100644 --- a/.azure/linux-stack.yml +++ b/.azure/linux-stack.yml @@ -6,25 +6,25 @@ jobs: strategy: matrix: stack-def: - STACK_YAML: stack.yaml + YAML_FILE: stack.yaml stack-8.6.5: - STACK_YAML: stack-8.6.5.yaml + YAML_FILE: stack-8.6.5.yaml stack-8.6.4: - STACK_YAML: stack-8.6.4.yaml + YAML_FILE: stack-8.6.4.yaml stack-8.6.3: - STACK_YAML: stack-8.6.3.yaml + YAML_FILE: stack-8.6.3.yaml stack-8.6.2: - STACK_YAML: stack-8.6.2.yaml + YAML_FILE: stack-8.6.2.yaml stack-8.6.1: - STACK_YAML: stack-8.6.1.yaml + YAML_FILE: stack-8.6.1.yaml stack-8.4.4: - STACK_YAML: stack-8.4.4.yaml + YAML_FILE: stack-8.4.4.yaml stack-8.4.3: - STACK_YAML: stack-8.4.3.yaml + YAML_FILE: stack-8.4.3.yaml stack-8.4.2: - STACK_YAML: stack-8.4.2.yaml + YAML_FILE: stack-8.4.2.yaml stack-8.2.2: - STACK_YAML: stack-8.2.2.yaml + YAML_FILE: stack-8.2.2.yaml steps: - bash: | git submodule sync @@ -38,23 +38,23 @@ jobs: displayName: Install stack - bash: | source .azure/linux.bashrc - stack setup + stack setup --stack-yaml $(YAML_FILE) displayName: Install GHC - bash: | source .azure/linux.bashrc - stack --install-ghc build --only-dependencies + stack --stack-yaml $(YAML_FILE) --install-ghc build --only-dependencies displayName: Build dependencies - bash: | source .azure/linux.bashrc - stack build + stack build --stack-yaml $(YAML_FILE) displayName: Build `hie` - bash: | source .azure/linux.bashrc - stack build --test --bench --only-dependencies - stack install # `hie` binary required for tests + stack build --stack-yaml $(YAML_FILE) --test --bench --only-dependencies + stack install --stack-yaml $(YAML_FILE) # `hie` binary required for tests stack setup --stack-yaml=stack-8.6.4.yaml stack install --stack-yaml=stack-8.6.4.yaml cabal-install-2.4.1.0 - stack exec hoogle generate + stack --stack-yaml $(YAML_FILE) exec hoogle generate cabal v1-update sudo apt update sudo apt install z3 @@ -63,5 +63,5 @@ jobs: displayName: Build Test-dependencies - bash: | source .azure/linux.bashrc - stack test + stack test --stack-yaml $(YAML_FILE) displayName: Run Test From f86a314fc7d0d5e715f735655f44ec9f7390f254 Mon Sep 17 00:00:00 2001 From: fendor Date: Thu, 13 Jun 2019 13:05:39 +0200 Subject: [PATCH 058/158] Fix pipelines for mac and windows --- .azure/macos-stack.yml | 32 ++++++++++++++++---------------- .azure/windows-stack.yml | 34 ++++++++++++++++------------------ 2 files changed, 32 insertions(+), 34 deletions(-) diff --git a/.azure/macos-stack.yml b/.azure/macos-stack.yml index 1583ece31..1a20ce87a 100644 --- a/.azure/macos-stack.yml +++ b/.azure/macos-stack.yml @@ -6,25 +6,25 @@ jobs: strategy: matrix: stack-def: - STACK_YAML: stack.yaml + YAML_FILE: stack.yaml stack-8.6.5: - STACK_YAML: stack-8.6.5.yaml + YAML_FILE: stack-8.6.5.yaml stack-8.6.4: - STACK_YAML: stack-8.6.4.yaml + YAML_FILE: stack-8.6.4.yaml stack-8.6.3: - STACK_YAML: stack-8.6.3.yaml + YAML_FILE: stack-8.6.3.yaml stack-8.6.2: - STACK_YAML: stack-8.6.2.yaml + YAML_FILE: stack-8.6.2.yaml stack-8.6.1: - STACK_YAML: stack-8.6.1.yaml + YAML_FILE: stack-8.6.1.yaml stack-8.4.4: - STACK_YAML: stack-8.4.4.yaml + YAML_FILE: stack-8.4.4.yaml stack-8.4.3: - STACK_YAML: stack-8.4.3.yaml + YAML_FILE: stack-8.4.3.yaml stack-8.4.2: - STACK_YAML: stack-8.4.2.yaml + YAML_FILE: stack-8.4.2.yaml stack-8.2.2: - STACK_YAML: stack-8.4.2.yaml + YAML_FILE: stack-8.2.2.yaml steps: - bash: | git submodule sync @@ -42,19 +42,19 @@ jobs: displayName: Install GHC - bash: | source .azure/macos.bashrc - stack --install-ghc build --only-dependencies + stack --stack-yaml $(YAML_FILE) --install-ghc build --only-dependencies displayName: Build dependencies - bash: | source .azure/macos.bashrc - stack build + stack build --stack-yaml $(YAML_FILE) displayName: Build `hie` - bash: | source .azure/macos.bashrc - stack build --test --bench --only-dependencies - stack install # `hie` binary required for tests + stack build --stack-yaml $(YAML_FILE) --test --bench --only-dependencies + stack install --stack-yaml $(YAML_FILE) # `hie` binary required for tests stack setup --stack-yaml=stack-8.6.4.yaml stack install --stack-yaml=stack-8.6.4.yaml cabal-install-2.4.1.0 - stack exec hoogle generate + stack exec --stack-yaml $(YAML_FILE) hoogle generate cabal v1-update curl -skL https://github.com/Z3Prover/z3/releases/download/Z3-4.8.5/z3-4.8.5-x64-osx-10.14.2.zip | \ tar xz -C ~/.local; @@ -63,5 +63,5 @@ jobs: displayName: Build Test-dependencies - bash: | source .azure/macos.bashrc - stack test + stack test --stack-yaml $(YAML_FILE) displayName: Run Test diff --git a/.azure/windows-stack.yml b/.azure/windows-stack.yml index 09e7b7ffc..3b789713f 100644 --- a/.azure/windows-stack.yml +++ b/.azure/windows-stack.yml @@ -6,25 +6,23 @@ jobs: strategy: matrix: stack-def: - STACK_YAML: stack.yaml + YAML_FILE: stack.yaml stack-8.6.5: - STACK_YAML: stack-8.6.5.yaml + YAML_FILE: stack-8.6.5.yaml stack-8.6.4: - STACK_YAML: stack-8.6.4.yaml - stack-8.6.3: - STACK_YAML: stack-8.6.3.yaml + YAML_FILE: stack-8.6.4.yaml stack-8.6.2: - STACK_YAML: stack-8.6.2.yaml + YAML_FILE: stack-8.6.2.yaml stack-8.6.1: - STACK_YAML: stack-8.6.1.yaml + YAML_FILE: stack-8.6.1.yaml stack-8.4.4: - STACK_YAML: stack-8.4.4.yaml + YAML_FILE: stack-8.4.4.yaml stack-8.4.3: - STACK_YAML: stack-8.4.3.yaml + YAML_FILE: stack-8.4.3.yaml stack-8.4.2: - STACK_YAML: stack-8.4.2.yaml + YAML_FILE: stack-8.4.2.yaml stack-8.2.2: - STACK_YAML: stack-8.4.2.yaml + YAML_FILE: stack-8.2.2.yaml steps: - bash: | git submodule sync @@ -37,24 +35,24 @@ jobs: displayName: Install stack - bash: | source .azure/windows.bashrc - stack setup + stack setup --stack-yaml $(YAML_FILE) displayName: Install GHC - bash: | source .azure/linux.bashrc - stack --install-ghc build --only-dependencies + stack --stack-yaml $(YAML_FILE) --install-ghc build --only-dependencies displayName: Build dependencies - bash: | source .azure/windows.bashrc - stack build + stack build --stack-yaml $(YAML_FILE) displayName: Build `hie` - bash: | source .azure/windows.bashrc - stack build --test --bench --only-dependencies - stack install # `hie` binary required for tests + stack build --stack-yaml $(YAML_FILE) --test --bench --only-dependencies + stack install --stack-yaml $(YAML_FILE) # `hie` binary required for tests # TODO: get `cabal` binary from somewhere else? stack setup --stack-yaml=stack-8.6.4.yaml stack install --stack-yaml=stack-8.6.4.yaml cabal-install-2.4.1.0 - stack exec hoogle generate + stack exec --stack-yaml $(YAML_FILE) hoogle generate cabal v1-update curl -L https://github.com/Z3Prover/z3/releases/download/Z3-4.8.5/z3-4.8.5-x64-win.zip -o /usr/local/z3.zip unzip -o /usr/local/z3.zip -d /usr/local/ @@ -63,5 +61,5 @@ jobs: displayName: Build Test-dependencies - bash: | source .azure/windows.bashrc - stack test + stack test --stack-yaml $(YAML_FILE) :unit-test displayName: Run Test From 1cf910fd0cd906670e997643b900900c6d1bb966 Mon Sep 17 00:00:00 2001 From: fendor Date: Thu, 13 Jun 2019 17:24:34 +0200 Subject: [PATCH 059/158] Install z3 --- .azure/macos-stack.yml | 9 ++++++--- .azure/windows-stack.yml | 5 +++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/.azure/macos-stack.yml b/.azure/macos-stack.yml index 1a20ce87a..929a1d0e2 100644 --- a/.azure/macos-stack.yml +++ b/.azure/macos-stack.yml @@ -38,7 +38,7 @@ jobs: displayName: Install stack - bash: | source .azure/macos.bashrc - stack setup + stack setup --stack-yaml $(YAML_FILE) displayName: Install GHC - bash: | source .azure/macos.bashrc @@ -52,9 +52,12 @@ jobs: source .azure/macos.bashrc stack build --stack-yaml $(YAML_FILE) --test --bench --only-dependencies stack install --stack-yaml $(YAML_FILE) # `hie` binary required for tests - stack setup --stack-yaml=stack-8.6.4.yaml - stack install --stack-yaml=stack-8.6.4.yaml cabal-install-2.4.1.0 + stack setup --stack-yaml=stack-8.6.5.yaml + stack install --stack-yaml=stack-8.6.5.yaml cabal-install-2.4.1.0 stack exec --stack-yaml $(YAML_FILE) hoogle generate + ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" + brew update + brew install z3 cabal v1-update curl -skL https://github.com/Z3Prover/z3/releases/download/Z3-4.8.5/z3-4.8.5-x64-osx-10.14.2.zip | \ tar xz -C ~/.local; diff --git a/.azure/windows-stack.yml b/.azure/windows-stack.yml index 3b789713f..713882536 100644 --- a/.azure/windows-stack.yml +++ b/.azure/windows-stack.yml @@ -50,9 +50,10 @@ jobs: stack build --stack-yaml $(YAML_FILE) --test --bench --only-dependencies stack install --stack-yaml $(YAML_FILE) # `hie` binary required for tests # TODO: get `cabal` binary from somewhere else? - stack setup --stack-yaml=stack-8.6.4.yaml - stack install --stack-yaml=stack-8.6.4.yaml cabal-install-2.4.1.0 + stack setup --stack-yaml=stack-8.6.5.yaml + stack install --stack-yaml=stack-8.6.5.yaml cabal-install-2.4.1.0 stack exec --stack-yaml $(YAML_FILE) hoogle generate + choco install z3 cabal v1-update curl -L https://github.com/Z3Prover/z3/releases/download/Z3-4.8.5/z3-4.8.5-x64-win.zip -o /usr/local/z3.zip unzip -o /usr/local/z3.zip -d /usr/local/ From f308fd41e481d3859969ac950d01e15301d30aed Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Sun, 16 Jun 2019 22:52:56 +0200 Subject: [PATCH 060/158] update to windows-2019 image --- .azure/windows-stack.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.azure/windows-stack.yml b/.azure/windows-stack.yml index 713882536..800748162 100644 --- a/.azure/windows-stack.yml +++ b/.azure/windows-stack.yml @@ -2,7 +2,7 @@ jobs: - job: Windows_Stack timeoutInMinutes: 0 pool: - vmImage: vs2017-win2016 + vmImage: windows-2019 strategy: matrix: stack-def: From 0fa495a6f30cfdbb8bb20029fb8c1d9922e13ea2 Mon Sep 17 00:00:00 2001 From: Mitsutoshi Aoe Date: Tue, 18 Jun 2019 10:22:19 +0900 Subject: [PATCH 061/158] install.hs: Make all available GHCs in PATH buildable --- install.hs | 44 +++++++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/install.hs b/install.hs index 0e3c314c4..b61323ab3 100755 --- a/install.hs +++ b/install.hs @@ -19,6 +19,7 @@ import Control.Monad.Extra ( unlessM ) import Data.Maybe ( isJust ) import System.Directory ( findExecutable + , findExecutables , listDirectory ) import System.Environment ( getProgName @@ -34,6 +35,8 @@ import Data.Maybe ( isNothing import Data.List ( dropWhileEnd , intersperse , intercalate + , isInfixOf + , nubBy , sort ) import qualified Data.Text as T @@ -42,7 +45,9 @@ import Data.Version ( parseVersion , makeVersion , showVersion ) -import Data.Function ( (&) ) +import Data.Function ( (&) + , on + ) import Text.ParserCombinators.ReadP ( readP_to_S ) type VersionNumber = String @@ -143,7 +148,7 @@ main = do forM_ ghcVersions cabalTest forM_ - hieVersions + ghcVersions (\version -> phony ("cabal-hie-" ++ version) $ do validateCabalNewInstallIsSupported need ["submodules"] @@ -182,7 +187,7 @@ validateCabalNewInstallIsSupported = when isWindowsSystem $ do configureCabal :: VersionNumber -> Action () configureCabal versionNumber = do - ghcPath <- getGhcPath versionNumber >>= \case + ghcPath <- getGhcPathOf versionNumber >>= \case Nothing -> do liftIO $ putStrLn $ embedInStars (ghcVersionNotFoundFailMsg versionNumber) error (ghcVersionNotFoundFailMsg versionNumber) @@ -193,12 +198,18 @@ configureCabal versionNumber = do findInstalledGhcs :: IO [(VersionNumber, GhcPath)] findInstalledGhcs = do hieVersions <- getHieVersions :: IO [VersionNumber] - mapMaybeM - (\version -> getGhcPath version >>= \case + knownGhcs <- mapMaybeM + (\version -> getGhcPathOf version >>= \case Nothing -> return Nothing Just p -> return $ Just (version, p) ) (reverse hieVersions) + availableGhcs <- getGhcPaths + return + -- filter out stack provided GHCs + $ filter (not . isInfixOf ".stack" . snd) + -- nub by version. knownGhcs takes precedence. + $ nubBy ((==) `on` fst) (knownGhcs ++ availableGhcs) cabalBuildHie :: VersionNumber -> Action () cabalBuildHie versionNumber = do @@ -515,16 +526,19 @@ getStackGhcPathShake = do -- First, it is checked whether there is a GHC with the name `ghc-$VersionNumber`. -- If this yields no result, it is checked, whether the numeric-version of the `ghc` -- command fits to the desired version. -getGhcPath :: MonadIO m => VersionNumber -> m (Maybe GhcPath) -getGhcPath ghcVersion = liftIO $ - findExecutable ("ghc-" ++ ghcVersion) >>= \case - Nothing -> do - findExecutable "ghc" >>= \case - Nothing -> return Nothing - Just p -> do - Stdout version <- cmd p ["--numeric-version"] :: IO (Stdout String) - if ghcVersion == trim version then return $ Just p else return Nothing - p -> return p +getGhcPathOf :: MonadIO m => VersionNumber -> m (Maybe GhcPath) +getGhcPathOf ghcVersion = + liftIO $ findExecutable ("ghc-" ++ ghcVersion) >>= \case + Nothing -> lookup ghcVersion <$> getGhcPaths + path -> return path + +-- | Get a list of GHCs that are available in $PATH +getGhcPaths :: MonadIO m => m [(VersionNumber, GhcPath)] +getGhcPaths = liftIO $ do + paths <- findExecutables "ghc" + forM paths $ \path -> do + Stdout version <- cmd path ["--numeric-version"] + return (trim version, path) -- | Read the local install root of the stack project specified by the VersionNumber -- Returns the filepath of the local install root. From de8e8fff971d67b92548fcaec53e41ff45237e01 Mon Sep 17 00:00:00 2001 From: Alan Zimmerman Date: Tue, 18 Jun 2019 18:11:30 +0200 Subject: [PATCH 062/158] Use ghc-mod without memory leak As fixed by @bubba in https://github.com/alanz/ghc-mod/pull/21 --- submodules/ghc-mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/submodules/ghc-mod b/submodules/ghc-mod index d050fac99..910887b2c 160000 --- a/submodules/ghc-mod +++ b/submodules/ghc-mod @@ -1 +1 @@ -Subproject commit d050fac998b58fb807e3f95ee7a502d79d566aa2 +Subproject commit 910887b2c33237b703417ec07f35ca8bbf35d729 From fdaf48bc135332278211c9a07ae9ce3cc5fb5b33 Mon Sep 17 00:00:00 2001 From: Mitsutoshi Aoe Date: Wed, 19 Jun 2019 09:02:08 +0900 Subject: [PATCH 063/158] fixup! install.hs: Make all available GHCs in PATH buildable --- install.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/install.hs b/install.hs index b61323ab3..c3ca1b0f1 100755 --- a/install.hs +++ b/install.hs @@ -206,10 +206,10 @@ findInstalledGhcs = do (reverse hieVersions) availableGhcs <- getGhcPaths return - -- filter out stack provided GHCs - $ filter (not . isInfixOf ".stack" . snd) -- nub by version. knownGhcs takes precedence. - $ nubBy ((==) `on` fst) (knownGhcs ++ availableGhcs) + $ nubBy ((==) `on` fst) + -- filter out stack provided GHCs + $ filter (not . isInfixOf ".stack" . snd) (knownGhcs ++ availableGhcs) cabalBuildHie :: VersionNumber -> Action () cabalBuildHie versionNumber = do From 87d798623ba3fafeca574a0f1ca5343425459f13 Mon Sep 17 00:00:00 2001 From: Alan Zimmerman Date: Wed, 19 Jun 2019 17:33:18 +0200 Subject: [PATCH 064/158] Remove brittany submodule in favour of hackage version --- .gitmodules | 4 ---- stack-8.2.2.yaml | 3 +-- stack-8.4.2.yaml | 3 +-- stack-8.4.3.yaml | 2 +- stack-8.4.4.yaml | 3 +-- stack-8.6.1.yaml | 2 +- stack-8.6.2.yaml | 2 +- stack-8.6.3.yaml | 2 +- stack-8.6.4.yaml | 2 +- stack-8.6.5.yaml | 2 +- stack.yaml | 2 +- 11 files changed, 10 insertions(+), 17 deletions(-) diff --git a/.gitmodules b/.gitmodules index 4e873c34d..2ca9d7a2a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -15,10 +15,6 @@ # url = https://github.com/bubba/HaRe.git url = https://github.com/alanz/HaRe.git -[submodule "submodules/brittany"] - path = submodules/brittany - url = https://github.com/lspitzner/brittany.git - [submodule "submodules/cabal-helper"] path = submodules/cabal-helper # url = https://github.com/arbor/cabal-helper.git diff --git a/stack-8.2.2.yaml b/stack-8.2.2.yaml index 2ebcc6d44..184c45494 100644 --- a/stack-8.2.2.yaml +++ b/stack-8.2.2.yaml @@ -5,13 +5,12 @@ packages: extra-deps: - ./submodules/HaRe -- ./submodules/brittany - ./submodules/cabal-helper - ./submodules/ghc-mod - ./submodules/ghc-mod/core - ./submodules/ghc-mod/ghc-project-types -# - brittany-0.11.0.0 +- brittany-0.12.0.0 - butcher-1.3.1.1 - cabal-plan-0.3.0.0 - conduit-parse-0.2.1.0 diff --git a/stack-8.4.2.yaml b/stack-8.4.2.yaml index 2dccd4d5d..2a908d531 100644 --- a/stack-8.4.2.yaml +++ b/stack-8.4.2.yaml @@ -5,13 +5,12 @@ packages: extra-deps: - ./submodules/HaRe -- ./submodules/brittany - ./submodules/cabal-helper - ./submodules/ghc-mod - ./submodules/ghc-mod/core - ./submodules/ghc-mod/ghc-project-types -# - brittany-0.11.0.0 +- brittany-0.12.0.0 - base-compat-0.9.3 - cabal-plan-0.3.0.0 - constrained-dynamic-0.1.0.0 diff --git a/stack-8.4.3.yaml b/stack-8.4.3.yaml index 8fc7c5bc5..67b6df6e3 100644 --- a/stack-8.4.3.yaml +++ b/stack-8.4.3.yaml @@ -5,13 +5,13 @@ packages: extra-deps: - ./submodules/HaRe -- ./submodules/brittany - ./submodules/cabal-helper - ./submodules/ghc-mod - ./submodules/ghc-mod/core - ./submodules/ghc-mod/ghc-project-types - base-compat-0.9.3 +- brittany-0.12.0.0 - cabal-plan-0.3.0.0 - constrained-dynamic-0.1.0.0 - floskell-0.10.0 diff --git a/stack-8.4.4.yaml b/stack-8.4.4.yaml index b77dd3d33..3037eff15 100644 --- a/stack-8.4.4.yaml +++ b/stack-8.4.4.yaml @@ -5,13 +5,12 @@ packages: extra-deps: - ./submodules/HaRe -- ./submodules/brittany - ./submodules/cabal-helper - ./submodules/ghc-mod - ./submodules/ghc-mod/core - ./submodules/ghc-mod/ghc-project-types -# - brittany-0.11.0.0 +- brittany-0.12.0.0 - cabal-plan-0.4.0.0 - constrained-dynamic-0.1.0.0 - floskell-0.10.0 diff --git a/stack-8.6.1.yaml b/stack-8.6.1.yaml index 6c7e43ccb..faa4c3080 100644 --- a/stack-8.6.1.yaml +++ b/stack-8.6.1.yaml @@ -5,13 +5,13 @@ packages: extra-deps: - ./submodules/HaRe -- ./submodules/brittany - ./submodules/cabal-helper - ./submodules/ghc-mod - ./submodules/ghc-mod/core - ./submodules/ghc-mod/ghc-project-types - apply-refact-0.6.0.0 +- brittany-0.12.0.0 - butcher-1.3.2.1 - cabal-install-2.4.0.0 - cabal-plan-0.4.0.0 diff --git a/stack-8.6.2.yaml b/stack-8.6.2.yaml index c0424c775..2ca931f02 100644 --- a/stack-8.6.2.yaml +++ b/stack-8.6.2.yaml @@ -5,12 +5,12 @@ packages: extra-deps: - ./submodules/HaRe -- ./submodules/brittany - ./submodules/cabal-helper - ./submodules/ghc-mod - ./submodules/ghc-mod/core - ./submodules/ghc-mod/ghc-project-types +- brittany-0.12.0.0 - butcher-1.3.2.1 - cabal-plan-0.4.0.0 - constrained-dynamic-0.1.0.0 diff --git a/stack-8.6.3.yaml b/stack-8.6.3.yaml index 0af5b4a14..18cfecaa3 100644 --- a/stack-8.6.3.yaml +++ b/stack-8.6.3.yaml @@ -5,12 +5,12 @@ packages: extra-deps: - ./submodules/HaRe -- ./submodules/brittany - ./submodules/cabal-helper - ./submodules/ghc-mod - ./submodules/ghc-mod/core - ./submodules/ghc-mod/ghc-project-types +- brittany-0.12.0.0 - butcher-1.3.2.1 - cabal-plan-0.4.0.0 - constrained-dynamic-0.1.0.0 diff --git a/stack-8.6.4.yaml b/stack-8.6.4.yaml index b1087ee4f..e9451f6ae 100644 --- a/stack-8.6.4.yaml +++ b/stack-8.6.4.yaml @@ -5,12 +5,12 @@ packages: extra-deps: - ./submodules/HaRe -- ./submodules/brittany - ./submodules/cabal-helper - ./submodules/ghc-mod - ./submodules/ghc-mod/core - ./submodules/ghc-mod/ghc-project-types +- brittany-0.12.0.0 - butcher-1.3.2.1 - cabal-plan-0.4.0.0 - constrained-dynamic-0.1.0.0 diff --git a/stack-8.6.5.yaml b/stack-8.6.5.yaml index 149f26a17..4d031beba 100644 --- a/stack-8.6.5.yaml +++ b/stack-8.6.5.yaml @@ -5,12 +5,12 @@ packages: extra-deps: - ./submodules/HaRe -- ./submodules/brittany - ./submodules/cabal-helper - ./submodules/ghc-mod - ./submodules/ghc-mod/core - ./submodules/ghc-mod/ghc-project-types +- brittany-0.12.0.0 - butcher-1.3.2.1 - cabal-plan-0.4.0.0 - constrained-dynamic-0.1.0.0 diff --git a/stack.yaml b/stack.yaml index 49a947db9..0bf95c7a7 100644 --- a/stack.yaml +++ b/stack.yaml @@ -5,7 +5,6 @@ packages: extra-deps: - ./submodules/HaRe -- ./submodules/brittany - ./submodules/cabal-helper - ./submodules/ghc-mod - ./submodules/ghc-mod/core @@ -13,6 +12,7 @@ extra-deps: - ansi-terminal-0.8.2 - ansi-wl-pprint-0.6.8.2 +- brittany-0.12.0.0 - butcher-1.3.2.1 - cabal-plan-0.4.0.0 - constrained-dynamic-0.1.0.0 From 0878f557fb24a749392b47254e93ee9989c7cb7d Mon Sep 17 00:00:00 2001 From: Alan Zimmerman Date: Wed, 19 Jun 2019 17:39:34 +0200 Subject: [PATCH 065/158] Remove brittany submodule --- submodules/brittany | 1 - 1 file changed, 1 deletion(-) delete mode 160000 submodules/brittany diff --git a/submodules/brittany b/submodules/brittany deleted file mode 160000 index 6c187da8f..000000000 --- a/submodules/brittany +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 6c187da8f8166d595f36d6aaf419370283b3d1e9 From 1e740c708305384a535ce2a7ad39dcf4f444877d Mon Sep 17 00:00:00 2001 From: Alan Zimmerman Date: Wed, 19 Jun 2019 19:36:04 +0200 Subject: [PATCH 066/158] Remove brittany submodule from cabal project too --- cabal.project | 1 - 1 file changed, 1 deletion(-) diff --git a/cabal.project b/cabal.project index 809c1948d..27c72c99c 100644 --- a/cabal.project +++ b/cabal.project @@ -3,7 +3,6 @@ packages: ./hie-plugin-api/ ./submodules/HaRe - ./submodules/brittany ./submodules/cabal-helper/ ./submodules/ghc-mod/ ./submodules/ghc-mod/core/ From 810b7ec097a15a8210ad1c2f70cc7c2d8c912928 Mon Sep 17 00:00:00 2001 From: jneira Date: Thu, 20 Jun 2019 14:08:40 +0200 Subject: [PATCH 067/158] Use last nightly resolver with unix-time-0.4.7 --- stack.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stack.yaml b/stack.yaml index 0bf95c7a7..973e0da74 100644 --- a/stack.yaml +++ b/stack.yaml @@ -1,4 +1,4 @@ -resolver: nightly-2019-05-31 # GHC 8.6.5 +resolver: nightly-2019-06-20 # GHC 8.6.5 packages: - . - hie-plugin-api From 9e02d569dd9c3d89bbb1140e29129d9015614e69 Mon Sep 17 00:00:00 2001 From: jneira Date: Thu, 20 Jun 2019 14:10:04 +0200 Subject: [PATCH 068/158] Use last lts resolver with unix-time-0.4.7 --- stack-8.6.5.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stack-8.6.5.yaml b/stack-8.6.5.yaml index 4d031beba..9bb5a0574 100644 --- a/stack-8.6.5.yaml +++ b/stack-8.6.5.yaml @@ -1,4 +1,4 @@ -resolver: lts-13.23 # First GHC 8.6.5 +resolver: lts-13.26 # First GHC 8.6.5 with unix-time >= 0.4.6 packages: - . - hie-plugin-api From 9e8c37ce82fdfbfba841c4c5afeefa0690427f09 Mon Sep 17 00:00:00 2001 From: jneira Date: Thu, 20 Jun 2019 14:10:38 +0200 Subject: [PATCH 069/158] Add unix-time-0.4.7 as extra-dep --- stack-8.2.2.yaml | 2 ++ stack-8.4.2.yaml | 2 ++ stack-8.4.3.yaml | 2 ++ stack-8.4.4.yaml | 2 ++ stack-8.6.1.yaml | 2 ++ stack-8.6.2.yaml | 2 ++ stack-8.6.3.yaml | 2 ++ stack-8.6.4.yaml | 2 ++ 8 files changed, 16 insertions(+) diff --git a/stack-8.2.2.yaml b/stack-8.2.2.yaml index 184c45494..65b0415e0 100644 --- a/stack-8.2.2.yaml +++ b/stack-8.2.2.yaml @@ -33,6 +33,8 @@ extra-deps: - rope-utf16-splay-0.3.1.0 - sorted-list-0.2.1.0 - syz-0.2.0.0 +# To make build work in windows 7 +- unix-time-0.4.7 flags: haskell-ide-engine: diff --git a/stack-8.4.2.yaml b/stack-8.4.2.yaml index 2a908d531..ec92a9c33 100644 --- a/stack-8.4.2.yaml +++ b/stack-8.4.2.yaml @@ -32,6 +32,8 @@ extra-deps: - rope-utf16-splay-0.3.1.0 - syz-0.2.0.0 - temporary-1.2.1.1 +# To make build work in windows 7 +- unix-time-0.4.7 - windns-0.1.0.0 - yaml-0.8.32 - yi-rope-0.11 diff --git a/stack-8.4.3.yaml b/stack-8.4.3.yaml index 67b6df6e3..f8d756903 100644 --- a/stack-8.4.3.yaml +++ b/stack-8.4.3.yaml @@ -31,6 +31,8 @@ extra-deps: - pretty-show-1.8.2 - rope-utf16-splay-0.3.1.0 - syz-0.2.0.0 +# To make build work in windows 7 +- unix-time-0.4.7 - temporary-1.2.1.1 flags: diff --git a/stack-8.4.4.yaml b/stack-8.4.4.yaml index 3037eff15..30200043a 100644 --- a/stack-8.4.4.yaml +++ b/stack-8.4.4.yaml @@ -31,6 +31,8 @@ extra-deps: - pretty-show-1.9.5 - rope-utf16-splay-0.3.1.0 - syz-0.2.0.0 +# To make build work in windows 7 +- unix-time-0.4.7 - temporary-1.2.1.1 flags: diff --git a/stack-8.6.1.yaml b/stack-8.6.1.yaml index faa4c3080..1479408ec 100644 --- a/stack-8.6.1.yaml +++ b/stack-8.6.1.yaml @@ -38,6 +38,8 @@ extra-deps: - rope-utf16-splay-0.3.1.0 - syz-0.2.0.0 - temporary-1.2.1.1 +# To make build work in windows 7 +- unix-time-0.4.7 - yaml-0.8.32 flags: diff --git a/stack-8.6.2.yaml b/stack-8.6.2.yaml index 2ca931f02..2fc6e881f 100644 --- a/stack-8.6.2.yaml +++ b/stack-8.6.2.yaml @@ -31,6 +31,8 @@ extra-deps: - rope-utf16-splay-0.3.1.0 - syz-0.2.0.0 - temporary-1.2.1.1 +# To make build work in windows 7 +- unix-time-0.4.7 - yaml-0.8.32 flags: diff --git a/stack-8.6.3.yaml b/stack-8.6.3.yaml index 18cfecaa3..14059e83b 100644 --- a/stack-8.6.3.yaml +++ b/stack-8.6.3.yaml @@ -32,6 +32,8 @@ extra-deps: - rope-utf16-splay-0.3.1.0 - syz-0.2.0.0 - temporary-1.2.1.1 +# To make build work in windows 7 +- unix-time-0.4.7 - yaml-0.8.32 flags: diff --git a/stack-8.6.4.yaml b/stack-8.6.4.yaml index e9451f6ae..5df504e5c 100644 --- a/stack-8.6.4.yaml +++ b/stack-8.6.4.yaml @@ -30,6 +30,8 @@ extra-deps: - rope-utf16-splay-0.3.1.0 - syz-0.2.0.0 - temporary-1.2.1.1 +# To make build work in windows 7 +- unix-time-0.4.7 - yaml-0.8.32 flags: From 032d7d78ca845983c334471a0583c0bf8165c3bf Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Rodriguez Date: Thu, 20 Jun 2019 15:46:22 +0200 Subject: [PATCH 070/158] Fix a memory leak found by mpickering --- hie-plugin-api/Haskell/Ide/Engine/ModuleCache.hs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hie-plugin-api/Haskell/Ide/Engine/ModuleCache.hs b/hie-plugin-api/Haskell/Ide/Engine/ModuleCache.hs index aa80778d2..6f7dad940 100644 --- a/hie-plugin-api/Haskell/Ide/Engine/ModuleCache.hs +++ b/hie-plugin-api/Haskell/Ide/Engine/ModuleCache.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE BangPatterns #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE FlexibleContexts #-} @@ -53,7 +54,8 @@ import Haskell.Ide.Engine.PluginsIdeMonads modifyCache :: (HasGhcModuleCache m) => (GhcModuleCache -> GhcModuleCache) -> m () modifyCache f = do mc <- getModuleCache - setModuleCache (f mc) + let !cached = f mc -- Avoid a space leak by forcing the cache calculation + setModuleCache cached -- --------------------------------------------------------------------- -- | Runs an IdeM action with the given Cradle From cf1510e699855f0e15a2640df61a2a90500fa478 Mon Sep 17 00:00:00 2001 From: jneira Date: Thu, 20 Jun 2019 22:57:34 +0200 Subject: [PATCH 071/158] Use unix-time extra dep instead bump up resolvers --- stack-8.6.5.yaml | 4 +++- stack.yaml | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/stack-8.6.5.yaml b/stack-8.6.5.yaml index 9bb5a0574..e24840307 100644 --- a/stack-8.6.5.yaml +++ b/stack-8.6.5.yaml @@ -1,4 +1,4 @@ -resolver: lts-13.26 # First GHC 8.6.5 with unix-time >= 0.4.6 +resolver: lts-13.23 # First GHC 8.6.5 packages: - . - hie-plugin-api @@ -30,6 +30,8 @@ extra-deps: - rope-utf16-splay-0.3.1.0 - syz-0.2.0.0 - temporary-1.2.1.1 +# To make build work in windows 7 +- unix-time-0.4.7 - yaml-0.8.32 flags: diff --git a/stack.yaml b/stack.yaml index 973e0da74..82b19111e 100644 --- a/stack.yaml +++ b/stack.yaml @@ -1,4 +1,4 @@ -resolver: nightly-2019-06-20 # GHC 8.6.5 +resolver: nightly-2019-05-31 # GHC 8.6.5 packages: - . - hie-plugin-api @@ -31,6 +31,8 @@ extra-deps: - multistate-0.8.0.1 - syz-0.2.0.0 - temporary-1.2.1.1 +# To make build work in windows 7 +- unix-time-0.4.7 - yaml-0.8.32 flags: From d373655d80974db8a6040619a9d999c244155e7e Mon Sep 17 00:00:00 2001 From: Alan Zimmerman Date: Fri, 21 Jun 2019 09:13:26 +0200 Subject: [PATCH 072/158] Add unix-time constraint to cabal file This makes sure PR #1304 is complete, constraining the cabal build as well, for Windows 7 --- haskell-ide-engine.cabal | 1 + 1 file changed, 1 insertion(+) diff --git a/haskell-ide-engine.cabal b/haskell-ide-engine.cabal index 8c98c9fd8..7cfb385fd 100644 --- a/haskell-ide-engine.cabal +++ b/haskell-ide-engine.cabal @@ -93,6 +93,7 @@ library , tagsoup , text , transformers + , unix-time >= 0.4.7 , unordered-containers , vector , versions From b7fb445fa51154dcaac715094586cb1bdbe9e0ed Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Rodriguez Date: Fri, 21 Jun 2019 09:50:55 +0200 Subject: [PATCH 073/158] Making setCache strict in it's first argument instead --- hie-plugin-api/Haskell/Ide/Engine/ModuleCache.hs | 4 +--- hie-plugin-api/Haskell/Ide/Engine/PluginsIdeMonads.hs | 3 ++- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/hie-plugin-api/Haskell/Ide/Engine/ModuleCache.hs b/hie-plugin-api/Haskell/Ide/Engine/ModuleCache.hs index 6f7dad940..aa80778d2 100644 --- a/hie-plugin-api/Haskell/Ide/Engine/ModuleCache.hs +++ b/hie-plugin-api/Haskell/Ide/Engine/ModuleCache.hs @@ -1,4 +1,3 @@ -{-# LANGUAGE BangPatterns #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE FlexibleContexts #-} @@ -54,8 +53,7 @@ import Haskell.Ide.Engine.PluginsIdeMonads modifyCache :: (HasGhcModuleCache m) => (GhcModuleCache -> GhcModuleCache) -> m () modifyCache f = do mc <- getModuleCache - let !cached = f mc -- Avoid a space leak by forcing the cache calculation - setModuleCache cached + setModuleCache (f mc) -- --------------------------------------------------------------------- -- | Runs an IdeM action with the given Cradle diff --git a/hie-plugin-api/Haskell/Ide/Engine/PluginsIdeMonads.hs b/hie-plugin-api/Haskell/Ide/Engine/PluginsIdeMonads.hs index 468d9cbce..06bf7b7eb 100644 --- a/hie-plugin-api/Haskell/Ide/Engine/PluginsIdeMonads.hs +++ b/hie-plugin-api/Haskell/Ide/Engine/PluginsIdeMonads.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE BangPatterns #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE DeriveAnyClass #-} @@ -499,7 +500,7 @@ instance HasGhcModuleCache IdeM where tvar <- lift ask state <- liftIO $ readTVarIO tvar return (moduleCache state) - setModuleCache mc = do + setModuleCache !mc = do tvar <- lift ask liftIO $ atomically $ modifyTVar' tvar (\st -> st { moduleCache = mc }) From 3563ef1ac86677fc85858c152c5f02662372578a Mon Sep 17 00:00:00 2001 From: jneira Date: Mon, 24 Jun 2019 08:17:36 +0200 Subject: [PATCH 074/158] Show stack path --- .azure/windows-stack.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.azure/windows-stack.yml b/.azure/windows-stack.yml index 800748162..37174de79 100644 --- a/.azure/windows-stack.yml +++ b/.azure/windows-stack.yml @@ -41,6 +41,9 @@ jobs: source .azure/linux.bashrc stack --stack-yaml $(YAML_FILE) --install-ghc build --only-dependencies displayName: Build dependencies + - bash: | + stack --stack-yaml $(YAML_FILE) path + displayName: Show stack paths - bash: | source .azure/windows.bashrc stack build --stack-yaml $(YAML_FILE) From 45e6f99dd20ddec619695d3553b067e97c3145ab Mon Sep 17 00:00:00 2001 From: jneira Date: Mon, 24 Jun 2019 08:34:31 +0200 Subject: [PATCH 075/158] Set STACK_ROOT to /sr to avoid long paths issues --- .azure/windows-stack.yml | 3 --- .azure/windows.bashrc | 1 + 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/.azure/windows-stack.yml b/.azure/windows-stack.yml index 37174de79..800748162 100644 --- a/.azure/windows-stack.yml +++ b/.azure/windows-stack.yml @@ -41,9 +41,6 @@ jobs: source .azure/linux.bashrc stack --stack-yaml $(YAML_FILE) --install-ghc build --only-dependencies displayName: Build dependencies - - bash: | - stack --stack-yaml $(YAML_FILE) path - displayName: Show stack paths - bash: | source .azure/windows.bashrc stack build --stack-yaml $(YAML_FILE) diff --git a/.azure/windows.bashrc b/.azure/windows.bashrc index 61f790fa8..9b7eb7ee6 100644 --- a/.azure/windows.bashrc +++ b/.azure/windows.bashrc @@ -1 +1,2 @@ export PATH=$HOME/.local/bin:$PATH +export STACK_ROOT=/sr From b5c8271714b948175a27160b53bb3b02401665cb Mon Sep 17 00:00:00 2001 From: jneira Date: Mon, 24 Jun 2019 09:08:52 +0200 Subject: [PATCH 076/158] Set STACK_ROOT using job property --- .azure/windows-stack.yml | 2 ++ .azure/windows.bashrc | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.azure/windows-stack.yml b/.azure/windows-stack.yml index 800748162..e9fb4ea70 100644 --- a/.azure/windows-stack.yml +++ b/.azure/windows-stack.yml @@ -3,6 +3,8 @@ jobs: timeoutInMinutes: 0 pool: vmImage: windows-2019 + variables: + STACK_ROOT: "C:\sr" strategy: matrix: stack-def: diff --git a/.azure/windows.bashrc b/.azure/windows.bashrc index 9b7eb7ee6..1c5132398 100644 --- a/.azure/windows.bashrc +++ b/.azure/windows.bashrc @@ -1,2 +1,2 @@ export PATH=$HOME/.local/bin:$PATH -export STACK_ROOT=/sr + From 8251f4fad3437eafbb62270e6a17b5f658dda3d3 Mon Sep 17 00:00:00 2001 From: jneira Date: Mon, 24 Jun 2019 09:10:02 +0200 Subject: [PATCH 077/158] Escape path separator --- .azure/windows-stack.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.azure/windows-stack.yml b/.azure/windows-stack.yml index e9fb4ea70..df67e871a 100644 --- a/.azure/windows-stack.yml +++ b/.azure/windows-stack.yml @@ -4,7 +4,7 @@ jobs: pool: vmImage: windows-2019 variables: - STACK_ROOT: "C:\sr" + STACK_ROOT: "C:\\sr" strategy: matrix: stack-def: From 674eb52fa38c74e2c37d9625daaeda62c317d86b Mon Sep 17 00:00:00 2001 From: jneira Date: Mon, 24 Jun 2019 09:25:23 +0200 Subject: [PATCH 078/158] Remove unnecessary source --- .azure/windows-stack.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.azure/windows-stack.yml b/.azure/windows-stack.yml index df67e871a..3e861fce2 100644 --- a/.azure/windows-stack.yml +++ b/.azure/windows-stack.yml @@ -31,7 +31,6 @@ jobs: git submodule update --init displayName: Sync submodules - bash: | - export STACK_ROOT="$(Build.SourcesDirectory)"/.stack-root curl -sSkL http://www.stackage.org/stack/windows-i386 -o /usr/bin/stack.zip unzip -o /usr/bin/stack.zip -d /usr/bin/ displayName: Install stack From 47c00fe4fb02578d0c31b0f639f4d7aa2a7abbfb Mon Sep 17 00:00:00 2001 From: jneira Date: Mon, 24 Jun 2019 09:58:54 +0200 Subject: [PATCH 079/158] Use x86_64 arch --- .azure/windows-stack.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.azure/windows-stack.yml b/.azure/windows-stack.yml index 3e861fce2..356f67afd 100644 --- a/.azure/windows-stack.yml +++ b/.azure/windows-stack.yml @@ -31,7 +31,7 @@ jobs: git submodule update --init displayName: Sync submodules - bash: | - curl -sSkL http://www.stackage.org/stack/windows-i386 -o /usr/bin/stack.zip + curl -sSkL http://www.stackage.org/stack/windows-x86_64 -o /usr/bin/stack.zip unzip -o /usr/bin/stack.zip -d /usr/bin/ displayName: Install stack - bash: | From 6e73dd5de22359b2cc6d5515420a410b7929aa0d Mon Sep 17 00:00:00 2001 From: jneira Date: Mon, 24 Jun 2019 10:00:26 +0200 Subject: [PATCH 080/158] Remove line-break --- .azure/windows.bashrc | 1 - 1 file changed, 1 deletion(-) diff --git a/.azure/windows.bashrc b/.azure/windows.bashrc index 1c5132398..61f790fa8 100644 --- a/.azure/windows.bashrc +++ b/.azure/windows.bashrc @@ -1,2 +1 @@ export PATH=$HOME/.local/bin:$PATH - From 3caaf674a26a3292414bf9f986ca6f979470b5ed Mon Sep 17 00:00:00 2001 From: jneira Date: Mon, 24 Jun 2019 10:15:01 +0200 Subject: [PATCH 081/158] Set default stack local-bin-path for windows --- .azure/windows.bashrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.azure/windows.bashrc b/.azure/windows.bashrc index 61f790fa8..645da5b32 100644 --- a/.azure/windows.bashrc +++ b/.azure/windows.bashrc @@ -1 +1 @@ -export PATH=$HOME/.local/bin:$PATH +export PATH=$LOCALAPPDATA/bin:$PATH From 29fd8dbd1368521e01d680bd47e05d82d5a584cd Mon Sep 17 00:00:00 2001 From: jneira Date: Mon, 24 Jun 2019 11:34:33 +0200 Subject: [PATCH 082/158] Use yaml variables instead .bashcr --- .azure/windows-stack.yml | 17 +++++++---------- .azure/windows.bashrc | 3 ++- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/.azure/windows-stack.yml b/.azure/windows-stack.yml index 356f67afd..c245b2a04 100644 --- a/.azure/windows-stack.yml +++ b/.azure/windows-stack.yml @@ -5,6 +5,8 @@ jobs: vmImage: windows-2019 variables: STACK_ROOT: "C:\\sr" + LOCAL_BIN_PATH: "%:LOCALAPPDATA%\\bin" + PATH: "%LOCAL_BIN_PATH%;%PATH%" strategy: matrix: stack-def: @@ -31,23 +33,19 @@ jobs: git submodule update --init displayName: Sync submodules - bash: | - curl -sSkL http://www.stackage.org/stack/windows-x86_64 -o /usr/bin/stack.zip - unzip -o /usr/bin/stack.zip -d /usr/bin/ + curl -sSkL http://www.stackage.org/stack/windows-x86_64 -o $LOCAL_BIN_PATH/stack.zip + unzip -o $LOCAL_BIN_PATH/stack.zip -d $LOCAL_BIN_PATH displayName: Install stack - bash: | - source .azure/windows.bashrc stack setup --stack-yaml $(YAML_FILE) displayName: Install GHC - bash: | - source .azure/linux.bashrc stack --stack-yaml $(YAML_FILE) --install-ghc build --only-dependencies displayName: Build dependencies - bash: | - source .azure/windows.bashrc stack build --stack-yaml $(YAML_FILE) displayName: Build `hie` - bash: | - source .azure/windows.bashrc stack build --stack-yaml $(YAML_FILE) --test --bench --only-dependencies stack install --stack-yaml $(YAML_FILE) # `hie` binary required for tests # TODO: get `cabal` binary from somewhere else? @@ -56,12 +54,11 @@ jobs: stack exec --stack-yaml $(YAML_FILE) hoogle generate choco install z3 cabal v1-update - curl -L https://github.com/Z3Prover/z3/releases/download/Z3-4.8.5/z3-4.8.5-x64-win.zip -o /usr/local/z3.zip - unzip -o /usr/local/z3.zip -d /usr/local/ + curl -L https://github.com/Z3Prover/z3/releases/download/Z3-4.8.5/z3-4.8.5-x64-win.zip -o $LOCALAPPDATA/z3.zip + unzip -o $LOCALAPPDATA/z3.zip -d $LOCALAPPDATA stack setup --stack-yaml=stack-8.2.2.yaml - cabal v1-install liquidhaskell-0.8.2.4 --symlink-bindir=$HOME/.local/bin -w $(stack path --stack-yaml=stack-8.2.2.yaml --compiler-exe) + cabal v1-install liquidhaskell-0.8.2.4 --symlink-bindir=$LOCAL_BIN_PATH -w $(stack path --stack-yaml=stack-8.2.2.yaml --compiler-exe) displayName: Build Test-dependencies - bash: | - source .azure/windows.bashrc stack test --stack-yaml $(YAML_FILE) :unit-test displayName: Run Test diff --git a/.azure/windows.bashrc b/.azure/windows.bashrc index 645da5b32..5d4bc1cdf 100644 --- a/.azure/windows.bashrc +++ b/.azure/windows.bashrc @@ -1 +1,2 @@ -export PATH=$LOCALAPPDATA/bin:$PATH +export LOCAL_BIN_PATH=$LOCALAPPDATA/bin +export PATH=$LOCAL_BIN_PATH:$PATH From f5d1ffad8ed246dc8364d2e330380aa866f0ce76 Mon Sep 17 00:00:00 2001 From: jneira Date: Mon, 24 Jun 2019 13:33:39 +0200 Subject: [PATCH 083/158] Try to use bashrc again --- .azure/windows-stack.yml | 8 ++++---- .azure/windows.bashrc | 4 +++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.azure/windows-stack.yml b/.azure/windows-stack.yml index 800748162..0b801fd1f 100644 --- a/.azure/windows-stack.yml +++ b/.azure/windows-stack.yml @@ -29,8 +29,7 @@ jobs: git submodule update --init displayName: Sync submodules - bash: | - export STACK_ROOT="$(Build.SourcesDirectory)"/.stack-root - curl -sSkL http://www.stackage.org/stack/windows-i386 -o /usr/bin/stack.zip + curl -sSkL http://www.stackage.org/stack/windows-x86_64 -o /usr/bin/stack.zip unzip -o /usr/bin/stack.zip -d /usr/bin/ displayName: Install stack - bash: | @@ -38,7 +37,7 @@ jobs: stack setup --stack-yaml $(YAML_FILE) displayName: Install GHC - bash: | - source .azure/linux.bashrc + source .azure/windows.bashrc stack --stack-yaml $(YAML_FILE) --install-ghc build --only-dependencies displayName: Build dependencies - bash: | @@ -55,10 +54,11 @@ jobs: stack exec --stack-yaml $(YAML_FILE) hoogle generate choco install z3 cabal v1-update + mkdir /usr/local -p curl -L https://github.com/Z3Prover/z3/releases/download/Z3-4.8.5/z3-4.8.5-x64-win.zip -o /usr/local/z3.zip unzip -o /usr/local/z3.zip -d /usr/local/ stack setup --stack-yaml=stack-8.2.2.yaml - cabal v1-install liquidhaskell-0.8.2.4 --symlink-bindir=$HOME/.local/bin -w $(stack path --stack-yaml=stack-8.2.2.yaml --compiler-exe) + cabal v1-install liquidhaskell-0.8.2.4 --symlink-bindir=$LOCAL_BIN_PATH -w $(stack path --stack-yaml=stack-8.2.2.yaml --compiler-exe) displayName: Build Test-dependencies - bash: | source .azure/windows.bashrc diff --git a/.azure/windows.bashrc b/.azure/windows.bashrc index 61f790fa8..e3edd5040 100644 --- a/.azure/windows.bashrc +++ b/.azure/windows.bashrc @@ -1 +1,3 @@ -export PATH=$HOME/.local/bin:$PATH +export STACK_ROOT="C:\\sr" +export LOCAL_BIN_PATH=$LOCALAPPDATA\\bin +export PATH=$LOCAL_BIN_PATH:$PATH From 9a0ab198fbdd015a1429f8434322ca3f6776ed88 Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Mon, 24 Jun 2019 16:30:33 +0200 Subject: [PATCH 084/158] remove test-run for macos azure-ci --- .azure/macos-stack.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.azure/macos-stack.yml b/.azure/macos-stack.yml index 929a1d0e2..350866241 100644 --- a/.azure/macos-stack.yml +++ b/.azure/macos-stack.yml @@ -64,7 +64,7 @@ jobs: stack setup --stack-yaml=stack-8.2.2.yaml cabal v1-install liquidhaskell-0.8.2.4 --symlink-bindir=$HOME/.local/bin -w $(stack path --stack-yaml=stack-8.2.2.yaml --compiler-exe) displayName: Build Test-dependencies - - bash: | - source .azure/macos.bashrc - stack test --stack-yaml $(YAML_FILE) - displayName: Run Test + # - bash: | + # source .azure/macos.bashrc + # stack test --stack-yaml $(YAML_FILE) + # displayName: Run Test From a76ee61ff0ff325ec19c4301491ceffaccce8c2d Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Mon, 24 Jun 2019 16:42:25 +0200 Subject: [PATCH 085/158] switch ';' to ':' in windows-path in azure-ci --- .azure/windows-stack.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.azure/windows-stack.yml b/.azure/windows-stack.yml index c245b2a04..df141f38a 100644 --- a/.azure/windows-stack.yml +++ b/.azure/windows-stack.yml @@ -6,7 +6,7 @@ jobs: variables: STACK_ROOT: "C:\\sr" LOCAL_BIN_PATH: "%:LOCALAPPDATA%\\bin" - PATH: "%LOCAL_BIN_PATH%;%PATH%" + PATH: "%LOCAL_BIN_PATH%:%PATH%" strategy: matrix: stack-def: From 827da32488e4f35dc14c5aed884b0c87ade0c818 Mon Sep 17 00:00:00 2001 From: jneira Date: Tue, 25 Jun 2019 07:51:25 +0200 Subject: [PATCH 086/158] Use cygpath to set LOCAL_BIN_PATH --- .azure/windows.bashrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.azure/windows.bashrc b/.azure/windows.bashrc index e3edd5040..214fbf60e 100644 --- a/.azure/windows.bashrc +++ b/.azure/windows.bashrc @@ -1,3 +1,3 @@ export STACK_ROOT="C:\\sr" -export LOCAL_BIN_PATH=$LOCALAPPDATA\\bin +export LOCAL_BIN_PATH=$(cygpath $APPDATA\\local\\bin) export PATH=$LOCAL_BIN_PATH:$PATH From 36d2e72f25810fbf5fc1bf9abdc15a8ed180e374 Mon Sep 17 00:00:00 2001 From: jneira Date: Tue, 25 Jun 2019 09:20:42 +0200 Subject: [PATCH 087/158] Using pacman to install z3, download cabal and separate Runtime test deps --- .azure/windows-stack.yml | 17 +++++++++-------- .azure/windows.bashrc | 1 + 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/.azure/windows-stack.yml b/.azure/windows-stack.yml index 0b801fd1f..353e09988 100644 --- a/.azure/windows-stack.yml +++ b/.azure/windows-stack.yml @@ -48,18 +48,19 @@ jobs: source .azure/windows.bashrc stack build --stack-yaml $(YAML_FILE) --test --bench --only-dependencies stack install --stack-yaml $(YAML_FILE) # `hie` binary required for tests - # TODO: get `cabal` binary from somewhere else? - stack setup --stack-yaml=stack-8.6.5.yaml - stack install --stack-yaml=stack-8.6.5.yaml cabal-install-2.4.1.0 stack exec --stack-yaml $(YAML_FILE) hoogle generate - choco install z3 + displayName: Build Test-dependencies + - bash: | + pacman -S --noconfirm mingw-w64-x86_64-z3 + displayName: Install Runtime Test-Dependencies: z3 + - bash: | + source .azure/windows.bashrc + curl -L https://downloads.haskell.org/cabal/cabal-install-$CABAL_VERSION/cabal-install-$CABAL_VERSION-x86_64-unknown-mingw32.zip -o $LOCAL_BIN_PATH/cabal-$CABAL_VERSION.zip + unzip -o $LOCAL_BIN_PATH/cabal-$CABAL_VERSION.zip -d $LOCAL_BIN_PATH cabal v1-update - mkdir /usr/local -p - curl -L https://github.com/Z3Prover/z3/releases/download/Z3-4.8.5/z3-4.8.5-x64-win.zip -o /usr/local/z3.zip - unzip -o /usr/local/z3.zip -d /usr/local/ stack setup --stack-yaml=stack-8.2.2.yaml cabal v1-install liquidhaskell-0.8.2.4 --symlink-bindir=$LOCAL_BIN_PATH -w $(stack path --stack-yaml=stack-8.2.2.yaml --compiler-exe) - displayName: Build Test-dependencies + displayName: Install Runtime Test-Dependencies: liquidhaskell - bash: | source .azure/windows.bashrc stack test --stack-yaml $(YAML_FILE) :unit-test diff --git a/.azure/windows.bashrc b/.azure/windows.bashrc index 214fbf60e..305a0304e 100644 --- a/.azure/windows.bashrc +++ b/.azure/windows.bashrc @@ -1,3 +1,4 @@ export STACK_ROOT="C:\\sr" export LOCAL_BIN_PATH=$(cygpath $APPDATA\\local\\bin) export PATH=$LOCAL_BIN_PATH:$PATH +export CABAL_VERSION=2.4.1.0 From 2dc7082e26877cc9758a8a9e409e0388c84f8b85 Mon Sep 17 00:00:00 2001 From: jneira Date: Tue, 25 Jun 2019 09:22:54 +0200 Subject: [PATCH 088/158] Use literals in displayName --- .azure/windows-stack.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.azure/windows-stack.yml b/.azure/windows-stack.yml index 353e09988..40a95b585 100644 --- a/.azure/windows-stack.yml +++ b/.azure/windows-stack.yml @@ -52,7 +52,7 @@ jobs: displayName: Build Test-dependencies - bash: | pacman -S --noconfirm mingw-w64-x86_64-z3 - displayName: Install Runtime Test-Dependencies: z3 + displayName: "Install Runtime Test-Dependencies: z3" - bash: | source .azure/windows.bashrc curl -L https://downloads.haskell.org/cabal/cabal-install-$CABAL_VERSION/cabal-install-$CABAL_VERSION-x86_64-unknown-mingw32.zip -o $LOCAL_BIN_PATH/cabal-$CABAL_VERSION.zip @@ -60,7 +60,7 @@ jobs: cabal v1-update stack setup --stack-yaml=stack-8.2.2.yaml cabal v1-install liquidhaskell-0.8.2.4 --symlink-bindir=$LOCAL_BIN_PATH -w $(stack path --stack-yaml=stack-8.2.2.yaml --compiler-exe) - displayName: Install Runtime Test-Dependencies: liquidhaskell + displayName: "Install Runtime Test-Dependencies: liquidhaskell" - bash: | source .azure/windows.bashrc stack test --stack-yaml $(YAML_FILE) :unit-test From 7d5a2f50044c3142a224183bca2456b9270e0ad9 Mon Sep 17 00:00:00 2001 From: jneira Date: Tue, 25 Jun 2019 10:48:35 +0200 Subject: [PATCH 089/158] Use variable for full cabal version and install z3 manually (no pacman :-() --- .azure/windows-stack.yml | 5 +++-- .azure/windows.bashrc | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.azure/windows-stack.yml b/.azure/windows-stack.yml index 40a95b585..dceb3cdaf 100644 --- a/.azure/windows-stack.yml +++ b/.azure/windows-stack.yml @@ -51,11 +51,12 @@ jobs: stack exec --stack-yaml $(YAML_FILE) hoogle generate displayName: Build Test-dependencies - bash: | - pacman -S --noconfirm mingw-w64-x86_64-z3 + curl -L https://github.com/Z3Prover/z3/releases/download/Z3-4.8.5/z3-4.8.5-x64-win.zip -o /mingw64/z3.zip + unzip -o /migw64/z3.zip -d /mingw64 displayName: "Install Runtime Test-Dependencies: z3" - bash: | source .azure/windows.bashrc - curl -L https://downloads.haskell.org/cabal/cabal-install-$CABAL_VERSION/cabal-install-$CABAL_VERSION-x86_64-unknown-mingw32.zip -o $LOCAL_BIN_PATH/cabal-$CABAL_VERSION.zip + curl -L https://downloads.haskell.org/cabal/cabal-install-$CABAL_VERSION/cabal-install-$CABAL_VERSION_FULL.zip -o $LOCAL_BIN_PATH/cabal-$CABAL_VERSION.zip unzip -o $LOCAL_BIN_PATH/cabal-$CABAL_VERSION.zip -d $LOCAL_BIN_PATH cabal v1-update stack setup --stack-yaml=stack-8.2.2.yaml diff --git a/.azure/windows.bashrc b/.azure/windows.bashrc index 305a0304e..06a04ab45 100644 --- a/.azure/windows.bashrc +++ b/.azure/windows.bashrc @@ -2,3 +2,4 @@ export STACK_ROOT="C:\\sr" export LOCAL_BIN_PATH=$(cygpath $APPDATA\\local\\bin) export PATH=$LOCAL_BIN_PATH:$PATH export CABAL_VERSION=2.4.1.0 +export CABAL_VERSION_FULL=$CABAL_VERSION-x86_64-unknown-mingw32 From 816a77c1bc6db1b45e0a4b7159ffd61b3e172089 Mon Sep 17 00:00:00 2001 From: jneira Date: Tue, 25 Jun 2019 11:40:19 +0200 Subject: [PATCH 090/158] Correct z3.zip path --- .azure/windows-stack.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.azure/windows-stack.yml b/.azure/windows-stack.yml index dceb3cdaf..15d56c7b1 100644 --- a/.azure/windows-stack.yml +++ b/.azure/windows-stack.yml @@ -51,8 +51,9 @@ jobs: stack exec --stack-yaml $(YAML_FILE) hoogle generate displayName: Build Test-dependencies - bash: | + # TODO: try to install automatically (`choco install z3` fails) curl -L https://github.com/Z3Prover/z3/releases/download/Z3-4.8.5/z3-4.8.5-x64-win.zip -o /mingw64/z3.zip - unzip -o /migw64/z3.zip -d /mingw64 + unzip -o /mingw64/z3.zip -d /mingw64 displayName: "Install Runtime Test-Dependencies: z3" - bash: | source .azure/windows.bashrc From dcada88685475fcef87aa9d128e9cfd12fa93c0d Mon Sep 17 00:00:00 2001 From: jneira Date: Tue, 25 Jun 2019 13:03:35 +0200 Subject: [PATCH 091/158] Install s3 in the original path (/usr/local) --- .azure/windows-stack.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.azure/windows-stack.yml b/.azure/windows-stack.yml index 15d56c7b1..b91c50b11 100644 --- a/.azure/windows-stack.yml +++ b/.azure/windows-stack.yml @@ -52,8 +52,9 @@ jobs: displayName: Build Test-dependencies - bash: | # TODO: try to install automatically (`choco install z3` fails) - curl -L https://github.com/Z3Prover/z3/releases/download/Z3-4.8.5/z3-4.8.5-x64-win.zip -o /mingw64/z3.zip - unzip -o /mingw64/z3.zip -d /mingw64 + mkdir -p /usr/local + curl -L https://github.com/Z3Prover/z3/releases/download/Z3-4.8.5/z3-4.8.5-x64-win.zip -o /usr/local/z3.zip + unzip -o /usr/local/z3.zip -d /usr/local/ displayName: "Install Runtime Test-Dependencies: z3" - bash: | source .azure/windows.bashrc From 7b24d523c17ce69ae998b59cc73e3471bfd9165a Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Tue, 25 Jun 2019 16:42:50 +0200 Subject: [PATCH 092/158] remove 8.6.2 and 8.6.1 from macos-ci, they cannot be installed --- .azure/macos-stack.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.azure/macos-stack.yml b/.azure/macos-stack.yml index 350866241..2ecebba87 100644 --- a/.azure/macos-stack.yml +++ b/.azure/macos-stack.yml @@ -13,10 +13,6 @@ jobs: YAML_FILE: stack-8.6.4.yaml stack-8.6.3: YAML_FILE: stack-8.6.3.yaml - stack-8.6.2: - YAML_FILE: stack-8.6.2.yaml - stack-8.6.1: - YAML_FILE: stack-8.6.1.yaml stack-8.4.4: YAML_FILE: stack-8.4.4.yaml stack-8.4.3: From da062b03cade4299388206b6c8fc516f09b40e78 Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Tue, 25 Jun 2019 16:43:38 +0200 Subject: [PATCH 093/158] disable test-runs in azure-ci --- .azure/linux-stack.yml | 8 ++++---- .azure/windows-stack.yml | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.azure/linux-stack.yml b/.azure/linux-stack.yml index e4b456356..f655c6503 100644 --- a/.azure/linux-stack.yml +++ b/.azure/linux-stack.yml @@ -61,7 +61,7 @@ jobs: stack setup --stack-yaml=stack-8.2.2.yaml cabal v1-install liquidhaskell-0.8.2.4 --symlink-bindir=$HOME/.local/bin -w $(stack path --stack-yaml=stack-8.2.2.yaml --compiler-exe) displayName: Build Test-dependencies - - bash: | - source .azure/linux.bashrc - stack test --stack-yaml $(YAML_FILE) - displayName: Run Test + # - bash: | + # source .azure/linux.bashrc + # stack test --stack-yaml $(YAML_FILE) + # displayName: Run Test diff --git a/.azure/windows-stack.yml b/.azure/windows-stack.yml index b91c50b11..15e24f45d 100644 --- a/.azure/windows-stack.yml +++ b/.azure/windows-stack.yml @@ -64,7 +64,7 @@ jobs: stack setup --stack-yaml=stack-8.2.2.yaml cabal v1-install liquidhaskell-0.8.2.4 --symlink-bindir=$LOCAL_BIN_PATH -w $(stack path --stack-yaml=stack-8.2.2.yaml --compiler-exe) displayName: "Install Runtime Test-Dependencies: liquidhaskell" - - bash: | - source .azure/windows.bashrc - stack test --stack-yaml $(YAML_FILE) :unit-test - displayName: Run Test + # - bash: | + # source .azure/windows.bashrc + # stack test --stack-yaml $(YAML_FILE) :unit-test + # displayName: Run Test From 4406e8b23220a826e6720c732dfea94ee402b5ec Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Tue, 25 Jun 2019 16:51:52 +0200 Subject: [PATCH 094/158] restructure test-dependencies z3 and liquidhaskell in ci-builds --- .azure/linux-stack.yml | 13 +++++++++---- .azure/macos-stack.yml | 15 +++++++++------ 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/.azure/linux-stack.yml b/.azure/linux-stack.yml index f655c6503..8926b18e5 100644 --- a/.azure/linux-stack.yml +++ b/.azure/linux-stack.yml @@ -52,15 +52,20 @@ jobs: source .azure/linux.bashrc stack build --stack-yaml $(YAML_FILE) --test --bench --only-dependencies stack install --stack-yaml $(YAML_FILE) # `hie` binary required for tests + stack --stack-yaml $(YAML_FILE) exec hoogle generate + displayName: Build Test-dependencies + - bash: | + sudo apt update + sudo apt install z3 + displayName: "Install Runtime Test-Dependencies: z3" + - bash: | + source .azure/linux.bashrc stack setup --stack-yaml=stack-8.6.4.yaml stack install --stack-yaml=stack-8.6.4.yaml cabal-install-2.4.1.0 - stack --stack-yaml $(YAML_FILE) exec hoogle generate cabal v1-update - sudo apt update - sudo apt install z3 stack setup --stack-yaml=stack-8.2.2.yaml cabal v1-install liquidhaskell-0.8.2.4 --symlink-bindir=$HOME/.local/bin -w $(stack path --stack-yaml=stack-8.2.2.yaml --compiler-exe) - displayName: Build Test-dependencies + displayName: "Install Runtime Test-Dependencies: liquidhaskell" # - bash: | # source .azure/linux.bashrc # stack test --stack-yaml $(YAML_FILE) diff --git a/.azure/macos-stack.yml b/.azure/macos-stack.yml index 2ecebba87..1c3b64105 100644 --- a/.azure/macos-stack.yml +++ b/.azure/macos-stack.yml @@ -48,18 +48,21 @@ jobs: source .azure/macos.bashrc stack build --stack-yaml $(YAML_FILE) --test --bench --only-dependencies stack install --stack-yaml $(YAML_FILE) # `hie` binary required for tests - stack setup --stack-yaml=stack-8.6.5.yaml - stack install --stack-yaml=stack-8.6.5.yaml cabal-install-2.4.1.0 - stack exec --stack-yaml $(YAML_FILE) hoogle generate + stack --stack-yaml $(YAML_FILE) exec hoogle generate + displayName: Build Test-dependencies + - bash: | ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" brew update brew install z3 + displayName: "Install Runtime Test-Dependencies: z3" + - bash: | + source .azure/macos.bashrc + stack setup --stack-yaml=stack-8.6.4.yaml + stack install --stack-yaml=stack-8.6.4.yaml cabal-install-2.4.1.0 cabal v1-update - curl -skL https://github.com/Z3Prover/z3/releases/download/Z3-4.8.5/z3-4.8.5-x64-osx-10.14.2.zip | \ - tar xz -C ~/.local; stack setup --stack-yaml=stack-8.2.2.yaml cabal v1-install liquidhaskell-0.8.2.4 --symlink-bindir=$HOME/.local/bin -w $(stack path --stack-yaml=stack-8.2.2.yaml --compiler-exe) - displayName: Build Test-dependencies + displayName: "Install Runtime Test-Dependencies: liquidhaskell" # - bash: | # source .azure/macos.bashrc # stack test --stack-yaml $(YAML_FILE) From 8cb60ad12d2f11547e5ef44cf704055c4e9bc79b Mon Sep 17 00:00:00 2001 From: jneira Date: Wed, 26 Jun 2019 10:45:52 +0200 Subject: [PATCH 095/158] Fix z3 install for windows and use stack to install liquid --- .azure/linux-stack.yml | 6 +----- .azure/macos-stack.yml | 6 +----- .azure/windows-stack.yml | 13 ++++--------- .azure/windows.bashrc | 2 -- 4 files changed, 6 insertions(+), 21 deletions(-) diff --git a/.azure/linux-stack.yml b/.azure/linux-stack.yml index 8926b18e5..a7e636913 100644 --- a/.azure/linux-stack.yml +++ b/.azure/linux-stack.yml @@ -60,11 +60,7 @@ jobs: displayName: "Install Runtime Test-Dependencies: z3" - bash: | source .azure/linux.bashrc - stack setup --stack-yaml=stack-8.6.4.yaml - stack install --stack-yaml=stack-8.6.4.yaml cabal-install-2.4.1.0 - cabal v1-update - stack setup --stack-yaml=stack-8.2.2.yaml - cabal v1-install liquidhaskell-0.8.2.4 --symlink-bindir=$HOME/.local/bin -w $(stack path --stack-yaml=stack-8.2.2.yaml --compiler-exe) + stack install --resolver=lts-11.18 liquid-fixpoint-0.7.0.7 dotgen-0.4.2 fgl-visualize-0.1.0.1 located-base-0.1.1.1 liquidhaskell-0.8.2.4 displayName: "Install Runtime Test-Dependencies: liquidhaskell" # - bash: | # source .azure/linux.bashrc diff --git a/.azure/macos-stack.yml b/.azure/macos-stack.yml index 1c3b64105..86644471e 100644 --- a/.azure/macos-stack.yml +++ b/.azure/macos-stack.yml @@ -57,11 +57,7 @@ jobs: displayName: "Install Runtime Test-Dependencies: z3" - bash: | source .azure/macos.bashrc - stack setup --stack-yaml=stack-8.6.4.yaml - stack install --stack-yaml=stack-8.6.4.yaml cabal-install-2.4.1.0 - cabal v1-update - stack setup --stack-yaml=stack-8.2.2.yaml - cabal v1-install liquidhaskell-0.8.2.4 --symlink-bindir=$HOME/.local/bin -w $(stack path --stack-yaml=stack-8.2.2.yaml --compiler-exe) + stack install --resolver=lts-11.18 liquid-fixpoint-0.7.0.7 dotgen-0.4.2 fgl-visualize-0.1.0.1 located-base-0.1.1.1 liquidhaskell-0.8.2.4 displayName: "Install Runtime Test-Dependencies: liquidhaskell" # - bash: | # source .azure/macos.bashrc diff --git a/.azure/windows-stack.yml b/.azure/windows-stack.yml index 15e24f45d..6b2c88f26 100644 --- a/.azure/windows-stack.yml +++ b/.azure/windows-stack.yml @@ -51,18 +51,13 @@ jobs: stack exec --stack-yaml $(YAML_FILE) hoogle generate displayName: Build Test-dependencies - bash: | - # TODO: try to install automatically (`choco install z3` fails) - mkdir -p /usr/local - curl -L https://github.com/Z3Prover/z3/releases/download/Z3-4.8.5/z3-4.8.5-x64-win.zip -o /usr/local/z3.zip - unzip -o /usr/local/z3.zip -d /usr/local/ + # TODO: try to install automatically (`choco install z3` fails and pacman is not installed) + curl -sSkL http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-z3-4.8.5-1-any.pkg.tar.xz -o /mingw64/z3.tar.xz + tar xf /mingw64/z3.tar.xz -C / displayName: "Install Runtime Test-Dependencies: z3" - bash: | source .azure/windows.bashrc - curl -L https://downloads.haskell.org/cabal/cabal-install-$CABAL_VERSION/cabal-install-$CABAL_VERSION_FULL.zip -o $LOCAL_BIN_PATH/cabal-$CABAL_VERSION.zip - unzip -o $LOCAL_BIN_PATH/cabal-$CABAL_VERSION.zip -d $LOCAL_BIN_PATH - cabal v1-update - stack setup --stack-yaml=stack-8.2.2.yaml - cabal v1-install liquidhaskell-0.8.2.4 --symlink-bindir=$LOCAL_BIN_PATH -w $(stack path --stack-yaml=stack-8.2.2.yaml --compiler-exe) + stack install --resolver=lts-11.18 liquid-fixpoint-0.7.0.7 dotgen-0.4.2 fgl-visualize-0.1.0.1 located-base-0.1.1.1 liquidhaskell-0.8.2.4 displayName: "Install Runtime Test-Dependencies: liquidhaskell" # - bash: | # source .azure/windows.bashrc diff --git a/.azure/windows.bashrc b/.azure/windows.bashrc index 06a04ab45..214fbf60e 100644 --- a/.azure/windows.bashrc +++ b/.azure/windows.bashrc @@ -1,5 +1,3 @@ export STACK_ROOT="C:\\sr" export LOCAL_BIN_PATH=$(cygpath $APPDATA\\local\\bin) export PATH=$LOCAL_BIN_PATH:$PATH -export CABAL_VERSION=2.4.1.0 -export CABAL_VERSION_FULL=$CABAL_VERSION-x86_64-unknown-mingw32 From d487c46e614e7693d06e35b90f55547b3266d284 Mon Sep 17 00:00:00 2001 From: jneira Date: Wed, 26 Jun 2019 13:33:44 +0200 Subject: [PATCH 096/158] Install z3 from github instead from the mingw64 package (doesn't work) --- .azure/windows-stack.yml | 6 ++++-- .azure/windows.bashrc | 3 ++- submodules/ghc-mod | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.azure/windows-stack.yml b/.azure/windows-stack.yml index 6b2c88f26..4187ec03c 100644 --- a/.azure/windows-stack.yml +++ b/.azure/windows-stack.yml @@ -52,12 +52,14 @@ jobs: displayName: Build Test-dependencies - bash: | # TODO: try to install automatically (`choco install z3` fails and pacman is not installed) - curl -sSkL http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-z3-4.8.5-1-any.pkg.tar.xz -o /mingw64/z3.tar.xz - tar xf /mingw64/z3.tar.xz -C / + mkdir -p /usr/local + curl -L https://github.com/Z3Prover/z3/releases/download/Z3-4.8.5/z3-4.8.5-x64-win.zip -o /usr/local/z3.zip + unzip -o /usr/local/z3.zip -d /usr/local/ displayName: "Install Runtime Test-Dependencies: z3" - bash: | source .azure/windows.bashrc stack install --resolver=lts-11.18 liquid-fixpoint-0.7.0.7 dotgen-0.4.2 fgl-visualize-0.1.0.1 located-base-0.1.1.1 liquidhaskell-0.8.2.4 + liquid -v displayName: "Install Runtime Test-Dependencies: liquidhaskell" # - bash: | # source .azure/windows.bashrc diff --git a/.azure/windows.bashrc b/.azure/windows.bashrc index 214fbf60e..8de96772d 100644 --- a/.azure/windows.bashrc +++ b/.azure/windows.bashrc @@ -1,3 +1,4 @@ export STACK_ROOT="C:\\sr" export LOCAL_BIN_PATH=$(cygpath $APPDATA\\local\\bin) -export PATH=$LOCAL_BIN_PATH:$PATH +export Z3_BIN_PATH=/usr/local/z3-4.8.5-x64-win/bin +export PATH=$Z3_BIN_PATH:$LOCAL_BIN_PATH:$PATH diff --git a/submodules/ghc-mod b/submodules/ghc-mod index d050fac99..910887b2c 160000 --- a/submodules/ghc-mod +++ b/submodules/ghc-mod @@ -1 +1 @@ -Subproject commit d050fac998b58fb807e3f95ee7a502d79d566aa2 +Subproject commit 910887b2c33237b703417ec07f35ca8bbf35d729 From 032097c9c749611b1841417d8ee82a14bb0da2c9 Mon Sep 17 00:00:00 2001 From: jneira Date: Wed, 26 Jun 2019 13:40:18 +0200 Subject: [PATCH 097/158] Reset ghc-mod submodule --- submodules/ghc-mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/submodules/ghc-mod b/submodules/ghc-mod index 910887b2c..d050fac99 160000 --- a/submodules/ghc-mod +++ b/submodules/ghc-mod @@ -1 +1 @@ -Subproject commit 910887b2c33237b703417ec07f35ca8bbf35d729 +Subproject commit d050fac998b58fb807e3f95ee7a502d79d566aa2 From 1822fcd76340ba986de06f17e4db3018dfd0862f Mon Sep 17 00:00:00 2001 From: jneira Date: Fri, 28 Jun 2019 09:57:40 +0200 Subject: [PATCH 098/158] Fix liquid unit tests normalizing paths --- test/unit/LiquidSpec.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit/LiquidSpec.hs b/test/unit/LiquidSpec.hs index 763ff967a..2acafe4fd 100644 --- a/test/unit/LiquidSpec.hs +++ b/test/unit/LiquidSpec.hs @@ -47,8 +47,8 @@ spec = do uri = filePathToUri $ cwd "test/testdata/liquid/Evens.hs" vimFile = vimAnnotFile uri jsonFile = jsonAnnotFile uri - vimFile `shouldBe` (cwd "test/testdata/liquid/.liquid/Evens.hs.vim.annot") - jsonFile `shouldBe` (cwd "test/testdata/liquid/.liquid/Evens.hs.json") + vimFile `shouldBe` normalise (cwd "test/testdata/liquid/.liquid/Evens.hs.vim.annot") + jsonFile `shouldBe` normalise (cwd "test/testdata/liquid/.liquid/Evens.hs.json") -- --------------------------------- From fa0b452aa823966a99295fe31562361057c2980b Mon Sep 17 00:00:00 2001 From: "Daniel P. Brice" Date: Wed, 3 Jul 2019 16:43:36 -0700 Subject: [PATCH 099/158] Update README.md The suggested Aura package, `haskell-ide-engine-git`, has been flagged out of date and has not been updated in about a year (and did not build on my machine due to a missing `stack.yaml` file in the project repo). This commit instructs the reader to install `hadkell-ide-engine` instead, as this package seems to be maintained (and did build on my machine). --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4fc8addd2..7f847268e 100644 --- a/README.md +++ b/README.md @@ -129,12 +129,12 @@ Follow the instructions at https://github.com/Infinisil/all-hies ### Installation on ArchLinux -An [haskell-ide-engine-git](https://aur.archlinux.org/packages/haskell-ide-engine-git/) package is available on the AUR. +An [haskell-ide-engine](https://aur.archlinux.org/packages/haskell-ide-engine/) package is available on the AUR. Using [Aura](https://github.com/aurapm/aura): ``` -# aura -A haskell-ide-engine-git +# aura -A haskell-ide-engine ``` From 80ec66b0ef045c0e6bda03c31a67a03a1a2b3c4f Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Rodriguez Date: Thu, 4 Jul 2019 10:52:34 +0200 Subject: [PATCH 100/158] Upgrade to haskell-lsp 0.15 --- haskell-ide-engine.cabal | 12 ++--- hie-plugin-api/Haskell/Ide/Engine/Config.hs | 13 ++++- hie-plugin-api/Haskell/Ide/Engine/Ghc.hs | 47 +++++++++++++------ .../Haskell/Ide/Engine/PluginsIdeMonads.hs | 3 +- hie-plugin-api/hie-plugin-api.cabal | 2 +- src/Haskell/Ide/Engine/LSP/CodeActions.hs | 2 +- src/Haskell/Ide/Engine/Transport/LspStdio.hs | 35 ++++++++------ stack-8.2.2.yaml | 6 +-- stack-8.4.2.yaml | 6 +-- stack-8.4.3.yaml | 6 +-- stack-8.4.4.yaml | 6 +-- stack-8.6.1.yaml | 4 +- stack-8.6.2.yaml | 6 +-- stack-8.6.3.yaml | 6 +-- stack-8.6.4.yaml | 6 +-- stack-8.6.5.yaml | 8 ++-- test/dispatcher/Main.hs | 4 +- test/unit/GhcModPluginSpec.hs | 4 +- 18 files changed, 105 insertions(+), 71 deletions(-) diff --git a/haskell-ide-engine.cabal b/haskell-ide-engine.cabal index 7cfb385fd..994244d4a 100644 --- a/haskell-ide-engine.cabal +++ b/haskell-ide-engine.cabal @@ -70,8 +70,8 @@ library , gitrev >= 1.1 , haddock-api , haddock-library - , haskell-lsp == 0.14.* - , haskell-lsp-types == 0.14.* + , haskell-lsp == 0.15.* + , haskell-lsp-types == 0.15.* , haskell-src-exts , hie-plugin-api , hlint (>= 2.0.11 && < 2.1.18) || >= 2.1.22 @@ -192,7 +192,7 @@ test-suite unit-test , filepath , free , haskell-ide-engine - , haskell-lsp-types + , haskell-lsp-types >= 0.15.0.0 , hie-test-utils , hie-plugin-api , hoogle > 5.0.11 @@ -278,10 +278,10 @@ test-suite func-test , data-default , directory , filepath - , lsp-test >= 0.5.2 + , lsp-test >= 0.6.0.0 , haskell-ide-engine - , haskell-lsp-types == 0.14.* - , haskell-lsp == 0.14.* + , haskell-lsp-types == 0.15.* + , haskell-lsp == 0.15.* , hie-test-utils , hie-plugin-api , hspec diff --git a/hie-plugin-api/Haskell/Ide/Engine/Config.hs b/hie-plugin-api/Haskell/Ide/Engine/Config.hs index 9f625023c..36d76bb9e 100644 --- a/hie-plugin-api/Haskell/Ide/Engine/Config.hs +++ b/hie-plugin-api/Haskell/Ide/Engine/Config.hs @@ -8,14 +8,23 @@ import Language.Haskell.LSP.Types -- --------------------------------------------------------------------- --- | Callback from haskell-lsp core to convert the generic message to the --- specific one for hie +-- | Given a DidChangeConfigurationNotification message, this function returns the parsed +-- Config object if possible. getConfigFromNotification :: DidChangeConfigurationNotification -> Either T.Text Config getConfigFromNotification (NotificationMessage _ _ (DidChangeConfigurationParams p)) = case fromJSON p of Success c -> Right c Error err -> Left $ T.pack err +-- | Given an InitializeRequest message, this function returns the parsed +-- Config object if possible. Otherwise, it returns the default configuration +getInitialConfig :: InitializeRequest -> Either T.Text Config +getInitialConfig (RequestMessage _ _ _ InitializeParams{_initializationOptions = Nothing }) = Right def +getInitialConfig (RequestMessage _ _ _ InitializeParams{_initializationOptions = Just opts}) = + case fromJSON opts of + Success c -> Right c + Error err -> Left $ T.pack err + -- --------------------------------------------------------------------- data Config = diff --git a/hie-plugin-api/Haskell/Ide/Engine/Ghc.hs b/hie-plugin-api/Haskell/Ide/Engine/Ghc.hs index bfac52030..b032a15d2 100644 --- a/hie-plugin-api/Haskell/Ide/Engine/Ghc.hs +++ b/hie-plugin-api/Haskell/Ide/Engine/Ghc.hs @@ -11,7 +11,7 @@ module Haskell.Ide.Engine.Ghc ( setTypecheckedModule - , Diagnostics + , Diagnostics(..) , AdditionalErrs , cabalModuleGraphs , makeRevRedirMapFunc @@ -21,9 +21,11 @@ import Bag import Control.Monad.IO.Class import Data.IORef import qualified Data.Map.Strict as Map -import Data.Monoid ((<>)) +import Data.Semigroup ((<>)) import qualified Data.Set as Set import qualified Data.Text as T +import qualified Data.Aeson +import Data.Coerce import ErrUtils import qualified GhcModCore as GM ( withDynFlags @@ -45,10 +47,23 @@ import GHC import IOEnv as G import HscTypes import Outputable (renderWithStyle) +import Language.Haskell.LSP.Types ( NormalizedUri(..), toNormalizedUri ) -- --------------------------------------------------------------------- -type Diagnostics = Map.Map Uri (Set.Set Diagnostic) +newtype Diagnostics = Diagnostics (Map.Map NormalizedUri (Set.Set Diagnostic)) + deriving (Show, Eq) + +instance Semigroup Diagnostics where + Diagnostics d1 <> Diagnostics d2 = Diagnostics (d1 <> d2) + +instance Monoid Diagnostics where + mempty = Diagnostics mempty + +instance Data.Aeson.ToJSON Diagnostics where + toJSON (Diagnostics d) = Data.Aeson.toJSON + (Map.mapKeys coerce d :: Map.Map T.Text (Set.Set Diagnostic)) + type AdditionalErrs = [T.Text] -- --------------------------------------------------------------------- @@ -68,10 +83,9 @@ logDiag rfm eref dref df _reason sev spn style msg = do let msgTxt = T.pack $ renderWithStyle df msg style case eloc of Right (Location uri range) -> do - let update = Map.insertWith Set.union uri l - where l = Set.singleton diag + let update = Map.insertWith Set.union (toNormalizedUri uri) (Set.singleton diag) diag = Diagnostic range (Just $ lspSev sev) Nothing (Just "ghcmod") msgTxt Nothing - modifyIORef' dref update + modifyIORef' dref (\(Diagnostics d) -> Diagnostics $ update d) Left _ -> do modifyIORef' eref (msgTxt:) return () @@ -109,9 +123,11 @@ srcErrToDiag df rfm se = do (m,es) <- processMsgs xs case res of Right (uri, diag) -> - return (Map.insertWith Set.union uri (Set.singleton diag) m, es) + return (Map.insertWith Set.union (toNormalizedUri uri) (Set.singleton diag) m, es) Left e -> return (m, e:es) - processMsgs errMsgs + + (diags, errs) <- processMsgs errMsgs + return (Diagnostics diags, errs) -- --------------------------------------------------------------------- @@ -121,11 +137,14 @@ myWrapper :: GM.IOish m -> GM.GmlT m (Diagnostics, AdditionalErrs) myWrapper rfm action = do env <- getSession - diagRef <- liftIO $ newIORef Map.empty + diagRef <- liftIO $ newIORef mempty errRef <- liftIO $ newIORef [] let setLogger df = df { log_action = logDiag rfm errRef diagRef } setDeferTypedHoles = setGeneralFlag' Opt_DeferTypedHoles - ghcErrRes msg = (Map.empty, [T.pack msg]) + + ghcErrRes :: String -> (Diagnostics, AdditionalErrs) + ghcErrRes msg = (mempty, [T.pack msg]) + handlers = errorHandlers ghcErrRes (srcErrToDiag (hsc_dflags env) rfm ) action' = do GM.withDynFlags (setLogger . setDeferTypedHoles) action @@ -167,7 +186,7 @@ setTypecheckedModule uri = debugm $ "setTypecheckedModule: file mapping state is: " ++ show fileMap rfm <- GM.mkRevRedirMapFunc let - ghcErrRes msg = ((Map.empty, [T.pack msg]),Nothing,Nothing) + ghcErrRes msg = ((Diagnostics Map.empty, [T.pack msg]),Nothing,Nothing) progTitle = "Typechecking " <> T.pack (takeFileName fp) debugm "setTypecheckedModule: before ghc-mod" -- TODO:AZ: loading this one module may/should trigger loads of any @@ -175,12 +194,12 @@ setTypecheckedModule uri = -- sure that their diagnostics are reported, and their module -- cache entries are updated. -- TODO: Are there any hooks we can use to report back on the progress? - ((diags', errs), mtm, mpm) <- withIndefiniteProgress progTitle NotCancellable $ GM.gcatches + ((Diagnostics diags', errs), mtm, mpm) <- withIndefiniteProgress progTitle NotCancellable $ GM.gcatches (GM.getModulesGhc' (myWrapper rfm) fp) (errorHandlers ghcErrRes (return . ghcErrRes . show)) debugm "setTypecheckedModule: after ghc-mod" - canonUri <- canonicalizeUri uri + canonUri <- toNormalizedUri <$> canonicalizeUri uri let diags = Map.insertWith Set.union canonUri Set.empty diags' diags2 <- case (mpm,mtm) of (Just pm, Nothing) -> do @@ -212,7 +231,7 @@ setTypecheckedModule uri = let d = Diagnostic range sev Nothing (Just "ghcmod") msgTxt Nothing return $ Map.insertWith Set.union canonUri (Set.singleton d) diags - return $ IdeResultOk (diags2,errs) + return $ IdeResultOk (Diagnostics diags2,errs) -- --------------------------------------------------------------------- diff --git a/hie-plugin-api/Haskell/Ide/Engine/PluginsIdeMonads.hs b/hie-plugin-api/Haskell/Ide/Engine/PluginsIdeMonads.hs index 06bf7b7eb..aca5c45b9 100644 --- a/hie-plugin-api/Haskell/Ide/Engine/PluginsIdeMonads.hs +++ b/hie-plugin-api/Haskell/Ide/Engine/PluginsIdeMonads.hs @@ -155,6 +155,7 @@ import Language.Haskell.LSP.Types ( Command(..) , WorkspaceEdit(..) , filePathToUri , uriToFilePath + , toNormalizedUri ) import Language.Haskell.LSP.VFS ( VirtualFile(..) ) @@ -410,7 +411,7 @@ getVirtualFile :: (MonadIde m, MonadIO m) => Uri -> m (Maybe VirtualFile) getVirtualFile uri = do mlf <- ideEnvLspFuncs <$> getIdeEnv case mlf of - Just lf -> liftIO $ Core.getVirtualFileFunc lf uri + Just lf -> liftIO $ Core.getVirtualFileFunc lf (toNormalizedUri uri) Nothing -> return Nothing getConfig :: (MonadIde m, MonadIO m) => m Config diff --git a/hie-plugin-api/hie-plugin-api.cabal b/hie-plugin-api/hie-plugin-api.cabal index e09f4a525..201ac6f3e 100644 --- a/hie-plugin-api/hie-plugin-api.cabal +++ b/hie-plugin-api/hie-plugin-api.cabal @@ -45,7 +45,7 @@ library , ghc , ghc-mod-core >= 5.9.0.0 , ghc-project-types >= 5.9.0.0 - , haskell-lsp == 0.14.* + , haskell-lsp == 0.15.* , hslogger , monad-control , mtl diff --git a/src/Haskell/Ide/Engine/LSP/CodeActions.hs b/src/Haskell/Ide/Engine/LSP/CodeActions.hs index f74efebf9..7eff8ede7 100644 --- a/src/Haskell/Ide/Engine/LSP/CodeActions.hs +++ b/src/Haskell/Ide/Engine/LSP/CodeActions.hs @@ -32,7 +32,7 @@ handleCodeActionReq :: TrackingNumber -> J.CodeActionRequest -> R () handleCodeActionReq tn req = do vfsFunc <- asksLspFuncs Core.getVirtualFileFunc - docVersion <- fmap _version <$> liftIO (vfsFunc docUri) + docVersion <- fmap _version <$> liftIO (vfsFunc (J.toNormalizedUri docUri)) let docId = J.VersionedTextDocumentIdentifier docUri docVersion let getProvider p = pluginCodeActionProvider p <*> return (pluginId p) diff --git a/src/Haskell/Ide/Engine/Transport/LspStdio.hs b/src/Haskell/Ide/Engine/Transport/LspStdio.hs index a993c7a3c..59272dc42 100644 --- a/src/Haskell/Ide/Engine/Transport/LspStdio.hs +++ b/src/Haskell/Ide/Engine/Transport/LspStdio.hs @@ -93,7 +93,7 @@ data DiagnosticsRequest = DiagnosticsRequest , trackingNumber :: TrackingNumber -- ^ The tracking identifier for this request - , file :: J.Uri + , file :: Uri -- ^ The file that was change and needs to be checked , documentVersion :: J.TextDocumentVersion @@ -118,7 +118,7 @@ run scheduler _origDir plugins captureFp = flip E.catches handlers $ do rin <- atomically newTChan :: IO (TChan ReactorInput) commandIds <- allLspCmdIds plugins - let dp lf = do + let onStartup lf = do diagIn <- atomically newTChan let react = runReactor lf scheduler diagnosticProviders hps sps fps plugins reactorFunc = react $ reactor rin diagIn @@ -175,8 +175,11 @@ run scheduler _origDir plugins captureFp = flip E.catches handlers $ do fps :: Map.Map PluginId FormattingProvider fps = Map.mapMaybe pluginFormattingProvider $ ipMap plugins + initCallbacks :: Core.InitializeCallbacks Config + initCallbacks = Core.InitializeCallbacks getInitialConfig getConfigFromNotification onStartup + flip E.finally finalProc $ do - CTRL.run (getConfigFromNotification, dp) (hieHandlers rin) (hieOptions commandIds) captureFp + CTRL.run initCallbacks (hieHandlers rin) (hieOptions commandIds) captureFp where handlers = [E.Handler ioExcept, E.Handler someExcept] finalProc = L.removeAllHandlers @@ -199,7 +202,7 @@ configVal field = field <$> getClientConfig getPrefixAtPos :: (MonadIO m, MonadReader REnv m) => Uri -> Position -> m (Maybe Hie.PosPrefixInfo) getPrefixAtPos uri pos = do - mvf <- liftIO =<< asksLspFuncs Core.getVirtualFileFunc <*> pure uri + mvf <- liftIO =<< asksLspFuncs Core.getVirtualFileFunc <*> pure (J.toNormalizedUri uri) case mvf of Just vf -> VFS.getCompletionPrefix pos vf Nothing -> return Nothing @@ -214,7 +217,7 @@ mapFileFromVfs tn vtdi = do let uri = vtdi ^. J.uri ver = fromMaybe 0 (vtdi ^. J.version) vfsFunc <- asksLspFuncs Core.getVirtualFileFunc - mvf <- liftIO $ vfsFunc uri + mvf <- liftIO $ vfsFunc (J.toNormalizedUri uri) case (mvf, uriToFilePath uri) of (Just (VFS.VirtualFile _ yitext _), Just fp) -> do let text' = Rope.toString yitext @@ -308,7 +311,7 @@ updatePositionMap uri changes = pluginGetFile "updatePositionMap: " uri $ \file -- --------------------------------------------------------------------- publishDiagnostics :: (MonadIO m, MonadReader REnv m) - => Int -> J.Uri -> J.TextDocumentVersion -> DiagnosticsBySource -> m () + => Int -> J.NormalizedUri -> J.TextDocumentVersion -> DiagnosticsBySource -> m () publishDiagnostics maxToSend uri' mv diags = do lf <- asks lspFuncs liftIO $ Core.publishDiagnosticsFunc lf maxToSend uri' mv diags @@ -797,7 +800,7 @@ reactor inp diagIn = do withDocumentContents :: J.LspId -> J.Uri -> (T.Text -> R ()) -> R () withDocumentContents reqId uri f = do vfsFunc <- asksLspFuncs Core.getVirtualFileFunc - mvf <- liftIO $ vfsFunc uri + mvf <- liftIO $ vfsFunc (J.toNormalizedUri uri) lf <- asks lspFuncs case mvf of Nothing -> liftIO $ @@ -838,7 +841,7 @@ queueDiagnosticsRequest :: TChan DiagnosticsRequest -- ^ The channel to publish the diagnostics requests to -> DiagnosticTrigger -> TrackingNumber - -> J.Uri + -> Uri -> J.TextDocumentVersion -> R () queueDiagnosticsRequest diagIn dt tn uri mVer = @@ -869,11 +872,11 @@ requestDiagnostics DiagnosticsRequest{trigger, file, trackingNumber, documentVer maxToSend = maxNumberOfProblems clientConfig sendOne (fileUri,ds') = do debugm $ "LspStdio.sendone:(fileUri,ds')=" ++ show(fileUri,ds') - publishDiagnosticsIO maxToSend fileUri Nothing (Map.fromList [(Just pid,SL.toSortedList ds')]) + publishDiagnosticsIO maxToSend (J.toNormalizedUri fileUri) Nothing (Map.fromList [(Just pid,SL.toSortedList ds')]) sendEmpty = do debugm "LspStdio.sendempty" - publishDiagnosticsIO maxToSend file Nothing (Map.fromList [(Just pid,SL.toSortedList [])]) + publishDiagnosticsIO maxToSend (J.toNormalizedUri file) Nothing (Map.fromList [(Just pid,SL.toSortedList [])]) -- fv = case documentVersion of -- Nothing -> Nothing @@ -901,7 +904,7 @@ requestDiagnostics DiagnosticsRequest{trigger, file, trackingNumber, documentVer when enabled $ makeRequest reql -- | get hlint and GHC diagnostics and loads the typechecked module into the cache -requestDiagnosticsNormal :: TrackingNumber -> J.Uri -> J.TextDocumentVersion -> R () +requestDiagnosticsNormal :: TrackingNumber -> Uri -> J.TextDocumentVersion -> R () requestDiagnosticsNormal tn file mVer = do clientConfig <- getClientConfig let @@ -909,18 +912,20 @@ requestDiagnosticsNormal tn file mVer = do -- | If there is a GHC error, flush the hlint diagnostics -- TODO: Just flush the parse error diagnostics - sendOneGhc :: J.DiagnosticSource -> (Uri, [Diagnostic]) -> R () + sendOneGhc :: J.DiagnosticSource -> (J.NormalizedUri, [Diagnostic]) -> R () sendOneGhc pid (fileUri,ds) = do if any (hasSeverity J.DsError) ds then publishDiagnostics maxToSend fileUri Nothing (Map.fromList [(Just "hlint",SL.toSortedList []),(Just pid,SL.toSortedList ds)]) else sendOne pid (fileUri,ds) + sendOne pid (fileUri,ds) = do publishDiagnostics maxToSend fileUri Nothing (Map.fromList [(Just pid,SL.toSortedList ds)]) + hasSeverity :: J.DiagnosticSeverity -> J.Diagnostic -> Bool hasSeverity sev (J.Diagnostic _ (Just s) _ _ _ _) = s == sev hasSeverity _ _ = False - sendEmpty = publishDiagnostics maxToSend file Nothing (Map.fromList [(Just "ghcmod",SL.toSortedList [])]) + sendEmpty = publishDiagnostics maxToSend (J.toNormalizedUri file) Nothing (Map.fromList [(Just "ghcmod",SL.toSortedList [])]) maxToSend = maxNumberOfProblems clientConfig let sendHlint = hlintOn clientConfig @@ -929,13 +934,13 @@ requestDiagnosticsNormal tn file mVer = do let reql = GReq tn (Just file) (Just (file,ver)) Nothing callbackl $ ApplyRefact.lintCmd' file callbackl (PublishDiagnosticsParams fp (List ds)) - = sendOne "hlint" (fp, ds) + = sendOne "hlint" (J.toNormalizedUri fp, ds) makeRequest reql -- get GHC diagnostics and loads the typechecked module into the cache let reqg = GReq tn (Just file) (Just (file,ver)) Nothing callbackg $ HIE.setTypecheckedModule file - callbackg (pd, errs) = do + callbackg (HIE.Diagnostics pd, errs) = do forM_ errs $ \e -> do reactorSend $ NotShowMessage $ fmServerShowMessageNotification J.MtError diff --git a/stack-8.2.2.yaml b/stack-8.2.2.yaml index 65b0415e0..8dffe2c8c 100644 --- a/stack-8.2.2.yaml +++ b/stack-8.2.2.yaml @@ -20,14 +20,14 @@ extra-deps: - ghc-exactprint-0.5.8.2 - haddock-api-2.18.1 - haddock-library-1.4.4 -- haskell-lsp-0.14.0.0 -- haskell-lsp-types-0.14.0.1 +- haskell-lsp-0.15.0.0 +- haskell-lsp-types-0.15.0.0 - haskell-src-exts-1.21.0 - haskell-src-exts-util-0.2.5 - hlint-2.1.17 # last hlint supporting GHC 8.2 - hoogle-5.0.17.9 - hsimport-0.8.8 -- lsp-test-0.5.4.0 +- lsp-test-0.6.0.0 - monad-dijkstra-0.1.1.2 - pretty-show-1.8.2 - rope-utf16-splay-0.3.1.0 diff --git a/stack-8.4.2.yaml b/stack-8.4.2.yaml index ec92a9c33..d13e63942 100644 --- a/stack-8.4.2.yaml +++ b/stack-8.4.2.yaml @@ -19,14 +19,14 @@ extra-deps: - ghc-lib-parser-8.8.0.20190424 - haddock-api-2.20.0 - haddock-library-1.6.0 -- haskell-lsp-0.14.0.0 -- haskell-lsp-types-0.14.0.1 +- haskell-lsp-0.15.0.0 +- haskell-lsp-types-0.15.0.0 - haskell-src-exts-1.21.0 - haskell-src-exts-util-0.2.5 - hlint-2.1.24 - hoogle-5.0.17.9 - hsimport-0.10.0 -- lsp-test-0.5.4.0 +- lsp-test-0.6.0.0 - monad-dijkstra-0.1.1.2 - pretty-show-1.8.2 - rope-utf16-splay-0.3.1.0 diff --git a/stack-8.4.3.yaml b/stack-8.4.3.yaml index f8d756903..7c78982de 100644 --- a/stack-8.4.3.yaml +++ b/stack-8.4.3.yaml @@ -19,14 +19,14 @@ extra-deps: - ghc-lib-parser-8.8.0.20190424 - haddock-api-2.20.0 - haddock-library-1.6.0 -- haskell-lsp-0.14.0.0 -- haskell-lsp-types-0.14.0.1 +- haskell-lsp-0.15.0.0 +- haskell-lsp-types-0.15.0.0 - haskell-src-exts-1.21.0 - haskell-src-exts-util-0.2.5 - hlint-2.1.24 - hoogle-5.0.17.9 - hsimport-0.10.0 -- lsp-test-0.5.4.0 +- lsp-test-0.6.0.0 - monad-dijkstra-0.1.1.2 - pretty-show-1.8.2 - rope-utf16-splay-0.3.1.0 diff --git a/stack-8.4.4.yaml b/stack-8.4.4.yaml index 30200043a..09edacf36 100644 --- a/stack-8.4.4.yaml +++ b/stack-8.4.4.yaml @@ -18,14 +18,14 @@ extra-deps: - ghc-lib-parser-8.8.0.20190424 - haddock-api-2.20.0 - haddock-library-1.6.0 -- haskell-lsp-0.14.0.0 -- haskell-lsp-types-0.14.0.1 +- haskell-lsp-0.15.0.0 +- haskell-lsp-types-0.15.0.0 - haskell-src-exts-1.21.0 - haskell-src-exts-util-0.2.5 - hlint-2.1.24 - hoogle-5.0.17.9 - hsimport-0.10.0 -- lsp-test-0.5.4.0 +- lsp-test-0.6.0.0 - monad-dijkstra-0.1.1.2 - optparse-simple-0.1.0 - pretty-show-1.9.5 diff --git a/stack-8.6.1.yaml b/stack-8.6.1.yaml index 1479408ec..5679651ff 100644 --- a/stack-8.6.1.yaml +++ b/stack-8.6.1.yaml @@ -21,8 +21,8 @@ extra-deps: - floskell-0.10.0 - ghc-lib-parser-8.8.0.20190424 - haddock-api-2.21.0 -- haskell-lsp-0.14.0.0 -- haskell-lsp-types-0.14.0.1 +- haskell-lsp-0.15.0.0 +- haskell-lsp-types-0.15.0.0 - haskell-src-exts-1.21.0 - haskell-src-exts-util-0.2.5 - hlint-2.1.24 diff --git a/stack-8.6.2.yaml b/stack-8.6.2.yaml index 2fc6e881f..2a4983b51 100644 --- a/stack-8.6.2.yaml +++ b/stack-8.6.2.yaml @@ -17,14 +17,14 @@ extra-deps: - floskell-0.10.0 - ghc-lib-parser-8.8.0.20190424 - haddock-api-2.21.0 -- haskell-lsp-0.14.0.0 -- haskell-lsp-types-0.14.0.1 +- haskell-lsp-0.15.0.0 +- haskell-lsp-types-0.15.0.0 - haskell-src-exts-1.21.0 - haskell-src-exts-util-0.2.5 - hlint-2.1.24 - hoogle-5.0.17.9 - hsimport-0.10.0 -- lsp-test-0.5.4.0 +- lsp-test-0.6.0.0 - monad-dijkstra-0.1.1.2 - monad-memo-0.4.1 - multistate-0.8.0.1 diff --git a/stack-8.6.3.yaml b/stack-8.6.3.yaml index 14059e83b..792bb8870 100644 --- a/stack-8.6.3.yaml +++ b/stack-8.6.3.yaml @@ -17,14 +17,14 @@ extra-deps: - floskell-0.10.0 - ghc-lib-parser-8.8.0.20190424 - haddock-api-2.21.0 -- haskell-lsp-0.14.0.0 -- haskell-lsp-types-0.14.0.1 +- haskell-lsp-0.15.0.0 +- haskell-lsp-types-0.15.0.0 - haskell-src-exts-1.21.0 - haskell-src-exts-util-0.2.5 - hlint-2.1.24 - hoogle-5.0.17.9 - hsimport-0.10.0 -- lsp-test-0.5.4.0 +- lsp-test-0.6.0.0 - monad-dijkstra-0.1.1.2 - monad-memo-0.4.1 - multistate-0.8.0.1 diff --git a/stack-8.6.4.yaml b/stack-8.6.4.yaml index 5df504e5c..521e175f1 100644 --- a/stack-8.6.4.yaml +++ b/stack-8.6.4.yaml @@ -17,13 +17,13 @@ extra-deps: - floskell-0.10.0 - ghc-lib-parser-8.8.0.20190424 - haddock-api-2.22.0 -- haskell-lsp-0.14.0.0 -- haskell-lsp-types-0.14.0.1 +- haskell-lsp-0.15.0.0 +- haskell-lsp-types-0.15.0.0 - haskell-src-exts-1.21.0 - hlint-2.1.24 - hoogle-5.0.17.9 - hsimport-0.10.0 -- lsp-test-0.5.4.0 +- lsp-test-0.6.0.0 - monad-dijkstra-0.1.1.2@rev:1 - monad-memo-0.4.1 - multistate-0.8.0.1 diff --git a/stack-8.6.5.yaml b/stack-8.6.5.yaml index e24840307..7afeba6f5 100644 --- a/stack-8.6.5.yaml +++ b/stack-8.6.5.yaml @@ -1,4 +1,4 @@ -resolver: lts-13.23 # First GHC 8.6.5 +resolver: lts-13.27 packages: - . - hie-plugin-api @@ -17,13 +17,13 @@ extra-deps: - floskell-0.10.0 - ghc-lib-parser-8.8.0.20190424 - haddock-api-2.22.0 -- haskell-lsp-0.14.0.0 -- haskell-lsp-types-0.14.0.1 +- haskell-lsp-0.15.0.0 +- haskell-lsp-types-0.15.0.0 - haskell-src-exts-1.21.0 - hlint-2.1.24 - hsimport-0.10.0 - hoogle-5.0.17.9 -- lsp-test-0.5.4.0 +- lsp-test-0.6.0.0 - monad-dijkstra-0.1.1.2@rev:1 - monad-memo-0.4.1 - multistate-0.8.0.1 diff --git a/test/dispatcher/Main.hs b/test/dispatcher/Main.hs index 4d8113363..dacd786f4 100644 --- a/test/dispatcher/Main.hs +++ b/test/dispatcher/Main.hs @@ -173,7 +173,7 @@ funcSpec = describe "functional dispatch" $ do -- followed by the diagnostics ... ("req2",Right res2) <- atomically $ readTChan logChan - show res2 `shouldBe` "((Map Uri (Set Diagnostic)),[Text])" + show res2 `shouldBe` "(Diagnostics,[Text])" -- No more pending results rr3 <- atomically $ tryReadTChan logChan @@ -280,7 +280,7 @@ funcSpec = describe "functional dispatch" $ do unpackRes hr7 `shouldBe` ("req7", Just ([] :: [Location])) ("req8", Right diags) <- atomically $ readTChan logChan - show diags `shouldBe` "((Map Uri (Set Diagnostic)),[Text])" + show diags `shouldBe` "(Diagnostics,[Text])" killThread dispatcher diff --git a/test/unit/GhcModPluginSpec.hs b/test/unit/GhcModPluginSpec.hs index 6a87d0e25..fcaa75ecd 100644 --- a/test/unit/GhcModPluginSpec.hs +++ b/test/unit/GhcModPluginSpec.hs @@ -15,7 +15,7 @@ import Haskell.Ide.Engine.MonadTypes import Haskell.Ide.Engine.Plugin.GhcMod import Haskell.Ide.Engine.PluginUtils import Haskell.Ide.Engine.Support.HieExtras -import Language.Haskell.LSP.Types (TextEdit (..)) +import Language.Haskell.LSP.Types (TextEdit (..), toNormalizedUri) import System.Directory import TestUtils @@ -51,7 +51,7 @@ ghcmodSpec = ss -> fail $ "got:" ++ show ss let res = IdeResultOk $ - (Map.singleton arg (S.singleton diag), env) + (Diagnostics (Map.singleton (toNormalizedUri arg) (S.singleton diag)), env) diag = Diagnostic (Range (toPos (4,7)) (toPos (4,8))) (Just DsError) From 09ab83a06f8a1b3e9a3afe8d5acc7b5547aca695 Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Rodriguez Date: Thu, 4 Jul 2019 13:47:15 +0200 Subject: [PATCH 101/158] Fixed stack file for 8.6.1 --- stack-8.6.1.yaml | 2 +- stack.yaml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/stack-8.6.1.yaml b/stack-8.6.1.yaml index 5679651ff..510ed9c4e 100644 --- a/stack-8.6.1.yaml +++ b/stack-8.6.1.yaml @@ -28,7 +28,7 @@ extra-deps: - hlint-2.1.24 - hoogle-5.0.17.9 - hsimport-0.10.0 -- lsp-test-0.5.4.0 +- lsp-test-0.6.0.0 - monad-dijkstra-0.1.1.2 - monad-memo-0.4.1 - monoid-subclasses-0.4.6.1 diff --git a/stack.yaml b/stack.yaml index 82b19111e..7250d5a31 100644 --- a/stack.yaml +++ b/stack.yaml @@ -21,11 +21,11 @@ extra-deps: - ghc-exactprint-0.5.8.2 - ghc-lib-parser-8.8.0.20190424 - haddock-api-2.22.0 -- haskell-lsp-0.14.0.0 -- haskell-lsp-types-0.14.0.1 +- haskell-lsp-0.15.0.0 +- haskell-lsp-types-0.15.0.0 - hlint-2.1.24 - hsimport-0.10.0 -- lsp-test-0.5.4.0 +- lsp-test-0.6.0.0 - monad-dijkstra-0.1.1.2@rev:1 - monad-memo-0.4.1 - multistate-0.8.0.1 From f295623eb79bebfb785a2876ff306e3b202842aa Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Rodriguez Date: Thu, 4 Jul 2019 15:43:25 +0200 Subject: [PATCH 102/158] Importing semigourp to please 8.2.2 --- hie-plugin-api/Haskell/Ide/Engine/Ghc.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hie-plugin-api/Haskell/Ide/Engine/Ghc.hs b/hie-plugin-api/Haskell/Ide/Engine/Ghc.hs index b032a15d2..d103507ac 100644 --- a/hie-plugin-api/Haskell/Ide/Engine/Ghc.hs +++ b/hie-plugin-api/Haskell/Ide/Engine/Ghc.hs @@ -21,7 +21,7 @@ import Bag import Control.Monad.IO.Class import Data.IORef import qualified Data.Map.Strict as Map -import Data.Semigroup ((<>)) +import Data.Semigroup ((<>), Semigroup) import qualified Data.Set as Set import qualified Data.Text as T import qualified Data.Aeson From 0afad0530279248f88355602f382a0ff29e8b441 Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Rodriguez Date: Thu, 4 Jul 2019 16:32:38 +0200 Subject: [PATCH 103/158] Fixed mappend implementation for 8.2.2 --- hie-plugin-api/Haskell/Ide/Engine/Ghc.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/hie-plugin-api/Haskell/Ide/Engine/Ghc.hs b/hie-plugin-api/Haskell/Ide/Engine/Ghc.hs index d103507ac..3f6813266 100644 --- a/hie-plugin-api/Haskell/Ide/Engine/Ghc.hs +++ b/hie-plugin-api/Haskell/Ide/Engine/Ghc.hs @@ -58,6 +58,7 @@ instance Semigroup Diagnostics where Diagnostics d1 <> Diagnostics d2 = Diagnostics (d1 <> d2) instance Monoid Diagnostics where + mappend = (<>) mempty = Diagnostics mempty instance Data.Aeson.ToJSON Diagnostics where From 79ded0c28acb32e070e9c7679565f78a2a55ffb9 Mon Sep 17 00:00:00 2001 From: jneira Date: Thu, 4 Jul 2019 07:31:43 +0200 Subject: [PATCH 104/158] Clear out pattern matching and error message of executeCodeActionByName --- test/functional/FunctionalCodeActionsSpec.hs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/functional/FunctionalCodeActionsSpec.hs b/test/functional/FunctionalCodeActionsSpec.hs index f25345d88..f029cafe1 100644 --- a/test/functional/FunctionalCodeActionsSpec.hs +++ b/test/functional/FunctionalCodeActionsSpec.hs @@ -751,11 +751,11 @@ hsImportSpec formatterName [e1, e2, e3, e4] = let actions = filter (\actn -> actn ^. L.title `elem` names) allActions case actions of (action:_) -> executeCodeAction action - xs -> + [] -> error - $ "Found an unexpected amount of action. Expected 1, but got: " - ++ show (length xs) - ++ ".\n Titles: " ++ show (map (^. L.title) allActions) + $ "No action found to be executed: " + ++ ".\n Actual actions titles: " ++ show (map (^. L.title) allActions) + ++ ".\n Expected action titles:" ++ show names -- Silence warnings hsImportSpec formatter args = From eec221798e37a6a0ae0c6d026b7e97b7cd1b5600 Mon Sep 17 00:00:00 2001 From: jneira Date: Fri, 5 Jul 2019 00:06:38 +0200 Subject: [PATCH 105/158] Correct punctuation --- test/functional/FunctionalCodeActionsSpec.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/functional/FunctionalCodeActionsSpec.hs b/test/functional/FunctionalCodeActionsSpec.hs index f029cafe1..414a0170a 100644 --- a/test/functional/FunctionalCodeActionsSpec.hs +++ b/test/functional/FunctionalCodeActionsSpec.hs @@ -753,9 +753,9 @@ hsImportSpec formatterName [e1, e2, e3, e4] = (action:_) -> executeCodeAction action [] -> error - $ "No action found to be executed: " - ++ ".\n Actual actions titles: " ++ show (map (^. L.title) allActions) - ++ ".\n Expected action titles:" ++ show names + $ "No action found to be executed!" + ++ "\n Actual actions titles: " ++ show (map (^. L.title) allActions) + ++ "\n Expected action titles: " ++ show names -- Silence warnings hsImportSpec formatter args = From db61869248c16e5f64735b66cd630b659492f9c4 Mon Sep 17 00:00:00 2001 From: jneira Date: Fri, 5 Jul 2019 00:33:22 +0200 Subject: [PATCH 106/158] Correct plural --- test/functional/FunctionalCodeActionsSpec.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/functional/FunctionalCodeActionsSpec.hs b/test/functional/FunctionalCodeActionsSpec.hs index 414a0170a..76b817243 100644 --- a/test/functional/FunctionalCodeActionsSpec.hs +++ b/test/functional/FunctionalCodeActionsSpec.hs @@ -755,7 +755,7 @@ hsImportSpec formatterName [e1, e2, e3, e4] = error $ "No action found to be executed!" ++ "\n Actual actions titles: " ++ show (map (^. L.title) allActions) - ++ "\n Expected action titles: " ++ show names + ++ "\n Expected actions titles: " ++ show names -- Silence warnings hsImportSpec formatter args = From 1a8c461e97c4e244604a43c9a21f2c4fd6389b75 Mon Sep 17 00:00:00 2001 From: Alan Zimmerman Date: Sun, 7 Jul 2019 12:22:57 +0200 Subject: [PATCH 107/158] Bump nightly resolver to 2019-07-07 --- stack.yaml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/stack.yaml b/stack.yaml index 7250d5a31..403e8e0e2 100644 --- a/stack.yaml +++ b/stack.yaml @@ -1,4 +1,4 @@ -resolver: nightly-2019-05-31 # GHC 8.6.5 +resolver: nightly-2019-07-07 # GHC 8.6.5 packages: - . - hie-plugin-api @@ -13,12 +13,9 @@ extra-deps: - ansi-terminal-0.8.2 - ansi-wl-pprint-0.6.8.2 - brittany-0.12.0.0 -- butcher-1.3.2.1 - cabal-plan-0.4.0.0 - constrained-dynamic-0.1.0.0 -- deque-0.2.7 - floskell-0.10.1 -- ghc-exactprint-0.5.8.2 - ghc-lib-parser-8.8.0.20190424 - haddock-api-2.22.0 - haskell-lsp-0.15.0.0 @@ -27,8 +24,6 @@ extra-deps: - hsimport-0.10.0 - lsp-test-0.6.0.0 - monad-dijkstra-0.1.1.2@rev:1 -- monad-memo-0.4.1 -- multistate-0.8.0.1 - syz-0.2.0.0 - temporary-1.2.1.1 # To make build work in windows 7 From f05ad2fdfbd81acae67074c5c4128657a2c81cbf Mon Sep 17 00:00:00 2001 From: fendor Date: Sun, 7 Jul 2019 13:10:51 +0200 Subject: [PATCH 108/158] Reuse unHTML for searchModules' --- src/Haskell/Ide/Engine/Plugin/Hoogle.hs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/Haskell/Ide/Engine/Plugin/Hoogle.hs b/src/Haskell/Ide/Engine/Plugin/Hoogle.hs index 018ccbbf9..9030105c6 100644 --- a/src/Haskell/Ide/Engine/Plugin/Hoogle.hs +++ b/src/Haskell/Ide/Engine/Plugin/Hoogle.hs @@ -141,6 +141,10 @@ renderTarget t = T.intercalate "\n" $ annotate :: (String, String) -> String annotate (thing,url) = "["<>thing<>"]"<>"("<>url<>")" +-- | Hoogle results contain html like tags. +-- We remove them with `tagsoup` here. +-- So, if something hoogle related shows html tags, +-- then maybe this function is responsible. unHTML :: T.Text -> T.Text unHTML = T.replace "<0>" "" . innerText . parseTags @@ -172,13 +176,6 @@ searchModules = fmap (map fst) . searchModules' searchModules' :: T.Text -> IdeM [(T.Text, T.Text)] searchModules' = fmap (take 5 . nub) . searchTargets retrieveModuleAndSignature where - -- | Hoogle results contain html like tags. - -- We remove them with `tagsoup` here. - -- So, if something hoogle related shows html tags, - -- then maybe this function is responsible. - normaliseItem :: T.Text -> T.Text - normaliseItem = innerText . parseTags - retrieveModuleAndSignature :: Target -> Maybe (T.Text, T.Text) retrieveModuleAndSignature target = liftA2 (,) (packModuleName target) (packSymbolSignature target) @@ -186,7 +183,7 @@ searchModules' = fmap (take 5 . nub) . searchTargets retrieveModuleAndSignature packModuleName = fmap (T.pack . fst) . targetModule packSymbolSignature :: Target -> Maybe T.Text - packSymbolSignature = Just . normaliseItem . T.pack . targetItem + packSymbolSignature = Just . unHTML . T.pack . targetItem -- | Search for packages that satisfy the given search text. -- Will return at most five, unique results. From e2c25cf5df9e95d15ce83862040a11da93a11409 Mon Sep 17 00:00:00 2001 From: Alan Zimmerman Date: Sun, 7 Jul 2019 13:12:23 +0200 Subject: [PATCH 109/158] Preparing for 0.11.0.0 release --- Changelog.md | 65 +++++++++++++++++++++++++++++ haskell-ide-engine.cabal | 2 +- hie-plugin-api/hie-plugin-api.cabal | 2 +- 3 files changed, 67 insertions(+), 2 deletions(-) diff --git a/Changelog.md b/Changelog.md index b4bbbc868..6a9047a61 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,68 @@ +# 0.11.0.0 + +- Bump resolvers. `lts-13.27` for GHC 8.6.5, `nightly-2019-07-07` for + nightly build, rest are unchanged. +([#1319 ](https://github.com/haskell/haskell-ide-engine/pull/1319),by @alanz) +([#1316 ](https://github.com/haskell/haskell-ide-engine/pull/1316), by @lorenzo) + +- Clear out pattern matching and error message of executeCodeActionByName +([#1317 ](https://github.com/haskell/haskell-ide-engine/pull/1317), by @jneira) + +- Upgrade to haskell-lsp 0.15 +([#1316 ](https://github.com/haskell/haskell-ide-engine/pull/1316), by @lorenzo) + +- Update Arch Linux install instructions +([#1315 ](https://github.com/haskell/haskell-ide-engine/pull/1315), by @friedbrice) + +- Fix liquid unit test normalizing paths +([#1310 ](https://github.com/haskell/haskell-ide-engine/pull/1310), by @jneira) + +- Add unix-time constraint to cabal file +([#1306 ](https://github.com/haskell/haskell-ide-engine/pull/1306), by @alanz) + +- Fix a memory leak found by @mpickering +([#1305 ](https://github.com/haskell/haskell-ide-engine/pull/1305), by @lorenzo) + +- Fix build for Windows 7 +([#1304 ](https://github.com/haskell/haskell-ide-engine/pull/1304), by @jneira) + +- Brittany 0.12 +([#1301 ](https://github.com/haskell/haskell-ide-engine/pull/1301), by @alanz) + +- Use ghc-mod without memory leak +([#1299 ](https://github.com/haskell/haskell-ide-engine/pull/1299), by @alanz) + +- install.hs: Make all available GHCs in PATH buildable +([#1297 ](https://github.com/haskell/haskell-ide-engine/pull/1297), by @maoe) + +- Fix file mapping state when we have a parsed module but not a typechecked module +([#1295 ](https://github.com/haskell/haskell-ide-engine/pull/1295), by @wz1000) + +- Use ghc-mod which loads ghc plugins +([#1293 ](https://github.com/haskell/haskell-ide-engine/pull/1293), by @alanz) + +- Fix UriCaches being leaked (bug fix) +([#1292 ](https://github.com/haskell/haskell-ide-engine/pull/1292), by @bubba) + +- Stack 2.1.1 +([#1291 ](https://github.com/haskell/haskell-ide-engine/pull/1291), by @alanz) + +- Render completion documentation to markdown +([#1290 ](https://github.com/haskell/haskell-ide-engine/pull/1290), by @Avi-D-coder) + +- Trying out haskell-lsp 0.14 +([#1288 ](https://github.com/haskell/haskell-ide-engine/pull/1288), by @alanz) + +- Hlint 2.1.24 +([#1287 ](https://github.com/haskell/haskell-ide-engine/pull/1287), by @alanz) + +- Improve import action of hsimport +([#1284 ](https://github.com/haskell/haskell-ide-engine/pull/1284), by @fendor) + +- Add liquid haskell smt solver to README +([#1283 ](https://github.com/haskell/haskell-ide-engine/pull/1283), by @fendor) + + # 0.10.0.0 - Drop GHC 8.2.1 support. diff --git a/haskell-ide-engine.cabal b/haskell-ide-engine.cabal index 994244d4a..6fde7cd5b 100644 --- a/haskell-ide-engine.cabal +++ b/haskell-ide-engine.cabal @@ -1,5 +1,5 @@ name: haskell-ide-engine -version: 0.10.0.0 +version: 0.11.0.0 synopsis: Provide a common engine to power any Haskell IDE description: Please see README.md homepage: http://github.com/githubuser/haskell-ide-engine#readme diff --git a/hie-plugin-api/hie-plugin-api.cabal b/hie-plugin-api/hie-plugin-api.cabal index 201ac6f3e..af65468a0 100644 --- a/hie-plugin-api/hie-plugin-api.cabal +++ b/hie-plugin-api/hie-plugin-api.cabal @@ -1,5 +1,5 @@ name: hie-plugin-api -version: 0.10.0.0 +version: 0.11.0.0 synopsis: Haskell IDE API for plugin communication license: BSD3 license-file: LICENSE From 575060ad84a02d26c8ce95b1be74919dfc4c647c Mon Sep 17 00:00:00 2001 From: fendor Date: Sun, 7 Jul 2019 13:40:34 +0200 Subject: [PATCH 110/158] Remove cabal file from test-suite for Package Plugin --- .../addPackageTest/hybrid-exe/asdf.cabal | 60 ------------------- 1 file changed, 60 deletions(-) delete mode 100644 test/testdata/addPackageTest/hybrid-exe/asdf.cabal diff --git a/test/testdata/addPackageTest/hybrid-exe/asdf.cabal b/test/testdata/addPackageTest/hybrid-exe/asdf.cabal deleted file mode 100644 index 79425af44..000000000 --- a/test/testdata/addPackageTest/hybrid-exe/asdf.cabal +++ /dev/null @@ -1,60 +0,0 @@ -cabal-version: 1.12 - --- This file has been generated from package.yaml by hpack version 0.31.2. --- --- see: https://github.com/sol/hpack --- --- hash: a63a1c272a979a805027c5855cbe062ec4698b6ea6dbe59dd5f7aa34b15656a6 - -name: asdf -version: 0.1.0.0 -description: Please see the README on GitHub at -homepage: https://github.com/githubuser/asdf#readme -bug-reports: https://github.com/githubuser/asdf/issues -author: Author name here -maintainer: example@example.com -copyright: 2018 Author name here -license: BSD3 -build-type: Simple -extra-source-files: - README.md - ChangeLog.md - -source-repository head - type: git - location: https://github.com/githubuser/asdf - -library - other-modules: - Paths_asdf - hs-source-dirs: - src - build-depends: - base >=4.7 && <5 - default-language: Haskell2010 - -executable asdf-exe - main-is: Main.hs - other-modules: - Asdf - Paths_asdf - hs-source-dirs: - app - ghc-options: -threaded -rtsopts -with-rtsopts=-N - build-depends: - asdf - , base >=4.7 && <5 - default-language: Haskell2010 - -test-suite asdf-test - type: exitcode-stdio-1.0 - main-is: Spec.hs - other-modules: - Paths_asdf - hs-source-dirs: - test - ghc-options: -threaded -rtsopts -with-rtsopts=-N - build-depends: - asdf - , base >=4.7 && <5 - default-language: Haskell2010 From d18813b4bf6c9b5c3a2f43b2346420adbf004c6f Mon Sep 17 00:00:00 2001 From: fendor Date: Sun, 7 Jul 2019 13:55:21 +0200 Subject: [PATCH 111/158] Remove hybrid test-cases Remove since they do not add anything to the coverage --- test/functional/FunctionalCodeActionsSpec.hs | 26 ------ .../addPackageTest/hybrid-exe/AddPackage.hs | 2 - .../addPackageTest/hybrid-exe/app/Asdf.hs | 5 -- .../addPackageTest/hybrid-exe/package.yaml | 37 --------- .../addPackageTest/hybrid-lib/app/Asdf.hs | 5 -- .../addPackageTest/hybrid-lib/asdf.cabal | 36 --------- .../addPackageTest/hybrid-lib/package.yaml | 25 ------ test/unit/PackagePluginSpec.hs | 79 +------------------ test/utils/TestUtils.hs | 2 - 9 files changed, 3 insertions(+), 214 deletions(-) delete mode 100644 test/testdata/addPackageTest/hybrid-exe/AddPackage.hs delete mode 100644 test/testdata/addPackageTest/hybrid-exe/app/Asdf.hs delete mode 100644 test/testdata/addPackageTest/hybrid-exe/package.yaml delete mode 100644 test/testdata/addPackageTest/hybrid-lib/app/Asdf.hs delete mode 100644 test/testdata/addPackageTest/hybrid-lib/asdf.cabal delete mode 100644 test/testdata/addPackageTest/hybrid-lib/package.yaml diff --git a/test/functional/FunctionalCodeActionsSpec.hs b/test/functional/FunctionalCodeActionsSpec.hs index 76b817243..5d763870c 100644 --- a/test/functional/FunctionalCodeActionsSpec.hs +++ b/test/functional/FunctionalCodeActionsSpec.hs @@ -268,32 +268,6 @@ spec = describe "code actions" $ do T.lines contents !! 3 `shouldSatisfy` T.isSuffixOf "zlib" T.lines contents !! 21 `shouldNotSatisfy` T.isSuffixOf "zlib" - it "adds to hpack package.yaml files if both are present" $ - runSession hieCommand fullCaps "test/testdata/addPackageTest/hybrid-exe" $ do - doc <- openDoc "app/Asdf.hs" "haskell" - - -- ignore the first empty hlint diagnostic publish - [_,diag:_] <- count 2 waitForDiagnostics - - let preds = [ T.isPrefixOf "Could not load module ‘Codec.Compression.GZip’" - , T.isPrefixOf "Could not find module ‘Codec.Compression.GZip’" - ] - in liftIO $ diag ^. L.message `shouldSatisfy` \x -> any (\f -> f x) preds - - mActions <- getAllCodeActions doc - let allActions = map fromAction mActions - action = head allActions - - liftIO $ do - action ^. L.title `shouldBe` "Add zlib as a dependency" - forM_ allActions $ \a -> a ^. L.kind `shouldBe` Just CodeActionQuickFix - forM_ allActions $ \a -> a ^. L.command . _Just . L.command `shouldSatisfy` T.isSuffixOf "package:add" - - executeCodeAction action - - contents <- getDocumentEdit . TextDocumentIdentifier =<< getDocUri "package.yaml" - liftIO $ - T.lines contents !! 23 `shouldSatisfy` T.isSuffixOf "zlib" -- ----------------------------------- diff --git a/test/testdata/addPackageTest/hybrid-exe/AddPackage.hs b/test/testdata/addPackageTest/hybrid-exe/AddPackage.hs deleted file mode 100644 index 963020508..000000000 --- a/test/testdata/addPackageTest/hybrid-exe/AddPackage.hs +++ /dev/null @@ -1,2 +0,0 @@ -import Data.Text -foo = pack "I'm a Text" \ No newline at end of file diff --git a/test/testdata/addPackageTest/hybrid-exe/app/Asdf.hs b/test/testdata/addPackageTest/hybrid-exe/app/Asdf.hs deleted file mode 100644 index fdd639ffe..000000000 --- a/test/testdata/addPackageTest/hybrid-exe/app/Asdf.hs +++ /dev/null @@ -1,5 +0,0 @@ -{-# LANGUAGE OverloadedStrings #-} - -import Codec.Compression.GZip - -main = return $ compress "hello" \ No newline at end of file diff --git a/test/testdata/addPackageTest/hybrid-exe/package.yaml b/test/testdata/addPackageTest/hybrid-exe/package.yaml deleted file mode 100644 index 8a03b67e9..000000000 --- a/test/testdata/addPackageTest/hybrid-exe/package.yaml +++ /dev/null @@ -1,37 +0,0 @@ -name: asdf -version: 0.1.0.0 -github: "githubuser/asdf" -license: BSD3 -author: "Author name here" -maintainer: "example@example.com" -copyright: "2018 Author name here" - -extra-source-files: -- README.md -- ChangeLog.md - -# Metadata used when publishing your package -# synopsis: Short description of your package -# category: Web - -# To avoid duplicated efforts in documentation and dealing with the -# complications of embedding Haddock markup inside cabal files, it is -# common to point users to the README.md file. -description: Please see the README on GitHub at - -library: - source-dirs: src - dependencies: - - base - -executables: - asdf-exe: - main: Main.hs - source-dirs: app - ghc-options: - - -threaded - - -rtsopts - - -with-rtsopts=-N - dependencies: - - base - - asdf diff --git a/test/testdata/addPackageTest/hybrid-lib/app/Asdf.hs b/test/testdata/addPackageTest/hybrid-lib/app/Asdf.hs deleted file mode 100644 index 1bed3539c..000000000 --- a/test/testdata/addPackageTest/hybrid-lib/app/Asdf.hs +++ /dev/null @@ -1,5 +0,0 @@ -{-# LANGUAGE OverloadedStrings #-} -module Asdf where -import Codec.Compression.GZip - -main = return $ compress "hello" \ No newline at end of file diff --git a/test/testdata/addPackageTest/hybrid-lib/asdf.cabal b/test/testdata/addPackageTest/hybrid-lib/asdf.cabal deleted file mode 100644 index dbe8509b7..000000000 --- a/test/testdata/addPackageTest/hybrid-lib/asdf.cabal +++ /dev/null @@ -1,36 +0,0 @@ -cabal-version: 1.12 - --- This file has been generated from package.yaml by hpack version 0.31.2. --- --- see: https://github.com/sol/hpack --- --- hash: 0a09a2280cfeb48f88861d105a48255e71ec34cc865390f1d038119511564661 - -name: asdf -version: 0.1.0.0 -description: Please see the README on GitHub at -homepage: https://github.com/githubuser/asdf#readme -bug-reports: https://github.com/githubuser/asdf/issues -author: Author name here -maintainer: example@example.com -copyright: 2018 Author name here -license: BSD3 -build-type: Simple -extra-source-files: - README.md - ChangeLog.md - -source-repository head - type: git - location: https://github.com/githubuser/asdf - -library - exposed-modules: - Asdf - other-modules: - Paths_asdf - hs-source-dirs: - app - build-depends: - base >=4.7 && <5 - default-language: Haskell2010 diff --git a/test/testdata/addPackageTest/hybrid-lib/package.yaml b/test/testdata/addPackageTest/hybrid-lib/package.yaml deleted file mode 100644 index 2ba0fe5b4..000000000 --- a/test/testdata/addPackageTest/hybrid-lib/package.yaml +++ /dev/null @@ -1,25 +0,0 @@ -name: asdf -version: 0.1.0.0 -github: "githubuser/asdf" -license: BSD3 -author: "Author name here" -maintainer: "example@example.com" -copyright: "2018 Author name here" - -extra-source-files: -- README.md -- ChangeLog.md - -# Metadata used when publishing your package -# synopsis: Short description of your package -# category: Web - -# To avoid duplicated efforts in documentation and dealing with the -# complications of embedding Haddock markup inside cabal files, it is -# common to point users to the README.md file. -description: Please see the README on GitHub at - -library: - source-dirs: app - dependencies: - - base >= 4.7 && < 5 diff --git a/test/unit/PackagePluginSpec.hs b/test/unit/PackagePluginSpec.hs index e1a0fdbc6..76f69c36e 100644 --- a/test/unit/PackagePluginSpec.hs +++ b/test/unit/PackagePluginSpec.hs @@ -22,7 +22,7 @@ spec :: Spec spec = describe "Package plugin" packageSpec testdata :: FilePath -testdata = "test/testdata/addPackageTest" +testdata = "test" "testdata" "addPackageTest" testPlugins :: IdePlugins testPlugins = pluginDescToIdePlugins [packageDescriptor "package"] @@ -31,7 +31,7 @@ cabalProject :: [FilePath] cabalProject = ["cabal-lib", "cabal-exe"] hpackProject :: [FilePath] -hpackProject = ["hpack-lib", "hpack-exe", "hybrid-lib", "hybrid-exe"] +hpackProject = ["hpack-lib", "hpack-exe"] packageSpec :: Spec packageSpec = do @@ -239,80 +239,7 @@ packageSpec = do ] ] testCommand testPlugins act "package" "add" args res - it - "Add package to package.yaml in hpack project with generated cabal to executable component" - $ withCurrentDirectory (testdata "hybrid-exe") - $ do - let - fp = cwd testdata "hybrid-exe" - uri = filePathToUri $ fp "package.yaml" - args = AddParams fp (fp "app" "Asdf.hs") "zlib" - act = addCmd' args - res = IdeResultOk - $ WorkspaceEdit (Just $ H.singleton uri textEdits) Nothing - textEdits = List - [ TextEdit (Range (Position 0 0) (Position 37 0)) $ T.concat - [ "library:\n" - , " source-dirs: src\n" - , " dependencies:\n" - , " - base\n" - , "copyright: 2018 Author name here\n" - , "maintainer: example@example.com\n" - , "name: asdf\n" - , "version: 0.1.0.0\n" - , "extra-source-files:\n" - , "- README.md\n" - , "- ChangeLog.md\n" - , "author: Author name here\n" - , "github: githubuser/asdf\n" - , "license: BSD3\n" - , "executables:\n" - , " asdf-exe:\n" - , " source-dirs: app\n" - , " main: Main.hs\n" - , " ghc-options:\n" - , " - -threaded\n" - , " - -rtsopts\n" - , " - -with-rtsopts=-N\n" - , " dependencies:\n" - , " - zlib\n" - , " - base\n" - , " - asdf\n" - , "description: Please see the README on GitHub at \n" - ] - ] - testCommand testPlugins act "package" "add" args res - it "Add package to package.yaml in hpack project with generated cabal to library component" - $ withCurrentDirectory (testdata "hybrid-lib") - $ do - let - fp = cwd testdata "hybrid-lib" - uri = filePathToUri $ fp "package.yaml" - args = AddParams fp (fp "app" "Asdf.hs") "zlib" - act = addCmd' args - res = IdeResultOk - $ WorkspaceEdit (Just $ H.singleton uri textEdits) Nothing - textEdits = List - [ TextEdit (Range (Position 0 0) (Position 25 0)) $ T.concat - [ "library:\n" - , " source-dirs: app\n" - , " dependencies:\n" - , " - zlib\n" - , " - base >= 4.7 && < 5\n" - , "copyright: 2018 Author name here\n" - , "maintainer: example@example.com\n" - , "name: asdf\n" - , "version: 0.1.0.0\n" - , "extra-source-files:\n" - , "- README.md\n" - , "- ChangeLog.md\n" - , "author: Author name here\n" - , "github: githubuser/asdf\n" - , "license: BSD3\n" - , "description: Please see the README on GitHub at \n" - ] - ] - testCommand testPlugins act "package" "add" args res + it "Do nothing on NoPackage" $ withCurrentDirectory (testdata "invalid") $ do diff --git a/test/utils/TestUtils.hs b/test/utils/TestUtils.hs index f1137f2f2..4d86f64eb 100644 --- a/test/utils/TestUtils.hs +++ b/test/utils/TestUtils.hs @@ -107,10 +107,8 @@ files = [ "./test/testdata/" , "./test/testdata/addPackageTest/cabal-exe/" , "./test/testdata/addPackageTest/hpack-exe/" - , "./test/testdata/addPackageTest/hybrid-exe/" , "./test/testdata/addPackageTest/cabal-lib/" , "./test/testdata/addPackageTest/hpack-lib/" - , "./test/testdata/addPackageTest/hybrid-lib/" , "./test/testdata/addPragmas/" , "./test/testdata/badProjects/cabal/" , "./test/testdata/completion/" From 59d37e63a463d9351ddcf7bd722cb3f4fc36c89f Mon Sep 17 00:00:00 2001 From: Alan Zimmerman Date: Sun, 7 Jul 2019 21:27:15 +0200 Subject: [PATCH 112/158] Use hlint-2.2 --- stack-8.4.2.yaml | 2 +- stack-8.4.3.yaml | 2 +- stack-8.4.4.yaml | 2 +- stack-8.6.1.yaml | 2 +- stack-8.6.2.yaml | 2 +- stack-8.6.3.yaml | 2 +- stack-8.6.4.yaml | 2 +- stack-8.6.5.yaml | 2 +- stack.yaml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/stack-8.4.2.yaml b/stack-8.4.2.yaml index d13e63942..b54391325 100644 --- a/stack-8.4.2.yaml +++ b/stack-8.4.2.yaml @@ -23,7 +23,7 @@ extra-deps: - haskell-lsp-types-0.15.0.0 - haskell-src-exts-1.21.0 - haskell-src-exts-util-0.2.5 -- hlint-2.1.24 +- hlint-2.2 - hoogle-5.0.17.9 - hsimport-0.10.0 - lsp-test-0.6.0.0 diff --git a/stack-8.4.3.yaml b/stack-8.4.3.yaml index 7c78982de..0dc2f9f2b 100644 --- a/stack-8.4.3.yaml +++ b/stack-8.4.3.yaml @@ -23,7 +23,7 @@ extra-deps: - haskell-lsp-types-0.15.0.0 - haskell-src-exts-1.21.0 - haskell-src-exts-util-0.2.5 -- hlint-2.1.24 +- hlint-2.2 - hoogle-5.0.17.9 - hsimport-0.10.0 - lsp-test-0.6.0.0 diff --git a/stack-8.4.4.yaml b/stack-8.4.4.yaml index 09edacf36..c2c8d8d4f 100644 --- a/stack-8.4.4.yaml +++ b/stack-8.4.4.yaml @@ -22,7 +22,7 @@ extra-deps: - haskell-lsp-types-0.15.0.0 - haskell-src-exts-1.21.0 - haskell-src-exts-util-0.2.5 -- hlint-2.1.24 +- hlint-2.2 - hoogle-5.0.17.9 - hsimport-0.10.0 - lsp-test-0.6.0.0 diff --git a/stack-8.6.1.yaml b/stack-8.6.1.yaml index 510ed9c4e..1ce5f4526 100644 --- a/stack-8.6.1.yaml +++ b/stack-8.6.1.yaml @@ -25,7 +25,7 @@ extra-deps: - haskell-lsp-types-0.15.0.0 - haskell-src-exts-1.21.0 - haskell-src-exts-util-0.2.5 -- hlint-2.1.24 +- hlint-2.2 - hoogle-5.0.17.9 - hsimport-0.10.0 - lsp-test-0.6.0.0 diff --git a/stack-8.6.2.yaml b/stack-8.6.2.yaml index 2a4983b51..194566ba6 100644 --- a/stack-8.6.2.yaml +++ b/stack-8.6.2.yaml @@ -21,7 +21,7 @@ extra-deps: - haskell-lsp-types-0.15.0.0 - haskell-src-exts-1.21.0 - haskell-src-exts-util-0.2.5 -- hlint-2.1.24 +- hlint-2.2 - hoogle-5.0.17.9 - hsimport-0.10.0 - lsp-test-0.6.0.0 diff --git a/stack-8.6.3.yaml b/stack-8.6.3.yaml index 792bb8870..610f4c80d 100644 --- a/stack-8.6.3.yaml +++ b/stack-8.6.3.yaml @@ -21,7 +21,7 @@ extra-deps: - haskell-lsp-types-0.15.0.0 - haskell-src-exts-1.21.0 - haskell-src-exts-util-0.2.5 -- hlint-2.1.24 +- hlint-2.2 - hoogle-5.0.17.9 - hsimport-0.10.0 - lsp-test-0.6.0.0 diff --git a/stack-8.6.4.yaml b/stack-8.6.4.yaml index 521e175f1..b2b1f456a 100644 --- a/stack-8.6.4.yaml +++ b/stack-8.6.4.yaml @@ -20,7 +20,7 @@ extra-deps: - haskell-lsp-0.15.0.0 - haskell-lsp-types-0.15.0.0 - haskell-src-exts-1.21.0 -- hlint-2.1.24 +- hlint-2.2 - hoogle-5.0.17.9 - hsimport-0.10.0 - lsp-test-0.6.0.0 diff --git a/stack-8.6.5.yaml b/stack-8.6.5.yaml index 7afeba6f5..21feadea9 100644 --- a/stack-8.6.5.yaml +++ b/stack-8.6.5.yaml @@ -20,7 +20,7 @@ extra-deps: - haskell-lsp-0.15.0.0 - haskell-lsp-types-0.15.0.0 - haskell-src-exts-1.21.0 -- hlint-2.1.24 +- hlint-2.2 - hsimport-0.10.0 - hoogle-5.0.17.9 - lsp-test-0.6.0.0 diff --git a/stack.yaml b/stack.yaml index 7250d5a31..8f3827fef 100644 --- a/stack.yaml +++ b/stack.yaml @@ -23,7 +23,7 @@ extra-deps: - haddock-api-2.22.0 - haskell-lsp-0.15.0.0 - haskell-lsp-types-0.15.0.0 -- hlint-2.1.24 +- hlint-2.2 - hsimport-0.10.0 - lsp-test-0.6.0.0 - monad-dijkstra-0.1.1.2@rev:1 From 152647281895fc4833b74e2959e56caf8b919bef Mon Sep 17 00:00:00 2001 From: jneira Date: Mon, 8 Jul 2019 07:38:29 +0200 Subject: [PATCH 113/158] Remove unnecesary extra-dep unix-time --- stack-8.6.5.yaml | 2 -- stack.yaml | 2 -- 2 files changed, 4 deletions(-) diff --git a/stack-8.6.5.yaml b/stack-8.6.5.yaml index 7afeba6f5..14fef26ce 100644 --- a/stack-8.6.5.yaml +++ b/stack-8.6.5.yaml @@ -30,8 +30,6 @@ extra-deps: - rope-utf16-splay-0.3.1.0 - syz-0.2.0.0 - temporary-1.2.1.1 -# To make build work in windows 7 -- unix-time-0.4.7 - yaml-0.8.32 flags: diff --git a/stack.yaml b/stack.yaml index 403e8e0e2..2339b9259 100644 --- a/stack.yaml +++ b/stack.yaml @@ -26,8 +26,6 @@ extra-deps: - monad-dijkstra-0.1.1.2@rev:1 - syz-0.2.0.0 - temporary-1.2.1.1 -# To make build work in windows 7 -- unix-time-0.4.7 - yaml-0.8.32 flags: From 07593527257eadecd9ca705a9896de1261a90850 Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Thu, 11 Jul 2019 12:34:40 +0200 Subject: [PATCH 114/158] Fix typos in challenges.md Also, improve formatting --- docs/Challenges.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/Challenges.md b/docs/Challenges.md index ce5c8eb27..803fecc94 100644 --- a/docs/Challenges.md +++ b/docs/Challenges.md @@ -2,15 +2,15 @@ ### ghc-mod - 1. Linking aginst Cabal directly meant lots of breakage when interacting with the on disk configuration state. (Since solved by using wrapper) - 2. Supporting ill defined interfaces and protocols is hard to impossible. Over the course of it's almost 100 releases (!!!) compatibility was broken way too often. - 3. Supporting many GHC versions simultaniously is very hard since they keep breaking the API. - 4. Linking against GHC means simmilar problems as with linking against Cabal, i.e. when the user upgrades their GHC binary stuff will break. - -:memo: Don't link against Cabal directly ever -:memo: (maybe) Target only one GHC version at a time or provide some compatibility layer -:memo: Let's get the interfaces mostly right on the first go -:memo: Handle changing compiler versions transparently + 1. Linking against Cabal directly meant lots of breakage when interacting with the on-disk configuration state. (Since solved by using wrapper) + 2. Supporting ill-defined interfaces and protocols is hard to impossible. Over the course of its almost 100 releases (!!!) compatibility was broken way too often. + 3. Supporting many GHC versions simultaneously is very hard since they keep breaking the API. + 4. Linking against GHC means similar problems as with linking against Cabal, i.e., when the user upgrades their GHC binary stuff will break. + +* :memo: Don't link against Cabal directly ever +* :memo: (maybe) Target only one GHC version at a time or provide some compatibility layer +* :memo: Let's get the interfaces mostly right on the first go +* :memo: Handle changing compiler versions transparently ### ide-backend / stack-ide From 84624187f2d1b68f44599cbf39a82432271a0e76 Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Mon, 29 Apr 2019 22:26:46 +0200 Subject: [PATCH 115/158] add possibility to run `install.hs` from cabal additionally provide mechanism for detecting if run from stack or cabal. --- install.hs | 612 +------------------------------------- install/BuildSystem.hs | 11 + install/Install.hs | 592 ++++++++++++++++++++++++++++++++++++ install/Setup.hs | 2 + install/hie-install.cabal | 28 ++ shake.project | 2 + shake.yaml | 6 +- 7 files changed, 653 insertions(+), 600 deletions(-) create mode 100644 install/BuildSystem.hs create mode 100644 install/Install.hs create mode 100644 install/Setup.hs create mode 100644 install/hie-install.cabal create mode 100644 shake.project diff --git a/install.hs b/install.hs index c3ca1b0f1..782c4a5ed 100755 --- a/install.hs +++ b/install.hs @@ -1,606 +1,20 @@ #!/usr/bin/env stack {- stack runghc - --stack-yaml=shake.yaml - --package shake - --package directory - --package extra + --stack-yaml=install/shake.yaml + --package hie-install -} -{-# LANGUAGE LambdaCase #-} -{-# LANGUAGE TupleSections #-} -import Development.Shake -import Development.Shake.Command -import Development.Shake.FilePath -import Control.Monad -import Control.Monad -import Control.Monad.IO.Class -import Control.Monad.Extra ( unlessM - , mapMaybeM - ) -import Data.Maybe ( isJust ) -import System.Directory ( findExecutable - , findExecutables - , listDirectory - ) -import System.Environment ( getProgName - , unsetEnv - ) -import System.Info ( os - , arch - ) - -import Data.Maybe ( isNothing - , mapMaybe - ) -import Data.List ( dropWhileEnd - , intersperse - , intercalate - , isInfixOf - , nubBy - , sort - ) -import qualified Data.Text as T -import Data.Char ( isSpace ) -import Data.Version ( parseVersion - , makeVersion - , showVersion - ) -import Data.Function ( (&) - , on - ) -import Text.ParserCombinators.ReadP ( readP_to_S ) - -type VersionNumber = String -type GhcPath = String - --- | Defines all different hie versions that are buildable. --- --- The current directory is scanned for `stack-*.yaml` files. --- On windows, `8.6.3` is excluded as this version of ghc does not work there -getHieVersions :: MonadIO m => m [VersionNumber] -getHieVersions = do - let stackYamlPrefix = T.pack "stack-" - let stackYamlSuffix = T.pack ".yaml" - files <- liftIO $ listDirectory "." - let hieVersions = files - & map T.pack - & mapMaybe - (T.stripPrefix stackYamlPrefix >=> T.stripSuffix stackYamlSuffix) - & map T.unpack - -- the following line excludes `8.6.3` on windows systems - & filter (\p -> not isWindowsSystem || p /= "8.6.3") - & sort - return hieVersions - --- | Most recent version of hie. --- Shown in the more concise help message. -mostRecentHieVersion :: MonadIO m => m VersionNumber -mostRecentHieVersion = last <$> getHieVersions - -main :: IO () -main = do - -- unset GHC_PACKAGE_PATH for cabal - unsetEnv "GHC_PACKAGE_PATH" - - ghcPaths <- findInstalledGhcs - let ghcVersions = map fst ghcPaths - - hieVersions <- getHieVersions - - shakeArgs shakeOptions { shakeFiles = "_build" } $ do - want ["short-help"] - -- general purpose targets - phony "submodules" updateSubmodules - phony "cabal" installCabal - phony "short-help" shortHelpMessage - phony "all" shortHelpMessage - phony "help" helpMessage - phony "check-stack" checkStack - - phony "cabal-ghcs" $ do - let - msg = - "Found the following GHC paths: \n" - ++ unlines - (map (\(version, path) -> "ghc-" ++ version ++ ": " ++ path) - ghcPaths - ) - liftIO $ putStrLn $ embedInStars msg - - -- stack specific targets - phony "build" (need (reverse $ map ("hie-" ++) hieVersions)) - phony "build-all" (need ["build-doc", "build"]) - phony "test" $ do - need ["submodules"] - need ["check-stack"] - need ["cabal"] - forM_ hieVersions stackTest - - phony "build-copy-compiler-tool" $ forM_ hieVersions buildCopyCompilerTool - - phony "build-doc" $ do - need ["submodules"] - need ["check-stack"] - stackBuildDoc - - -- main targets for building hie with `stack` - forM_ - hieVersions - (\version -> phony ("hie-" ++ version) $ do - need ["submodules"] - need ["check-stack"] - need ["cabal"] - stackBuildHie version - stackInstallHie version - ) - - -- cabal specific targets - phony "cabal-build" (need (map ("cabal-hie-" ++) ghcVersions)) - phony "cabal-build-all" (need ["cabal-build-doc", "cabal-build"]) - phony "cabal-build-doc" $ do - need ["submodules"] - need ["cabal"] - cabalBuildDoc - - phony "cabal-test" $ do - need ["submodules"] - need ["cabal"] - forM_ ghcVersions cabalTest - - forM_ - ghcVersions - (\version -> phony ("cabal-hie-" ++ version) $ do - validateCabalNewInstallIsSupported - need ["submodules"] - need ["cabal"] - cabalBuildHie version - cabalInstallHie version - ) - - -- macos specific targets - phony "icu-macos-fix" - (need ["icu-macos-fix-install"] >> need ["icu-macos-fix-build"]) - phony "icu-macos-fix-install" (command_ [] "brew" ["install", "icu4c"]) - phony "icu-macos-fix-build" $ mapM_ buildIcuMacosFix hieVersions - - -buildIcuMacosFix :: VersionNumber -> Action () -buildIcuMacosFix version = execStackWithGhc_ - version - [ "build" - , "text-icu" - , "--extra-lib-dirs=/usr/local/opt/icu4c/lib" - , "--extra-include-dirs=/usr/local/opt/icu4c/include" - ] - --- | update the submodules that the project is in the state as required by the `stack.yaml` files -updateSubmodules :: Action () -updateSubmodules = do - command_ [] "git" ["submodule", "sync", "--recursive"] - command_ [] "git" ["submodule", "update", "--init", "--recursive"] - --- TODO: this restriction will be gone in the next release of cabal -validateCabalNewInstallIsSupported :: Action () -validateCabalNewInstallIsSupported = when isWindowsSystem $ do - liftIO $ putStrLn $ embedInStars cabalInstallNotSuportedFailMsg - error cabalInstallNotSuportedFailMsg - -configureCabal :: VersionNumber -> Action () -configureCabal versionNumber = do - ghcPath <- getGhcPathOf versionNumber >>= \case - Nothing -> do - liftIO $ putStrLn $ embedInStars (ghcVersionNotFoundFailMsg versionNumber) - error (ghcVersionNotFoundFailMsg versionNumber) - Just p -> return p - execCabal_ - ["new-configure", "-w", ghcPath, "--write-ghc-environment-files=never"] - -findInstalledGhcs :: IO [(VersionNumber, GhcPath)] -findInstalledGhcs = do - hieVersions <- getHieVersions :: IO [VersionNumber] - knownGhcs <- mapMaybeM - (\version -> getGhcPathOf version >>= \case - Nothing -> return Nothing - Just p -> return $ Just (version, p) - ) - (reverse hieVersions) - availableGhcs <- getGhcPaths - return - -- nub by version. knownGhcs takes precedence. - $ nubBy ((==) `on` fst) - -- filter out stack provided GHCs - $ filter (not . isInfixOf ".stack" . snd) (knownGhcs ++ availableGhcs) - -cabalBuildHie :: VersionNumber -> Action () -cabalBuildHie versionNumber = do - configureCabal versionNumber - execCabal_ ["new-build", "--write-ghc-environment-files=never"] - -cabalInstallHie :: VersionNumber -> Action () -cabalInstallHie versionNumber = do - localBin <- getLocalBin - execCabal_ - [ "new-install" - , "--write-ghc-environment-files=never" - , "--symlink-bindir=" ++ localBin - , "exe:hie" - , "--overwrite-policy=always" - ] - copyFile' (localBin "hie" <.> exe) - (localBin "hie-" ++ versionNumber <.> exe) - copyFile' (localBin "hie" <.> exe) - (localBin "hie-" ++ dropExtension versionNumber <.> exe) - -cabalBuildDoc :: Action () -cabalBuildDoc = do - execCabal_ ["new-build", "hoogle"] - execCabal_ ["new-exec", "hoogle", "generate"] - -cabalTest :: VersionNumber -> Action () -cabalTest versionNumber = do - configureCabal versionNumber - execCabal_ ["new-test"] - -installCabal :: Action () -installCabal = do - -- try to find existing `cabal` executable with appropriate version - cabalExe <- liftIO (findExecutable "cabal") >>= \case - Nothing -> return Nothing - Just cabalExe -> do - Stdout cabalVersion <- execCabal ["--numeric-version"] - let (parsedVersion, "") : _ = - cabalVersion & trim & readP_to_S parseVersion & filter - (("" ==) . snd) - - return $ if parsedVersion >= makeVersion [2, 4, 1, 0] - then Just cabalExe - else Nothing - -- install `cabal-install` if not already installed - when (isNothing cabalExe) $ - execStackShake_ ["install", "cabal-install"] - execCabal_ ["v1-update"] - - -checkStack :: Action () -checkStack = do - Stdout stackVersion <- execStackShake ["--numeric-version"] - let (parsedVersion, "") : _ = - stackVersion & trim & readP_to_S parseVersion & filter - (("" ==) . snd) - unless (parsedVersion >= makeVersion requiredStackVersion) $ do - liftIO $ putStrLn $ embedInStars $ stackExeIsOldFailMsg $ trim stackVersion - error $ stackExeIsOldFailMsg $ trim stackVersion - - -stackBuildHie :: VersionNumber -> Action () -stackBuildHie versionNumber = - execStackWithGhc_ versionNumber ["build"] - `actionOnException` liftIO (putStrLn stackBuildFailMsg) - --- | copy the built binaries into the localBinDir -stackInstallHie :: VersionNumber -> Action () -stackInstallHie versionNumber = do - execStackWithGhc_ versionNumber ["install"] - localBinDir <- getLocalBin - localInstallRoot <- getLocalInstallRoot versionNumber - let hie = "hie" <.> exe - copyFile' (localInstallRoot "bin" hie) - (localBinDir "hie-" ++ versionNumber <.> exe) - copyFile' (localInstallRoot "bin" hie) - (localBinDir "hie-" ++ dropExtension versionNumber <.> exe) - -buildCopyCompilerTool :: VersionNumber -> Action () -buildCopyCompilerTool versionNumber = - execStackWithGhc_ versionNumber ["build", "--copy-compiler-tool"] - -stackTest :: VersionNumber -> Action () -stackTest versionNumber = execStackWithGhc_ versionNumber ["test"] - -stackBuildDoc :: Action () -stackBuildDoc = do - execStackShake_ ["build", "hoogle"] - execStackShake_ ["exec", "hoogle", "generate"] - --- | short help message is printed by default -shortHelpMessage :: Action () -shortHelpMessage = do - hieVersions <- getHieVersions - let out = liftIO . putStrLn - scriptName <- liftIO getProgName - out "" - out "Usage:" - out' ("stack " <> scriptName <> " ") - out "" - out "Targets:" - mapM_ (out' . showTarget (spaces hieVersions)) (targets hieVersions) - out "" - where - out = liftIO . putStrLn - out' = out . (" " ++) - - spaces hieVersions = space (targets hieVersions) - targets hieVersions = - [ ("help", "Show help message including all targets") - , emptyTarget - , ( "build" - , "Builds hie for all supported GHC versions (" - ++ allVersionMessage hieVersions - ++ ")" - ) - , stackBuildAllTarget - -- , stackHieTarget mostRecentHieVersion - , stackBuildDocTarget - , stackHieTarget (last hieVersions) - , emptyTarget - , ( "cabal-ghcs" - , "Show all GHC versions that can be installed via `cabal-build` and `cabal-build-all`." - ) - , cabalBuildTarget - , cabalBuildAllTarget - -- , cabalHieTarget mostRecentHieVersion - , cabalBuildDocTarget - , cabalHieTarget (last hieVersions) - ] - - -helpMessage :: Action () -helpMessage = do - - hieVersions <- getHieVersions - scriptName <- liftIO getProgName - out "" - out "Usage:" - out' ("stack " <> scriptName <> " ") - out "" - out "Targets:" - mapM_ (out' . showTarget (spaces hieVersions)) (targets hieVersions) - out "" - where - out = liftIO . putStrLn - out' = out . (" " ++) - - spaces hieVersions = space (targets hieVersions) - -- All targets the shake file supports - targets :: [VersionNumber] -> [(String, String)] - targets hieVersions = intercalate - [emptyTarget] - [ generalTargets - , stackTargets hieVersions - , cabalTargets hieVersions - , macosTargets - ] - - -- All targets with their respective help message. - generalTargets = - [ ("help", "Show help message including all targets") - , ( "cabal" - , "Makes sure that Cabal the lib is available for cabal-helper-wapper, to speed up project start" - ) - ] - - macosTargets = [("icu-macos-fix", "Fixes icu related problems in MacOS")] - - stackTargets hieVersions = - [ ( "build" - , "Builds hie for all supported GHC versions (" - ++ allVersionMessage hieVersions - ++ ")" - ) - , stackBuildAllTarget - , stackBuildDocTarget - , ("test", "Runs hie tests with stack") - ] - ++ map stackHieTarget hieVersions - - cabalTargets hieVersions = - [ ( "cabal-ghcs" - , "Show all GHC versions that can be installed via `cabal-build` and `cabal-build-all`." - ) - , cabalBuildTarget - , cabalBuildAllTarget - , cabalBuildDocTarget - , ("cabal-test", "Runs hie tests with cabal") - ] - ++ map cabalHieTarget hieVersions - --- | Empty target. Purpose is to introduce a newline between the targets -emptyTarget :: (String, String) -emptyTarget = ("", "") - --- | Number of spaces the target name including whitespace should have. --- At least twenty, maybe more if target names are long. At most the length of the longest target plus five. -space :: [(String, String)] -> Int -space phonyTargets = maximum (20 : map ((+ 5) . length . fst) phonyTargets) - --- | Show a target. --- Concatenates the target with its help message and inserts whitespace between them. -showTarget :: Int -> (String, String) -> String -showTarget spaces (target, msg) = - target ++ replicate (spaces - length target) ' ' ++ msg - --- | Target for a specific ghc version -stackHieTarget :: String -> (String, String) -stackHieTarget version = - ( "hie-" ++ version - , "Builds hie for GHC version " ++ version ++ " only with stack" - ) - --- | Target for a specific ghc version -cabalHieTarget :: String -> (String, String) -cabalHieTarget version = - ( "cabal-hie-" ++ version - , "Builds hie for GHC version " ++ version ++ " only with cabal new-build" - ) - -stackBuildDocTarget :: (String, String) -stackBuildDocTarget = ("build-doc", "Builds the Hoogle database") - -stackBuildAllTarget :: (String, String) -stackBuildAllTarget = - ( "build-all" - , "Builds hie for all supported GHC versions and the hoogle database" - ) - -cabalBuildTarget :: (String, String) -cabalBuildTarget = - ("cabal-build", "Builds hie with cabal with all installed GHCs.") - -cabalBuildDocTarget :: (String, String) -cabalBuildDocTarget = - ("cabal-build-doc", "Builds the Hoogle database with cabal") - -cabalBuildAllTarget :: (String, String) -cabalBuildAllTarget = - ( "cabal-build-all" - , "Builds hie for all installed GHC versions and the hoogle database with cabal" - ) - --- | Creates a message of the form "a, b, c and d", where a,b,c,d are GHC versions. --- If there is no GHC in the list of `hieVersions` -allVersionMessage :: [String] -> String -allVersionMessage wordList = case wordList of - [] -> "" - [a] -> show a - (a : as) -> - let msg = intersperse ", " wordList - lastVersion = last msg - in concat $ (init $ init msg) ++ [" and ", lastVersion] - - --- RUN EXECUTABLES - --- | Execute a stack command for a specified ghc, discarding the output -execStackWithGhc_ :: VersionNumber -> [String] -> Action () -execStackWithGhc_ versionNumber args = do - let stackFile = "stack-" ++ versionNumber ++ ".yaml" - command_ [] "stack" (("--stack-yaml=" ++ stackFile) : args) - --- | Execute a stack command for a specified ghc -execStackWithGhc :: CmdResult r => VersionNumber -> [String] -> Action r -execStackWithGhc versionNumber args = do - let stackFile = "stack-" ++ versionNumber ++ ".yaml" - command [] "stack" (("--stack-yaml=" ++ stackFile) : args) - --- | Execute a stack command with the same resolver as the build script -execStackShake :: CmdResult r => [String] -> Action r -execStackShake args = - command [] "stack" ("--stack-yaml=shake.yaml" : args) - --- | Execute a stack command with the same resolver as the build script, discarding the output -execStackShake_ :: [String] -> Action () -execStackShake_ args = - command_ [] "stack" ("--stack-yaml=shake.yaml" : args) - -execCabal :: CmdResult r => [String] -> Action r -execCabal = - command [] "cabal" - -execCabal_ :: [String] -> Action () -execCabal_ = command_ [] "cabal" - -existsExecutable :: MonadIO m => String -> m Bool -existsExecutable executable = liftIO $ isJust <$> findExecutable executable - - --- QUERY ENVIRONMENT - --- |Check if the current system is windows -isWindowsSystem :: Bool -isWindowsSystem = os `elem` ["mingw32", "win32"] - --- | Get the path to the GHC compiler executable linked to the local `stack-$GHCVER.yaml`. --- Equal to the command `stack path --stack-yaml $stack-yaml --compiler-exe`. --- This might install a GHC if it is not already installed, thus, might fail if stack fails to install the GHC. -getStackGhcPath :: VersionNumber -> Action GhcPath -getStackGhcPath ghcVersion = do - Stdout ghc <- execStackWithGhc ghcVersion ["path", "--compiler-exe"] - return $ trim ghc - -getStackGhcPathShake :: Action GhcPath -getStackGhcPathShake = do - Stdout ghc <- execStackShake ["path", "--compiler-exe"] - return $ trim ghc - --- | Get the path to a GHC that has the version specified by `VersionNumber` --- If no such GHC can be found, Nothing is returned. --- First, it is checked whether there is a GHC with the name `ghc-$VersionNumber`. --- If this yields no result, it is checked, whether the numeric-version of the `ghc` --- command fits to the desired version. -getGhcPathOf :: MonadIO m => VersionNumber -> m (Maybe GhcPath) -getGhcPathOf ghcVersion = - liftIO $ findExecutable ("ghc-" ++ ghcVersion) >>= \case - Nothing -> lookup ghcVersion <$> getGhcPaths - path -> return path - --- | Get a list of GHCs that are available in $PATH -getGhcPaths :: MonadIO m => m [(VersionNumber, GhcPath)] -getGhcPaths = liftIO $ do - paths <- findExecutables "ghc" - forM paths $ \path -> do - Stdout version <- cmd path ["--numeric-version"] - return (trim version, path) - --- | Read the local install root of the stack project specified by the VersionNumber --- Returns the filepath of the local install root. --- Equal to the command `stack path --local-install-root` -getLocalInstallRoot :: VersionNumber -> Action FilePath -getLocalInstallRoot hieVersion = do - Stdout localInstallRoot' <- execStackWithGhc - hieVersion - ["path", "--local-install-root"] - return $ trim localInstallRoot' - --- | Get the local binary path of stack. --- Equal to the command `stack path --local-bin` -getLocalBin :: Action FilePath -getLocalBin = do - Stdout stackLocalDir' <- execStackShake - ["path", "--local-bin"] - return $ trim stackLocalDir' - --- | Trim the end of a string -trim :: String -> String -trim = dropWhileEnd isSpace - --- | Embed a string within two lines of stars to improve perceivability and, thus, readability. -embedInStars :: String -> String -embedInStars str = - let starsLine - = "\n******************************************************************\n" - in starsLine <> str <> starsLine - --- |Stack build fails message -stackBuildFailMsg :: String -stackBuildFailMsg = - embedInStars - $ "Building failed, " - ++ "Try running `stack clean` and restart the build\n" - ++ "If this does not work, open an issue at \n" - ++ "\thttps://github.com/haskell/haskell-ide-engine" - --- | No suitable ghc version has been found. Show a message. -ghcVersionNotFoundFailMsg :: VersionNumber -> String -ghcVersionNotFoundFailMsg versionNumber = - "No GHC with version " - <> versionNumber - <> " has been found.\n" - <> "Either install a fitting GHC, use the stack targets or modify the PATH variable accordingly." +{- cabal: +build-depends: + base + , hie-install +-} +-- call as: +-- * `cabal v2-run install.hs --project-file install/shake.project ` +-- * `stack install.hs ` --- | Error message when a windows system tries to install HIE via `cabal new-install` -cabalInstallNotSuportedFailMsg :: String -cabalInstallNotSuportedFailMsg = - "This system has been identified as a windows system.\n" - ++ "Unfortunately, `cabal new-install` is currently not supported on windows.\n" - ++ "Please use one of the stack-based targets.\n\n" - ++ "If this system has been falsely identified, please open an issue at:\n\thttps://github.com/haskell/haskell-ide-engine\n" +-- TODO: set `shake.project` in cabal-config above, when supported --- | Error message when the `stack` binary is an older version -stackExeIsOldFailMsg :: String -> String -stackExeIsOldFailMsg stackVersion = - "The `stack` executable is outdated.\n" - ++ "found version is `" ++ stackVersion ++ "`.\n" - ++ "required version is `" ++ showVersion (makeVersion requiredStackVersion) ++ "`.\n" - ++ "Please run `stack upgrade` to upgrade your stack installation" +import Install (defaultMain) -requiredStackVersion :: [Int] -requiredStackVersion = [1, 9, 3] +main = defaultMain diff --git a/install/BuildSystem.hs b/install/BuildSystem.hs new file mode 100644 index 000000000..75d76ad79 --- /dev/null +++ b/install/BuildSystem.hs @@ -0,0 +1,11 @@ +{-# LANGUAGE CPP #-} + +module BuildSystem where + +buildSystem :: String +buildSystem = +#if RUN_FROM_STACK + "stack" +#else + "cabal" +#endif diff --git a/install/Install.hs b/install/Install.hs new file mode 100644 index 000000000..8203e9cf8 --- /dev/null +++ b/install/Install.hs @@ -0,0 +1,592 @@ +module Install where + +{-# LANGUAGE TupleSections #-} +import Development.Shake +import Development.Shake.Command +import Development.Shake.FilePath +import Control.Monad +import Control.Monad +import Control.Monad.IO.Class +import Control.Monad.Extra ( unlessM + , mapMaybeM + ) +import Data.Maybe ( isJust ) +import System.Directory ( findExecutable + , listDirectory + ) +import System.Environment ( getProgName + , unsetEnv + ) +import System.Info ( os + , arch + ) + +import Data.Maybe ( isNothing + , mapMaybe + ) +import Data.List ( dropWhileEnd + , intersperse + , intercalate + , sort + , sortOn + ) +import qualified Data.Text as T +import Data.Char ( isSpace ) +import Data.Version ( parseVersion + , makeVersion + , showVersion + ) +import Data.Function ( (&) ) +import Text.ParserCombinators.ReadP ( readP_to_S ) + +import BuildSystem + +type VersionNumber = String +type GhcPath = String + +-- | Defines all different hie versions that are buildable. +-- +-- The current directory is scanned for `stack-*.yaml` files. +-- On windows, `8.6.3` is excluded as this version of ghc does not work there +getHieVersions :: MonadIO m => m [VersionNumber] +getHieVersions = do + let stackYamlPrefix = T.pack "stack-" + let stackYamlSuffix = T.pack ".yaml" + files <- liftIO $ listDirectory "." + let hieVersions = files + & map T.pack + & mapMaybe + (T.stripPrefix stackYamlPrefix >=> T.stripSuffix stackYamlSuffix) + & map T.unpack + -- the following line excludes `8.6.3` on windows systems + & filter (\p -> not isWindowsSystem || p /= "8.6.3") + & sort + return hieVersions + +-- | Most recent version of hie. +-- Shown in the more concise help message. +mostRecentHieVersion :: MonadIO m => m VersionNumber +mostRecentHieVersion = last <$> getHieVersions + +defaultMain :: IO () +defaultMain = do + putStrLn $ "run from build-system: " ++ buildSystem + + exitWith ExitSuccess + + -- unset GHC_PACKAGE_PATH for cabal + unsetEnv "GHC_PACKAGE_PATH" + + ghcPaths <- findInstalledGhcs + let ghcVersions = map fst ghcPaths + + hieVersions <- getHieVersions + + shakeArgs shakeOptions { shakeFiles = "_build" } $ do + want ["short-help"] + -- general purpose targets + phony "submodules" updateSubmodules + phony "cabal" installCabal + phony "short-help" shortHelpMessage + phony "all" shortHelpMessage + phony "help" helpMessage + phony "check-stack" checkStack + + phony "cabal-ghcs" $ do + let + msg = + "Found the following GHC paths: \n" + ++ unlines + (map (\(version, path) -> "ghc-" ++ version ++ ": " ++ path) + ghcPaths + ) + liftIO $ putStrLn $ embedInStars msg + + -- stack specific targets + phony "build" (need (reverse $ map ("hie-" ++) hieVersions)) + phony "build-all" (need ["build-doc", "build"]) + phony "test" $ do + need ["submodules"] + need ["check-stack"] + need ["cabal"] + forM_ hieVersions stackTest + + phony "build-copy-compiler-tool" $ forM_ hieVersions buildCopyCompilerTool + + phony "build-doc" $ do + need ["submodules"] + need ["check-stack"] + stackBuildDoc + + -- main targets for building hie with `stack` + forM_ + hieVersions + (\version -> phony ("hie-" ++ version) $ do + need ["submodules"] + need ["check-stack"] + need ["cabal"] + stackBuildHie version + stackInstallHie version + ) + + -- cabal specific targets + phony "cabal-build" (need (map ("cabal-hie-" ++) ghcVersions)) + phony "cabal-build-all" (need ["cabal-build-doc", "cabal-build"]) + phony "cabal-build-doc" $ do + need ["submodules"] + need ["cabal"] + cabalBuildDoc + + phony "cabal-test" $ do + need ["submodules"] + need ["cabal"] + forM_ ghcVersions cabalTest + + forM_ + hieVersions + (\version -> phony ("cabal-hie-" ++ version) $ do + validateCabalNewInstallIsSupported + need ["submodules"] + need ["cabal"] + cabalBuildHie version + cabalInstallHie version + ) + + -- macos specific targets + phony "icu-macos-fix" + (need ["icu-macos-fix-install"] >> need ["icu-macos-fix-build"]) + phony "icu-macos-fix-install" (command_ [] "brew" ["install", "icu4c"]) + phony "icu-macos-fix-build" $ mapM_ buildIcuMacosFix hieVersions + + +buildIcuMacosFix :: VersionNumber -> Action () +buildIcuMacosFix version = execStackWithGhc_ + version + [ "build" + , "text-icu" + , "--extra-lib-dirs=/usr/local/opt/icu4c/lib" + , "--extra-include-dirs=/usr/local/opt/icu4c/include" + ] + +-- | update the submodules that the project is in the state as required by the `stack.yaml` files +updateSubmodules :: Action () +updateSubmodules = do + command_ [] "git" ["submodule", "sync", "--recursive"] + command_ [] "git" ["submodule", "update", "--init", "--recursive"] + +-- TODO: this restriction will be gone in the next release of cabal +validateCabalNewInstallIsSupported :: Action () +validateCabalNewInstallIsSupported = when isWindowsSystem $ do + liftIO $ putStrLn $ embedInStars cabalInstallNotSuportedFailMsg + error cabalInstallNotSuportedFailMsg + +configureCabal :: VersionNumber -> Action () +configureCabal versionNumber = do + ghcPath <- getGhcPath versionNumber >>= \case + Nothing -> do + liftIO $ putStrLn $ embedInStars (ghcVersionNotFoundFailMsg versionNumber) + error (ghcVersionNotFoundFailMsg versionNumber) + Just p -> return p + execCabal_ + ["new-configure", "-w", ghcPath, "--write-ghc-environment-files=never"] + +findInstalledGhcs :: IO [(VersionNumber, GhcPath)] +findInstalledGhcs = do + hieVersions <- getHieVersions :: IO [VersionNumber] + mapMaybeM + (\version -> getGhcPath version >>= \case + Nothing -> return Nothing + Just p -> return $ Just (version, p) + ) + (reverse hieVersions) + +cabalBuildHie :: VersionNumber -> Action () +cabalBuildHie versionNumber = do + configureCabal versionNumber + execCabal_ ["new-build", "--write-ghc-environment-files=never"] + +cabalInstallHie :: VersionNumber -> Action () +cabalInstallHie versionNumber = do + localBin <- getLocalBin + execCabal_ + [ "new-install" + , "--write-ghc-environment-files=never" + , "--symlink-bindir=" ++ localBin + , "exe:hie" + , "--overwrite-policy=always" + ] + copyFile' (localBin "hie" <.> exe) + (localBin "hie-" ++ versionNumber <.> exe) + copyFile' (localBin "hie" <.> exe) + (localBin "hie-" ++ dropExtension versionNumber <.> exe) + +cabalBuildDoc :: Action () +cabalBuildDoc = do + execCabal_ ["new-build", "hoogle", "generate"] + execCabal_ ["new-exec", "hoogle", "generate"] + +cabalTest :: VersionNumber -> Action () +cabalTest versionNumber = do + configureCabal versionNumber + execCabal_ ["new-test"] + +installCabal :: Action () +installCabal = do + -- try to find existing `cabal` executable with appropriate version + cabalExe <- liftIO (findExecutable "cabal") >>= \case + Nothing -> return Nothing + Just cabalExe -> do + Stdout cabalVersion <- execCabal ["--numeric-version"] + let (parsedVersion, "") : _ = + cabalVersion & trim & readP_to_S parseVersion & filter + (("" ==) . snd) + + return $ if parsedVersion >= makeVersion [2, 4, 1, 0] + then Just cabalExe + else Nothing + -- install `cabal-install` if not already installed + when (isNothing cabalExe) $ + execStackShake_ ["install", "cabal-install"] + execCabal_ ["update"] + + +checkStack :: Action () +checkStack = do + Stdout stackVersion <- execStackShake ["--numeric-version"] + let (parsedVersion, "") : _ = + stackVersion & trim & readP_to_S parseVersion & filter + (("" ==) . snd) + unless (parsedVersion >= makeVersion requiredStackVersion) $ do + liftIO $ putStrLn $ embedInStars $ stackExeIsOldFailMsg $ trim stackVersion + error $ stackExeIsOldFailMsg $ trim stackVersion + + +stackBuildHie :: VersionNumber -> Action () +stackBuildHie versionNumber = + execStackWithGhc_ versionNumber ["build"] + `actionOnException` liftIO (putStrLn stackBuildFailMsg) + +-- | copy the built binaries into the localBinDir +stackInstallHie :: VersionNumber -> Action () +stackInstallHie versionNumber = do + execStackWithGhc_ versionNumber ["install"] + localBinDir <- getLocalBin + localInstallRoot <- getLocalInstallRoot versionNumber + let hie = "hie" <.> exe + copyFile' (localInstallRoot "bin" hie) + (localBinDir "hie-" ++ versionNumber <.> exe) + copyFile' (localInstallRoot "bin" hie) + (localBinDir "hie-" ++ dropExtension versionNumber <.> exe) + +buildCopyCompilerTool :: VersionNumber -> Action () +buildCopyCompilerTool versionNumber = + execStackWithGhc_ versionNumber ["build", "--copy-compiler-tool"] + +stackTest :: VersionNumber -> Action () +stackTest versionNumber = execStackWithGhc_ versionNumber ["test"] + +stackBuildDoc :: Action () +stackBuildDoc = do + execStackShake_ ["build", "hoogle"] + execStackShake_ ["exec", "hoogle", "generate"] + +-- | short help message is printed by default +shortHelpMessage :: Action () +shortHelpMessage = do + hieVersions <- getHieVersions + let out = liftIO . putStrLn + scriptName <- liftIO getProgName + out "" + out "Usage:" + out' ("stack " <> scriptName <> " ") + out "" + out "Targets:" + mapM_ (out' . showTarget (spaces hieVersions)) (targets hieVersions) + out "" + where + out = liftIO . putStrLn + out' = out . (" " ++) + + spaces hieVersions = space (targets hieVersions) + targets hieVersions = + [ ("help", "Show help message including all targets") + , emptyTarget + , ( "build" + , "Builds hie for all supported GHC versions (" + ++ allVersionMessage hieVersions + ++ ")" + ) + , stackBuildAllTarget + -- , stackHieTarget mostRecentHieVersion + , stackBuildDocTarget + , stackHieTarget (last hieVersions) + , emptyTarget + , ( "cabal-ghcs" + , "Show all GHC versions that can be installed via `cabal-build` and `cabal-build-all`." + ) + , cabalBuildTarget + , cabalBuildAllTarget + -- , cabalHieTarget mostRecentHieVersion + , cabalBuildDocTarget + , cabalHieTarget (last hieVersions) + ] + + +helpMessage :: Action () +helpMessage = do + + hieVersions <- getHieVersions + scriptName <- liftIO getProgName + out "" + out "Usage:" + out' ("stack " <> scriptName <> " ") + out "" + out "Targets:" + mapM_ (out' . showTarget (spaces hieVersions)) (targets hieVersions) + out "" + where + out = liftIO . putStrLn + out' = out . (" " ++) + + spaces hieVersions = space (targets hieVersions) + -- All targets the shake file supports + targets :: [VersionNumber] -> [(String, String)] + targets hieVersions = intercalate + [emptyTarget] + [ generalTargets + , stackTargets hieVersions + , cabalTargets hieVersions + , macosTargets + ] + + -- All targets with their respective help message. + generalTargets = + [ ("help", "Show help message including all targets") + , ( "cabal" + , "Makes sure that Cabal the lib is available for cabal-helper-wapper, to speed up project start" + ) + ] + + macosTargets = [("icu-macos-fix", "Fixes icu related problems in MacOS")] + + stackTargets hieVersions = + [ ( "build" + , "Builds hie for all supported GHC versions (" + ++ allVersionMessage hieVersions + ++ ")" + ) + , stackBuildAllTarget + , stackBuildDocTarget + , ("test", "Runs hie tests with stack") + ] + ++ map stackHieTarget hieVersions + + cabalTargets hieVersions = + [ ( "cabal-ghcs" + , "Show all GHC versions that can be installed via `cabal-build` and `cabal-build-all`." + ) + , cabalBuildTarget + , cabalBuildAllTarget + , cabalBuildDocTarget + , ("cabal-test", "Runs hie tests with cabal") + ] + ++ map cabalHieTarget hieVersions + +-- | Empty target. Purpose is to introduce a newline between the targets +emptyTarget :: (String, String) +emptyTarget = ("", "") + +-- | Number of spaces the target name including whitespace should have. +-- At least twenty, maybe more if target names are long. At most the length of the longest target plus five. +space :: [(String, String)] -> Int +space phonyTargets = maximum (20 : map ((+ 5) . length . fst) phonyTargets) + +-- | Show a target. +-- Concatenates the target with its help message and inserts whitespace between them. +showTarget :: Int -> (String, String) -> String +showTarget spaces (target, msg) = + target ++ replicate (spaces - length target) ' ' ++ msg + +-- | Target for a specific ghc version +stackHieTarget :: String -> (String, String) +stackHieTarget version = + ( "hie-" ++ version + , "Builds hie for GHC version " ++ version ++ " only with stack" + ) + +-- | Target for a specific ghc version +cabalHieTarget :: String -> (String, String) +cabalHieTarget version = + ( "cabal-hie-" ++ version + , "Builds hie for GHC version " ++ version ++ " only with cabal new-build" + ) + +stackBuildDocTarget :: (String, String) +stackBuildDocTarget = ("build-doc", "Builds the Hoogle database") + +stackBuildAllTarget :: (String, String) +stackBuildAllTarget = + ( "build-all" + , "Builds hie for all supported GHC versions and the hoogle database" + ) + +cabalBuildTarget :: (String, String) +cabalBuildTarget = + ("cabal-build", "Builds hie with cabal with all installed GHCs.") + +cabalBuildDocTarget :: (String, String) +cabalBuildDocTarget = + ("cabal-build-doc", "Builds the Hoogle database with cabal") + +cabalBuildAllTarget :: (String, String) +cabalBuildAllTarget = + ( "cabal-build-all" + , "Builds hie for all installed GHC versions and the hoogle database with cabal" + ) + +-- | Creates a message of the form "a, b, c and d", where a,b,c,d are GHC versions. +-- If there is no GHC in the list of `hieVersions` +allVersionMessage :: [String] -> String +allVersionMessage wordList = case wordList of + [] -> "" + [a] -> show a + (a : as) -> + let msg = intersperse ", " wordList + lastVersion = last msg + in concat $ (init $ init msg) ++ [" and ", lastVersion] + + +-- RUN EXECUTABLES + +-- | Execute a stack command for a specified ghc, discarding the output +execStackWithGhc_ :: VersionNumber -> [String] -> Action () +execStackWithGhc_ versionNumber args = do + let stackFile = "stack-" ++ versionNumber ++ ".yaml" + command_ [] "stack" (("--stack-yaml=" ++ stackFile) : args) + +-- | Execute a stack command for a specified ghc +execStackWithGhc :: CmdResult r => VersionNumber -> [String] -> Action r +execStackWithGhc versionNumber args = do + let stackFile = "stack-" ++ versionNumber ++ ".yaml" + command [] "stack" (("--stack-yaml=" ++ stackFile) : args) + +-- | Execute a stack command with the same resolver as the build script +execStackShake :: CmdResult r => [String] -> Action r +execStackShake args = + command [] "stack" ("--stack-yaml=shake.yaml" : args) + +-- | Execute a stack command with the same resolver as the build script, discarding the output +execStackShake_ :: [String] -> Action () +execStackShake_ args = + command_ [] "stack" ("--stack-yaml=shake.yaml" : args) + +execCabal :: CmdResult r => [String] -> Action r +execCabal = + command [] "cabal" + +execCabal_ :: [String] -> Action () +execCabal_ = command_ [] "cabal" + +existsExecutable :: MonadIO m => String -> m Bool +existsExecutable executable = liftIO $ isJust <$> findExecutable executable + + +-- QUERY ENVIRONMENT + +-- |Check if the current system is windows +isWindowsSystem :: Bool +isWindowsSystem = os `elem` ["mingw32", "win32"] + +-- | Get the path to the GHC compiler executable linked to the local `stack-$GHCVER.yaml`. +-- Equal to the command `stack path --stack-yaml $stack-yaml --compiler-exe`. +-- This might install a GHC if it is not already installed, thus, might fail if stack fails to install the GHC. +getStackGhcPath :: VersionNumber -> Action GhcPath +getStackGhcPath ghcVersion = do + Stdout ghc <- execStackWithGhc ghcVersion ["path", "--compiler-exe"] + return $ trim ghc + +getStackGhcPathShake :: Action GhcPath +getStackGhcPathShake = do + Stdout ghc <- execStackShake ["path", "--compiler-exe"] + return $ trim ghc + +-- | Get the path to a GHC that has the version specified by `VersionNumber` +-- If no such GHC can be found, Nothing is returned. +-- First, it is checked whether there is a GHC with the name `ghc-$VersionNumber`. +-- If this yields no result, it is checked, whether the numeric-version of the `ghc` +-- command fits to the desired version. +getGhcPath :: MonadIO m => VersionNumber -> m (Maybe GhcPath) +getGhcPath ghcVersion = liftIO $ + findExecutable ("ghc-" ++ ghcVersion) >>= \case + Nothing -> do + findExecutable "ghc" >>= \case + Nothing -> return Nothing + Just p -> do + Stdout version <- cmd p ["--numeric-version"] :: IO (Stdout String) + if ghcVersion == trim version then return $ Just p else return Nothing + p -> return p + +-- | Read the local install root of the stack project specified by the VersionNumber +-- Returns the filepath of the local install root. +-- Equal to the command `stack path --local-install-root` +getLocalInstallRoot :: VersionNumber -> Action FilePath +getLocalInstallRoot hieVersion = do + Stdout localInstallRoot' <- execStackWithGhc + hieVersion + ["path", "--local-install-root"] + return $ trim localInstallRoot' + +-- | Get the local binary path of stack. +-- Equal to the command `stack path --local-bin` +getLocalBin :: Action FilePath +getLocalBin = do + Stdout stackLocalDir' <- execStackShake + ["path", "--local-bin"] + return $ trim stackLocalDir' + +-- | Trim the end of a string +trim :: String -> String +trim = dropWhileEnd isSpace + +-- | Embed a string within two lines of stars to improve perceivability and, thus, readability. +embedInStars :: String -> String +embedInStars str = + let starsLine + = "\n******************************************************************\n" + in starsLine <> str <> starsLine + +-- |Stack build fails message +stackBuildFailMsg :: String +stackBuildFailMsg = + embedInStars + $ "Building failed, " + ++ "Try running `stack clean` and restart the build\n" + ++ "If this does not work, open an issue at \n" + ++ "\thttps://github.com/haskell/haskell-ide-engine" + +-- | No suitable ghc version has been found. Show a message. +ghcVersionNotFoundFailMsg :: VersionNumber -> String +ghcVersionNotFoundFailMsg versionNumber = + "No GHC with version " + <> versionNumber + <> " has been found.\n" + <> "Either install a fitting GHC, use the stack targets or modify the PATH variable accordingly." + +-- | Error message when a windows system tries to install HIE via `cabal new-install` +cabalInstallNotSuportedFailMsg :: String +cabalInstallNotSuportedFailMsg = + "This system has been identified as a windows system.\n" + ++ "Unfortunately, `cabal new-install` is currently not supported on windows.\n" + ++ "Please use one of the stack-based targets.\n\n" + ++ "If this system has been falsely identified, please open an issue at:\n\thttps://github.com/haskell/haskell-ide-engine\n" + +-- | Error message when the `stack` binary is an older version +stackExeIsOldFailMsg :: String -> String +stackExeIsOldFailMsg stackVersion = + "The `stack` executable is outdated.\n" + ++ "found version is `" ++ stackVersion ++ "`.\n" + ++ "required version is `" ++ showVersion (makeVersion requiredStackVersion) ++ "`.\n" + ++ "Please run `stack upgrade` to upgrade your stack installation" + +requiredStackVersion :: [Int] +requiredStackVersion = [1, 9, 3] diff --git a/install/Setup.hs b/install/Setup.hs new file mode 100644 index 000000000..9a994af67 --- /dev/null +++ b/install/Setup.hs @@ -0,0 +1,2 @@ +import Distribution.Simple +main = defaultMain diff --git a/install/hie-install.cabal b/install/hie-install.cabal new file mode 100644 index 000000000..f4b28a7ea --- /dev/null +++ b/install/hie-install.cabal @@ -0,0 +1,28 @@ +name: hie-install +version: 0.8.0.0 +synopsis: Install the haskell-ide-engine +license: BSD3 +author: Many, TBD when we release +maintainer: samuel.pilz@posteo.net +copyright: 2019 +build-type: Simple +cabal-version: >=2.0 + +library + hs-source-dirs: . + exposed-modules: Install + other-modules: BuildSystem + build-depends: base >= 4.9 && < 5 + , shake == 0.17.3 + , directory + , extra + , text + default-extensions: LambdaCase + + if flag(run-from-stack) + cpp-options: -DRUN_FROM_STACK + +flag run-from-stack + description: Inform the application that it is run from stack + default: False + manual: True diff --git a/shake.project b/shake.project new file mode 100644 index 000000000..94f06ec7e --- /dev/null +++ b/shake.project @@ -0,0 +1,2 @@ +packages: + install diff --git a/shake.yaml b/shake.yaml index e89f45704..b77f32905 100644 --- a/shake.yaml +++ b/shake.yaml @@ -1,7 +1,11 @@ # Used to provide a different environment for the shake build script resolver: lts-13.18 # GHC 8.6.4 packages: -- . +- install nix: packages: [ zlib ] + +flags: + hie-install: + run-from-stack: true From 1cc4501a2dea6bf197d64ad6b1a5cfff709d898c Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Sat, 4 May 2019 23:27:28 +0200 Subject: [PATCH 116/158] refactor installer-code --- install/Install.hs | 592 ------------------------------- install/hie-install.cabal | 9 +- install/{ => src}/BuildSystem.hs | 6 + install/src/Cabal.hs | 122 +++++++ install/src/Env.hs | 91 +++++ install/src/Install.hs | 355 ++++++++++++++++++ install/src/Print.hs | 39 ++ install/src/Stack.hs | 60 ++++ install/src/Version.hs | 24 ++ 9 files changed, 705 insertions(+), 593 deletions(-) delete mode 100644 install/Install.hs rename install/{ => src}/BuildSystem.hs (51%) create mode 100644 install/src/Cabal.hs create mode 100644 install/src/Env.hs create mode 100644 install/src/Install.hs create mode 100644 install/src/Print.hs create mode 100644 install/src/Stack.hs create mode 100644 install/src/Version.hs diff --git a/install/Install.hs b/install/Install.hs deleted file mode 100644 index 8203e9cf8..000000000 --- a/install/Install.hs +++ /dev/null @@ -1,592 +0,0 @@ -module Install where - -{-# LANGUAGE TupleSections #-} -import Development.Shake -import Development.Shake.Command -import Development.Shake.FilePath -import Control.Monad -import Control.Monad -import Control.Monad.IO.Class -import Control.Monad.Extra ( unlessM - , mapMaybeM - ) -import Data.Maybe ( isJust ) -import System.Directory ( findExecutable - , listDirectory - ) -import System.Environment ( getProgName - , unsetEnv - ) -import System.Info ( os - , arch - ) - -import Data.Maybe ( isNothing - , mapMaybe - ) -import Data.List ( dropWhileEnd - , intersperse - , intercalate - , sort - , sortOn - ) -import qualified Data.Text as T -import Data.Char ( isSpace ) -import Data.Version ( parseVersion - , makeVersion - , showVersion - ) -import Data.Function ( (&) ) -import Text.ParserCombinators.ReadP ( readP_to_S ) - -import BuildSystem - -type VersionNumber = String -type GhcPath = String - --- | Defines all different hie versions that are buildable. --- --- The current directory is scanned for `stack-*.yaml` files. --- On windows, `8.6.3` is excluded as this version of ghc does not work there -getHieVersions :: MonadIO m => m [VersionNumber] -getHieVersions = do - let stackYamlPrefix = T.pack "stack-" - let stackYamlSuffix = T.pack ".yaml" - files <- liftIO $ listDirectory "." - let hieVersions = files - & map T.pack - & mapMaybe - (T.stripPrefix stackYamlPrefix >=> T.stripSuffix stackYamlSuffix) - & map T.unpack - -- the following line excludes `8.6.3` on windows systems - & filter (\p -> not isWindowsSystem || p /= "8.6.3") - & sort - return hieVersions - --- | Most recent version of hie. --- Shown in the more concise help message. -mostRecentHieVersion :: MonadIO m => m VersionNumber -mostRecentHieVersion = last <$> getHieVersions - -defaultMain :: IO () -defaultMain = do - putStrLn $ "run from build-system: " ++ buildSystem - - exitWith ExitSuccess - - -- unset GHC_PACKAGE_PATH for cabal - unsetEnv "GHC_PACKAGE_PATH" - - ghcPaths <- findInstalledGhcs - let ghcVersions = map fst ghcPaths - - hieVersions <- getHieVersions - - shakeArgs shakeOptions { shakeFiles = "_build" } $ do - want ["short-help"] - -- general purpose targets - phony "submodules" updateSubmodules - phony "cabal" installCabal - phony "short-help" shortHelpMessage - phony "all" shortHelpMessage - phony "help" helpMessage - phony "check-stack" checkStack - - phony "cabal-ghcs" $ do - let - msg = - "Found the following GHC paths: \n" - ++ unlines - (map (\(version, path) -> "ghc-" ++ version ++ ": " ++ path) - ghcPaths - ) - liftIO $ putStrLn $ embedInStars msg - - -- stack specific targets - phony "build" (need (reverse $ map ("hie-" ++) hieVersions)) - phony "build-all" (need ["build-doc", "build"]) - phony "test" $ do - need ["submodules"] - need ["check-stack"] - need ["cabal"] - forM_ hieVersions stackTest - - phony "build-copy-compiler-tool" $ forM_ hieVersions buildCopyCompilerTool - - phony "build-doc" $ do - need ["submodules"] - need ["check-stack"] - stackBuildDoc - - -- main targets for building hie with `stack` - forM_ - hieVersions - (\version -> phony ("hie-" ++ version) $ do - need ["submodules"] - need ["check-stack"] - need ["cabal"] - stackBuildHie version - stackInstallHie version - ) - - -- cabal specific targets - phony "cabal-build" (need (map ("cabal-hie-" ++) ghcVersions)) - phony "cabal-build-all" (need ["cabal-build-doc", "cabal-build"]) - phony "cabal-build-doc" $ do - need ["submodules"] - need ["cabal"] - cabalBuildDoc - - phony "cabal-test" $ do - need ["submodules"] - need ["cabal"] - forM_ ghcVersions cabalTest - - forM_ - hieVersions - (\version -> phony ("cabal-hie-" ++ version) $ do - validateCabalNewInstallIsSupported - need ["submodules"] - need ["cabal"] - cabalBuildHie version - cabalInstallHie version - ) - - -- macos specific targets - phony "icu-macos-fix" - (need ["icu-macos-fix-install"] >> need ["icu-macos-fix-build"]) - phony "icu-macos-fix-install" (command_ [] "brew" ["install", "icu4c"]) - phony "icu-macos-fix-build" $ mapM_ buildIcuMacosFix hieVersions - - -buildIcuMacosFix :: VersionNumber -> Action () -buildIcuMacosFix version = execStackWithGhc_ - version - [ "build" - , "text-icu" - , "--extra-lib-dirs=/usr/local/opt/icu4c/lib" - , "--extra-include-dirs=/usr/local/opt/icu4c/include" - ] - --- | update the submodules that the project is in the state as required by the `stack.yaml` files -updateSubmodules :: Action () -updateSubmodules = do - command_ [] "git" ["submodule", "sync", "--recursive"] - command_ [] "git" ["submodule", "update", "--init", "--recursive"] - --- TODO: this restriction will be gone in the next release of cabal -validateCabalNewInstallIsSupported :: Action () -validateCabalNewInstallIsSupported = when isWindowsSystem $ do - liftIO $ putStrLn $ embedInStars cabalInstallNotSuportedFailMsg - error cabalInstallNotSuportedFailMsg - -configureCabal :: VersionNumber -> Action () -configureCabal versionNumber = do - ghcPath <- getGhcPath versionNumber >>= \case - Nothing -> do - liftIO $ putStrLn $ embedInStars (ghcVersionNotFoundFailMsg versionNumber) - error (ghcVersionNotFoundFailMsg versionNumber) - Just p -> return p - execCabal_ - ["new-configure", "-w", ghcPath, "--write-ghc-environment-files=never"] - -findInstalledGhcs :: IO [(VersionNumber, GhcPath)] -findInstalledGhcs = do - hieVersions <- getHieVersions :: IO [VersionNumber] - mapMaybeM - (\version -> getGhcPath version >>= \case - Nothing -> return Nothing - Just p -> return $ Just (version, p) - ) - (reverse hieVersions) - -cabalBuildHie :: VersionNumber -> Action () -cabalBuildHie versionNumber = do - configureCabal versionNumber - execCabal_ ["new-build", "--write-ghc-environment-files=never"] - -cabalInstallHie :: VersionNumber -> Action () -cabalInstallHie versionNumber = do - localBin <- getLocalBin - execCabal_ - [ "new-install" - , "--write-ghc-environment-files=never" - , "--symlink-bindir=" ++ localBin - , "exe:hie" - , "--overwrite-policy=always" - ] - copyFile' (localBin "hie" <.> exe) - (localBin "hie-" ++ versionNumber <.> exe) - copyFile' (localBin "hie" <.> exe) - (localBin "hie-" ++ dropExtension versionNumber <.> exe) - -cabalBuildDoc :: Action () -cabalBuildDoc = do - execCabal_ ["new-build", "hoogle", "generate"] - execCabal_ ["new-exec", "hoogle", "generate"] - -cabalTest :: VersionNumber -> Action () -cabalTest versionNumber = do - configureCabal versionNumber - execCabal_ ["new-test"] - -installCabal :: Action () -installCabal = do - -- try to find existing `cabal` executable with appropriate version - cabalExe <- liftIO (findExecutable "cabal") >>= \case - Nothing -> return Nothing - Just cabalExe -> do - Stdout cabalVersion <- execCabal ["--numeric-version"] - let (parsedVersion, "") : _ = - cabalVersion & trim & readP_to_S parseVersion & filter - (("" ==) . snd) - - return $ if parsedVersion >= makeVersion [2, 4, 1, 0] - then Just cabalExe - else Nothing - -- install `cabal-install` if not already installed - when (isNothing cabalExe) $ - execStackShake_ ["install", "cabal-install"] - execCabal_ ["update"] - - -checkStack :: Action () -checkStack = do - Stdout stackVersion <- execStackShake ["--numeric-version"] - let (parsedVersion, "") : _ = - stackVersion & trim & readP_to_S parseVersion & filter - (("" ==) . snd) - unless (parsedVersion >= makeVersion requiredStackVersion) $ do - liftIO $ putStrLn $ embedInStars $ stackExeIsOldFailMsg $ trim stackVersion - error $ stackExeIsOldFailMsg $ trim stackVersion - - -stackBuildHie :: VersionNumber -> Action () -stackBuildHie versionNumber = - execStackWithGhc_ versionNumber ["build"] - `actionOnException` liftIO (putStrLn stackBuildFailMsg) - --- | copy the built binaries into the localBinDir -stackInstallHie :: VersionNumber -> Action () -stackInstallHie versionNumber = do - execStackWithGhc_ versionNumber ["install"] - localBinDir <- getLocalBin - localInstallRoot <- getLocalInstallRoot versionNumber - let hie = "hie" <.> exe - copyFile' (localInstallRoot "bin" hie) - (localBinDir "hie-" ++ versionNumber <.> exe) - copyFile' (localInstallRoot "bin" hie) - (localBinDir "hie-" ++ dropExtension versionNumber <.> exe) - -buildCopyCompilerTool :: VersionNumber -> Action () -buildCopyCompilerTool versionNumber = - execStackWithGhc_ versionNumber ["build", "--copy-compiler-tool"] - -stackTest :: VersionNumber -> Action () -stackTest versionNumber = execStackWithGhc_ versionNumber ["test"] - -stackBuildDoc :: Action () -stackBuildDoc = do - execStackShake_ ["build", "hoogle"] - execStackShake_ ["exec", "hoogle", "generate"] - --- | short help message is printed by default -shortHelpMessage :: Action () -shortHelpMessage = do - hieVersions <- getHieVersions - let out = liftIO . putStrLn - scriptName <- liftIO getProgName - out "" - out "Usage:" - out' ("stack " <> scriptName <> " ") - out "" - out "Targets:" - mapM_ (out' . showTarget (spaces hieVersions)) (targets hieVersions) - out "" - where - out = liftIO . putStrLn - out' = out . (" " ++) - - spaces hieVersions = space (targets hieVersions) - targets hieVersions = - [ ("help", "Show help message including all targets") - , emptyTarget - , ( "build" - , "Builds hie for all supported GHC versions (" - ++ allVersionMessage hieVersions - ++ ")" - ) - , stackBuildAllTarget - -- , stackHieTarget mostRecentHieVersion - , stackBuildDocTarget - , stackHieTarget (last hieVersions) - , emptyTarget - , ( "cabal-ghcs" - , "Show all GHC versions that can be installed via `cabal-build` and `cabal-build-all`." - ) - , cabalBuildTarget - , cabalBuildAllTarget - -- , cabalHieTarget mostRecentHieVersion - , cabalBuildDocTarget - , cabalHieTarget (last hieVersions) - ] - - -helpMessage :: Action () -helpMessage = do - - hieVersions <- getHieVersions - scriptName <- liftIO getProgName - out "" - out "Usage:" - out' ("stack " <> scriptName <> " ") - out "" - out "Targets:" - mapM_ (out' . showTarget (spaces hieVersions)) (targets hieVersions) - out "" - where - out = liftIO . putStrLn - out' = out . (" " ++) - - spaces hieVersions = space (targets hieVersions) - -- All targets the shake file supports - targets :: [VersionNumber] -> [(String, String)] - targets hieVersions = intercalate - [emptyTarget] - [ generalTargets - , stackTargets hieVersions - , cabalTargets hieVersions - , macosTargets - ] - - -- All targets with their respective help message. - generalTargets = - [ ("help", "Show help message including all targets") - , ( "cabal" - , "Makes sure that Cabal the lib is available for cabal-helper-wapper, to speed up project start" - ) - ] - - macosTargets = [("icu-macos-fix", "Fixes icu related problems in MacOS")] - - stackTargets hieVersions = - [ ( "build" - , "Builds hie for all supported GHC versions (" - ++ allVersionMessage hieVersions - ++ ")" - ) - , stackBuildAllTarget - , stackBuildDocTarget - , ("test", "Runs hie tests with stack") - ] - ++ map stackHieTarget hieVersions - - cabalTargets hieVersions = - [ ( "cabal-ghcs" - , "Show all GHC versions that can be installed via `cabal-build` and `cabal-build-all`." - ) - , cabalBuildTarget - , cabalBuildAllTarget - , cabalBuildDocTarget - , ("cabal-test", "Runs hie tests with cabal") - ] - ++ map cabalHieTarget hieVersions - --- | Empty target. Purpose is to introduce a newline between the targets -emptyTarget :: (String, String) -emptyTarget = ("", "") - --- | Number of spaces the target name including whitespace should have. --- At least twenty, maybe more if target names are long. At most the length of the longest target plus five. -space :: [(String, String)] -> Int -space phonyTargets = maximum (20 : map ((+ 5) . length . fst) phonyTargets) - --- | Show a target. --- Concatenates the target with its help message and inserts whitespace between them. -showTarget :: Int -> (String, String) -> String -showTarget spaces (target, msg) = - target ++ replicate (spaces - length target) ' ' ++ msg - --- | Target for a specific ghc version -stackHieTarget :: String -> (String, String) -stackHieTarget version = - ( "hie-" ++ version - , "Builds hie for GHC version " ++ version ++ " only with stack" - ) - --- | Target for a specific ghc version -cabalHieTarget :: String -> (String, String) -cabalHieTarget version = - ( "cabal-hie-" ++ version - , "Builds hie for GHC version " ++ version ++ " only with cabal new-build" - ) - -stackBuildDocTarget :: (String, String) -stackBuildDocTarget = ("build-doc", "Builds the Hoogle database") - -stackBuildAllTarget :: (String, String) -stackBuildAllTarget = - ( "build-all" - , "Builds hie for all supported GHC versions and the hoogle database" - ) - -cabalBuildTarget :: (String, String) -cabalBuildTarget = - ("cabal-build", "Builds hie with cabal with all installed GHCs.") - -cabalBuildDocTarget :: (String, String) -cabalBuildDocTarget = - ("cabal-build-doc", "Builds the Hoogle database with cabal") - -cabalBuildAllTarget :: (String, String) -cabalBuildAllTarget = - ( "cabal-build-all" - , "Builds hie for all installed GHC versions and the hoogle database with cabal" - ) - --- | Creates a message of the form "a, b, c and d", where a,b,c,d are GHC versions. --- If there is no GHC in the list of `hieVersions` -allVersionMessage :: [String] -> String -allVersionMessage wordList = case wordList of - [] -> "" - [a] -> show a - (a : as) -> - let msg = intersperse ", " wordList - lastVersion = last msg - in concat $ (init $ init msg) ++ [" and ", lastVersion] - - --- RUN EXECUTABLES - --- | Execute a stack command for a specified ghc, discarding the output -execStackWithGhc_ :: VersionNumber -> [String] -> Action () -execStackWithGhc_ versionNumber args = do - let stackFile = "stack-" ++ versionNumber ++ ".yaml" - command_ [] "stack" (("--stack-yaml=" ++ stackFile) : args) - --- | Execute a stack command for a specified ghc -execStackWithGhc :: CmdResult r => VersionNumber -> [String] -> Action r -execStackWithGhc versionNumber args = do - let stackFile = "stack-" ++ versionNumber ++ ".yaml" - command [] "stack" (("--stack-yaml=" ++ stackFile) : args) - --- | Execute a stack command with the same resolver as the build script -execStackShake :: CmdResult r => [String] -> Action r -execStackShake args = - command [] "stack" ("--stack-yaml=shake.yaml" : args) - --- | Execute a stack command with the same resolver as the build script, discarding the output -execStackShake_ :: [String] -> Action () -execStackShake_ args = - command_ [] "stack" ("--stack-yaml=shake.yaml" : args) - -execCabal :: CmdResult r => [String] -> Action r -execCabal = - command [] "cabal" - -execCabal_ :: [String] -> Action () -execCabal_ = command_ [] "cabal" - -existsExecutable :: MonadIO m => String -> m Bool -existsExecutable executable = liftIO $ isJust <$> findExecutable executable - - --- QUERY ENVIRONMENT - --- |Check if the current system is windows -isWindowsSystem :: Bool -isWindowsSystem = os `elem` ["mingw32", "win32"] - --- | Get the path to the GHC compiler executable linked to the local `stack-$GHCVER.yaml`. --- Equal to the command `stack path --stack-yaml $stack-yaml --compiler-exe`. --- This might install a GHC if it is not already installed, thus, might fail if stack fails to install the GHC. -getStackGhcPath :: VersionNumber -> Action GhcPath -getStackGhcPath ghcVersion = do - Stdout ghc <- execStackWithGhc ghcVersion ["path", "--compiler-exe"] - return $ trim ghc - -getStackGhcPathShake :: Action GhcPath -getStackGhcPathShake = do - Stdout ghc <- execStackShake ["path", "--compiler-exe"] - return $ trim ghc - --- | Get the path to a GHC that has the version specified by `VersionNumber` --- If no such GHC can be found, Nothing is returned. --- First, it is checked whether there is a GHC with the name `ghc-$VersionNumber`. --- If this yields no result, it is checked, whether the numeric-version of the `ghc` --- command fits to the desired version. -getGhcPath :: MonadIO m => VersionNumber -> m (Maybe GhcPath) -getGhcPath ghcVersion = liftIO $ - findExecutable ("ghc-" ++ ghcVersion) >>= \case - Nothing -> do - findExecutable "ghc" >>= \case - Nothing -> return Nothing - Just p -> do - Stdout version <- cmd p ["--numeric-version"] :: IO (Stdout String) - if ghcVersion == trim version then return $ Just p else return Nothing - p -> return p - --- | Read the local install root of the stack project specified by the VersionNumber --- Returns the filepath of the local install root. --- Equal to the command `stack path --local-install-root` -getLocalInstallRoot :: VersionNumber -> Action FilePath -getLocalInstallRoot hieVersion = do - Stdout localInstallRoot' <- execStackWithGhc - hieVersion - ["path", "--local-install-root"] - return $ trim localInstallRoot' - --- | Get the local binary path of stack. --- Equal to the command `stack path --local-bin` -getLocalBin :: Action FilePath -getLocalBin = do - Stdout stackLocalDir' <- execStackShake - ["path", "--local-bin"] - return $ trim stackLocalDir' - --- | Trim the end of a string -trim :: String -> String -trim = dropWhileEnd isSpace - --- | Embed a string within two lines of stars to improve perceivability and, thus, readability. -embedInStars :: String -> String -embedInStars str = - let starsLine - = "\n******************************************************************\n" - in starsLine <> str <> starsLine - --- |Stack build fails message -stackBuildFailMsg :: String -stackBuildFailMsg = - embedInStars - $ "Building failed, " - ++ "Try running `stack clean` and restart the build\n" - ++ "If this does not work, open an issue at \n" - ++ "\thttps://github.com/haskell/haskell-ide-engine" - --- | No suitable ghc version has been found. Show a message. -ghcVersionNotFoundFailMsg :: VersionNumber -> String -ghcVersionNotFoundFailMsg versionNumber = - "No GHC with version " - <> versionNumber - <> " has been found.\n" - <> "Either install a fitting GHC, use the stack targets or modify the PATH variable accordingly." - --- | Error message when a windows system tries to install HIE via `cabal new-install` -cabalInstallNotSuportedFailMsg :: String -cabalInstallNotSuportedFailMsg = - "This system has been identified as a windows system.\n" - ++ "Unfortunately, `cabal new-install` is currently not supported on windows.\n" - ++ "Please use one of the stack-based targets.\n\n" - ++ "If this system has been falsely identified, please open an issue at:\n\thttps://github.com/haskell/haskell-ide-engine\n" - --- | Error message when the `stack` binary is an older version -stackExeIsOldFailMsg :: String -> String -stackExeIsOldFailMsg stackVersion = - "The `stack` executable is outdated.\n" - ++ "found version is `" ++ stackVersion ++ "`.\n" - ++ "required version is `" ++ showVersion (makeVersion requiredStackVersion) ++ "`.\n" - ++ "Please run `stack upgrade` to upgrade your stack installation" - -requiredStackVersion :: [Int] -requiredStackVersion = [1, 9, 3] diff --git a/install/hie-install.cabal b/install/hie-install.cabal index f4b28a7ea..0244a3bc5 100644 --- a/install/hie-install.cabal +++ b/install/hie-install.cabal @@ -9,15 +9,22 @@ build-type: Simple cabal-version: >=2.0 library - hs-source-dirs: . + hs-source-dirs: src exposed-modules: Install other-modules: BuildSystem + , Stack + , Version + , Cabal + , Print + , Env build-depends: base >= 4.9 && < 5 , shake == 0.17.3 , directory , extra , text default-extensions: LambdaCase + , TupleSections + default-language: Haskell2010 if flag(run-from-stack) cpp-options: -DRUN_FROM_STACK diff --git a/install/BuildSystem.hs b/install/src/BuildSystem.hs similarity index 51% rename from install/BuildSystem.hs rename to install/src/BuildSystem.hs index 75d76ad79..e75dc4ce4 100644 --- a/install/BuildSystem.hs +++ b/install/src/BuildSystem.hs @@ -9,3 +9,9 @@ buildSystem = #else "cabal" #endif + +isRunFromStack :: Bool +isRunFromStack = buildSystem == "stack" + +isRunFromCabal :: Bool +isRunFromCabal = buildSystem == "cabal" diff --git a/install/src/Cabal.hs b/install/src/Cabal.hs new file mode 100644 index 000000000..105259568 --- /dev/null +++ b/install/src/Cabal.hs @@ -0,0 +1,122 @@ +module Cabal where + +import Development.Shake +import Development.Shake.Command +import Development.Shake.FilePath +import Control.Monad +import Data.Maybe ( isNothing ) +import Control.Monad.Extra ( whenMaybe ) +import System.Directory ( findExecutable ) + +import Version +import Print +import Env +import Stack + + +execCabal :: CmdResult r => [String] -> Action r +execCabal = command [] "cabal" + +execCabal_ :: [String] -> Action () +execCabal_ = command_ [] "cabal" + +-- TODO: review +installCabal :: Action () +installCabal = do + -- try to find existing `cabal` executable with appropriate version + cabalExe <- liftIO (findExecutable "cabal") >>= \case + Nothing -> return Nothing + Just cabalExe -> do + cabalVersion <- trimmedStdout <$> execCabal ["--numeric-version"] + whenMaybe (checkVersion requiredCabalVersion cabalVersion) + $ return cabalExe + + -- install `cabal-install` if not already installed + when (isNothing cabalExe) $ execStackShake_ ["install", "cabal-install"] + +-- | check `stack` has the required version +checkCabal :: Action () +checkCabal = do + cabalVersion <- trimmedStdout <$> execCabal ["--numeric-version"] + unless (checkVersion requiredCabalVersion cabalVersion) $ do + printInStars $ cabalInstallIsOldFailMsg cabalVersion + error $ stackExeIsOldFailMsg cabalVersion + + +getCabalVersion :: Action String +getCabalVersion = trimmedStdout <$> execCabal ["--numeric-version"] + + +-- | update the cabal index. This is required for ghc-mod. +-- +-- TODO: remove when ghc-mod supports new-style builds +updateCabal :: Action () +updateCabal = do + execCabal_ ["v1-update"] + + +cabalBuildDoc :: Action () +cabalBuildDoc = do + execCabal_ ["new-build", "hoogle", "generate"] + execCabal_ ["new-exec", "hoogle", "generate"] + +configureCabal :: VersionNumber -> Action () +configureCabal versionNumber = do + ghcPath <- getGhcPath versionNumber >>= \case + Nothing -> do + printInStars $ ghcVersionNotFoundFailMsg versionNumber + error (ghcVersionNotFoundFailMsg versionNumber) + Just p -> return p + execCabal_ + ["new-configure", "-w", ghcPath, "--write-ghc-environment-files=never"] + +cabalBuildHie :: VersionNumber -> Action () +cabalBuildHie versionNumber = do + configureCabal versionNumber + execCabal_ ["new-build", "--write-ghc-environment-files=never"] + +cabalInstallHie :: VersionNumber -> Action () +cabalInstallHie versionNumber = do + localBin <- getLocalBin + execCabal_ + [ "new-install" + , "--write-ghc-environment-files=never" + , "--symlink-bindir=" ++ localBin + , "exe:hie" + , "--overwrite-policy=always" + ] + copyFile' (localBin "hie" <.> exe) + (localBin "hie-" ++ versionNumber <.> exe) + copyFile' (localBin "hie" <.> exe) + (localBin "hie-" ++ dropExtension versionNumber <.> exe) + + +-- TODO: this restriction will be gone in the next release of cabal +validateCabalNewInstallIsSupported :: Action () +validateCabalNewInstallIsSupported = when isWindowsSystem $ do + printInStars cabalInstallNotSuportedFailMsg + error cabalInstallNotSuportedFailMsg + +-- | Error message when a windows system tries to install HIE via `cabal new-install` +cabalInstallNotSuportedFailMsg :: String +cabalInstallNotSuportedFailMsg = + "This system has been identified as a windows system.\n" + ++ "Unfortunately, `cabal new-install` is currently not supported on windows.\n" + ++ "Please use one of the stack-based targets.\n\n" + ++ "If this system has been falsely identified, please open an issue at:\n\thttps://github.com/haskell/haskell-ide-engine\n" + + +-- | Error message when the `stack` binary is an older version +cabalInstallIsOldFailMsg :: String -> String +cabalInstallIsOldFailMsg cabalVersion = + "The `cabal` executable is outdated.\n" + ++ "found version is `" + ++ cabalVersion + ++ "`.\n" + ++ "required version is `" + ++ versionToString requiredCabalVersion + ++ "`." + + +requiredCabalVersion :: RequiredVersion +requiredCabalVersion = [2, 4, 1, 0] diff --git a/install/src/Env.hs b/install/src/Env.hs new file mode 100644 index 000000000..9b7398d7d --- /dev/null +++ b/install/src/Env.hs @@ -0,0 +1,91 @@ +module Env where + +import Development.Shake +import Development.Shake.Command +import Control.Monad.IO.Class +import Control.Monad +import Development.Shake.FilePath +import System.Info ( os + , arch + ) +import Data.Maybe ( isJust ) +import System.Directory ( findExecutable + , listDirectory + ) +import Data.Function ( (&) ) +import Data.List ( sort ) +import Control.Monad.Extra ( mapMaybeM ) +import Data.Maybe ( isNothing + , mapMaybe + ) +import qualified Data.Text as T + +import Version +import Print + + +type GhcPath = String + +existsExecutable :: MonadIO m => String -> m Bool +existsExecutable executable = liftIO $ isJust <$> findExecutable executable + + +-- | Check if the current system is windows +isWindowsSystem :: Bool +isWindowsSystem = os `elem` ["mingw32", "win32"] + +findInstalledGhcs :: IO [(VersionNumber, GhcPath)] +findInstalledGhcs = do + hieVersions <- getHieVersions :: IO [VersionNumber] + mapMaybeM + (\version -> getGhcPath version >>= \case + Nothing -> return Nothing + Just p -> return $ Just (version, p) + ) + (reverse hieVersions) + +-- | Get the path to a GHC that has the version specified by `VersionNumber` +-- If no such GHC can be found, Nothing is returned. +-- First, it is checked whether there is a GHC with the name `ghc-$VersionNumber`. +-- If this yields no result, it is checked, whether the numeric-version of the `ghc` +-- command fits to the desired version. +getGhcPath :: MonadIO m => VersionNumber -> m (Maybe GhcPath) +getGhcPath ghcVersion = + liftIO $ findExecutable ("ghc-" ++ ghcVersion) >>= \case + Nothing -> do + findExecutable "ghc" >>= \case + Nothing -> return Nothing + Just p -> do + Stdout version <- cmd p ["--numeric-version"] :: IO (Stdout String) + if ghcVersion == trim version then return $ Just p else return Nothing + p -> return p + + +-- | No suitable ghc version has been found. Show a message. +ghcVersionNotFoundFailMsg :: VersionNumber -> String +ghcVersionNotFoundFailMsg versionNumber = + "No GHC with version " + <> versionNumber + <> " has been found.\n" + <> "Either install a fitting GHC, use the stack targets or modify the PATH variable accordingly." + + +-- | Defines all different hie versions that are buildable. +-- +-- The current directory is scanned for `stack-*.yaml` files. +-- On windows, `8.6.3` is excluded as this version of ghc does not work there +getHieVersions :: MonadIO m => m [VersionNumber] +getHieVersions = do + let stackYamlPrefix = T.pack "stack-" + let stackYamlSuffix = T.pack ".yaml" + files <- liftIO $ listDirectory "." + let hieVersions = + files + & map T.pack + & mapMaybe + (T.stripPrefix stackYamlPrefix >=> T.stripSuffix stackYamlSuffix) + & map T.unpack + -- the following line excludes `8.6.3` on windows systems + & filter (\p -> not isWindowsSystem || p /= "8.6.3") + & sort + return hieVersions diff --git a/install/src/Install.hs b/install/src/Install.hs new file mode 100644 index 000000000..ee7078c90 --- /dev/null +++ b/install/src/Install.hs @@ -0,0 +1,355 @@ +module Install where + +import Development.Shake +import Development.Shake.Command +import Development.Shake.FilePath +import Control.Monad +import Control.Monad.IO.Class +import Control.Monad.Extra ( unlessM + , mapMaybeM + ) +import Data.Maybe ( isJust ) +import System.Directory ( listDirectory ) +import System.Environment ( getProgName + , unsetEnv + ) +import System.Info ( os + , arch + ) + +import Data.Maybe ( isNothing + , mapMaybe + ) +import Data.List ( dropWhileEnd + , intersperse + , intercalate + , sort + , sortOn + ) +import qualified Data.Text as T +import Data.Char ( isSpace ) +import Data.Version ( parseVersion + , makeVersion + , showVersion + ) +import Data.Function ( (&) ) +import Text.ParserCombinators.ReadP ( readP_to_S ) + +import BuildSystem +import Stack +import Cabal +import Version +import Print +import Env + +-- | Most recent version of hie. +-- Shown in the more concise help message. +mostRecentHieVersion :: MonadIO m => m VersionNumber +mostRecentHieVersion = last <$> getHieVersions + +defaultMain :: IO () +defaultMain = do + -- unset GHC_PACKAGE_PATH for cabal + unsetEnv "GHC_PACKAGE_PATH" + + ghcPaths <- findInstalledGhcs + let ghcVersions = map fst ghcPaths + + hieVersions <- getHieVersions + + putStrLn $ "run from: " ++ buildSystem + + shakeArgs shakeOptions { shakeFiles = "_build" } $ do + want ["short-help"] + -- general purpose targets + phony "submodules" updateSubmodules + phony "cabal" installCabal + phony "short-help" shortHelpMessage + phony "all" shortHelpMessage + phony "help" helpMessage + phony "check-stack" checkStack + phony "check-cabal" checkCabal + -- TODO: check-cabal + + phony "cabal-ghcs" $ do + let + msg = + "Found the following GHC paths: \n" + ++ unlines + (map (\(version, path) -> "ghc-" ++ version ++ ": " ++ path) + ghcPaths + ) + printInStars msg + + -- default-targets + phony "build" $ need [buildSystem ++ "-build"] + phony "build-all" $ need [buildSystem ++ "-build-all"] + phony "build-doc" $ need [buildSystem ++ "-build"] + forM_ + hieVersions + (\version -> + phony ("hie-" ++ version) $ need [buildSystem ++ "-hie-" ++ version] + ) + + -- stack specific targets + phony "stack-build" (need (reverse $ map ("hie-" ++) hieVersions)) + phony "stack-build-all" (need ["build-doc", "build"]) + phony "stack-build-doc" $ do + need ["submodules"] + need ["check-stack"] + stackBuildDoc + forM_ + hieVersions + (\version -> phony ("stack-hie-" ++ version) $ do + need ["submodules"] + need ["check-stack"] + need ["cabal"] + stackBuildHie version + stackInstallHie version + ) + + -- cabal specific targets + phony "cabal-build" (need (map ("cabal-hie-" ++) ghcVersions)) + phony "cabal-build-all" (need ["cabal-build-doc", "cabal-build"]) + phony "cabal-build-doc" $ do + need ["submodules"] + need ["cabal"] + cabalBuildDoc + forM_ + hieVersions + (\version -> phony ("cabal-hie-" ++ version) $ do + validateCabalNewInstallIsSupported + need ["submodules"] + need ["cabal"] + cabalBuildHie version + cabalInstallHie version + ) + + -- macos specific targets + phony "icu-macos-fix" + (need ["icu-macos-fix-install"] >> need ["icu-macos-fix-build"]) + phony "icu-macos-fix-install" (command_ [] "brew" ["install", "icu4c"]) + phony "icu-macos-fix-build" $ mapM_ buildIcuMacosFix hieVersions + + +buildIcuMacosFix :: VersionNumber -> Action () +buildIcuMacosFix version = execStackWithGhc_ + version + [ "build" + , "text-icu" + , "--extra-lib-dirs=/usr/local/opt/icu4c/lib" + , "--extra-include-dirs=/usr/local/opt/icu4c/include" + ] + +-- | update the submodules that the project is in the state as required by the `stack.yaml` files +updateSubmodules :: Action () +updateSubmodules = do + command_ [] "git" ["submodule", "sync"] + command_ [] "git" ["submodule", "update", "--init"] + +stackBuildHie :: VersionNumber -> Action () +stackBuildHie versionNumber = execStackWithGhc_ versionNumber ["build"] + `actionOnException` liftIO (putStrLn stackBuildFailMsg) + +-- | copy the built binaries into the localBinDir +stackInstallHie :: VersionNumber -> Action () +stackInstallHie versionNumber = do + execStackWithGhc_ versionNumber ["install"] + localBinDir <- getLocalBin + localInstallRoot <- getLocalInstallRoot versionNumber + let hie = "hie" <.> exe + copyFile' (localInstallRoot "bin" hie) + (localBinDir "hie-" ++ versionNumber <.> exe) + copyFile' (localInstallRoot "bin" hie) + (localBinDir "hie-" ++ dropExtension versionNumber <.> exe) + +buildCopyCompilerTool :: VersionNumber -> Action () +buildCopyCompilerTool versionNumber = + execStackWithGhc_ versionNumber ["build", "--copy-compiler-tool"] + +stackBuildDoc :: Action () +stackBuildDoc = do + execStackShake_ ["build", "hoogle"] + execStackShake_ ["exec", "hoogle", "generate"] + +-- | short help message is printed by default +shortHelpMessage :: Action () +shortHelpMessage = do + hieVersions <- getHieVersions + let out = liftIO . putStrLn + scriptName <- liftIO getProgName + out "" + out "Usage:" + out' ("stack " <> scriptName <> " ") + out "" + out "Targets:" + mapM_ (out' . showTarget (spaces hieVersions)) (targets hieVersions) + out "" + where + out = liftIO . putStrLn + out' = out . (" " ++) + + spaces hieVersions = space (targets hieVersions) + targets hieVersions = + [ ("help", "Show help message including all targets") + , emptyTarget + , ( "build" + , "Builds hie for all supported GHC versions (" + ++ allVersionMessage hieVersions + ++ ")" + ) + , stackBuildAllTarget + -- , stackHieTarget mostRecentHieVersion + , stackBuildDocTarget + , stackHieTarget (last hieVersions) + , emptyTarget + , ( "cabal-ghcs" + , "Show all GHC versions that can be installed via `cabal-build` and `cabal-build-all`." + ) + , cabalBuildTarget + , cabalBuildAllTarget + -- , cabalHieTarget mostRecentHieVersion + , cabalBuildDocTarget + , cabalHieTarget (last hieVersions) + ] + + +helpMessage :: Action () +helpMessage = do + + hieVersions <- getHieVersions + scriptName <- liftIO getProgName + out "" + out "Usage:" + out' ("stack " <> scriptName <> " ") + out "" + out "Targets:" + mapM_ (out' . showTarget (spaces hieVersions)) (targets hieVersions) + out "" + where + out = liftIO . putStrLn + out' = out . (" " ++) + + spaces hieVersions = space (targets hieVersions) + -- All targets the shake file supports + targets :: [VersionNumber] -> [(String, String)] + targets hieVersions = intercalate + [emptyTarget] + [ generalTargets + , stackTargets hieVersions + , cabalTargets hieVersions + , macosTargets + ] + + -- All targets with their respective help message. + generalTargets = + [ ("help", "Show help message including all targets") + , ( "cabal" + , "Makes sure that Cabal the lib is available for cabal-helper-wapper, to speed up project start" + ) + ] + + macosTargets = [("icu-macos-fix", "Fixes icu related problems in MacOS")] + + stackTargets hieVersions = + [ ( "build" + , "Builds hie for all supported GHC versions (" + ++ allVersionMessage hieVersions + ++ ")" + ) + , stackBuildAllTarget + , stackBuildDocTarget + , ("test", "Runs hie tests with stack") + ] + ++ map stackHieTarget hieVersions + + cabalTargets hieVersions = + [ ( "cabal-ghcs" + , "Show all GHC versions that can be installed via `cabal-build` and `cabal-build-all`." + ) + , cabalBuildTarget + , cabalBuildAllTarget + , cabalBuildDocTarget + , ("cabal-test", "Runs hie tests with cabal") + ] + ++ map cabalHieTarget hieVersions + +-- | Empty target. Purpose is to introduce a newline between the targets +emptyTarget :: (String, String) +emptyTarget = ("", "") + +-- | Target for a specific ghc version +stackHieTarget :: String -> TargetDescription +stackHieTarget version = + ( "hie-" ++ version + , "Builds hie for GHC version " ++ version ++ " only with stack" + ) + +-- | Target for a specific ghc version +cabalHieTarget :: String -> TargetDescription +cabalHieTarget version = + ( "cabal-hie-" ++ version + , "Builds hie for GHC version " ++ version ++ " only with cabal new-build" + ) + +stackBuildDocTarget :: TargetDescription +stackBuildDocTarget = ("build-doc", "Builds the Hoogle database") + +stackBuildAllTarget :: TargetDescription +stackBuildAllTarget = + ( "build-all" + , "Builds hie for all supported GHC versions and the hoogle database" + ) + +cabalBuildTarget :: TargetDescription +cabalBuildTarget = + ("cabal-build", "Builds hie with cabal with all installed GHCs.") + +cabalBuildDocTarget :: TargetDescription +cabalBuildDocTarget = + ("cabal-build-doc", "Builds the Hoogle database with cabal") + +cabalBuildAllTarget :: TargetDescription +cabalBuildAllTarget = + ( "cabal-build-all" + , "Builds hie for all installed GHC versions and the hoogle database with cabal" + ) + +-- | Creates a message of the form "a, b, c and d", where a,b,c,d are GHC versions. +-- If there is no GHC in the list of `hieVersions` +allVersionMessage :: [String] -> String +allVersionMessage wordList = case wordList of + [] -> "" + [a] -> show a + (a : as) -> + let msg = intersperse ", " wordList + lastVersion = last msg + in concat $ init (init msg) ++ [" and ", lastVersion] + + +-- | Get the path to the GHC compiler executable linked to the local `stack-$GHCVER.yaml`. +-- Equal to the command `stack path --stack-yaml $stack-yaml --compiler-exe`. +-- This might install a GHC if it is not already installed, thus, might fail if stack fails to install the GHC. +getStackGhcPath :: VersionNumber -> Action GhcPath +getStackGhcPath ghcVersion = do + Stdout ghc <- execStackWithGhc ghcVersion ["path", "--compiler-exe"] + return $ trim ghc + +-- | Read the local install root of the stack project specified by the VersionNumber +-- Returns the filepath of the local install root. +-- Equal to the command `stack path --local-install-root` +getLocalInstallRoot :: VersionNumber -> Action FilePath +getLocalInstallRoot hieVersion = do + Stdout localInstallRoot' <- execStackWithGhc + hieVersion + ["path", "--local-install-root"] + return $ trim localInstallRoot' + +-- |Stack build fails message +stackBuildFailMsg :: String +stackBuildFailMsg = + embedInStars + $ "Building failed, " + ++ "Try running `stack clean` and restart the build\n" + ++ "If this does not work, open an issue at \n" + ++ "\thttps://github.com/haskell/haskell-ide-engine" diff --git a/install/src/Print.hs b/install/src/Print.hs new file mode 100644 index 000000000..6fbb667dd --- /dev/null +++ b/install/src/Print.hs @@ -0,0 +1,39 @@ +module Print where + +import Development.Shake +import Development.Shake.Command +import Control.Monad.IO.Class +import Data.List ( dropWhileEnd + , dropWhile + ) +import Data.Char ( isSpace ) + +embedInStars :: String -> String +embedInStars str = + let starsLine = "\n" <> replicate 30 '*' <> "\n" + in starsLine <> str <> starsLine + +printInStars :: MonadIO m => String -> m () +printInStars = liftIO . putStrLn . embedInStars + + +-- | Trim whitespace of both ends of a string +trim :: String -> String +trim = dropWhileEnd isSpace . dropWhile isSpace + +-- | Trim the whitespace of the stdout of a command +trimmedStdout :: Stdout String -> String +trimmedStdout (Stdout s) = trim s + +type TargetDescription = (String, String) + +-- | Number of spaces the target name including whitespace should have. +-- At least twenty, maybe more if target names are long. At most the length of the longest target plus five. +space :: [TargetDescription] -> Int +space phonyTargets = maximum (20 : map ((+ 5) . length . fst) phonyTargets) + +-- | Show a target. +-- Concatenates the target with its help message and inserts whitespace between them. +showTarget :: Int -> TargetDescription -> String +showTarget spaces (target, msg) = + target ++ replicate (spaces - length target) ' ' ++ msg diff --git a/install/src/Stack.hs b/install/src/Stack.hs new file mode 100644 index 000000000..74d00d8c1 --- /dev/null +++ b/install/src/Stack.hs @@ -0,0 +1,60 @@ +module Stack where + +import Development.Shake +import Development.Shake.Command +import Control.Monad + +import Version +import Print + +-- | check `stack` has the required version +checkStack :: Action () +checkStack = do + stackVersion <- trimmedStdout <$> execStackShake ["--numeric-version"] + unless (checkVersion requiredStackVersion stackVersion) $ do + printInStars $ stackExeIsOldFailMsg stackVersion + error $ stackExeIsOldFailMsg stackVersion + +-- | Get the local binary path of stack. +-- Equal to the command `stack path --local-bin` +getLocalBin :: Action FilePath +getLocalBin = do + Stdout stackLocalDir' <- execStackShake ["path", "--local-bin"] + return $ trim stackLocalDir' + + +-- | Execute a stack command for a specified ghc, discarding the output +execStackWithGhc_ :: VersionNumber -> [String] -> Action () +execStackWithGhc_ versionNumber args = do + let stackFile = "stack-" ++ versionNumber ++ ".yaml" + command_ [] "stack" (("--stack-yaml=" ++ stackFile) : args) + +-- | Execute a stack command for a specified ghc +execStackWithGhc :: CmdResult r => VersionNumber -> [String] -> Action r +execStackWithGhc versionNumber args = do + let stackFile = "stack-" ++ versionNumber ++ ".yaml" + command [] "stack" (("--stack-yaml=" ++ stackFile) : args) + +-- | Execute a stack command with the same resolver as the build script +execStackShake :: CmdResult r => [String] -> Action r +execStackShake args = command [] "stack" ("--stack-yaml=shake.yaml" : args) + +-- | Execute a stack command with the same resolver as the build script, discarding the output +execStackShake_ :: [String] -> Action () +execStackShake_ args = command_ [] "stack" ("--stack-yaml=shake.yaml" : args) + + +-- | Error message when the `stack` binary is an older version +stackExeIsOldFailMsg :: String -> String +stackExeIsOldFailMsg stackVersion = + "The `stack` executable is outdated.\n" + ++ "found version is `" + ++ stackVersion + ++ "`.\n" + ++ "required version is `" + ++ versionToString requiredStackVersion + ++ "`.\n" + ++ "Please run `stack upgrade` to upgrade your stack installation" + +requiredStackVersion :: RequiredVersion +requiredStackVersion = [1, 9, 3] diff --git a/install/src/Version.hs b/install/src/Version.hs new file mode 100644 index 000000000..de9bfd019 --- /dev/null +++ b/install/src/Version.hs @@ -0,0 +1,24 @@ +module Version where + +import Data.Version ( Version + , parseVersion + , makeVersion + , showVersion + ) +import Text.ParserCombinators.ReadP ( readP_to_S ) +import Control.Monad.IO.Class + + +type VersionNumber = String +type RequiredVersion = [Int] + +versionToString :: RequiredVersion -> String +versionToString = showVersion . makeVersion + +-- | Parse a version-string into a version. Fails if the version-string is not valid +parseVersionEx :: String -> Version +parseVersionEx = fst . head . filter (("" ==) . snd) . readP_to_S parseVersion + + +checkVersion :: RequiredVersion -> String -> Bool +checkVersion required given = parseVersionEx given >= makeVersion required From b77e39beb1642abe75f8c4044819ba8e72792687 Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Fri, 14 Jun 2019 16:03:38 +0200 Subject: [PATCH 117/158] refactor help messages and clean up cabal- and stack- targets --- install/hie-install.cabal | 1 + install/src/Cabal.hs | 76 +++++-------- install/src/Env.hs | 6 + install/src/Help.hs | 149 ++++++++++++++++++++++++ install/src/Install.hs | 231 ++------------------------------------ install/src/Print.hs | 6 + install/src/Stack.hs | 36 ++++++ 7 files changed, 237 insertions(+), 268 deletions(-) create mode 100644 install/src/Help.hs diff --git a/install/hie-install.cabal b/install/hie-install.cabal index 0244a3bc5..cf28c517e 100644 --- a/install/hie-install.cabal +++ b/install/hie-install.cabal @@ -17,6 +17,7 @@ library , Cabal , Print , Env + , Help build-depends: base >= 4.9 && < 5 , shake == 0.17.3 , directory diff --git a/install/src/Cabal.hs b/install/src/Cabal.hs index 105259568..91acdc861 100644 --- a/install/src/Cabal.hs +++ b/install/src/Cabal.hs @@ -20,60 +20,20 @@ execCabal = command [] "cabal" execCabal_ :: [String] -> Action () execCabal_ = command_ [] "cabal" --- TODO: review -installCabal :: Action () -installCabal = do - -- try to find existing `cabal` executable with appropriate version - cabalExe <- liftIO (findExecutable "cabal") >>= \case - Nothing -> return Nothing - Just cabalExe -> do - cabalVersion <- trimmedStdout <$> execCabal ["--numeric-version"] - whenMaybe (checkVersion requiredCabalVersion cabalVersion) - $ return cabalExe - - -- install `cabal-install` if not already installed - when (isNothing cabalExe) $ execStackShake_ ["install", "cabal-install"] - --- | check `stack` has the required version -checkCabal :: Action () -checkCabal = do - cabalVersion <- trimmedStdout <$> execCabal ["--numeric-version"] - unless (checkVersion requiredCabalVersion cabalVersion) $ do - printInStars $ cabalInstallIsOldFailMsg cabalVersion - error $ stackExeIsOldFailMsg cabalVersion - - -getCabalVersion :: Action String -getCabalVersion = trimmedStdout <$> execCabal ["--numeric-version"] - - --- | update the cabal index. This is required for ghc-mod. --- --- TODO: remove when ghc-mod supports new-style builds -updateCabal :: Action () -updateCabal = do - execCabal_ ["v1-update"] - - -cabalBuildDoc :: Action () -cabalBuildDoc = do - execCabal_ ["new-build", "hoogle", "generate"] +cabalBuildData :: Action () +cabalBuildData = do + execCabal_ ["new-build", "hoogle"] execCabal_ ["new-exec", "hoogle", "generate"] -configureCabal :: VersionNumber -> Action () -configureCabal versionNumber = do +cabalBuildHie :: VersionNumber -> Action () +cabalBuildHie versionNumber = do ghcPath <- getGhcPath versionNumber >>= \case Nothing -> do printInStars $ ghcVersionNotFoundFailMsg versionNumber error (ghcVersionNotFoundFailMsg versionNumber) Just p -> return p execCabal_ - ["new-configure", "-w", ghcPath, "--write-ghc-environment-files=never"] - -cabalBuildHie :: VersionNumber -> Action () -cabalBuildHie versionNumber = do - configureCabal versionNumber - execCabal_ ["new-build", "--write-ghc-environment-files=never"] + ["new-build", "-w", ghcPath, "--write-ghc-environment-files=never"] cabalInstallHie :: VersionNumber -> Action () cabalInstallHie versionNumber = do @@ -90,6 +50,30 @@ cabalInstallHie versionNumber = do copyFile' (localBin "hie" <.> exe) (localBin "hie-" ++ dropExtension versionNumber <.> exe) +-- TODO: review +installCabal :: Action () +installCabal = do + -- try to find existing `cabal` executable with appropriate version + cabalExe <- liftIO (findExecutable "cabal") >>= \case + Nothing -> return Nothing + Just cabalExe -> do + cabalVersion <- trimmedStdout <$> execCabal ["--numeric-version"] + whenMaybe (checkVersion requiredCabalVersion cabalVersion) + $ return cabalExe + + -- install `cabal-install` if not already installed + when (isNothing cabalExe) $ execStackShake_ ["install", "cabal-install"] + +-- | check `stack` has the required version +checkCabal :: Action () +checkCabal = do + cabalVersion <- trimmedStdout <$> execCabal ["--numeric-version"] + unless (checkVersion requiredCabalVersion cabalVersion) $ do + printInStars $ cabalInstallIsOldFailMsg cabalVersion + error $ stackExeIsOldFailMsg cabalVersion + +getCabalVersion :: Action String +getCabalVersion = trimmedStdout <$> execCabal ["--numeric-version"] -- TODO: this restriction will be gone in the next release of cabal validateCabalNewInstallIsSupported :: Action () diff --git a/install/src/Env.hs b/install/src/Env.hs index 9b7398d7d..eca37ee62 100644 --- a/install/src/Env.hs +++ b/install/src/Env.hs @@ -89,3 +89,9 @@ getHieVersions = do & filter (\p -> not isWindowsSystem || p /= "8.6.3") & sort return hieVersions + + +-- | Most recent version of hie. +-- Shown in the more concise help message. +mostRecentHieVersion :: MonadIO m => m VersionNumber +mostRecentHieVersion = last <$> getHieVersions diff --git a/install/src/Help.hs b/install/src/Help.hs new file mode 100644 index 000000000..1cdcc58ec --- /dev/null +++ b/install/src/Help.hs @@ -0,0 +1,149 @@ +-- |Module for Help messages and traget descriptions +module Help where + +import Development.Shake +import Data.List ( intersperse + , intercalate + ) + +import Env +import Print +import Version + +printUsage :: Action () +printUsage = do + out "" + out "Usage:" + out' ("stack install.hs ") + out' "or" + out' ("cabal new-run install.hs --project-file shake.project ") + +-- | short help message is printed by default +shortHelpMessage :: Action () +shortHelpMessage = do + hieVersions <- getHieVersions + printUsage + out "" + out "Targets:" + mapM_ (out' . showTarget (spaces hieVersions)) (targets hieVersions) + out "" + where + spaces hieVersions = space (targets hieVersions) + targets hieVersions = + [ ("help", "Show help message including all targets") + , emptyTarget + , buildTarget + , buildAllTarget + , hieTarget $ last hieVersions + , buildDataTarget + , cabalGhcsTarget + ] + + + +helpMessage :: Action () +helpMessage = do + hieVersions <- getHieVersions + printUsage + out "" + out "Targets:" + mapM_ (out' . showTarget (spaces hieVersions)) (targets hieVersions) + out "" + where + spaces hieVersions = space (targets hieVersions) + -- All targets the shake file supports + targets :: [VersionNumber] -> [(String, String)] + targets hieVersions = intercalate + [emptyTarget] + [ generalTargets + , defaultTargets hieVersions + , stackTargets hieVersions + , cabalTargets hieVersions + , [macosIcuTarget] + ] + + -- All targets with their respective help message. + generalTargets = + [ helpTarget + ] + + defaultTargets hieVersions = + [ buildTarget + , buildAllTarget + , buildDataTarget + ] + ++ map hieTarget hieVersions + + stackTargets hieVersions = + [ stackTarget buildTarget + , stackTarget buildAllTarget + , stackTarget buildDataTarget + ] + ++ map (stackTarget . hieTarget) hieVersions + + cabalTargets hieVersions = + [ cabalGhcsTarget + , cabalTarget buildTarget + , cabalTarget buildAllTarget + , cabalTarget buildDataTarget + ] + ++ map (cabalTarget . hieTarget) hieVersions + +-- | Empty target. Purpose is to introduce a newline between the targets +emptyTarget :: (String, String) +emptyTarget = ("", "") + +targetWithBuildSystem :: String -> TargetDescription -> TargetDescription +targetWithBuildSystem system (target, description) = + (system ++ "-" ++ target, description ++ "; with " ++ system) + +stackTarget :: TargetDescription -> TargetDescription +stackTarget = targetWithBuildSystem "stack" + +cabalTarget :: TargetDescription -> TargetDescription +cabalTarget = targetWithBuildSystem "cabal" + +hieTarget :: String -> TargetDescription +hieTarget version = + ( "hie-" ++ version + , "Builds hie for GHC version " ++ version + ) + +buildTarget :: TargetDescription +buildTarget = + ("build", "Builds hie with all installed GHCs") + +buildDataTarget :: TargetDescription +buildDataTarget = + ("build-data", "Get the required data-files for `hie` (Hoogle DB)") + +buildAllTarget :: TargetDescription +buildAllTarget = + ( "build-all" + , "Builds hie for all installed GHC versions and the data files" + ) + +-- speical targets + +macosIcuTarget :: TargetDescription +macosIcuTarget = ("icu-macos-fix", "Fixes icu related problems in MacOS") + +helpTarget :: TargetDescription +helpTarget = ("help", "Show help message including all targets") + +cabalGhcsTarget :: TargetDescription +cabalGhcsTarget = + ( "cabal-ghcs" + , "Show all GHC versions that can be installed via `cabal-build` and `cabal-build-all`." + ) + +-- | Creates a message of the form "a, b, c and d", where a,b,c,d are GHC versions. +-- If there is no GHC in the list of `hieVersions` +allVersionMessage :: [String] -> String +allVersionMessage wordList = case wordList of + [] -> "" + [a] -> show a + (a : as) -> + let msg = intersperse ", " wordList + lastVersion = last msg + in concat $ init (init msg) ++ [" and ", lastVersion] diff --git a/install/src/Install.hs b/install/src/Install.hs index ee7078c90..46f1e0da9 100644 --- a/install/src/Install.hs +++ b/install/src/Install.hs @@ -10,8 +10,7 @@ import Control.Monad.Extra ( unlessM ) import Data.Maybe ( isJust ) import System.Directory ( listDirectory ) -import System.Environment ( getProgName - , unsetEnv +import System.Environment ( unsetEnv ) import System.Info ( os , arch @@ -41,11 +40,7 @@ import Cabal import Version import Print import Env - --- | Most recent version of hie. --- Shown in the more concise help message. -mostRecentHieVersion :: MonadIO m => m VersionNumber -mostRecentHieVersion = last <$> getHieVersions +import Help defaultMain :: IO () defaultMain = do @@ -69,7 +64,6 @@ defaultMain = do phony "help" helpMessage phony "check-stack" checkStack phony "check-cabal" checkCabal - -- TODO: check-cabal phony "cabal-ghcs" $ do let @@ -84,7 +78,7 @@ defaultMain = do -- default-targets phony "build" $ need [buildSystem ++ "-build"] phony "build-all" $ need [buildSystem ++ "-build-all"] - phony "build-doc" $ need [buildSystem ++ "-build"] + phony "build-data" $ need [buildSystem ++ "-build-data"] forM_ hieVersions (\version -> @@ -93,11 +87,11 @@ defaultMain = do -- stack specific targets phony "stack-build" (need (reverse $ map ("hie-" ++) hieVersions)) - phony "stack-build-all" (need ["build-doc", "build"]) - phony "stack-build-doc" $ do + phony "stack-build-all" (need ["build-data", "build"]) + phony "stack-build-data" $ do need ["submodules"] need ["check-stack"] - stackBuildDoc + stackBuildData forM_ hieVersions (\version -> phony ("stack-hie-" ++ version) $ do @@ -110,11 +104,11 @@ defaultMain = do -- cabal specific targets phony "cabal-build" (need (map ("cabal-hie-" ++) ghcVersions)) - phony "cabal-build-all" (need ["cabal-build-doc", "cabal-build"]) - phony "cabal-build-doc" $ do + phony "cabal-build-all" (need ["cabal-build-data", "cabal-build"]) + phony "cabal-build-data" $ do need ["submodules"] need ["cabal"] - cabalBuildDoc + cabalBuildData forM_ hieVersions (\version -> phony ("cabal-hie-" ++ version) $ do @@ -146,210 +140,3 @@ updateSubmodules :: Action () updateSubmodules = do command_ [] "git" ["submodule", "sync"] command_ [] "git" ["submodule", "update", "--init"] - -stackBuildHie :: VersionNumber -> Action () -stackBuildHie versionNumber = execStackWithGhc_ versionNumber ["build"] - `actionOnException` liftIO (putStrLn stackBuildFailMsg) - --- | copy the built binaries into the localBinDir -stackInstallHie :: VersionNumber -> Action () -stackInstallHie versionNumber = do - execStackWithGhc_ versionNumber ["install"] - localBinDir <- getLocalBin - localInstallRoot <- getLocalInstallRoot versionNumber - let hie = "hie" <.> exe - copyFile' (localInstallRoot "bin" hie) - (localBinDir "hie-" ++ versionNumber <.> exe) - copyFile' (localInstallRoot "bin" hie) - (localBinDir "hie-" ++ dropExtension versionNumber <.> exe) - -buildCopyCompilerTool :: VersionNumber -> Action () -buildCopyCompilerTool versionNumber = - execStackWithGhc_ versionNumber ["build", "--copy-compiler-tool"] - -stackBuildDoc :: Action () -stackBuildDoc = do - execStackShake_ ["build", "hoogle"] - execStackShake_ ["exec", "hoogle", "generate"] - --- | short help message is printed by default -shortHelpMessage :: Action () -shortHelpMessage = do - hieVersions <- getHieVersions - let out = liftIO . putStrLn - scriptName <- liftIO getProgName - out "" - out "Usage:" - out' ("stack " <> scriptName <> " ") - out "" - out "Targets:" - mapM_ (out' . showTarget (spaces hieVersions)) (targets hieVersions) - out "" - where - out = liftIO . putStrLn - out' = out . (" " ++) - - spaces hieVersions = space (targets hieVersions) - targets hieVersions = - [ ("help", "Show help message including all targets") - , emptyTarget - , ( "build" - , "Builds hie for all supported GHC versions (" - ++ allVersionMessage hieVersions - ++ ")" - ) - , stackBuildAllTarget - -- , stackHieTarget mostRecentHieVersion - , stackBuildDocTarget - , stackHieTarget (last hieVersions) - , emptyTarget - , ( "cabal-ghcs" - , "Show all GHC versions that can be installed via `cabal-build` and `cabal-build-all`." - ) - , cabalBuildTarget - , cabalBuildAllTarget - -- , cabalHieTarget mostRecentHieVersion - , cabalBuildDocTarget - , cabalHieTarget (last hieVersions) - ] - - -helpMessage :: Action () -helpMessage = do - - hieVersions <- getHieVersions - scriptName <- liftIO getProgName - out "" - out "Usage:" - out' ("stack " <> scriptName <> " ") - out "" - out "Targets:" - mapM_ (out' . showTarget (spaces hieVersions)) (targets hieVersions) - out "" - where - out = liftIO . putStrLn - out' = out . (" " ++) - - spaces hieVersions = space (targets hieVersions) - -- All targets the shake file supports - targets :: [VersionNumber] -> [(String, String)] - targets hieVersions = intercalate - [emptyTarget] - [ generalTargets - , stackTargets hieVersions - , cabalTargets hieVersions - , macosTargets - ] - - -- All targets with their respective help message. - generalTargets = - [ ("help", "Show help message including all targets") - , ( "cabal" - , "Makes sure that Cabal the lib is available for cabal-helper-wapper, to speed up project start" - ) - ] - - macosTargets = [("icu-macos-fix", "Fixes icu related problems in MacOS")] - - stackTargets hieVersions = - [ ( "build" - , "Builds hie for all supported GHC versions (" - ++ allVersionMessage hieVersions - ++ ")" - ) - , stackBuildAllTarget - , stackBuildDocTarget - , ("test", "Runs hie tests with stack") - ] - ++ map stackHieTarget hieVersions - - cabalTargets hieVersions = - [ ( "cabal-ghcs" - , "Show all GHC versions that can be installed via `cabal-build` and `cabal-build-all`." - ) - , cabalBuildTarget - , cabalBuildAllTarget - , cabalBuildDocTarget - , ("cabal-test", "Runs hie tests with cabal") - ] - ++ map cabalHieTarget hieVersions - --- | Empty target. Purpose is to introduce a newline between the targets -emptyTarget :: (String, String) -emptyTarget = ("", "") - --- | Target for a specific ghc version -stackHieTarget :: String -> TargetDescription -stackHieTarget version = - ( "hie-" ++ version - , "Builds hie for GHC version " ++ version ++ " only with stack" - ) - --- | Target for a specific ghc version -cabalHieTarget :: String -> TargetDescription -cabalHieTarget version = - ( "cabal-hie-" ++ version - , "Builds hie for GHC version " ++ version ++ " only with cabal new-build" - ) - -stackBuildDocTarget :: TargetDescription -stackBuildDocTarget = ("build-doc", "Builds the Hoogle database") - -stackBuildAllTarget :: TargetDescription -stackBuildAllTarget = - ( "build-all" - , "Builds hie for all supported GHC versions and the hoogle database" - ) - -cabalBuildTarget :: TargetDescription -cabalBuildTarget = - ("cabal-build", "Builds hie with cabal with all installed GHCs.") - -cabalBuildDocTarget :: TargetDescription -cabalBuildDocTarget = - ("cabal-build-doc", "Builds the Hoogle database with cabal") - -cabalBuildAllTarget :: TargetDescription -cabalBuildAllTarget = - ( "cabal-build-all" - , "Builds hie for all installed GHC versions and the hoogle database with cabal" - ) - --- | Creates a message of the form "a, b, c and d", where a,b,c,d are GHC versions. --- If there is no GHC in the list of `hieVersions` -allVersionMessage :: [String] -> String -allVersionMessage wordList = case wordList of - [] -> "" - [a] -> show a - (a : as) -> - let msg = intersperse ", " wordList - lastVersion = last msg - in concat $ init (init msg) ++ [" and ", lastVersion] - - --- | Get the path to the GHC compiler executable linked to the local `stack-$GHCVER.yaml`. --- Equal to the command `stack path --stack-yaml $stack-yaml --compiler-exe`. --- This might install a GHC if it is not already installed, thus, might fail if stack fails to install the GHC. -getStackGhcPath :: VersionNumber -> Action GhcPath -getStackGhcPath ghcVersion = do - Stdout ghc <- execStackWithGhc ghcVersion ["path", "--compiler-exe"] - return $ trim ghc - --- | Read the local install root of the stack project specified by the VersionNumber --- Returns the filepath of the local install root. --- Equal to the command `stack path --local-install-root` -getLocalInstallRoot :: VersionNumber -> Action FilePath -getLocalInstallRoot hieVersion = do - Stdout localInstallRoot' <- execStackWithGhc - hieVersion - ["path", "--local-install-root"] - return $ trim localInstallRoot' - --- |Stack build fails message -stackBuildFailMsg :: String -stackBuildFailMsg = - embedInStars - $ "Building failed, " - ++ "Try running `stack clean` and restart the build\n" - ++ "If this does not work, open an issue at \n" - ++ "\thttps://github.com/haskell/haskell-ide-engine" diff --git a/install/src/Print.hs b/install/src/Print.hs index 6fbb667dd..6ae7c4946 100644 --- a/install/src/Print.hs +++ b/install/src/Print.hs @@ -8,6 +8,12 @@ import Data.List ( dropWhileEnd ) import Data.Char ( isSpace ) +out :: MonadIO m => String -> m () +out = liftIO . putStrLn + +out' :: MonadIO m => String -> m () +out' = out . (" " ++) + embedInStars :: String -> String embedInStars str = let starsLine = "\n" <> replicate 30 '*' <> "\n" diff --git a/install/src/Stack.hs b/install/src/Stack.hs index 74d00d8c1..292b5a18b 100644 --- a/install/src/Stack.hs +++ b/install/src/Stack.hs @@ -2,10 +2,33 @@ module Stack where import Development.Shake import Development.Shake.Command +import Development.Shake.FilePath import Control.Monad import Version import Print +import Env + + +stackBuildHie :: VersionNumber -> Action () +stackBuildHie versionNumber = execStackWithGhc_ versionNumber ["build"] + `actionOnException` liftIO (putStrLn stackBuildFailMsg) + +-- | copy the built binaries into the localBinDir +stackInstallHie :: VersionNumber -> Action () +stackInstallHie versionNumber = do + execStackWithGhc_ versionNumber ["install"] + localBinDir <- getLocalBin + let hie = "hie" <.> exe + copyFile' (localBinDir hie) + (localBinDir "hie-" ++ versionNumber <.> exe) + copyFile' (localBinDir hie) + (localBinDir "hie-" ++ dropExtension versionNumber <.> exe) + +buildCopyCompilerTool :: VersionNumber -> Action () +buildCopyCompilerTool versionNumber = + execStackWithGhc_ versionNumber ["build", "--copy-compiler-tool"] + -- | check `stack` has the required version checkStack :: Action () @@ -22,6 +45,10 @@ getLocalBin = do Stdout stackLocalDir' <- execStackShake ["path", "--local-bin"] return $ trim stackLocalDir' +stackBuildData :: Action () +stackBuildData = do + execStackShake_ ["build", "hoogle"] + execStackShake_ ["exec", "hoogle", "generate"] -- | Execute a stack command for a specified ghc, discarding the output execStackWithGhc_ :: VersionNumber -> [String] -> Action () @@ -58,3 +85,12 @@ stackExeIsOldFailMsg stackVersion = requiredStackVersion :: RequiredVersion requiredStackVersion = [1, 9, 3] + +-- |Stack build fails message +stackBuildFailMsg :: String +stackBuildFailMsg = + embedInStars + $ "Building failed, " + ++ "Try running `stack clean` and restart the build\n" + ++ "If this does not work, open an issue at \n" + ++ "\thttps://github.com/haskell/haskell-ide-engine" From e0e8a07afdde2198a072de2428909ee95f1a2402 Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Sun, 16 Jun 2019 22:46:08 +0200 Subject: [PATCH 118/158] upgrade shake --- install/hie-install.cabal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/hie-install.cabal b/install/hie-install.cabal index cf28c517e..87983ec57 100644 --- a/install/hie-install.cabal +++ b/install/hie-install.cabal @@ -19,7 +19,7 @@ library , Env , Help build-depends: base >= 4.9 && < 5 - , shake == 0.17.3 + , shake == 0.17.8 , directory , extra , text From 4167153509c7babab4678b945c3dcce27a01dbbb Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Tue, 25 Jun 2019 18:08:29 +0200 Subject: [PATCH 119/158] include work of #1297 into this project --- install/src/Cabal.hs | 2 +- install/src/Env.hs | 40 +++++++++++++++++++++++++++------------- install/src/Install.hs | 4 +++- 3 files changed, 31 insertions(+), 15 deletions(-) diff --git a/install/src/Cabal.hs b/install/src/Cabal.hs index 91acdc861..db6bf1b3a 100644 --- a/install/src/Cabal.hs +++ b/install/src/Cabal.hs @@ -27,7 +27,7 @@ cabalBuildData = do cabalBuildHie :: VersionNumber -> Action () cabalBuildHie versionNumber = do - ghcPath <- getGhcPath versionNumber >>= \case + ghcPath <- getGhcPathOf versionNumber >>= \case Nothing -> do printInStars $ ghcVersionNotFoundFailMsg versionNumber error (ghcVersionNotFoundFailMsg versionNumber) diff --git a/install/src/Env.hs b/install/src/Env.hs index eca37ee62..b7d232c37 100644 --- a/install/src/Env.hs +++ b/install/src/Env.hs @@ -10,10 +10,16 @@ import System.Info ( os ) import Data.Maybe ( isJust ) import System.Directory ( findExecutable + , findExecutables , listDirectory ) -import Data.Function ( (&) ) -import Data.List ( sort ) +import Data.Function ( (&) + , on + ) +import Data.List ( sort + , isInfixOf + , nubBy + ) import Control.Monad.Extra ( mapMaybeM ) import Data.Maybe ( isNothing , mapMaybe @@ -37,29 +43,37 @@ isWindowsSystem = os `elem` ["mingw32", "win32"] findInstalledGhcs :: IO [(VersionNumber, GhcPath)] findInstalledGhcs = do hieVersions <- getHieVersions :: IO [VersionNumber] - mapMaybeM - (\version -> getGhcPath version >>= \case + knownGhcs <- mapMaybeM + (\version -> getGhcPathOf version >>= \case Nothing -> return Nothing Just p -> return $ Just (version, p) ) (reverse hieVersions) + availableGhcs <- getGhcPaths + return + -- nub by version. knownGhcs takes precedence. + $ nubBy ((==) `on` fst) + -- filter out stack provided GHCs + $ filter (not . isInfixOf ".stack" . snd) (knownGhcs ++ availableGhcs) -- | Get the path to a GHC that has the version specified by `VersionNumber` -- If no such GHC can be found, Nothing is returned. -- First, it is checked whether there is a GHC with the name `ghc-$VersionNumber`. -- If this yields no result, it is checked, whether the numeric-version of the `ghc` -- command fits to the desired version. -getGhcPath :: MonadIO m => VersionNumber -> m (Maybe GhcPath) -getGhcPath ghcVersion = +getGhcPathOf :: MonadIO m => VersionNumber -> m (Maybe GhcPath) +getGhcPathOf ghcVersion = liftIO $ findExecutable ("ghc-" ++ ghcVersion) >>= \case - Nothing -> do - findExecutable "ghc" >>= \case - Nothing -> return Nothing - Just p -> do - Stdout version <- cmd p ["--numeric-version"] :: IO (Stdout String) - if ghcVersion == trim version then return $ Just p else return Nothing - p -> return p + Nothing -> lookup ghcVersion <$> getGhcPaths + path -> return path +-- | Get a list of GHCs that are available in $PATH +getGhcPaths :: MonadIO m => m [(VersionNumber, GhcPath)] +getGhcPaths = liftIO $ do + paths <- findExecutables "ghc" + forM paths $ \path -> do + Stdout version <- cmd path ["--numeric-version"] + return (trim version, path) -- | No suitable ghc version has been found. Show a message. ghcVersionNotFoundFailMsg :: VersionNumber -> String diff --git a/install/src/Install.hs b/install/src/Install.hs index 46f1e0da9..aebdcc509 100644 --- a/install/src/Install.hs +++ b/install/src/Install.hs @@ -47,9 +47,11 @@ defaultMain = do -- unset GHC_PACKAGE_PATH for cabal unsetEnv "GHC_PACKAGE_PATH" + -- used for cabal-based targets ghcPaths <- findInstalledGhcs let ghcVersions = map fst ghcPaths + -- used for stack-based targets hieVersions <- getHieVersions putStrLn $ "run from: " ++ buildSystem @@ -110,7 +112,7 @@ defaultMain = do need ["cabal"] cabalBuildData forM_ - hieVersions + ghcVersions (\version -> phony ("cabal-hie-" ++ version) $ do validateCabalNewInstallIsSupported need ["submodules"] From 39e5c3c3a8a984ade1e1e605a2ef0b2fb2949d4f Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Wed, 26 Jun 2019 01:25:59 +0200 Subject: [PATCH 120/158] use strict copyFile function for hie-x.y binaries --- install/src/Cabal.hs | 13 ++++++++----- install/src/Stack.hs | 12 +++++++----- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/install/src/Cabal.hs b/install/src/Cabal.hs index db6bf1b3a..d6e82e054 100644 --- a/install/src/Cabal.hs +++ b/install/src/Cabal.hs @@ -6,7 +6,9 @@ import Development.Shake.FilePath import Control.Monad import Data.Maybe ( isNothing ) import Control.Monad.Extra ( whenMaybe ) -import System.Directory ( findExecutable ) +import System.Directory ( findExecutable + , copyFile + ) import Version import Print @@ -45,10 +47,11 @@ cabalInstallHie versionNumber = do , "exe:hie" , "--overwrite-policy=always" ] - copyFile' (localBin "hie" <.> exe) - (localBin "hie-" ++ versionNumber <.> exe) - copyFile' (localBin "hie" <.> exe) - (localBin "hie-" ++ dropExtension versionNumber <.> exe) + liftIO $ do + copyFile (localBin "hie" <.> exe) + (localBin "hie-" ++ versionNumber <.> exe) + copyFile (localBin "hie" <.> exe) + (localBin "hie-" ++ dropExtension versionNumber <.> exe) -- TODO: review installCabal :: Action () diff --git a/install/src/Stack.hs b/install/src/Stack.hs index 292b5a18b..11470d079 100644 --- a/install/src/Stack.hs +++ b/install/src/Stack.hs @@ -4,6 +4,7 @@ import Development.Shake import Development.Shake.Command import Development.Shake.FilePath import Control.Monad +import System.Directory ( copyFile ) import Version import Print @@ -18,12 +19,13 @@ stackBuildHie versionNumber = execStackWithGhc_ versionNumber ["build"] stackInstallHie :: VersionNumber -> Action () stackInstallHie versionNumber = do execStackWithGhc_ versionNumber ["install"] - localBinDir <- getLocalBin + localBinDir <- getLocalBin let hie = "hie" <.> exe - copyFile' (localBinDir hie) - (localBinDir "hie-" ++ versionNumber <.> exe) - copyFile' (localBinDir hie) - (localBinDir "hie-" ++ dropExtension versionNumber <.> exe) + liftIO $ do + copyFile (localBinDir hie) + (localBinDir "hie-" ++ versionNumber <.> exe) + copyFile (localBinDir hie) + (localBinDir "hie-" ++ dropExtension versionNumber <.> exe) buildCopyCompilerTool :: VersionNumber -> Action () buildCopyCompilerTool versionNumber = From d670f5a9bd4749eacd47600f6533dc743a61c1b4 Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Thu, 27 Jun 2019 17:37:12 +0200 Subject: [PATCH 121/158] move shake.* files into install/ folder --- .gitignore | 1 + install/shake.project | 2 ++ shake.yaml => install/shake.yaml | 2 +- shake.project | 2 -- 4 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 install/shake.project rename shake.yaml => install/shake.yaml (94%) delete mode 100644 shake.project diff --git a/.gitignore b/.gitignore index 90a09f165..144edde75 100644 --- a/.gitignore +++ b/.gitignore @@ -73,3 +73,4 @@ _build/ # stack 2.1 stack.yaml lock files stack*.yaml.lock +shake.yaml.lock diff --git a/install/shake.project b/install/shake.project new file mode 100644 index 000000000..43c7e6072 --- /dev/null +++ b/install/shake.project @@ -0,0 +1,2 @@ +packages: + install/ diff --git a/shake.yaml b/install/shake.yaml similarity index 94% rename from shake.yaml rename to install/shake.yaml index b77f32905..e684d5cee 100644 --- a/shake.yaml +++ b/install/shake.yaml @@ -1,7 +1,7 @@ # Used to provide a different environment for the shake build script resolver: lts-13.18 # GHC 8.6.4 packages: -- install +- . nix: packages: [ zlib ] diff --git a/shake.project b/shake.project deleted file mode 100644 index 94f06ec7e..000000000 --- a/shake.project +++ /dev/null @@ -1,2 +0,0 @@ -packages: - install From 9b351945583646318ffedf961d5df3a52fa41f9a Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Thu, 27 Jun 2019 17:58:27 +0200 Subject: [PATCH 122/158] correct help message to show only available ghcs for cabal --- install/hie-install.cabal | 1 + install/src/Help.hs | 48 +++++++++++++++++++++++---------------- install/src/Install.hs | 9 +++++--- 3 files changed, 36 insertions(+), 22 deletions(-) diff --git a/install/hie-install.cabal b/install/hie-install.cabal index 87983ec57..269a07819 100644 --- a/install/hie-install.cabal +++ b/install/hie-install.cabal @@ -25,6 +25,7 @@ library , text default-extensions: LambdaCase , TupleSections + , RecordWildCards default-language: Haskell2010 if flag(run-from-stack) diff --git a/install/src/Help.hs b/install/src/Help.hs index 1cdcc58ec..fff5aa01a 100644 --- a/install/src/Help.hs +++ b/install/src/Help.hs @@ -6,9 +6,10 @@ import Data.List ( intersperse , intercalate ) -import Env -import Print -import Version +import Env +import Print +import Version +import BuildSystem printUsage :: Action () printUsage = do @@ -39,26 +40,35 @@ shortHelpMessage = do , cabalGhcsTarget ] +-- | A record that specifies for each build system which versions of @hie@ can be built. +data BuildableVersions = BuildableVersions + { stackVersions :: [VersionNumber] + , cabalVersions :: [VersionNumber] + } +getDefaultBuildSystemVersions :: BuildableVersions -> [VersionNumber] +getDefaultBuildSystemVersions BuildableVersions{..} + | isRunFromStack = stackVersions + | isRunFromCabal = cabalVersions + | otherwise = error $ "unknown build system: " ++ buildSystem -helpMessage :: Action () -helpMessage = do - hieVersions <- getHieVersions +helpMessage :: BuildableVersions -> Action () +helpMessage versions@BuildableVersions{..} = do printUsage out "" out "Targets:" - mapM_ (out' . showTarget (spaces hieVersions)) (targets hieVersions) + mapM_ (out' . showTarget spaces) targets out "" where - spaces hieVersions = space (targets hieVersions) + spaces = space targets -- All targets the shake file supports - targets :: [VersionNumber] -> [(String, String)] - targets hieVersions = intercalate + targets :: [(String, String)] + targets = intercalate [emptyTarget] [ generalTargets - , defaultTargets hieVersions - , stackTargets hieVersions - , cabalTargets hieVersions + , defaultTargets + , stackTargets + , cabalTargets , [macosIcuTarget] ] @@ -67,27 +77,27 @@ helpMessage = do [ helpTarget ] - defaultTargets hieVersions = + defaultTargets = [ buildTarget , buildAllTarget , buildDataTarget ] - ++ map hieTarget hieVersions + ++ map hieTarget (getDefaultBuildSystemVersions versions) - stackTargets hieVersions = + stackTargets = [ stackTarget buildTarget , stackTarget buildAllTarget , stackTarget buildDataTarget ] - ++ map (stackTarget . hieTarget) hieVersions + ++ map (stackTarget . hieTarget) stackVersions - cabalTargets hieVersions = + cabalTargets = [ cabalGhcsTarget , cabalTarget buildTarget , cabalTarget buildAllTarget , cabalTarget buildDataTarget ] - ++ map (cabalTarget . hieTarget) hieVersions + ++ map (cabalTarget . hieTarget) cabalVersions -- | Empty target. Purpose is to introduce a newline between the targets emptyTarget :: (String, String) diff --git a/install/src/Install.hs b/install/src/Install.hs index aebdcc509..857306b37 100644 --- a/install/src/Install.hs +++ b/install/src/Install.hs @@ -10,8 +10,7 @@ import Control.Monad.Extra ( unlessM ) import Data.Maybe ( isJust ) import System.Directory ( listDirectory ) -import System.Environment ( unsetEnv - ) +import System.Environment ( unsetEnv ) import System.Info ( os , arch ) @@ -54,6 +53,10 @@ defaultMain = do -- used for stack-based targets hieVersions <- getHieVersions + let versions = BuildableVersions { stackVersions = hieVersions + , cabalVersions = ghcVersions + } + putStrLn $ "run from: " ++ buildSystem shakeArgs shakeOptions { shakeFiles = "_build" } $ do @@ -63,7 +66,7 @@ defaultMain = do phony "cabal" installCabal phony "short-help" shortHelpMessage phony "all" shortHelpMessage - phony "help" helpMessage + phony "help" (helpMessage versions) phony "check-stack" checkStack phony "check-cabal" checkCabal From 71cbab17ec6a562a852140629f9acaad6dfdb04c Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Thu, 27 Jun 2019 18:03:25 +0200 Subject: [PATCH 123/158] apply brittany reformat --- install/src/Help.hs | 45 +++++++++++++++++--------------------------- install/src/Print.hs | 2 +- 2 files changed, 18 insertions(+), 29 deletions(-) diff --git a/install/src/Help.hs b/install/src/Help.hs index fff5aa01a..1e6debe7c 100644 --- a/install/src/Help.hs +++ b/install/src/Help.hs @@ -47,13 +47,13 @@ data BuildableVersions = BuildableVersions } getDefaultBuildSystemVersions :: BuildableVersions -> [VersionNumber] -getDefaultBuildSystemVersions BuildableVersions{..} +getDefaultBuildSystemVersions BuildableVersions {..} | isRunFromStack = stackVersions | isRunFromCabal = cabalVersions - | otherwise = error $ "unknown build system: " ++ buildSystem + | otherwise = error $ "unknown build system: " ++ buildSystem helpMessage :: BuildableVersions -> Action () -helpMessage versions@BuildableVersions{..} = do +helpMessage versions@BuildableVersions {..} = do printUsage out "" out "Targets:" @@ -63,7 +63,7 @@ helpMessage versions@BuildableVersions{..} = do spaces = space targets -- All targets the shake file supports targets :: [(String, String)] - targets = intercalate + targets = intercalate [emptyTarget] [ generalTargets , defaultTargets @@ -73,30 +73,24 @@ helpMessage versions@BuildableVersions{..} = do ] -- All targets with their respective help message. - generalTargets = - [ helpTarget - ] + generalTargets = [helpTarget] - defaultTargets = - [ buildTarget - , buildAllTarget - , buildDataTarget - ] - ++ map hieTarget (getDefaultBuildSystemVersions versions) + defaultTargets = [buildTarget, buildAllTarget, buildDataTarget] + ++ map hieTarget (getDefaultBuildSystemVersions versions) stackTargets = [ stackTarget buildTarget - , stackTarget buildAllTarget - , stackTarget buildDataTarget - ] + , stackTarget buildAllTarget + , stackTarget buildDataTarget + ] ++ map (stackTarget . hieTarget) stackVersions cabalTargets = [ cabalGhcsTarget - , cabalTarget buildTarget - , cabalTarget buildAllTarget - , cabalTarget buildDataTarget - ] + , cabalTarget buildTarget + , cabalTarget buildAllTarget + , cabalTarget buildDataTarget + ] ++ map (cabalTarget . hieTarget) cabalVersions -- | Empty target. Purpose is to introduce a newline between the targets @@ -115,13 +109,10 @@ cabalTarget = targetWithBuildSystem "cabal" hieTarget :: String -> TargetDescription hieTarget version = - ( "hie-" ++ version - , "Builds hie for GHC version " ++ version - ) + ("hie-" ++ version, "Builds hie for GHC version " ++ version) buildTarget :: TargetDescription -buildTarget = - ("build", "Builds hie with all installed GHCs") +buildTarget = ("build", "Builds hie with all installed GHCs") buildDataTarget :: TargetDescription buildDataTarget = @@ -129,9 +120,7 @@ buildDataTarget = buildAllTarget :: TargetDescription buildAllTarget = - ( "build-all" - , "Builds hie for all installed GHC versions and the data files" - ) + ("build-all", "Builds hie for all installed GHC versions and the data files") -- speical targets diff --git a/install/src/Print.hs b/install/src/Print.hs index 6ae7c4946..8e308d62e 100644 --- a/install/src/Print.hs +++ b/install/src/Print.hs @@ -9,7 +9,7 @@ import Data.List ( dropWhileEnd import Data.Char ( isSpace ) out :: MonadIO m => String -> m () -out = liftIO . putStrLn +out = liftIO . putStrLn out' :: MonadIO m => String -> m () out' = out . (" " ++) From f07ad7ca3937a260be507c421fd2523e0f432657 Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Thu, 27 Jun 2019 18:05:15 +0200 Subject: [PATCH 124/158] add cabal.project to install-dir --- install/cabal.project | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 install/cabal.project diff --git a/install/cabal.project b/install/cabal.project new file mode 100644 index 000000000..a14a803d4 --- /dev/null +++ b/install/cabal.project @@ -0,0 +1,2 @@ +packages: + ./ From 7fad241883f01afc5bc44164fc361123b87ac431 Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Thu, 27 Jun 2019 18:55:38 +0200 Subject: [PATCH 125/158] add documentation to install-helper-functions --- install/src/Help.hs | 26 +++++++++++++------------- install/src/Print.hs | 10 ++++++---- install/src/Version.hs | 2 +- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/install/src/Help.hs b/install/src/Help.hs index 1e6debe7c..c9ec690f4 100644 --- a/install/src/Help.hs +++ b/install/src/Help.hs @@ -13,21 +13,21 @@ import BuildSystem printUsage :: Action () printUsage = do - out "" - out "Usage:" - out' ("stack install.hs ") - out' "or" - out' ("cabal new-run install.hs --project-file shake.project ") + printLine "" + printLine "Usage:" + printLineIndented ("stack install.hs ") + printLineIndented "or" + printLineIndented ("cabal new-run install.hs --project-file shake.project ") -- | short help message is printed by default shortHelpMessage :: Action () shortHelpMessage = do hieVersions <- getHieVersions printUsage - out "" - out "Targets:" - mapM_ (out' . showTarget (spaces hieVersions)) (targets hieVersions) - out "" + printLine "" + printLine "Targets:" + mapM_ (printLineIndented . showTarget (spaces hieVersions)) (targets hieVersions) + printLine "" where spaces hieVersions = space (targets hieVersions) targets hieVersions = @@ -55,10 +55,10 @@ getDefaultBuildSystemVersions BuildableVersions {..} helpMessage :: BuildableVersions -> Action () helpMessage versions@BuildableVersions {..} = do printUsage - out "" - out "Targets:" - mapM_ (out' . showTarget spaces) targets - out "" + printLine "" + printLine "Targets:" + mapM_ (printLineIndented . showTarget spaces) targets + printLine "" where spaces = space targets -- All targets the shake file supports diff --git a/install/src/Print.hs b/install/src/Print.hs index 8e308d62e..82904491f 100644 --- a/install/src/Print.hs +++ b/install/src/Print.hs @@ -8,11 +8,13 @@ import Data.List ( dropWhileEnd ) import Data.Char ( isSpace ) -out :: MonadIO m => String -> m () -out = liftIO . putStrLn +-- | lift putStrLn to MonadIO +printLine :: MonadIO m => String -> m () +printLine = liftIO . putStrLn -out' :: MonadIO m => String -> m () -out' = out . (" " ++) +-- | print a line prepended with 4 spaces +printLineIndented :: MonadIO m => String -> m () +printLineIndented = printLine . (" " ++) embedInStars :: String -> String embedInStars str = diff --git a/install/src/Version.hs b/install/src/Version.hs index de9bfd019..0d89b4b95 100644 --- a/install/src/Version.hs +++ b/install/src/Version.hs @@ -19,6 +19,6 @@ versionToString = showVersion . makeVersion parseVersionEx :: String -> Version parseVersionEx = fst . head . filter (("" ==) . snd) . readP_to_S parseVersion - +-- | Check that a given version-string is not smaller than the required version checkVersion :: RequiredVersion -> String -> Bool checkVersion required given = parseVersionEx given >= makeVersion required From edb411ca136b9a43b5cfd9697ddfd783197a2075 Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Fri, 28 Jun 2019 15:35:12 +0200 Subject: [PATCH 126/158] let stack use moved shake.yaml in install.hs --- install/src/Install.hs | 2 +- install/src/Stack.hs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/install/src/Install.hs b/install/src/Install.hs index 857306b37..9b088200e 100644 --- a/install/src/Install.hs +++ b/install/src/Install.hs @@ -85,7 +85,7 @@ defaultMain = do phony "build-all" $ need [buildSystem ++ "-build-all"] phony "build-data" $ need [buildSystem ++ "-build-data"] forM_ - hieVersions + (getDefaultBuildSystemVersions versions) (\version -> phony ("hie-" ++ version) $ need [buildSystem ++ "-hie-" ++ version] ) diff --git a/install/src/Stack.hs b/install/src/Stack.hs index 11470d079..a2c351333 100644 --- a/install/src/Stack.hs +++ b/install/src/Stack.hs @@ -66,11 +66,11 @@ execStackWithGhc versionNumber args = do -- | Execute a stack command with the same resolver as the build script execStackShake :: CmdResult r => [String] -> Action r -execStackShake args = command [] "stack" ("--stack-yaml=shake.yaml" : args) +execStackShake args = command [] "stack" ("--stack-yaml=install/shake.yaml" : args) -- | Execute a stack command with the same resolver as the build script, discarding the output execStackShake_ :: [String] -> Action () -execStackShake_ args = command_ [] "stack" ("--stack-yaml=shake.yaml" : args) +execStackShake_ args = command_ [] "stack" ("--stack-yaml=install/shake.yaml" : args) -- | Error message when the `stack` binary is an older version From aa49439c4a4992bbc8e1a0f5cbf954e134d1e38c Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Fri, 28 Jun 2019 17:04:54 +0200 Subject: [PATCH 127/158] increase max-backjumps when building `hie` with cabal --- install/src/Cabal.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/src/Cabal.hs b/install/src/Cabal.hs index d6e82e054..7d6314504 100644 --- a/install/src/Cabal.hs +++ b/install/src/Cabal.hs @@ -35,7 +35,7 @@ cabalBuildHie versionNumber = do error (ghcVersionNotFoundFailMsg versionNumber) Just p -> return p execCabal_ - ["new-build", "-w", ghcPath, "--write-ghc-environment-files=never"] + ["new-build", "-w", ghcPath, "--write-ghc-environment-files=never", "--max-backjumps=5000"] cabalInstallHie :: VersionNumber -> Action () cabalInstallHie versionNumber = do From 385de659d728d4a6a8fe7d84e854aad5b688df66 Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Sat, 29 Jun 2019 16:43:15 +0200 Subject: [PATCH 128/158] document running install.hs from cabal in readme --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index 7f847268e..fd38d53f2 100644 --- a/README.md +++ b/README.md @@ -201,6 +201,18 @@ stack ./install.hs help Remember, this will take time to download a Stackage-LTS and an appropriate GHC. However, afterwards all commands should work as expected. +##### Install via cabal + +The install-script can be invoked via `cabal` instead of `stack` with the command + +```bash +cabal v2-run ./install.hs --project-file install/shake.project +``` + +Unfortunalely, it is still required to have `stack` installed so that the install-script can locate the `local-bin` directory (on Linux `~/.local/bin`) and copy the the `hie` binaries to `hie-x.y.z`, which is required for the `hie-wrapper` to function as expected. + +For briefty, only the `stack`-based commands are presented in the following sections. + ##### Install specific GHC Version Install **Nightly** (and hoogle docs): From 8d10d6e2812a07892565d6da08fed755579a97d2 Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Sun, 30 Jun 2019 09:13:21 +0200 Subject: [PATCH 129/158] fix typos in readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fd38d53f2..3c3878048 100644 --- a/README.md +++ b/README.md @@ -209,9 +209,9 @@ The install-script can be invoked via `cabal` instead of `stack` with the comman cabal v2-run ./install.hs --project-file install/shake.project ``` -Unfortunalely, it is still required to have `stack` installed so that the install-script can locate the `local-bin` directory (on Linux `~/.local/bin`) and copy the the `hie` binaries to `hie-x.y.z`, which is required for the `hie-wrapper` to function as expected. +Unfortunately, it is still required to have `stack` installed so that the install-script can locate the `local-bin` directory (on Linux `~/.local/bin`) and copy the the `hie` binaries to `hie-x.y.z`, which is required for the `hie-wrapper` to function as expected. -For briefty, only the `stack`-based commands are presented in the following sections. +For brevity, only the `stack`-based commands are presented in the following sections. ##### Install specific GHC Version From 109df6011fafe83d5ff857af7d44cd8d2989e87a Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Mon, 1 Jul 2019 00:30:36 +0200 Subject: [PATCH 130/158] remove todo for review --- install/src/Cabal.hs | 1 - 1 file changed, 1 deletion(-) diff --git a/install/src/Cabal.hs b/install/src/Cabal.hs index 7d6314504..c09527505 100644 --- a/install/src/Cabal.hs +++ b/install/src/Cabal.hs @@ -53,7 +53,6 @@ cabalInstallHie versionNumber = do copyFile (localBin "hie" <.> exe) (localBin "hie-" ++ dropExtension versionNumber <.> exe) --- TODO: review installCabal :: Action () installCabal = do -- try to find existing `cabal` executable with appropriate version From 8346b7fdfdd348ec2501872f35eef3c4e72d21cd Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Mon, 1 Jul 2019 06:53:36 +0200 Subject: [PATCH 131/158] rename module Install to HieInstall in hie-install now, tests should work on windows --- install.hs | 2 +- install/hie-install.cabal | 2 +- install/src/Cabal.hs | 1 + install/src/{Install.hs => HieInstall.hs} | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) rename install/src/{Install.hs => HieInstall.hs} (99%) diff --git a/install.hs b/install.hs index 782c4a5ed..b68745bd3 100755 --- a/install.hs +++ b/install.hs @@ -15,6 +15,6 @@ build-depends: -- TODO: set `shake.project` in cabal-config above, when supported -import Install (defaultMain) +import HieInstall (defaultMain) main = defaultMain diff --git a/install/hie-install.cabal b/install/hie-install.cabal index 269a07819..287b56f6a 100644 --- a/install/hie-install.cabal +++ b/install/hie-install.cabal @@ -10,7 +10,7 @@ cabal-version: >=2.0 library hs-source-dirs: src - exposed-modules: Install + exposed-modules: HieInstall other-modules: BuildSystem , Stack , Version diff --git a/install/src/Cabal.hs b/install/src/Cabal.hs index c09527505..7d6314504 100644 --- a/install/src/Cabal.hs +++ b/install/src/Cabal.hs @@ -53,6 +53,7 @@ cabalInstallHie versionNumber = do copyFile (localBin "hie" <.> exe) (localBin "hie-" ++ dropExtension versionNumber <.> exe) +-- TODO: review installCabal :: Action () installCabal = do -- try to find existing `cabal` executable with appropriate version diff --git a/install/src/Install.hs b/install/src/HieInstall.hs similarity index 99% rename from install/src/Install.hs rename to install/src/HieInstall.hs index 9b088200e..3f89e0dc5 100644 --- a/install/src/Install.hs +++ b/install/src/HieInstall.hs @@ -1,4 +1,4 @@ -module Install where +module HieInstall where import Development.Shake import Development.Shake.Command From 84baa246bdd62003126abd0aed33eacd98bf7858 Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Mon, 1 Jul 2019 07:01:51 +0200 Subject: [PATCH 132/158] add a testrun of install.hs to ci --- .azure/windows-installhs-stack.yml | 30 ++++++++++++++++++++++++++++++ azure-pipelines.yml | 2 ++ 2 files changed, 32 insertions(+) create mode 100644 .azure/windows-installhs-stack.yml diff --git a/.azure/windows-installhs-stack.yml b/.azure/windows-installhs-stack.yml new file mode 100644 index 000000000..3fab9d640 --- /dev/null +++ b/.azure/windows-installhs-stack.yml @@ -0,0 +1,30 @@ +jobs: +- job: Windows_installhs_Stack + timeoutInMinutes: 0 + pool: + vmImage: windows-2019 + strategy: + matrix: + shake: + YAML_FILE: install/shake.yaml + steps: + - bash: | + curl -sSkL http://www.stackage.org/stack/windows-x86_64 -o /usr/bin/stack.zip + unzip -o /usr/bin/stack.zip -d /usr/bin/ + displayName: Install stack + - bash: | + source .azure/windows.bashrc + stack setup --stack-yaml $(YAML_FILE) + displayName: Install GHC + - bash: | + source .azure/windows.bashrc + stack --stack-yaml $(YAML_FILE) --install-ghc build --only-dependencies + displayName: Build dependencies + - bash: | + source .azure/windows.bashrc + stack build --stack-yaml $(YAML_FILE) + displayName: Build `hie-install` + - bash: | + source .azure/windows.bashrc + stack install.hs help + displayName: Run help of `instal.hs` diff --git a/azure-pipelines.yml b/azure-pipelines.yml index a78fae1c9..4eae53800 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -2,3 +2,5 @@ jobs: - template: ./.azure/linux-stack.yml - template: ./.azure/windows-stack.yml - template: ./.azure/macos-stack.yml +- template: ./.azure/windows-installhs-stack.yml + From 767f467337949dac8174e19a458e7097aac4b449 Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Mon, 1 Jul 2019 13:42:42 +0200 Subject: [PATCH 133/158] remove todo for review --- install/src/Cabal.hs | 1 - 1 file changed, 1 deletion(-) diff --git a/install/src/Cabal.hs b/install/src/Cabal.hs index 7d6314504..c09527505 100644 --- a/install/src/Cabal.hs +++ b/install/src/Cabal.hs @@ -53,7 +53,6 @@ cabalInstallHie versionNumber = do copyFile (localBin "hie" <.> exe) (localBin "hie-" ++ dropExtension versionNumber <.> exe) --- TODO: review installCabal :: Action () installCabal = do -- try to find existing `cabal` executable with appropriate version From a8ae740e974eb49f0efcbc3538cb0219fd88ead4 Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Thu, 11 Jul 2019 20:24:00 +0200 Subject: [PATCH 134/158] add install.hs tests on more plattforms --- .azure/linux-installhs-stack.yml | 32 ++++++++++++++++++++++++++ .azure/macos-installhs-stack.yml | 32 ++++++++++++++++++++++++++ .azure/windows-installhs-cabal.yml | 37 ++++++++++++++++++++++++++++++ azure-pipelines.yml | 3 ++- 4 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 .azure/linux-installhs-stack.yml create mode 100644 .azure/macos-installhs-stack.yml create mode 100644 .azure/windows-installhs-cabal.yml diff --git a/.azure/linux-installhs-stack.yml b/.azure/linux-installhs-stack.yml new file mode 100644 index 000000000..40bdc6424 --- /dev/null +++ b/.azure/linux-installhs-stack.yml @@ -0,0 +1,32 @@ +jobs: +- job: Linux_installhs_Stack + timeoutInMinutes: 0 + pool: + vmImage: ubuntu-16.04 + strategy: + matrix: + shake: + YAML_FILE: install/shake.yaml + steps: + - bash: | + export STACK_ROOT="$(Build.SourcesDirectory)"/.stack-root + mkdir -p ~/.local/bin + curl -L https://get.haskellstack.org/stable/linux-x86_64.tar.gz | \ + tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack' + displayName: Install stack + - bash: | + source .azure/linux.bashrc + stack setup --stack-yaml $(YAML_FILE) + displayName: Install GHC + - bash: | + source .azure/linux.bashrc + stack --stack-yaml $(YAML_FILE) --install-ghc build --only-dependencies + displayName: Build dependencies + - bash: | + source .azure/linux.bashrc + stack build --stack-yaml $(YAML_FILE) + displayName: Build `hie-install` + - bash: | + source .azure/linux.bashrc + stack install.hs help + displayName: Run help of `instal.hs` diff --git a/.azure/macos-installhs-stack.yml b/.azure/macos-installhs-stack.yml new file mode 100644 index 000000000..971b12a23 --- /dev/null +++ b/.azure/macos-installhs-stack.yml @@ -0,0 +1,32 @@ +jobs: +- job: MacOs_installhs_Stack + timeoutInMinutes: 0 + pool: + vmImage: macOS-10.13 + strategy: + matrix: + shake: + YAML_FILE: install/shake.yaml + steps: + - bash: | + export STACK_ROOT="$(Build.SourcesDirectory)"/.stack-root + mkdir -p ~/.local/bin + curl -skL https://get.haskellstack.org/stable/osx-x86_64.tar.gz | \ + tar xz --strip-components=1 --include '*/stack' -C ~/.local/bin; + displayName: Install stack + - bash: | + source .azure/macos.bashrc + stack setup --stack-yaml $(YAML_FILE) + displayName: Install GHC + - bash: | + source .azure/macos.bashrc + stack --stack-yaml $(YAML_FILE) --install-ghc build --only-dependencies + displayName: Build dependencies + - bash: | + source .azure/macos.bashrc + stack build --stack-yaml $(YAML_FILE) + displayName: Build `hie-install` + - bash: | + source .azure/macos.bashrc + stack install.hs help + displayName: Run help of `instal.hs` diff --git a/.azure/windows-installhs-cabal.yml b/.azure/windows-installhs-cabal.yml new file mode 100644 index 000000000..e37d20018 --- /dev/null +++ b/.azure/windows-installhs-cabal.yml @@ -0,0 +1,37 @@ +jobs: +- job: Windows_installhs_Cabal + timeoutInMinutes: 0 + pool: + vmImage: windows-2019 + variables: + YAML_FILE: install/shake.yaml + PROJECT_FILE: install/shake.project + steps: + - bash: | + curl -sSkL http://www.stackage.org/stack/windows-x86_64 -o /usr/bin/stack.zip + unzip -o /usr/bin/stack.zip -d /usr/bin/ + displayName: Install stack + - bash: | + source .azure/windows.bashrc + stack setup --stack-yaml $(YAML_FILE) + displayName: Install GHC + - bash: | + source .azure/windows.bashrc + stack install cabal-install --stack-yaml $(YAML_FILE) + displayName: Install `cabal-install` + - bash: | + source .azure/windows.bashrc + cabal update + displayName: update cabal + # - bash: | + # source .azure/windows.bashrc + # stack --stack-yaml $(YAML_FILE) build --only-dependencies + # displayName: Build dependencies + - bash: | + source .azure/windows.bashrc + cabal v2-build hie-install -w $(stack path --stack-yaml $(YAML_FILE) --compiler-exe) --project-file $(PROJECT_FILE) + displayName: Build `hie-install` + - bash: | + source .azure/windows.bashrc + cabal v2-run install.hs -w $(stack path --stack-yaml $(YAML_FILE) --compiler-exe) --project-file $(PROJECT_FILE) help + displayName: Run help of `install.hs` diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 4eae53800..57aa8497e 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -2,5 +2,6 @@ jobs: - template: ./.azure/linux-stack.yml - template: ./.azure/windows-stack.yml - template: ./.azure/macos-stack.yml +- template: ./.azure/linux-installhs-stack.yml - template: ./.azure/windows-installhs-stack.yml - +- template: ./.azure/macos-installhs-stack.yml From 34f79646b2ec8f9ace476819bb50a385f4ce1fb5 Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Thu, 11 Jul 2019 20:26:08 +0200 Subject: [PATCH 135/158] readme typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3c3878048..b44a50dd1 100644 --- a/README.md +++ b/README.md @@ -209,7 +209,7 @@ The install-script can be invoked via `cabal` instead of `stack` with the comman cabal v2-run ./install.hs --project-file install/shake.project ``` -Unfortunately, it is still required to have `stack` installed so that the install-script can locate the `local-bin` directory (on Linux `~/.local/bin`) and copy the the `hie` binaries to `hie-x.y.z`, which is required for the `hie-wrapper` to function as expected. +Unfortunately, it is still required to have `stack` installed so that the install-script can locate the `local-bin` directory (on Linux `~/.local/bin`) and copy the `hie` binaries to `hie-x.y.z`, which is required for the `hie-wrapper` to function as expected. For brevity, only the `stack`-based commands are presented in the following sections. From 9aa390d95431f19d4172d6f3257adc47a73b73e3 Mon Sep 17 00:00:00 2001 From: Samuel Pilz Date: Thu, 11 Jul 2019 21:20:49 +0200 Subject: [PATCH 136/158] add note that cabal v2-run is not supported on windows --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index b44a50dd1..32025f6d3 100644 --- a/README.md +++ b/README.md @@ -209,6 +209,8 @@ The install-script can be invoked via `cabal` instead of `stack` with the comman cabal v2-run ./install.hs --project-file install/shake.project ``` +Running the script with cabal on windows seems to have some issues and is currently not fully supported. + Unfortunately, it is still required to have `stack` installed so that the install-script can locate the `local-bin` directory (on Linux `~/.local/bin`) and copy the `hie` binaries to `hie-x.y.z`, which is required for the `hie-wrapper` to function as expected. For brevity, only the `stack`-based commands are presented in the following sections. From e6247193dc4e3cb089de7025e956a72496cde1b6 Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Sun, 14 Jul 2019 18:06:41 +0200 Subject: [PATCH 137/158] Update README.md The changes should make it easier for a newcomer to integrate HIE with Vim. The previous version made me think that I as Vim user had to clone the LanguageClient-neovim repo, when in reality vim-plug works just fine to install the plugin. Using vim-plug is arguably easier than cloning the repo and adding it to the runtime path. --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 32025f6d3..35f47fbc7 100644 --- a/README.md +++ b/README.md @@ -360,7 +360,7 @@ in } ``` -Now open a haskell project with Sublime Text. You should have these features available to you: +Now open a Haskell project with Sublime Text. You should have these features available to you: 1. Errors are underlined in red 2. LSP: Show Diagnostics will show a list of hints and errors @@ -371,8 +371,8 @@ Now open a haskell project with Sublime Text. You should have these features ava As above, make sure HIE is installed. These instructions are for using the [LanguageClient-neovim](https://github.com/autozimu/LanguageClient-neovim) client. #### vim-plug -If you use [vim-plug](https://github.com/junegunn/vim-plug), then you can do this by e.g. -including the following line in the Plug section of your `init.vim`: +If you use [vim-plug](https://github.com/junegunn/vim-plug), then you can do this by e.g., +including the following line in the Plug section of your `init.vim` or `~/.vimrc`: ``` Plug 'autozimu/LanguageClient-neovim', { @@ -381,10 +381,10 @@ Plug 'autozimu/LanguageClient-neovim', { \ } ``` -and issuing a `:PlugInstall` command within neovim. +and issuing a `:PlugInstall` command within Neovim or Vim. -#### Vim 8.0 -Clone [LanguageClient-neovim](https://github.com/autozimu/LanguageClient-neovim) +#### Clone the LanguageClient-neovim repo +As an alternative to using [vim-plug](https://github.com/junegunn/vim-plug) shown above, clone [LanguageClient-neovim](https://github.com/autozimu/LanguageClient-neovim) into `~/.vim/pack/XXX/start/`, where `XXX` is just a name for your "plugin suite". #### Sample `~/.vimrc` From 8e44c14f3202bce2e9b331a65d8bb4ad99c9aeb7 Mon Sep 17 00:00:00 2001 From: Zubin Duggal Date: Mon, 15 Jul 2019 16:52:31 +0530 Subject: [PATCH 138/158] fix compilation with hie-plugin-api and remove hare submodules --- hie-plugin-api/Haskell/Ide/Engine/PluginApi.hs | 2 +- stack.yaml | 1 + submodules/HaRe | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/hie-plugin-api/Haskell/Ide/Engine/PluginApi.hs b/hie-plugin-api/Haskell/Ide/Engine/PluginApi.hs index af81c4a8d..f9bebe438 100644 --- a/hie-plugin-api/Haskell/Ide/Engine/PluginApi.hs +++ b/hie-plugin-api/Haskell/Ide/Engine/PluginApi.hs @@ -58,7 +58,7 @@ module Haskell.Ide.Engine.PluginApi , HIE.CachedInfo(..) -- * used for tests in HaRe --- , HIE.BiosLogLevel(..) + , BiosLogLevel(..) , BiosOptions(..) , defaultOptions ) where diff --git a/stack.yaml b/stack.yaml index 0623e55c5..1d1293ee3 100644 --- a/stack.yaml +++ b/stack.yaml @@ -34,6 +34,7 @@ extra-deps: - syz-0.2.0.0 - temporary-1.2.1.1 - yaml-0.8.32 +- dhall-1.20.1@sha256:3377090039ba3560b50515799affc57d74d2d3e57d3f8699bb2a9fc428fa4918,23401 # allow-newer: true diff --git a/submodules/HaRe b/submodules/HaRe index dfab00043..9de2e991b 160000 --- a/submodules/HaRe +++ b/submodules/HaRe @@ -1 +1 @@ -Subproject commit dfab0004320c28e1aa0331a507a9428952f2c938 +Subproject commit 9de2e991b005d15f9fbe5c5d4ed303630cd19d80 From 30fb1e778bb7c6008b07af20448b261dc2a4a71d Mon Sep 17 00:00:00 2001 From: Zubin Duggal Date: Mon, 15 Jul 2019 17:11:38 +0530 Subject: [PATCH 139/158] remove ghc-mod deps --- hie-plugin-api/hie-plugin-api.cabal | 1 - stack.yaml | 2 -- 2 files changed, 3 deletions(-) diff --git a/hie-plugin-api/hie-plugin-api.cabal b/hie-plugin-api/hie-plugin-api.cabal index f8602b99a..4a5c18ddc 100644 --- a/hie-plugin-api/hie-plugin-api.cabal +++ b/hie-plugin-api/hie-plugin-api.cabal @@ -48,7 +48,6 @@ library , fingertree , free , ghc - , ghc-mod-core >= 5.9.0.0 , hie-bios , ghc-project-types >= 5.9.0.0 , haskell-lsp == 0.13.* diff --git a/stack.yaml b/stack.yaml index 1d1293ee3..b847ea11a 100644 --- a/stack.yaml +++ b/stack.yaml @@ -8,8 +8,6 @@ extra-deps: - ./submodules/HaRe - ./submodules/brittany - ./submodules/cabal-helper -- ./submodules/ghc-mod -- ./submodules/ghc-mod/core - ./submodules/ghc-mod/ghc-project-types - ansi-terminal-0.8.2 From 40342a0be971b886396eacde219d22eb62be5f49 Mon Sep 17 00:00:00 2001 From: Zubin Duggal Date: Mon, 15 Jul 2019 18:53:00 +0530 Subject: [PATCH 140/158] Get it to compile --- hie-plugin-api/Haskell/Ide/Engine/Ghc.hs | 48 ++++--------------- .../Haskell/Ide/Engine/ModuleCache.hs | 2 +- .../Haskell/Ide/Engine/PluginsIdeMonads.hs | 2 +- src/Haskell/Ide/Engine/Transport/LspStdio.hs | 5 +- stack.yaml | 1 + 5 files changed, 15 insertions(+), 43 deletions(-) diff --git a/hie-plugin-api/Haskell/Ide/Engine/Ghc.hs b/hie-plugin-api/Haskell/Ide/Engine/Ghc.hs index ddc12c69f..220839322 100644 --- a/hie-plugin-api/Haskell/Ide/Engine/Ghc.hs +++ b/hie-plugin-api/Haskell/Ide/Engine/Ghc.hs @@ -75,7 +75,7 @@ newtype Diagnostics = Diagnostics (Map.Map NormalizedUri (Set.Set Diagnostic)) deriving (Show, Eq) instance Semigroup Diagnostics where - Diagnostics d1 <> Diagnostics d2 = Diagnostics (d1 <> d2) + Diagnostics d1 <> Diagnostics d2 = Diagnostics (Map.unionWith Set.union d1 d2) instance Monoid Diagnostics where mappend = (<>) @@ -97,20 +97,6 @@ lspSev SevFatal = DsError lspSev SevInfo = DsInfo lspSev _ = DsInfo --- type LogAction = DynFlags -> WarnReason -> Severity -> SrcSpan -> PprStyle -> MsgDoc -> IO () -logDiag :: (FilePath -> FilePath) -> IORef AdditionalErrs -> IORef Diagnostics -> LogAction -logDiag rfm eref dref df _reason sev spn style msg = do - eloc <- srcSpan2Loc rfm spn - let msgTxt = T.pack $ renderWithStyle df msg style - case eloc of - Right (Location uri range) -> do - let update = Map.insertWith Set.union (toNormalizedUri uri) (Set.singleton diag) - diag = Diagnostic range (Just $ lspSev sev) Nothing (Just "ghcmod") msgTxt Nothing - modifyIORef' dref (\(Diagnostics d) -> Diagnostics $ update d) - Left _ -> do - modifyIORef' eref (msgTxt:) - return () - -- --------------------------------------------------------------------- -- unhelpfulSrcSpanErr :: T.Text -> IdeError @@ -158,24 +144,20 @@ captureDiagnostics :: (MonadIO m, GhcMonad m) -> m (Diagnostics, AdditionalErrs, Maybe r) captureDiagnostics rfm action = do env <- getSession - diagRef <- liftIO $ newIORef mempty + diagRef <- liftIO $ newIORef $ Diagnostics mempty errRef <- liftIO $ newIORef [] let setLogger df = df { log_action = logDiag rfm errRef diagRef } setDeferTypedHoles = setGeneralFlag' Opt_DeferTypedHoles - ghcErrRes :: String -> (Diagnostics, AdditionalErrs) - ghcErrRes msg = do - diags <- liftIO $ readIORef diagRef - errs <- liftIO $ readIORef errRef - return (diags, (T.pack msg) : errs, Nothing) + ghcErrRes msg = pure (mempty, [T.pack msg], Nothing) to_diag x = do (d1, e1) <- srcErrToDiag (hsc_dflags env) rfm x diags <- liftIO $ readIORef diagRef errs <- liftIO $ readIORef errRef - return (Map.unionWith Set.union d1 diags, e1 ++ errs, Nothing) + return (d1 <> diags, e1 ++ errs, Nothing) + handlers = errorHandlers ghcErrRes to_diag - handlers = errorHandlers ghcErrRes (srcErrToDiag (hsc_dflags env) rfm ) action' = do r <- BIOS.withDynFlags (setLogger . setDeferTypedHoles) action diags <- liftIO $ readIORef diagRef @@ -193,11 +175,11 @@ logDiag rfm eref dref df _reason sev spn style msg = do let msgTxt = T.pack $ renderWithStyle df msg style case eloc of Right (Location uri range) -> do - let update = Map.insertWith Set.union uri l + let update = Map.insertWith Set.union (toNormalizedUri uri) l where l = Set.singleton diag diag = Diagnostic range (Just $ lspSev sev) Nothing (Just "bios") msgTxt Nothing debugm $ "Writing diag" <> (show diag) - modifyIORef' dref update + modifyIORef' dref (\(Diagnostics u) -> Diagnostics (update u)) Left _ -> do debugm $ "Writing err" <> (show msgTxt) modifyIORef' eref (msgTxt:) @@ -263,25 +245,13 @@ setTypecheckedModule_load uri = mapped_fp <- persistVirtualFile uri liftIO $ copyHsBoot fp mapped_fp rfm <- reverseFileMap - let progTitle = "Typechecking " <> T.pack (takeFileName fp) - (diags', errs, mmods) <- loadFile rfm (fp, mapped_fp) - debugm "File, loaded" - fileMap <- GM.getMMappedFiles - debugm $ "setTypecheckedModule: file mapping state is: " ++ show fileMap - rfm <- GM.mkRevRedirMapFunc - let - ghcErrRes msg = ((Diagnostics Map.empty, [T.pack msg]),Nothing,Nothing) - progTitle = "Typechecking " <> T.pack (takeFileName fp) - debugm "setTypecheckedModule: before ghc-mod" -- TODO:AZ: loading this one module may/should trigger loads of any -- other modules which currently have a VFS entry. Need to make -- sure that their diagnostics are reported, and their module -- cache entries are updated. -- TODO: Are there any hooks we can use to report back on the progress? - ((Diagnostics diags', errs), mtm, mpm) <- withIndefiniteProgress progTitle NotCancellable $ GM.gcatches - (GM.getModulesGhc' (myWrapper rfm) fp) - (errorHandlers ghcErrRes (return . ghcErrRes . show)) - + (Diagnostics diags', errs, mmods) <- loadFile rfm (fp, mapped_fp) + debugm "File, loaded" canonUri <- toNormalizedUri <$> canonicalizeUri uri let diags = Map.insertWith Set.union canonUri Set.empty diags' debugm "setTypecheckedModule: after ghc-mod" diff --git a/hie-plugin-api/Haskell/Ide/Engine/ModuleCache.hs b/hie-plugin-api/Haskell/Ide/Engine/ModuleCache.hs index 12831b45d..ff002bafc 100644 --- a/hie-plugin-api/Haskell/Ide/Engine/ModuleCache.hs +++ b/hie-plugin-api/Haskell/Ide/Engine/ModuleCache.hs @@ -286,7 +286,7 @@ cacheModule fp modul = do -- old TypecheckedModule still contains spans relative to that oldCI = cachedInfo uc in uc { cachedPsMod = pm, cachedInfo = newCI } - _ -> UriCache defInfo pm Nothing mempty + _ -> UriCache defInfo pm Nothing mempty fp_hash Right tm -> do typm <- genTypeMap tm diff --git a/hie-plugin-api/Haskell/Ide/Engine/PluginsIdeMonads.hs b/hie-plugin-api/Haskell/Ide/Engine/PluginsIdeMonads.hs index b9c8220b3..3a6fcd417 100644 --- a/hie-plugin-api/Haskell/Ide/Engine/PluginsIdeMonads.hs +++ b/hie-plugin-api/Haskell/Ide/Engine/PluginsIdeMonads.hs @@ -421,7 +421,7 @@ persistVirtualFile :: (MonadIde m, MonadIO m) => Uri -> m FilePath persistVirtualFile uri = do mlf <- ideEnvLspFuncs <$> getIdeEnv case mlf of - Just lf -> liftIO $ Core.persistVirtualFileFunc lf uri + Just lf -> liftIO $ Core.persistVirtualFileFunc lf (toNormalizedUri uri) Nothing -> maybe (error "persist") return (uriToFilePath uri) reverseFileMap :: (MonadIde m, MonadIO m) => m (FilePath -> FilePath) diff --git a/src/Haskell/Ide/Engine/Transport/LspStdio.hs b/src/Haskell/Ide/Engine/Transport/LspStdio.hs index 7dc514682..7c231f694 100644 --- a/src/Haskell/Ide/Engine/Transport/LspStdio.hs +++ b/src/Haskell/Ide/Engine/Transport/LspStdio.hs @@ -234,7 +234,8 @@ mapFileFromVfs tn vtdi = do let req = GReq tn (Just uri) Nothing Nothing (const $ return ()) $ IdeResultOk <$> do persistVirtualFile uri - updateDocumentRequest uri ver req + updateDocumentRequest uri ver req + (_, _) -> return () -- TODO: generalise this and move it to GhcMod.ModuleLoader updatePositionMap :: Uri -> [J.TextDocumentContentChangeEvent] -> IdeGhcM (IdeResult ()) @@ -947,7 +948,7 @@ requestDiagnosticsNormal tn file mVer = do -- get GHC diagnostics and loads the typechecked module into the cache let reqg = GReq tn (Just file) (Just (file,ver)) Nothing callbackg $ BIOS.setTypecheckedModule file - callbackg (pd, errs) = do + callbackg (HIE.Diagnostics pd, errs) = do forM_ errs $ \e -> do reactorSend $ NotShowMessage $ fmServerShowMessageNotification J.MtError diff --git a/stack.yaml b/stack.yaml index 6a0865b63..02e0e2516 100644 --- a/stack.yaml +++ b/stack.yaml @@ -9,6 +9,7 @@ extra-deps: - ./submodules/cabal-helper - ./submodules/ghc-mod/ghc-project-types +- deque-0.2.7@sha256:ab8ac7a379347fdb8e083297d3bc95372e420c8a96833ddb10a9c8d11ae1f278,1202 - ansi-terminal-0.8.2 - butcher-1.3.2.1 - bytestring-trie-0.2.5.0 From cd882b60540d6eecd31f467e4224bb89c36cc875 Mon Sep 17 00:00:00 2001 From: Zubin Duggal Date: Mon, 15 Jul 2019 20:11:43 +0530 Subject: [PATCH 141/158] Re-enable HaRe --- src/Haskell/Ide/Engine/Plugin/HaRe.hs | 36 +++----------------- src/Haskell/Ide/Engine/Transport/LspStdio.hs | 10 +----- 2 files changed, 6 insertions(+), 40 deletions(-) diff --git a/src/Haskell/Ide/Engine/Plugin/HaRe.hs b/src/Haskell/Ide/Engine/Plugin/HaRe.hs index aabcbf9c3..11175d2de 100644 --- a/src/Haskell/Ide/Engine/Plugin/HaRe.hs +++ b/src/Haskell/Ide/Engine/Plugin/HaRe.hs @@ -21,9 +21,6 @@ import qualified Data.Text as T import qualified Data.Text.IO as T import Exception import GHC.Generics (Generic) ---import qualified GhcMod.Error as GM ---import qualified GhcMod.Monad as GM --- import qualified GhcMod.Utils as GM import Haskell.Ide.Engine.ArtifactMap import Haskell.Ide.Engine.MonadFunctions import Haskell.Ide.Engine.MonadTypes @@ -46,8 +43,7 @@ hareDescriptor plId = PluginDescriptor <> "Haskell 2010 standard, through making use of the GHC API. HaRe attempts to " <> "operate in a safe way, by first writing new files with proposed changes, and " <> "only swapping these with the originals when the change is accepted. " - , pluginCommands = [] - {- + , pluginCommands = [ PluginCommand "demote" "Move a definition one level down" demoteCmd , PluginCommand "dupdef" "Duplicate a definition" @@ -66,14 +62,12 @@ hareDescriptor plId = PluginDescriptor genApplicativeCommand ] - -} - , pluginCodeActionProvider = Nothing -- Just codeActionProvider + , pluginCodeActionProvider = Just codeActionProvider , pluginDiagnosticProvider = Nothing , pluginHoverProvider = Nothing , pluginSymbolProvider = Nothing , pluginFormattingProvider = Nothing } - {- -- --------------------------------------------------------------------- @@ -266,30 +260,11 @@ runHareCommand' cmd = evalStateT cmd' initialState handlers :: Applicative m - => [GM.GHandler m (Either String a)] + => [ErrorHandler m (Either String a)] handlers = - [GM.GHandler (\(ErrorCall e) -> pure (Left e)) - ,GM.GHandler (\(err :: GM.GhcModError) -> pure (Left (show err)))] + [ErrorHandler (\(ErrorCall e) -> pure (Left e))] + fmap Right embeddedCmd `gcatches` handlers - r <- liftIO $ GM.runGhcModT Language.Haskell.Refact.HaRe.defaultOptions (fmap Right embeddedCmd `GM.gcatches` handlers) - case r of - (Right err, _) -> return err - (Left err, _) -> error (show err) - - - --- --------------------------------------------------------------------- --- | This is like hoist from the mmorph package, but build on --- `MonadTransControl` since we don’t have an `MFunctor` instance. -hoist - :: (MonadTransControl t,Monad (t m'),Monad m',Monad m) - => (forall b. m b -> m' b) -> t m a -> t m' a -hoist f a = - liftWith (\run -> - let b = run a - c = f b - in pure c) >>= - restoreT -- --------------------------------------------------------------------- @@ -331,4 +306,3 @@ codeActionProvider pId docId (J.Range pos _) _ = let args = [J.toJSON $ HPT (docId ^. J.uri) pos (name <> "'")] cmd <- mkLspCommand pId aId title (Just args) return $ J.CodeAction (title <> name) (Just kind) mempty Nothing (Just cmd) --} diff --git a/src/Haskell/Ide/Engine/Transport/LspStdio.hs b/src/Haskell/Ide/Engine/Transport/LspStdio.hs index 7c231f694..a4d0396fa 100644 --- a/src/Haskell/Ide/Engine/Transport/LspStdio.hs +++ b/src/Haskell/Ide/Engine/Transport/LspStdio.hs @@ -52,14 +52,7 @@ import Haskell.Ide.Engine.PluginUtils import qualified Haskell.Ide.Engine.Scheduler as Scheduler import qualified Haskell.Ide.Engine.Support.HieExtras as Hie import Haskell.Ide.Engine.Types ---import Haskell.Ide.Engine.LSP.CodeActions ---import Haskell.Ide.Engine.LSP.Reactor --- import qualified Haskell.Ide.Engine.Plugin.HaRe as HaRe import qualified Haskell.Ide.Engine.Plugin.Bios as BIOS ---import qualified Haskell.Ide.Engine.Plugin.ApplyRefact as ApplyRefact ---import qualified Haskell.Ide.Engine.Plugin.Hoogle as Hoogle ---import qualified Haskell.Ide.Engine.Support.HieExtras as Hie --- import Haskell.Ide.Engine.Plugin.Base import qualified Language.Haskell.LSP.Control as CTRL import qualified Language.Haskell.LSP.Core as Core import Language.Haskell.LSP.Diagnostics @@ -514,7 +507,7 @@ reactor inp diagIn = do -- ------------------------------- - {-ReqRename req -> do + ReqRename req -> do liftIO $ U.logs $ "reactor:got RenameRequest:" ++ show req let (params, doc, pos) = reqParams req newName = params ^. J.newName @@ -522,7 +515,6 @@ reactor inp diagIn = do let hreq = GReq tn (Just doc) Nothing (Just $ req ^. J.id) callback $ HaRe.renameCmd' doc pos newName makeRequest hreq - -} -- ------------------------------- From ca53013953ea11290295f6c408079b182cce486c Mon Sep 17 00:00:00 2001 From: Zubin Duggal Date: Tue, 16 Jul 2019 14:38:19 +0530 Subject: [PATCH 142/158] Fix HaRe, remove module hash --- app/MainHie.hs | 2 + hie-plugin-api/Haskell/Ide/Engine/Ghc.hs | 59 +++++++++---------- .../Haskell/Ide/Engine/GhcModuleCache.hs | 9 ++- .../Haskell/Ide/Engine/ModuleCache.hs | 28 +++------ .../Haskell/Ide/Engine/PluginsIdeMonads.hs | 9 +++ src/Haskell/Ide/Engine/Plugin/ApplyRefact.hs | 13 ++-- src/Haskell/Ide/Engine/Plugin/HaRe.hs | 10 +++- src/Haskell/Ide/Engine/Plugin/HsImport.hs | 3 +- 8 files changed, 63 insertions(+), 70 deletions(-) diff --git a/app/MainHie.hs b/app/MainHie.hs index a8a94ab81..9fa07e20a 100644 --- a/app/MainHie.hs +++ b/app/MainHie.hs @@ -18,6 +18,7 @@ import System.Directory import System.Environment import qualified System.Log.Logger as L import HIE.Bios.Types +import System.IO -- --------------------------------------------------------------------- -- plugins @@ -102,6 +103,7 @@ main = do run :: GlobalOpts -> IO () run opts = do + hSetBuffering stderr LineBuffering let mLogFileName = optLogFile opts logLevel = if optDebugOn opts diff --git a/hie-plugin-api/Haskell/Ide/Engine/Ghc.hs b/hie-plugin-api/Haskell/Ide/Engine/Ghc.hs index 220839322..77923e93c 100644 --- a/hie-plugin-api/Haskell/Ide/Engine/Ghc.hs +++ b/hie-plugin-api/Haskell/Ide/Engine/Ghc.hs @@ -21,6 +21,7 @@ import Bag import Control.Monad.IO.Class import Data.IORef import qualified Data.Map.Strict as Map +import qualified Data.IntMap.Strict as IM import Data.Semigroup ((<>), Semigroup) import qualified Data.Set as Set import qualified Data.Text as T @@ -31,7 +32,6 @@ import ErrUtils import Haskell.Ide.Engine.MonadFunctions import Haskell.Ide.Engine.MonadTypes import Haskell.Ide.Engine.PluginUtils -import System.FilePath import DynFlags import GHC @@ -40,36 +40,24 @@ import HscTypes import Outputable (renderWithStyle) import Language.Haskell.LSP.Types ( NormalizedUri(..), toNormalizedUri ) -import Bag -import Control.Monad.IO.Class -import Data.IORef -import qualified Data.Map.Strict as Map import Data.Monoid ((<>)) -import qualified Data.Set as Set -import qualified Data.Text as T -import ErrUtils -import System.FilePath -import Haskell.Ide.Engine.MonadFunctions -import Haskell.Ide.Engine.MonadTypes -import Haskell.Ide.Engine.PluginUtils import Haskell.Ide.Engine.GhcUtils --import qualified Haskell.Ide.Engine.Plugin.HieExtras as Hie -import DynFlags -import GHC -import IOEnv as G -import HscTypes import Outputable hiding ((<>)) -- This function should be defined in HIE probably, nothing in particular -- to do with BIOS import qualified HIE.Bios.GHCApi as BIOS (withDynFlags, CradleError) import qualified HIE.Bios as BIOS import Debug.Trace -import qualified HscMain as G import System.Directory +import GhcProject.Types as GM +import Digraph (Node(..), verticesG) +import GhcMake ( moduleGraphNodes ) + newtype Diagnostics = Diagnostics (Map.Map NormalizedUri (Set.Set Diagnostic)) deriving (Show, Eq) @@ -292,22 +280,29 @@ setTypecheckedModule_load uri = return $ IdeResultOk (Diagnostics diags2,errs) --- -cabalModuleGraphs = undefined -{- +-- TODO: make this work for all components cabalModuleGraphs :: IdeGhcM [GM.GmModuleGraph] -cabalModuleGraphs = doCabalModuleGraphs - where - doCabalModuleGraphs :: (GM.IOish m) => GM.GhcModT m [GM.GmModuleGraph] - doCabalModuleGraphs = do - crdl <- GM.cradle - case GM.cradleCabalFile crdl of - Just _ -> do - mcs <- GM.cabalResolvedComponents - let graph = map GM.gmcHomeModuleGraph $ Map.elems mcs - return graph - Nothing -> return [] - -} +cabalModuleGraphs = do + mg <- getModuleGraph + let (graph, _) = moduleGraphNodes False (mgModSummaries mg) + msToModulePath ms = + case ml_hs_file (ms_location ms) of + Nothing -> [] + Just fp -> [ModulePath mn fp] + where mn = moduleName (ms_mod ms) + nodeMap = IM.fromList [(node_key n,n) | n <- nodes] + nodes = verticesG graph + gmg = Map.fromList + [(mp,Set.fromList deps) + | node <- nodes + , mp <- msToModulePath (node_payload node) + , let int_deps = node_dependencies node + deps = [ d | i <- int_deps + , Just dep_node <- pure $ IM.lookup i nodeMap + , d <- msToModulePath (node_payload dep_node) + ] + ] + pure [GmModuleGraph gmg] -- --------------------------------------------------------------------- diff --git a/hie-plugin-api/Haskell/Ide/Engine/GhcModuleCache.hs b/hie-plugin-api/Haskell/Ide/Engine/GhcModuleCache.hs index a77de7fdb..3bcd86e4c 100644 --- a/hie-plugin-api/Haskell/Ide/Engine/GhcModuleCache.hs +++ b/hie-plugin-api/Haskell/Ide/Engine/GhcModuleCache.hs @@ -41,7 +41,6 @@ data UriCache = UriCache -- | Data pertaining to the typechecked module, -- not the parsed module , cachedData :: !(Map.Map TypeRep Dynamic) - , cachedHash :: !ModuleHash } newtype ModuleHash = ModuleHash BS.ByteString deriving (Show, Eq) @@ -51,9 +50,9 @@ hashModule f = ModuleHash . hash <$> BS.readFile f instance Show UriCache where - show (UriCache _ _ (Just _) dat _h) = + show (UriCache _ _ (Just _) dat) = "UriCache { cachedTcMod, cachedData { " ++ show dat ++ " } }" - show (UriCache _ _ _ dat _h) = + show (UriCache _ _ _ dat) = "UriCache { cachedPsMod, cachedData { " ++ show dat ++ " } }" data CachedInfo = CachedInfo @@ -70,10 +69,10 @@ class CacheableModule a where fromUriCache :: UriCache -> Maybe a instance CacheableModule TypecheckedModule where - fromUriCache (UriCache _ _ mtm _ _) = mtm + fromUriCache (UriCache _ _ mtm _) = mtm instance CacheableModule ParsedModule where - fromUriCache (UriCache _ pm _ _ _) = Just pm + fromUriCache (UriCache _ pm _ _) = Just pm -- --------------------------------------------------------------------- diff --git a/hie-plugin-api/Haskell/Ide/Engine/ModuleCache.hs b/hie-plugin-api/Haskell/Ide/Engine/ModuleCache.hs index ff002bafc..96be2a0b0 100644 --- a/hie-plugin-api/Haskell/Ide/Engine/ModuleCache.hs +++ b/hie-plugin-api/Haskell/Ide/Engine/ModuleCache.hs @@ -35,7 +35,6 @@ import qualified Data.Map as Map import Data.Maybe import Data.Typeable (Typeable) import System.Directory -import UnliftIO import Debug.Trace @@ -176,7 +175,7 @@ ifCachedModuleAndData :: forall a b m. (ModuleCache a, HasGhcModuleCache m, Mona ifCachedModuleAndData fp def callback = do muc <- getUriCache fp case muc of - Just (UriCacheSuccess uc@(UriCache info _ (Just tm) dat _)) -> + Just (UriCacheSuccess uc@(UriCache info _ (Just tm) dat)) -> case fromUriCache uc of Just modul -> lookupCachedData fp tm info dat >>= callback modul (cachedInfo uc) Nothing -> return def @@ -191,7 +190,7 @@ ifCachedModuleAndData fp def callback = do -- see also 'ifCachedModule'. withCachedModule :: CacheableModule b => FilePath -> a -> (b -> CachedInfo -> IdeDeferM a) -> IdeDeferM a withCachedModule fp def callback = deferIfNotCached fp go - where go (UriCacheSuccess uc@(UriCache _ _ _ _ _)) = + where go (UriCacheSuccess uc@(UriCache _ _ _ _)) = case fromUriCache uc of Just modul -> callback modul (cachedInfo uc) Nothing -> wrap (Defer fp go) @@ -209,7 +208,7 @@ withCachedModuleAndData :: forall a b. (ModuleCache a) => FilePath -> b -> (GHC.TypecheckedModule -> CachedInfo -> a -> IdeDeferM b) -> IdeDeferM b withCachedModuleAndData fp def callback = deferIfNotCached fp go - where go (UriCacheSuccess (uc@(UriCache info _ (Just tm) dat _))) = + where go (UriCacheSuccess (uc@(UriCache info _ (Just tm) dat))) = lookupCachedData fp tm info dat >>= callback tm (cachedInfo uc) go (UriCacheSuccess (UriCache { cachedTcMod = Nothing })) = wrap (Defer fp go) go UriCacheFailed = return def @@ -217,18 +216,7 @@ withCachedModuleAndData fp def callback = deferIfNotCached fp go getUriCache :: (HasGhcModuleCache m, MonadIO m) => FilePath -> m (Maybe UriCacheResult) getUriCache fp = do canonical_fp <- liftIO $ canonicalizePath fp - raw_res <- fmap (Map.lookup canonical_fp . uriCaches) getModuleCache - case raw_res of - Just uri_res -> liftIO $ checkModuleHash canonical_fp uri_res - Nothing -> return Nothing - -checkModuleHash :: FilePath -> UriCacheResult -> IO (Maybe UriCacheResult) -checkModuleHash fp r@(UriCacheSuccess uri_res) = do - cur_hash <- hashModule fp - return $ if cachedHash uri_res == cur_hash - then Just r - else Nothing -checkModuleHash _ r = return (Just r) + fmap (Map.lookup canonical_fp . uriCaches) getModuleCache deferIfNotCached :: FilePath -> (UriCacheResult -> IdeDeferM a) -> IdeDeferM a deferIfNotCached fp cb = do @@ -246,9 +234,8 @@ lookupCachedData fp tm info dat = do case Map.lookup (typeRep proxy) dat of Nothing -> do val <- cacheDataProducer tm info - h <- liftIO $ hashModule canonical_fp let dat' = Map.insert (typeOf val) (toDyn val) dat - newUc = UriCache info (GHC.tm_parsed_module tm) (Just tm) dat' h + newUc = UriCache info (GHC.tm_parsed_module tm) (Just tm) dat' modifyCache (\s -> s {uriCaches = Map.insert canonical_fp (UriCacheSuccess newUc) (uriCaches s)}) return val @@ -272,7 +259,6 @@ cacheModule :: FilePath -> (Either GHC.ParsedModule GHC.TypecheckedModule) -> Id cacheModule fp modul = do canonical_fp <- liftIO $ canonicalizePath fp rfm <- reverseFileMap - fp_hash <- liftIO $ hashModule fp newUc <- case modul of Left pm -> do @@ -286,13 +272,13 @@ cacheModule fp modul = do -- old TypecheckedModule still contains spans relative to that oldCI = cachedInfo uc in uc { cachedPsMod = pm, cachedInfo = newCI } - _ -> UriCache defInfo pm Nothing mempty fp_hash + _ -> UriCache defInfo pm Nothing mempty Right tm -> do typm <- genTypeMap tm let info = CachedInfo (genLocMap tm) typm (genImportMap tm) (genDefMap tm) rfm return return pm = GHC.tm_parsed_module tm - return $ UriCache info pm (Just tm) mempty fp_hash + return $ UriCache info pm (Just tm) mempty let res = UriCacheSuccess newUc modifyCache $ \gmc -> diff --git a/hie-plugin-api/Haskell/Ide/Engine/PluginsIdeMonads.hs b/hie-plugin-api/Haskell/Ide/Engine/PluginsIdeMonads.hs index 3a6fcd417..025ca91af 100644 --- a/hie-plugin-api/Haskell/Ide/Engine/PluginsIdeMonads.hs +++ b/hie-plugin-api/Haskell/Ide/Engine/PluginsIdeMonads.hs @@ -68,6 +68,7 @@ module Haskell.Ide.Engine.PluginsIdeMonads , withIndefiniteProgress , persistVirtualFile , reverseFileMap + , withMappedFile , Core.Progress(..) , Core.ProgressCancellable(..) -- ** Lifting @@ -119,6 +120,7 @@ import qualified Data.Text as T import Data.Typeable ( TypeRep , Typeable ) +import System.Directory import GhcMonad import qualified HIE.Bios as BIOS import GHC.Generics @@ -431,6 +433,13 @@ reverseFileMap = do Just lf -> liftIO $ Core.reverseFileMapFunc lf Nothing -> return id +withMappedFile :: (MonadIde m, MonadIO m) => FilePath -> (FilePath -> m a) -> m a +withMappedFile fp k = do + rfm <- reverseFileMap + fp' <- liftIO $ canonicalizePath fp + k $ rfm fp' + + getConfig :: (MonadIde m, MonadIO m) => m Config getConfig = do mlf <- ideEnvLspFuncs <$> getIdeEnv diff --git a/src/Haskell/Ide/Engine/Plugin/ApplyRefact.hs b/src/Haskell/Ide/Engine/Plugin/ApplyRefact.hs index e85f6b014..36fd6f45a 100644 --- a/src/Haskell/Ide/Engine/Plugin/ApplyRefact.hs +++ b/src/Haskell/Ide/Engine/Plugin/ApplyRefact.hs @@ -80,9 +80,8 @@ applyOneCmd = CmdSync $ \(AOP uri pos title) -> do applyOneCmd' :: Uri -> OneHint -> IdeGhcM (IdeResult WorkspaceEdit) applyOneCmd' uri oneHint = pluginGetFile "applyOne: " uri $ \fp -> do - revMapp <- return id --GM.mkRevRedirMapFunc - res <- liftToGhc $ applyHint fp (Just oneHint) revMapp - --GM.withMappedFile fp $ \file' -> liftToGhc $ applyHint file' (Just oneHint) revMapp + revMapp <- reverseFileMap + res <- withMappedFile fp $ \file' -> liftToGhc $ applyHint file' (Just oneHint) revMapp logm $ "applyOneCmd:file=" ++ show fp logm $ "applyOneCmd:res=" ++ show res case res of @@ -100,8 +99,7 @@ applyAllCmd = CmdSync $ \uri -> do applyAllCmd' :: Uri -> IdeGhcM (IdeResult WorkspaceEdit) applyAllCmd' uri = pluginGetFile "applyAll: " uri $ \fp -> do revMapp <- reverseFileMap - res <- liftToGhc $ applyHint fp Nothing revMapp - --GM.withMappedFile fp $ \file' -> liftToGhc $ applyHint file' Nothing revMapp + res <- withMappedFile fp $ \file' -> liftToGhc $ applyHint file' Nothing revMapp logm $ "applyAllCmd:res=" ++ show res case res of Left err -> return $ IdeResultFail (IdeError PluginError @@ -117,9 +115,8 @@ lintCmd = CmdSync $ \uri -> do -- AZ:TODO: Why is this in IdeGhcM? lintCmd' :: Uri -> IdeGhcM (IdeResult PublishDiagnosticsParams) lintCmd' uri = pluginGetFile "lintCmd: " uri $ \fp -> do - eitherErrorResult <- - liftIO (try $ runExceptT $ runLintCmd fp [] :: IO (Either IOException (Either [Diagnostic] [Idea]))) - --TODO: GM.withMappedFile fp $ \file' -> liftIO $ runExceptT $ runLintCmd file' [] + eitherErrorResult <- withMappedFile fp $ \file' -> + liftIO (try $ runExceptT $ runLintCmd file' [] :: IO (Either IOException (Either [Diagnostic] [Idea]))) case eitherErrorResult of Left err -> return diff --git a/src/Haskell/Ide/Engine/Plugin/HaRe.hs b/src/Haskell/Ide/Engine/Plugin/HaRe.hs index 11175d2de..5b57cf454 100644 --- a/src/Haskell/Ide/Engine/Plugin/HaRe.hs +++ b/src/Haskell/Ide/Engine/Plugin/HaRe.hs @@ -28,11 +28,14 @@ import Haskell.Ide.Engine.PluginUtils import qualified Haskell.Ide.Engine.Support.HieExtras as Hie import Language.Haskell.GHC.ExactPrint.Print import qualified Language.Haskell.LSP.Core as Core +import Language.Haskell.LSP.VFS import qualified Language.Haskell.LSP.Types as J import qualified Language.Haskell.LSP.Types.Lens as J import Language.Haskell.Refact.API hiding (logm) import Language.Haskell.Refact.HaRe import Language.Haskell.Refact.Utils.Monad hiding (logm) +import qualified Data.Rope.UTF16 as Rope + -- --------------------------------------------------------------------- hareDescriptor :: PluginId -> PluginDescriptor @@ -208,8 +211,11 @@ makeRefactorResult changedFiles = do let diffOne :: (FilePath, T.Text) -> IdeGhcM WorkspaceEdit diffOne (fp, newText) = do - origText <- liftIO $ T.readFile fp - -- GM.withMappedFile fp $ liftIO . T.readFile + uri <- canonicalizeUri $ filePathToUri fp + mvf <- getVirtualFile uri + origText <- case mvf of + Nothing -> withMappedFile fp $ liftIO . T.readFile + Just vf -> pure (Rope.toText $ _text vf) -- TODO: remove this logging once we are sure we have a working solution logm $ "makeRefactorResult:groupedDiff = " ++ show (getGroupedDiff (lines $ T.unpack origText) (lines $ T.unpack newText)) logm $ "makeRefactorResult:diffops = " ++ show (diffToLineRanges $ getGroupedDiff (lines $ T.unpack origText) (lines $ T.unpack newText)) diff --git a/src/Haskell/Ide/Engine/Plugin/HsImport.hs b/src/Haskell/Ide/Engine/Plugin/HsImport.hs index 0fa130421..ebade20a5 100644 --- a/src/Haskell/Ide/Engine/Plugin/HsImport.hs +++ b/src/Haskell/Ide/Engine/Plugin/HsImport.hs @@ -128,8 +128,7 @@ importModule uri impStyle modName = pluginGetFile "hsimport cmd: " uri $ \origInput -> do shouldFormat <- formatOnImportOn <$> getConfig - fileMap <- return id -- TODO: GM.mkRevRedirMapFunc --- GM.withMappedFile origInput $ \input -> do + fileMap <- reverseFileMap let input = origInput do tmpDir <- liftIO getTemporaryDirectory From 6f905aa091e73ab3d8a9a53b349d52bc8cba32a0 Mon Sep 17 00:00:00 2001 From: Zubin Duggal Date: Tue, 16 Jul 2019 16:24:09 +0530 Subject: [PATCH 143/158] Restore HaRe tests, get tests to compile --- test/dispatcher/Main.hs | 6 +- test/plugin-dispatcher/Main.hs | 1 - test/unit/CodeActionsSpec.hs | 2 +- test/unit/GhcModPluginSpec.hs | 68 ++++----- test/unit/HaRePluginSpec.hs | 268 ++++++++++++++++++++++++++++++++- test/unit/JsonSpec.hs | 2 +- test/utils/TestUtils.hs | 7 + 7 files changed, 314 insertions(+), 40 deletions(-) diff --git a/test/dispatcher/Main.hs b/test/dispatcher/Main.hs index 4f5f6ca81..9cc939d5d 100644 --- a/test/dispatcher/Main.hs +++ b/test/dispatcher/Main.hs @@ -25,6 +25,7 @@ import System.FilePath import Test.Hspec import Test.Hspec.Runner +import System.IO -- --------------------------------------------------------------------- -- plugins @@ -41,6 +42,7 @@ import Haskell.Ide.Engine.Plugin.Generic main :: IO () main = do + hSetBuffering stderr LineBuffering setupStackFiles config <- getHspecFormattedConfig "dispatcher" withFileLogging "main-dispatcher.log" $ do @@ -162,7 +164,7 @@ funcSpec = describe "functional dispatch" $ do show rrr `shouldBe` "Nothing" -- need to typecheck the module to trigger deferred response - dispatchGhcRequest 2 "req2" 2 scheduler logChan "ghcmod" "check" (toJSON testUri) + dispatchGhcRequest 2 "req2" 2 scheduler logChan "bios" "check" (toJSON testUri) -- And now we get the deferred response (once the module is loaded) ("req1",Right res) <- atomically $ readTChan logChan @@ -275,7 +277,7 @@ funcSpec = describe "functional dispatch" $ do dispatchIdeRequest 7 "req7" scheduler logChan (IdInt 7) $ findDef testFailUri (Position 1 2) - dispatchGhcRequest 8 "req8" 8 scheduler logChan "ghcmod" "check" (toJSON testFailUri) + dispatchGhcRequest 8 "req8" 8 scheduler logChan "bios" "check" (toJSON testFailUri) hr7 <- atomically $ readTChan logChan unpackRes hr7 `shouldBe` ("req7", Just ([] :: [Location])) diff --git a/test/plugin-dispatcher/Main.hs b/test/plugin-dispatcher/Main.hs index d182235d9..3886f7dd2 100644 --- a/test/plugin-dispatcher/Main.hs +++ b/test/plugin-dispatcher/Main.hs @@ -12,7 +12,6 @@ import Haskell.Ide.Engine.Scheduler import Haskell.Ide.Engine.Types import Language.Haskell.LSP.Types import TestUtils - import Test.Hspec import Test.Hspec.Runner diff --git a/test/unit/CodeActionsSpec.hs b/test/unit/CodeActionsSpec.hs index 6e8c33ad5..c901f28ea 100644 --- a/test/unit/CodeActionsSpec.hs +++ b/test/unit/CodeActionsSpec.hs @@ -4,7 +4,7 @@ module CodeActionsSpec where import Test.Hspec import qualified Data.Text.IO as T import Haskell.Ide.Engine.Plugin.HsImport -import Haskell.Ide.Engine.Plugin.Generic +import Haskell.Ide.Engine.Plugin.Generic hiding (Import) import Haskell.Ide.Engine.Plugin.Package main :: IO () diff --git a/test/unit/GhcModPluginSpec.hs b/test/unit/GhcModPluginSpec.hs index e9da9b4cd..24449b19a 100644 --- a/test/unit/GhcModPluginSpec.hs +++ b/test/unit/GhcModPluginSpec.hs @@ -12,7 +12,7 @@ import qualified Data.Set as S import qualified Data.Text as T import Haskell.Ide.Engine.Ghc import Haskell.Ide.Engine.MonadTypes -import Haskell.Ide.Engine.Plugin.GhcMod +import Haskell.Ide.Engine.Plugin.Generic import Haskell.Ide.Engine.PluginUtils import Haskell.Ide.Engine.Support.HieExtras import Language.Haskell.LSP.Types (TextEdit (..), toNormalizedUri) @@ -33,7 +33,7 @@ spec = do -- --------------------------------------------------------------------- testPlugins :: IdePlugins -testPlugins = pluginDescToIdePlugins [ghcmodDescriptor "ghcmod"] +testPlugins = pluginDescToIdePlugins [genericDescriptor "ghcmod"] -- --------------------------------------------------------------------- @@ -534,35 +534,35 @@ ghcmodSpec = -- --------------------------------- - it "runs the casesplit command" $ withCurrentDirectory "./test/testdata" $ do - fp <- makeAbsolute "GhcModCaseSplit.hs" - let uri = filePathToUri fp - act = do - _ <- setTypecheckedModule uri - splitCaseCmd' uri (toPos (5,5)) - arg = HP uri (toPos (5,5)) - res = IdeResultOk $ WorkspaceEdit - (Just $ H.singleton uri - $ List [TextEdit (Range (Position 4 0) (Position 4 10)) - "foo Nothing = ()\nfoo (Just x) = ()"]) - Nothing - testCommand testPlugins act "ghcmod" "casesplit" arg res - - it "runs the casesplit command with an absolute path from another folder, correct params" $ do - fp <- makeAbsolute "./test/testdata/GhcModCaseSplit.hs" - cd <- getCurrentDirectory - cd2 <- getHomeDirectory - bracket (setCurrentDirectory cd2) - (\_-> setCurrentDirectory cd) - $ \_-> do - let uri = filePathToUri fp - act = do - _ <- setTypecheckedModule uri - splitCaseCmd' uri (toPos (5,5)) - arg = HP uri (toPos (5,5)) - res = IdeResultOk $ WorkspaceEdit - (Just $ H.singleton uri - $ List [TextEdit (Range (Position 4 0) (Position 4 10)) - "foo Nothing = ()\nfoo (Just x) = ()"]) - Nothing - testCommand testPlugins act "ghcmod" "casesplit" arg res +-- it "runs the casesplit command" $ withCurrentDirectory "./test/testdata" $ do +-- fp <- makeAbsolute "GhcModCaseSplit.hs" +-- let uri = filePathToUri fp +-- act = do +-- _ <- setTypecheckedModule uri +-- splitCaseCmd' uri (toPos (5,5)) +-- arg = HP uri (toPos (5,5)) +-- res = IdeResultOk $ WorkspaceEdit +-- (Just $ H.singleton uri +-- $ List [TextEdit (Range (Position 4 0) (Position 4 10)) +-- "foo Nothing = ()\nfoo (Just x) = ()"]) +-- Nothing +-- testCommand testPlugins act "ghcmod" "casesplit" arg res + +-- it "runs the casesplit command with an absolute path from another folder, correct params" $ do +-- fp <- makeAbsolute "./test/testdata/GhcModCaseSplit.hs" +-- cd <- getCurrentDirectory +-- cd2 <- getHomeDirectory +-- bracket (setCurrentDirectory cd2) +-- (\_-> setCurrentDirectory cd) +-- $ \_-> do +-- let uri = filePathToUri fp +-- act = do +-- _ <- setTypecheckedModule uri +-- splitCaseCmd' uri (toPos (5,5)) +-- arg = HP uri (toPos (5,5)) +-- res = IdeResultOk $ WorkspaceEdit +-- (Just $ H.singleton uri +-- $ List [TextEdit (Range (Position 4 0) (Position 4 10)) +-- "foo Nothing = ()\nfoo (Just x) = ()"]) +-- Nothing +-- testCommand testPlugins act "ghcmod" "casesplit" arg res diff --git a/test/unit/HaRePluginSpec.hs b/test/unit/HaRePluginSpec.hs index 4538fc5e9..6d425118f 100644 --- a/test/unit/HaRePluginSpec.hs +++ b/test/unit/HaRePluginSpec.hs @@ -10,9 +10,9 @@ import Control.Monad.IO.Class import Data.Aeson import qualified Data.Map as M import qualified Data.HashMap.Strict as H +import Haskell.Ide.Engine.Ghc import Haskell.Ide.Engine.MonadTypes import Haskell.Ide.Engine.PluginUtils -import Haskell.Ide.Engine.Plugin.GhcMod import Haskell.Ide.Engine.Plugin.HaRe import Haskell.Ide.Engine.Support.HieExtras import Language.Haskell.LSP.Types ( Location(..) @@ -29,3 +29,269 @@ import Test.Hspec {-# ANN module ("hlint: ignore Redundant do" :: String) #-} -- --------------------------------------------------------------------- +main :: IO () +main = hspec spec + +spec :: Spec +spec = do + describe "hare plugin" hareSpec + +-- --------------------------------------------------------------------- + +testPlugins :: IdePlugins +testPlugins = pluginDescToIdePlugins [hareDescriptor "hare"] + +dispatchRequestPGoto :: IdeGhcM a -> IO a +dispatchRequestPGoto = + withCurrentDirectory "./test/testdata/gototest" + . runIGM testPlugins + +-- --------------------------------------------------------------------- + +hareSpec :: Spec +hareSpec = do + describe "hare plugin commands(old plugin api)" $ do + cwd <- runIO getCurrentDirectory + -- --------------------------------- + + it "renames" $ withCurrentDirectory "test/testdata" $ do + + let uri = filePathToUri $ cwd "test/testdata/HaReRename.hs" + act = renameCmd' uri (toPos (5,1)) "foolong" + arg = HPT uri (toPos (5,1)) "foolong" + textEdits = List [TextEdit (Range (Position 3 0) (Position 4 13)) "foolong :: Int -> Int\nfoolong x = x + 3"] + res = IdeResultOk $ WorkspaceEdit + (Just $ H.singleton uri textEdits) + Nothing + testCommand testPlugins act "hare" "rename" arg res + + -- --------------------------------- + + it "returns an error for invalid rename" $ withCurrentDirectory "test/testdata" $ do + let uri = filePathToUri $ cwd "test/testdata/HaReRename.hs" + act = renameCmd' uri (toPos (15,1)) "foolong" + arg = HPT uri (toPos (15,1)) "foolong" + res = IdeResultFail + IdeError { ideCode = PluginError + , ideMessage = "rename: \"Invalid cursor position!\"", ideInfo = Null} + testCommand testPlugins act "hare" "rename" arg res + + -- --------------------------------- + + it "demotes" $ withCurrentDirectory "test/testdata" $ do + let uri = filePathToUri $ cwd "test/testdata/HaReDemote.hs" + act = demoteCmd' uri (toPos (6,1)) + arg = HP uri (toPos (6,1)) + textEdits = List [TextEdit (Range (Position 4 0) (Position 5 5)) " where\n y = 7"] + res = IdeResultOk $ WorkspaceEdit + (Just $ H.singleton uri textEdits) + Nothing + testCommand testPlugins act "hare" "demote" arg res + + -- --------------------------------- + + it "duplicates a definition" $ withCurrentDirectory "test/testdata" $ do + let uri = filePathToUri $ cwd "test/testdata/HaReRename.hs" + act = dupdefCmd' uri (toPos (5,1)) "foonew" + arg = HPT uri (toPos (5,1)) "foonew" + textEdits = List [TextEdit (Range (Position 6 0) (Position 6 0)) "foonew :: Int -> Int\nfoonew x = x + 3\n\n"] + res = IdeResultOk $ WorkspaceEdit + (Just $ H.singleton uri textEdits) + Nothing + testCommand testPlugins act "hare" "dupdef" arg res + + -- --------------------------------- + + it "converts if to case" $ withCurrentDirectory "test/testdata" $ do + + let uri = filePathToUri $ cwd "test/testdata/HaReCase.hs" + act = iftocaseCmd' uri (Range (toPos (5,9)) + (toPos (9,12))) + arg = HR uri (toPos (5,9)) (toPos (9,12)) + textEdits = List [TextEdit (Range (Position 4 0) (Position 8 11)) + "foo x = case odd x of\n True ->\n x + 3\n False ->\n x"] + res = IdeResultOk $ WorkspaceEdit + (Just $ H.singleton uri textEdits) + Nothing + testCommand testPlugins act "hare" "iftocase" arg res + + -- --------------------------------- + + it "lifts one level" $ withCurrentDirectory "test/testdata" $ do + + let uri = filePathToUri $ cwd "test/testdata/HaReMoveDef.hs" + act = liftonelevelCmd' uri (toPos (6,5)) + arg = HP uri (toPos (6,5)) + textEdits = List [ TextEdit (Range (Position 6 0) (Position 6 0)) "y = 4\n\n" + , TextEdit (Range (Position 4 0) (Position 6 0)) ""] + res = IdeResultOk $ WorkspaceEdit + (Just $ H.singleton uri textEdits) + Nothing + testCommand testPlugins act "hare" "liftonelevel" arg res + + -- --------------------------------- + + it "lifts to top level" $ withCurrentDirectory "test/testdata" $ do + + let uri = filePathToUri $ cwd "test/testdata/HaReMoveDef.hs" + act = lifttotoplevelCmd' uri (toPos (12,9)) + arg = HP uri (toPos (12,9)) + textEdits = List [ TextEdit (Range (Position 13 0) (Position 13 0)) "\n" + , TextEdit (Range (Position 12 0) (Position 12 0)) "z = 7\n" + , TextEdit (Range (Position 10 0) (Position 12 0)) "" + ] + res = IdeResultOk $ WorkspaceEdit + (Just $ H.singleton uri textEdits) + Nothing + testCommand testPlugins act "hare" "lifttotoplevel" arg res + + -- --------------------------------- + + it "deletes a definition" $ withCurrentDirectory "test/testdata" $ do + let uri = filePathToUri $ cwd "test/testdata/FuncTest.hs" + act = deleteDefCmd' uri (toPos (6,1)) + arg = HP uri (toPos (6,1)) + textEdits = List [TextEdit (Range (Position 4 0) (Position 7 0)) ""] + res = IdeResultOk $ WorkspaceEdit + (Just $ H.singleton uri textEdits) + Nothing + testCommand testPlugins act "hare" "deletedef" arg res + + -- --------------------------------- + + it "generalises an applicative" $ withCurrentDirectory "test/testdata" $ do + let uri = filePathToUri $ cwd "test/testdata/HaReGA1.hs" + act = genApplicativeCommand' uri (toPos (4,1)) + arg = HP uri (toPos (4,1)) + textEdits = List [TextEdit (Range (Position 4 0) (Position 8 12)) + "parseStr = char '\"' *> (many1 (noneOf \"\\\"\")) <* char '\"'"] + res = IdeResultOk $ WorkspaceEdit + (Just $ H.singleton uri textEdits) + Nothing + testCommand testPlugins act "hare" "genapplicative" arg res + + -- --------------------------------- + + describe "Additional GHC API commands" $ do + cwd <- runIO getCurrentDirectory + + it "finds definition across components" $ do + let u = filePathToUri $ cwd "test/testdata/gototest/app/Main.hs" + lreq = setTypecheckedModule u + req = liftToGhc $ TestDeferM $ findDef u (toPos (7,8)) + r <- dispatchRequestPGoto $ lreq >> req + r `shouldBe` IdeResultOk [Location (filePathToUri $ cwd "test/testdata/gototest/src/Lib.hs") + (Range (toPos (6,1)) (toPos (6,9)))] + let req2 = liftToGhc $ TestDeferM $ findDef u (toPos (7,20)) + r2 <- dispatchRequestPGoto $ lreq >> req2 + r2 `shouldBe` IdeResultOk [Location (filePathToUri $ cwd "test/testdata/gototest/src/Lib2.hs") + (Range (toPos (5,1)) (toPos (5,2)))] + it "finds definition in the same component" $ do + let u = filePathToUri $ cwd "test/testdata/gototest/src/Lib2.hs" + lreq = setTypecheckedModule u + req = liftToGhc $ TestDeferM $ findDef u (toPos (6,5)) + r <- dispatchRequestPGoto $ lreq >> req + r `shouldBe` IdeResultOk [Location (filePathToUri $ cwd "test/testdata/gototest/src/Lib.hs") + (Range (toPos (6,1)) (toPos (6,9)))] + it "finds local definitions" $ do + let u = filePathToUri $ cwd "test/testdata/gototest/src/Lib2.hs" + lreq = setTypecheckedModule u + req = liftToGhc $ TestDeferM $ findDef u (toPos (7,11)) + r <- dispatchRequestPGoto $ lreq >> req + r `shouldBe` IdeResultOk [Location (filePathToUri $ cwd "test/testdata/gototest/src/Lib2.hs") + (Range (toPos (10,9)) (toPos (10,10)))] + let req2 = liftToGhc $ TestDeferM $ findDef u (toPos (10,13)) + r2 <- dispatchRequestPGoto $ lreq >> req2 + r2 `shouldBe` IdeResultOk [Location (filePathToUri $ cwd "test/testdata/gototest/src/Lib2.hs") + (Range (toPos (9,9)) (toPos (9,10)))] + it "finds local definition of record variable" $ do + let u = filePathToUri $ cwd "test/testdata/gototest/src/Lib.hs" + lreq = setTypecheckedModule u + req = liftToGhc $ TestDeferM $ findTypeDef u (toPos (11, 23)) + r <- dispatchRequestPGoto $ lreq >> req + r `shouldBe` IdeResultOk + [ Location + (filePathToUri $ cwd "test/testdata/gototest/src/Lib.hs") + (Range (toPos (8, 1)) (toPos (8, 29))) + ] + it "finds local definition of newtype variable" $ do + let u = filePathToUri $ cwd "test/testdata/gototest/src/Lib.hs" + lreq = setTypecheckedModule u + req = liftToGhc $ TestDeferM $ findTypeDef u (toPos (16, 21)) + r <- dispatchRequestPGoto $ lreq >> req + r `shouldBe` IdeResultOk + [ Location + (filePathToUri $ cwd "test/testdata/gototest/src/Lib.hs") + (Range (toPos (13, 1)) (toPos (13, 30))) + ] + it "finds local definition of sum type variable" $ do + let u = filePathToUri $ cwd "test/testdata/gototest/src/Lib.hs" + lreq = setTypecheckedModule u + req = liftToGhc $ TestDeferM $ findTypeDef u (toPos (21, 13)) + r <- dispatchRequestPGoto $ lreq >> req + r `shouldBe` IdeResultOk + [ Location + (filePathToUri $ cwd "test/testdata/gototest/src/Lib.hs") + (Range (toPos (18, 1)) (toPos (18, 26))) + ] + it "finds local definition of sum type contructor" $ do + let u = filePathToUri $ cwd "test/testdata/gototest/src/Lib.hs" + lreq = setTypecheckedModule u + req = liftToGhc $ TestDeferM $ findTypeDef u (toPos (24, 7)) + r <- dispatchRequestPGoto $ lreq >> req + r `shouldBe` IdeResultOk + [ Location + (filePathToUri $ cwd "test/testdata/gototest/src/Lib.hs") + (Range (toPos (18, 1)) (toPos (18, 26))) + ] + it "can not find non-local definition of type def" $ do + let u = filePathToUri $ cwd "test/testdata/gototest/src/Lib.hs" + lreq = setTypecheckedModule u + req = liftToGhc $ TestDeferM $ findTypeDef u (toPos (30, 17)) + r <- dispatchRequestPGoto $ lreq >> req + r `shouldBe` IdeResultOk [] + it "find local definition of type def" $ do + let u = filePathToUri $ cwd "test/testdata/gototest/src/Lib.hs" + lreq = setTypecheckedModule u + req = liftToGhc $ TestDeferM $ findTypeDef u (toPos (35, 16)) + r <- dispatchRequestPGoto $ lreq >> req + r `shouldBe` IdeResultOk + [ Location + (filePathToUri $ cwd "test/testdata/gototest/src/Lib.hs") + (Range (toPos (18, 1)) (toPos (18, 26))) + ] + it "find type-definition of type def in component" $ do + let u = filePathToUri $ cwd "test/testdata/gototest/src/Lib2.hs" + lreq = setTypecheckedModule u + req = liftToGhc $ TestDeferM $ findTypeDef u (toPos (13, 20)) + r <- dispatchRequestPGoto $ lreq >> req + r `shouldBe` IdeResultOk + [ Location + (filePathToUri $ cwd "test/testdata/gototest/src/Lib.hs") + (Range (toPos (8, 1)) (toPos (8, 29))) + ] + it "find definition of parameterized data type" $ do + let u = filePathToUri $ cwd "test/testdata/gototest/src/Lib.hs" + lreq = setTypecheckedModule u + req = liftToGhc $ TestDeferM $ findTypeDef u (toPos (40, 19)) + r <- dispatchRequestPGoto $ lreq >> req + r `shouldBe` IdeResultOk + [ Location + (filePathToUri $ cwd "test/testdata/gototest/src/Lib.hs") + (Range (toPos (37, 1)) (toPos (37, 31))) + ] + + -- --------------------------------- + +newtype TestDeferM a = TestDeferM (IdeDeferM a) deriving (Functor, Applicative, Monad) +instance LiftsToGhc TestDeferM where + liftToGhc (TestDeferM (FreeT f)) = do + x <- liftToGhc f + case x of + Pure a -> return a + Free (Defer fp cb) -> do + fp' <- liftIO $ canonicalizePath fp + muc <- fmap (M.lookup fp' . uriCaches) getModuleCache + case muc of + Just uc -> liftToGhc $ TestDeferM $ cb uc + Nothing -> error "No cache to lift IdeDeferM to IdeGhcM" diff --git a/test/unit/JsonSpec.hs b/test/unit/JsonSpec.hs index 2fe2e4f12..6b13ee182 100644 --- a/test/unit/JsonSpec.hs +++ b/test/unit/JsonSpec.hs @@ -8,7 +8,7 @@ module JsonSpec where import Haskell.Ide.Engine.MonadTypes import Haskell.Ide.Engine.Plugin.ApplyRefact -import Haskell.Ide.Engine.Plugin.GhcMod +import Haskell.Ide.Engine.Plugin.Generic import Haskell.Ide.Engine.Plugin.HaRe import Haskell.Ide.Engine.Support.HieExtras import Haskell.Ide.Engine.Config diff --git a/test/utils/TestUtils.hs b/test/utils/TestUtils.hs index 468ca38a2..caa390cec 100644 --- a/test/utils/TestUtils.hs +++ b/test/utils/TestUtils.hs @@ -14,6 +14,7 @@ module TestUtils , hieCommandVomit , hieCommandExamplePlugin , getHspecFormattedConfig + , testOptions ) where import Control.Concurrent.STM @@ -38,6 +39,12 @@ import Test.Hspec.Runner import Test.Hspec.Core.Formatters import Text.Blaze.Renderer.String (renderMarkup) import Text.Blaze.Internal +import qualified Haskell.Ide.Engine.PluginApi as HIE (BiosOptions(..),BiosLogLevel(..),defaultOptions) + +import HIE.Bios.Types + +testOptions :: HIE.BiosOptions +testOptions = HIE.defaultOptions { cradleOptsVerbosity = Verbose } -- --------------------------------------------------------------------- From a305239eab5365b4ac9d63de65e63a08c6e631db Mon Sep 17 00:00:00 2001 From: Zubin Duggal Date: Tue, 16 Jul 2019 16:32:09 +0530 Subject: [PATCH 144/158] use upstream for hie-bios --- .gitmodules | 3 + hie-bios | 1 + hie-bios/.travis.yml | 34 ---- hie-bios/ChangeLog | 2 - hie-bios/LICENSE | 29 --- hie-bios/README.md | 132 -------------- hie-bios/Setup.hs | 2 - hie-bios/cabal.project | 1 - hie-bios/default.nix | 1 - hie-bios/exe/biosc.hs | 82 --------- hie-bios/hie-bios.cabal | 68 ------- hie-bios/nix/default.nix | 9 - hie-bios/nix/packages.nix | 3 - hie-bios/nix/sources.json | 23 --- hie-bios/nix/sources.nix | 26 --- hie-bios/shell.nix | 4 - hie-bios/src/HIE/Bios.hs | 20 -- hie-bios/src/HIE/Bios/Check.hs | 75 -------- hie-bios/src/HIE/Bios/Config.hs | 48 ----- hie-bios/src/HIE/Bios/Cradle.hs | 284 ----------------------------- hie-bios/src/HIE/Bios/Debug.hs | 33 ---- hie-bios/src/HIE/Bios/Doc.hs | 24 --- hie-bios/src/HIE/Bios/GHCApi.hs | 291 ------------------------------ hie-bios/src/HIE/Bios/Gap.hs | 129 ------------- hie-bios/src/HIE/Bios/Ghc.hs | 16 -- hie-bios/src/HIE/Bios/Internal.hs | 18 -- hie-bios/src/HIE/Bios/Load.hs | 121 ------------- hie-bios/src/HIE/Bios/Logger.hs | 124 ------------- hie-bios/src/HIE/Bios/Things.hs | 63 ------- hie-bios/src/HIE/Bios/Types.hs | 178 ------------------ hie-bios/wrappers/bazel | 5 - hie-bios/wrappers/cabal | 7 - 32 files changed, 4 insertions(+), 1852 deletions(-) create mode 160000 hie-bios delete mode 100644 hie-bios/.travis.yml delete mode 100644 hie-bios/ChangeLog delete mode 100644 hie-bios/LICENSE delete mode 100644 hie-bios/README.md delete mode 100644 hie-bios/Setup.hs delete mode 100644 hie-bios/cabal.project delete mode 100644 hie-bios/default.nix delete mode 100644 hie-bios/exe/biosc.hs delete mode 100644 hie-bios/hie-bios.cabal delete mode 100644 hie-bios/nix/default.nix delete mode 100644 hie-bios/nix/packages.nix delete mode 100644 hie-bios/nix/sources.json delete mode 100644 hie-bios/nix/sources.nix delete mode 100644 hie-bios/shell.nix delete mode 100644 hie-bios/src/HIE/Bios.hs delete mode 100644 hie-bios/src/HIE/Bios/Check.hs delete mode 100644 hie-bios/src/HIE/Bios/Config.hs delete mode 100644 hie-bios/src/HIE/Bios/Cradle.hs delete mode 100644 hie-bios/src/HIE/Bios/Debug.hs delete mode 100644 hie-bios/src/HIE/Bios/Doc.hs delete mode 100644 hie-bios/src/HIE/Bios/GHCApi.hs delete mode 100644 hie-bios/src/HIE/Bios/Gap.hs delete mode 100644 hie-bios/src/HIE/Bios/Ghc.hs delete mode 100644 hie-bios/src/HIE/Bios/Internal.hs delete mode 100644 hie-bios/src/HIE/Bios/Load.hs delete mode 100644 hie-bios/src/HIE/Bios/Logger.hs delete mode 100644 hie-bios/src/HIE/Bios/Things.hs delete mode 100644 hie-bios/src/HIE/Bios/Types.hs delete mode 100755 hie-bios/wrappers/bazel delete mode 100755 hie-bios/wrappers/cabal diff --git a/.gitmodules b/.gitmodules index 0a7d3cd22..bbfcb96fd 100644 --- a/.gitmodules +++ b/.gitmodules @@ -26,3 +26,6 @@ # url = https://github.com/arbor/ghc-mod.git url = https://github.com/alanz/ghc-mod.git #url = https://github.com/mpickering/ghc-mod.git +[submodule "hie-bios"] + path = hie-bios + url = https://github.com/mpickering/hie-bios diff --git a/hie-bios b/hie-bios new file mode 160000 index 000000000..8427e424a --- /dev/null +++ b/hie-bios @@ -0,0 +1 @@ +Subproject commit 8427e424a83c2f3d60bdd26c02478c00d2189a73 diff --git a/hie-bios/.travis.yml b/hie-bios/.travis.yml deleted file mode 100644 index 50e6c0b1a..000000000 --- a/hie-bios/.travis.yml +++ /dev/null @@ -1,34 +0,0 @@ -# NB: don't set `language: haskell` here - -# The following enables several GHC versions to be tested; often it's enough to test only against the last release in a major GHC version. Feel free to omit lines listings versions you don't need/want testing for. -env: - - CABALVER=1.24 GHCVER=8.0.2 - - CABALVER=2.0 GHCVER=8.2.2 - - CABALVER=2.2 GHCVER=8.4.4 - - CABALVER=2.4 GHCVER=8.6.3 - - CABALVER=head GHCVER=head # see section about GHC HEAD snapshots - -matrix: - allow_failures: - - env: CABALVER=head GHCVER=head - -# Note: the distinction between `before_install` and `install` is not important. -before_install: - - travis_retry sudo add-apt-repository -y ppa:hvr/ghc - - travis_retry sudo apt-get update - - travis_retry sudo apt-get install cabal-install-$CABALVER ghc-$GHCVER happy alex - - export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH - -install: - - cabal --version - - echo "$(ghc --version) [$(ghc --print-project-git-commit-id 2> /dev/null || echo '?')]" - - travis_retry cabal update - - cabal install --only-dependencies --enable-tests --enable-benchmarks - -# Here starts the actual work to be performed for the package under test; any command which exits with a non-zero exit code causes the build to fail. -script: - - if [ -f configure.ac ]; then autoreconf -i; fi - - cabal configure --enable-tests --enable-benchmarks -v2 # -v2 provides useful information for debugging - - cabal build # this builds all libraries and executables (including tests/benchmarks) - - cabal test - - cabal check diff --git a/hie-bios/ChangeLog b/hie-bios/ChangeLog deleted file mode 100644 index 03256aa3e..000000000 --- a/hie-bios/ChangeLog +++ /dev/null @@ -1,2 +0,0 @@ -2018-12-18 v0.0.0 - * First release diff --git a/hie-bios/LICENSE b/hie-bios/LICENSE deleted file mode 100644 index 542219308..000000000 --- a/hie-bios/LICENSE +++ /dev/null @@ -1,29 +0,0 @@ -Copyright (c) 2009, IIJ Innovation Institute Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - * Neither the name of the copyright holders nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. diff --git a/hie-bios/README.md b/hie-bios/README.md deleted file mode 100644 index 7a9f7af1c..000000000 --- a/hie-bios/README.md +++ /dev/null @@ -1,132 +0,0 @@ -# hie-bios - -`hie-bios` is the way which `hie` sets up a GHC API session. - -Its design is motivated by the guiding principle: - -> It is the responsibility of the build tool to describe the environment -> which a package should be built in. - -This means that it is possible -to easily support a wide range of tools including `cabal-install`, `stack`, -`rules_haskell`, `hadrian` and `obelisk` without major contortions. -`hie-bios` does not depend on the `Cabal` library nor does not -read any complicated build products and so on. - -How does a tool specify a session? A session is fully specified by a set of -standard GHC flags. Most tools already produce this information if they support -a `repl` command. Launching a repl is achieved by calling `ghci` with the -right flags to specify the package database. `hie-bios` needs a way to get -these flags and then it can set up GHC API session correctly. - -Futher it means that any failure to set up the API session is the responsibility -of the build tool. It is up to them to provide the correct information if they -want HIE to work correctly. - -## Explicit Configuration - -The user can place a `hie.dhall` file in the root of the workspace which -describes how to setup the environment. For example, to explicitly state -that you want to use `stack` then the configuration file would look like: - -``` -{ cradle = CradleConfig.Stack {=} } -``` - -If you use `cabal` then you probably need to specify which component you want -to use. - -``` -{ cradle = CradleConfig.Cabal { component = Some "lib:haskell-ide-engine" } } -``` - -Or you can explicitly state the program which should be used to collect -the options by supplying the path to the program. It is interpreted -relative to the current working directory if it is not an absolute path. - -``` -{ cradle = CradleConfig.Bios { prog = ".hie-bios" } } -``` - -The complete dhall configuration is described by the following type - -``` -< cradle : -< Cabal : { component : Optional Text } - | Stack : {} - | Bazel : {} - | Obelisk : {} - | Bios : { prog : Text} - | Default : {} > > -``` - -## Implicit Configuration - -There are several built in modes which captures most common Haskell development -scenarios. If no `hie.dhall` configuration file is found then an implicit -configuration is searched for. - -### Priority - -The targets are searched for in following order. - -1. A specific `hie-bios` file. -2. An `obelisk` project -3. A `rules_haskell` project -4. A `stack` project -4. A `cabal` project -5. The default cradle which has no specific options. - -### `cabal-install` - -The workspace root is the first folder containing a `cabal.project` file. - -The arguments are collected by running `cabal v2-repl`. - -If `cabal v2-repl` fails, then the user needs to configure the correct -target to use by writing a `hie.dhall` file. - -### `rules_haskell` - -The workspace root is the folder containing a `WORKSPACE` file. - -The options are collected by querying `bazel`. - -### `obelisk` - -The workspace root is the folder containing a `.obelisk` directory. - -The options are collected by running `ob ide-args`. - -### `bios` - -The most general form is the `bios` mode which allows a user to specify themselves -which flags to provide. - -In this mode, an executable file called `.hie-bios` is placed in the root -of the workspace directory. The script takes one argument, the filepath -to the current file we want to load into the session. The script returns -the correct arguments in order to load that file successfully. - -A good guiding specification for this file is that the following command -should work for any file in your project. - -``` -ghci $(./hie-bios /path/to/foo.hs) /path/to/foo.hs -``` - -This is useful if you are designing a new build system or the other modes -fail to setup the correct session for some reason. For example, this is -how hadrian (GHC's build system) is integrated into HIE. - - -## Relationship with `ghcid` - -The design of `hie-bios` is inspired by `ghcid`. Like `ghcid`, it does not depend -on any of the tools it supports. The success of `ghcid` is that it works reliably -in many situations. This is because of the fact that it delegates complicated -decisions about a build to the build tool. - -`ghcid` could be implemented using `hie-bios` using the `ghci $(./hie-bios Main.hs) Main.hs` -idiom described earlier. - diff --git a/hie-bios/Setup.hs b/hie-bios/Setup.hs deleted file mode 100644 index 9a994af67..000000000 --- a/hie-bios/Setup.hs +++ /dev/null @@ -1,2 +0,0 @@ -import Distribution.Simple -main = defaultMain diff --git a/hie-bios/cabal.project b/hie-bios/cabal.project deleted file mode 100644 index e6fdbadb4..000000000 --- a/hie-bios/cabal.project +++ /dev/null @@ -1 +0,0 @@ -packages: . diff --git a/hie-bios/default.nix b/hie-bios/default.nix deleted file mode 100644 index 9d1503167..000000000 --- a/hie-bios/default.nix +++ /dev/null @@ -1 +0,0 @@ -let pkgs = import ./nix {}; in pkgs.packages diff --git a/hie-bios/exe/biosc.hs b/hie-bios/exe/biosc.hs deleted file mode 100644 index 4fe85542b..000000000 --- a/hie-bios/exe/biosc.hs +++ /dev/null @@ -1,82 +0,0 @@ -{-# LANGUAGE DeriveDataTypeable #-} - -module Main where - -import Config (cProjectVersion) - -import Control.Exception (Exception, Handler(..), ErrorCall(..)) -import qualified Control.Exception as E -import Data.Typeable (Typeable) -import Data.Version (showVersion) -import System.Directory (getCurrentDirectory) -import System.Environment (getArgs) -import System.Exit (exitFailure) -import System.IO (hPutStr, hPutStrLn, stdout, stderr, hSetEncoding, utf8) - -import HIE.Bios -import HIE.Bios.Types -import HIE.Bios.Check -import HIE.Bios.Debug -import Paths_hie_bios - ----------------------------------------------------------------- - -progVersion :: String -progVersion = "biosc version " ++ showVersion version ++ " compiled by GHC " ++ cProjectVersion ++ "\n" - -ghcOptHelp :: String -ghcOptHelp = " [-g GHC_opt1 -g GHC_opt2 ...] " - -usage :: String -usage = progVersion - ++ "Usage:\n" - ++ "\t biosc check" ++ ghcOptHelp ++ "\n" - ++ "\t biosc version\n" - ++ "\t biosc help\n" - ----------------------------------------------------------------- - -data HhpcError = SafeList - | TooManyArguments String - | NoSuchCommand String - | CmdArg [String] - | FileNotExist String deriving (Show, Typeable) - -instance Exception HhpcError - ----------------------------------------------------------------- - -main :: IO () -main = flip E.catches handlers $ do - hSetEncoding stdout utf8 - args <- getArgs - cradle <- getCurrentDirectory >>= findCradle - let cmdArg0 = args !. 0 - remainingArgs = tail args - opt = defaultOptions - res <- case cmdArg0 of - "check" -> checkSyntax opt cradle remainingArgs - "expand" -> expandTemplate opt cradle remainingArgs - "debug" -> debugInfo opt cradle - "root" -> rootInfo opt cradle - "version" -> return progVersion - cmd -> E.throw (NoSuchCommand cmd) - putStr res - where - handlers = [Handler (handleThenExit handler1), Handler (handleThenExit handler2)] - handleThenExit handler e = handler e >> exitFailure - handler1 :: ErrorCall -> IO () - handler1 = print -- for debug - handler2 :: HhpcError -> IO () - handler2 SafeList = return () - handler2 (TooManyArguments cmd) = do - hPutStrLn stderr $ "\"" ++ cmd ++ "\": Too many arguments" - handler2 (NoSuchCommand cmd) = do - hPutStrLn stderr $ "\"" ++ cmd ++ "\" not supported" - handler2 (CmdArg errs) = do - mapM_ (hPutStr stderr) errs - handler2 (FileNotExist file) = do - hPutStrLn stderr $ "\"" ++ file ++ "\" not found" - xs !. idx - | length xs <= idx = E.throw SafeList - | otherwise = xs !! idx diff --git a/hie-bios/hie-bios.cabal b/hie-bios/hie-bios.cabal deleted file mode 100644 index 3bd5dc0ca..000000000 --- a/hie-bios/hie-bios.cabal +++ /dev/null @@ -1,68 +0,0 @@ -Name: hie-bios -Version: 0.0.0 -Author: Kazu Yamamoto and Matthew Pickering -Maintainer: Matthew Pickering -License: BSD3 -License-File: LICENSE -Homepage: https://github.com/mpickering/hie-bios -Synopsis: Set up a GHC API session -Description: - -Category: Development -Cabal-Version: >= 1.10 -Build-Type: Simple -Extra-Source-Files: ChangeLog - wrappers/bazel - wrappers/cabal - -Library - Default-Language: Haskell2010 - GHC-Options: -Wall - HS-Source-Dirs: src - Exposed-Modules: HIE.Bios - HIE.Bios.Check - HIE.Bios.Cradle - HIE.Bios.Debug - HIE.Bios.GHCApi - HIE.Bios.Gap - HIE.Bios.Doc - HIE.Bios.Load - HIE.Bios.Logger - HIE.Bios.Types - HIE.Bios.Things - HIE.Bios.Config - Build-Depends: base >= 4.9 && < 5 - , containers - , deepseq - , directory - , filepath - , ghc - , process - , transformers - , file-embed - , temporary - , unix-compat - , cryptohash-sha1 - , bytestring - , base16-bytestring - , dhall <= 1.20.1 - , text - , lens-family-core - if impl(ghc < 8.2) - Build-Depends: ghc-boot - -Executable biosc - Default-Language: Haskell2010 - Main-Is: biosc.hs - Other-Modules: Paths_hie_bios - GHC-Options: -Wall - HS-Source-Dirs: exe - Build-Depends: base >= 4.9 && < 5 - , directory - , filepath - , ghc - , hie-bios - -Source-Repository head - Type: git - Location: git://github.com/mpickering/hie-bios.git diff --git a/hie-bios/nix/default.nix b/hie-bios/nix/default.nix deleted file mode 100644 index 68e1cb236..000000000 --- a/hie-bios/nix/default.nix +++ /dev/null @@ -1,9 +0,0 @@ -{ sources ? import ./sources.nix }: -with - { overlay = _: pkgs: - { inherit (import sources.niv {}) niv; - packages = pkgs.callPackages ./packages.nix {}; - }; - }; -import sources.nixpkgs - { overlays = [ overlay ] ; config = {}; } diff --git a/hie-bios/nix/packages.nix b/hie-bios/nix/packages.nix deleted file mode 100644 index 1d9de7913..000000000 --- a/hie-bios/nix/packages.nix +++ /dev/null @@ -1,3 +0,0 @@ -{ writeScriptBin -}: -{ foo = writeScriptBin "foo" "echo foo" ; } diff --git a/hie-bios/nix/sources.json b/hie-bios/nix/sources.json deleted file mode 100644 index df329ce88..000000000 --- a/hie-bios/nix/sources.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "nixpkgs": { - "url": "https://github.com/NixOS/nixpkgs-channels/archive/19eedaf867da3155eec62721e0c8a02895aed74b.tar.gz", - "owner": "NixOS", - "branch": "nixos-unstable", - "url_template": "https://github.com///archive/.tar.gz", - "repo": "nixpkgs-channels", - "sha256": "06k0hmdn8l1wiirfjcym86pn9rdi8xyfh1any6vgb5nbx87al515", - "description": "Nixpkgs/NixOS branches that track the Nixpkgs/NixOS channels", - "rev": "19eedaf867da3155eec62721e0c8a02895aed74b" - }, - "niv": { - "homepage": "https://github.com/nmattia/niv", - "url": "https://github.com/nmattia/niv/archive/84692d2123b654da98f626bcf738f07cad3a2144.tar.gz", - "owner": "nmattia", - "branch": "master", - "url_template": "https://github.com///archive/.tar.gz", - "repo": "niv", - "sha256": "11j16q6rid8jrhrsanycsi86v0jhw07mp9c1n3yw8njj8gq4vfjq", - "description": "Easy dependency management for Nix projects", - "rev": "84692d2123b654da98f626bcf738f07cad3a2144" - } -} \ No newline at end of file diff --git a/hie-bios/nix/sources.nix b/hie-bios/nix/sources.nix deleted file mode 100644 index 30b77ce5f..000000000 --- a/hie-bios/nix/sources.nix +++ /dev/null @@ -1,26 +0,0 @@ -# A record, from name to path, of the third-party packages -with -{ - versions = builtins.fromJSON (builtins.readFile ./sources.json); - - # fetchTarball version that is compatible between all the versions of Nix - fetchTarball = - { url, sha256 }: - if builtins.lessThan builtins.nixVersion "1.12" then - builtins.fetchTarball { inherit url; } - else - builtins.fetchTarball { inherit url sha256; }; -}; - -# NOTE: spec must _not_ have an "outPath" attribute -builtins.mapAttrs (_: spec: - if builtins.hasAttr "outPath" spec - then abort - "The values in versions.json should not have an 'outPath' attribute" - else - if builtins.hasAttr "url" spec && builtins.hasAttr "sha256" spec - then - spec // - { outPath = fetchTarball { inherit (spec) url sha256; } ; } - else spec - ) versions diff --git a/hie-bios/shell.nix b/hie-bios/shell.nix deleted file mode 100644 index 37a5948cc..000000000 --- a/hie-bios/shell.nix +++ /dev/null @@ -1,4 +0,0 @@ -with { pkgs = import ./nix {}; }; -pkgs.mkShell - { buildInputs = [ pkgs.niv pkgs.haskell.compiler.ghc863 pkgs.haskell.packages.ghc863.cabal-install ]; - } diff --git a/hie-bios/src/HIE/Bios.hs b/hie-bios/src/HIE/Bios.hs deleted file mode 100644 index db2b0fd31..000000000 --- a/hie-bios/src/HIE/Bios.hs +++ /dev/null @@ -1,20 +0,0 @@ --- | The HIE Bios - -module HIE.Bios ( - -- * Initialise a session - Cradle(..) - , findCradle - , defaultCradle - , initializeFlagsWithCradle - , initializeFlagsWithCradleWithMessage - -- * Load a module into a session - , loadFile - , loadFileWithMessage - -- * Eliminate a session to IO - , withGhcT - ) where - -import HIE.Bios.Cradle -import HIE.Bios.Types -import HIE.Bios.GHCApi -import HIE.Bios.Load diff --git a/hie-bios/src/HIE/Bios/Check.hs b/hie-bios/src/HIE/Bios/Check.hs deleted file mode 100644 index 001eb24bb..000000000 --- a/hie-bios/src/HIE/Bios/Check.hs +++ /dev/null @@ -1,75 +0,0 @@ -module HIE.Bios.Check ( - checkSyntax - , check - , expandTemplate - , expand - ) where - -import DynFlags (dopt_set, DumpFlag(Opt_D_dump_splices)) -import GHC (Ghc, DynFlags(..), GhcMonad) - -import HIE.Bios.GHCApi -import HIE.Bios.Logger -import HIE.Bios.Types -import HIE.Bios.Load -import Outputable - ----------------------------------------------------------------- - --- | Checking syntax of a target file using GHC. --- Warnings and errors are returned. -checkSyntax :: Options - -> Cradle - -> [FilePath] -- ^ The target files. - -> IO String -checkSyntax _ _ [] = return "" -checkSyntax opt cradle files = withGhcT $ do - pprTrace "cradble" (text $ show cradle) (return ()) - initializeFlagsWithCradle (head files) cradle - either id id <$> check opt files - where - {- - sessionName = case files of - [file] -> file - _ -> "MultipleFiles" - -} - ----------------------------------------------------------------- - --- | Checking syntax of a target file using GHC. --- Warnings and errors are returned. -check :: (GhcMonad m) - => Options - -> [FilePath] -- ^ The target files. - -> m (Either String String) -check opt fileNames = withLogger opt setAllWaringFlags $ setTargetFiles (map dup fileNames) - -dup :: a -> (a, a) -dup x = (x, x) - ----------------------------------------------------------------- - --- | Expanding Haskell Template. -expandTemplate :: Options - -> Cradle - -> [FilePath] -- ^ The target files. - -> IO String -expandTemplate _ _ [] = return "" -expandTemplate opt cradle files = withGHC sessionName $ do - initializeFlagsWithCradle (head files) cradle - either id id <$> expand opt files - where - sessionName = case files of - [file] -> file - _ -> "MultipleFiles" - ----------------------------------------------------------------- - --- | Expanding Haskell Template. -expand :: Options - -> [FilePath] -- ^ The target files. - -> Ghc (Either String String) -expand opt fileNames = withLogger opt (setDumpSplices . setNoWaringFlags) $ setTargetFiles (map dup fileNames) - -setDumpSplices :: DynFlags -> DynFlags -setDumpSplices dflag = dopt_set dflag Opt_D_dump_splices diff --git a/hie-bios/src/HIE/Bios/Config.hs b/hie-bios/src/HIE/Bios/Config.hs deleted file mode 100644 index f4cb86831..000000000 --- a/hie-bios/src/HIE/Bios/Config.hs +++ /dev/null @@ -1,48 +0,0 @@ -{-# LANGUAGE DeriveGeneric #-} -{-# LANGUAGE OverloadedStrings #-} -{-# LANGUAGE TypeApplications #-} -module HIE.Bios.Config where - -import Dhall -import qualified Data.Text.IO as T -import qualified Data.Text as T --- import Lens.Family ( set ) --- import qualified Dhall.Context as C - - -data CradleConfig = Cabal { component :: Maybe String } - | Stack - | Bazel - | Obelisk - | Bios { prog :: FilePath } - | Default - deriving (Generic, Show) - -instance Interpret CradleConfig - -data Config = Config { cradle :: CradleConfig } - deriving (Generic, Show) - -instance Interpret Config - -wrapper :: T.Text -> T.Text -wrapper t = - "let CradleConfig : Type = < Cabal : { component : Optional Text } | Stack : {} | Bazel : {} | Obelisk : {} | Bios : { prog : Text} | Default : {} > in\n" <> t - -readConfig :: FilePath -> IO Config -readConfig fp = T.readFile fp >>= input auto . wrapper - where - -- ip = (set startingContext sc defaultInputSettings) - -- sc = C.insert "CradleConfig" (expected (auto @CradleConfig)) C.empty - -{- -stringToCC :: T.Text -> CradleConfig -stringToCC t = case t of - "cabal" -> Cabal - "stack" -> Stack - "rules_haskell" -> Bazel - "obelisk" -> Obelisk - "bios" -> Bios - "default" -> Default - _ -> Default - -} diff --git a/hie-bios/src/HIE/Bios/Cradle.hs b/hie-bios/src/HIE/Bios/Cradle.hs deleted file mode 100644 index 8d7705f45..000000000 --- a/hie-bios/src/HIE/Bios/Cradle.hs +++ /dev/null @@ -1,284 +0,0 @@ -{-# LANGUAGE TemplateHaskell #-} -{-# LANGUAGE TupleSections #-} -module HIE.Bios.Cradle ( - findCradle - , findCradleWithOpts - , defaultCradle - ) where - -import System.Process -import System.Exit -import HIE.Bios.Types -import HIE.Bios.Config -import System.Directory hiding (findFile) -import Control.Monad.Trans.Maybe -import System.FilePath -import Control.Monad -import Control.Monad.IO.Class -import Control.Applicative ((<|>)) -import Data.FileEmbed -import System.IO.Temp -import Data.List - -import Debug.Trace -import System.PosixCompat.Files - ----------------------------------------------------------------- -findCradle :: FilePath -> IO Cradle -findCradle = findCradleWithOpts defaultCradleOpts - --- | Finding 'Cradle'. --- Find a cabal file by tracing ancestor directories. --- Find a sandbox according to a cabal sandbox config --- in a cabal directory. -findCradleWithOpts :: CradleOpts -> FilePath -> IO Cradle -findCradleWithOpts _copts wfile = do - let wdir = takeDirectory wfile - cfg <- runMaybeT (dhallConfig wdir <|> implicitConfig wdir) - return $ case cfg of - Just bc -> getCradle bc - Nothing -> (defaultCradle wdir) - - -getCradle :: (CradleConfig, FilePath) -> Cradle -getCradle (cc, wdir) = case cc of - Cabal mc -> cabalCradle wdir mc - Stack -> stackCradle wdir - Bazel -> rulesHaskellCradle wdir - Obelisk -> obeliskCradle wdir - Bios bios -> biosCradle wdir bios - Default -> defaultCradle wdir - -implicitConfig :: FilePath -> MaybeT IO (CradleConfig, FilePath) -implicitConfig fp = - (\wdir -> (Bios (wdir ".hie-bios"), wdir)) <$> biosWorkDir fp - <|> (Obelisk,) <$> obeliskWorkDir fp - <|> (Bazel,) <$> rulesHaskellWorkDir fp - <|> (Stack,) <$> stackWorkDir fp - <|> ((Cabal Nothing,) <$> cabalWorkDir fp) - -dhallConfig :: FilePath -> MaybeT IO (CradleConfig, FilePath) -dhallConfig fp = do - wdir <- findFileUpwards ("hie.dhall" ==) fp - cfg <- liftIO $ readConfig (wdir "hie.dhall") - return (cradle cfg, wdir) - - - - ---------------------------------------------------------------- --- Default cradle has no special options, not very useful for loading --- modules. - -defaultCradle :: FilePath -> Cradle -defaultCradle cur_dir = - Cradle { - cradleRootDir = cur_dir - , cradleOptsProg = CradleAction "default" (const $ return (ExitSuccess, "", [])) - } - -------------------------------------------------------------------------- - - --- | Find a cradle by finding an executable `hie-bios` file which will --- be executed to find the correct GHC options to use. -biosCradle :: FilePath -> FilePath -> Cradle -biosCradle wdir bios = do - Cradle { - cradleRootDir = wdir - , cradleOptsProg = CradleAction "bios" (biosAction wdir bios) - } - -biosWorkDir :: FilePath -> MaybeT IO FilePath -biosWorkDir = findFileUpwards (".hie-bios" ==) - - -biosAction :: FilePath -> FilePath -> FilePath -> IO (ExitCode, String, [String]) -biosAction _wdir bios fp = do - bios' <- canonicalizePath bios - (ex, res, std) <- readProcessWithExitCode bios' [fp] [] - return (ex, std, words res) - ------------------------------------------------------------------------- --- Cabal Cradle --- Works for new-build by invoking `v2-repl` does not support components --- yet. - -cabalCradle :: FilePath -> Maybe String -> Cradle -cabalCradle wdir mc = do - Cradle { - cradleRootDir = wdir - , cradleOptsProg = CradleAction "cabal" (cabalAction wdir mc) - } - -cabalWrapper :: String -cabalWrapper = $(embedStringFile "wrappers/cabal") - -cabalAction :: FilePath -> Maybe String -> FilePath -> IO (ExitCode, String, [String]) -cabalAction work_dir mc _fp = do - wrapper_fp <- writeSystemTempFile "wrapper" cabalWrapper - -- TODO: This isn't portable for windows - setFileMode wrapper_fp accessModes - check <- readFile wrapper_fp - traceM check - let cab_args = ["v2-repl", "-v0", "-w", wrapper_fp] - ++ [component_name | Just component_name <- [mc]] - (ex, args, stde) <- - withCurrentDirectory work_dir (readProcessWithExitCode "cabal" cab_args []) - case lines args of - [dir, ghc_args] -> do - let final_args = removeInteractive $ map (fixImportDirs dir) (words ghc_args) - traceM dir - return (ex, stde, final_args) - _ -> error (show (ex, args, stde)) - -removeInteractive :: [String] -> [String] -removeInteractive = filter (/= "--interactive") - -fixImportDirs :: FilePath -> String -> String -fixImportDirs base_dir arg = - if "-i" `isPrefixOf` arg - then let dir = drop 2 arg - in if isRelative dir then ("-i" <> base_dir <> "/" <> dir) - else arg - else arg - - -cabalWorkDir :: FilePath -> MaybeT IO FilePath -cabalWorkDir = findFileUpwards isCabal - where - isCabal name = name == "cabal.project" - ------------------------------------------------------------------------- --- Stack Cradle --- Works for by invoking `stack repl` with a wrapper script - -stackCradle :: FilePath -> Cradle -stackCradle wdir = - Cradle { - cradleRootDir = wdir - , cradleOptsProg = CradleAction "stack" (stackAction wdir) - } - --- Same wrapper works as with cabal -stackWrapper :: String -stackWrapper = $(embedStringFile "wrappers/cabal") - -stackAction :: FilePath -> FilePath -> IO (ExitCode, String, [String]) -stackAction work_dir fp = do - wrapper_fp <- writeSystemTempFile "wrapper" stackWrapper - -- TODO: This isn't portable for windows - setFileMode wrapper_fp accessModes - check <- readFile wrapper_fp - traceM check - (ex1, args, stde) <- - withCurrentDirectory work_dir (readProcessWithExitCode "stack" ["repl", "--silent", "--no-load", "--with-ghc", wrapper_fp, fp ] []) - (ex2, pkg_args, stdr) <- - withCurrentDirectory work_dir (readProcessWithExitCode "stack" ["path", "--ghc-package-path"] []) - let split_pkgs = splitSearchPath (init pkg_args) - pkg_ghc_args = concatMap (\p -> ["-package-db", p] ) split_pkgs - ghc_args = words args ++ pkg_ghc_args - return (combineExitCodes [ex1, ex2], stde ++ stdr, ghc_args) - -combineExitCodes :: [ExitCode] -> ExitCode -combineExitCodes = foldr go ExitSuccess - where - go ExitSuccess b = b - go a _ = a - - - -stackWorkDir :: FilePath -> MaybeT IO FilePath -stackWorkDir = findFileUpwards isStack - where - isStack name = name == "stack.yaml" - - ----------------------------------------------------------------------------- --- rules_haskell - Thanks for David Smith for helping with this one. --- Looks for the directory containing a WORKSPACE file --- -rulesHaskellWorkDir :: FilePath -> MaybeT IO FilePath -rulesHaskellWorkDir fp = - findFileUpwards (== "WORKSPACE") fp - -rulesHaskellCradle :: FilePath -> Cradle -rulesHaskellCradle wdir = do - Cradle { - cradleRootDir = wdir - , cradleOptsProg = CradleAction "bazel" (rulesHaskellAction wdir) - } - - -bazelCommand :: String -bazelCommand = $(embedStringFile "wrappers/bazel") - -rulesHaskellAction :: FilePath -> FilePath -> IO (ExitCode, String, [String]) -rulesHaskellAction work_dir fp = do - wrapper_fp <- writeSystemTempFile "wrapper" bazelCommand - -- TODO: This isn't portable for windows - setFileMode wrapper_fp accessModes - check <- readFile wrapper_fp - traceM check - let rel_path = makeRelative work_dir fp - traceM rel_path - (ex, args, stde) <- - withCurrentDirectory work_dir (readProcessWithExitCode wrapper_fp [rel_path] []) - let args' = filter (/= '\'') args - let args'' = filter (/= "\"$GHCI_LOCATION\"") (words args') - return (ex, stde, args'') - - ------------------------------------------------------------------------------- --- Obelisk Cradle --- Searches for the directory which contains `.obelisk`. - -obeliskWorkDir :: FilePath -> MaybeT IO FilePath -obeliskWorkDir fp = do - -- Find a possible root which will contain the cabal.project - wdir <- findFileUpwards (== "cabal.project") fp - -- Check for the ".obelisk" folder in this directory - check <- liftIO $ doesDirectoryExist (wdir ".obelisk") - unless check (fail "Not obelisk dir") - return wdir - - -obeliskCradle :: FilePath -> Cradle -obeliskCradle wdir = - Cradle { - cradleRootDir = wdir - , cradleOptsProg = CradleAction "obelisk" (obeliskAction wdir) - } - -obeliskAction :: FilePath -> FilePath -> IO (ExitCode, String, [String]) -obeliskAction work_dir _fp = do - (ex, args, stde) <- - withCurrentDirectory work_dir (readProcessWithExitCode "ob" ["ide-args"] []) - return (ex, stde, words args) - - ------------------------------------------------------------------------------- --- Utilities - - --- | Searches upwards for the first directory containing a file to match --- the predicate. -findFileUpwards :: (FilePath -> Bool) -> FilePath -> MaybeT IO FilePath -findFileUpwards p dir = do - cnts <- liftIO $ findFile p dir - case cnts of - [] | dir' == dir -> fail "No cabal files" - | otherwise -> findFileUpwards p dir' - _:_ -> return dir - where - dir' = takeDirectory dir - --- | Sees if any file in the directory matches the predicate -findFile :: (FilePath -> Bool) -> FilePath -> IO [FilePath] -findFile p dir = getFiles >>= filterM doesPredFileExist - where - getFiles = filter p <$> getDirectoryContents dir - doesPredFileExist file = doesFileExist $ dir file - - - diff --git a/hie-bios/src/HIE/Bios/Debug.hs b/hie-bios/src/HIE/Bios/Debug.hs deleted file mode 100644 index e9a0970e2..000000000 --- a/hie-bios/src/HIE/Bios/Debug.hs +++ /dev/null @@ -1,33 +0,0 @@ -module HIE.Bios.Debug (debugInfo, rootInfo) where - -import CoreMonad (liftIO) - -import Data.Maybe (fromMaybe) - -import HIE.Bios.GHCApi -import HIE.Bios.Types - ----------------------------------------------------------------- - --- | Obtaining debug information. -debugInfo :: Options - -> Cradle - -> IO String -debugInfo opt cradle = convert opt <$> do - (_ex, _sterr, gopts) <- getOptions (cradleOptsProg cradle) (cradleRootDir cradle) - mglibdir <- liftIO getSystemLibDir - return [ - "Root directory: " ++ rootDir - , "GHC options: " ++ unwords gopts - , "System libraries: " ++ fromMaybe "" mglibdir - ] - where - rootDir = cradleRootDir cradle - ----------------------------------------------------------------- - --- | Obtaining root information. -rootInfo :: Options - -> Cradle - -> IO String -rootInfo opt cradle = return $ convert opt $ cradleRootDir cradle diff --git a/hie-bios/src/HIE/Bios/Doc.hs b/hie-bios/src/HIE/Bios/Doc.hs deleted file mode 100644 index 3504de25f..000000000 --- a/hie-bios/src/HIE/Bios/Doc.hs +++ /dev/null @@ -1,24 +0,0 @@ -module HIE.Bios.Doc where - -import GHC (DynFlags, getPrintUnqual, pprCols, GhcMonad) -import Outputable (PprStyle, SDoc, withPprStyleDoc, neverQualify) -import Pretty (Mode(..), Doc, Style(..), renderStyle, style) - -import HIE.Bios.Gap (makeUserStyle) - -showPage :: DynFlags -> PprStyle -> SDoc -> String -showPage dflag stl = showDocWith dflag PageMode . withPprStyleDoc dflag stl - -showOneLine :: DynFlags -> PprStyle -> SDoc -> String -showOneLine dflag stl = showDocWith dflag OneLineMode . withPprStyleDoc dflag stl - -getStyle :: (GhcMonad m) => DynFlags -> m PprStyle -getStyle dflags = makeUserStyle dflags <$> getPrintUnqual - -styleUnqualified :: DynFlags -> PprStyle -styleUnqualified dflags = makeUserStyle dflags neverQualify - -showDocWith :: DynFlags -> Mode -> Doc -> String -showDocWith dflags md = renderStyle mstyle - where - mstyle = style { mode = md, lineLength = pprCols dflags } diff --git a/hie-bios/src/HIE/Bios/GHCApi.hs b/hie-bios/src/HIE/Bios/GHCApi.hs deleted file mode 100644 index fdc101405..000000000 --- a/hie-bios/src/HIE/Bios/GHCApi.hs +++ /dev/null @@ -1,291 +0,0 @@ -{-# LANGUAGE ScopedTypeVariables, RecordWildCards, CPP #-} - -module HIE.Bios.GHCApi ( - withGHC - , withGHC' - , withGhcT - , initializeFlagsWithCradle - , initializeFlagsWithCradleWithMessage - , getDynamicFlags - , getSystemLibDir - , withDynFlags - , withCmdFlags - , setNoWaringFlags - , setAllWaringFlags - , CradleError(..) - ) where - -import CoreMonad (liftIO) -import Exception (ghandle, SomeException(..), ExceptionMonad(..), throwIO, Exception(..)) -import GHC (Ghc, DynFlags(..), GhcLink(..), HscTarget(..), LoadHowMuch(..), GhcMonad, GhcT) -import qualified GHC as G -import qualified Outputable as G -import qualified MonadUtils as G -import qualified HscMain as G -import qualified GhcMake as G -import DynFlags -import HscTypes -import GhcMonad -import DynamicLoading - -import Control.Monad (void, when) -import System.Exit (exitSuccess, ExitCode(..)) -import System.IO (hPutStr, hPrint, stderr) -import System.IO.Unsafe (unsafePerformIO) -import System.Process (readProcess) - -import System.Directory -import System.FilePath - -import qualified HIE.Bios.Gap as Gap -import HIE.Bios.Types -import Debug.Trace -import qualified Crypto.Hash.SHA1 as H -import qualified Data.ByteString.Char8 as B -import Data.ByteString.Base16 -import Data.List - ----------------------------------------------------------------- - --- | Obtaining the directory for system libraries. -getSystemLibDir :: IO (Maybe FilePath) -getSystemLibDir = do - res <- readProcess "ghc" ["--print-libdir"] [] - return $ case res of - "" -> Nothing - dirn -> Just (init dirn) - ----------------------------------------------------------------- - --- | Converting the 'Ghc' monad to the 'IO' monad. -withGHC :: FilePath -- ^ A target file displayed in an error message. - -> Ghc a -- ^ 'Ghc' actions created by the Ghc utilities. - -> IO a -withGHC file body = ghandle ignore $ withGHC' body - where - ignore :: SomeException -> IO a - ignore e = do - hPutStr stderr $ file ++ ":0:0:Error:" - hPrint stderr e - exitSuccess - -withGHC' :: Ghc a -> IO a -withGHC' body = do - mlibdir <- getSystemLibDir - G.runGhc mlibdir body - -withGhcT :: (Exception.ExceptionMonad m, G.MonadIO m, Monad m) => GhcT m a -> m a -withGhcT body = do - mlibdir <- G.liftIO $ getSystemLibDir - G.runGhcT mlibdir body - ----------------------------------------------------------------- - -data Build = CabalPkg | SingleFile deriving Eq - -initializeFlagsWithCradle :: - (GhcMonad m) - => FilePath -- The file we are loading it because of - -> Cradle - -> m () -initializeFlagsWithCradle = initializeFlagsWithCradleWithMessage (Just G.batchMsg) - --- | Initialize the 'DynFlags' relating to the compilation of a single --- file or GHC session according to the 'Cradle' and 'Options' --- provided. -initializeFlagsWithCradleWithMessage :: - (GhcMonad m) - => Maybe G.Messager - -> FilePath -- The file we are loading it because of - -> Cradle - -> m () -initializeFlagsWithCradleWithMessage msg fp cradle = do - (ex, err, ghcOpts) <- liftIO $ getOptions (cradleOptsProg cradle) fp - G.pprTrace "res" (G.text (show (ex, err, ghcOpts, fp))) (return ()) - case ex of - ExitFailure _ -> throwCradleError err - _ -> return () - let compOpts = CompilerOptions ghcOpts - liftIO $ hPrint stderr ghcOpts - initSessionWithMessage msg compOpts - -data CradleError = CradleError String deriving (Show) - -instance Exception CradleError where - -throwCradleError :: GhcMonad m => String -> m () -throwCradleError = liftIO . throwIO . CradleError - ----------------------------------------------------------------- -cacheDir :: String -cacheDir = "haskell-ide-engine" - -clearInterfaceCache :: FilePath -> IO () -clearInterfaceCache fp = do - cd <- getCacheDir fp - res <- doesPathExist cd - when res (removeDirectoryRecursive cd) - -getCacheDir :: FilePath -> IO FilePath -getCacheDir fp = getXdgDirectory XdgCache (cacheDir ++ "/" ++ fp) - -initSessionWithMessage :: (GhcMonad m) - => Maybe G.Messager - -> CompilerOptions - -> m () -initSessionWithMessage msg CompilerOptions {..} = do - df <- G.getSessionDynFlags - traceShowM (length ghcOptions) - - let opts_hash = B.unpack $ encode $ H.finalize $ H.updates H.init (map B.pack ghcOptions) - fp <- liftIO $ getCacheDir opts_hash - -- For now, clear the cache initially rather than persist it across - -- sessions - liftIO $ clearInterfaceCache opts_hash - (df', targets) <- addCmdOpts ghcOptions df - void $ G.setSessionDynFlags - (disableOptimisation - $ setIgnoreInterfacePragmas - $ resetPackageDb --- $ ignorePackageEnv - $ writeInterfaceFiles (Just fp) - -- $ setOutputDir fp - $ setVerbosity 0 - - $ setLinkerOptions df' - ) - hsc_env <- G.getSession - dflags <- G.getSessionDynFlags >>= liftIO . initializePlugins hsc_env - modifySession $ \h -> h { hsc_dflags = dflags } - G.setLogAction (\_df _wr _s _ss _pp _m -> return ()) - G.setTargets targets - -- Get the module graph using the function `getModuleGraph` - mod_graph <- G.depanal [] True - void $ G.load' LoadAllTargets msg mod_graph - ----------------------------------------------------------------- - --- we don't want to generate object code so we compile to bytecode --- (HscInterpreted) which implies LinkInMemory --- HscInterpreted -setLinkerOptions :: DynFlags -> DynFlags -setLinkerOptions df = df { - ghcLink = LinkInMemory - , hscTarget = HscNothing - , ghcMode = CompManager - } - -resetPackageDb :: DynFlags -> DynFlags -resetPackageDb df = df { pkgDatabase = Nothing } - ---ignorePackageEnv :: DynFlags -> DynFlags ---ignorePackageEnv df = df { packageEnv = Just "-" } - -setIgnoreInterfacePragmas :: DynFlags -> DynFlags -setIgnoreInterfacePragmas df = gopt_set df Opt_IgnoreInterfacePragmas - -setVerbosity :: Int -> DynFlags -> DynFlags -setVerbosity n df = df { verbosity = n } - -writeInterfaceFiles :: Maybe FilePath -> DynFlags -> DynFlags -writeInterfaceFiles Nothing df = df -writeInterfaceFiles (Just hi_dir) df = setHiDir hi_dir (gopt_set df Opt_WriteInterface) - -setHiDir :: FilePath -> DynFlags -> DynFlags -setHiDir f d = d { hiDir = Just f} - - -addCmdOpts :: (GhcMonad m) - => [String] -> DynFlags -> m (DynFlags, [G.Target]) -addCmdOpts cmdOpts df1 = do - (df2, leftovers, warns) <- G.parseDynamicFlags df1 (map G.noLoc cmdOpts) - traceShowM (map G.unLoc leftovers, length warns) - - let - -- To simplify the handling of filepaths, we normalise all filepaths right - -- away. Note the asymmetry of FilePath.normalise: - -- Linux: p/q -> p/q; p\q -> p\q - -- Windows: p/q -> p\q; p\q -> p\q - -- #12674: Filenames starting with a hypen get normalised from ./-foo.hs - -- to -foo.hs. We have to re-prepend the current directory. - normalise_hyp fp - | strt_dot_sl && "-" `isPrefixOf` nfp = cur_dir ++ nfp - | otherwise = nfp - where -#if defined(mingw32_HOST_OS) - strt_dot_sl = "./" `isPrefixOf` fp || ".\\" `isPrefixOf` fp -#else - strt_dot_sl = "./" `isPrefixOf` fp -#endif - cur_dir = '.' : [pathSeparator] - nfp = normalise fp - normal_fileish_paths = map (normalise_hyp . G.unLoc) leftovers - ts <- mapM (flip G.guessTarget Nothing) normal_fileish_paths - return (df2, ts) - -- TODO: Need to handle these as well - -- Ideally it requires refactoring to work in GHCi monad rather than - -- Ghc monad and then can just use newDynFlags. - {- - liftIO $ G.handleFlagWarnings idflags1 warns - when (not $ null leftovers) - (throwGhcException . CmdLineError - $ "Some flags have not been recognized: " - ++ (concat . intersperse ", " $ map unLoc leftovers)) - when (interactive_only && packageFlagsChanged idflags1 idflags0) $ do - liftIO $ hPutStrLn stderr "cannot set package flags with :seti; use :set" - -} - ----------------------------------------------------------------- - - ----------------------------------------------------------------- - --- | Return the 'DynFlags' currently in use in the GHC session. -getDynamicFlags :: IO DynFlags -getDynamicFlags = do - mlibdir <- getSystemLibDir - G.runGhc mlibdir G.getSessionDynFlags - -withDynFlags :: - (GhcMonad m) - => (DynFlags -> DynFlags) -> m a -> m a -withDynFlags setFlag body = G.gbracket setup teardown (\_ -> body) - where - setup = do - dflag <- G.getSessionDynFlags - void $ G.setSessionDynFlags (setFlag dflag) - return dflag - teardown = void . G.setSessionDynFlags - -withCmdFlags :: - (GhcMonad m) - => [String] -> m a -> m a -withCmdFlags flags body = G.gbracket setup teardown (\_ -> body) - where - setup = do - (dflag, _) <- G.getSessionDynFlags >>= addCmdOpts flags - void $ G.setSessionDynFlags dflag - return dflag - teardown = void . G.setSessionDynFlags - ----------------------------------------------------------------- - --- | Set 'DynFlags' equivalent to "-w:". -setNoWaringFlags :: DynFlags -> DynFlags -setNoWaringFlags df = df { warningFlags = Gap.emptyWarnFlags} - --- | Set 'DynFlags' equivalent to "-Wall". -setAllWaringFlags :: DynFlags -> DynFlags -setAllWaringFlags df = df { warningFlags = allWarningFlags } - -disableOptimisation :: DynFlags -> DynFlags -disableOptimisation df = updOptLevel 0 df - -{-# NOINLINE allWarningFlags #-} -allWarningFlags :: Gap.WarnFlags -allWarningFlags = unsafePerformIO $ do - mlibdir <- getSystemLibDir - G.runGhcT mlibdir $ do - df <- G.getSessionDynFlags - (df', _) <- addCmdOpts ["-Wall"] df - return $ G.warningFlags df' diff --git a/hie-bios/src/HIE/Bios/Gap.hs b/hie-bios/src/HIE/Bios/Gap.hs deleted file mode 100644 index 6270705e9..000000000 --- a/hie-bios/src/HIE/Bios/Gap.hs +++ /dev/null @@ -1,129 +0,0 @@ -{-# LANGUAGE TypeSynonymInstances, FlexibleInstances, CPP #-} - -module HIE.Bios.Gap ( - WarnFlags - , emptyWarnFlags - , makeUserStyle - , getModuleName - , getTyThing - , fixInfo - , getModSummaries - , LExpression - , LBinding - , LPattern - , inTypes - , outType - ) where - -import DynFlags (DynFlags) -import GHC(LHsBind, LHsExpr, LPat, Type) -import HsExpr (MatchGroup) -import Outputable (PrintUnqualified, PprStyle, Depth(AllTheWay), mkUserStyle) - ----------------------------------------------------------------- ----------------------------------------------------------------- - -#if __GLASGOW_HASKELL__ >= 802 -#else -import GHC.PackageDb (ExposedModule(..)) -#endif - -#if __GLASGOW_HASKELL__ >= 804 -import DynFlags (WarningFlag) -import qualified EnumSet as E (EnumSet, empty) -import GHC (mgModSummaries, ModSummary, ModuleGraph) -#else -import qualified Data.IntSet as I (IntSet, empty) -#endif - -#if __GLASGOW_HASKELL__ >= 806 -import HsExpr (MatchGroupTc(..)) -import HsExtension (GhcTc) -import GHC (mg_ext) -#elif __GLASGOW_HASKELL__ >= 804 -import HsExtension (GhcTc) -import GHC (mg_res_ty, mg_arg_tys) -#else -import GHC (Id, mg_res_ty, mg_arg_tys) -#endif - ----------------------------------------------------------------- ----------------------------------------------------------------- - -makeUserStyle :: DynFlags -> PrintUnqualified -> PprStyle -#if __GLASGOW_HASKELL__ >= 802 -makeUserStyle dflags style = mkUserStyle dflags style AllTheWay -#else -makeUserStyle _ style = mkUserStyle style AllTheWay -#endif - -#if __GLASGOW_HASKELL__ >= 802 -getModuleName :: (a, b) -> a -getModuleName = fst -#else -getModuleName :: ExposedModule unitid modulename -> modulename -getModuleName = exposedName -#endif - ----------------------------------------------------------------- - -#if __GLASGOW_HASKELL__ >= 804 -type WarnFlags = E.EnumSet WarningFlag -emptyWarnFlags :: WarnFlags -emptyWarnFlags = E.empty -#else -type WarnFlags = I.IntSet -emptyWarnFlags :: WarnFlags -emptyWarnFlags = I.empty -#endif - -#if __GLASGOW_HASKELL__ >= 804 -getModSummaries :: ModuleGraph -> [ModSummary] -getModSummaries = mgModSummaries - -getTyThing :: (a, b, c, d, e) -> a -getTyThing (t,_,_,_,_) = t - -fixInfo :: (a, b, c, d, e) -> (a, b, c, d) -fixInfo (t,f,cs,fs,_) = (t,f,cs,fs) -#else -getModSummaries :: a -> a -getModSummaries = id - -getTyThing :: (a, b, c, d) -> a -getTyThing (t,_,_,_) = t - -fixInfo :: (a, b, c, d) -> (a, b, c, d) -fixInfo = id -#endif - ----------------------------------------------------------------- - -#if __GLASGOW_HASKELL__ >= 806 -type LExpression = LHsExpr GhcTc -type LBinding = LHsBind GhcTc -type LPattern = LPat GhcTc - -inTypes :: MatchGroup GhcTc LExpression -> [Type] -inTypes = mg_arg_tys . mg_ext -outType :: MatchGroup GhcTc LExpression -> Type -outType = mg_res_ty . mg_ext -#elif __GLASGOW_HASKELL__ >= 804 -type LExpression = LHsExpr GhcTc -type LBinding = LHsBind GhcTc -type LPattern = LPat GhcTc - -inTypes :: MatchGroup GhcTc LExpression -> [Type] -inTypes = mg_arg_tys -outType :: MatchGroup GhcTc LExpression -> Type -outType = mg_res_ty -#else -type LExpression = LHsExpr Id -type LBinding = LHsBind Id -type LPattern = LPat Id - -inTypes :: MatchGroup Id LExpression -> [Type] -inTypes = mg_arg_tys -outType :: MatchGroup Id LExpression -> Type -outType = mg_res_ty -#endif diff --git a/hie-bios/src/HIE/Bios/Ghc.hs b/hie-bios/src/HIE/Bios/Ghc.hs deleted file mode 100644 index dcef200a3..000000000 --- a/hie-bios/src/HIE/Bios/Ghc.hs +++ /dev/null @@ -1,16 +0,0 @@ --- | The Happy Haskell Programming library. --- API for interactive processes - -module HIE.Bios.Ghc ( - -- * Converting the Ghc monad to the IO monad - withGHC - , withGHC' - -- * Initializing DynFlags - , initializeFlagsWithCradle - -- * Ghc utilities - -- * Misc - , getSystemLibDir - ) where - -import HIE.Bios.Check -import HIE.Bios.GHCApi diff --git a/hie-bios/src/HIE/Bios/Internal.hs b/hie-bios/src/HIE/Bios/Internal.hs deleted file mode 100644 index 198f8f331..000000000 --- a/hie-bios/src/HIE/Bios/Internal.hs +++ /dev/null @@ -1,18 +0,0 @@ --- | The Happy Haskell Programming library in low level. - -module HIE.Bios.Internal ( - -- * Types - CompilerOptions(..) - -- * IO - , getDynamicFlags - -- * Targets - , setTargetFiles - -- * Logging - , withLogger - , setNoWaringFlags - , setAllWaringFlags - ) where - -import HIE.Bios.GHCApi -import HIE.Bios.Logger -import HIE.Bios.Types diff --git a/hie-bios/src/HIE/Bios/Load.hs b/hie-bios/src/HIE/Bios/Load.hs deleted file mode 100644 index 92f18ec16..000000000 --- a/hie-bios/src/HIE/Bios/Load.hs +++ /dev/null @@ -1,121 +0,0 @@ -{-# LANGUAGE ScopedTypeVariables #-} -{-# LANGUAGE CPP #-} -module HIE.Bios.Load ( loadFileWithMessage, loadFile, setTargetFiles, setTargetFilesWithMessage) where - -import CoreMonad (liftIO) -import DynFlags (gopt_set, wopt_set, WarningFlag(Opt_WarnTypedHoles)) -import GHC -import qualified GHC as G -import qualified GhcMake as G -import qualified HscMain as G -import HscTypes -import Outputable - -import Data.IORef - -import HIE.Bios.GHCApi -import System.Directory -import Hooks -import TcRnTypes (FrontendResult(..)) -import Control.Monad (forM, void) -import GhcMonad -import HscMain -import Debug.Trace -import Data.List - -#if __GLASGOW_HASKELL__ < 806 -pprTraceM x s = pprTrace x s (return ()) -#endif - --- | Obtaining type of a target expression. (GHCi's type:) -loadFileWithMessage :: GhcMonad m - => Maybe G.Messager - -> (FilePath, FilePath) -- ^ A target file. - -> m (Maybe TypecheckedModule, [TypecheckedModule]) -loadFileWithMessage msg file = do - dir <- liftIO $ getCurrentDirectory - pprTraceM "loadFile:2" (text dir) - withDynFlags (setWarnTypedHoles . setNoWaringFlags) $ do - - df <- getSessionDynFlags - pprTraceM "loadFile:3" (ppr $ optLevel df) - (_, tcs) <- collectASTs (setTargetFilesWithMessage msg [file]) - pprTraceM "loaded" (text (fst file) $$ text (snd file)) - let get_fp = ml_hs_file . ms_location . pm_mod_summary . tm_parsed_module - traceShowM ("tms", (map get_fp tcs)) - let findMod [] = Nothing - findMod (x:xs) = case get_fp x of - Just fp -> if fp `isSuffixOf` (snd file) then Just x else findMod xs - Nothing -> findMod xs - return (findMod tcs, tcs) - -loadFile :: (GhcMonad m) - => (FilePath, FilePath) - -> m (Maybe TypecheckedModule, [TypecheckedModule]) -loadFile = loadFileWithMessage (Just G.batchMsg) - -{- -fileModSummary :: GhcMonad m => FilePath -> m ModSummary -fileModSummary file = do - mss <- getModSummaries <$> G.getModuleGraph - let [ms] = filter (\m -> G.ml_hs_file (G.ms_location m) == Just file) mss - return ms - -} - - -setDeferTypeErrors :: DynFlags -> DynFlags -setDeferTypeErrors dflag = gopt_set dflag G.Opt_DeferTypeErrors - -setWarnTypedHoles :: DynFlags -> DynFlags -setWarnTypedHoles dflag = wopt_set dflag Opt_WarnTypedHoles - -setTargetFiles :: GhcMonad m => [(FilePath, FilePath)] -> m () -setTargetFiles = setTargetFilesWithMessage (Just G.batchMsg) - --- | Set the files as targets and load them. -setTargetFilesWithMessage :: (GhcMonad m) => Maybe G.Messager -> [(FilePath, FilePath)] -> m () -setTargetFilesWithMessage msg files = do - targets <- forM files guessTargetMapped - pprTrace "setTargets" (vcat (map ppr files) $$ ppr targets) (return ()) - G.setTargets (map (\t -> t { G.targetAllowObjCode = False }) targets) - mod_graph <- depanal [] False - void $ G.load' LoadAllTargets msg mod_graph - -collectASTs :: (GhcMonad m) => m a -> m (a, [TypecheckedModule]) -collectASTs action = do - dflags0 <- getSessionDynFlags - ref1 <- liftIO $ newIORef [] - let dflags1 = dflags0 { hooks = (hooks dflags0) - { hscFrontendHook = Just (astHook ref1) } } - void $ setSessionDynFlags dflags1 - res <- action - tcs <- liftIO $ readIORef ref1 - return (res, tcs) - -astHook :: IORef [TypecheckedModule] -> ModSummary -> Hsc FrontendResult -astHook tc_ref ms = ghcInHsc $ do - p <- G.parseModule ms - tcm <- G.typecheckModule p - let tcg_env = fst (tm_internals_ tcm) - liftIO $ modifyIORef tc_ref (tcm :) - return $ FrontendTypecheck tcg_env - -ghcInHsc :: Ghc a -> Hsc a -ghcInHsc gm = do - hsc_session <- getHscEnv - session <- liftIO $ newIORef hsc_session - liftIO $ reflectGhc gm (Session session) - - - - -guessTargetMapped :: (GhcMonad m) => (FilePath, FilePath) -> m Target -guessTargetMapped (orig_file_name, mapped_file_name) = do - t <- G.guessTarget orig_file_name Nothing - return (setTargetFilename mapped_file_name t) - -setTargetFilename :: FilePath -> Target -> Target -setTargetFilename fn t = - t { targetId = case targetId t of - TargetFile _ p -> TargetFile fn p - tid -> tid } diff --git a/hie-bios/src/HIE/Bios/Logger.hs b/hie-bios/src/HIE/Bios/Logger.hs deleted file mode 100644 index d66ff27f3..000000000 --- a/hie-bios/src/HIE/Bios/Logger.hs +++ /dev/null @@ -1,124 +0,0 @@ -{-# LANGUAGE BangPatterns #-} - -module HIE.Bios.Logger ( - withLogger - , checkErrorPrefix - , getSrcSpan - ) where - -import Bag (Bag, bagToList) -import CoreMonad (liftIO) -import DynFlags (LogAction, dopt, DumpFlag(Opt_D_dump_splices)) -import ErrUtils -import Exception (ghandle) -import FastString (unpackFS) -import GHC (DynFlags(..), SrcSpan(..), Severity(SevError), GhcMonad) -import qualified GHC as G -import HscTypes (SourceError, srcErrorMessages) -import Outputable (PprStyle, SDoc) - -import Data.IORef (IORef, newIORef, readIORef, writeIORef, modifyIORef) -import Data.List (isPrefixOf) -import Data.Maybe (fromMaybe) -import System.FilePath (normalise) - -import HIE.Bios.Doc (showPage, getStyle) -import HIE.Bios.GHCApi (withDynFlags, withCmdFlags) -import HIE.Bios.Types (Options(..), convert) - ----------------------------------------------------------------- - -type Builder = [String] -> [String] - -newtype LogRef = LogRef (IORef Builder) - -newLogRef :: IO LogRef -newLogRef = LogRef <$> newIORef id - -readAndClearLogRef :: Options -> LogRef -> IO String -readAndClearLogRef opt (LogRef ref) = do - b <- readIORef ref - writeIORef ref id - return $! convert opt (b []) - -appendLogRef :: DynFlags -> LogRef -> LogAction -appendLogRef df (LogRef ref) _ _ sev src style msg = do - let !l = ppMsg src sev df style msg - modifyIORef ref (\b -> b . (l:)) - ----------------------------------------------------------------- - --- | Set the session flag (e.g. "-Wall" or "-w:") then --- executes a body. Log messages are returned as 'String'. --- Right is success and Left is failure. -withLogger :: - (GhcMonad m) - => Options -> (DynFlags -> DynFlags) -> m () -> m (Either String String) -withLogger opt setDF body = ghandle (sourceError opt) $ do - logref <- liftIO newLogRef - withDynFlags (setLogger logref . setDF) $ do - withCmdFlags wflags $ do - body - liftIO $ Right <$> readAndClearLogRef opt logref - where - setLogger logref df = df { log_action = appendLogRef df logref } - wflags = filter ("-fno-warn" `isPrefixOf`) $ ghcOpts opt - ----------------------------------------------------------------- - --- | Converting 'SourceError' to 'String'. -sourceError :: - (GhcMonad m) - => Options -> SourceError -> m (Either String String) -sourceError opt err = do - dflag <- G.getSessionDynFlags - style <- getStyle dflag - let ret = convert opt . errBagToStrList dflag style . srcErrorMessages $ err - return (Left ret) - -errBagToStrList :: DynFlags -> PprStyle -> Bag ErrMsg -> [String] -errBagToStrList dflag style = map (ppErrMsg dflag style) . reverse . bagToList - ----------------------------------------------------------------- - -ppErrMsg :: DynFlags -> PprStyle -> ErrMsg -> String -ppErrMsg dflag style err = ppMsg spn SevError dflag style msg -- ++ ext - where - spn = errMsgSpan err - msg = pprLocErrMsg err - -- fixme --- ext = showPage dflag style (pprLocErrMsg $ errMsgReason err) - -ppMsg :: SrcSpan -> Severity-> DynFlags -> PprStyle -> SDoc -> String -ppMsg spn sev dflag style msg = prefix ++ cts - where - cts = showPage dflag style msg - defaultPrefix - | isDumpSplices dflag = "" - | otherwise = checkErrorPrefix - prefix = fromMaybe defaultPrefix $ do - (line,col,_,_) <- getSrcSpan spn - file <- normalise <$> getSrcFile spn - let severityCaption = showSeverityCaption sev - return $ file ++ ":" ++ show line ++ ":" ++ show col ++ ":" ++ severityCaption - -checkErrorPrefix :: String -checkErrorPrefix = "Dummy:0:0:Error:" - -showSeverityCaption :: Severity -> String -showSeverityCaption SevWarning = "Warning: " -showSeverityCaption _ = "" - -getSrcFile :: SrcSpan -> Maybe String -getSrcFile (G.RealSrcSpan spn) = Just . unpackFS . G.srcSpanFile $ spn -getSrcFile _ = Nothing - -isDumpSplices :: DynFlags -> Bool -isDumpSplices dflag = dopt Opt_D_dump_splices dflag - -getSrcSpan :: SrcSpan -> Maybe (Int,Int,Int,Int) -getSrcSpan (RealSrcSpan spn) = Just ( G.srcSpanStartLine spn - , G.srcSpanStartCol spn - , G.srcSpanEndLine spn - , G.srcSpanEndCol spn) -getSrcSpan _ = Nothing diff --git a/hie-bios/src/HIE/Bios/Things.hs b/hie-bios/src/HIE/Bios/Things.hs deleted file mode 100644 index 577eb5652..000000000 --- a/hie-bios/src/HIE/Bios/Things.hs +++ /dev/null @@ -1,63 +0,0 @@ -module HIE.Bios.Things ( - GapThing(..) - , fromTyThing - , infoThing - ) where - -import ConLike (ConLike(..)) -import FamInstEnv -import GHC -import HscTypes -import qualified InstEnv -import NameSet -import Outputable -import PatSyn -import PprTyThing -import Var (varType) - -import Data.List (intersperse) -import Data.Maybe (catMaybes) - -import HIE.Bios.Gap (getTyThing, fixInfo) - --- from ghc/InteractiveUI.hs - ----------------------------------------------------------------- - -data GapThing = GtA Type - | GtT TyCon - | GtN - | GtPatSyn PatSyn - -fromTyThing :: TyThing -> GapThing -fromTyThing (AnId i) = GtA $ varType i -fromTyThing (AConLike (RealDataCon d)) = GtA $ dataConUserType d -fromTyThing (AConLike (PatSynCon p)) = GtPatSyn p -fromTyThing (ATyCon t) = GtT t -fromTyThing _ = GtN - ----------------------------------------------------------------- - -infoThing :: String -> Ghc SDoc -infoThing str = do - names <- parseName str - mb_stuffs <- mapM (getInfo False) names - let filtered = filterOutChildren getTyThing $ catMaybes mb_stuffs - return $ vcat (intersperse (text "") $ map (pprInfo . fixInfo) filtered) - -filterOutChildren :: (a -> TyThing) -> [a] -> [a] -filterOutChildren get_thing xs - = [x | x <- xs, not (getName (get_thing x) `elemNameSet` implicits)] - where - implicits = mkNameSet [getName t | x <- xs, t <- implicitTyThings (get_thing x)] - -pprInfo :: (TyThing, GHC.Fixity, [InstEnv.ClsInst], [FamInst]) -> SDoc -pprInfo (thing, fixity, insts, famInsts) - = pprTyThingInContextLoc thing - $$ show_fixity fixity - $$ InstEnv.pprInstances insts - $$ pprFamInsts famInsts - where - show_fixity fx - | fx == defaultFixity = Outputable.empty - | otherwise = ppr fx <+> ppr (getName thing) diff --git a/hie-bios/src/HIE/Bios/Types.hs b/hie-bios/src/HIE/Bios/Types.hs deleted file mode 100644 index 1bee1ec9e..000000000 --- a/hie-bios/src/HIE/Bios/Types.hs +++ /dev/null @@ -1,178 +0,0 @@ -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE ScopedTypeVariables #-} -{-# OPTIONS_GHC -Wno-orphans #-} - -module HIE.Bios.Types where - -import qualified Exception as GE -import GHC (Ghc) - -import Control.Exception (IOException) -import Control.Applicative (Alternative(..)) -import System.Exit -import System.IO - -data BIOSVerbosity = Silent | Verbose - -data CradleOpts = CradleOpts - { cradleOptsVerbosity :: BIOSVerbosity - , cradleOptsHandle :: Maybe Handle - -- ^ The handle where to send output to, if not set, stderr - } - -defaultCradleOpts :: CradleOpts -defaultCradleOpts = CradleOpts Silent Nothing - --- | Output style. -data OutputStyle = LispStyle -- ^ S expression style. - | PlainStyle -- ^ Plain textstyle. - --- | The type for line separator. Historically, a Null string is used. -newtype LineSeparator = LineSeparator String - -data Options = Options { - outputStyle :: OutputStyle - , hlintOpts :: [String] - , ghcOpts :: [String] - -- | If 'True', 'browse' also returns operators. - , operators :: Bool - -- | If 'True', 'browse' also returns types. - , detailed :: Bool - -- | If 'True', 'browse' will return fully qualified name - , qualified :: Bool - -- | Line separator string. - , lineSeparator :: LineSeparator - } - --- | A default 'Options'. -defaultOptions :: Options -defaultOptions = Options { - outputStyle = PlainStyle - , hlintOpts = [] - , ghcOpts = [] - , operators = False - , detailed = False - , qualified = False - , lineSeparator = LineSeparator "\0" - } - ----------------------------------------------------------------- - -type Builder = String -> String - --- | --- --- >>> replace '"' "\\\"" "foo\"bar" "" --- "foo\\\"bar" -replace :: Char -> String -> String -> Builder -replace _ _ [] = id -replace c cs (x:xs) - | x == c = (cs ++) . replace c cs xs - | otherwise = (x :) . replace c cs xs - -inter :: Char -> [Builder] -> Builder -inter _ [] = id -inter c bs = foldr1 (\x y -> x . (c:) . y) bs - -convert :: ToString a => Options -> a -> String -convert opt@Options { outputStyle = LispStyle } x = toLisp opt x "\n" -convert opt@Options { outputStyle = PlainStyle } x - | str == "\n" = "" - | otherwise = str - where - str = toPlain opt x "\n" - -class ToString a where - toLisp :: Options -> a -> Builder - toPlain :: Options -> a -> Builder - -lineSep :: Options -> String -lineSep opt = lsep - where - LineSeparator lsep = lineSeparator opt - --- | --- --- >>> toLisp defaultOptions "fo\"o" "" --- "\"fo\\\"o\"" --- >>> toPlain defaultOptions "foo" "" --- "foo" -instance ToString String where - toLisp opt = quote opt - toPlain opt = replace '\n' (lineSep opt) - --- | --- --- >>> toLisp defaultOptions ["foo", "bar", "ba\"z"] "" --- "(\"foo\" \"bar\" \"ba\\\"z\")" --- >>> toPlain defaultOptions ["foo", "bar", "baz"] "" --- "foo\nbar\nbaz" -instance ToString [String] where - toLisp opt = toSexp1 opt - toPlain opt = inter '\n' . map (toPlain opt) - --- | --- --- >>> let inp = [((1,2,3,4),"foo"),((5,6,7,8),"bar")] :: [((Int,Int,Int,Int),String)] --- >>> toLisp defaultOptions inp "" --- "((1 2 3 4 \"foo\") (5 6 7 8 \"bar\"))" --- >>> toPlain defaultOptions inp "" --- "1 2 3 4 \"foo\"\n5 6 7 8 \"bar\"" -instance ToString [((Int,Int,Int,Int),String)] where - toLisp opt = toSexp2 . map toS - where - toS x = ('(' :) . tupToString opt x . (')' :) - toPlain opt = inter '\n' . map (tupToString opt) - -toSexp1 :: Options -> [String] -> Builder -toSexp1 opt ss = ('(' :) . inter ' ' (map (quote opt) ss) . (')' :) - -toSexp2 :: [Builder] -> Builder -toSexp2 ss = ('(' :) . inter ' ' ss . (')' :) - -tupToString :: Options -> ((Int,Int,Int,Int),String) -> Builder -tupToString opt ((a,b,c,d),s) = (show a ++) . (' ' :) - . (show b ++) . (' ' :) - . (show c ++) . (' ' :) - . (show d ++) . (' ' :) - . quote opt s -- fixme: quote is not necessary - -quote :: Options -> String -> Builder -quote opt str = ("\"" ++) . (quote' str ++) . ("\"" ++) - where - lsep = lineSep opt - quote' [] = [] - quote' (x:xs) - | x == '\n' = lsep ++ quote' xs - | x == '\\' = "\\\\" ++ quote' xs - | x == '"' = "\\\"" ++ quote' xs - | otherwise = x : quote' xs - ----------------------------------------------------------------- - --- | The environment where this library is used. -data Cradle = Cradle { - -- | The project root directory. - cradleRootDir :: FilePath - -- | The action which needs to be executed to get the correct - -- command line arguments - , cradleOptsProg :: CradleAction - } deriving (Show) - -data CradleAction = CradleAction { - actionName :: String - , getOptions :: (FilePath -> IO (ExitCode, String, [String])) - } - -instance Show CradleAction where - show (CradleAction name _) = "CradleAction: " ++ name ----------------------------------------------------------------- - --- | Option information for GHC -data CompilerOptions = CompilerOptions { - ghcOptions :: [String] -- ^ Command line options - } deriving (Eq, Show) - -instance Alternative Ghc where - x <|> y = x `GE.gcatch` (\(_ :: IOException) -> y) - empty = undefined diff --git a/hie-bios/wrappers/bazel b/hie-bios/wrappers/bazel deleted file mode 100755 index 1624cea61..000000000 --- a/hie-bios/wrappers/bazel +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash -fullname=$(bazel query "$1") -attr=$(bazel query "kind(haskell_*, attr('srcs', $fullname, ${fullname//:*/}:*))") -bazel build "$attr@repl" --experimental_show_artifacts 2>&1 | sed -ne '/>>>/ s/^>>>\(.*\)$/\1/ p' | xargs tail -1 - diff --git a/hie-bios/wrappers/cabal b/hie-bios/wrappers/cabal deleted file mode 100755 index a83ad3fdb..000000000 --- a/hie-bios/wrappers/cabal +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash -if [ "$1" == "--interactive" ]; then - pwd - echo "$@" -else - ghc "$@" -fi From 580b188345d3927ced054dd89213750adcb0bb60 Mon Sep 17 00:00:00 2001 From: Zubin Duggal Date: Tue, 16 Jul 2019 17:14:47 +0530 Subject: [PATCH 145/158] fix HaRe submodule --- .gitmodules | 2 +- submodules/HaRe | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index bbfcb96fd..a2bf98a22 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,7 +13,7 @@ [submodule "submodules/HaRe"] path = submodules/HaRe # url = https://github.com/bubba/HaRe.git - url = https://github.com/alanz/HaRe.git + url = https://github.com/wz1000/HaRe.git [submodule "submodules/cabal-helper"] path = submodules/cabal-helper diff --git a/submodules/HaRe b/submodules/HaRe index 9de2e991b..03de75229 160000 --- a/submodules/HaRe +++ b/submodules/HaRe @@ -1 +1 @@ -Subproject commit 9de2e991b005d15f9fbe5c5d4ed303630cd19d80 +Subproject commit 03de7522995a3b192c3a2b010539d02e753e3d3d From 2c8b51b00f64b59e9e3e7c70ec808afd95e01be2 Mon Sep 17 00:00:00 2001 From: Zubin Duggal Date: Sat, 20 Jul 2019 11:07:26 +0530 Subject: [PATCH 146/158] Fix some tests and completions/session saving --- hie-plugin-api/Haskell/Ide/Engine/Ghc.hs | 3 ++- .../Haskell/Ide/Engine/PluginsIdeMonads.hs | 2 +- src/Haskell/Ide/Engine/Plugin/Haddock.hs | 3 +-- src/Haskell/Ide/Engine/Support/HieExtras.hs | 16 ++++++++++------ test/dispatcher/Main.hs | 14 +++++++------- test/testdata/.hie-bios | 1 + test/testdata/FuncTestFail.hs | 2 +- test/testdata/addPackageTest/cabal-exe/.hie-bios | 1 + test/testdata/addPackageTest/cabal-lib/.hie-bios | 1 + test/testdata/badProjects/cabal/.hie-bios | 1 + test/testdata/definition/.hie-bios | 1 + test/testdata/gototest/.hie-bios | 1 + test/testdata/redundantImportTest/.hie-bios | 1 + test/testdata/wErrorTest/.hie-bios | 1 + test/utils/TestUtils.hs | 2 +- 15 files changed, 31 insertions(+), 19 deletions(-) create mode 100755 test/testdata/.hie-bios create mode 100755 test/testdata/addPackageTest/cabal-exe/.hie-bios create mode 100755 test/testdata/addPackageTest/cabal-lib/.hie-bios create mode 100755 test/testdata/badProjects/cabal/.hie-bios create mode 100755 test/testdata/definition/.hie-bios create mode 100755 test/testdata/gototest/.hie-bios create mode 100755 test/testdata/redundantImportTest/.hie-bios create mode 100755 test/testdata/wErrorTest/.hie-bios diff --git a/hie-plugin-api/Haskell/Ide/Engine/Ghc.hs b/hie-plugin-api/Haskell/Ide/Engine/Ghc.hs index 77923e93c..52f2acc57 100644 --- a/hie-plugin-api/Haskell/Ide/Engine/Ghc.hs +++ b/hie-plugin-api/Haskell/Ide/Engine/Ghc.hs @@ -260,7 +260,8 @@ setTypecheckedModule_load uri = -- set the session before we cache the module, so that deferred -- responses triggered by cacheModule can access it - --modifyMTS (\s -> s {ghcSession = sess}) + sess <- getSession + modifyMTS (\s -> s {ghcSession = Just sess}) cacheModules rfm ts --cacheModules rfm [tm] debugm "setTypecheckedModule: done" diff --git a/hie-plugin-api/Haskell/Ide/Engine/PluginsIdeMonads.hs b/hie-plugin-api/Haskell/Ide/Engine/PluginsIdeMonads.hs index 025ca91af..1f2ea65c5 100644 --- a/hie-plugin-api/Haskell/Ide/Engine/PluginsIdeMonads.hs +++ b/hie-plugin-api/Haskell/Ide/Engine/PluginsIdeMonads.hs @@ -487,7 +487,7 @@ data IdeState = IdeState -- | A queue of requests to be performed once a module is loaded , requestQueue :: Map.Map FilePath [UriCacheResult -> IdeM ()] , extensibleState :: !(Map.Map TypeRep Dynamic) - , ghcSession :: Maybe (IORef HscEnv) + , ghcSession :: Maybe HscEnv } instance MonadMTState IdeState IdeGhcM where diff --git a/src/Haskell/Ide/Engine/Plugin/Haddock.hs b/src/Haskell/Ide/Engine/Plugin/Haddock.hs index 12b75e05c..31bc5fee9 100644 --- a/src/Haskell/Ide/Engine/Plugin/Haddock.hs +++ b/src/Haskell/Ide/Engine/Plugin/Haddock.hs @@ -86,8 +86,7 @@ nameCacheFromGhcMonad = ( read_from_session , write_to_session ) runInLightGhc :: Ghc a -> IdeM a runInLightGhc a = do - hscEnvRef <- ghcSession <$> readMTS - mhscEnv <- liftIO $ traverse readIORef hscEnvRef + mhscEnv <- ghcSession <$> readMTS liftIO $ case mhscEnv of Nothing -> error "Ghc Session not initialized" Just env -> do diff --git a/src/Haskell/Ide/Engine/Support/HieExtras.hs b/src/Haskell/Ide/Engine/Support/HieExtras.hs index 2fa45fcb5..b3ad8dced 100644 --- a/src/Haskell/Ide/Engine/Support/HieExtras.hs +++ b/src/Haskell/Ide/Engine/Support/HieExtras.hs @@ -24,6 +24,7 @@ module Haskell.Ide.Engine.Support.HieExtras , getFormattingPlugin ) where +import TcRnTypes import ConLike import Control.Lens.Operators ( (^?), (?~) ) import Control.Lens.Prism ( _Just ) @@ -224,6 +225,8 @@ instance ModuleCache CachedCompletions where languagesAndExts = map T.pack GHC.supportedLanguagesAndExtensions typeEnv = md_types $ snd $ tm_internals_ tm + typeEnv' = tcg_type_env $ fst $ tm_internals_ tm + rdrev = tcg_rdr_env $ fst $ tm_internals_ tm toplevelVars = mapMaybe safeTyThingId $ typeEnvElts typeEnv varToCompl :: Var -> CompItem @@ -307,11 +310,14 @@ instance ModuleCache CachedCompletions where return $ varType tyid return $ ci { thingType = typ } - hscEnvRef <- ghcSession <$> readMTS - hscEnv <- liftIO $ traverse readIORef hscEnvRef + hscEnv <- ghcSession <$> readMTS + (unquals, quals) <- maybe (pure ([], Map.empty)) (\env -> liftIO $ do sess <- newIORef env + debugm $ GHC.showPpr (hsc_dflags env) typeEnv + debugm $ GHC.showPpr (hsc_dflags env) typeEnv' + debugm $ GHC.showPpr (hsc_dflags env) rdrev reflectGhc (getModCompls env) (Session sess)) hscEnv return $ CC @@ -484,8 +490,7 @@ getCompletions uri prefixInfo (WithSnippets withSnippets) = getTypeForName :: Name -> IdeM (Maybe Type) getTypeForName n = do - hscEnvRef <- ghcSession <$> readMTS - mhscEnv <- liftIO $ traverse readIORef hscEnvRef + mhscEnv <- ghcSession <$> readMTS case mhscEnv of Nothing -> return Nothing Just hscEnv -> do @@ -653,8 +658,7 @@ srcSpanToFileLocation invoker rfm srcSpan = do -- | Goto given module. gotoModule :: (FilePath -> FilePath) -> ModuleName -> IdeDeferM (IdeResult [Location]) gotoModule rfm mn = do - hscEnvRef <- ghcSession <$> readMTS - mHscEnv <- liftIO $ traverse readIORef hscEnvRef + mHscEnv <- ghcSession <$> readMTS case mHscEnv of Just env -> do fr <- liftIO $ do diff --git a/test/dispatcher/Main.hs b/test/dispatcher/Main.hs index 9cc939d5d..302ab2403 100644 --- a/test/dispatcher/Main.hs +++ b/test/dispatcher/Main.hs @@ -93,15 +93,15 @@ logToChan c t = atomically $ writeTChan c t -- --------------------------------------------------------------------- dispatchGhcRequest :: ToJSON a - => TrackingNumber -> String -> Int + => TrackingNumber -> Maybe Uri -> String -> Int -> Scheduler IO -> TChan LogVal -> PluginId -> CommandName -> a -> IO () -dispatchGhcRequest tn ctx n scheduler lc plugin com arg = do +dispatchGhcRequest tn uri ctx n scheduler lc plugin com arg = do let logger :: RequestCallback IO DynamicJSON logger x = logToChan lc (ctx, Right x) - let req = GReq tn Nothing Nothing (Just (IdInt n)) logger $ + let req = GReq tn uri Nothing (Just (IdInt n)) logger $ runPluginCommand plugin com (toJSON arg) sendRequest scheduler Nothing req @@ -164,7 +164,7 @@ funcSpec = describe "functional dispatch" $ do show rrr `shouldBe` "Nothing" -- need to typecheck the module to trigger deferred response - dispatchGhcRequest 2 "req2" 2 scheduler logChan "bios" "check" (toJSON testUri) + dispatchGhcRequest 2 (Just testUri) "req2" 2 scheduler logChan "bios" "check" (toJSON testUri) -- And now we get the deferred response (once the module is loaded) ("req1",Right res) <- atomically $ readTChan logChan @@ -242,7 +242,7 @@ funcSpec = describe "functional dispatch" $ do it "returns hints as diagnostics" $ do - dispatchGhcRequest 5 "r5" 5 scheduler logChan "applyrefact" "lint" testUri + dispatchGhcRequest 5 (Just testUri) "r5" 5 scheduler logChan "applyrefact" "lint" testUri hr5 <- atomically $ readTChan logChan unpackRes hr5 `shouldBe` ("r5", @@ -261,7 +261,7 @@ funcSpec = describe "functional dispatch" $ do ) let req6 = HP testUri (toPos (8, 1)) - dispatchGhcRequest 6 "r6" 6 scheduler logChan "hare" "demote" req6 + dispatchGhcRequest 6 (Just testUri) "r6" 6 scheduler logChan "hare" "demote" req6 hr6 <- atomically $ readTChan logChan -- show hr6 `shouldBe` "hr6" @@ -277,7 +277,7 @@ funcSpec = describe "functional dispatch" $ do dispatchIdeRequest 7 "req7" scheduler logChan (IdInt 7) $ findDef testFailUri (Position 1 2) - dispatchGhcRequest 8 "req8" 8 scheduler logChan "bios" "check" (toJSON testFailUri) + dispatchGhcRequest 8 (Just testUri) "req8" 8 scheduler logChan "bios" "check" (toJSON testFailUri) hr7 <- atomically $ readTChan logChan unpackRes hr7 `shouldBe` ("req7", Just ([] :: [Location])) diff --git a/test/testdata/.hie-bios b/test/testdata/.hie-bios new file mode 100755 index 000000000..80ff32c69 --- /dev/null +++ b/test/testdata/.hie-bios @@ -0,0 +1 @@ +cabal-helper-helper . $1 diff --git a/test/testdata/FuncTestFail.hs b/test/testdata/FuncTestFail.hs index 610cbee4c..ac61d1113 100644 --- a/test/testdata/FuncTestFail.hs +++ b/test/testdata/FuncTestFail.hs @@ -1,2 +1,2 @@ main :: IO Int -main = return "yow" \ No newline at end of file +main = return "yow diff --git a/test/testdata/addPackageTest/cabal-exe/.hie-bios b/test/testdata/addPackageTest/cabal-exe/.hie-bios new file mode 100755 index 000000000..80ff32c69 --- /dev/null +++ b/test/testdata/addPackageTest/cabal-exe/.hie-bios @@ -0,0 +1 @@ +cabal-helper-helper . $1 diff --git a/test/testdata/addPackageTest/cabal-lib/.hie-bios b/test/testdata/addPackageTest/cabal-lib/.hie-bios new file mode 100755 index 000000000..80ff32c69 --- /dev/null +++ b/test/testdata/addPackageTest/cabal-lib/.hie-bios @@ -0,0 +1 @@ +cabal-helper-helper . $1 diff --git a/test/testdata/badProjects/cabal/.hie-bios b/test/testdata/badProjects/cabal/.hie-bios new file mode 100755 index 000000000..80ff32c69 --- /dev/null +++ b/test/testdata/badProjects/cabal/.hie-bios @@ -0,0 +1 @@ +cabal-helper-helper . $1 diff --git a/test/testdata/definition/.hie-bios b/test/testdata/definition/.hie-bios new file mode 100755 index 000000000..80ff32c69 --- /dev/null +++ b/test/testdata/definition/.hie-bios @@ -0,0 +1 @@ +cabal-helper-helper . $1 diff --git a/test/testdata/gototest/.hie-bios b/test/testdata/gototest/.hie-bios new file mode 100755 index 000000000..80ff32c69 --- /dev/null +++ b/test/testdata/gototest/.hie-bios @@ -0,0 +1 @@ +cabal-helper-helper . $1 diff --git a/test/testdata/redundantImportTest/.hie-bios b/test/testdata/redundantImportTest/.hie-bios new file mode 100755 index 000000000..80ff32c69 --- /dev/null +++ b/test/testdata/redundantImportTest/.hie-bios @@ -0,0 +1 @@ +cabal-helper-helper . $1 diff --git a/test/testdata/wErrorTest/.hie-bios b/test/testdata/wErrorTest/.hie-bios new file mode 100755 index 000000000..80ff32c69 --- /dev/null +++ b/test/testdata/wErrorTest/.hie-bios @@ -0,0 +1 @@ +cabal-helper-helper . $1 diff --git a/test/utils/TestUtils.hs b/test/utils/TestUtils.hs index caa390cec..470c25584 100644 --- a/test/utils/TestUtils.hs +++ b/test/utils/TestUtils.hs @@ -167,7 +167,7 @@ logFilePath = "functional-hie-" ++ stackYaml ++ ".log" -- run with `stack test` hieCommand :: String hieCommand = "stack exec --no-stack-exe --no-ghc-package-path --stack-yaml=" ++ stackYaml ++ - " hie -- -d -l test-logs/" ++ logFilePath + " hie -- --bios-verbose -d -l test-logs/" ++ logFilePath hieCommandVomit :: String hieCommandVomit = hieCommand ++ " --vomit" From 6ad2a6d82ebd719076c39c595bac319788aa8d44 Mon Sep 17 00:00:00 2001 From: Zubin Duggal Date: Sat, 20 Jul 2019 12:55:16 +0530 Subject: [PATCH 147/158] Simplify completions - missing type info for non local names --- src/Haskell/Ide/Engine/Support/HieExtras.hs | 134 +++++++------------- 1 file changed, 45 insertions(+), 89 deletions(-) diff --git a/src/Haskell/Ide/Engine/Support/HieExtras.hs b/src/Haskell/Ide/Engine/Support/HieExtras.hs index c2cc1a085..aaf70ffa5 100644 --- a/src/Haskell/Ide/Engine/Support/HieExtras.hs +++ b/src/Haskell/Ide/Engine/Support/HieExtras.hs @@ -50,9 +50,11 @@ import FastString import Finder import GHC hiding (getContext) import GHC.Generics (Generic) +import TcRnTypes +import RdrName import qualified GhcMod as GM (splits',SplitResult(..)) -import qualified GhcModCore as GM (GhcModError(..), listVisibleModuleNames,runLightGhc, withMappedFile ) +import qualified GhcModCore as GM (GhcModError(..), listVisibleModuleNames, withMappedFile ) import Haskell.Ide.Engine.ArtifactMap import Haskell.Ide.Engine.Config @@ -194,16 +196,25 @@ safeTyThingId (AConLike (RealDataCon dc)) = Just $ dataConWrapId dc safeTyThingId _ = Nothing -- Associates a module's qualifier with its members -type QualCompls = Map.Map T.Text [CompItem] +newtype QualCompls = QualCompls { getQualCompls :: Map.Map T.Text [CompItem] } + +instance Semigroup QualCompls where + (QualCompls a) <> (QualCompls b) = QualCompls $ Map.unionWith (++) a b + +instance Monoid QualCompls where + mempty = QualCompls Map.empty data CachedCompletions = CC { allModNamesAsNS :: [T.Text] , unqualCompls :: [CompItem] , qualCompls :: QualCompls , importableModules :: [T.Text] - , cachedExtensions :: [T.Text] } deriving (Typeable) +-- The supported languages and extensions +languagesAndExts :: [T.Text] +languagesAndExts = map T.pack GHC.supportedLanguagesAndExtensions + instance ModuleCache CachedCompletions where cacheDataProducer tm _ = do let parsedMod = tm_parsed_module tm @@ -227,11 +238,32 @@ instance ModuleCache CachedCompletions where -- The given namespaces for the imported modules (ie. full name, or alias if used) allModNamesAsNS = map (showModName . asNamespace) importDeclerations - -- The supported languages and extensions - languagesAndExts = map T.pack GHC.supportedLanguagesAndExtensions - - typeEnv = md_types $ snd $ tm_internals_ tm - toplevelVars = mapMaybe safeTyThingId $ typeEnvElts typeEnv + typeEnv = tcg_type_env $ fst $ tm_internals_ tm + rdrEnv = tcg_rdr_env $ fst $ tm_internals_ tm + rdrElts = globalRdrEnvElts rdrEnv + + getCompls :: [GlobalRdrElt] -> ([CompItem],QualCompls) + getCompls = foldMap getComplsForOne + + getComplsForOne :: GlobalRdrElt -> ([CompItem],QualCompls) + getComplsForOne (GRE n _ True _) = + case lookupTypeEnv typeEnv n of + Just tt -> case safeTyThingId tt of + Just var -> ([varToCompl var],mempty) + Nothing -> ([toCompItem curMod n],mempty) + Nothing -> ([toCompItem curMod n],mempty) + getComplsForOne (GRE n _ False prov) = + flip foldMap (map is_decl prov) $ \spec -> + let unqual + | is_qual spec = [] + | otherwise = compItem + qual + | is_qual spec = Map.singleton asMod compItem + | otherwise = Map.fromList [(asMod,compItem),(origMod,compItem)] + compItem = [toCompItem (is_mod spec) n] + asMod = showModName (is_as spec) + origMod = showModName (is_mod spec) + in (unqual,QualCompls qual) varToCompl :: Var -> CompItem varToCompl var = CI name (showModName curMod) typ label Nothing @@ -240,92 +272,16 @@ instance ModuleCache CachedCompletions where name = Var.varName var label = T.pack $ showGhc name - toplevelCompls :: [CompItem] - toplevelCompls = map varToCompl toplevelVars - toCompItem :: ModuleName -> Name -> CompItem toCompItem mn n = CI n (showModName mn) Nothing (T.pack $ showGhc n) Nothing - allImportsInfo :: [(Bool, T.Text, ModuleName, Maybe (Bool, [Name]))] - allImportsInfo = map getImpInfo importDeclerations - where - getImpInfo imp = - let modName = iDeclToModName imp - modQual = showModName (asNamespace imp) - isQual = ideclQualified imp - hasHiddsMembers = - case ideclHiding imp of - Nothing -> Nothing - Just (hasHiddens, L _ liens) -> - Just (hasHiddens, concatMap (ieNames . unLoc) liens) - in (isQual, modQual, modName, hasHiddsMembers) - - getModCompls :: GhcMonad m => HscEnv -> m ([CompItem], QualCompls) - getModCompls hscEnv = do - (unquals, qualKVs) <- foldM (orgUnqualQual hscEnv) ([], []) allImportsInfo - return (unquals, Map.fromListWith (++) qualKVs) - - orgUnqualQual hscEnv (prevUnquals, prevQualKVs) (isQual, modQual, modName, hasHiddsMembers) = - let - ifUnqual xs = if isQual then prevUnquals else prevUnquals ++ xs - setTypes = setComplsType hscEnv - in - case hasHiddsMembers of - Just (False, members) -> do - compls <- setTypes (map (toCompItem modName) members) - return - ( ifUnqual compls - , (modQual, compls) : prevQualKVs - ) - Just (True , members) -> do - let hiddens = map (toCompItem modName) members - allCompls <- getComplsFromModName modName - compls <- setTypes (allCompls List.\\ hiddens) - return - ( ifUnqual compls - , (modQual, compls) : prevQualKVs - ) - Nothing -> do - -- debugm $ "///////// Nothing " ++ (show modQual) - compls <- setTypes =<< getComplsFromModName modName - return - ( ifUnqual compls - , (modQual, compls) : prevQualKVs - ) - - getComplsFromModName :: GhcMonad m - => ModuleName -> m [CompItem] - getComplsFromModName mn = do - mminf <- getModuleInfo =<< findModule mn Nothing - return $ case mminf of - Nothing -> [] - Just minf -> map (toCompItem mn) $ modInfoExports minf - - setComplsType :: (Traversable t, MonadIO m) - => HscEnv -> t CompItem -> m (t CompItem) - setComplsType hscEnv xs = - liftIO $ forM xs $ \ci@CI{origName} -> do - mt <- (Just <$> lookupGlobal hscEnv origName) - `catch` \(_ :: SourceError) -> return Nothing - let typ = do - t <- mt - tyid <- safeTyThingId t - return $ varType tyid - return $ ci { thingType = typ } - - hscEnvRef <- ghcSession <$> readMTS - hscEnv <- liftIO $ traverse readIORef hscEnvRef - (unquals, quals) <- maybe - (pure ([], Map.empty)) - (\env -> GM.runLightGhc env (getModCompls env)) - hscEnv + (unquals,quals) = getCompls rdrElts return $ CC { allModNamesAsNS = allModNamesAsNS - , unqualCompls = toplevelCompls ++ unquals + , unqualCompls = unquals , qualCompls = quals , importableModules = moduleNames - , cachedExtensions = languagesAndExts } newtype WithSnippets = WithSnippets Bool @@ -355,7 +311,7 @@ getCompletions uri prefixInfo (WithSnippets withSnippets) = fullPrefix = enteredQual <> prefixText ifCachedModuleAndData file (IdeResultOk []) - $ \tm CachedInfo { newPosToOld } CC { allModNamesAsNS, unqualCompls, qualCompls, importableModules, cachedExtensions } -> + $ \tm CachedInfo { newPosToOld } CC { allModNamesAsNS, unqualCompls, qualCompls, importableModules } -> let -- default to value context if no explicit context context = fromMaybe ValueContext $ getContext pos (tm_parsed_module tm) @@ -423,7 +379,7 @@ getCompletions uri prefixInfo (WithSnippets withSnippets) = compls = if T.null prefixModule then unqualCompls - else Map.findWithDefault [] prefixModule qualCompls + else Map.findWithDefault [] prefixModule $ getQualCompls qualCompls mkImportCompl label = (J.detail ?~ label) . mkModCompl $ fromMaybe @@ -456,7 +412,7 @@ getCompletions uri prefixInfo (WithSnippets withSnippets) = | "import " `T.isPrefixOf` fullLine = filtImportCompls | "{-# language" `T.isPrefixOf` T.toLower fullLine - = filtOptsCompls cachedExtensions + = filtOptsCompls languagesAndExts | "{-# options_ghc" `T.isPrefixOf` T.toLower fullLine = filtOptsCompls (map (T.pack . stripLeading '-') $ GHC.flagsForCompletion False) | "{-# " `T.isPrefixOf` fullLine From a8a62ead95cc178c17852c7096db37d2ff35f30e Mon Sep 17 00:00:00 2001 From: Zubin Duggal Date: Sat, 20 Jul 2019 20:19:44 +0530 Subject: [PATCH 148/158] Implement resolving to fill in type and insert text for non local names --- src/Haskell/Ide/Engine/Support/HieExtras.hs | 171 +++++++++++++++---- src/Haskell/Ide/Engine/Transport/LspStdio.hs | 22 +-- 2 files changed, 139 insertions(+), 54 deletions(-) diff --git a/src/Haskell/Ide/Engine/Support/HieExtras.hs b/src/Haskell/Ide/Engine/Support/HieExtras.hs index aaf70ffa5..b64401da1 100644 --- a/src/Haskell/Ide/Engine/Support/HieExtras.hs +++ b/src/Haskell/Ide/Engine/Support/HieExtras.hs @@ -8,6 +8,7 @@ module Haskell.Ide.Engine.Support.HieExtras ( getDynFlags , WithSnippets(..) , getCompletions + , resolveCompletion , getTypeForName , getSymbolsAtPoint , getReferencesInDoc @@ -26,7 +27,7 @@ module Haskell.Ide.Engine.Support.HieExtras ) where import ConLike -import Control.Lens.Operators ( (^?), (?~), (&) ) +import Control.Lens.Operators ( (.~), (^.), (^?), (?~), (&) ) import Control.Lens.Prism ( _Just ) import Control.Lens.Setter ((%~)) import Control.Lens.Traversal (traverseOf) @@ -62,7 +63,8 @@ import Haskell.Ide.Engine.Context import Haskell.Ide.Engine.MonadFunctions import Haskell.Ide.Engine.MonadTypes import Haskell.Ide.Engine.PluginUtils -import qualified Haskell.Ide.Engine.Support.Fuzzy as Fuzzy +import qualified Haskell.Ide.Engine.Support.Fuzzy as Fuzzy +import qualified Haskell.Ide.Engine.Plugin.Hoogle as Hoogle import HscTypes import qualified Language.Haskell.LSP.Types as J import qualified Language.Haskell.LSP.Types.Lens as J @@ -74,9 +76,11 @@ import Outputable (Outputable) import qualified Outputable as GHC import Packages import SrcLoc -import TcEnv import Type import Var +import Unique +import UniqFM +import Module hiding (getModule) -- --------------------------------------------------------------------- @@ -124,6 +128,67 @@ occNameToComKind oc | otherwise = J.CiVariable type HoogleQuery = T.Text +data CompItemResolveData + = CompItemResolveData + { nameDetails :: Maybe NameDetails + , hoogleQuery :: HoogleQuery + } deriving (Eq,Generic) + +data NameDetails + = NameDetails Unique Module + deriving (Eq) + +instance FromJSON NameDetails where + parseJSON v@(Array _) + = do + [uchar,uint,modname,modid] <- parseJSON v + ch <- parseJSON uchar + i <- parseJSON uint + mn <- parseJSON modname + mid <- parseJSON modid + pure $ NameDetails (mkUnique ch i) (mkModule (stringToUnitId mid) (mkModuleName mn)) + parseJSON _ = mempty +instance ToJSON NameDetails where + toJSON (NameDetails uniq mdl) = toJSON [toJSON ch,toJSON uint,toJSON mname,toJSON mid] + where + (ch,uint) = unpkUnique uniq + mname = moduleNameString $ moduleName mdl + mid = unitIdString $ moduleUnitId mdl + +instance FromJSON CompItemResolveData where + parseJSON = genericParseJSON $ customOptions 2 +instance ToJSON CompItemResolveData where + toJSON = genericToJSON $ customOptions 2 + +resolveCompletion :: J.CompletionItem -> IdeM J.CompletionItem +resolveCompletion origCompl = + case fromJSON <$> origCompl ^. J.xdata of + Just (J.Success (CompItemResolveData dets query)) -> do + mdocs <- Hoogle.infoCmd' query + let docText = case mdocs of + Right x -> Just x + _ -> Nothing + markup = J.MarkupContent J.MkMarkdown <$> docText + docs = J.CompletionDocMarkup <$> markup + (detail,insert) <- case dets of + Nothing -> pure (Nothing,Nothing) + Just (NameDetails uniq mdl) -> do + mtyp <- getTypeForNameDirectly uniq mdl + case mtyp of + Nothing -> pure (Nothing, Nothing) + Just typ -> do + let label = origCompl ^. J.label + insertText = label <> " " <> getArgText typ + det = Just . stripForall $ T.pack (showGhc typ) <> "\n" + pure (det,Just insertText) + return $ origCompl & J.documentation .~ docs + & J.insertText .~ insert + & J.detail .~ (detail <> origCompl ^. J.detail) + Just (J.Error err) -> do + debugm $ "resolveCompletion: Decoding data failed because of: " ++ err + pure origCompl + _ -> pure origCompl + mkQuery :: T.Text -> T.Text -> HoogleQuery mkQuery name importedFrom = name <> " module:" <> importedFrom @@ -133,50 +198,62 @@ mkCompl :: CompItem -> J.CompletionItem mkCompl CI{origName,importedFrom,thingType,label,isInfix} = J.CompletionItem label kind (Just $ maybe "" (<>"\n") typeText <> importedFrom) Nothing Nothing Nothing Nothing Nothing (Just insertText) (Just J.Snippet) - Nothing Nothing Nothing Nothing hoogleQuery + Nothing Nothing Nothing Nothing resolveData where kind = Just $ occNameToComKind $ occName origName - hoogleQuery = Just $ toJSON $ mkQuery label importedFrom - argTypes = maybe [] getArgs thingType + resolveData = Just $ toJSON $ CompItemResolveData nameDets hoogleQuery + hoogleQuery = mkQuery label importedFrom insertText = case isInfix of - Nothing -> case argTypes of - [] -> label - _ -> label <> " " <> argText + Nothing -> case getArgText <$> thingType of + Nothing -> label + Just argText -> label <> " " <> argText Just LeftSide -> label <> "`" Just Surrounded -> label - - argText :: T.Text - argText = mconcat $ List.intersperse " " $ zipWith snippet [1..] argTypes - stripForall t - | T.isPrefixOf "forall" t = - -- We drop 2 to remove the '.' and the space after it - T.drop 2 (T.dropWhile (/= '.') t) - | otherwise = t - snippet :: Int -> Type -> T.Text - snippet i t = T.pack $ "${" <> show i <> ":" <> showGhc t <> "}" typeText | Just t <- thingType = Just . stripForall $ T.pack (showGhc t) | otherwise = Nothing - getArgs :: Type -> [Type] - getArgs t - | isPredTy t = [] - | isDictTy t = [] - | isForAllTy t = getArgs $ snd (splitForAllTys t) - | isFunTy t = - let (args, ret) = splitFunTys t - in if isForAllTy ret - then getArgs ret - else filter (not . isDictTy) args - | isPiTy t = getArgs $ snd (splitPiTys t) - | isCoercionTy t = maybe [] (getArgs . snd) (splitCoercionType_maybe t) - | otherwise = [] + nameDets = + case (thingType, nameModule_maybe origName) of + (Just _,_) -> Nothing + (Nothing, Nothing) -> Nothing + (Nothing, Just mdl) -> Just (NameDetails (nameUnique origName) mdl) + +stripForall :: T.Text -> T.Text +stripForall t + | T.isPrefixOf "forall" t = + -- We drop 2 to remove the '.' and the space after it + T.drop 2 (T.dropWhile (/= '.') t) + | otherwise = t + +getArgText :: Type -> T.Text +getArgText typ = argText + where + argTypes = getArgs typ + argText :: T.Text + argText = mconcat $ List.intersperse " " $ zipWith snippet [1..] argTypes + snippet :: Int -> Type -> T.Text + snippet i t = T.pack $ "${" <> show i <> ":" <> showGhc t <> "}" + getArgs :: Type -> [Type] + getArgs t + | isPredTy t = [] + | isDictTy t = [] + | isForAllTy t = getArgs $ snd (splitForAllTys t) + | isFunTy t = + let (args, ret) = splitFunTys t + in if isForAllTy ret + then getArgs ret + else filter (not . isDictTy) args + | isPiTy t = getArgs $ snd (splitPiTys t) + | isCoercionTy t = maybe [] (getArgs . snd) (splitCoercionType_maybe t) + | otherwise = [] mkModCompl :: T.Text -> J.CompletionItem mkModCompl label = J.CompletionItem label (Just J.CiModule) Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing - Nothing Nothing Nothing Nothing hoogleQuery - where hoogleQuery = Just $ toJSON $ "module:" <> label + Nothing Nothing Nothing Nothing (Just $ toJSON resolveData) + where hoogleQuery = "module:" <> label + resolveData = Just $ CompItemResolveData Nothing hoogleQuery mkExtCompl :: T.Text -> J.CompletionItem mkExtCompl label = @@ -445,16 +522,36 @@ getCompletions uri prefixInfo (WithSnippets withSnippets) = -- --------------------------------------------------------------------- getTypeForName :: Name -> IdeM (Maybe Type) -getTypeForName n = do +getTypeForName n = case nameModule_maybe n of + Nothing -> pure Nothing + Just mdl -> getTypeForNameDirectly (nameUnique n) mdl + +getTypeForNameDirectly :: Unique -> Module -> IdeM (Maybe Type) +getTypeForNameDirectly n m = do hscEnvRef <- ghcSession <$> readMTS mhscEnv <- liftIO $ traverse readIORef hscEnvRef case mhscEnv of Nothing -> return Nothing Just hscEnv -> do - mt <- liftIO $ (Just <$> lookupGlobal hscEnv n) - `catch` \(_ :: SomeException) -> return Nothing + mt <- liftIO $ lookupGlobalDirectly hscEnv n m return $ fmap varType $ safeTyThingId =<< mt +lookupTypeDirectly + :: HomePackageTable + -> PackageTypeEnv + -> Unique + -> Module + -> Maybe TyThing +lookupTypeDirectly hpt pte name mdl + = case lookupHptByModule hpt mdl of + Just hm -> lookupUFM_Directly (md_types (hm_details hm)) name + Nothing -> lookupUFM_Directly pte name + +lookupGlobalDirectly :: HscEnv -> Unique -> Module -> IO (Maybe TyThing) +lookupGlobalDirectly hsc_env name mdl = do + eps <- readIORef (hsc_EPS hsc_env) + return $! lookupTypeDirectly (hsc_HPT hsc_env) (eps_PTE eps) name mdl + -- --------------------------------------------------------------------- getSymbolsAtPoint :: Position -> CachedInfo -> [(Range,Name)] diff --git a/src/Haskell/Ide/Engine/Transport/LspStdio.hs b/src/Haskell/Ide/Engine/Transport/LspStdio.hs index 59272dc42..3ec5bd81e 100644 --- a/src/Haskell/Ide/Engine/Transport/LspStdio.hs +++ b/src/Haskell/Ide/Engine/Transport/LspStdio.hs @@ -19,7 +19,7 @@ import Control.Concurrent import Control.Concurrent.STM.TChan import qualified Control.Exception as E import qualified Control.FoldDebounce as Debounce -import Control.Lens ( (^.), (.~) ) +import Control.Lens ( (^.) ) import Control.Monad import Control.Monad.IO.Class import Control.Monad.Reader @@ -30,7 +30,6 @@ import qualified Data.ByteString.Lazy as BL import Data.Coerce (coerce) import Data.Default import Data.Foldable -import Data.Function import qualified Data.Map as Map import Data.Maybe import Data.Semigroup (Semigroup(..), Option(..), option) @@ -649,22 +648,11 @@ reactor inp diagIn = do ReqCompletionItemResolve req -> do liftIO $ U.logs $ "reactor:got CompletionItemResolveRequest:" ++ show req let origCompl = req ^. J.params - mquery = case J.fromJSON <$> origCompl ^. J.xdata of - Just (J.Success q) -> Just q - _ -> Nothing - callback docText = do - let markup = J.MarkupContent J.MkMarkdown <$> docText - docs = J.CompletionDocMarkup <$> markup - rspMsg = Core.makeResponseMessage req $ - origCompl & J.documentation .~ docs + callback res = do + let rspMsg = Core.makeResponseMessage req $ res reactorSend $ RspCompletionItemResolve rspMsg - hreq = IReq tn (req ^. J.id) callback $ runIdeResultT $ case mquery of - Nothing -> return Nothing - Just query -> do - result <- lift $ lift $ Hoogle.infoCmd' query - case result of - Right x -> return $ Just x - _ -> return Nothing + hreq = IReq tn (req ^. J.id) callback $ runIdeResultT $ do + lift $ lift $ Hie.resolveCompletion origCompl makeRequest hreq -- ------------------------------- From d7e5da6b214050446c3d29cb19c9282c7a3b9cb9 Mon Sep 17 00:00:00 2001 From: Zubin Duggal Date: Sat, 20 Jul 2019 22:20:45 +0530 Subject: [PATCH 149/158] Fix tests --- src/Haskell/Ide/Engine/Support/HieExtras.hs | 4 +- test/functional/CompletionSpec.hs | 75 +++++++++++++++++---- test/testdata/completion/Completion.hs | 8 ++- 3 files changed, 70 insertions(+), 17 deletions(-) diff --git a/src/Haskell/Ide/Engine/Support/HieExtras.hs b/src/Haskell/Ide/Engine/Support/HieExtras.hs index b64401da1..757212ba2 100644 --- a/src/Haskell/Ide/Engine/Support/HieExtras.hs +++ b/src/Haskell/Ide/Engine/Support/HieExtras.hs @@ -156,9 +156,9 @@ instance ToJSON NameDetails where mid = unitIdString $ moduleUnitId mdl instance FromJSON CompItemResolveData where - parseJSON = genericParseJSON $ customOptions 2 + parseJSON = genericParseJSON $ customOptions 0 instance ToJSON CompItemResolveData where - toJSON = genericToJSON $ customOptions 2 + toJSON = genericToJSON $ customOptions 0 resolveCompletion :: J.CompletionItem -> IdeM J.CompletionItem resolveCompletion origCompl = diff --git a/test/functional/CompletionSpec.hs b/test/functional/CompletionSpec.hs index e703b5923..68f130d54 100644 --- a/test/functional/CompletionSpec.hs +++ b/test/functional/CompletionSpec.hs @@ -1,4 +1,5 @@ -{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE ScopedTypeVariables #-} module CompletionSpec where import Control.Applicative.Combinators @@ -25,9 +26,47 @@ spec = describe "completions" $ do liftIO $ do item ^. label `shouldBe` "putStrLn" item ^. kind `shouldBe` Just CiFunction - item ^. detail `shouldBe` Just "String -> IO ()\nPrelude" - item ^. insertTextFormat `shouldBe` Just Snippet - item ^. insertText `shouldBe` Just "putStrLn ${1:String}" + item ^. detail `shouldBe` Just "Prelude" + resolvedRes <- request CompletionItemResolve item + let Just (resolved :: CompletionItem) = resolvedRes ^. result + liftIO $ do + resolved ^. label `shouldBe` "putStrLn" + resolved ^. kind `shouldBe` Just CiFunction + resolved ^. detail `shouldBe` Just "String -> IO ()\nPrelude" + resolved ^. insertTextFormat `shouldBe` Just Snippet + resolved ^. insertText `shouldBe` Just "putStrLn ${1:String}" + + it "does not pull in unnecessary modules until needed" $ + runSession hieCommand fullCaps "test/testdata/completion" $ do + doc <- openDoc "Completion.hs" "haskell" + _ <- skipManyTill loggingNotification (count 2 noDiagnostics) + + let te = TextEdit (Range (Position 5 7) (Position 5 24)) "enum" + _ <- applyEdit doc te + + compls <- getCompletions doc (Position 5 11) + let item = head $ filter ((== "enumFrom") . (^. label)) compls + resolvedRes <- request CompletionItemResolve item + let Just (resolved :: CompletionItem) = resolvedRes ^. result + liftIO $ do + resolved ^. label `shouldBe` "enumFrom" + resolved ^. kind `shouldBe` Just CiFunction + resolved ^. detail `shouldBe` Just "Prelude" + resolved ^. insertText `shouldBe` Nothing + + let te2 = TextEdit (Range (Position 5 7) (Position 5 11)) "putStrLn (enumFrom 'a')" + _ <- applyEdit doc te2 + _ <- skipManyTill loggingNotification (count 2 noDiagnostics) + + compls2 <- getCompletions doc (Position 5 22) + let item2 = head $ filter ((== "enumFrom") . (^. label)) compls2 + resolvedRes2 <- request CompletionItemResolve item2 + let Just (resolved2 :: CompletionItem) = resolvedRes2 ^. result + liftIO $ do + resolved2 ^. label `shouldBe` "enumFrom" + resolved2 ^. kind `shouldBe` Just CiFunction + resolved2 ^. detail `shouldBe` Just "Enum a => a -> [a]\nPrelude" + resolved2 ^. insertText `shouldBe` Just "enumFrom ${1:a}" it "completes imports" $ runSession hieCommand fullCaps "test/testdata/completion" $ do doc <- openDoc "Completion.hs" "haskell" @@ -193,8 +232,10 @@ spec = describe "completions" $ do _ <- applyEdit doc te compls <- getCompletions doc (Position 5 9) let item = head $ filter ((== "id") . (^. label)) compls + resolvedRes <- request CompletionItemResolve item + let Just (resolved :: CompletionItem) = resolvedRes ^. result liftIO $ - item ^. detail `shouldBe` Just "a -> a\nPrelude" + resolved ^. detail `shouldBe` Just "a -> a\nPrelude" it "have implicit foralls with multiple type variables" $ runSession hieCommand fullCaps "test/testdata/completion" $ do doc <- openDoc "Completion.hs" "haskell" @@ -203,8 +244,10 @@ spec = describe "completions" $ do _ <- applyEdit doc te compls <- getCompletions doc (Position 5 11) let item = head $ filter ((== "flip") . (^. label)) compls + resolvedRes <- request CompletionItemResolve item + let Just (resolved :: CompletionItem) = resolvedRes ^. result liftIO $ - item ^. detail `shouldBe` Just "(a -> b -> c) -> b -> a -> c\nPrelude" + resolved ^. detail `shouldBe` Just "(a -> b -> c) -> b -> a -> c\nPrelude" describe "snippets" $ do it "work for argumentless constructors" $ runSession hieCommand fullCaps "test/testdata/completion" $ do @@ -229,11 +272,13 @@ spec = describe "completions" $ do compls <- getCompletions doc (Position 5 11) let item = head $ filter ((== "foldl") . (^. label)) compls + resolvedRes <- request CompletionItemResolve item + let Just (resolved :: CompletionItem) = resolvedRes ^. result liftIO $ do - item ^. label `shouldBe` "foldl" - item ^. kind `shouldBe` Just CiFunction - item ^. insertTextFormat `shouldBe` Just Snippet - item ^. insertText `shouldBe` Just "foldl ${1:b -> a -> b} ${2:b} ${3:t a}" + resolved ^. label `shouldBe` "foldl" + resolved ^. kind `shouldBe` Just CiFunction + resolved ^. insertTextFormat `shouldBe` Just Snippet + resolved ^. insertText `shouldBe` Just "foldl ${1:b -> a -> b} ${2:b} ${3:t a}" it "work for complex types" $ runSession hieCommand fullCaps "test/testdata/completion" $ do doc <- openDoc "Completion.hs" "haskell" @@ -244,11 +289,13 @@ spec = describe "completions" $ do compls <- getCompletions doc (Position 5 11) let item = head $ filter ((== "mapM") . (^. label)) compls + resolvedRes <- request CompletionItemResolve item + let Just (resolved :: CompletionItem) = resolvedRes ^. result liftIO $ do - item ^. label `shouldBe` "mapM" - item ^. kind `shouldBe` Just CiFunction - item ^. insertTextFormat `shouldBe` Just Snippet - item ^. insertText `shouldBe` Just "mapM ${1:a -> m b} ${2:t a}" + resolved ^. label `shouldBe` "mapM" + resolved ^. kind `shouldBe` Just CiFunction + resolved ^. insertTextFormat `shouldBe` Just Snippet + resolved ^. insertText `shouldBe` Just "mapM ${1:a -> m b} ${2:t a}" it "work for infix functions" $ runSession hieCommand fullCaps "test/testdata/completion" $ do doc <- openDoc "Completion.hs" "haskell" diff --git a/test/testdata/completion/Completion.hs b/test/testdata/completion/Completion.hs index d6480903b..2d778cf8d 100644 --- a/test/testdata/completion/Completion.hs +++ b/test/testdata/completion/Completion.hs @@ -6,4 +6,10 @@ main :: IO () main = putStrLn "hello" foo :: Either a b -> Either a b -foo = id \ No newline at end of file +foo = id + +bar :: Int +bar = foldl (-) 0 [1,2,3] + +baz :: [String] +baz = mapM head [["a"]] From 9c7365f686285e2df10f3c001bb2fe8cf6e776bf Mon Sep 17 00:00:00 2001 From: Zubin Duggal Date: Sat, 20 Jul 2019 23:44:07 +0530 Subject: [PATCH 150/158] make ghcSession an IORef again --- hie-plugin-api/Haskell/Ide/Engine/Ghc.hs | 4 +++- hie-plugin-api/Haskell/Ide/Engine/PluginsIdeMonads.hs | 2 +- src/Haskell/Ide/Engine/Plugin/Haddock.hs | 3 ++- src/Haskell/Ide/Engine/Support/HieExtras.hs | 10 +++------- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/hie-plugin-api/Haskell/Ide/Engine/Ghc.hs b/hie-plugin-api/Haskell/Ide/Engine/Ghc.hs index 52f2acc57..63533b5c2 100644 --- a/hie-plugin-api/Haskell/Ide/Engine/Ghc.hs +++ b/hie-plugin-api/Haskell/Ide/Engine/Ghc.hs @@ -57,6 +57,7 @@ import System.Directory import GhcProject.Types as GM import Digraph (Node(..), verticesG) import GhcMake ( moduleGraphNodes ) +import GhcMonad newtype Diagnostics = Diagnostics (Map.Map NormalizedUri (Set.Set Diagnostic)) @@ -260,7 +261,8 @@ setTypecheckedModule_load uri = -- set the session before we cache the module, so that deferred -- responses triggered by cacheModule can access it - sess <- getSession + + Session sess <- GhcT pure modifyMTS (\s -> s {ghcSession = Just sess}) cacheModules rfm ts --cacheModules rfm [tm] diff --git a/hie-plugin-api/Haskell/Ide/Engine/PluginsIdeMonads.hs b/hie-plugin-api/Haskell/Ide/Engine/PluginsIdeMonads.hs index 1f2ea65c5..82892b848 100644 --- a/hie-plugin-api/Haskell/Ide/Engine/PluginsIdeMonads.hs +++ b/hie-plugin-api/Haskell/Ide/Engine/PluginsIdeMonads.hs @@ -487,7 +487,7 @@ data IdeState = IdeState -- | A queue of requests to be performed once a module is loaded , requestQueue :: Map.Map FilePath [UriCacheResult -> IdeM ()] , extensibleState :: !(Map.Map TypeRep Dynamic) - , ghcSession :: Maybe HscEnv + , ghcSession :: !(Maybe (IORef HscEnv)) } instance MonadMTState IdeState IdeGhcM where diff --git a/src/Haskell/Ide/Engine/Plugin/Haddock.hs b/src/Haskell/Ide/Engine/Plugin/Haddock.hs index 31bc5fee9..12b75e05c 100644 --- a/src/Haskell/Ide/Engine/Plugin/Haddock.hs +++ b/src/Haskell/Ide/Engine/Plugin/Haddock.hs @@ -86,7 +86,8 @@ nameCacheFromGhcMonad = ( read_from_session , write_to_session ) runInLightGhc :: Ghc a -> IdeM a runInLightGhc a = do - mhscEnv <- ghcSession <$> readMTS + hscEnvRef <- ghcSession <$> readMTS + mhscEnv <- liftIO $ traverse readIORef hscEnvRef liftIO $ case mhscEnv of Nothing -> error "Ghc Session not initialized" Just env -> do diff --git a/src/Haskell/Ide/Engine/Support/HieExtras.hs b/src/Haskell/Ide/Engine/Support/HieExtras.hs index 9994a8cd3..5bb39256a 100644 --- a/src/Haskell/Ide/Engine/Support/HieExtras.hs +++ b/src/Haskell/Ide/Engine/Support/HieExtras.hs @@ -42,18 +42,13 @@ import qualified Data.Text as T import Data.Typeable import DataCon import qualified DynFlags as GHC -import Exception import FastString import Finder import GHC hiding (getContext) -import GhcMonad import GHC.Generics (Generic) import TcRnTypes import RdrName -import qualified GhcMod as GM (splits',SplitResult(..)) -import qualified GhcModCore as GM (GhcModError(..), listVisibleModuleNames, withMappedFile ) - import Haskell.Ide.Engine.ArtifactMap import Haskell.Ide.Engine.Config import Haskell.Ide.Engine.Context @@ -709,8 +704,9 @@ srcSpanToFileLocation invoker rfm srcSpan = do -- | Goto given module. gotoModule :: (FilePath -> FilePath) -> ModuleName -> IdeDeferM (IdeResult [Location]) gotoModule rfm mn = do - mHscEnv <- ghcSession <$> readMTS - case mHscEnv of + hscEnvRef <- ghcSession <$> readMTS + mhscEnv <- liftIO $ traverse readIORef hscEnvRef + case mhscEnv of Just env -> do fr <- liftIO $ do -- Flush cache or else we get temporary files From c5f7d28c4a2ce60897cde87196d04e4818820c2d Mon Sep 17 00:00:00 2001 From: Zubin Duggal Date: Sun, 21 Jul 2019 02:16:23 +0530 Subject: [PATCH 151/158] fix some more tests and embarrassing implmentation of withMappedFile --- hie-plugin-api/Haskell/Ide/Engine/Config.hs | 2 +- .../Haskell/Ide/Engine/PluginsIdeMonads.hs | 6 +++--- test/testdata/testdata.cabal | 16 ++++++++++++++++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/hie-plugin-api/Haskell/Ide/Engine/Config.hs b/hie-plugin-api/Haskell/Ide/Engine/Config.hs index 4ccb0d973..36d76bb9e 100644 --- a/hie-plugin-api/Haskell/Ide/Engine/Config.hs +++ b/hie-plugin-api/Haskell/Ide/Engine/Config.hs @@ -42,7 +42,7 @@ data Config = instance Default Config where def = Config { hlintOn = True - , diagnosticsOnChange = False + , diagnosticsOnChange = True , maxNumberOfProblems = 100 , diagnosticsDebounceDuration = 350000 , liquidOn = False diff --git a/hie-plugin-api/Haskell/Ide/Engine/PluginsIdeMonads.hs b/hie-plugin-api/Haskell/Ide/Engine/PluginsIdeMonads.hs index 82892b848..50e07e62e 100644 --- a/hie-plugin-api/Haskell/Ide/Engine/PluginsIdeMonads.hs +++ b/hie-plugin-api/Haskell/Ide/Engine/PluginsIdeMonads.hs @@ -435,9 +435,9 @@ reverseFileMap = do withMappedFile :: (MonadIde m, MonadIO m) => FilePath -> (FilePath -> m a) -> m a withMappedFile fp k = do - rfm <- reverseFileMap - fp' <- liftIO $ canonicalizePath fp - k $ rfm fp' + canon <- liftIO $ canonicalizePath fp + fp' <- persistVirtualFile (filePathToUri canon) + k fp' getConfig :: (MonadIde m, MonadIO m) => m Config diff --git a/test/testdata/testdata.cabal b/test/testdata/testdata.cabal index b83f6ee8a..6c7a6063c 100644 --- a/test/testdata/testdata.cabal +++ b/test/testdata/testdata.cabal @@ -8,6 +8,22 @@ executable applyrefact main-is: ApplyRefact.hs default-language: Haskell2010 +executable hover + build-depends: base + main-is: Hover.hs + default-language: Haskell2010 + +executable symbols + build-depends: base + main-is: Symbols.hs + default-language: Haskell2010 + + +executable applyrefact2 + build-depends: base + main-is: ApplyRefact2.hs + default-language: Haskell2010 + executable hlintpragma build-depends: base main-is: HlintPragma.hs From 775eca299c3981c417b4d01ea8cd3d56b7793d38 Mon Sep 17 00:00:00 2001 From: Zubin Duggal Date: Sun, 21 Jul 2019 02:42:10 +0530 Subject: [PATCH 152/158] "ghcmod" -> "bios" --- hie-bios | 2 +- src/Haskell/Ide/Engine/Plugin/Generic.hs | 10 +-- src/Haskell/Ide/Engine/Plugin/HsImport.hs | 2 +- src/Haskell/Ide/Engine/Plugin/Package.hs | 2 +- src/Haskell/Ide/Engine/Plugin/Pragmas.hs | 2 +- test/functional/DiagnosticsSpec.hs | 4 +- test/functional/FunctionalBadProjectSpec.hs | 4 +- test/functional/FunctionalCodeActionsSpec.hs | 30 ++++---- test/unit/GhcModPluginSpec.hs | 78 ++++++++++---------- 9 files changed, 67 insertions(+), 67 deletions(-) diff --git a/hie-bios b/hie-bios index 8427e424a..e14cefa88 160000 --- a/hie-bios +++ b/hie-bios @@ -1 +1 @@ -Subproject commit 8427e424a83c2f3d60bdd26c02478c00d2189a73 +Subproject commit e14cefa883522c8e01022e2ebf48b4c4ca3ec0a5 diff --git a/src/Haskell/Ide/Engine/Plugin/Generic.hs b/src/Haskell/Ide/Engine/Plugin/Generic.hs index 55728a315..8ac1b4778 100644 --- a/src/Haskell/Ide/Engine/Plugin/Generic.hs +++ b/src/Haskell/Ide/Engine/Plugin/Generic.hs @@ -187,7 +187,7 @@ codeActionProvider' supportsDocChanges _ docId _ context = codeAction = LSP.CodeAction title (Just kind) (Just diags) (Just we) Nothing getRenamables :: LSP.Diagnostic -> [(LSP.Diagnostic, T.Text)] - getRenamables diag@(LSP.Diagnostic _ _ _ (Just "ghcmod") msg _) = map (diag,) $ extractRenamableTerms msg + getRenamables diag@(LSP.Diagnostic _ _ _ (Just "bios") msg _) = map (diag,) $ extractRenamableTerms msg getRenamables _ = [] mkRedundantImportActions :: LSP.Diagnostic -> T.Text -> [LSP.CodeAction] @@ -213,7 +213,7 @@ codeActionProvider' supportsDocChanges _ docId _ context = tEdit = LSP.TextEdit (diag ^. LSP.range) ("import " <> modName <> "()") getRedundantImports :: LSP.Diagnostic -> Maybe (LSP.Diagnostic, T.Text) - getRedundantImports diag@(LSP.Diagnostic _ _ _ (Just "ghcmod") msg _) = (diag,) <$> extractRedundantImport msg + getRedundantImports diag@(LSP.Diagnostic _ _ _ (Just "bios") msg _) = (diag,) <$> extractRedundantImport msg getRedundantImports _ = Nothing mkTypedHoleActions :: TypedHoles -> [LSP.CodeAction] @@ -235,14 +235,14 @@ codeActionProvider' supportsDocChanges _ docId _ context = getTypedHoles :: LSP.Diagnostic -> Maybe TypedHoles - getTypedHoles diag@(LSP.Diagnostic _ _ _ (Just "ghcmod") msg _) = + getTypedHoles diag@(LSP.Diagnostic _ _ _ (Just "bios") msg _) = case extractHoleSubstitutions msg of Nothing -> Nothing Just (want, subs, bindings) -> Just $ TypedHoles diag want subs bindings getTypedHoles _ = Nothing getMissingSignatures :: LSP.Diagnostic -> Maybe (LSP.Diagnostic, T.Text) - getMissingSignatures diag@(LSP.Diagnostic _ _ _ (Just "ghcmod") msg _) = + getMissingSignatures diag@(LSP.Diagnostic _ _ _ (Just "bios") msg _) = case extractMissingSignature msg of Nothing -> Nothing Just signature -> Just (diag, signature) @@ -260,7 +260,7 @@ codeActionProvider' supportsDocChanges _ docId _ context = codeAction = LSP.CodeAction title (Just kind) (Just diags) (Just edit) Nothing getUnusedTerms :: LSP.Diagnostic -> Maybe (LSP.Diagnostic, T.Text) - getUnusedTerms diag@(LSP.Diagnostic _ _ _ (Just "ghcmod") msg _) = + getUnusedTerms diag@(LSP.Diagnostic _ _ _ (Just "bios") msg _) = case extractUnusedTerm msg of Nothing -> Nothing Just signature -> Just (diag, signature) diff --git a/src/Haskell/Ide/Engine/Plugin/HsImport.hs b/src/Haskell/Ide/Engine/Plugin/HsImport.hs index ebade20a5..e3114a13b 100644 --- a/src/Haskell/Ide/Engine/Plugin/HsImport.hs +++ b/src/Haskell/Ide/Engine/Plugin/HsImport.hs @@ -461,7 +461,7 @@ codeActionProvider plId docId _ context = do -- | For a Diagnostic, get an associated function name. -- If Ghc-Mod can not find any candidates, Nothing is returned. getImportables :: J.Diagnostic -> Maybe ImportDiagnostic - getImportables diag@(J.Diagnostic _ _ _ (Just "ghcmod") msg _) = + getImportables diag@(J.Diagnostic _ _ _ (Just "bios") msg _) = uncurry (ImportDiagnostic diag) <$> extractImportableTerm msg getImportables _ = Nothing diff --git a/src/Haskell/Ide/Engine/Plugin/Package.hs b/src/Haskell/Ide/Engine/Plugin/Package.hs index 8de006182..6f990c52f 100644 --- a/src/Haskell/Ide/Engine/Plugin/Package.hs +++ b/src/Haskell/Ide/Engine/Plugin/Package.hs @@ -331,7 +331,7 @@ codeActionProvider plId docId _ context = do _ -> return Nothing getAddablePackages :: J.Diagnostic -> Maybe (J.Diagnostic, Package) - getAddablePackages diag@(J.Diagnostic _ _ _ (Just "ghcmod") msg _) = (diag,) <$> extractModuleName msg + getAddablePackages diag@(J.Diagnostic _ _ _ (Just "bios") msg _) = (diag,) <$> extractModuleName msg getAddablePackages _ = Nothing -- | Extract a module name from an error message. diff --git a/src/Haskell/Ide/Engine/Plugin/Pragmas.hs b/src/Haskell/Ide/Engine/Plugin/Pragmas.hs index f075f7139..57b6cccb7 100644 --- a/src/Haskell/Ide/Engine/Plugin/Pragmas.hs +++ b/src/Haskell/Ide/Engine/Plugin/Pragmas.hs @@ -66,7 +66,7 @@ codeActionProvider plId docId _ (J.CodeActionContext (J.List diags) _monly) = do return $ IdeResultOk cmds where -- Filter diagnostics that are from ghcmod - ghcDiags = filter (\d -> d ^. J.source == Just "ghcmod") diags + ghcDiags = filter (\d -> d ^. J.source == Just "bios") diags -- Get all potential Pragmas for all diagnostics. pragmas = concatMap (\d -> findPragma (d ^. J.message)) ghcDiags mkCommand pragmaName = do diff --git a/test/functional/DiagnosticsSpec.hs b/test/functional/DiagnosticsSpec.hs index bfd613e1b..fefe6bf30 100644 --- a/test/functional/DiagnosticsSpec.hs +++ b/test/functional/DiagnosticsSpec.hs @@ -64,14 +64,14 @@ spec = describe "diagnostics providers" $ do it "is deferred" $ runSession hieCommand fullCaps "test/testdata" $ do _ <- openDoc "TypedHoles.hs" "haskell" - [diag] <- waitForDiagnosticsSource "ghcmod" + [diag] <- waitForDiagnosticsSource "bios" liftIO $ diag ^. LSP.severity `shouldBe` Just DsWarning describe "Warnings are warnings" $ it "Overrides -Werror" $ runSession hieCommand fullCaps "test/testdata/wErrorTest" $ do _ <- openDoc "src/WError.hs" "haskell" - [diag] <- waitForDiagnosticsSource "ghcmod" + [diag] <- waitForDiagnosticsSource "bios" liftIO $ diag ^. LSP.severity `shouldBe` Just DsWarning describe "only diagnostics on save" $ diff --git a/test/functional/FunctionalBadProjectSpec.hs b/test/functional/FunctionalBadProjectSpec.hs index 8e474729d..3ca97183d 100644 --- a/test/functional/FunctionalBadProjectSpec.hs +++ b/test/functional/FunctionalBadProjectSpec.hs @@ -21,7 +21,7 @@ spec = describe "behaviour on malformed projects" $ do -- runSessionWithConfig logConfig hieCommandExamplePlugin codeActionSupportCaps "test/testdata" $ do _doc <- openDoc "Foo.hs" "haskell" - diags@(d:_) <- waitForDiagnosticsSource "ghcmod" + diags@(d:_) <- waitForDiagnosticsSource "bios" -- liftIO $ show diags `shouldBe` "" -- liftIO $ putStrLn $ show diags -- liftIO $ putStrLn "a" @@ -30,7 +30,7 @@ spec = describe "behaviour on malformed projects" $ do d ^. range `shouldBe` Range (Position 0 0) (Position 1 0) d ^. severity `shouldBe` (Just DsError) d ^. code `shouldBe` Nothing - d ^. source `shouldBe` Just "ghcmod" + d ^. source `shouldBe` Just "bios" d ^. message `shouldBe` (T.pack "readCreateProcess: stack \"build\" \"--only-configure\" \".\" (exit 1): failed\n") diff --git a/test/functional/FunctionalCodeActionsSpec.hs b/test/functional/FunctionalCodeActionsSpec.hs index 5d763870c..a042af32c 100644 --- a/test/functional/FunctionalCodeActionsSpec.hs +++ b/test/functional/FunctionalCodeActionsSpec.hs @@ -101,7 +101,7 @@ spec = describe "code actions" $ do it "works" $ runSession hieCommand noLiteralCaps "test/testdata" $ do doc <- openDoc "CodeActionRename.hs" "haskell" - _ <- waitForDiagnosticsSource "ghcmod" + _ <- waitForDiagnosticsSource "bios" CACommand cmd:_ <- getAllCodeActions doc executeCommand cmd @@ -112,7 +112,7 @@ spec = describe "code actions" $ do runSession hieCommand noLiteralCaps "test/testdata" $ do doc <- openDoc "CodeActionRename.hs" "haskell" - _ <- waitForDiagnosticsSource "ghcmod" + _ <- waitForDiagnosticsSource "bios" CACommand cmd <- (!! 2) <$> getAllCodeActions doc let Just (List [Object args]) = cmd ^. L.arguments @@ -323,7 +323,7 @@ spec = describe "code actions" $ do it "works" $ runSession hieCommand fullCaps "test/testdata" $ do doc <- openDoc "TypedHoles.hs" "haskell" - _ <- waitForDiagnosticsSource "ghcmod" + _ <- waitForDiagnosticsSource "bios" cas <- map (\(CACodeAction x)-> x) <$> getAllCodeActions doc suggestion <- @@ -363,7 +363,7 @@ spec = describe "code actions" $ do it "shows more suggestions" $ runSession hieCommand fullCaps "test/testdata" $ do doc <- openDoc "TypedHoles2.hs" "haskell" - _ <- waitForDiagnosticsSource "ghcmod" + _ <- waitForDiagnosticsSource "bios" cas <- map fromAction <$> getAllCodeActions doc suggestion <- @@ -411,7 +411,7 @@ spec = describe "code actions" $ do runSession hieCommand fullCaps "test/testdata/" $ do doc <- openDoc "TopLevelSignature.hs" "haskell" - _ <- waitForDiagnosticsSource "ghcmod" + _ <- waitForDiagnosticsSource "bios" cas <- map fromAction <$> getAllCodeActions doc liftIO $ map (^. L.title) cas `shouldContain` [ "Add signature: main :: IO ()"] @@ -437,7 +437,7 @@ spec = describe "code actions" $ do runSession hieCommand fullCaps "test/testdata/addPragmas" $ do doc <- openDoc "NeedsPragmas.hs" "haskell" - _ <- waitForDiagnosticsSource "ghcmod" + _ <- waitForDiagnosticsSource "bios" cas <- map fromAction <$> getAllCodeActions doc liftIO $ map (^. L.title) cas `shouldContain` [ "Add \"TypeSynonymInstances\""] @@ -474,7 +474,7 @@ spec = describe "code actions" $ do runSession hieCommand fullCaps "test/testdata/" $ do doc <- openDoc "UnusedTerm.hs" "haskell" - _ <- waitForDiagnosticsSource "ghcmod" + _ <- waitForDiagnosticsSource "bios" cas <- map fromAction <$> getAllCodeActions doc liftIO $ map (^. L.title) cas `shouldContain` [ "Prefix imUnused with _"] @@ -545,7 +545,7 @@ hsImportSpec formatterName [e1, e2, e3, e4] = it "formats" $ runSession hieCommand fullCaps "test/testdata" $ do doc <- openDoc "CodeActionImportBrittany.hs" "haskell" - _ <- waitForDiagnosticsSource "ghcmod" + _ <- waitForDiagnosticsSource "bios" let config = def { formattingProvider = formatterName } sendNotification WorkspaceDidChangeConfiguration (DidChangeConfigurationParams (toJSON config)) @@ -559,7 +559,7 @@ hsImportSpec formatterName [e1, e2, e3, e4] = it "import-list formats" $ runSession hieCommand fullCaps "test/testdata" $ do doc <- openDoc "CodeActionImportBrittany.hs" "haskell" - _ <- waitForDiagnosticsSource "ghcmod" + _ <- waitForDiagnosticsSource "bios" let config = def { formattingProvider = formatterName } sendNotification WorkspaceDidChangeConfiguration (DidChangeConfigurationParams (toJSON config)) @@ -614,7 +614,7 @@ hsImportSpec formatterName [e1, e2, e3, e4] = ] it "respects format config" $ runSession hieCommand fullCaps "test/testdata" $ do doc <- openDoc "CodeActionImportBrittany.hs" "haskell" - _ <- waitForDiagnosticsSource "ghcmod" + _ <- waitForDiagnosticsSource "bios" let config = def { formatOnImportOn = False, formattingProvider = formatterName } sendNotification WorkspaceDidChangeConfiguration (DidChangeConfigurationParams (toJSON config)) @@ -633,7 +633,7 @@ hsImportSpec formatterName [e1, e2, e3, e4] = it "import-list respects format config" $ runSession hieCommand fullCaps "test/testdata" $ do doc <- openDoc "CodeActionImportBrittany.hs" "haskell" - _ <- waitForDiagnosticsSource "ghcmod" + _ <- waitForDiagnosticsSource "bios" let config = def { formatOnImportOn = False, formattingProvider = formatterName } sendNotification WorkspaceDidChangeConfiguration (DidChangeConfigurationParams (toJSON config)) @@ -652,7 +652,7 @@ hsImportSpec formatterName [e1, e2, e3, e4] = it "complex import-list" $ runSession hieCommand fullCaps "test/testdata" $ do doc <- openDoc "CodeActionImportListElaborate.hs" "haskell" - _ <- waitForDiagnosticsSource "ghcmod" + _ <- waitForDiagnosticsSource "bios" let config = def { formatOnImportOn = True, formattingProvider = formatterName } sendNotification WorkspaceDidChangeConfiguration (DidChangeConfigurationParams (toJSON config)) @@ -673,7 +673,7 @@ hsImportSpec formatterName [e1, e2, e3, e4] = it "complex import-list respects format config" $ runSession hieCommand fullCaps "test/testdata" $ do doc <- openDoc "CodeActionImportListElaborate.hs" "haskell" - _ <- waitForDiagnosticsSource "ghcmod" + _ <- waitForDiagnosticsSource "bios" let config = def { formatOnImportOn = False, formattingProvider = formatterName } sendNotification WorkspaceDidChangeConfiguration (DidChangeConfigurationParams (toJSON config)) @@ -709,10 +709,10 @@ hsImportSpec formatterName [e1, e2, e3, e4] = executeAllCodeActions :: TextDocumentIdentifier -> [T.Text] -> Session T.Text executeAllCodeActions doc names = foldM (\_ _ -> do - _ <- waitForDiagnosticsSource "ghcmod" + _ <- waitForDiagnosticsSource "bios" executeCodeActionByName doc names content <- skipManyTill publishDiagnosticsNotification $ getDocumentEdit doc - _ <- waitForDiagnosticsSource "ghcmod" + _ <- waitForDiagnosticsSource "bios" return content ) (T.pack "") diff --git a/test/unit/GhcModPluginSpec.hs b/test/unit/GhcModPluginSpec.hs index 24449b19a..93bf22388 100644 --- a/test/unit/GhcModPluginSpec.hs +++ b/test/unit/GhcModPluginSpec.hs @@ -33,7 +33,7 @@ spec = do -- --------------------------------------------------------------------- testPlugins :: IdePlugins -testPlugins = pluginDescToIdePlugins [genericDescriptor "ghcmod"] +testPlugins = pluginDescToIdePlugins [genericDescriptor "bios"] -- --------------------------------------------------------------------- @@ -56,11 +56,11 @@ ghcmodSpec = (toPos (4,8))) (Just DsError) Nothing - (Just "ghcmod") + (Just "bios") "Variable not in scope: x" Nothing - testCommand testPlugins act "ghcmod" "check" arg res + testCommand testPlugins act "bios" "check" arg res -- --------------------------------- @@ -75,7 +75,7 @@ ghcmodSpec = -- #else -- res = IdeResultOk (T.pack fp <> ":6:9: Warning: Redundant do\NULFound:\NUL do return (3 + x)\NULWhy not:\NUL return (3 + x)\n") -- #endif --- testCommand testPlugins act "ghcmod" "lint" arg res +-- testCommand testPlugins act "bios" "lint" arg res -- --------------------------------- @@ -86,7 +86,7 @@ ghcmodSpec = -- arg = IP uri "main" -- res = IdeResultOk "main :: IO () \t-- Defined at HaReRename.hs:2:1\n" -- -- ghc-mod tries to load the test file in the context of the hie project if we do not cd first. - -- testCommand testPlugins act "ghcmod" "info" arg res + -- testCommand testPlugins act "bios" "info" arg res -- ---------------------------------------------------------------------------- @@ -102,7 +102,7 @@ ghcmodSpec = , (Range (toPos (5,1)) (toPos (5,14)), "Int -> Int") ] - testCommand testPlugins act "ghcmod" "type" arg res + testCommand testPlugins act "bios" "type" arg res it "runs the type command, find function type" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "HaReRename.hs" @@ -115,7 +115,7 @@ ghcmodSpec = [ (Range (toPos (2, 8)) (toPos (2,16)), "String -> IO ()") , (Range (toPos (2, 1)) (toPos (2,24)), "IO ()") ] - testCommand testPlugins act "ghcmod" "type" arg res + testCommand testPlugins act "bios" "type" arg res it "runs the type command, no type at location" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "HaReRename.hs" @@ -125,7 +125,7 @@ ghcmodSpec = liftToGhc $ newTypeCmd (toPos (1,1)) uri arg = TP False uri (toPos (1,1)) res = IdeResultOk [] - testCommand testPlugins act "ghcmod" "type" arg res + testCommand testPlugins act "bios" "type" arg res it "runs the type command, simple" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -138,7 +138,7 @@ ghcmodSpec = [ (Range (toPos (6, 16)) (toPos (6,17)), "Int") , (Range (toPos (6, 1)) (toPos (7, 16)), "Maybe Int -> Int") ] - testCommand testPlugins act "ghcmod" "type" arg res + testCommand testPlugins act "bios" "type" arg res it "runs the type command, sum type pattern match, just" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -152,7 +152,7 @@ ghcmodSpec = , (Range (toPos (6, 5)) (toPos (6, 13)), "Maybe Int") , (Range (toPos (6, 1)) (toPos (7, 16)), "Maybe Int -> Int") ] - testCommand testPlugins act "ghcmod" "type" arg res + testCommand testPlugins act "bios" "type" arg res it "runs the type command, sum type pattern match, just value" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -167,7 +167,7 @@ ghcmodSpec = , (Range (toPos (6, 5)) (toPos (6, 13)), "Maybe Int") , (Range (toPos (6, 1)) (toPos (7, 16)), "Maybe Int -> Int") ] - testCommand testPlugins act "ghcmod" "type" arg res + testCommand testPlugins act "bios" "type" arg res it "runs the type command, sum type pattern match, nothing" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -180,7 +180,7 @@ ghcmodSpec = [ (Range (toPos (7, 5)) (toPos (7, 12)), "Maybe Int") , (Range (toPos (6, 1)) (toPos (7, 16)), "Maybe Int -> Int") ] - testCommand testPlugins act "ghcmod" "type" arg res + testCommand testPlugins act "bios" "type" arg res it "runs the type command, sum type pattern match, nothing, literal" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -193,7 +193,7 @@ ghcmodSpec = [ (Range (toPos (7, 15)) (toPos (7, 16)), "Int") , (Range (toPos (6, 1)) (toPos (7, 16)), "Maybe Int -> Int") ] - testCommand testPlugins act "ghcmod" "type" arg res + testCommand testPlugins act "bios" "type" arg res it "runs the type command, variable matching" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -206,7 +206,7 @@ ghcmodSpec = [ (Range (toPos (10, 5)) (toPos (10, 6)), "Maybe Int") , (Range (toPos (10, 1)) (toPos (12, 17)), "Maybe Int -> Int") ] - testCommand testPlugins act "ghcmod" "type" arg res + testCommand testPlugins act "bios" "type" arg res it "runs the type command, case expr" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -220,7 +220,7 @@ ghcmodSpec = , (Range (toPos (10, 9)) (toPos (12, 17)), "Maybe Int -> Int") , (Range (toPos (10, 1)) (toPos (12, 17)), "Maybe Int -> Int") ] - testCommand testPlugins act "ghcmod" "type" arg res + testCommand testPlugins act "bios" "type" arg res it "runs the type command, case expr match, just" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -234,7 +234,7 @@ ghcmodSpec = , (Range (toPos (10, 9)) (toPos (12, 17)), "Maybe Int -> Int") , (Range (toPos (10, 1)) (toPos (12, 17)), "Maybe Int -> Int") ] - testCommand testPlugins act "ghcmod" "type" arg res + testCommand testPlugins act "bios" "type" arg res it "runs the type command, case expr match, just value" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -249,7 +249,7 @@ ghcmodSpec = , (Range (toPos (10, 9)) (toPos (12, 17)), "Maybe Int -> Int") , (Range (toPos (10, 1)) (toPos (12, 17)), "Maybe Int -> Int") ] - testCommand testPlugins act "ghcmod" "type" arg res + testCommand testPlugins act "bios" "type" arg res it "runs the type command, infix operator" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -263,7 +263,7 @@ ghcmodSpec = , (Range (toPos (10, 9)) (toPos (12, 17)), "Maybe Int -> Int") , (Range (toPos (10, 1)) (toPos (12, 17)), "Maybe Int -> Int") ] - testCommand testPlugins act "ghcmod" "type" arg res + testCommand testPlugins act "bios" "type" arg res it "runs the type command, case expr match, nothing" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -277,7 +277,7 @@ ghcmodSpec = , (Range (toPos (10, 9)) (toPos (12, 17)), "Maybe Int -> Int") , (Range (toPos (10, 1)) (toPos (12, 17)), "Maybe Int -> Int") ] - testCommand testPlugins act "ghcmod" "type" arg res + testCommand testPlugins act "bios" "type" arg res it "runs the type command, do bind expr result " $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -290,7 +290,7 @@ ghcmodSpec = [ (Range (toPos (16, 5)) (toPos (16, 6)), "Int") , (Range (toPos (15, 1)) (toPos (19, 19)), "Maybe Int -> Maybe Int") ] - testCommand testPlugins act "ghcmod" "type" arg res + testCommand testPlugins act "bios" "type" arg res it "runs the type command, do bind expr" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -303,7 +303,7 @@ ghcmodSpec = [ (Range (toPos (16, 10)) (toPos (16, 11)), "Maybe Int") , (Range (toPos (15, 1)) (toPos (19, 19)), "Maybe Int -> Maybe Int") ] - testCommand testPlugins act "ghcmod" "type" arg res + testCommand testPlugins act "bios" "type" arg res it "runs the type command, let binding function, return func" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -317,7 +317,7 @@ ghcmodSpec = , (Range (toPos (17, 9)) (toPos (17, 28)), "Maybe Int") , (Range (toPos (15, 1)) (toPos (19, 19)), "Maybe Int -> Maybe Int") ] - testCommand testPlugins act "ghcmod" "type" arg res + testCommand testPlugins act "bios" "type" arg res it "runs the type command, let binding function, return param" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -331,7 +331,7 @@ ghcmodSpec = , (Range (toPos (17, 9)) (toPos (17, 28)), "Maybe Int") , (Range (toPos (15, 1)) (toPos (19, 19)), "Maybe Int -> Maybe Int") ] - testCommand testPlugins act "ghcmod" "type" arg res + testCommand testPlugins act "bios" "type" arg res it "runs the type command, let binding function, function type" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -344,7 +344,7 @@ ghcmodSpec = [ (Range (toPos (17, 9)) (toPos (17, 28)), "Maybe Int") , (Range (toPos (15, 1)) (toPos (19, 19)), "Maybe Int -> Maybe Int") ] - testCommand testPlugins act "ghcmod" "type" arg res + testCommand testPlugins act "bios" "type" arg res it "runs the type command, do expr, function type" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -357,7 +357,7 @@ ghcmodSpec = [ (Range (toPos (18, 10)) (toPos (18, 11)), "Maybe Int") , (Range (toPos (15, 1)) (toPos (19, 19)), "Maybe Int -> Maybe Int") ] - testCommand testPlugins act "ghcmod" "type" arg res + testCommand testPlugins act "bios" "type" arg res it "runs the type command, let binding function, do expr bind for local func" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -370,7 +370,7 @@ ghcmodSpec = [ (Range (toPos (18, 5)) (toPos (18, 6)), "Int") , (Range (toPos (15, 1)) (toPos (19, 19)), "Maybe Int -> Maybe Int") ] - testCommand testPlugins act "ghcmod" "type" arg res + testCommand testPlugins act "bios" "type" arg res it "runs the type command, function type" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -382,7 +382,7 @@ ghcmodSpec = res = IdeResultOk [ (Range (toPos (15, 1)) (toPos (19, 19)), "Maybe Int -> Maybe Int") ] - testCommand testPlugins act "ghcmod" "type" arg res + testCommand testPlugins act "bios" "type" arg res it "runs the type command, function parameter" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -395,7 +395,7 @@ ghcmodSpec = [ (Range (toPos (22, 10)) (toPos (22, 11)), "a -> a") , (Range (toPos (22, 1)) (toPos (22, 19)), "(a -> a) -> a -> a") ] - testCommand testPlugins act "ghcmod" "type" arg res + testCommand testPlugins act "bios" "type" arg res it "runs the type command, function composition" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -409,7 +409,7 @@ ghcmodSpec = , (Range (toPos (25, 20)) (toPos (25, 29)), "a -> c") , (Range (toPos (25, 1)) (toPos (25, 34)), "(b -> c) -> (a -> b) -> a -> c") ] - testCommand testPlugins act "ghcmod" "type" arg res + testCommand testPlugins act "bios" "type" arg res it "runs the type command, let binding, function composition" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -422,7 +422,7 @@ ghcmodSpec = [ (Range (toPos (25, 20)) (toPos (25, 29)), "a -> c") , (Range (toPos (25, 1)) (toPos (25, 34)), "(b -> c) -> (a -> b) -> a -> c") ] - testCommand testPlugins act "ghcmod" "type" arg res + testCommand testPlugins act "bios" "type" arg res it "runs the type command, let binding, type of function" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -435,7 +435,7 @@ ghcmodSpec = [ (Range (toPos (25, 33)) (toPos (25, 34)), "a -> c") , (Range (toPos (25, 1)) (toPos (25, 34)), "(b -> c) -> (a -> b) -> a -> c") ] - testCommand testPlugins act "ghcmod" "type" arg res + testCommand testPlugins act "bios" "type" arg res it "runs the type command, function type composition" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -447,7 +447,7 @@ ghcmodSpec = res = IdeResultOk [ (Range (toPos (25, 1)) (toPos (25, 34)), "(b -> c) -> (a -> b) -> a -> c") ] - testCommand testPlugins act "ghcmod" "type" arg res + testCommand testPlugins act "bios" "type" arg res it "runs the type command, infix operator" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -460,7 +460,7 @@ ghcmodSpec = [ (Range (toPos (28, 25)) (toPos (28, 28)), "(a -> b) -> IO a -> IO b") , (Range (toPos (28, 1)) (toPos (28, 35)), "(a -> b) -> IO a -> IO b") ] - testCommand testPlugins act "ghcmod" "type" arg res + testCommand testPlugins act "bios" "type" arg res it "runs the type command, constructor" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -472,7 +472,7 @@ ghcmodSpec = res = IdeResultOk [ -- (Range (toPos (31, 7)) (toPos (31, 12)), "Int -> Test") ] - testCommand testPlugins act "ghcmod" "type" arg res + testCommand testPlugins act "bios" "type" arg res it "runs the type command, deriving clause Show type" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -492,7 +492,7 @@ ghcmodSpec = , (Range (toPos (33, 15)) (toPos (33, 19)), "[Test] -> ShowS") #endif ] - testCommand testPlugins act "ghcmod" "type" arg res + testCommand testPlugins act "bios" "type" arg res it "runs the type command, deriving clause Eq type" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -511,7 +511,7 @@ ghcmodSpec = , (Range (toPos (33, 21)) (toPos (33, 23)), "Test -> Test -> Bool") #endif ] - testCommand testPlugins act "ghcmod" "type" arg res + testCommand testPlugins act "bios" "type" arg res -- ---------------------------------------------------------------------------- it "runs the type command with an absolute path from another folder, correct params" $ do @@ -530,7 +530,7 @@ ghcmodSpec = [(Range (toPos (5,9)) (toPos (5,10)), "Int") , (Range (toPos (5,1)) (toPos (5,14)), "Int -> Int") ] - testCommand testPlugins act "ghcmod" "type" arg res + testCommand testPlugins act "bios" "type" arg res -- --------------------------------- @@ -546,7 +546,7 @@ ghcmodSpec = -- $ List [TextEdit (Range (Position 4 0) (Position 4 10)) -- "foo Nothing = ()\nfoo (Just x) = ()"]) -- Nothing --- testCommand testPlugins act "ghcmod" "casesplit" arg res +-- testCommand testPlugins act "bios" "casesplit" arg res -- it "runs the casesplit command with an absolute path from another folder, correct params" $ do -- fp <- makeAbsolute "./test/testdata/GhcModCaseSplit.hs" @@ -565,4 +565,4 @@ ghcmodSpec = -- $ List [TextEdit (Range (Position 4 0) (Position 4 10)) -- "foo Nothing = ()\nfoo (Just x) = ()"]) -- Nothing --- testCommand testPlugins act "ghcmod" "casesplit" arg res +-- testCommand testPlugins act "bios" "casesplit" arg res From d25984cd3ac7464ea9170ea7373ba6fb4b9bad02 Mon Sep 17 00:00:00 2001 From: Zubin Duggal Date: Mon, 22 Jul 2019 20:02:35 +0530 Subject: [PATCH 153/158] fix more tests --- cabal.project | 2 +- haskell-ide-engine.cabal | 1 + hie-plugin-api/Haskell/Ide/Engine/Ghc.hs | 11 ++----- src/Haskell/Ide/Engine/Plugin/Generic.hs | 13 +++++++- src/Haskell/Ide/Engine/Plugin/Haddock.hs | 2 +- test/functional/ProgressSpec.hs | 30 +++++++++++-------- test/testdata/gototest/cabal.project | 1 + .../gototest/{test.cabal => gototest.cabal} | 11 +++++-- test/unit/HaRePluginSpec.hs | 30 +++++++++++++------ 9 files changed, 66 insertions(+), 35 deletions(-) create mode 100644 test/testdata/gototest/cabal.project rename test/testdata/gototest/{test.cabal => gototest.cabal} (61%) diff --git a/cabal.project b/cabal.project index ec4e1c23d..e75e930ec 100644 --- a/cabal.project +++ b/cabal.project @@ -11,7 +11,7 @@ packages: allow-newer: floskell:all -profiling: True +profiling: false ghc-options: -Werror diff --git a/haskell-ide-engine.cabal b/haskell-ide-engine.cabal index 82d7dcfdd..2f31cc9ba 100644 --- a/haskell-ide-engine.cabal +++ b/haskell-ide-engine.cabal @@ -187,6 +187,7 @@ test-suite unit-test build-tool-depends: cabal-helper:cabal-helper-main, hspec-discover:hspec-discover build-depends: QuickCheck , aeson + , ghc , base , bytestring , containers diff --git a/hie-plugin-api/Haskell/Ide/Engine/Ghc.hs b/hie-plugin-api/Haskell/Ide/Engine/Ghc.hs index 63533b5c2..755a71b4b 100644 --- a/hie-plugin-api/Haskell/Ide/Engine/Ghc.hs +++ b/hie-plugin-api/Haskell/Ide/Engine/Ghc.hs @@ -248,7 +248,7 @@ setTypecheckedModule_load uri = let collapse Nothing = (Nothing, []) collapse (Just (n, xs)) = (n, xs) - diags2 <- case collapse mmods of + case collapse mmods of --Just (Just pm, Nothing) -> do -- debugm $ "setTypecheckedModule: Did get parsed module for: " ++ show fp -- cacheModule fp (Left pm) @@ -267,7 +267,6 @@ setTypecheckedModule_load uri = cacheModules rfm ts --cacheModules rfm [tm] debugm "setTypecheckedModule: done" - return diags (Nothing, ts) -> do debugm $ "setTypecheckedModule: Didn't get typechecked or parsed module for: " ++ show fp @@ -275,13 +274,7 @@ setTypecheckedModule_load uri = cacheModules rfm ts failModule fp - let sev = Just DsError - range = Range (Position 0 0) (Position 1 0) - msgTxt = T.unlines errs - let d = Diagnostic range sev Nothing (Just "bios") msgTxt Nothing - return $ Map.insertWith Set.union canonUri (Set.singleton d) diags - - return $ IdeResultOk (Diagnostics diags2,errs) + return $ IdeResultOk (Diagnostics diags,errs) -- TODO: make this work for all components cabalModuleGraphs :: IdeGhcM [GM.GmModuleGraph] diff --git a/src/Haskell/Ide/Engine/Plugin/Generic.hs b/src/Haskell/Ide/Engine/Plugin/Generic.hs index 8ac1b4778..97cfea906 100644 --- a/src/Haskell/Ide/Engine/Plugin/Generic.hs +++ b/src/Haskell/Ide/Engine/Plugin/Generic.hs @@ -490,11 +490,22 @@ symbolProvider uri = pluginGetFile "ghc-mod symbolProvider: " uri $ goValD (L l (PatBind { pat_lhs = p })) = map (\n -> Decl LSP.SkVariable n [] l) $ hsNamessRdr p +#if __GLASGOW_HASKELL__ >= 806 + goValD (L l (PatSynBind _ idR)) = case idR of + XPatSynBind _ -> error "xPatSynBind" + PSB { psb_id = ln } -> +#else + goValD (L l (PatSynBind (PSB { psb_id = ln }))) = +#endif + -- We are reporting pattern synonyms as functions. There is no such + -- thing as pattern synonym in current LSP specification so we pick up + -- an (arguably) closest match. + pure (Decl LSP.SkFunction ln [] l) + #if __GLASGOW_HASKELL__ >= 806 goValD (L _ (FunBind _ _ (XMatchGroup _) _ _)) = error "goValD" goValD (L _ (VarBind _ _ _ _)) = error "goValD" goValD (L _ (AbsBinds _ _ _ _ _ _ _)) = error "goValD" - goValD (L _ (PatSynBind _ _)) = error "goValD" goValD (L _ (XHsBindsLR _)) = error "goValD" #elif __GLASGOW_HASKELL__ >= 804 goValD (L _ (VarBind _ _ _)) = error "goValD" diff --git a/src/Haskell/Ide/Engine/Plugin/Haddock.hs b/src/Haskell/Ide/Engine/Plugin/Haddock.hs index 12b75e05c..94d478bfb 100644 --- a/src/Haskell/Ide/Engine/Plugin/Haddock.hs +++ b/src/Haskell/Ide/Engine/Plugin/Haddock.hs @@ -43,7 +43,7 @@ haddockDescriptor plId = PluginDescriptor , pluginCommands = [] , pluginCodeActionProvider = Nothing , pluginDiagnosticProvider = Nothing - , pluginHoverProvider = Nothing + , pluginHoverProvider = Just hoverProvider , pluginSymbolProvider = Nothing , pluginFormattingProvider = Nothing } diff --git a/test/functional/ProgressSpec.hs b/test/functional/ProgressSpec.hs index a42659cfb..bc07216b9 100644 --- a/test/functional/ProgressSpec.hs +++ b/test/functional/ProgressSpec.hs @@ -24,36 +24,42 @@ spec = describe "window/progress" $ do skipMany loggingNotification - -- Initial hlint notifications - _ <- publishDiagnosticsNotification - startNotification <- message :: Session ProgressStartNotification liftIO $ do - startNotification ^. L.params . L.title `shouldBe` "Typechecking ApplyRefact2.hs" + startNotification ^. L.params . L.title `shouldBe` "Initialising Cradle" startNotification ^. L.params . L.id `shouldBe` "0" + reportNotification <- message :: Session ProgressReportNotification + liftIO $ do + reportNotification ^. L.params . L.message `shouldBe` Just "Main" + reportNotification ^. L.params . L.id `shouldBe` "0" + doneNotification <- message :: Session ProgressDoneNotification liftIO $ doneNotification ^. L.params . L.id `shouldBe` "0" - -- the ghc-mod diagnostics + -- Initial hlint notifications _ <- publishDiagnosticsNotification -- Test incrementing ids sendNotification TextDocumentDidSave (DidSaveTextDocumentParams doc) - -- hlint notifications - _ <- publishDiagnosticsNotification - startNotification' <- message :: Session ProgressStartNotification liftIO $ do - startNotification' ^. L.params . L.title `shouldBe` "Typechecking ApplyRefact2.hs" + startNotification' ^. L.params . L.title `shouldBe` "loading" startNotification' ^. L.params . L.id `shouldBe` "1" + reportNotification' <- message :: Session ProgressReportNotification + liftIO $ do + reportNotification' ^. L.params . L.message `shouldBe` Just "Main" + reportNotification' ^. L.params . L.id `shouldBe` "1" + doneNotification' <- message :: Session ProgressDoneNotification liftIO $ doneNotification' ^. L.params . L.id `shouldBe` "1" - -- the ghc-mod diagnostics - const () <$> publishDiagnosticsNotification + -- hlint notifications + _ <- publishDiagnosticsNotification + return () + it "sends indefinite progress notifications with liquid" $ -- Testing that Liquid Haskell sends progress notifications runSession hieCommand progressCaps "test/testdata" $ do @@ -92,4 +98,4 @@ spec = describe "window/progress" $ do return () progressCaps :: ClientCapabilities -progressCaps = fullCaps { _window = Just (WindowClientCapabilities (Just True)) } \ No newline at end of file +progressCaps = fullCaps { _window = Just (WindowClientCapabilities (Just True)) } diff --git a/test/testdata/gototest/cabal.project b/test/testdata/gototest/cabal.project new file mode 100644 index 000000000..e6fdbadb4 --- /dev/null +++ b/test/testdata/gototest/cabal.project @@ -0,0 +1 @@ +packages: . diff --git a/test/testdata/gototest/test.cabal b/test/testdata/gototest/gototest.cabal similarity index 61% rename from test/testdata/gototest/test.cabal rename to test/testdata/gototest/gototest.cabal index 66b93f810..5cac1ffef 100644 --- a/test/testdata/gototest/test.cabal +++ b/test/testdata/gototest/gototest.cabal @@ -1,4 +1,4 @@ -name: test +name: gototest version: 0.1.0.0 -- synopsis: -- description: @@ -10,8 +10,15 @@ category: Web build-type: Simple cabal-version: >=1.10 +executable gototest-exec + hs-source-dirs: app + main-is: Main.hs + other-modules: + build-depends: base >= 4.7 && < 5, gototest + default-language: Haskell2010 + library hs-source-dirs: src exposed-modules: Lib, Lib2 build-depends: base >= 4.7 && < 5 - default-language: Haskell2010 \ No newline at end of file + default-language: Haskell2010 diff --git a/test/unit/HaRePluginSpec.hs b/test/unit/HaRePluginSpec.hs index 6d425118f..c7f1c37d0 100644 --- a/test/unit/HaRePluginSpec.hs +++ b/test/unit/HaRePluginSpec.hs @@ -21,7 +21,7 @@ import Language.Haskell.LSP.Types ( Location(..) import System.Directory import System.FilePath import TestUtils - +import GhcMonad import Test.Hspec -- --------------------------------------------------------------------- @@ -176,8 +176,11 @@ hareSpec = do cwd <- runIO getCurrentDirectory it "finds definition across components" $ do - let u = filePathToUri $ cwd "test/testdata/gototest/app/Main.hs" - lreq = setTypecheckedModule u + let fp = cwd "test/testdata/gototest/app/Main.hs" + let u = filePathToUri $ fp + lreq = do + df <- getSessionDynFlags + runActionWithContext df (Just fp) $ setTypecheckedModule u req = liftToGhc $ TestDeferM $ findDef u (toPos (7,8)) r <- dispatchRequestPGoto $ lreq >> req r `shouldBe` IdeResultOk [Location (filePathToUri $ cwd "test/testdata/gototest/src/Lib.hs") @@ -187,15 +190,21 @@ hareSpec = do r2 `shouldBe` IdeResultOk [Location (filePathToUri $ cwd "test/testdata/gototest/src/Lib2.hs") (Range (toPos (5,1)) (toPos (5,2)))] it "finds definition in the same component" $ do - let u = filePathToUri $ cwd "test/testdata/gototest/src/Lib2.hs" - lreq = setTypecheckedModule u + let fp = cwd "test/testdata/gototest/src/Lib2.hs" + let u = filePathToUri $ fp + lreq = do + df <- getSessionDynFlags + runActionWithContext df (Just fp) $ setTypecheckedModule u req = liftToGhc $ TestDeferM $ findDef u (toPos (6,5)) r <- dispatchRequestPGoto $ lreq >> req r `shouldBe` IdeResultOk [Location (filePathToUri $ cwd "test/testdata/gototest/src/Lib.hs") (Range (toPos (6,1)) (toPos (6,9)))] it "finds local definitions" $ do - let u = filePathToUri $ cwd "test/testdata/gototest/src/Lib2.hs" - lreq = setTypecheckedModule u + let fp = cwd "test/testdata/gototest/src/Lib2.hs" + let u = filePathToUri $ fp + lreq = do + df <- getSessionDynFlags + runActionWithContext df (Just fp) $ setTypecheckedModule u req = liftToGhc $ TestDeferM $ findDef u (toPos (7,11)) r <- dispatchRequestPGoto $ lreq >> req r `shouldBe` IdeResultOk [Location (filePathToUri $ cwd "test/testdata/gototest/src/Lib2.hs") @@ -261,8 +270,11 @@ hareSpec = do (Range (toPos (18, 1)) (toPos (18, 26))) ] it "find type-definition of type def in component" $ do - let u = filePathToUri $ cwd "test/testdata/gototest/src/Lib2.hs" - lreq = setTypecheckedModule u + let fp = cwd "test/testdata/gototest/src/Lib2.hs" + let u = filePathToUri $ fp + lreq = do + df <- getSessionDynFlags + runActionWithContext df (Just fp) $ setTypecheckedModule u req = liftToGhc $ TestDeferM $ findTypeDef u (toPos (13, 20)) r <- dispatchRequestPGoto $ lreq >> req r `shouldBe` IdeResultOk From 2bd16d845317b6302a741552ff4af523cabc1ce7 Mon Sep 17 00:00:00 2001 From: Zubin Duggal Date: Mon, 22 Jul 2019 20:21:55 +0530 Subject: [PATCH 154/158] fix more tests redux --- src/Haskell/Ide/Engine/Plugin/Generic.hs | 6 ++- test/functional/DeferredSpec.hs | 2 +- test/unit/GhcModPluginSpec.hs | 67 ++++++++++++------------ 3 files changed, 40 insertions(+), 35 deletions(-) diff --git a/src/Haskell/Ide/Engine/Plugin/Generic.hs b/src/Haskell/Ide/Engine/Plugin/Generic.hs index 97cfea906..64260aee6 100644 --- a/src/Haskell/Ide/Engine/Plugin/Generic.hs +++ b/src/Haskell/Ide/Engine/Plugin/Generic.hs @@ -44,7 +44,7 @@ genericDescriptor plId = PluginDescriptor { pluginId = plId , pluginName = "generic" , pluginDesc = "generic actions" - , pluginCommands = [] + , pluginCommands = [PluginCommand "type" "Get the type of the expression under (LINE,COL)" typeCmd] , pluginCodeActionProvider = Just codeActionProvider , pluginDiagnosticProvider = Nothing , pluginHoverProvider = Just hoverProvider @@ -65,6 +65,10 @@ instance FromJSON TypeParams where instance ToJSON TypeParams where toJSON = genericToJSON customOptions +typeCmd :: CommandFunc TypeParams [(Range,T.Text)] +typeCmd = CmdSync $ \(TP _bool uri pos) -> + liftToGhc $ newTypeCmd pos uri + newTypeCmd :: Position -> Uri -> IdeM (IdeResult [(Range, T.Text)]) newTypeCmd newPos uri = pluginGetFile "newTypeCmd: " uri $ \fp -> diff --git a/test/functional/DeferredSpec.hs b/test/functional/DeferredSpec.hs index 1ad189c25..373eee229 100644 --- a/test/functional/DeferredSpec.hs +++ b/test/functional/DeferredSpec.hs @@ -153,7 +153,7 @@ spec = do describe "multiple main modules" $ it "Can load one file at a time, when more than one Main module exists" -- $ runSession hieCommand fullCaps "test/testdata" $ do - $ runSession hieCommandVomit fullCaps "test/testdata" $ do + $ runSession hieCommand fullCaps "test/testdata" $ do _doc <- openDoc "ApplyRefact2.hs" "haskell" _diagsRspHlint <- skipManyTill anyNotification message :: Session PublishDiagnosticsNotification diagsRspGhc <- skipManyTill anyNotification message :: Session PublishDiagnosticsNotification diff --git a/test/unit/GhcModPluginSpec.hs b/test/unit/GhcModPluginSpec.hs index 93bf22388..8e20ba1c3 100644 --- a/test/unit/GhcModPluginSpec.hs +++ b/test/unit/GhcModPluginSpec.hs @@ -13,6 +13,7 @@ import qualified Data.Text as T import Haskell.Ide.Engine.Ghc import Haskell.Ide.Engine.MonadTypes import Haskell.Ide.Engine.Plugin.Generic +import Haskell.Ide.Engine.Plugin.Bios import Haskell.Ide.Engine.PluginUtils import Haskell.Ide.Engine.Support.HieExtras import Language.Haskell.LSP.Types (TextEdit (..), toNormalizedUri) @@ -33,7 +34,7 @@ spec = do -- --------------------------------------------------------------------- testPlugins :: IdePlugins -testPlugins = pluginDescToIdePlugins [genericDescriptor "bios"] +testPlugins = pluginDescToIdePlugins [biosDescriptor "bios", genericDescriptor "generic" ] -- --------------------------------------------------------------------- @@ -102,7 +103,7 @@ ghcmodSpec = , (Range (toPos (5,1)) (toPos (5,14)), "Int -> Int") ] - testCommand testPlugins act "bios" "type" arg res + testCommand testPlugins act "generic" "type" arg res it "runs the type command, find function type" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "HaReRename.hs" @@ -115,7 +116,7 @@ ghcmodSpec = [ (Range (toPos (2, 8)) (toPos (2,16)), "String -> IO ()") , (Range (toPos (2, 1)) (toPos (2,24)), "IO ()") ] - testCommand testPlugins act "bios" "type" arg res + testCommand testPlugins act "generic" "type" arg res it "runs the type command, no type at location" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "HaReRename.hs" @@ -125,7 +126,7 @@ ghcmodSpec = liftToGhc $ newTypeCmd (toPos (1,1)) uri arg = TP False uri (toPos (1,1)) res = IdeResultOk [] - testCommand testPlugins act "bios" "type" arg res + testCommand testPlugins act "generic" "type" arg res it "runs the type command, simple" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -138,7 +139,7 @@ ghcmodSpec = [ (Range (toPos (6, 16)) (toPos (6,17)), "Int") , (Range (toPos (6, 1)) (toPos (7, 16)), "Maybe Int -> Int") ] - testCommand testPlugins act "bios" "type" arg res + testCommand testPlugins act "generic" "type" arg res it "runs the type command, sum type pattern match, just" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -152,7 +153,7 @@ ghcmodSpec = , (Range (toPos (6, 5)) (toPos (6, 13)), "Maybe Int") , (Range (toPos (6, 1)) (toPos (7, 16)), "Maybe Int -> Int") ] - testCommand testPlugins act "bios" "type" arg res + testCommand testPlugins act "generic" "type" arg res it "runs the type command, sum type pattern match, just value" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -167,7 +168,7 @@ ghcmodSpec = , (Range (toPos (6, 5)) (toPos (6, 13)), "Maybe Int") , (Range (toPos (6, 1)) (toPos (7, 16)), "Maybe Int -> Int") ] - testCommand testPlugins act "bios" "type" arg res + testCommand testPlugins act "generic" "type" arg res it "runs the type command, sum type pattern match, nothing" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -180,7 +181,7 @@ ghcmodSpec = [ (Range (toPos (7, 5)) (toPos (7, 12)), "Maybe Int") , (Range (toPos (6, 1)) (toPos (7, 16)), "Maybe Int -> Int") ] - testCommand testPlugins act "bios" "type" arg res + testCommand testPlugins act "generic" "type" arg res it "runs the type command, sum type pattern match, nothing, literal" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -193,7 +194,7 @@ ghcmodSpec = [ (Range (toPos (7, 15)) (toPos (7, 16)), "Int") , (Range (toPos (6, 1)) (toPos (7, 16)), "Maybe Int -> Int") ] - testCommand testPlugins act "bios" "type" arg res + testCommand testPlugins act "generic" "type" arg res it "runs the type command, variable matching" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -206,7 +207,7 @@ ghcmodSpec = [ (Range (toPos (10, 5)) (toPos (10, 6)), "Maybe Int") , (Range (toPos (10, 1)) (toPos (12, 17)), "Maybe Int -> Int") ] - testCommand testPlugins act "bios" "type" arg res + testCommand testPlugins act "generic" "type" arg res it "runs the type command, case expr" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -220,7 +221,7 @@ ghcmodSpec = , (Range (toPos (10, 9)) (toPos (12, 17)), "Maybe Int -> Int") , (Range (toPos (10, 1)) (toPos (12, 17)), "Maybe Int -> Int") ] - testCommand testPlugins act "bios" "type" arg res + testCommand testPlugins act "generic" "type" arg res it "runs the type command, case expr match, just" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -234,7 +235,7 @@ ghcmodSpec = , (Range (toPos (10, 9)) (toPos (12, 17)), "Maybe Int -> Int") , (Range (toPos (10, 1)) (toPos (12, 17)), "Maybe Int -> Int") ] - testCommand testPlugins act "bios" "type" arg res + testCommand testPlugins act "generic" "type" arg res it "runs the type command, case expr match, just value" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -249,7 +250,7 @@ ghcmodSpec = , (Range (toPos (10, 9)) (toPos (12, 17)), "Maybe Int -> Int") , (Range (toPos (10, 1)) (toPos (12, 17)), "Maybe Int -> Int") ] - testCommand testPlugins act "bios" "type" arg res + testCommand testPlugins act "generic" "type" arg res it "runs the type command, infix operator" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -263,7 +264,7 @@ ghcmodSpec = , (Range (toPos (10, 9)) (toPos (12, 17)), "Maybe Int -> Int") , (Range (toPos (10, 1)) (toPos (12, 17)), "Maybe Int -> Int") ] - testCommand testPlugins act "bios" "type" arg res + testCommand testPlugins act "generic" "type" arg res it "runs the type command, case expr match, nothing" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -277,7 +278,7 @@ ghcmodSpec = , (Range (toPos (10, 9)) (toPos (12, 17)), "Maybe Int -> Int") , (Range (toPos (10, 1)) (toPos (12, 17)), "Maybe Int -> Int") ] - testCommand testPlugins act "bios" "type" arg res + testCommand testPlugins act "generic" "type" arg res it "runs the type command, do bind expr result " $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -290,7 +291,7 @@ ghcmodSpec = [ (Range (toPos (16, 5)) (toPos (16, 6)), "Int") , (Range (toPos (15, 1)) (toPos (19, 19)), "Maybe Int -> Maybe Int") ] - testCommand testPlugins act "bios" "type" arg res + testCommand testPlugins act "generic" "type" arg res it "runs the type command, do bind expr" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -303,7 +304,7 @@ ghcmodSpec = [ (Range (toPos (16, 10)) (toPos (16, 11)), "Maybe Int") , (Range (toPos (15, 1)) (toPos (19, 19)), "Maybe Int -> Maybe Int") ] - testCommand testPlugins act "bios" "type" arg res + testCommand testPlugins act "generic" "type" arg res it "runs the type command, let binding function, return func" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -317,7 +318,7 @@ ghcmodSpec = , (Range (toPos (17, 9)) (toPos (17, 28)), "Maybe Int") , (Range (toPos (15, 1)) (toPos (19, 19)), "Maybe Int -> Maybe Int") ] - testCommand testPlugins act "bios" "type" arg res + testCommand testPlugins act "generic" "type" arg res it "runs the type command, let binding function, return param" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -331,7 +332,7 @@ ghcmodSpec = , (Range (toPos (17, 9)) (toPos (17, 28)), "Maybe Int") , (Range (toPos (15, 1)) (toPos (19, 19)), "Maybe Int -> Maybe Int") ] - testCommand testPlugins act "bios" "type" arg res + testCommand testPlugins act "generic" "type" arg res it "runs the type command, let binding function, function type" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -344,7 +345,7 @@ ghcmodSpec = [ (Range (toPos (17, 9)) (toPos (17, 28)), "Maybe Int") , (Range (toPos (15, 1)) (toPos (19, 19)), "Maybe Int -> Maybe Int") ] - testCommand testPlugins act "bios" "type" arg res + testCommand testPlugins act "generic" "type" arg res it "runs the type command, do expr, function type" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -357,7 +358,7 @@ ghcmodSpec = [ (Range (toPos (18, 10)) (toPos (18, 11)), "Maybe Int") , (Range (toPos (15, 1)) (toPos (19, 19)), "Maybe Int -> Maybe Int") ] - testCommand testPlugins act "bios" "type" arg res + testCommand testPlugins act "generic" "type" arg res it "runs the type command, let binding function, do expr bind for local func" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -370,7 +371,7 @@ ghcmodSpec = [ (Range (toPos (18, 5)) (toPos (18, 6)), "Int") , (Range (toPos (15, 1)) (toPos (19, 19)), "Maybe Int -> Maybe Int") ] - testCommand testPlugins act "bios" "type" arg res + testCommand testPlugins act "generic" "type" arg res it "runs the type command, function type" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -382,7 +383,7 @@ ghcmodSpec = res = IdeResultOk [ (Range (toPos (15, 1)) (toPos (19, 19)), "Maybe Int -> Maybe Int") ] - testCommand testPlugins act "bios" "type" arg res + testCommand testPlugins act "generic" "type" arg res it "runs the type command, function parameter" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -395,7 +396,7 @@ ghcmodSpec = [ (Range (toPos (22, 10)) (toPos (22, 11)), "a -> a") , (Range (toPos (22, 1)) (toPos (22, 19)), "(a -> a) -> a -> a") ] - testCommand testPlugins act "bios" "type" arg res + testCommand testPlugins act "generic" "type" arg res it "runs the type command, function composition" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -409,7 +410,7 @@ ghcmodSpec = , (Range (toPos (25, 20)) (toPos (25, 29)), "a -> c") , (Range (toPos (25, 1)) (toPos (25, 34)), "(b -> c) -> (a -> b) -> a -> c") ] - testCommand testPlugins act "bios" "type" arg res + testCommand testPlugins act "generic" "type" arg res it "runs the type command, let binding, function composition" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -422,7 +423,7 @@ ghcmodSpec = [ (Range (toPos (25, 20)) (toPos (25, 29)), "a -> c") , (Range (toPos (25, 1)) (toPos (25, 34)), "(b -> c) -> (a -> b) -> a -> c") ] - testCommand testPlugins act "bios" "type" arg res + testCommand testPlugins act "generic" "type" arg res it "runs the type command, let binding, type of function" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -435,7 +436,7 @@ ghcmodSpec = [ (Range (toPos (25, 33)) (toPos (25, 34)), "a -> c") , (Range (toPos (25, 1)) (toPos (25, 34)), "(b -> c) -> (a -> b) -> a -> c") ] - testCommand testPlugins act "bios" "type" arg res + testCommand testPlugins act "generic" "type" arg res it "runs the type command, function type composition" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -447,7 +448,7 @@ ghcmodSpec = res = IdeResultOk [ (Range (toPos (25, 1)) (toPos (25, 34)), "(b -> c) -> (a -> b) -> a -> c") ] - testCommand testPlugins act "bios" "type" arg res + testCommand testPlugins act "generic" "type" arg res it "runs the type command, infix operator" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -460,7 +461,7 @@ ghcmodSpec = [ (Range (toPos (28, 25)) (toPos (28, 28)), "(a -> b) -> IO a -> IO b") , (Range (toPos (28, 1)) (toPos (28, 35)), "(a -> b) -> IO a -> IO b") ] - testCommand testPlugins act "bios" "type" arg res + testCommand testPlugins act "generic" "type" arg res it "runs the type command, constructor" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -472,7 +473,7 @@ ghcmodSpec = res = IdeResultOk [ -- (Range (toPos (31, 7)) (toPos (31, 12)), "Int -> Test") ] - testCommand testPlugins act "bios" "type" arg res + testCommand testPlugins act "generic" "type" arg res it "runs the type command, deriving clause Show type" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -492,7 +493,7 @@ ghcmodSpec = , (Range (toPos (33, 15)) (toPos (33, 19)), "[Test] -> ShowS") #endif ] - testCommand testPlugins act "bios" "type" arg res + testCommand testPlugins act "generic" "type" arg res it "runs the type command, deriving clause Eq type" $ withCurrentDirectory "./test/testdata" $ do fp <- makeAbsolute "Types.hs" @@ -511,7 +512,7 @@ ghcmodSpec = , (Range (toPos (33, 21)) (toPos (33, 23)), "Test -> Test -> Bool") #endif ] - testCommand testPlugins act "bios" "type" arg res + testCommand testPlugins act "generic" "type" arg res -- ---------------------------------------------------------------------------- it "runs the type command with an absolute path from another folder, correct params" $ do @@ -530,7 +531,7 @@ ghcmodSpec = [(Range (toPos (5,9)) (toPos (5,10)), "Int") , (Range (toPos (5,1)) (toPos (5,14)), "Int -> Int") ] - testCommand testPlugins act "bios" "type" arg res + testCommand testPlugins act "generic" "type" arg res -- --------------------------------- From f5a0308f1fa0aa1d26ab5b4cefd3178457f0b920 Mon Sep 17 00:00:00 2001 From: Zubin Duggal Date: Mon, 22 Jul 2019 22:24:07 +0530 Subject: [PATCH 155/158] Fix HaRe unit tests --- test/testdata/HaReGA1/.hie-bios | 1 + test/testdata/HaReGA1/HaReGA1.cabal | 10 +++++ test/testdata/{ => HaReGA1}/HaReGA1.hs | 0 test/testdata/HaReGA1/cabal.project | 1 + test/unit/HaRePluginSpec.hs | 59 +++++++++++++------------- 5 files changed, 41 insertions(+), 30 deletions(-) create mode 100755 test/testdata/HaReGA1/.hie-bios create mode 100644 test/testdata/HaReGA1/HaReGA1.cabal rename test/testdata/{ => HaReGA1}/HaReGA1.hs (100%) create mode 100644 test/testdata/HaReGA1/cabal.project diff --git a/test/testdata/HaReGA1/.hie-bios b/test/testdata/HaReGA1/.hie-bios new file mode 100755 index 000000000..80ff32c69 --- /dev/null +++ b/test/testdata/HaReGA1/.hie-bios @@ -0,0 +1 @@ +cabal-helper-helper . $1 diff --git a/test/testdata/HaReGA1/HaReGA1.cabal b/test/testdata/HaReGA1/HaReGA1.cabal new file mode 100644 index 000000000..add265b77 --- /dev/null +++ b/test/testdata/HaReGA1/HaReGA1.cabal @@ -0,0 +1,10 @@ +name: HaReGA1 +version: 0.1.0.0 +cabal-version: >=2.0 +build-type: Simple + +executable harega + build-depends: base, parsec + main-is: HaReGA1.hs + default-language: Haskell2010 + diff --git a/test/testdata/HaReGA1.hs b/test/testdata/HaReGA1/HaReGA1.hs similarity index 100% rename from test/testdata/HaReGA1.hs rename to test/testdata/HaReGA1/HaReGA1.hs diff --git a/test/testdata/HaReGA1/cabal.project b/test/testdata/HaReGA1/cabal.project new file mode 100644 index 000000000..e6fdbadb4 --- /dev/null +++ b/test/testdata/HaReGA1/cabal.project @@ -0,0 +1 @@ +packages: . diff --git a/test/unit/HaRePluginSpec.hs b/test/unit/HaRePluginSpec.hs index c7f1c37d0..60eefc2bb 100644 --- a/test/unit/HaRePluginSpec.hs +++ b/test/unit/HaRePluginSpec.hs @@ -48,6 +48,13 @@ dispatchRequestPGoto = -- --------------------------------------------------------------------- +runWithContext :: Uri -> IdeGhcM a -> IdeGhcM a +runWithContext uri act = case uriToFilePath uri of + Just fp -> do + df <- getSessionDynFlags + runActionWithContext df (Just fp) act + Nothing -> error $ "uri not valid: " ++ show uri + hareSpec :: Spec hareSpec = do describe "hare plugin commands(old plugin api)" $ do @@ -57,7 +64,7 @@ hareSpec = do it "renames" $ withCurrentDirectory "test/testdata" $ do let uri = filePathToUri $ cwd "test/testdata/HaReRename.hs" - act = renameCmd' uri (toPos (5,1)) "foolong" + act = runWithContext uri $ renameCmd' uri (toPos (5,1)) "foolong" arg = HPT uri (toPos (5,1)) "foolong" textEdits = List [TextEdit (Range (Position 3 0) (Position 4 13)) "foolong :: Int -> Int\nfoolong x = x + 3"] res = IdeResultOk $ WorkspaceEdit @@ -69,7 +76,7 @@ hareSpec = do it "returns an error for invalid rename" $ withCurrentDirectory "test/testdata" $ do let uri = filePathToUri $ cwd "test/testdata/HaReRename.hs" - act = renameCmd' uri (toPos (15,1)) "foolong" + act = runWithContext uri $ renameCmd' uri (toPos (15,1)) "foolong" arg = HPT uri (toPos (15,1)) "foolong" res = IdeResultFail IdeError { ideCode = PluginError @@ -80,7 +87,7 @@ hareSpec = do it "demotes" $ withCurrentDirectory "test/testdata" $ do let uri = filePathToUri $ cwd "test/testdata/HaReDemote.hs" - act = demoteCmd' uri (toPos (6,1)) + act = runWithContext uri $ demoteCmd' uri (toPos (6,1)) arg = HP uri (toPos (6,1)) textEdits = List [TextEdit (Range (Position 4 0) (Position 5 5)) " where\n y = 7"] res = IdeResultOk $ WorkspaceEdit @@ -92,7 +99,7 @@ hareSpec = do it "duplicates a definition" $ withCurrentDirectory "test/testdata" $ do let uri = filePathToUri $ cwd "test/testdata/HaReRename.hs" - act = dupdefCmd' uri (toPos (5,1)) "foonew" + act = runWithContext uri $ dupdefCmd' uri (toPos (5,1)) "foonew" arg = HPT uri (toPos (5,1)) "foonew" textEdits = List [TextEdit (Range (Position 6 0) (Position 6 0)) "foonew :: Int -> Int\nfoonew x = x + 3\n\n"] res = IdeResultOk $ WorkspaceEdit @@ -105,7 +112,7 @@ hareSpec = do it "converts if to case" $ withCurrentDirectory "test/testdata" $ do let uri = filePathToUri $ cwd "test/testdata/HaReCase.hs" - act = iftocaseCmd' uri (Range (toPos (5,9)) + act = runWithContext uri $ iftocaseCmd' uri (Range (toPos (5,9)) (toPos (9,12))) arg = HR uri (toPos (5,9)) (toPos (9,12)) textEdits = List [TextEdit (Range (Position 4 0) (Position 8 11)) @@ -120,7 +127,7 @@ hareSpec = do it "lifts one level" $ withCurrentDirectory "test/testdata" $ do let uri = filePathToUri $ cwd "test/testdata/HaReMoveDef.hs" - act = liftonelevelCmd' uri (toPos (6,5)) + act = runWithContext uri $ liftonelevelCmd' uri (toPos (6,5)) arg = HP uri (toPos (6,5)) textEdits = List [ TextEdit (Range (Position 6 0) (Position 6 0)) "y = 4\n\n" , TextEdit (Range (Position 4 0) (Position 6 0)) ""] @@ -134,7 +141,7 @@ hareSpec = do it "lifts to top level" $ withCurrentDirectory "test/testdata" $ do let uri = filePathToUri $ cwd "test/testdata/HaReMoveDef.hs" - act = lifttotoplevelCmd' uri (toPos (12,9)) + act = runWithContext uri $ lifttotoplevelCmd' uri (toPos (12,9)) arg = HP uri (toPos (12,9)) textEdits = List [ TextEdit (Range (Position 13 0) (Position 13 0)) "\n" , TextEdit (Range (Position 12 0) (Position 12 0)) "z = 7\n" @@ -149,7 +156,7 @@ hareSpec = do it "deletes a definition" $ withCurrentDirectory "test/testdata" $ do let uri = filePathToUri $ cwd "test/testdata/FuncTest.hs" - act = deleteDefCmd' uri (toPos (6,1)) + act = runWithContext uri $ deleteDefCmd' uri (toPos (6,1)) arg = HP uri (toPos (6,1)) textEdits = List [TextEdit (Range (Position 4 0) (Position 7 0)) ""] res = IdeResultOk $ WorkspaceEdit @@ -159,9 +166,9 @@ hareSpec = do -- --------------------------------- - it "generalises an applicative" $ withCurrentDirectory "test/testdata" $ do - let uri = filePathToUri $ cwd "test/testdata/HaReGA1.hs" - act = genApplicativeCommand' uri (toPos (4,1)) + it "generalises an applicative" $ withCurrentDirectory "test/testdata/HaReGA1/" $ do + let uri = filePathToUri $ cwd "test/testdata/HaReGA1/HaReGA1.hs" + act = runWithContext uri $ genApplicativeCommand' uri (toPos (4,1)) arg = HP uri (toPos (4,1)) textEdits = List [TextEdit (Range (Position 4 0) (Position 8 12)) "parseStr = char '\"' *> (many1 (noneOf \"\\\"\")) <* char '\"'"] @@ -178,9 +185,7 @@ hareSpec = do it "finds definition across components" $ do let fp = cwd "test/testdata/gototest/app/Main.hs" let u = filePathToUri $ fp - lreq = do - df <- getSessionDynFlags - runActionWithContext df (Just fp) $ setTypecheckedModule u + lreq = runWithContext u $ setTypecheckedModule u req = liftToGhc $ TestDeferM $ findDef u (toPos (7,8)) r <- dispatchRequestPGoto $ lreq >> req r `shouldBe` IdeResultOk [Location (filePathToUri $ cwd "test/testdata/gototest/src/Lib.hs") @@ -192,9 +197,7 @@ hareSpec = do it "finds definition in the same component" $ do let fp = cwd "test/testdata/gototest/src/Lib2.hs" let u = filePathToUri $ fp - lreq = do - df <- getSessionDynFlags - runActionWithContext df (Just fp) $ setTypecheckedModule u + lreq = runWithContext u $ setTypecheckedModule u req = liftToGhc $ TestDeferM $ findDef u (toPos (6,5)) r <- dispatchRequestPGoto $ lreq >> req r `shouldBe` IdeResultOk [Location (filePathToUri $ cwd "test/testdata/gototest/src/Lib.hs") @@ -202,9 +205,7 @@ hareSpec = do it "finds local definitions" $ do let fp = cwd "test/testdata/gototest/src/Lib2.hs" let u = filePathToUri $ fp - lreq = do - df <- getSessionDynFlags - runActionWithContext df (Just fp) $ setTypecheckedModule u + lreq = runWithContext u $ setTypecheckedModule u req = liftToGhc $ TestDeferM $ findDef u (toPos (7,11)) r <- dispatchRequestPGoto $ lreq >> req r `shouldBe` IdeResultOk [Location (filePathToUri $ cwd "test/testdata/gototest/src/Lib2.hs") @@ -215,7 +216,7 @@ hareSpec = do (Range (toPos (9,9)) (toPos (9,10)))] it "finds local definition of record variable" $ do let u = filePathToUri $ cwd "test/testdata/gototest/src/Lib.hs" - lreq = setTypecheckedModule u + lreq = runWithContext u $ setTypecheckedModule u req = liftToGhc $ TestDeferM $ findTypeDef u (toPos (11, 23)) r <- dispatchRequestPGoto $ lreq >> req r `shouldBe` IdeResultOk @@ -225,7 +226,7 @@ hareSpec = do ] it "finds local definition of newtype variable" $ do let u = filePathToUri $ cwd "test/testdata/gototest/src/Lib.hs" - lreq = setTypecheckedModule u + lreq = runWithContext u $ setTypecheckedModule u req = liftToGhc $ TestDeferM $ findTypeDef u (toPos (16, 21)) r <- dispatchRequestPGoto $ lreq >> req r `shouldBe` IdeResultOk @@ -235,7 +236,7 @@ hareSpec = do ] it "finds local definition of sum type variable" $ do let u = filePathToUri $ cwd "test/testdata/gototest/src/Lib.hs" - lreq = setTypecheckedModule u + lreq = runWithContext u $ setTypecheckedModule u req = liftToGhc $ TestDeferM $ findTypeDef u (toPos (21, 13)) r <- dispatchRequestPGoto $ lreq >> req r `shouldBe` IdeResultOk @@ -245,7 +246,7 @@ hareSpec = do ] it "finds local definition of sum type contructor" $ do let u = filePathToUri $ cwd "test/testdata/gototest/src/Lib.hs" - lreq = setTypecheckedModule u + lreq = runWithContext u $ setTypecheckedModule u req = liftToGhc $ TestDeferM $ findTypeDef u (toPos (24, 7)) r <- dispatchRequestPGoto $ lreq >> req r `shouldBe` IdeResultOk @@ -255,13 +256,13 @@ hareSpec = do ] it "can not find non-local definition of type def" $ do let u = filePathToUri $ cwd "test/testdata/gototest/src/Lib.hs" - lreq = setTypecheckedModule u + lreq = runWithContext u $ setTypecheckedModule u req = liftToGhc $ TestDeferM $ findTypeDef u (toPos (30, 17)) r <- dispatchRequestPGoto $ lreq >> req r `shouldBe` IdeResultOk [] it "find local definition of type def" $ do let u = filePathToUri $ cwd "test/testdata/gototest/src/Lib.hs" - lreq = setTypecheckedModule u + lreq = runWithContext u $ setTypecheckedModule u req = liftToGhc $ TestDeferM $ findTypeDef u (toPos (35, 16)) r <- dispatchRequestPGoto $ lreq >> req r `shouldBe` IdeResultOk @@ -272,9 +273,7 @@ hareSpec = do it "find type-definition of type def in component" $ do let fp = cwd "test/testdata/gototest/src/Lib2.hs" let u = filePathToUri $ fp - lreq = do - df <- getSessionDynFlags - runActionWithContext df (Just fp) $ setTypecheckedModule u + lreq = runWithContext u $ setTypecheckedModule u req = liftToGhc $ TestDeferM $ findTypeDef u (toPos (13, 20)) r <- dispatchRequestPGoto $ lreq >> req r `shouldBe` IdeResultOk @@ -284,7 +283,7 @@ hareSpec = do ] it "find definition of parameterized data type" $ do let u = filePathToUri $ cwd "test/testdata/gototest/src/Lib.hs" - lreq = setTypecheckedModule u + lreq = runWithContext u $ setTypecheckedModule u req = liftToGhc $ TestDeferM $ findTypeDef u (toPos (40, 19)) r <- dispatchRequestPGoto $ lreq >> req r `shouldBe` IdeResultOk From 94c3bcf789a2f7957f233e364f503f3fc78ab2d7 Mon Sep 17 00:00:00 2001 From: Zubin Duggal Date: Tue, 23 Jul 2019 15:25:41 +0530 Subject: [PATCH 156/158] Set defer type errors and report the resulting warnings as errors --- hie-bios | 2 +- hie-plugin-api/Haskell/Ide/Engine/Ghc.hs | 31 ++++++++++++++---------- src/Haskell/Ide/Engine/Plugin/Bios.hs | 15 ------------ 3 files changed, 19 insertions(+), 29 deletions(-) diff --git a/hie-bios b/hie-bios index e14cefa88..2b6228fea 160000 --- a/hie-bios +++ b/hie-bios @@ -1 +1 @@ -Subproject commit e14cefa883522c8e01022e2ebf48b4c4ca3ec0a5 +Subproject commit 2b6228fea7691cb25d1d6494fce77d95edc0b539 diff --git a/hie-plugin-api/Haskell/Ide/Engine/Ghc.hs b/hie-plugin-api/Haskell/Ide/Engine/Ghc.hs index 755a71b4b..0740dec6f 100644 --- a/hie-plugin-api/Haskell/Ide/Engine/Ghc.hs +++ b/hie-plugin-api/Haskell/Ide/Engine/Ghc.hs @@ -34,21 +34,20 @@ import Haskell.Ide.Engine.MonadTypes import Haskell.Ide.Engine.PluginUtils import DynFlags +import qualified EnumSet as ES import GHC import IOEnv as G import HscTypes import Outputable (renderWithStyle) import Language.Haskell.LSP.Types ( NormalizedUri(..), toNormalizedUri ) -import Data.Monoid ((<>)) - import Haskell.Ide.Engine.GhcUtils --import qualified Haskell.Ide.Engine.Plugin.HieExtras as Hie import Outputable hiding ((<>)) -- This function should be defined in HIE probably, nothing in particular -- to do with BIOS -import qualified HIE.Bios.GHCApi as BIOS (withDynFlags, CradleError) +import qualified HIE.Bios.GHCApi as BIOS (withDynFlags, CradleError,setDeferTypeErrors) import qualified HIE.Bios as BIOS import Debug.Trace @@ -79,12 +78,17 @@ type AdditionalErrs = [T.Text] -- --------------------------------------------------------------------- -lspSev :: Severity -> DiagnosticSeverity -lspSev SevWarning = DsWarning -lspSev SevError = DsError -lspSev SevFatal = DsError -lspSev SevInfo = DsInfo -lspSev _ = DsInfo +lspSev :: WarnReason -> Severity -> DiagnosticSeverity +lspSev (Reason r) _ + | r `elem` [ Opt_WarnDeferredTypeErrors + , Opt_WarnDeferredOutOfScopeVariables + ] + = DsError +lspSev _ SevWarning = DsWarning +lspSev _ SevError = DsError +lspSev _ SevFatal = DsError +lspSev _ SevInfo = DsInfo +lspSev _ _ = DsInfo -- --------------------------------------------------------------------- @@ -136,7 +140,7 @@ captureDiagnostics rfm action = do diagRef <- liftIO $ newIORef $ Diagnostics mempty errRef <- liftIO $ newIORef [] let setLogger df = df { log_action = logDiag rfm errRef diagRef } - setDeferTypedHoles = setGeneralFlag' Opt_DeferTypedHoles + unsetWErr df = unSetGeneralFlag' Opt_WarnIsError (df {fatalWarningFlags = ES.empty}) ghcErrRes msg = pure (mempty, [T.pack msg], Nothing) to_diag x = do @@ -148,7 +152,8 @@ captureDiagnostics rfm action = do handlers = errorHandlers ghcErrRes to_diag action' = do - r <- BIOS.withDynFlags (setLogger . setDeferTypedHoles) action + r <- BIOS.withDynFlags (setLogger . BIOS.setDeferTypeErrors . unsetWErr) $ + action diags <- liftIO $ readIORef diagRef errs <- liftIO $ readIORef errRef return (diags,errs, Just r) @@ -158,7 +163,7 @@ captureDiagnostics rfm action = do -- write anything to `stdout`. logDiag :: (FilePath -> FilePath) -> IORef AdditionalErrs -> IORef Diagnostics -> LogAction -- type LogAction = DynFlags -> WarnReason -> Severity -> SrcSpan -> PprStyle -> MsgDoc -> IO () -logDiag rfm eref dref df _reason sev spn style msg = do +logDiag rfm eref dref df reason sev spn style msg = do eloc <- srcSpan2Loc rfm spn traceShowM (spn, eloc) let msgTxt = T.pack $ renderWithStyle df msg style @@ -166,7 +171,7 @@ logDiag rfm eref dref df _reason sev spn style msg = do Right (Location uri range) -> do let update = Map.insertWith Set.union (toNormalizedUri uri) l where l = Set.singleton diag - diag = Diagnostic range (Just $ lspSev sev) Nothing (Just "bios") msgTxt Nothing + diag = Diagnostic range (Just $ lspSev reason sev) Nothing (Just "bios") msgTxt Nothing debugm $ "Writing diag" <> (show diag) modifyIORef' dref (\(Diagnostics u) -> Diagnostics (update u)) Left _ -> do diff --git a/src/Haskell/Ide/Engine/Plugin/Bios.hs b/src/Haskell/Ide/Engine/Plugin/Bios.hs index 9c61d6275..7d1efee13 100644 --- a/src/Haskell/Ide/Engine/Plugin/Bios.hs +++ b/src/Haskell/Ide/Engine/Plugin/Bios.hs @@ -7,16 +7,6 @@ {-# LANGUAGE TypeFamilies #-} module Haskell.Ide.Engine.Plugin.Bios(setTypecheckedModule, biosDescriptor) where -import Bag -import Control.Monad.IO.Class -import Data.IORef -import qualified Data.Map.Strict as Map -import Data.Monoid ((<>)) -import qualified Data.Set as Set -import qualified Data.Text as T -import ErrUtils -import System.FilePath - import Haskell.Ide.Engine.MonadFunctions import Haskell.Ide.Engine.MonadTypes import Haskell.Ide.Engine.PluginUtils @@ -28,11 +18,6 @@ import GHC import IOEnv as G import HscTypes import Outputable hiding ((<>)) --- This function should be defined in HIE probably, nothing in particular --- to do with BIOS -import qualified HIE.Bios.GHCApi as BIOS (withDynFlags, CradleError) -import qualified HIE.Bios as BIOS -import Debug.Trace import qualified HscMain as G import Haskell.Ide.Engine.Ghc From 092c7a2606c22a6fc2660e47307666f743c73cbd Mon Sep 17 00:00:00 2001 From: Zubin Duggal Date: Tue, 23 Jul 2019 15:58:41 +0530 Subject: [PATCH 157/158] Fix most code action tests --- src/Haskell/Ide/Engine/Plugin/HsImport.hs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Haskell/Ide/Engine/Plugin/HsImport.hs b/src/Haskell/Ide/Engine/Plugin/HsImport.hs index e3114a13b..2172a9b60 100644 --- a/src/Haskell/Ide/Engine/Plugin/HsImport.hs +++ b/src/Haskell/Ide/Engine/Plugin/HsImport.hs @@ -127,10 +127,8 @@ importModule importModule uri impStyle modName = pluginGetFile "hsimport cmd: " uri $ \origInput -> do shouldFormat <- formatOnImportOn <$> getConfig - fileMap <- reverseFileMap - let input = origInput - do + withMappedFile origInput $ \input -> do tmpDir <- liftIO getTemporaryDirectory (output, outputH) <- liftIO $ openTempFile tmpDir "hsimportOutput" liftIO $ hClose outputH From 805961d829a88c9daf290a2c36e21ff737808e26 Mon Sep 17 00:00:00 2001 From: Zubin Duggal Date: Tue, 23 Jul 2019 16:15:21 +0530 Subject: [PATCH 158/158] Fix another code action test --- test/functional/FunctionalCodeActionsSpec.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/functional/FunctionalCodeActionsSpec.hs b/test/functional/FunctionalCodeActionsSpec.hs index a042af32c..85d40bac9 100644 --- a/test/functional/FunctionalCodeActionsSpec.hs +++ b/test/functional/FunctionalCodeActionsSpec.hs @@ -331,7 +331,7 @@ spec = describe "code actions" $ do GHC86 -> do liftIO $ map (^. L.title) cas `shouldMatchList` [ "Substitute hole (Int) with x ([Int])" - , "Substitute hole (Int) with foo ([Int] -> Int Valid hole fits include)" + , "Substitute hole (Int) with foo ([Int] -> Int)" , "Substitute hole (Int) with maxBound (forall a. Bounded a => a with maxBound @Int)" , "Substitute hole (Int) with minBound (forall a. Bounded a => a with minBound @Int)" ]