summaryrefslogtreecommitdiff
path: root/ghc
diff options
context:
space:
mode:
authorLorenzo Tabacchini <lortabac@gmx.com>2014-06-08 10:54:39 +0200
committerJoachim Breitner <mail@joachim-breitner.de>2014-06-13 08:01:26 -0700
commitce19d5079ea85d3190e837a1fc60000fbd82134d (patch)
treee3eb58a107197de2fb6db9c919265e519976c451 /ghc
parent632fcf1f90b65201500250d5d13617ba778e310a (diff)
downloadhaskell-ce19d5079ea85d3190e837a1fc60000fbd82134d.tar.gz
Fixes #95 :edit command should jump to the last error
Diffstat (limited to 'ghc')
-rw-r--r--ghc/GhciMonad.hs4
-rw-r--r--ghc/InteractiveUI.hs87
2 files changed, 64 insertions, 27 deletions
diff --git a/ghc/GhciMonad.hs b/ghc/GhciMonad.hs
index 8f429c53f0..22109c428d 100644
--- a/ghc/GhciMonad.hs
+++ b/ghc/GhciMonad.hs
@@ -33,6 +33,7 @@ import Outputable hiding (printForUser, printForUserPartWay)
import qualified Outputable
import Util
import DynFlags
+import FastString
import HscTypes
import SrcLoc
import Module
@@ -105,7 +106,8 @@ data GHCiState = GHCiState
-- help text to display to a user
short_help :: String,
- long_help :: String
+ long_help :: String,
+ lastErrorLocations :: IORef [(FastString, Int)]
}
type TickArray = Array Int [(BreakIndex,SrcSpan)]
diff --git a/ghc/InteractiveUI.hs b/ghc/InteractiveUI.hs
index 53ada93126..0a56799679 100644
--- a/ghc/InteractiveUI.hs
+++ b/ghc/InteractiveUI.hs
@@ -28,6 +28,7 @@ import Debugger
-- The GHC interface
import DynFlags
+import ErrUtils
import GhcMonad ( modifySession )
import qualified GHC
import GHC ( LoadHowMuch(..), Target(..), TargetId(..), InteractiveImport(..),
@@ -72,7 +73,7 @@ import Data.Array
import qualified Data.ByteString.Char8 as BS
import Data.Char
import Data.Function
-import Data.IORef ( IORef, readIORef, writeIORef )
+import Data.IORef ( IORef, modifyIORef, newIORef, readIORef, writeIORef )
import Data.List ( find, group, intercalate, intersperse, isPrefixOf, nub,
partition, sort, sortBy )
import Data.Maybe
@@ -104,7 +105,6 @@ import GHC.IO.Exception ( IOErrorType(InvalidArgument) )
import GHC.IO.Handle ( hFlushAll )
import GHC.TopHandler ( topHandler )
-
-----------------------------------------------------------------------------
data GhciSettings = GhciSettings {
@@ -380,6 +380,12 @@ interactiveUI config srcs maybe_exprs = do
$ dflags
GHC.setInteractiveDynFlags dflags'
+ lastErrLocationsRef <- liftIO $ newIORef []
+ progDynFlags <- GHC.getProgramDynFlags
+ _ <- GHC.setProgramDynFlags $
+ progDynFlags { log_action = ghciLogAction lastErrLocationsRef }
+
+
liftIO $ when (isNothing maybe_exprs) $ do
-- Only for GHCi (not runghc and ghc -e):
@@ -400,31 +406,46 @@ interactiveUI config srcs maybe_exprs = do
#endif
default_editor <- liftIO $ findEditor
-
startGHCi (runGHCi srcs maybe_exprs)
- GHCiState{ progname = default_progname,
- GhciMonad.args = default_args,
- prompt = defPrompt config,
- prompt2 = defPrompt2 config,
- stop = default_stop,
- editor = default_editor,
- options = [],
- line_number = 1,
- break_ctr = 0,
- breaks = [],
- tickarrays = emptyModuleEnv,
- ghci_commands = availableCommands config,
- last_command = Nothing,
- cmdqueue = [],
- remembered_ctx = [],
- transient_ctx = [],
- ghc_e = isJust maybe_exprs,
- short_help = shortHelpText config,
- long_help = fullHelpText config
+ GHCiState{ progname = default_progname,
+ GhciMonad.args = default_args,
+ prompt = defPrompt config,
+ prompt2 = defPrompt2 config,
+ stop = default_stop,
+ editor = default_editor,
+ options = [],
+ line_number = 1,
+ break_ctr = 0,
+ breaks = [],
+ tickarrays = emptyModuleEnv,
+ ghci_commands = availableCommands config,
+ last_command = Nothing,
+ cmdqueue = [],
+ remembered_ctx = [],
+ transient_ctx = [],
+ ghc_e = isJust maybe_exprs,
+ short_help = shortHelpText config,
+ long_help = fullHelpText config,
+ lastErrorLocations = lastErrLocationsRef
}
-
+
return ()
+resetLastErrorLocations :: GHCi ()
+resetLastErrorLocations = do
+ st <- getGHCiState
+ liftIO $ writeIORef (lastErrorLocations st) []
+
+ghciLogAction :: IORef [(FastString, Int)] -> LogAction
+ghciLogAction lastErrLocations dflags severity srcSpan style msg = do
+ defaultLogAction dflags severity srcSpan style msg
+ case severity of
+ SevError -> case srcSpan of
+ RealSrcSpan rsp -> modifyIORef lastErrLocations
+ (++ [(srcLocFile (realSrcSpanStart rsp), srcLocLine (realSrcSpanStart rsp))])
+ _ -> return ()
+ _ -> return ()
+
withGhcAppData :: (FilePath -> IO a) -> IO a -> IO a
withGhcAppData right left = do
either_dir <- tryIO (getAppUserDataDirectory "ghc")
@@ -1170,10 +1191,18 @@ editFile :: String -> InputT GHCi ()
editFile str =
do file <- if null str then lift chooseEditFile else expandPath str
st <- lift getGHCiState
+ errs <- liftIO $ readIORef $ lastErrorLocations st
let cmd = editor st
when (null cmd)
$ throwGhcException (CmdLineError "editor not set, use :set editor")
- code <- liftIO $ system (cmd ++ ' ':file)
+ lineOpt <- liftIO $ do
+ curFileErrs <- filterM (\(f, _) -> unpackFS f `sameFile` file) errs
+ return $ case curFileErrs of
+ (_, line):_ -> " +" ++ show line
+ _ -> ""
+ let cmdArgs = ' ':(file ++ lineOpt)
+ code <- liftIO $ system (cmd ++ cmdArgs)
+
when (code == ExitSuccess)
$ reloadModule ""
@@ -1364,6 +1393,7 @@ doLoad retain_context howmuch = do
-- the ModBreaks will have gone away.
lift discardActiveBreakPoints
+ lift resetLastErrorLocations
-- Enable buffering stdout and stderr as we're compiling. Keeping these
-- handles unbuffered will just slow the compilation down, especially when
-- compiling in parallel.
@@ -1388,7 +1418,6 @@ afterLoad ok retain_context = do
modulesLoadedMsg ok loaded_mods
lift $ setContextAfterLoad retain_context loaded_mod_summaries
-
setContextAfterLoad :: Bool -> [GHC.ModSummary] -> GHCi ()
setContextAfterLoad keep_ctxt [] = do
setContextKeepingPackageModules keep_ctxt []
@@ -3118,7 +3147,13 @@ expandPathIO p =
tilde <- getHomeDirectory -- will fail if HOME not defined
return (tilde ++ '/':d)
other ->
- return other
+ return other
+
+sameFile :: FilePath -> FilePath -> IO Bool
+sameFile path1 path2 = do
+ absPath1 <- canonicalizePath path1
+ absPath2 <- canonicalizePath path2
+ return $ absPath1 == absPath2
wantInterpretedModule :: GHC.GhcMonad m => String -> m Module
wantInterpretedModule str = wantInterpretedModuleName (GHC.mkModuleName str)