diff --git a/src/Ide/Plugin/Eval.hs b/src/Ide/Plugin/Eval.hs index a14d14393a..1d1372deda 100644 --- a/src/Ide/Plugin/Eval.hs +++ b/src/Ide/Plugin/Eval.hs @@ -63,7 +63,7 @@ import GHC (DynFlags, ExecResult (..), Gene setInteractiveDynFlags, setLogAction, setSessionDynFlags, setTargets, - simpleImportDecl, ways) + simpleImportDecl, typeKind, ways) import GHC.Generics (Generic) import GhcMonad (modifySession) import GhcPlugins (defaultLogActionHPutStrDoc, @@ -86,6 +86,8 @@ import qualified Control.Exception as E import Control.DeepSeq ( NFData , deepseq ) +import Outputable (Outputable(ppr), showSDoc) +import Control.Applicative ((<|>)) descriptor :: PluginId -> PluginDescriptor descriptor plId = @@ -245,6 +247,18 @@ done, we want to switch back to GhcSessionDeps: df <- liftIO $ evalGhcEnv hscEnv' getSessionDynFlags let eval (stmt, l) + | let stmt0 = T.strip $ T.pack stmt -- For stripping and de-prefixing + , Just (reduce, type_) <- + (True,) <$> T.stripPrefix ":kind! " stmt0 + <|> (False,) <$> T.stripPrefix ":kind " stmt0 + = do + let input = T.strip type_ + (ty, kind) <- typeKind reduce $ T.unpack input + pure $ Just + $ T.unlines + $ map ("-- " <>) + $ (input <> " :: " <> T.pack (showSDoc df $ ppr kind)) + : [ "= " <> T.pack (showSDoc df $ ppr ty) | reduce] | isStmt df stmt = do -- set up a custom interactive print function liftIO $ writeFile temp "" diff --git a/test/functional/Eval.hs b/test/functional/Eval.hs index 3af6c9d83a..0f99057867 100644 --- a/test/functional/Eval.hs +++ b/test/functional/Eval.hs @@ -64,6 +64,12 @@ tests = testGroup , testCase "Refresh a multiline evaluation" $ goldenTest "T7.hs" , testCase "Evaluate incorrect expressions" $ goldenTest "T8.hs" , testCase "Applies file LANGUAGE extensions" $ goldenTest "T9.hs" + , testCase "Evaluate a type with :kind!" $ goldenTest "T10.hs" + , testCase "Reports an error for an incorrect type with :kind!" + $ goldenTest "T11.hs" + , testCase "Shows a kind with :kind" $ goldenTest "T12.hs" + , testCase "Reports an error for an incorrect type with :kind" + $ goldenTest "T13.hs" ] goldenTest :: FilePath -> IO () diff --git a/test/testdata/eval/T10.hs b/test/testdata/eval/T10.hs new file mode 100644 index 0000000000..e29c75876e --- /dev/null +++ b/test/testdata/eval/T10.hs @@ -0,0 +1,9 @@ +{-# LANGUAGE DataKinds, TypeOperators #-} +module T10 where +import GHC.TypeNats ( type (+) ) + +type Dummy = 1 + 1 + +-- >>> type N = 1 +-- >>> type M = 40 +-- >>> :kind! N + M + 1 diff --git a/test/testdata/eval/T10.hs.expected b/test/testdata/eval/T10.hs.expected new file mode 100644 index 0000000000..2c50750981 --- /dev/null +++ b/test/testdata/eval/T10.hs.expected @@ -0,0 +1,11 @@ +{-# LANGUAGE DataKinds, TypeOperators #-} +module T10 where +import GHC.TypeNats ( type (+) ) + +type Dummy = 1 + 1 + +-- >>> type N = 1 +-- >>> type M = 40 +-- >>> :kind! N + M + 1 +-- N + M + 1 :: Nat +-- = 42 diff --git a/test/testdata/eval/T11.hs b/test/testdata/eval/T11.hs new file mode 100644 index 0000000000..724100f3a6 --- /dev/null +++ b/test/testdata/eval/T11.hs @@ -0,0 +1,3 @@ +module T11 where + +-- >>> :kind! a diff --git a/test/testdata/eval/T11.hs.expected b/test/testdata/eval/T11.hs.expected new file mode 100644 index 0000000000..fac41da1cd --- /dev/null +++ b/test/testdata/eval/T11.hs.expected @@ -0,0 +1,4 @@ +module T11 where + +-- >>> :kind! a +-- Not in scope: type variable ‘a’ diff --git a/test/testdata/eval/T12.hs b/test/testdata/eval/T12.hs new file mode 100644 index 0000000000..8a2d269165 --- /dev/null +++ b/test/testdata/eval/T12.hs @@ -0,0 +1,9 @@ +{-# LANGUAGE DataKinds, TypeOperators #-} +module T12 where +import GHC.TypeNats ( type (+) ) + +type Dummy = 1 + 1 + +-- >>> type N = 1 +-- >>> type M = 40 +-- >>> :kind N + M + 1 diff --git a/test/testdata/eval/T12.hs.expected b/test/testdata/eval/T12.hs.expected new file mode 100644 index 0000000000..81bf5c30c2 --- /dev/null +++ b/test/testdata/eval/T12.hs.expected @@ -0,0 +1,10 @@ +{-# LANGUAGE DataKinds, TypeOperators #-} +module T12 where +import GHC.TypeNats ( type (+) ) + +type Dummy = 1 + 1 + +-- >>> type N = 1 +-- >>> type M = 40 +-- >>> :kind N + M + 1 +-- N + M + 1 :: Nat diff --git a/test/testdata/eval/T13.hs b/test/testdata/eval/T13.hs new file mode 100644 index 0000000000..f8512aae2d --- /dev/null +++ b/test/testdata/eval/T13.hs @@ -0,0 +1,3 @@ +module T13 where + +-- >>> :kind a diff --git a/test/testdata/eval/T13.hs.expected b/test/testdata/eval/T13.hs.expected new file mode 100644 index 0000000000..c76a2af295 --- /dev/null +++ b/test/testdata/eval/T13.hs.expected @@ -0,0 +1,4 @@ +module T13 where + +-- >>> :kind a +-- Not in scope: type variable ‘a’ diff --git a/test/testdata/eval/T9.hs b/test/testdata/eval/T9.hs index bc83803bb3..9926ad836e 100644 --- a/test/testdata/eval/T9.hs +++ b/test/testdata/eval/T9.hs @@ -1,5 +1,7 @@ {-# LANGUAGE DataKinds #-} module T9 where -import Data.Proxy +import Data.Proxy (Proxy(..)) + +type P = Proxy -- >>> Proxy :: Proxy 3 diff --git a/test/testdata/eval/T9.hs.expected b/test/testdata/eval/T9.hs.expected index 4ea9e33218..bc09993826 100644 --- a/test/testdata/eval/T9.hs.expected +++ b/test/testdata/eval/T9.hs.expected @@ -1,6 +1,8 @@ {-# LANGUAGE DataKinds #-} module T9 where -import Data.Proxy +import Data.Proxy (Proxy(..)) + +type P = Proxy -- >>> Proxy :: Proxy 3 -- Proxy