{-# LANGUAGE CPP #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE ExtendedDefaultRules #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ViewPatterns #-}
{-# OPTIONS_GHC -fno-warn-type-defaults -Wno-unused-imports #-}
module Ide.Plugin.Eval.CodeLens (
codeLens,
evalCommand,
) where
import Control.Applicative (Alternative ((<|>)))
import Control.Arrow (second, (>>>))
import Control.Exception (bracket_, try)
import qualified Control.Exception as E
import Control.Lens (_1, _3, ix, (%~),
(<&>), (^.))
import Control.Monad (guard, void,
when)
import Control.Monad.IO.Class (MonadIO (liftIO))
import Control.Monad.Trans.Except (ExceptT (..),
runExceptT)
import Data.Aeson (toJSON)
import Data.Char (isSpace)
import Data.Foldable (toList)
import Data.List (dropWhileEnd,
find,
intercalate,
intersperse)
import qualified Data.Map as Map
import Data.Maybe (catMaybes)
import Data.String (IsString)
import Data.Text (Text)
import qualified Data.Text as T
import Data.Typeable (Typeable)
import Development.IDE.Core.Rules (IdeState,
runAction)
import Development.IDE.Core.RuleTypes (LinkableResult (linkableHomeMod),
NeedsCompilation (NeedsCompilation),
TypeCheck (..),
tmrTypechecked)
import Development.IDE.Core.Shake (useNoFile_,
useWithStale_,
use_, uses_)
import Development.IDE.GHC.Compat hiding (typeKind,
unitState)
import Development.IDE.GHC.Compat.Util (GhcException,
OverridingBool (..),
bagToList)
import Development.IDE.GHC.Util (evalGhcEnv,
modifyDynFlags,
printOutputable)
import Development.IDE.Import.DependencyInformation (transitiveDeps,
transitiveModuleDeps)
import Development.IDE.Types.Location (toNormalizedFilePath',
uriToFilePath')
import GHC (ClsInst,
ExecOptions (execLineNumber, execSourceFile),
FamInst,
GhcMonad,
NamedThing (getName),
defaultFixity,
execOptions,
exprType,
getInfo,
getInteractiveDynFlags,
isImport, isStmt,
parseName,
pprFamInst,
pprInstance,
typeKind)
import Development.IDE.Core.RuleTypes (GetLinkable (GetLinkable),
GetModSummary (GetModSummary),
GetModuleGraph (GetModuleGraph),
GhcSessionDeps (GhcSessionDeps),
ModSummaryResult (msrModSummary))
import Development.IDE.Core.Shake (VFSModified (VFSUnmodified))
import qualified Development.IDE.GHC.Compat.Core as Compat (InteractiveImport (IIModule))
import qualified Development.IDE.GHC.Compat.Core as SrcLoc (HasSrcSpan (getLoc),
unLoc)
import Development.IDE.Types.HscEnvEq (HscEnvEq (hscEnv))
import qualified GHC.LanguageExtensions.Type as LangExt (Extension (..))
import Development.IDE.Core.FileStore (setSomethingModified)
import Development.IDE.Core.PluginUtils
import Development.IDE.Types.Shake (toKey)
import GHC.Types.SrcLoc (UnhelpfulSpanReason (UnhelpfulInteractive))
import Ide.Plugin.Error (PluginError (PluginInternalError),
handleMaybe,
handleMaybeM)
import Ide.Plugin.Eval.Code (Statement,
asStatements,
myExecStmt,
propSetup,
resultRange,
testCheck,
testRanges)
import Ide.Plugin.Eval.Config (EvalConfig (..),
getEvalConfig)
import Ide.Plugin.Eval.GHC (addImport,
addPackages,
hasPackage,
setSessionAndInteractiveDynFlags,
showDynFlags)
import Ide.Plugin.Eval.Parse.Comments (commentsToSections)
import Ide.Plugin.Eval.Parse.Option (parseSetFlags)
import Ide.Plugin.Eval.Rules (queueForEvaluation,
unqueueForEvaluation)
import Ide.Plugin.Eval.Types
import Ide.Plugin.Eval.Util (gStrictTry,
isLiterate,
logWith,
response', timed)
import Ide.Types
import qualified Language.LSP.Protocol.Lens as L
import Language.LSP.Protocol.Message
import Language.LSP.Protocol.Types
import Language.LSP.Server
import Language.LSP.VFS (virtualFileText)
codeLens :: PluginMethodHandler IdeState Method_TextDocumentCodeLens
codeLens :: PluginMethodHandler IdeState 'Method_TextDocumentCodeLens
codeLens IdeState
st PluginId
plId CodeLensParams{TextDocumentIdentifier
_textDocument :: TextDocumentIdentifier
$sel:_textDocument:CodeLensParams :: CodeLensParams -> TextDocumentIdentifier
_textDocument} =
let dbg :: a1 -> a2 -> m ()
dbg = IdeState -> a1 -> a2 -> m ()
forall (m :: * -> *) a1 a2.
(HasCallStack, MonadIO m, Show a1, Show a2) =>
IdeState -> a1 -> a2 -> m ()
logWith IdeState
st
perf :: t -> m b -> m b
perf = (t -> String -> m ()) -> t -> m b -> m b
forall (m :: * -> *) t a b.
MonadIO m =>
(t -> String -> m a) -> t -> m b -> m b
timed t -> String -> m ()
forall {m :: * -> *} {a1} {a2}.
(MonadIO m, Show a1, Show a2) =>
a1 -> a2 -> m ()
dbg
in String
-> ExceptT
PluginError
(LspM Config)
(MessageResult 'Method_TextDocumentCodeLens)
-> ExceptT
PluginError
(LspM Config)
(MessageResult 'Method_TextDocumentCodeLens)
forall {m :: * -> *} {t} {b}.
(MonadIO m, Show t) =>
t -> m b -> m b
perf String
"codeLens" (ExceptT
PluginError
(LspM Config)
(MessageResult 'Method_TextDocumentCodeLens)
-> ExceptT
PluginError
(LspM Config)
(MessageResult 'Method_TextDocumentCodeLens))
-> ExceptT
PluginError
(LspM Config)
(MessageResult 'Method_TextDocumentCodeLens)
-> ExceptT
PluginError
(LspM Config)
(MessageResult 'Method_TextDocumentCodeLens)
forall a b. (a -> b) -> a -> b
$
do
let TextDocumentIdentifier Uri
uri = TextDocumentIdentifier
_textDocument
String
fp <- Uri -> ExceptT PluginError (LspM Config) String
forall (m :: * -> *).
Monad m =>
Uri -> ExceptT PluginError m String
uriToFilePathE Uri
uri
let nfp :: NormalizedFilePath
nfp = String -> NormalizedFilePath
toNormalizedFilePath' String
fp
isLHS :: Bool
isLHS = String -> Bool
isLiterate String
fp
String -> String -> ExceptT PluginError (LspM Config) ()
forall {m :: * -> *} {a1} {a2}.
(MonadIO m, Show a1, Show a2) =>
a1 -> a2 -> m ()
dbg String
"fp" String
fp
(Comments
comments, PositionMapping
_) <-
String
-> IdeState
-> ExceptT PluginError Action (Comments, PositionMapping)
-> ExceptT PluginError (LspM Config) (Comments, PositionMapping)
forall (m :: * -> *) e a.
MonadIO m =>
String -> IdeState -> ExceptT e Action a -> ExceptT e m a
runActionE String
"eval.GetParsedModuleWithComments" IdeState
st (ExceptT PluginError Action (Comments, PositionMapping)
-> ExceptT PluginError (LspM Config) (Comments, PositionMapping))
-> ExceptT PluginError Action (Comments, PositionMapping)
-> ExceptT PluginError (LspM Config) (Comments, PositionMapping)
forall a b. (a -> b) -> a -> b
$ GetEvalComments
-> NormalizedFilePath
-> ExceptT PluginError Action (Comments, PositionMapping)
forall k v.
IdeRule k v =>
k
-> NormalizedFilePath
-> ExceptT PluginError Action (v, PositionMapping)
useWithStaleE GetEvalComments
GetEvalComments NormalizedFilePath
nfp
String -> String -> ExceptT PluginError (LspM Config) ()
forall {m :: * -> *} {a1} {a2}.
(MonadIO m, Show a1, Show a2) =>
a1 -> a2 -> m ()
dbg String
"comments" (String -> ExceptT PluginError (LspM Config) ())
-> String -> ExceptT PluginError (LspM Config) ()
forall a b. (a -> b) -> a -> b
$ Comments -> String
forall a. Show a => a -> String
show Comments
comments
let Sections{[Section]
nonSetupSections :: [Section]
setupSections :: [Section]
nonSetupSections :: Sections -> [Section]
setupSections :: Sections -> [Section]
..} = Bool -> Comments -> Sections
commentsToSections Bool
isLHS Comments
comments
tests :: [(Section, Int, Test)]
tests = [Section] -> [(Section, Int, Test)]
testsBySection [Section]
nonSetupSections
cmd :: Command
cmd = PluginId -> CommandId -> Text -> Maybe [Value] -> Command
mkLspCommand PluginId
plId CommandId
evalCommandName Text
"Evaluate=..." ([Value] -> Maybe [Value]
forall a. a -> Maybe a
Just [])
let lenses :: [CodeLens]
lenses =
[ Range -> Maybe Command -> Maybe Value -> CodeLens
CodeLens Range
testRange (Command -> Maybe Command
forall a. a -> Maybe a
Just Command
cmd') Maybe Value
forall a. Maybe a
Nothing
| (Section
section, Int
ident, Test
test) <- [(Section, Int, Test)]
tests
, let (Range
testRange, Range
resultRange) = Test -> (Range, Range)
testRanges Test
test
args :: EvalParams
args = [Section] -> TextDocumentIdentifier -> Int -> EvalParams
EvalParams ([Section]
setupSections [Section] -> [Section] -> [Section]
forall a. [a] -> [a] -> [a]
++ [Section
section]) TextDocumentIdentifier
_textDocument Int
ident
cmd' :: Command
cmd' =
(Command
cmd :: Command)
{ _arguments = Just [toJSON args]
, _title =
if trivial resultRange
then "Evaluate..."
else "Refresh..."
}
]
String
-> ExceptT PluginError (LspM Config) ()
-> ExceptT PluginError (LspM Config) ()
forall {m :: * -> *} {t} {b}.
(MonadIO m, Show t) =>
t -> m b -> m b
perf String
"tests" (ExceptT PluginError (LspM Config) ()
-> ExceptT PluginError (LspM Config) ())
-> ExceptT PluginError (LspM Config) ()
-> ExceptT PluginError (LspM Config) ()
forall a b. (a -> b) -> a -> b
$
String -> String -> ExceptT PluginError (LspM Config) ()
forall {m :: * -> *} {a1} {a2}.
(MonadIO m, Show a1, Show a2) =>
a1 -> a2 -> m ()
dbg String
"Tests" (String -> ExceptT PluginError (LspM Config) ())
-> String -> ExceptT PluginError (LspM Config) ()
forall a b. (a -> b) -> a -> b
$
[String] -> String
unwords
[ Int -> String
forall a. Show a => a -> String
show ([(Section, Int, Test)] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(Section, Int, Test)]
tests)
, String
"tests in"
, Int -> String
forall a. Show a => a -> String
show ([Section] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Section]
nonSetupSections)
, String
"sections"
, Int -> String
forall a. Show a => a -> String
show ([Section] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Section]
setupSections)
, String
"setups"
, Int -> String
forall a. Show a => a -> String
show ([CodeLens] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [CodeLens]
lenses)
, String
"lenses."
]
([CodeLens] |? Null)
-> ExceptT PluginError (LspM Config) ([CodeLens] |? Null)
forall a. a -> ExceptT PluginError (LspM Config) a
forall (m :: * -> *) a. Monad m => a -> m a
return (([CodeLens] |? Null)
-> ExceptT PluginError (LspM Config) ([CodeLens] |? Null))
-> ([CodeLens] |? Null)
-> ExceptT PluginError (LspM Config) ([CodeLens] |? Null)
forall a b. (a -> b) -> a -> b
$ [CodeLens] -> [CodeLens] |? Null
forall a b. a -> a |? b
InL [CodeLens]
lenses
where
trivial :: Range -> Bool
trivial (Range Position
p Position
p') = Position
p Position -> Position -> Bool
forall a. Eq a => a -> a -> Bool
== Position
p'
evalCommandName :: CommandId
evalCommandName :: CommandId
evalCommandName = CommandId
"evalCommand"
evalCommand :: PluginId -> PluginCommand IdeState
evalCommand :: PluginId -> PluginCommand IdeState
evalCommand PluginId
plId = CommandId
-> Text
-> CommandFunction IdeState EvalParams
-> PluginCommand IdeState
forall ideState a.
FromJSON a =>
CommandId
-> Text -> CommandFunction ideState a -> PluginCommand ideState
PluginCommand CommandId
evalCommandName Text
"evaluate" (PluginId -> CommandFunction IdeState EvalParams
runEvalCmd PluginId
plId)
type EvalId = Int
runEvalCmd :: PluginId -> CommandFunction IdeState EvalParams
runEvalCmd :: PluginId -> CommandFunction IdeState EvalParams
runEvalCmd PluginId
plId IdeState
st Maybe ProgressToken
mtoken EvalParams{Int
[Section]
TextDocumentIdentifier
sections :: [Section]
module_ :: TextDocumentIdentifier
evalId :: Int
sections :: EvalParams -> [Section]
module_ :: EvalParams -> TextDocumentIdentifier
evalId :: EvalParams -> Int
..} =
let dbg :: a1 -> a2 -> m ()
dbg = IdeState -> a1 -> a2 -> m ()
forall (m :: * -> *) a1 a2.
(HasCallStack, MonadIO m, Show a1, Show a2) =>
IdeState -> a1 -> a2 -> m ()
logWith IdeState
st
perf :: t -> m b -> m b
perf = (t -> String -> m ()) -> t -> m b -> m b
forall (m :: * -> *) t a b.
MonadIO m =>
(t -> String -> m a) -> t -> m b -> m b
timed t -> String -> m ()
forall {m :: * -> *} {a1} {a2}.
(MonadIO m, Show a1, Show a2) =>
a1 -> a2 -> m ()
dbg
cmd :: ExceptT PluginError (LspM Config) WorkspaceEdit
cmd :: ExceptT PluginError (LspM Config) WorkspaceEdit
cmd = do
let tests :: [(Section, Test)]
tests = ((Section, Int, Test) -> (Section, Test))
-> [(Section, Int, Test)] -> [(Section, Test)]
forall a b. (a -> b) -> [a] -> [b]
map (\(Section
a,Int
_,Test
b) -> (Section
a,Test
b)) ([(Section, Int, Test)] -> [(Section, Test)])
-> [(Section, Int, Test)] -> [(Section, Test)]
forall a b. (a -> b) -> a -> b
$ [Section] -> [(Section, Int, Test)]
testsBySection [Section]
sections
let TextDocumentIdentifier{Uri
_uri :: Uri
$sel:_uri:TextDocumentIdentifier :: TextDocumentIdentifier -> Uri
_uri} = TextDocumentIdentifier
module_
String
fp <- Uri -> ExceptT PluginError (LspM Config) String
forall (m :: * -> *).
Monad m =>
Uri -> ExceptT PluginError m String
uriToFilePathE Uri
_uri
let nfp :: NormalizedFilePath
nfp = String -> NormalizedFilePath
toNormalizedFilePath' String
fp
Text
mdlText <- Uri -> ExceptT PluginError (LspM Config) Text
forall c (m :: * -> *).
MonadLsp c m =>
Uri -> ExceptT PluginError m Text
moduleText Uri
_uri
HscEnv
final_hscEnv <- IO HscEnv -> ExceptT PluginError (LspM Config) HscEnv
forall a. IO a -> ExceptT PluginError (LspM Config) a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO HscEnv -> ExceptT PluginError (LspM Config) HscEnv)
-> IO HscEnv -> ExceptT PluginError (LspM Config) HscEnv
forall a b. (a -> b) -> a -> b
$ IO () -> IO () -> IO HscEnv -> IO HscEnv
forall a b c. IO a -> IO b -> IO c -> IO c
bracket_
(do IdeState -> NormalizedFilePath -> IO ()
queueForEvaluation IdeState
st NormalizedFilePath
nfp
VFSModified -> IdeState -> [Key] -> String -> IO ()
setSomethingModified VFSModified
VFSUnmodified IdeState
st [IsEvaluating -> NormalizedFilePath -> Key
forall k. ShakeValue k => k -> NormalizedFilePath -> Key
toKey IsEvaluating
IsEvaluating NormalizedFilePath
nfp] String
"Eval")
(do IdeState -> NormalizedFilePath -> IO ()
unqueueForEvaluation IdeState
st NormalizedFilePath
nfp
VFSModified -> IdeState -> [Key] -> String -> IO ()
setSomethingModified VFSModified
VFSUnmodified IdeState
st [IsEvaluating -> NormalizedFilePath -> Key
forall k. ShakeValue k => k -> NormalizedFilePath -> Key
toKey IsEvaluating
IsEvaluating NormalizedFilePath
nfp] String
"Eval")
(Bool -> IdeState -> NormalizedFilePath -> IO HscEnv
initialiseSessionForEval ([(Section, Test)] -> Bool
needsQuickCheck [(Section, Test)]
tests) IdeState
st NormalizedFilePath
nfp)
EvalConfig
evalCfg <- IO EvalConfig -> ExceptT PluginError (LspM Config) EvalConfig
forall a. IO a -> ExceptT PluginError (LspM Config) a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO EvalConfig -> ExceptT PluginError (LspM Config) EvalConfig)
-> IO EvalConfig -> ExceptT PluginError (LspM Config) EvalConfig
forall a b. (a -> b) -> a -> b
$ String -> IdeState -> Action EvalConfig -> IO EvalConfig
forall a. String -> IdeState -> Action a -> IO a
runAction String
"eval: config" IdeState
st (Action EvalConfig -> IO EvalConfig)
-> Action EvalConfig -> IO EvalConfig
forall a b. (a -> b) -> a -> b
$ PluginId -> Action EvalConfig
getEvalConfig PluginId
plId
[TextEdit]
edits <-
String
-> ExceptT PluginError (LspM Config) [TextEdit]
-> ExceptT PluginError (LspM Config) [TextEdit]
forall {m :: * -> *} {t} {b}.
(MonadIO m, Show t) =>
t -> m b -> m b
perf String
"edits" (ExceptT PluginError (LspM Config) [TextEdit]
-> ExceptT PluginError (LspM Config) [TextEdit])
-> ExceptT PluginError (LspM Config) [TextEdit]
-> ExceptT PluginError (LspM Config) [TextEdit]
forall a b. (a -> b) -> a -> b
$
IO [TextEdit] -> ExceptT PluginError (LspM Config) [TextEdit]
forall a. IO a -> ExceptT PluginError (LspM Config) a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO [TextEdit] -> ExceptT PluginError (LspM Config) [TextEdit])
-> IO [TextEdit] -> ExceptT PluginError (LspM Config) [TextEdit]
forall a b. (a -> b) -> a -> b
$
HscEnv -> Ghc [TextEdit] -> IO [TextEdit]
forall b. HscEnv -> Ghc b -> IO b
evalGhcEnv HscEnv
final_hscEnv (Ghc [TextEdit] -> IO [TextEdit])
-> Ghc [TextEdit] -> IO [TextEdit]
forall a b. (a -> b) -> a -> b
$ do
EvalConfig -> TEnv -> [(Section, Test)] -> Ghc [TextEdit]
runTests EvalConfig
evalCfg (IdeState
st, String
fp) [(Section, Test)]
tests
let workspaceEditsMap :: Map Uri [TextEdit]
workspaceEditsMap = [(Uri, [TextEdit])] -> Map Uri [TextEdit]
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList [(Uri
_uri, Text -> [TextEdit] -> [TextEdit]
addFinalReturn Text
mdlText [TextEdit]
edits)]
let workspaceEdits :: WorkspaceEdit
workspaceEdits = Maybe (Map Uri [TextEdit])
-> Maybe
[TextDocumentEdit |? (CreateFile |? (RenameFile |? DeleteFile))]
-> Maybe (Map ChangeAnnotationIdentifier ChangeAnnotation)
-> WorkspaceEdit
WorkspaceEdit (Map Uri [TextEdit] -> Maybe (Map Uri [TextEdit])
forall a. a -> Maybe a
Just Map Uri [TextEdit]
workspaceEditsMap) Maybe
[TextDocumentEdit |? (CreateFile |? (RenameFile |? DeleteFile))]
forall a. Maybe a
Nothing Maybe (Map ChangeAnnotationIdentifier ChangeAnnotation)
forall a. Maybe a
Nothing
WorkspaceEdit -> ExceptT PluginError (LspM Config) WorkspaceEdit
forall a. a -> ExceptT PluginError (LspM Config) a
forall (m :: * -> *) a. Monad m => a -> m a
return WorkspaceEdit
workspaceEdits
in String
-> ExceptT PluginError (LspM Config) (Value |? Null)
-> ExceptT PluginError (LspM Config) (Value |? Null)
forall {m :: * -> *} {t} {b}.
(MonadIO m, Show t) =>
t -> m b -> m b
perf String
"evalCmd" (ExceptT PluginError (LspM Config) (Value |? Null)
-> ExceptT PluginError (LspM Config) (Value |? Null))
-> ExceptT PluginError (LspM Config) (Value |? Null)
-> ExceptT PluginError (LspM Config) (Value |? Null)
forall a b. (a -> b) -> a -> b
$ LspM Config (Either PluginError (Value |? Null))
-> ExceptT PluginError (LspM Config) (Value |? Null)
forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT (LspM Config (Either PluginError (Value |? Null))
-> ExceptT PluginError (LspM Config) (Value |? Null))
-> LspM Config (Either PluginError (Value |? Null))
-> ExceptT PluginError (LspM Config) (Value |? Null)
forall a b. (a -> b) -> a -> b
$
Text
-> Maybe ProgressToken
-> ProgressCancellable
-> ((Text -> LspT Config IO ())
-> LspM Config (Either PluginError (Value |? Null)))
-> LspM Config (Either PluginError (Value |? Null))
forall c (m :: * -> *) a.
MonadLsp c m =>
Text
-> Maybe ProgressToken
-> ProgressCancellable
-> ((Text -> m ()) -> m a)
-> m a
withIndefiniteProgress Text
"Evaluating" Maybe ProgressToken
mtoken ProgressCancellable
Cancellable (((Text -> LspT Config IO ())
-> LspM Config (Either PluginError (Value |? Null)))
-> LspM Config (Either PluginError (Value |? Null)))
-> ((Text -> LspT Config IO ())
-> LspM Config (Either PluginError (Value |? Null)))
-> LspM Config (Either PluginError (Value |? Null))
forall a b. (a -> b) -> a -> b
$ \Text -> LspT Config IO ()
_updater ->
ExceptT PluginError (LspM Config) (Value |? Null)
-> LspM Config (Either PluginError (Value |? Null))
forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT (ExceptT PluginError (LspM Config) (Value |? Null)
-> LspM Config (Either PluginError (Value |? Null)))
-> ExceptT PluginError (LspM Config) (Value |? Null)
-> LspM Config (Either PluginError (Value |? Null))
forall a b. (a -> b) -> a -> b
$ ExceptT PluginError (LspM Config) WorkspaceEdit
-> ExceptT PluginError (LspM Config) (Value |? Null)
forall c.
ExceptT PluginError (LspM c) WorkspaceEdit
-> ExceptT PluginError (LspM c) (Value |? Null)
response' ExceptT PluginError (LspM Config) WorkspaceEdit
cmd
initialiseSessionForEval :: Bool -> IdeState -> NormalizedFilePath -> IO HscEnv
initialiseSessionForEval :: Bool -> IdeState -> NormalizedFilePath -> IO HscEnv
initialiseSessionForEval Bool
needs_quickcheck IdeState
st NormalizedFilePath
nfp = do
(ModSummary
ms, HscEnv
env1) <- String
-> IdeState
-> Action (ModSummary, HscEnv)
-> IO (ModSummary, HscEnv)
forall a. String -> IdeState -> Action a -> IO a
runAction String
"runEvalCmd" IdeState
st (Action (ModSummary, HscEnv) -> IO (ModSummary, HscEnv))
-> Action (ModSummary, HscEnv) -> IO (ModSummary, HscEnv)
forall a b. (a -> b) -> a -> b
$ do
ModSummary
ms <- ModSummaryResult -> ModSummary
msrModSummary (ModSummaryResult -> ModSummary)
-> Action ModSummaryResult -> Action ModSummary
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GetModSummary -> NormalizedFilePath -> Action ModSummaryResult
forall k v. IdeRule k v => k -> NormalizedFilePath -> Action v
use_ GetModSummary
GetModSummary NormalizedFilePath
nfp
HscEnv
deps_hsc <- HscEnvEq -> HscEnv
hscEnv (HscEnvEq -> HscEnv) -> Action HscEnvEq -> Action HscEnv
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GhcSessionDeps -> NormalizedFilePath -> Action HscEnvEq
forall k v. IdeRule k v => k -> NormalizedFilePath -> Action v
use_ GhcSessionDeps
GhcSessionDeps NormalizedFilePath
nfp
Maybe TransitiveDependencies
linkables_needed <- DependencyInformation
-> NormalizedFilePath -> Maybe TransitiveDependencies
transitiveDeps (DependencyInformation
-> NormalizedFilePath -> Maybe TransitiveDependencies)
-> Action DependencyInformation
-> Action (NormalizedFilePath -> Maybe TransitiveDependencies)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GetModuleGraph -> Action DependencyInformation
forall k v. IdeRule k v => k -> Action v
useNoFile_ GetModuleGraph
GetModuleGraph Action (NormalizedFilePath -> Maybe TransitiveDependencies)
-> Action NormalizedFilePath
-> Action (Maybe TransitiveDependencies)
forall a b. Action (a -> b) -> Action a -> Action b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> NormalizedFilePath -> Action NormalizedFilePath
forall a. a -> Action a
forall (f :: * -> *) a. Applicative f => a -> f a
pure NormalizedFilePath
nfp
[LinkableResult]
linkables <- GetLinkable -> [NormalizedFilePath] -> Action [LinkableResult]
forall (f :: * -> *) k v.
(Traversable f, IdeRule k v) =>
k -> f NormalizedFilePath -> Action (f v)
uses_ GetLinkable
GetLinkable (NormalizedFilePath
nfp NormalizedFilePath -> [NormalizedFilePath] -> [NormalizedFilePath]
forall a. a -> [a] -> [a]
: [NormalizedFilePath]
-> (TransitiveDependencies -> [NormalizedFilePath])
-> Maybe TransitiveDependencies
-> [NormalizedFilePath]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] TransitiveDependencies -> [NormalizedFilePath]
transitiveModuleDeps Maybe TransitiveDependencies
linkables_needed)
GlobalRdrEnv
rdr_env <- TcGblEnv -> GlobalRdrEnv
tcg_rdr_env (TcGblEnv -> GlobalRdrEnv)
-> (TcModuleResult -> TcGblEnv) -> TcModuleResult -> GlobalRdrEnv
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TcModuleResult -> TcGblEnv
tmrTypechecked (TcModuleResult -> GlobalRdrEnv)
-> Action TcModuleResult -> Action GlobalRdrEnv
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TypeCheck -> NormalizedFilePath -> Action TcModuleResult
forall k v. IdeRule k v => k -> NormalizedFilePath -> Action v
use_ TypeCheck
TypeCheck NormalizedFilePath
nfp
let linkable_hsc :: HscEnv
linkable_hsc = [HomeModInfo] -> HscEnv -> HscEnv
loadModulesHome ((LinkableResult -> HomeModInfo)
-> [LinkableResult] -> [HomeModInfo]
forall a b. (a -> b) -> [a] -> [b]
map (HomeModInfo -> HomeModInfo
addRdrEnv (HomeModInfo -> HomeModInfo)
-> (LinkableResult -> HomeModInfo) -> LinkableResult -> HomeModInfo
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LinkableResult -> HomeModInfo
linkableHomeMod) [LinkableResult]
linkables) HscEnv
deps_hsc
addRdrEnv :: HomeModInfo -> HomeModInfo
addRdrEnv HomeModInfo
hmi
| ModIface
iface <- HomeModInfo -> ModIface
hm_iface HomeModInfo
hmi
, ModSummary -> Module
ms_mod ModSummary
ms Module -> Module -> Bool
forall a. Eq a => a -> a -> Bool
== ModIface -> Module
forall (phase :: ModIfacePhase). ModIface_ phase -> Module
mi_module ModIface
iface
= HomeModInfo
hmi { hm_iface = iface { mi_globals = Just $!
#if MIN_VERSION_ghc(9,8,0)
forceGlobalRdrEnv
#endif
rdr_env
}}
| Bool
otherwise = HomeModInfo
hmi
(ModSummary, HscEnv) -> Action (ModSummary, HscEnv)
forall a. a -> Action a
forall (m :: * -> *) a. Monad m => a -> m a
return (ModSummary
ms, HscEnv
linkable_hsc)
HscEnv
env2 <- IO HscEnv -> IO HscEnv
forall a. IO a -> IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO HscEnv -> IO HscEnv) -> IO HscEnv -> IO HscEnv
forall a b. (a -> b) -> a -> b
$ HscEnv -> Ghc HscEnv -> IO HscEnv
forall b. HscEnv -> Ghc b -> IO b
evalGhcEnv HscEnv
env1 (Ghc HscEnv -> IO HscEnv) -> Ghc HscEnv -> IO HscEnv
forall a b. (a -> b) -> a -> b
$ do
[InteractiveImport] -> Ghc ()
forall (m :: * -> *). GhcMonad m => [InteractiveImport] -> m ()
setContext [ModuleName -> InteractiveImport
Compat.IIModule (Module -> ModuleName
forall unit. GenModule unit -> ModuleName
moduleName (ModSummary -> Module
ms_mod ModSummary
ms))]
let df :: DynFlags
df = (DynFlags -> Extension -> DynFlags)
-> Extension -> DynFlags -> DynFlags
forall a b c. (a -> b -> c) -> b -> a -> c
flip DynFlags -> Extension -> DynFlags
xopt_set Extension
LangExt.ExtendedDefaultRules
(DynFlags -> DynFlags)
-> (DynFlags -> DynFlags) -> DynFlags -> DynFlags
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (DynFlags -> Extension -> DynFlags)
-> Extension -> DynFlags -> DynFlags
forall a b c. (a -> b -> c) -> b -> a -> c
flip DynFlags -> Extension -> DynFlags
xopt_unset Extension
LangExt.MonomorphismRestriction
(DynFlags -> DynFlags)
-> (DynFlags -> DynFlags) -> DynFlags -> DynFlags
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (DynFlags -> GeneralFlag -> DynFlags)
-> GeneralFlag -> DynFlags -> DynFlags
forall a b c. (a -> b -> c) -> b -> a -> c
flip DynFlags -> GeneralFlag -> DynFlags
gopt_set GeneralFlag
Opt_ImplicitImportQualified
(DynFlags -> DynFlags)
-> (DynFlags -> DynFlags) -> DynFlags -> DynFlags
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (DynFlags -> GeneralFlag -> DynFlags)
-> GeneralFlag -> DynFlags -> DynFlags
forall a b c. (a -> b -> c) -> b -> a -> c
flip DynFlags -> GeneralFlag -> DynFlags
gopt_unset GeneralFlag
Opt_DiagnosticsShowCaret
(DynFlags -> DynFlags) -> DynFlags -> DynFlags
forall a b. (a -> b) -> a -> b
$ (ModSummary -> DynFlags
ms_hspp_opts ModSummary
ms) {
useColor = Never
, canUseColor = False }
(DynFlags -> DynFlags) -> Ghc ()
forall (m :: * -> *). GhcMonad m => (DynFlags -> DynFlags) -> m ()
modifyDynFlags (DynFlags -> DynFlags -> DynFlags
forall a b. a -> b -> a
const DynFlags
df)
Bool -> Ghc () -> Ghc ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
needs_quickcheck (Ghc () -> Ghc ()) -> Ghc () -> Ghc ()
forall a b. (a -> b) -> a -> b
$ Ghc (Either String DynFlags) -> Ghc ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Ghc (Either String DynFlags) -> Ghc ())
-> Ghc (Either String DynFlags) -> Ghc ()
forall a b. (a -> b) -> a -> b
$ [String] -> Ghc (Either String DynFlags)
addPackages [String
"QuickCheck"]
Ghc HscEnv
forall (m :: * -> *). GhcMonad m => m HscEnv
getSession
HscEnv -> IO HscEnv
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return HscEnv
env2
addFinalReturn :: Text -> [TextEdit] -> [TextEdit]
addFinalReturn :: Text -> [TextEdit] -> [TextEdit]
addFinalReturn Text
mdlText [TextEdit]
edits
| Bool -> Bool
not ([TextEdit] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [TextEdit]
edits) Bool -> Bool -> Bool
&& Bool -> Bool
not (Text -> Bool
T.null Text
mdlText) Bool -> Bool -> Bool
&& HasCallStack => Text -> Char
Text -> Char
T.last Text
mdlText Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'\n' =
Text -> TextEdit
finalReturn Text
mdlText TextEdit -> [TextEdit] -> [TextEdit]
forall a. a -> [a] -> [a]
: [TextEdit]
edits
| Bool
otherwise = [TextEdit]
edits
finalReturn :: Text -> TextEdit
finalReturn :: Text -> TextEdit
finalReturn Text
txt =
let ls :: [Text]
ls = Text -> [Text]
T.lines Text
txt
l :: b
l = Int -> b
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> b) -> Int -> b
forall a b. (a -> b) -> a -> b
$ [Text] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Text]
ls Int -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1
c :: b
c = Int -> b
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> b) -> Int -> b
forall a b. (a -> b) -> a -> b
$ Text -> Int
T.length (Text -> Int) -> ([Text] -> Text) -> [Text] -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Text] -> Text
forall a. HasCallStack => [a] -> a
last ([Text] -> Int) -> [Text] -> Int
forall a b. (a -> b) -> a -> b
$ [Text]
ls
p :: Position
p = UInt -> UInt -> Position
Position UInt
forall {b}. Num b => b
l UInt
forall {b}. Num b => b
c
in Range -> Text -> TextEdit
TextEdit (Position -> Position -> Range
Range Position
p Position
p) Text
"\n"
moduleText :: MonadLsp c m => Uri -> ExceptT PluginError m Text
moduleText :: forall c (m :: * -> *).
MonadLsp c m =>
Uri -> ExceptT PluginError m Text
moduleText Uri
uri =
PluginError -> m (Maybe Text) -> ExceptT PluginError m Text
forall (m :: * -> *) e b.
Monad m =>
e -> m (Maybe b) -> ExceptT e m b
handleMaybeM (Text -> PluginError
PluginInternalError Text
"mdlText") (m (Maybe Text) -> ExceptT PluginError m Text)
-> m (Maybe Text) -> ExceptT PluginError m Text
forall a b. (a -> b) -> a -> b
$
(VirtualFile -> Text
virtualFileText <$>)
(Maybe VirtualFile -> Maybe Text)
-> m (Maybe VirtualFile) -> m (Maybe Text)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> NormalizedUri -> m (Maybe VirtualFile)
forall config (m :: * -> *).
MonadLsp config m =>
NormalizedUri -> m (Maybe VirtualFile)
getVirtualFile
(Uri -> NormalizedUri
toNormalizedUri Uri
uri)
testsBySection :: [Section] -> [(Section, EvalId, Test)]
testsBySection :: [Section] -> [(Section, Int, Test)]
testsBySection [Section]
sections =
[(Section
section, Int
ident, Test
test)
| (Int
ident, Section
section) <- [Int] -> [Section] -> [(Int, Section)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int
0..] [Section]
sections
, Test
test <- Section -> [Test]
sectionTests Section
section
]
type TEnv = (IdeState, String)
evalSetup :: Ghc ()
evalSetup :: Ghc ()
evalSetup = do
ImportDecl GhcPs
preludeAsP <- String -> Ghc (ImportDecl GhcPs)
forall (m :: * -> *). GhcMonad m => String -> m (ImportDecl GhcPs)
parseImportDecl String
"import qualified Prelude as P"
[InteractiveImport]
context <- Ghc [InteractiveImport]
forall (m :: * -> *). GhcMonad m => m [InteractiveImport]
getContext
[InteractiveImport] -> Ghc ()
forall (m :: * -> *). GhcMonad m => [InteractiveImport] -> m ()
setContext (ImportDecl GhcPs -> InteractiveImport
IIDecl ImportDecl GhcPs
preludeAsP InteractiveImport -> [InteractiveImport] -> [InteractiveImport]
forall a. a -> [a] -> [a]
: [InteractiveImport]
context)
runTests :: EvalConfig -> TEnv -> [(Section, Test)] -> Ghc [TextEdit]
runTests :: EvalConfig -> TEnv -> [(Section, Test)] -> Ghc [TextEdit]
runTests EvalConfig{Bool
eval_cfg_diff :: Bool
eval_cfg_exception :: Bool
eval_cfg_diff :: EvalConfig -> Bool
eval_cfg_exception :: EvalConfig -> Bool
..} e :: TEnv
e@(IdeState
_st, String
_) [(Section, Test)]
tests = do
DynFlags
df <- Ghc DynFlags
forall (m :: * -> *). GhcMonad m => m DynFlags
getInteractiveDynFlags
Ghc ()
evalSetup
Bool -> Ghc () -> Ghc ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (DynFlags -> Bool
hasQuickCheck DynFlags
df Bool -> Bool -> Bool
&& [(Section, Test)] -> Bool
needsQuickCheck [(Section, Test)]
tests) (Ghc () -> Ghc ()) -> Ghc () -> Ghc ()
forall a b. (a -> b) -> a -> b
$ Ghc [Text] -> Ghc ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Ghc [Text] -> Ghc ()) -> Ghc [Text] -> Ghc ()
forall a b. (a -> b) -> a -> b
$ Bool -> TEnv -> DynFlags -> [Statement] -> Ghc [Text]
evals Bool
True TEnv
e DynFlags
df [Statement]
propSetup
((Section, Test) -> Ghc TextEdit)
-> [(Section, Test)] -> Ghc [TextEdit]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (TEnv -> DynFlags -> (Section, Test) -> Ghc TextEdit
processTest TEnv
e DynFlags
df) [(Section, Test)]
tests
where
processTest :: TEnv -> DynFlags -> (Section, Test) -> Ghc TextEdit
processTest :: TEnv -> DynFlags -> (Section, Test) -> Ghc TextEdit
processTest e :: TEnv
e@(IdeState
st, String
fp) DynFlags
df (Section
section, Test
test) = do
let dbg :: a1 -> a2 -> m ()
dbg = IdeState -> a1 -> a2 -> m ()
forall (m :: * -> *) a1 a2.
(HasCallStack, MonadIO m, Show a1, Show a2) =>
IdeState -> a1 -> a2 -> m ()
logWith IdeState
st
let pad :: Text -> Text
pad = Text -> Text -> Text
pad_ (Text -> Text -> Text) -> Text -> Text -> Text
forall a b. (a -> b) -> a -> b
$ (if String -> Bool
isLiterate String
fp then (Text
"> " `T.append`) else Text -> Text
forall a. a -> a
id) (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ Format -> Text
forall p. IsString p => Format -> p
padPrefix (Section -> Format
sectionFormat Section
section)
[Text]
rs <- TEnv -> DynFlags -> Test -> Ghc [Text]
runTest TEnv
e DynFlags
df Test
test
String -> [Text] -> Ghc ()
forall {m :: * -> *} {a1} {a2}.
(MonadIO m, Show a1, Show a2) =>
a1 -> a2 -> m ()
dbg String
"TEST RESULTS" [Text]
rs
let checkedResult :: [Text]
checkedResult = Bool -> (Section, Test) -> [Text] -> [Text]
testCheck Bool
eval_cfg_diff (Section
section, Test
test) [Text]
rs
let resultLines :: [Text]
resultLines = (Text -> [Text]) -> [Text] -> [Text]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Text -> [Text]
T.lines [Text]
checkedResult
let edit :: TextEdit
edit = Format -> Test -> [Text] -> TextEdit
asEdit (Section -> Format
sectionFormat Section
section) Test
test ((Text -> Text) -> [Text] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map Text -> Text
pad [Text]
resultLines)
String -> TextEdit -> Ghc ()
forall {m :: * -> *} {a1} {a2}.
(MonadIO m, Show a1, Show a2) =>
a1 -> a2 -> m ()
dbg String
"TEST EDIT" TextEdit
edit
TextEdit -> Ghc TextEdit
forall a. a -> Ghc a
forall (m :: * -> *) a. Monad m => a -> m a
return TextEdit
edit
runTest :: TEnv -> DynFlags -> Test -> Ghc [Text]
runTest TEnv
_ DynFlags
df Test
test
| Bool -> Bool
not (DynFlags -> Bool
hasQuickCheck DynFlags
df) Bool -> Bool -> Bool
&& Test -> Bool
isProperty Test
test =
[Text] -> Ghc [Text]
forall a. a -> Ghc a
forall (m :: * -> *) a. Monad m => a -> m a
return ([Text] -> Ghc [Text]) -> [Text] -> Ghc [Text]
forall a b. (a -> b) -> a -> b
$
String -> [Text]
singleLine
String
"Add QuickCheck to your cabal dependencies to run this test."
runTest TEnv
e DynFlags
df Test
test = Bool -> TEnv -> DynFlags -> [Statement] -> Ghc [Text]
evals (Bool
eval_cfg_exception Bool -> Bool -> Bool
&& Bool -> Bool
not (Test -> Bool
isProperty Test
test)) TEnv
e DynFlags
df (Test -> [Statement]
asStatements Test
test)
asEdit :: Format -> Test -> [Text] -> TextEdit
asEdit :: Format -> Test -> [Text] -> TextEdit
asEdit (MultiLine Range
commRange) Test
test [Text]
resultLines
| Test -> Range
testRange Test
test Range -> Getting UInt Range UInt -> UInt
forall s a. s -> Getting a s a -> a
^. (Position -> Const UInt Position) -> Range -> Const UInt Range
forall s a. HasEnd s a => Lens' s a
Lens' Range Position
L.end ((Position -> Const UInt Position) -> Range -> Const UInt Range)
-> ((UInt -> Const UInt UInt) -> Position -> Const UInt Position)
-> Getting UInt Range UInt
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (UInt -> Const UInt UInt) -> Position -> Const UInt Position
forall s a. HasLine s a => Lens' s a
Lens' Position UInt
L.line UInt -> UInt -> Bool
forall a. Eq a => a -> a -> Bool
== Range
commRange Range -> Getting UInt Range UInt -> UInt
forall s a. s -> Getting a s a -> a
^. (Position -> Const UInt Position) -> Range -> Const UInt Range
forall s a. HasEnd s a => Lens' s a
Lens' Range Position
L.end ((Position -> Const UInt Position) -> Range -> Const UInt Range)
-> ((UInt -> Const UInt UInt) -> Position -> Const UInt Position)
-> Getting UInt Range UInt
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (UInt -> Const UInt UInt) -> Position -> Const UInt Position
forall s a. HasLine s a => Lens' s a
Lens' Position UInt
L.line
=
Range -> Text -> TextEdit
TextEdit
(Position -> Position -> Range
Range
(Test -> Range
testRange Test
test Range -> Getting Position Range Position -> Position
forall s a. s -> Getting a s a -> a
^. Getting Position Range Position
forall s a. HasEnd s a => Lens' s a
Lens' Range Position
L.end)
(Test -> Range
resultRange Test
test Range -> Getting Position Range Position -> Position
forall s a. s -> Getting a s a -> a
^. Getting Position Range Position
forall s a. HasEnd s a => Lens' s a
Lens' Range Position
L.end)
)
(Text
"\n" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> [Text] -> Text
T.unlines ([Text]
resultLines [Text] -> [Text] -> [Text]
forall a. Semigroup a => a -> a -> a
<> [Text
"-}"]))
asEdit Format
_ Test
test [Text]
resultLines =
Range -> Text -> TextEdit
TextEdit (Test -> Range
resultRange Test
test) ([Text] -> Text
T.unlines [Text]
resultLines)
evals :: Bool -> TEnv -> DynFlags -> [Statement] -> Ghc [Text]
evals :: Bool -> TEnv -> DynFlags -> [Statement] -> Ghc [Text]
evals Bool
mark_exception (IdeState
st, String
fp) DynFlags
df [Statement]
stmts = do
Either String [Maybe [Text]]
er <- Ghc [Maybe [Text]] -> Ghc (Either String [Maybe [Text]])
forall (m :: * -> *) b.
(MonadIO m, MonadCatch m) =>
m b -> m (Either String b)
gStrictTry (Ghc [Maybe [Text]] -> Ghc (Either String [Maybe [Text]]))
-> Ghc [Maybe [Text]] -> Ghc (Either String [Maybe [Text]])
forall a b. (a -> b) -> a -> b
$ (Statement -> Ghc (Maybe [Text]))
-> [Statement] -> Ghc [Maybe [Text]]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM Statement -> Ghc (Maybe [Text])
eval [Statement]
stmts
[Text] -> Ghc [Text]
forall a. a -> Ghc a
forall (m :: * -> *) a. Monad m => a -> m a
return ([Text] -> Ghc [Text]) -> [Text] -> Ghc [Text]
forall a b. (a -> b) -> a -> b
$ case Either String [Maybe [Text]]
er of
Left String
err -> String -> [Text]
errorLines String
err
Right [Maybe [Text]]
rs -> [[Text]] -> [Text]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[Text]] -> [Text])
-> ([Maybe [Text]] -> [[Text]]) -> [Maybe [Text]] -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Maybe [Text]] -> [[Text]]
forall a. [Maybe a] -> [a]
catMaybes ([Maybe [Text]] -> [Text]) -> [Maybe [Text]] -> [Text]
forall a b. (a -> b) -> a -> b
$ [Maybe [Text]]
rs
where
dbg :: a1 -> a2 -> m ()
dbg = IdeState -> a1 -> a2 -> m ()
forall (m :: * -> *) a1 a2.
(HasCallStack, MonadIO m, Show a1, Show a2) =>
IdeState -> a1 -> a2 -> m ()
logWith IdeState
st
eval :: Statement -> Ghc (Maybe [Text])
eval :: Statement -> Ghc (Maybe [Text])
eval (Located Int
l String
stmt)
|
Just (String -> [String]
words -> [String]
flags) <- String -> Maybe String
parseSetFlags String
stmt = do
String -> [String] -> Ghc ()
forall {m :: * -> *} {a1} {a2}.
(MonadIO m, Show a1, Show a2) =>
a1 -> a2 -> m ()
dbg String
"{:SET" [String]
flags
DynFlags
ndf <- Ghc DynFlags
forall (m :: * -> *). GhcMonad m => m DynFlags
getInteractiveDynFlags
String -> String -> Ghc ()
forall {m :: * -> *} {a1} {a2}.
(MonadIO m, Show a1, Show a2) =>
a1 -> a2 -> m ()
dbg String
"pre set" (String -> Ghc ()) -> String -> Ghc ()
forall a b. (a -> b) -> a -> b
$ DynFlags -> String
showDynFlags DynFlags
ndf
Either GhcException (DynFlags, [Located String], [Warn])
eans <-
IO (Either GhcException (DynFlags, [Located String], [Warn]))
-> Ghc (Either GhcException (DynFlags, [Located String], [Warn]))
forall a. IO a -> Ghc a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Either GhcException (DynFlags, [Located String], [Warn]))
-> Ghc (Either GhcException (DynFlags, [Located String], [Warn])))
-> IO (Either GhcException (DynFlags, [Located String], [Warn]))
-> Ghc (Either GhcException (DynFlags, [Located String], [Warn]))
forall a b. (a -> b) -> a -> b
$ forall e a. Exception e => IO a -> IO (Either e a)
try @GhcException (IO (DynFlags, [Located String], [Warn])
-> IO (Either GhcException (DynFlags, [Located String], [Warn])))
-> IO (DynFlags, [Located String], [Warn])
-> IO (Either GhcException (DynFlags, [Located String], [Warn]))
forall a b. (a -> b) -> a -> b
$
DynFlags
-> [Located String] -> IO (DynFlags, [Located String], [Warn])
forall (m :: * -> *).
MonadIO m =>
DynFlags
-> [Located String] -> m (DynFlags, [Located String], [Warn])
parseDynamicFlagsCmdLine DynFlags
ndf
((String -> Located String) -> [String] -> [Located String]
forall a b. (a -> b) -> [a] -> [b]
map (SrcSpan -> String -> Located String
forall l e. l -> e -> GenLocated l e
L (SrcSpan -> String -> Located String)
-> SrcSpan -> String -> Located String
forall a b. (a -> b) -> a -> b
$ UnhelpfulSpanReason -> SrcSpan
UnhelpfulSpan UnhelpfulSpanReason
unhelpfulReason) [String]
flags)
String
-> Either GhcException (String, [Located String], String) -> Ghc ()
forall {m :: * -> *} {a1} {a2}.
(MonadIO m, Show a1, Show a2) =>
a1 -> a2 -> m ()
dbg String
"parsed flags" (Either GhcException (String, [Located String], String) -> Ghc ())
-> Either GhcException (String, [Located String], String) -> Ghc ()
forall a b. (a -> b) -> a -> b
$ Either GhcException (DynFlags, [Located String], [Warn])
eans
Either GhcException (DynFlags, [Located String], [Warn])
-> ((DynFlags, [Located String], [Warn])
-> (String, [Located String], String))
-> Either GhcException (String, [Located String], String)
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> ((DynFlags -> Identity String)
-> (DynFlags, [Located String], [Warn])
-> Identity (String, [Located String], [Warn])
forall s t a b. Field1 s t a b => Lens s t a b
Lens
(DynFlags, [Located String], [Warn])
(String, [Located String], [Warn])
DynFlags
String
_1 ((DynFlags -> Identity String)
-> (DynFlags, [Located String], [Warn])
-> Identity (String, [Located String], [Warn]))
-> (DynFlags -> String)
-> (DynFlags, [Located String], [Warn])
-> (String, [Located String], [Warn])
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ DynFlags -> String
showDynFlags ((DynFlags, [Located String], [Warn])
-> (String, [Located String], [Warn]))
-> ((String, [Located String], [Warn])
-> (String, [Located String], String))
-> (DynFlags, [Located String], [Warn])
-> (String, [Located String], String)
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> ([Warn] -> Identity String)
-> (String, [Located String], [Warn])
-> Identity (String, [Located String], String)
forall s t a b. Field3 s t a b => Lens s t a b
Lens
(String, [Located String], [Warn])
(String, [Located String], String)
[Warn]
String
_3 (([Warn] -> Identity String)
-> (String, [Located String], [Warn])
-> Identity (String, [Located String], String))
-> ([Warn] -> String)
-> (String, [Located String], [Warn])
-> (String, [Located String], String)
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ [Warn] -> String
prettyWarnings)
case Either GhcException (DynFlags, [Located String], [Warn])
eans of
Left GhcException
err -> Maybe [Text] -> Ghc (Maybe [Text])
forall a. a -> Ghc a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe [Text] -> Ghc (Maybe [Text]))
-> Maybe [Text] -> Ghc (Maybe [Text])
forall a b. (a -> b) -> a -> b
$ [Text] -> Maybe [Text]
forall a. a -> Maybe a
Just ([Text] -> Maybe [Text]) -> [Text] -> Maybe [Text]
forall a b. (a -> b) -> a -> b
$ String -> [Text]
errorLines (String -> [Text]) -> String -> [Text]
forall a b. (a -> b) -> a -> b
$ GhcException -> String
forall a. Show a => a -> String
show GhcException
err
Right (DynFlags
df', [Located String]
ignoreds, [Warn]
warns) -> do
let warnings :: m [Text]
warnings = do
Bool -> m ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> m ()) -> Bool -> m ()
forall a b. (a -> b) -> a -> b
$ Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ [Warn] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Warn]
warns
[Text] -> m [Text]
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([Text] -> m [Text]) -> [Text] -> m [Text]
forall a b. (a -> b) -> a -> b
$ String -> [Text]
errorLines (String -> [Text]) -> String -> [Text]
forall a b. (a -> b) -> a -> b
$
[Warn] -> String
prettyWarnings [Warn]
warns
igns :: m [Text]
igns = do
Bool -> m ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> m ()) -> Bool -> m ()
forall a b. (a -> b) -> a -> b
$ Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ [Located String] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Located String]
ignoreds
[Text] -> m [Text]
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
[Text
"Some flags have not been recognized: "
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
", " ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ (Located String -> String) -> [Located String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Located String -> String
forall l e. GenLocated l e -> e
SrcLoc.unLoc [Located String]
ignoreds)
]
String -> String -> Ghc ()
forall {m :: * -> *} {a1} {a2}.
(MonadIO m, Show a1, Show a2) =>
a1 -> a2 -> m ()
dbg String
"post set" (String -> Ghc ()) -> String -> Ghc ()
forall a b. (a -> b) -> a -> b
$ DynFlags -> String
showDynFlags DynFlags
df'
DynFlags -> Ghc ()
setSessionAndInteractiveDynFlags DynFlags
df'
Maybe [Text] -> Ghc (Maybe [Text])
forall a. a -> Ghc a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe [Text] -> Ghc (Maybe [Text]))
-> Maybe [Text] -> Ghc (Maybe [Text])
forall a b. (a -> b) -> a -> b
$ Maybe [Text]
forall {m :: * -> *}. (Monad m, Alternative m) => m [Text]
warnings Maybe [Text] -> Maybe [Text] -> Maybe [Text]
forall a. Semigroup a => a -> a -> a
<> Maybe [Text]
forall {m :: * -> *}. (Monad m, Alternative m) => m [Text]
igns
|
Just (Text
cmd, Text
arg) <- Text -> Maybe (Text, Text)
parseGhciLikeCmd (Text -> Maybe (Text, Text)) -> Text -> Maybe (Text, Text)
forall a b. (a -> b) -> a -> b
$ String -> Text
T.pack String
stmt =
Text -> Text -> Ghc (Maybe [Text])
evalGhciLikeCmd Text
cmd Text
arg
|
ParserOpts -> String -> Bool
isStmt ParserOpts
pf String
stmt =
do
String -> String -> Ghc ()
forall {m :: * -> *} {a1} {a2}.
(MonadIO m, Show a1, Show a2) =>
a1 -> a2 -> m ()
dbg String
"{STMT " String
stmt
Either String (Maybe String)
res <- String -> Int -> Ghc (Either String (Maybe String))
exec String
stmt Int
l
let r :: Maybe [Text]
r = case Either String (Maybe String)
res of
Left String
err -> [Text] -> Maybe [Text]
forall a. a -> Maybe a
Just ([Text] -> Maybe [Text])
-> (String -> [Text]) -> String -> Maybe [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (if Bool
mark_exception then String -> [Text]
exceptionLines else String -> [Text]
errorLines) (String -> Maybe [Text]) -> String -> Maybe [Text]
forall a b. (a -> b) -> a -> b
$ String
err
Right Maybe String
x -> String -> [Text]
singleLine (String -> [Text]) -> Maybe String -> Maybe [Text]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe String
x
String -> Maybe [Text] -> Ghc ()
forall {m :: * -> *} {a1} {a2}.
(MonadIO m, Show a1, Show a2) =>
a1 -> a2 -> m ()
dbg String
"STMT} -> " Maybe [Text]
r
Maybe [Text] -> Ghc (Maybe [Text])
forall a. a -> Ghc a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe [Text]
r
|
ParserOpts -> String -> Bool
isImport ParserOpts
pf String
stmt =
do
String -> String -> Ghc ()
forall {m :: * -> *} {a1} {a2}.
(MonadIO m, Show a1, Show a2) =>
a1 -> a2 -> m ()
dbg String
"{IMPORT " String
stmt
[InteractiveImport]
_ <- String -> Ghc [InteractiveImport]
forall (m :: * -> *). GhcMonad m => String -> m [InteractiveImport]
addImport String
stmt
Maybe [Text] -> Ghc (Maybe [Text])
forall a. a -> Ghc a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe [Text]
forall a. Maybe a
Nothing
|
Bool
otherwise =
do
String -> String -> Ghc ()
forall {m :: * -> *} {a1} {a2}.
(MonadIO m, Show a1, Show a2) =>
a1 -> a2 -> m ()
dbg String
"{DECL " String
stmt
Ghc [Name] -> Ghc ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Ghc [Name] -> Ghc ()) -> Ghc [Name] -> Ghc ()
forall a b. (a -> b) -> a -> b
$ String -> Ghc [Name]
forall (m :: * -> *). GhcMonad m => String -> m [Name]
runDecls String
stmt
Maybe [Text] -> Ghc (Maybe [Text])
forall a. a -> Ghc a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe [Text]
forall a. Maybe a
Nothing
pf :: ParserOpts
pf = DynFlags -> ParserOpts
initParserOpts DynFlags
df
unhelpfulReason :: UnhelpfulSpanReason
unhelpfulReason = UnhelpfulSpanReason
UnhelpfulInteractive
exec :: String -> Int -> Ghc (Either String (Maybe String))
exec String
stmt Int
l =
let opts :: ExecOptions
opts = ExecOptions
execOptions{execSourceFile = fp, execLineNumber = l}
in String -> ExecOptions -> Ghc (Either String (Maybe String))
myExecStmt String
stmt ExecOptions
opts
#if MIN_VERSION_ghc(9,8,0)
prettyWarnings :: Messages DriverMessage -> String
prettyWarnings = printWithoutUniques . pprMessages (defaultDiagnosticOpts @DriverMessage)
#else
prettyWarnings :: [Warn] -> String
prettyWarnings :: [Warn] -> String
prettyWarnings = [String] -> String
unlines ([String] -> String) -> ([Warn] -> [String]) -> [Warn] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Warn -> String) -> [Warn] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Warn -> String
prettyWarn
prettyWarn :: Warn -> String
prettyWarn :: Warn -> String
prettyWarn Warn{Located String
DiagnosticReason
warnReason :: DiagnosticReason
warnMsg :: Located String
warnReason :: Warn -> DiagnosticReason
warnMsg :: Warn -> Located String
..} =
Text -> String
T.unpack (SrcSpan -> Text
forall a. Outputable a => a -> Text
printOutputable (SrcSpan -> Text) -> SrcSpan -> Text
forall a b. (a -> b) -> a -> b
$ Located String -> SrcSpan
forall a. HasSrcSpan a => a -> SrcSpan
SrcLoc.getLoc Located String
warnMsg) String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
": warning:\n"
String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
" " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Located String -> String
forall l e. GenLocated l e -> e
SrcLoc.unLoc Located String
warnMsg
#endif
needsQuickCheck :: [(Section, Test)] -> Bool
needsQuickCheck :: [(Section, Test)] -> Bool
needsQuickCheck = ((Section, Test) -> Bool) -> [(Section, Test)] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Test -> Bool
isProperty (Test -> Bool)
-> ((Section, Test) -> Test) -> (Section, Test) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Section, Test) -> Test
forall a b. (a, b) -> b
snd)
hasQuickCheck :: DynFlags -> Bool
hasQuickCheck :: DynFlags -> Bool
hasQuickCheck DynFlags
df = DynFlags -> String -> Bool
hasPackage DynFlags
df String
"QuickCheck"
singleLine :: String -> [Text]
singleLine :: String -> [Text]
singleLine String
s = [String -> Text
T.pack String
s]
errorLines :: String -> [Text]
errorLines :: String -> [Text]
errorLines =
(Text -> Bool) -> [Text] -> [Text]
forall a. (a -> Bool) -> [a] -> [a]
dropWhileEnd Text -> Bool
T.null
([Text] -> [Text]) -> (String -> [Text]) -> String -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Bool) -> [Text] -> [Text]
forall a. (a -> Bool) -> [a] -> [a]
takeWhile (Bool -> Bool
not (Bool -> Bool) -> (Text -> Bool) -> Text -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text
"CallStack" `T.isPrefixOf`))
([Text] -> [Text]) -> (String -> [Text]) -> String -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Text]
T.lines
(Text -> [Text]) -> (String -> Text) -> String -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
T.pack
exceptionLines :: String -> [Text]
exceptionLines :: String -> [Text]
exceptionLines = (Index [Text] -> Traversal' [Text] (IxValue [Text])
forall m. Ixed m => Index m -> Traversal' m (IxValue m)
ix Int
Index [Text]
0 ((Text -> Identity Text) -> [Text] -> Identity [Text])
-> (Text -> Text) -> [Text] -> [Text]
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ (Text
"*** Exception: " <>)) ([Text] -> [Text]) -> (String -> [Text]) -> String -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [Text]
errorLines
pad_ :: Text -> Text -> Text
pad_ :: Text -> Text -> Text
pad_ Text
prefix = (Text
prefix `T.append`) (Text -> Text) -> (Text -> Text) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
convertBlank
convertBlank :: Text -> Text
convertBlank :: Text -> Text
convertBlank Text
x
| Text -> Bool
T.null Text
x = Text
"<BLANKLINE>"
| Bool
otherwise = Text
x
padPrefix :: IsString p => Format -> p
padPrefix :: forall p. IsString p => Format -> p
padPrefix Format
SingleLine = p
"-- "
padPrefix Format
_ = p
""
type GHCiLikeCmd = DynFlags -> Text -> Ghc (Maybe Text)
ghciLikeCommands :: [(Text, GHCiLikeCmd)]
ghciLikeCommands :: [(Text, GHCiLikeCmd)]
ghciLikeCommands =
[ (Text
"info", Bool -> GHCiLikeCmd
doInfoCmd Bool
False)
, (Text
"info!", Bool -> GHCiLikeCmd
doInfoCmd Bool
True)
, (Text
"kind", Bool -> GHCiLikeCmd
doKindCmd Bool
False)
, (Text
"kind!", Bool -> GHCiLikeCmd
doKindCmd Bool
True)
, (Text
"type", GHCiLikeCmd
doTypeCmd)
]
evalGhciLikeCmd :: Text -> Text -> Ghc (Maybe [Text])
evalGhciLikeCmd :: Text -> Text -> Ghc (Maybe [Text])
evalGhciLikeCmd Text
cmd Text
arg = do
DynFlags
df <- Ghc DynFlags
forall (m :: * -> *). GhcMonad m => m DynFlags
getSessionDynFlags
case Text -> [(Text, GHCiLikeCmd)] -> Maybe GHCiLikeCmd
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup Text
cmd [(Text, GHCiLikeCmd)]
ghciLikeCommands
Maybe GHCiLikeCmd -> Maybe GHCiLikeCmd -> Maybe GHCiLikeCmd
forall a. Maybe a -> Maybe a -> Maybe a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Text, GHCiLikeCmd) -> GHCiLikeCmd
forall a b. (a, b) -> b
snd
((Text, GHCiLikeCmd) -> GHCiLikeCmd)
-> Maybe (Text, GHCiLikeCmd) -> Maybe GHCiLikeCmd
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ((Text, GHCiLikeCmd) -> Bool)
-> [(Text, GHCiLikeCmd)] -> Maybe (Text, GHCiLikeCmd)
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find (Text -> Text -> Bool
T.isPrefixOf Text
cmd (Text -> Bool)
-> ((Text, GHCiLikeCmd) -> Text) -> (Text, GHCiLikeCmd) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text, GHCiLikeCmd) -> Text
forall a b. (a, b) -> a
fst) [(Text, GHCiLikeCmd)]
ghciLikeCommands of
Just GHCiLikeCmd
hndler ->
(Text -> [Text]) -> Maybe Text -> Maybe [Text]
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap
Text -> [Text]
T.lines
(Maybe Text -> Maybe [Text])
-> Ghc (Maybe Text) -> Ghc (Maybe [Text])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GHCiLikeCmd
hndler DynFlags
df Text
arg
Maybe GHCiLikeCmd
_ -> GhciLikeCmdException -> Ghc (Maybe [Text])
forall a e. Exception e => e -> a
E.throw (GhciLikeCmdException -> Ghc (Maybe [Text]))
-> GhciLikeCmdException -> Ghc (Maybe [Text])
forall a b. (a -> b) -> a -> b
$ Text -> Text -> GhciLikeCmdException
GhciLikeCmdNotImplemented Text
cmd Text
arg
doInfoCmd :: Bool -> DynFlags -> Text -> Ghc (Maybe Text)
doInfoCmd :: Bool -> GHCiLikeCmd
doInfoCmd Bool
allInfo DynFlags
dflags Text
s = do
[SDoc]
sdocs <- (Text -> Ghc SDoc) -> [Text] -> Ghc [SDoc]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM Text -> Ghc SDoc
forall (m :: * -> *). GhcMonad m => Text -> m SDoc
infoThing (Text -> [Text]
T.words Text
s)
Maybe Text -> Ghc (Maybe Text)
forall a. a -> Ghc a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe Text -> Ghc (Maybe Text)) -> Maybe Text -> Ghc (Maybe Text)
forall a b. (a -> b) -> a -> b
$ Text -> Maybe Text
forall a. a -> Maybe a
Just (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ DynFlags -> SDoc -> String
showSDoc DynFlags
dflags ([SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat [SDoc]
sdocs)
where
infoThing :: GHC.GhcMonad m => Text -> m SDoc
infoThing :: forall (m :: * -> *). GhcMonad m => Text -> m SDoc
infoThing (Text -> String
T.unpack -> String
str) = do
NonEmpty Name
names <- String -> m (NonEmpty Name)
forall (m :: * -> *). GhcMonad m => String -> m (NonEmpty Name)
GHC.parseName String
str
NonEmpty (Maybe (TyThing, Fixity, [ClsInst], [FamInst], SDoc))
mb_stuffs <- (Name -> m (Maybe (TyThing, Fixity, [ClsInst], [FamInst], SDoc)))
-> NonEmpty Name
-> m (NonEmpty
(Maybe (TyThing, Fixity, [ClsInst], [FamInst], SDoc)))
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> NonEmpty a -> m (NonEmpty b)
mapM (Bool
-> Name -> m (Maybe (TyThing, Fixity, [ClsInst], [FamInst], SDoc))
forall (m :: * -> *).
GhcMonad m =>
Bool
-> Name -> m (Maybe (TyThing, Fixity, [ClsInst], [FamInst], SDoc))
GHC.getInfo Bool
allInfo) NonEmpty Name
names
let filtered :: [(TyThing, Fixity, [ClsInst], [FamInst], SDoc)]
filtered = ((TyThing, Fixity, [ClsInst], [FamInst], SDoc) -> TyThing)
-> [(TyThing, Fixity, [ClsInst], [FamInst], SDoc)]
-> [(TyThing, Fixity, [ClsInst], [FamInst], SDoc)]
forall a. (a -> TyThing) -> [a] -> [a]
filterOutChildren (\(TyThing
t,Fixity
_f,[ClsInst]
_ci,[FamInst]
_fi,SDoc
_sd) -> TyThing
t)
([Maybe (TyThing, Fixity, [ClsInst], [FamInst], SDoc)]
-> [(TyThing, Fixity, [ClsInst], [FamInst], SDoc)]
forall a. [Maybe a] -> [a]
catMaybes ([Maybe (TyThing, Fixity, [ClsInst], [FamInst], SDoc)]
-> [(TyThing, Fixity, [ClsInst], [FamInst], SDoc)])
-> [Maybe (TyThing, Fixity, [ClsInst], [FamInst], SDoc)]
-> [(TyThing, Fixity, [ClsInst], [FamInst], SDoc)]
forall a b. (a -> b) -> a -> b
$ NonEmpty (Maybe (TyThing, Fixity, [ClsInst], [FamInst], SDoc))
-> [Maybe (TyThing, Fixity, [ClsInst], [FamInst], SDoc)]
forall a. NonEmpty a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList NonEmpty (Maybe (TyThing, Fixity, [ClsInst], [FamInst], SDoc))
mb_stuffs)
SDoc -> m SDoc
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (SDoc -> m SDoc) -> SDoc -> m SDoc
forall a b. (a -> b) -> a -> b
$ [SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat (SDoc -> [SDoc] -> [SDoc]
forall a. a -> [a] -> [a]
intersperse (String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"") ([SDoc] -> [SDoc]) -> [SDoc] -> [SDoc]
forall a b. (a -> b) -> a -> b
$ ((TyThing, Fixity, [ClsInst], [FamInst], SDoc) -> SDoc)
-> [(TyThing, Fixity, [ClsInst], [FamInst], SDoc)] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map (TyThing, Fixity, [ClsInst], [FamInst], SDoc) -> SDoc
pprInfo [(TyThing, Fixity, [ClsInst], [FamInst], SDoc)]
filtered)
filterOutChildren :: (a -> TyThing) -> [a] -> [a]
filterOutChildren :: forall a. (a -> TyThing) -> [a] -> [a]
filterOutChildren a -> TyThing
get_thing [a]
xs
= (a -> Bool) -> [a] -> [a]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool) -> (a -> Bool) -> a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Bool
has_parent) [a]
xs
where
all_names :: NameSet
all_names = [Name] -> NameSet
mkNameSet ((a -> Name) -> [a] -> [Name]
forall a b. (a -> b) -> [a] -> [b]
map (TyThing -> Name
forall a. NamedThing a => a -> Name
getName (TyThing -> Name) -> (a -> TyThing) -> a -> Name
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> TyThing
get_thing) [a]
xs)
has_parent :: a -> Bool
has_parent a
x = case TyThing -> Maybe TyThing
tyThingParent_maybe (a -> TyThing
get_thing a
x) of
Just TyThing
p -> TyThing -> Name
forall a. NamedThing a => a -> Name
getName TyThing
p Name -> NameSet -> Bool
`elemNameSet` NameSet
all_names
Maybe TyThing
Nothing -> Bool
False
pprInfo :: (TyThing, Fixity, [GHC.ClsInst], [GHC.FamInst], SDoc) -> SDoc
pprInfo :: (TyThing, Fixity, [ClsInst], [FamInst], SDoc) -> SDoc
pprInfo (TyThing
thing, Fixity
fixity, [ClsInst]
cls_insts, [FamInst]
fam_insts, SDoc
docs)
= SDoc
docs
SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ TyThing -> SDoc
pprTyThingInContextLoc TyThing
thing
SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ TyThing -> Fixity -> SDoc
showFixity TyThing
thing Fixity
fixity
SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ [SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat ((ClsInst -> SDoc) -> [ClsInst] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map ClsInst -> SDoc
GHC.pprInstance [ClsInst]
cls_insts)
SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ [SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat ((FamInst -> SDoc) -> [FamInst] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map FamInst -> SDoc
GHC.pprFamInst [FamInst]
fam_insts)
pprTyThingInContextLoc :: TyThing -> SDoc
pprTyThingInContextLoc :: TyThing -> SDoc
pprTyThingInContextLoc TyThing
tyThing
= SDoc -> SDoc -> SDoc
showWithLoc (Name -> SDoc
pprDefinedAt (TyThing -> Name
forall a. NamedThing a => a -> Name
getName TyThing
tyThing))
(ShowSub -> TyThing -> SDoc
pprTyThingInContext ShowSub
showToHeader TyThing
tyThing)
showWithLoc :: SDoc -> SDoc -> SDoc
showWithLoc :: SDoc -> SDoc -> SDoc
showWithLoc SDoc
loc SDoc
doc
= SDoc -> Int -> SDoc -> SDoc
hang SDoc
doc Int
2 (String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"\t--" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> SDoc
loc)
showFixity :: TyThing -> Fixity -> SDoc
showFixity :: TyThing -> Fixity -> SDoc
showFixity TyThing
thing Fixity
fixity
| Fixity
fixity Fixity -> Fixity -> Bool
forall a. Eq a => a -> a -> Bool
/= Fixity
GHC.defaultFixity Bool -> Bool -> Bool
|| OccName -> Bool
isSymOcc (TyThing -> OccName
forall a. NamedThing a => a -> OccName
getOccName TyThing
thing)
= Fixity -> SDoc
forall a. Outputable a => a -> SDoc
ppr Fixity
fixity SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Name -> SDoc
forall a. (Outputable a, NamedThing a) => a -> SDoc
pprInfixName (TyThing -> Name
forall a. NamedThing a => a -> Name
GHC.getName TyThing
thing)
| Bool
otherwise = SDoc
forall doc. IsOutput doc => doc
empty
doKindCmd :: Bool -> DynFlags -> Text -> Ghc (Maybe Text)
doKindCmd :: Bool -> GHCiLikeCmd
doKindCmd Bool
False DynFlags
df Text
arg = do
let input :: Text
input = Text -> Text
T.strip Text
arg
(Type
_, Type
kind) <- Bool -> String -> Ghc (Type, Type)
forall (m :: * -> *).
GhcMonad m =>
Bool -> String -> m (Type, Type)
typeKind Bool
False (String -> Ghc (Type, Type)) -> String -> Ghc (Type, Type)
forall a b. (a -> b) -> a -> b
$ Text -> String
T.unpack Text
input
let kindText :: SDoc
kindText = String -> SDoc
forall doc. IsLine doc => String -> doc
text (Text -> String
T.unpack Text
input) SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> SDoc
"::" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Type -> SDoc
pprSigmaType Type
kind
Maybe Text -> Ghc (Maybe Text)
forall a. a -> Ghc a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe Text -> Ghc (Maybe Text)) -> Maybe Text -> Ghc (Maybe Text)
forall a b. (a -> b) -> a -> b
$ Text -> Maybe Text
forall a. a -> Maybe a
Just (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ String -> Text
T.pack (DynFlags -> SDoc -> String
showSDoc DynFlags
df SDoc
kindText)
doKindCmd Bool
True DynFlags
df Text
arg = do
let input :: Text
input = Text -> Text
T.strip Text
arg
(Type
ty, Type
kind) <- Bool -> String -> Ghc (Type, Type)
forall (m :: * -> *).
GhcMonad m =>
Bool -> String -> m (Type, Type)
typeKind Bool
True (String -> Ghc (Type, Type)) -> String -> Ghc (Type, Type)
forall a b. (a -> b) -> a -> b
$ Text -> String
T.unpack Text
input
let kindDoc :: SDoc
kindDoc = String -> SDoc
forall doc. IsLine doc => String -> doc
text (Text -> String
T.unpack Text
input) SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> SDoc
"::" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Type -> SDoc
pprSigmaType Type
kind
tyDoc :: SDoc
tyDoc = SDoc
"=" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Type -> SDoc
pprSigmaType Type
ty
Maybe Text -> Ghc (Maybe Text)
forall a. a -> Ghc a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe Text -> Ghc (Maybe Text)) -> Maybe Text -> Ghc (Maybe Text)
forall a b. (a -> b) -> a -> b
$ Text -> Maybe Text
forall a. a -> Maybe a
Just (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ String -> Text
T.pack (DynFlags -> SDoc -> String
showSDoc DynFlags
df (SDoc -> String) -> SDoc -> String
forall a b. (a -> b) -> a -> b
$ SDoc
kindDoc SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ SDoc
tyDoc)
doTypeCmd :: DynFlags -> Text -> Ghc (Maybe Text)
doTypeCmd :: GHCiLikeCmd
doTypeCmd DynFlags
dflags Text
arg = do
let (TcRnExprMode
emod, Text
expr) = Text -> (TcRnExprMode, Text)
parseExprMode Text
arg
Type
ty <- TcRnExprMode -> String -> Ghc Type
forall (m :: * -> *).
GhcMonad m =>
TcRnExprMode -> String -> m Type
GHC.exprType TcRnExprMode
emod (String -> Ghc Type) -> String -> Ghc Type
forall a b. (a -> b) -> a -> b
$ Text -> String
T.unpack Text
expr
let rawType :: Text
rawType = Text -> Text
T.strip (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ DynFlags -> SDoc -> String
showSDoc DynFlags
dflags (SDoc -> String) -> SDoc -> String
forall a b. (a -> b) -> a -> b
$ Type -> SDoc
pprSigmaType Type
ty
broken :: Bool
broken = (Char -> Bool) -> Text -> Bool
T.any (\Char
c -> Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'\r' Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'\n') Text
rawType
Maybe Text -> Ghc (Maybe Text)
forall a. a -> Ghc a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe Text -> Ghc (Maybe Text)) -> Maybe Text -> Ghc (Maybe Text)
forall a b. (a -> b) -> a -> b
$
Text -> Maybe Text
forall a. a -> Maybe a
Just (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$
if Bool
broken
then
String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$
DynFlags -> SDoc -> String
showSDoc DynFlags
dflags (SDoc -> String) -> SDoc -> String
forall a b. (a -> b) -> a -> b
$
String -> SDoc
forall doc. IsLine doc => String -> doc
text (Text -> String
T.unpack Text
expr)
SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ Int -> SDoc -> SDoc
nest Int
2 (SDoc
"::" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Type -> SDoc
pprSigmaType Type
ty)
else Text
expr Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" :: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
rawType Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"\n"
parseExprMode :: Text -> (TcRnExprMode, T.Text)
parseExprMode :: Text -> (TcRnExprMode, Text)
parseExprMode Text
rawArg = case (Char -> Bool) -> Text -> (Text, Text)
T.break Char -> Bool
isSpace Text
rawArg of
(Text
"+d", Text
rest) -> (TcRnExprMode
TM_Default, Text -> Text
T.strip Text
rest)
(Text, Text)
_ -> (TcRnExprMode
TM_Inst, Text
rawArg)
data GhciLikeCmdException = GhciLikeCmdNotImplemented
{ GhciLikeCmdException -> Text
ghciCmdName :: Text
, GhciLikeCmdException -> Text
ghciCmdArg :: Text
}
deriving (Typeable)
instance Show GhciLikeCmdException where
showsPrec :: Int -> GhciLikeCmdException -> String -> String
showsPrec Int
_ GhciLikeCmdNotImplemented{Text
$sel:ghciCmdName:GhciLikeCmdNotImplemented :: GhciLikeCmdException -> Text
$sel:ghciCmdArg:GhciLikeCmdNotImplemented :: GhciLikeCmdException -> Text
ghciCmdName :: Text
ghciCmdArg :: Text
..} =
String -> String -> String
showString String
"unknown command '"
(String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String -> String
showString (Text -> String
T.unpack Text
ghciCmdName)
(String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> String -> String
showChar Char
'\''
instance E.Exception GhciLikeCmdException
parseGhciLikeCmd :: Text -> Maybe (Text, Text)
parseGhciLikeCmd :: Text -> Maybe (Text, Text)
parseGhciLikeCmd Text
input = do
(Char
':', Text
rest) <- Text -> Maybe (Char, Text)
T.uncons (Text -> Maybe (Char, Text)) -> Text -> Maybe (Char, Text)
forall a b. (a -> b) -> a -> b
$ Text -> Text
T.stripStart Text
input
(Text, Text) -> Maybe (Text, Text)
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((Text, Text) -> Maybe (Text, Text))
-> (Text, Text) -> Maybe (Text, Text)
forall a b. (a -> b) -> a -> b
$ (Text -> Text) -> (Text, Text) -> (Text, Text)
forall b c d. (b -> c) -> (d, b) -> (d, c)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (d, b) (d, c)
second Text -> Text
T.strip ((Text, Text) -> (Text, Text)) -> (Text, Text) -> (Text, Text)
forall a b. (a -> b) -> a -> b
$ (Char -> Bool) -> Text -> (Text, Text)
T.break Char -> Bool
isSpace Text
rest