Merge branch 'release-5.6.0.0'

This commit is contained in:
Daniel Gröber 2016-07-10 23:43:30 +02:00
commit ddfd791679
44 changed files with 583 additions and 206 deletions

View File

@ -66,7 +66,6 @@ instance Binary a => GGBinary (K1 i a) where
#define GETSUM(WORD) GUARD(WORD) = (get :: Get WORD) >>= checkGetSum (fromIntegral size) #define GETSUM(WORD) GUARD(WORD) = (get :: Get WORD) >>= checkGetSum (fromIntegral size)
instance ( GSum a, GSum b instance ( GSum a, GSum b
, GGBinary a, GGBinary b
, SumSize a, SumSize b) => GGBinary (a :+: b) where , SumSize a, SumSize b) => GGBinary (a :+: b) where
ggput | PUTSUM(Word8) | PUTSUM(Word16) | PUTSUM(Word32) | PUTSUM(Word64) ggput | PUTSUM(Word8) | PUTSUM(Word16) | PUTSUM(Word32) | PUTSUM(Word64)
| otherwise = sizeError "encode" size | otherwise = sizeError "encode" size
@ -96,7 +95,7 @@ class GSum f where
getSum :: (Ord word, Num word, Bits word) => word -> word -> Get (f a) getSum :: (Ord word, Num word, Bits word) => word -> word -> Get (f a)
putSum :: (Num w, Bits w, Binary w) => w -> w -> f a -> Put putSum :: (Num w, Bits w, Binary w) => w -> w -> f a -> Put
instance (GSum a, GSum b, GGBinary a, GGBinary b) => GSum (a :+: b) where instance (GSum a, GSum b) => GSum (a :+: b) where
getSum !code !size | code < sizeL = L1 <$> getSum code sizeL getSum !code !size | code < sizeL = L1 <$> getSum code sizeL
| otherwise = R1 <$> getSum (code - sizeL) sizeR | otherwise = R1 <$> getSum (code - sizeL) sizeR
where where

View File

@ -7,12 +7,13 @@ import Language.Haskell.GhcMod.Flag
import Language.Haskell.GhcMod.Lang import Language.Haskell.GhcMod.Lang
import Language.Haskell.GhcMod.Monad import Language.Haskell.GhcMod.Monad
import Language.Haskell.GhcMod.Modules import Language.Haskell.GhcMod.Modules
import Language.Haskell.GhcMod.Types (defaultBrowseOpts)
-- | Printing necessary information for front-end booting. -- | Printing necessary information for front-end booting.
boot :: IOish m => GhcModT m String boot :: IOish m => GhcModT m String
boot = concat <$> sequence ms boot = concat <$> sequence ms
where where
ms = [modules False, languages, flags, concat <$> mapM (browse (BrowseOpts False False False)) preBrowsedModules] ms = [modules False, languages, flags, concat <$> mapM (browse defaultBrowseOpts) preBrowsedModules]
preBrowsedModules :: [String] preBrowsedModules :: [String]
preBrowsedModules = [ preBrowsedModules = [

View File

@ -1,3 +1,4 @@
{-# LANGUAGE CPP #-}
module Language.Haskell.GhcMod.Browse ( module Language.Haskell.GhcMod.Browse (
browse, browse,
BrowseOpts(..) BrowseOpts(..)
@ -11,6 +12,7 @@ import Data.List
import Data.Maybe import Data.Maybe
import FastString import FastString
import GHC import GHC
import HscTypes
import qualified GHC as G import qualified GHC as G
import Language.Haskell.GhcMod.Convert import Language.Haskell.GhcMod.Convert
import Language.Haskell.GhcMod.Doc (showPage, styleUnqualified) import Language.Haskell.GhcMod.Doc (showPage, styleUnqualified)
@ -24,6 +26,9 @@ import TyCon (isAlgTyCon)
import Type (dropForAlls, splitFunTy_maybe, mkFunTy, isPredTy) import Type (dropForAlls, splitFunTy_maybe, mkFunTy, isPredTy)
import Exception (ExceptionMonad, ghandle) import Exception (ExceptionMonad, ghandle)
import Prelude import Prelude
#if __GLASGOW_HASKELL__ >= 800
import PatSyn (pprPatSynType)
#endif
---------------------------------------------------------------- ----------------------------------------------------------------
@ -96,14 +101,20 @@ showExport opt minfo e = do
mqualified = (G.moduleNameString (G.moduleName $ G.nameModule e) ++ ".") `justIf` optBrowseQualified opt mqualified = (G.moduleNameString (G.moduleName $ G.nameModule e) ++ ".") `justIf` optBrowseQualified opt
mtype :: m (Maybe String) mtype :: m (Maybe String)
mtype mtype
| optBrowseDetailed opt = do | optBrowseDetailed opt || optBrowseParents opt = do
tyInfo <- G.modInfoLookupName minfo e tyInfo <- G.modInfoLookupName minfo e
-- If nothing found, load dependent module and lookup global -- If nothing found, load dependent module and lookup global
tyResult <- maybe (inOtherModule e) (return . Just) tyInfo tyResult <- maybe (inOtherModule e) (return . Just) tyInfo
dflag <- G.getSessionDynFlags dflag <- G.getSessionDynFlags
return $ do let sig = do
typeName <- tyResult >>= showThing dflag typeName <- tyResult >>= showThing dflag
(" :: " ++ typeName) `justIf` optBrowseDetailed opt (" :: " ++ typeName) `justIf` optBrowseDetailed opt
let parent = do
thing <- fmap getOccString $ tyResult >>= tyThingParent_maybe
(" -- from:" ++ thing) `justIf` optBrowseParents opt
return $ case concat $ catMaybes [sig, parent] of
[] -> Nothing
x -> Just x
| otherwise = return Nothing | otherwise = return Nothing
formatOp nm formatOp nm
| null nm = error "formatOp" | null nm = error "formatOp"
@ -124,6 +135,9 @@ showThing' dflag (GtA a) = Just $ formatType dflag a
showThing' _ (GtT t) = unwords . toList <$> tyType t showThing' _ (GtT t) = unwords . toList <$> tyType t
where where
toList t' = t' : getOccString t : map getOccString (G.tyConTyVars t) toList t' = t' : getOccString t : map getOccString (G.tyConTyVars t)
#if __GLASGOW_HASKELL__ >= 800
showThing' dflag (GtPatSyn p) = Just $ showSDoc dflag $ pprPatSynType p
#endif
showThing' _ _ = Nothing showThing' _ _ = Nothing
formatType :: DynFlags -> Type -> String formatType :: DynFlags -> Type -> String

View File

@ -29,6 +29,7 @@ import Language.Haskell.GhcMod.Logging
import Language.Haskell.GhcMod.Types import Language.Haskell.GhcMod.Types
import Language.Haskell.GhcMod.Utils (withMappedFile) import Language.Haskell.GhcMod.Utils (withMappedFile)
import Language.Haskell.GhcMod.FileMapping (fileModSummaryWithMapping) import Language.Haskell.GhcMod.FileMapping (fileModSummaryWithMapping)
import Control.DeepSeq
---------------------------------------------------------------- ----------------------------------------------------------------
-- CASE SPLITTING -- CASE SPLITTING
@ -55,19 +56,17 @@ splits file lineNo colNo =
style <- getStyle style <- getStyle
dflag <- G.getSessionDynFlags dflag <- G.getSessionDynFlags
modSum <- fileModSummaryWithMapping (cradleCurrentDir crdl </> file) modSum <- fileModSummaryWithMapping (cradleCurrentDir crdl </> file)
whenFound' oopts (getSrcSpanTypeForSplit modSum lineNo colNo) $ \x -> case x of whenFound' oopts (getSrcSpanTypeForSplit modSum lineNo colNo) $ \x -> do
(SplitInfo varName bndLoc (varLoc,varT) _matches) -> do let (varName, bndLoc, (varLoc,varT))
let varName' = showName dflag style varName -- Convert name to string | (SplitInfo vn bl vlvt _matches) <- x
= (vn, bl, vlvt)
| (TySplitInfo vn bl vlvt) <- x
= (vn, bl, vlvt)
varName' = showName dflag style varName -- Convert name to string
t <- withMappedFile file $ \file' -> t <- withMappedFile file $ \file' ->
genCaseSplitTextFile file' (SplitToTextInfo varName' bndLoc varLoc $ genCaseSplitTextFile file' (SplitToTextInfo varName' bndLoc varLoc $
getTyCons dflag style varName varT) getTyCons dflag style varName varT)
return (fourInts bndLoc, t) return $!! (fourInts bndLoc, t)
(TySplitInfo varName bndLoc (varLoc,varT)) -> do
let varName' = showName dflag style varName -- Convert name to string
t <- withMappedFile file $ \file' ->
genCaseSplitTextFile file' (SplitToTextInfo varName' bndLoc varLoc $
getTyCons dflag style varName varT)
return (fourInts bndLoc, t)
where where
handler (SomeException ex) = do handler (SomeException ex) = do
gmLog GmException "splits" $ gmLog GmException "splits" $
@ -110,7 +109,11 @@ isPatternVar (L _ (G.VarPat _)) = True
isPatternVar _ = False isPatternVar _ = False
getPatternVarName :: LPat Id -> G.Name getPatternVarName :: LPat Id -> G.Name
#if __GLASGOW_HASKELL__ >= 800
getPatternVarName (L _ (G.VarPat (L _ vName))) = G.getName vName
#else
getPatternVarName (L _ (G.VarPat vName)) = G.getName vName getPatternVarName (L _ (G.VarPat vName)) = G.getName vName
#endif
getPatternVarName _ = error "This should never happened" getPatternVarName _ = error "This should never happened"
-- TODO: Information for a type family case split -- TODO: Information for a type family case split
@ -170,7 +173,11 @@ getDataCon dflag style vName dcon | [] <- Ty.dataConFieldLabels dcon =
-- 3. Records -- 3. Records
getDataCon dflag style vName dcon = getDataCon dflag style vName dcon =
let dName = showName dflag style $ Ty.dataConName dcon let dName = showName dflag style $ Ty.dataConName dcon
#if __GLASGOW_HASKELL__ >= 800
flds = map Ty.flSelector $ Ty.dataConFieldLabels dcon
#else
flds = Ty.dataConFieldLabels dcon flds = Ty.dataConFieldLabels dcon
#endif
in dName ++ " { " ++ showFieldNames dflag style vName flds ++ " }" in dName ++ " { " ++ showFieldNames dflag style vName flds ++ " }"
-- Create a new variable by adjoining a number -- Create a new variable by adjoining a number
@ -207,8 +214,8 @@ genCaseSplitTextFile file info = liftIO $ do
return $ getCaseSplitText (T.lines t) info return $ getCaseSplitText (T.lines t) info
getCaseSplitText :: [T.Text] -> SplitToTextInfo -> String getCaseSplitText :: [T.Text] -> SplitToTextInfo -> String
getCaseSplitText t (SplitToTextInfo { sVarName = sVN, sBindingSpan = sBS getCaseSplitText t SplitToTextInfo{ sVarName = sVN, sBindingSpan = sBS
, sVarSpan = sVS, sTycons = sT }) = , sVarSpan = sVS, sTycons = sT } =
let bindingText = getBindingText t sBS let bindingText = getBindingText t sBS
difference = srcSpanDifference sBS sVS difference = srcSpanDifference sBS sVS
replaced = map (replaceVarWithTyCon bindingText difference sVN) sT replaced = map (replaceVarWithTyCon bindingText difference sVN) sT

View File

@ -33,7 +33,7 @@ check files =
runGmlTWith runGmlTWith
(map Left files) (map Left files)
return return
((fmap fst <$>) . withLogger setNoMaxRelevantBindings) ((fmap fst <$>) . withLogger Gap.setNoMaxRelevantBindings)
(return ()) (return ())
---------------------------------------------------------------- ----------------------------------------------------------------

View File

@ -13,7 +13,7 @@
-- --
-- You should have received a copy of the GNU Affero General Public License -- You should have received a copy of the GNU Affero General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>. -- along with this program. If not, see <http://www.gnu.org/licenses/>.
{-# LANGUAGE CPP #-} {-# LANGUAGE CPP, RankNTypes #-}
module Language.Haskell.GhcMod.DebugLogger where module Language.Haskell.GhcMod.DebugLogger where
-- (c) The University of Glasgow 2005 -- (c) The University of Glasgow 2005
@ -62,27 +62,27 @@ import Language.Haskell.GhcMod.Gap
import Prelude import Prelude
debugLogAction :: (String -> IO ()) -> GmLogAction debugLogAction :: (String -> IO ()) -> GmLogAction
debugLogAction putErr dflags severity srcSpan style msg debugLogAction putErr _reason dflags severity srcSpan style' msg
= case severity of = case severity of
SevOutput -> printSDoc putErr msg style SevOutput -> printSDoc putErr msg style'
#if __GLASGOW_HASKELL__ >= 706 #if __GLASGOW_HASKELL__ >= 706
SevDump -> printSDoc putErr (msg Outputable.$$ blankLine) style SevDump -> printSDoc putErr (msg Outputable.$$ blankLine) style'
#endif #endif
#if __GLASGOW_HASKELL__ >= 708 #if __GLASGOW_HASKELL__ >= 708
SevInteractive -> let SevInteractive -> let
putStrSDoc = debugLogActionHPutStrDoc dflags putErr putStrSDoc = debugLogActionHPutStrDoc dflags putErr
in in
putStrSDoc msg style putStrSDoc msg style'
#endif #endif
SevInfo -> printErrs putErr msg style SevInfo -> printErrs putErr msg style'
SevFatal -> printErrs putErr msg style SevFatal -> printErrs putErr msg style'
_ -> do putErr "\n" _ -> do putErr "\n"
#if __GLASGOW_HASKELL__ >= 706 #if __GLASGOW_HASKELL__ >= 706
printErrs putErr (mkLocMessage severity srcSpan msg) style printErrs putErr (mkLocMessage severity srcSpan msg) style'
#else #else
printErrs putErr (mkLocMessage srcSpan msg) style printErrs putErr (mkLocMessage srcSpan msg) style'
#endif #endif
-- careful (#2302): printErrs prints in UTF-8, -- careful (#2302): printErrs prints in UTF-8,
-- whereas converting to string first and using -- whereas converting to string first and using

View File

@ -11,11 +11,6 @@ showPage dflag style = showDocWith dflag PageMode . withStyle dflag style
showOneLine :: DynFlags -> PprStyle -> SDoc -> String showOneLine :: DynFlags -> PprStyle -> SDoc -> String
showOneLine dflag style = showDocWith dflag OneLineMode . withStyle dflag style showOneLine dflag style = showDocWith dflag OneLineMode . withStyle dflag style
-- showForUser :: DynFlags -> PrintUnqualified -> SDoc -> String
-- showForUser dflags unqual sdoc =
-- showDocWith dflags PageMode $
-- runSDoc sdoc $ initSDocContext dflags $ mkUserStyle unqual AllTheWay
getStyle :: GhcMonad m => m PprStyle getStyle :: GhcMonad m => m PprStyle
getStyle = do getStyle = do
unqual <- getPrintUnqual unqual <- getPrintUnqual

View File

@ -1,4 +1,4 @@
{-# LANGUAGE CPP, TemplateHaskell #-} {-# LANGUAGE TemplateHaskell #-}
module Language.Haskell.GhcMod.DynFlags where module Language.Haskell.GhcMod.DynFlags where
@ -16,7 +16,7 @@ import Prelude
setEmptyLogger :: DynFlags -> DynFlags setEmptyLogger :: DynFlags -> DynFlags
setEmptyLogger df = setEmptyLogger df =
Gap.setLogAction df $ \_ _ _ _ _ -> return () Gap.setLogAction df $ \_ _ _ _ _ _ -> return ()
setDebugLogger :: (String -> IO ()) -> DynFlags -> DynFlags setDebugLogger :: (String -> IO ()) -> DynFlags -> DynFlags
setDebugLogger put df = do setDebugLogger put df = do
@ -95,14 +95,6 @@ allWarningFlags = unsafePerformIO $
---------------------------------------------------------------- ----------------------------------------------------------------
-- | Set 'DynFlags' equivalent to "-fno-max-relevant-bindings".
setNoMaxRelevantBindings :: DynFlags -> DynFlags
#if __GLASGOW_HASKELL__ >= 708
setNoMaxRelevantBindings df = df { maxRelevantBinds = Nothing }
#else
setNoMaxRelevantBindings = id
#endif
deferErrors :: Monad m => DynFlags -> m DynFlags deferErrors :: Monad m => DynFlags -> m DynFlags
deferErrors df = return $ deferErrors df = return $
Gap.setWarnTypedHoles $ Gap.setDeferTypedHoles $ Gap.setWarnTypedHoles $ Gap.setDeferTypedHoles $

View File

@ -27,7 +27,12 @@ import Prelude
deriveEqDynFlags :: Q [Dec] -> Q [Dec] deriveEqDynFlags :: Q [Dec] -> Q [Dec]
deriveEqDynFlags qds = do deriveEqDynFlags qds = do
~(TyConI (DataD [] _ [] [ctor] _ )) <- reify ''DynFlags #if __GLASGOW_HASKELL__ <= 710
~(TyConI (DataD [] _ [] [ctor] _ ))
#else
~(TyConI (DataD [] _ [] _ [ctor] _ ))
#endif
<- reify ''DynFlags
let ~(RecC _ fs) = ctor let ~(RecC _ fs) = ctor
a <- newName "a" a <- newName "a"
@ -83,7 +88,7 @@ deriveEqDynFlags qds = do
|] |]
return $ AppE (AppE eqfn fa) fb return $ AppE (AppE eqfn fa) fb
#if __GLASGOW_HASKELL__ >= 710 #if __GLASGOW_HASKELL__ >= 710 && __GLASGOW_HASKELL__ < 800
"sigOf" -> do "sigOf" -> do
eqfn <- [| let eqfn NotSigOf NotSigOf = True eqfn <- [| let eqfn NotSigOf NotSigOf = True
eqfn (SigOf a') (SigOf b') = a' == b' eqfn (SigOf a') (SigOf b') = a' == b'

View File

@ -63,23 +63,22 @@ loadMappedFile' from to isTemp = do
let to' = makeRelative (cradleRootDir crdl) to let to' = makeRelative (cradleRootDir crdl) to
addMMappedFile cfn (FileMapping to' isTemp) addMMappedFile cfn (FileMapping to' isTemp)
mapFile :: (IOish m, GmState m, GhcMonad m, GmEnv m) => mapFile :: (IOish m, GmState m) => HscEnv -> Target -> m Target
HscEnv -> Target -> m Target
mapFile _ (Target tid@(TargetFile filePath _) taoc _) = do mapFile _ (Target tid@(TargetFile filePath _) taoc _) = do
mapping <- lookupMMappedFile filePath mapping <- lookupMMappedFile filePath
mkMappedTarget (Just filePath) tid taoc mapping return $ mkMappedTarget (Just filePath) tid taoc mapping
mapFile env (Target tid@(TargetModule moduleName) taoc _) = do mapFile env (Target tid@(TargetModule moduleName) taoc _) = do
(fp, mapping) <- do (fp, mapping) <- do
filePath <- fmap (fmap mpPath) (liftIO $ findModulePath env moduleName) filePath <- fmap (fmap mpPath) (liftIO $ findModulePath env moduleName)
mmf <- runMaybeT $ MaybeT (return filePath) >>= MaybeT . lookupMMappedFile mmf <- runMaybeT $ MaybeT (return filePath) >>= MaybeT . lookupMMappedFile
return (filePath, mmf) return (filePath, mmf)
mkMappedTarget fp tid taoc mapping return $ mkMappedTarget fp tid taoc mapping
mkMappedTarget :: (IOish m, GmState m, GmEnv m, GhcMonad m) => mkMappedTarget :: Maybe FilePath -> TargetId -> Bool -> Maybe FileMapping -> Target
Maybe FilePath -> TargetId -> Bool -> Maybe FileMapping -> m Target
mkMappedTarget _ _ taoc (Just to) = mkMappedTarget _ _ taoc (Just to) =
return $ mkTarget (TargetFile (fmPath to) Nothing) taoc Nothing mkTarget (TargetFile (fmPath to) Nothing) taoc Nothing
mkMappedTarget _ tid taoc _ = return $ mkTarget tid taoc Nothing mkMappedTarget _ tid taoc _ =
mkTarget tid taoc Nothing
{-| {-|
unloads previously mapped file \'file\', so that it's no longer mapped, unloads previously mapped file \'file\', so that it's no longer mapped,

View File

@ -116,7 +116,9 @@ getSignature modSum lineNo colNo = do
p@ParsedModule{pm_parsed_source = ps} <- G.parseModule modSum p@ParsedModule{pm_parsed_source = ps} <- G.parseModule modSum
-- Inspect the parse tree to find the signature -- Inspect the parse tree to find the signature
case listifyParsedSpans ps (lineNo, colNo) :: [G.LHsDecl G.RdrName] of case listifyParsedSpans ps (lineNo, colNo) :: [G.LHsDecl G.RdrName] of
#if __GLASGOW_HASKELL__ >= 710 #if __GLASGOW_HASKELL__ >= 800
[L loc (G.SigD (Ty.TypeSig names (G.HsIB _ (G.HsWC _ _ (L _ ty)))))] ->
#elif __GLASGOW_HASKELL__ >= 710
[L loc (G.SigD (Ty.TypeSig names (L _ ty) _))] -> [L loc (G.SigD (Ty.TypeSig names (L _ ty) _))] ->
#else #else
[L loc (G.SigD (Ty.TypeSig names (L _ ty)))] -> [L loc (G.SigD (Ty.TypeSig names (L _ ty)))] ->
@ -131,7 +133,9 @@ getSignature modSum lineNo colNo = do
case Gap.getClass lst of case Gap.getClass lst of
Just (clsName,loc) -> obtainClassInfo minfo clsName loc Just (clsName,loc) -> obtainClassInfo minfo clsName loc
_ -> return Nothing _ -> return Nothing
#if __GLASGOW_HASKELL__ >= 708 #if __GLASGOW_HASKELL__ >= 800
[L loc (G.TyClD (G.FamDecl (G.FamilyDecl info (L _ name) (G.HsQTvs _ vars _) _ _)))] -> do
#elif __GLASGOW_HASKELL__ >= 708
[L loc (G.TyClD (G.FamDecl (G.FamilyDecl info (L _ name) (G.HsQTvs _ vars) _)))] -> do [L loc (G.TyClD (G.FamDecl (G.FamilyDecl info (L _ name) (G.HsQTvs _ vars) _)))] -> do
#elif __GLASGOW_HASKELL__ >= 706 #elif __GLASGOW_HASKELL__ >= 706
[L loc (G.TyClD (G.TyFamily info (L _ name) (G.HsQTvs _ vars) _))] -> do [L loc (G.TyClD (G.TyFamily info (L _ name) (G.HsQTvs _ vars) _))] -> do
@ -149,7 +153,11 @@ getSignature modSum lineNo colNo = do
G.DataFamily -> Data G.DataFamily -> Data
#endif #endif
#if __GLASGOW_HASKELL__ >= 710 #if __GLASGOW_HASKELL__ >= 800
getTyFamVarName x = case x of
L _ (G.UserTyVar (G.L _ n)) -> n
L _ (G.KindedTyVar (G.L _ n) _) -> n
#elif __GLASGOW_HASKELL__ >= 710
getTyFamVarName x = case x of getTyFamVarName x = case x of
L _ (G.UserTyVar n) -> n L _ (G.UserTyVar n) -> n
L _ (G.KindedTyVar (G.L _ n) _) -> n L _ (G.KindedTyVar (G.L _ n) _) -> n
@ -269,7 +277,9 @@ class FnArgsInfo ty name | ty -> name, name -> ty where
instance FnArgsInfo (G.HsType G.RdrName) (G.RdrName) where instance FnArgsInfo (G.HsType G.RdrName) (G.RdrName) where
getFnName dflag style name = showOccName dflag style $ Gap.occName name getFnName dflag style name = showOccName dflag style $ Gap.occName name
#if __GLASGOW_HASKELL__ >= 710 #if __GLASGOW_HASKELL__ >= 800
getFnArgs (G.HsForAllTy _ (L _ iTy))
#elif __GLASGOW_HASKELL__ >= 710
getFnArgs (G.HsForAllTy _ _ _ _ (L _ iTy)) getFnArgs (G.HsForAllTy _ _ _ _ (L _ iTy))
#else #else
getFnArgs (G.HsForAllTy _ _ _ (L _ iTy)) getFnArgs (G.HsForAllTy _ _ _ (L _ iTy))
@ -280,7 +290,9 @@ instance FnArgsInfo (G.HsType G.RdrName) (G.RdrName) where
getFnArgs (G.HsFunTy (L _ lTy) (L _ rTy)) = getFnArgs (G.HsFunTy (L _ lTy) (L _ rTy)) =
(if fnarg lTy then FnArgFunction else FnArgNormal):getFnArgs rTy (if fnarg lTy then FnArgFunction else FnArgNormal):getFnArgs rTy
where fnarg ty = case ty of where fnarg ty = case ty of
#if __GLASGOW_HASKELL__ >= 710 #if __GLASGOW_HASKELL__ >= 800
(G.HsForAllTy _ (L _ iTy)) ->
#elif __GLASGOW_HASKELL__ >= 710
(G.HsForAllTy _ _ _ _ (L _ iTy)) -> (G.HsForAllTy _ _ _ _ (L _ iTy)) ->
#else #else
(G.HsForAllTy _ _ _ (L _ iTy)) -> (G.HsForAllTy _ _ _ (L _ iTy)) ->
@ -381,7 +393,11 @@ findVar
-> m (Maybe (SrcSpan, String, Type, Bool)) -> m (Maybe (SrcSpan, String, Type, Bool))
findVar dflag style tcm tcs lineNo colNo = findVar dflag style tcm tcs lineNo colNo =
case lst of case lst of
#if __GLASGOW_HASKELL__ >= 800
e@(L _ (G.HsVar (L _ i))):others -> do
#else
e@(L _ (G.HsVar i)):others -> do e@(L _ (G.HsVar i)):others -> do
#endif
tyInfo <- Gap.getType tcm e tyInfo <- Gap.getType tcm e
case tyInfo of case tyInfo of
Just (s, typ) Just (s, typ)
@ -409,7 +425,11 @@ doParen False s = s
doParen True s = if ' ' `elem` s then '(':s ++ ")" else s doParen True s = if ' ' `elem` s then '(':s ++ ")" else s
isSearchedVar :: Id -> G.HsExpr Id -> Bool isSearchedVar :: Id -> G.HsExpr Id -> Bool
#if __GLASGOW_HASKELL__ >= 800
isSearchedVar i (G.HsVar (L _ i2)) = i == i2
#else
isSearchedVar i (G.HsVar i2) = i == i2 isSearchedVar i (G.HsVar i2) = i == i2
#endif
isSearchedVar _ _ = False isSearchedVar _ _ = False
@ -512,7 +532,11 @@ getPatsForVariable tcs (lineNo, colNo) =
_ -> (error "This should never happen", []) _ -> (error "This should never happen", [])
getBindingsForPat :: Ty.Pat Id -> M.Map G.Name Type getBindingsForPat :: Ty.Pat Id -> M.Map G.Name Type
#if __GLASGOW_HASKELL__ >= 800
getBindingsForPat (Ty.VarPat (L _ i)) = M.singleton (G.getName i) (Ty.varType i)
#else
getBindingsForPat (Ty.VarPat i) = M.singleton (G.getName i) (Ty.varType i) getBindingsForPat (Ty.VarPat i) = M.singleton (G.getName i) (Ty.varType i)
#endif
getBindingsForPat (Ty.LazyPat (L _ l)) = getBindingsForPat l getBindingsForPat (Ty.LazyPat (L _ l)) = getBindingsForPat l
getBindingsForPat (Ty.BangPat (L _ b)) = getBindingsForPat b getBindingsForPat (Ty.BangPat (L _ b)) = getBindingsForPat b
getBindingsForPat (Ty.AsPat (L _ a) (L _ i)) = getBindingsForPat (Ty.AsPat (L _ a) (L _ i)) =
@ -537,11 +561,23 @@ getBindingsForPat (Ty.ConPatOut { Ty.pat_args = d }) = getBindingsForRecPat d
getBindingsForPat _ = M.empty getBindingsForPat _ = M.empty
getBindingsForRecPat :: Ty.HsConPatDetails Id -> M.Map G.Name Type getBindingsForRecPat :: Ty.HsConPatDetails Id -> M.Map G.Name Type
#if __GLASGOW_HASKELL__ >= 800
getBindingsForRecPat (G.PrefixCon args) =
#else
getBindingsForRecPat (Ty.PrefixCon args) = getBindingsForRecPat (Ty.PrefixCon args) =
#endif
M.unions $ map (\(L _ i) -> getBindingsForPat i) args M.unions $ map (\(L _ i) -> getBindingsForPat i) args
#if __GLASGOW_HASKELL__ >= 800
getBindingsForRecPat (G.InfixCon (L _ a1) (L _ a2)) =
#else
getBindingsForRecPat (Ty.InfixCon (L _ a1) (L _ a2)) = getBindingsForRecPat (Ty.InfixCon (L _ a1) (L _ a2)) =
#endif
M.union (getBindingsForPat a1) (getBindingsForPat a2) M.union (getBindingsForPat a1) (getBindingsForPat a2)
#if __GLASGOW_HASKELL__ >= 800
getBindingsForRecPat (G.RecCon (Ty.HsRecFields { Ty.rec_flds = fields })) =
#else
getBindingsForRecPat (Ty.RecCon (Ty.HsRecFields { Ty.rec_flds = fields })) = getBindingsForRecPat (Ty.RecCon (Ty.HsRecFields { Ty.rec_flds = fields })) =
#endif
getBindingsForRecFields (map unLoc' fields) getBindingsForRecFields (map unLoc' fields)
where where
#if __GLASGOW_HASKELL__ >= 710 #if __GLASGOW_HASKELL__ >= 710

View File

@ -72,7 +72,16 @@ data SymbolDb = SymbolDb
, sdTimestamp :: ModTime , sdTimestamp :: ModTime
} deriving (Generic) } deriving (Generic)
#if __GLASGOW_HASKELL__ >= 708
instance Binary SymbolDb instance Binary SymbolDb
#else
instance Binary SymbolDb where
put (SymbolDb a b) = put a >> put b
get = do
a <- get
b <- get
return (SymbolDb a b)
#endif
instance NFData SymbolDb instance NFData SymbolDb
isOutdated :: IOish m => SymbolDb -> GhcModT m Bool isOutdated :: IOish m => SymbolDb -> GhcModT m Bool

View File

@ -4,10 +4,6 @@ import qualified Language.Haskell.GhcMod.Gap as Gap
import Language.Haskell.GhcMod.Convert import Language.Haskell.GhcMod.Convert
import Language.Haskell.GhcMod.Monad import Language.Haskell.GhcMod.Monad
-- | Listing GHC flags. (e.g -fno-warn-orphans) -- | Listing of GHC flags, same as @ghc@\'s @--show-options@ with @ghc >= 7.10@.
flags :: IOish m => GhcModT m String flags :: IOish m => GhcModT m String
flags = convert' [ "-f" ++ prefix ++ option flags = convert' Gap.ghcCmdOptions
| option <- Gap.fOptions
, prefix <- ["","no-"]
]

View File

@ -9,7 +9,7 @@ module Language.Haskell.GhcMod.Gap (
, getSrcSpan , getSrcSpan
, getSrcFile , getSrcFile
, withInteractiveContext , withInteractiveContext
, fOptions , ghcCmdOptions
, toStringBuffer , toStringBuffer
, showSeverityCaption , showSeverityCaption
, setCabalPkg , setCabalPkg
@ -18,12 +18,14 @@ module Language.Haskell.GhcMod.Gap (
, setDeferTypedHoles , setDeferTypedHoles
, setWarnTypedHoles , setWarnTypedHoles
, setDumpSplices , setDumpSplices
, setNoMaxRelevantBindings
, isDumpSplices , isDumpSplices
, filterOutChildren , filterOutChildren
, infoThing , infoThing
, pprInfo , pprInfo
, HasType(..) , HasType(..)
, errorMsgSpan , errorMsgSpan
, setErrorMsgSpan
, typeForUser , typeForUser
, nameForUser , nameForUser
, occNameForUser , occNameForUser
@ -44,6 +46,7 @@ module Language.Haskell.GhcMod.Gap (
, Language.Haskell.GhcMod.Gap.isSynTyCon , Language.Haskell.GhcMod.Gap.isSynTyCon
, parseModuleHeader , parseModuleHeader
, mkErrStyle' , mkErrStyle'
, everythingStagedWithContext
) where ) where
import Control.Applicative hiding (empty) import Control.Applicative hiding (empty)
@ -82,7 +85,7 @@ import CoAxiom (coAxiomTyCon)
#if __GLASGOW_HASKELL__ >= 708 #if __GLASGOW_HASKELL__ >= 708
import FamInstEnv import FamInstEnv
import ConLike (ConLike(..)) import ConLike (ConLike(..))
import PatSyn (patSynType) import PatSyn
#else #else
import TcRnTypes import TcRnTypes
#endif #endif
@ -115,6 +118,8 @@ import Lexer as L
import Parser import Parser
import SrcLoc import SrcLoc
import Packages import Packages
import Data.Generics (GenericQ, extQ, gmapQ)
import GHC.SYB.Utils (Stage(..))
import Language.Haskell.GhcMod.Types (Expression(..)) import Language.Haskell.GhcMod.Types (Expression(..))
import Prelude import Prelude
@ -145,22 +150,32 @@ withStyle = withPprStyleDoc
withStyle _ = withPprStyleDoc withStyle _ = withPprStyleDoc
#endif #endif
#if __GLASGOW_HASKELL__ >= 706 #if __GLASGOW_HASKELL__ >= 800
type GmLogAction = LogAction -- flip LogAction
type GmLogAction = WarnReason -> DynFlags -> Severity -> SrcSpan -> PprStyle -> MsgDoc -> IO ()
#elif __GLASGOW_HASKELL__ >= 706
type GmLogAction = forall a. a -> LogAction
#else #else
type GmLogAction = DynFlags -> LogAction type GmLogAction = forall a. a -> DynFlags -> LogAction
#endif #endif
-- DynFlags -> WarnReason -> Severity -> SrcSpan -> PprStyle -> MsgDoc -> IO ()
setLogAction :: DynFlags -> GmLogAction -> DynFlags setLogAction :: DynFlags -> GmLogAction -> DynFlags
setLogAction df f = setLogAction df f =
#if __GLASGOW_HASKELL__ >= 706 #if __GLASGOW_HASKELL__ >= 800
df { log_action = f } df { log_action = flip f }
#elif __GLASGOW_HASKELL__ >= 706
df { log_action = f (error "setLogAction") }
#else #else
df { log_action = f df } df { log_action = f (error "setLogAction") df }
#endif #endif
showDocWith :: DynFlags -> Pretty.Mode -> Pretty.Doc -> String showDocWith :: DynFlags -> Pretty.Mode -> Pretty.Doc -> String
#if __GLASGOW_HASKELL__ >= 708 #if __GLASGOW_HASKELL__ >= 800
showDocWith dflags mode = Pretty.renderStyle mstyle where
mstyle = Pretty.style { Pretty.mode = mode, Pretty.lineLength = pprCols dflags }
#elif __GLASGOW_HASKELL__ >= 708
-- Pretty.showDocWith disappeard. -- Pretty.showDocWith disappeard.
-- https://github.com/ghc/ghc/commit/08a3536e4246e323fbcd8040e0b80001950fe9bc -- https://github.com/ghc/ghc/commit/08a3536e4246e323fbcd8040e0b80001950fe9bc
showDocWith dflags mode = Pretty.showDoc mode (pprCols dflags) showDocWith dflags mode = Pretty.showDoc mode (pprCols dflags)
@ -202,19 +217,26 @@ toStringBuffer = liftIO . stringToStringBuffer . unlines
---------------------------------------------------------------- ----------------------------------------------------------------
fOptions :: [String] ghcCmdOptions :: [String]
#if __GLASGOW_HASKELL__ >= 710 #if __GLASGOW_HASKELL__ >= 710
fOptions = [option | (FlagSpec option _ _ _) <- fFlags] -- this also includes -X options and all sorts of other things so the
++ [option | (FlagSpec option _ _ _) <- fWarningFlags] ghcCmdOptions = flagsForCompletion False
++ [option | (FlagSpec option _ _ _) <- fLangFlags] #else
#elif __GLASGOW_HASKELL__ >= 704 ghcCmdOptions = [ "-f" ++ prefix ++ option
fOptions = [option | (option,_,_) <- fFlags] | option <- opts
, prefix <- ["","no-"]
]
# if __GLASGOW_HASKELL__ >= 704
where opts =
[option | (option,_,_) <- fFlags]
++ [option | (option,_,_) <- fWarningFlags] ++ [option | (option,_,_) <- fWarningFlags]
++ [option | (option,_,_) <- fLangFlags] ++ [option | (option,_,_) <- fLangFlags]
#else # else
fOptions = [option | (option,_,_,_) <- fFlags] where opts =
[option | (option,_,_,_) <- fFlags]
++ [option | (option,_,_,_) <- fWarningFlags] ++ [option | (option,_,_,_) <- fWarningFlags]
++ [option | (option,_,_,_) <- fLangFlags] ++ [option | (option,_,_,_) <- fLangFlags]
# endif
#endif #endif
---------------------------------------------------------------- ----------------------------------------------------------------
@ -316,6 +338,16 @@ setWarnTypedHoles dflag = wopt_set dflag Opt_WarnTypedHoles
setWarnTypedHoles = id setWarnTypedHoles = id
#endif #endif
----------------------------------------------------------------
-- | Set 'DynFlags' equivalent to "-fno-max-relevant-bindings".
setNoMaxRelevantBindings :: DynFlags -> DynFlags
#if __GLASGOW_HASKELL__ >= 708
setNoMaxRelevantBindings df = df { maxRelevantBinds = Nothing }
#else
setNoMaxRelevantBindings = id
#endif
---------------------------------------------------------------- ----------------------------------------------------------------
---------------------------------------------------------------- ----------------------------------------------------------------
@ -420,6 +452,13 @@ errorMsgSpan = errMsgSpan
errorMsgSpan = head . errMsgSpans errorMsgSpan = head . errMsgSpans
#endif #endif
setErrorMsgSpan :: ErrMsg -> SrcSpan -> ErrMsg
#if __GLASGOW_HASKELL__ >= 708
setErrorMsgSpan err s = err { errMsgSpan = s }
#else
setErrorMsgSpan err s = err { errMsgSpans = [s] }
#endif
typeForUser :: Type -> SDoc typeForUser :: Type -> SDoc
#if __GLASGOW_HASKELL__ >= 708 #if __GLASGOW_HASKELL__ >= 708
typeForUser = pprTypeForUser typeForUser = pprTypeForUser
@ -449,13 +488,22 @@ deSugar tcm e hs_env = snd <$> deSugarExpr hs_env modu rn_env ty_env e
---------------------------------------------------------------- ----------------------------------------------------------------
---------------------------------------------------------------- ----------------------------------------------------------------
data GapThing = GtA Type | GtT TyCon | GtN data GapThing = GtA Type
| GtT TyCon
| GtN
#if __GLASGOW_HASKELL__ >= 800
| GtPatSyn PatSyn
#endif
fromTyThing :: TyThing -> GapThing fromTyThing :: TyThing -> GapThing
fromTyThing (AnId i) = GtA $ varType i fromTyThing (AnId i) = GtA $ varType i
#if __GLASGOW_HASKELL__ >= 708 #if __GLASGOW_HASKELL__ >= 708
fromTyThing (AConLike (RealDataCon d)) = GtA $ dataConRepType d fromTyThing (AConLike (RealDataCon d)) = GtA $ dataConRepType d
#if __GLASGOW_HASKELL__ >= 800
fromTyThing (AConLike (PatSynCon p)) = GtPatSyn p
#else
fromTyThing (AConLike (PatSynCon p)) = GtA $ patSynType p fromTyThing (AConLike (PatSynCon p)) = GtA $ patSynType p
#endif
#else #else
fromTyThing (ADataCon d) = GtA $ dataConRepType d fromTyThing (ADataCon d) = GtA $ dataConRepType d
#endif #endif
@ -487,7 +535,12 @@ type GLMatchI = LMatch Id
#endif #endif
getClass :: [LInstDecl Name] -> Maybe (Name, SrcSpan) getClass :: [LInstDecl Name] -> Maybe (Name, SrcSpan)
#if __GLASGOW_HASKELL__ >= 710 #if __GLASGOW_HASKELL__ >= 800
-- Instance declarations of sort 'instance F (G a)'
getClass [L loc (ClsInstD (ClsInstDecl {cid_poly_ty = HsIB _ (L _ (HsForAllTy _ (L _ (HsAppTy (L _ (HsTyVar (L _ className))) _))))}))] = Just (className, loc)
-- Instance declarations of sort 'instance F G' (no variables)
getClass [L loc (ClsInstD (ClsInstDecl {cid_poly_ty = HsIB _ (L _ (HsAppTy (L _ (HsTyVar (L _ className))) _))}))] = Just (className, loc)
#elif __GLASGOW_HASKELL__ >= 710
-- Instance declarations of sort 'instance F (G a)' -- Instance declarations of sort 'instance F (G a)'
getClass [L loc (ClsInstD (ClsInstDecl {cid_poly_ty = (L _ (HsForAllTy _ _ _ _ (L _ (HsAppTy (L _ (HsTyVar className)) _))))}))] = Just (className, loc) getClass [L loc (ClsInstD (ClsInstDecl {cid_poly_ty = (L _ (HsForAllTy _ _ _ _ (L _ (HsAppTy (L _ (HsTyVar className)) _))))}))] = Just (className, loc)
-- Instance declarations of sort 'instance F G' (no variables) -- Instance declarations of sort 'instance F G' (no variables)
@ -595,3 +648,20 @@ instance NFData ByteString where
rnf Empty = () rnf Empty = ()
rnf (Chunk _ b) = rnf b rnf (Chunk _ b) = rnf b
#endif #endif
-- | Like 'everything', but avoid known potholes, based on the 'Stage' that
-- generated the Ast.
everythingStagedWithContext :: Stage -> s -> (r -> r -> r) -> r -> GenericQ (s -> (r, s)) -> GenericQ r
everythingStagedWithContext stage s0 f z q x
| (const False
#if __GLASGOW_HASKELL__ <= 708
`extQ` postTcType
#endif
`extQ` fixity `extQ` nameSet) x = z
| otherwise = foldl f r (gmapQ (everythingStagedWithContext stage s' f z q) x)
where nameSet = const (stage `elem` [Parser,TypeChecker]) :: NameSet -> Bool
#if __GLASGOW_HASKELL__ <= 708
postTcType = const (stage<TypeChecker) :: PostTcType -> Bool
#endif
fixity = const (stage<Renamer) :: GHC.Fixity -> Bool
(r, s') = q x s0

View File

@ -5,10 +5,9 @@ module Language.Haskell.GhcMod.Info (
import Data.Function (on) import Data.Function (on)
import Data.List (sortBy) import Data.List (sortBy)
import Data.Maybe (catMaybes)
import System.FilePath import System.FilePath
import Exception (ghandle, SomeException(..)) import Exception (ghandle, SomeException(..))
import GHC (GhcMonad, LHsBind, LHsExpr, LPat, Id, TypecheckedModule(..), SrcSpan, Type) import GHC (GhcMonad, SrcSpan)
import Prelude import Prelude
import qualified GHC as G import qualified GHC as G
import qualified Language.Haskell.GhcMod.Gap as Gap import qualified Language.Haskell.GhcMod.Gap as Gap
@ -53,17 +52,18 @@ info file expr =
-- | Obtaining type of a target expression. (GHCi's type:) -- | Obtaining type of a target expression. (GHCi's type:)
types :: IOish m types :: IOish m
=> FilePath -- ^ A target file. => Bool -- ^ Include constraints into type signature
-> FilePath -- ^ A target file.
-> Int -- ^ Line number. -> Int -- ^ Line number.
-> Int -- ^ Column number. -> Int -- ^ Column number.
-> GhcModT m String -> GhcModT m String
types file lineNo colNo = types withConstraints file lineNo colNo =
ghandle handler $ ghandle handler $
runGmlT' [Left file] deferErrors $ runGmlT' [Left file] deferErrors $
withInteractiveContext $ do withInteractiveContext $ do
crdl <- cradle crdl <- cradle
modSum <- fileModSummaryWithMapping (cradleCurrentDir crdl </> file) modSum <- fileModSummaryWithMapping (cradleCurrentDir crdl </> file)
srcSpanTypes <- getSrcSpanType modSum lineNo colNo srcSpanTypes <- getSrcSpanType withConstraints modSum lineNo colNo
dflag <- G.getSessionDynFlags dflag <- G.getSessionDynFlags
st <- getStyle st <- getStyle
convert' $ map (toTup dflag st) $ sortBy (cmp `on` fst) srcSpanTypes convert' $ map (toTup dflag st) $ sortBy (cmp `on` fst) srcSpanTypes
@ -72,14 +72,8 @@ types file lineNo colNo =
gmLog GmException "types" $ showDoc ex gmLog GmException "types" $ showDoc ex
return [] return []
getSrcSpanType :: GhcMonad m => G.ModSummary -> Int -> Int -> m [(SrcSpan, Type)] getSrcSpanType :: (GhcMonad m) => Bool -> G.ModSummary -> Int -> Int -> m [(SrcSpan, G.Type)]
getSrcSpanType modSum lineNo colNo = do getSrcSpanType withConstraints modSum lineNo colNo =
p <- G.parseModule modSum G.parseModule modSum
tcm@TypecheckedModule{tm_typechecked_source = tcs} <- G.typecheckModule p >>= G.typecheckModule
let bs = listifySpans tcs (lineNo, colNo) :: [LHsBind Id] >>= flip (collectSpansTypes withConstraints) (lineNo, colNo)
es = listifySpans tcs (lineNo, colNo) :: [LHsExpr Id]
ps = listifySpans tcs (lineNo, colNo) :: [LPat Id]
bts <- mapM (getType tcm) bs
ets <- mapM (getType tcm) es
pts <- mapM (getType tcm) ps
return $ catMaybes $ concat [ets, bts, pts]

View File

@ -9,7 +9,7 @@ import Language.Haskell.GhcMod.Monad
import Language.Haskell.HLint3 import Language.Haskell.HLint3
import Language.Haskell.GhcMod.Utils (withMappedFile) import Language.Haskell.GhcMod.Utils (withMappedFile)
import Language.Haskell.Exts.Pretty (prettyPrint) import Language.Haskell.Exts.SrcLoc (SrcLoc(..))
import System.IO import System.IO
-- | Checking syntax of a target file using hlint. -- | Checking syntax of a target file using hlint.
@ -27,7 +27,8 @@ lint opt file = ghandle handler $
case res of case res of
Right m -> pack . map show $ applyHints classify hint [m] Right m -> pack . map show $ applyHints classify hint [m]
Left ParseError{parseErrorLocation=loc, parseErrorMessage=err} -> Left ParseError{parseErrorLocation=loc, parseErrorMessage=err} ->
return $ prettyPrint loc ++ ":Error:" ++ err ++ "\n" return $ showSrcLoc loc ++ ":Error:" ++ err ++ "\n"
where where
pack = convert' . map init -- init drops the last \n. pack = convert' . map init -- init drops the last \n.
handler (SomeException e) = return $ checkErrorPrefix ++ show e ++ "\n" handler (SomeException e) = return $ checkErrorPrefix ++ show e ++ "\n"
showSrcLoc (SrcLoc f l c) = concat [f, ":", show l, ":", show c]

View File

@ -1,3 +1,5 @@
{-# LANGUAGE CPP, RankNTypes #-}
module Language.Haskell.GhcMod.Logger ( module Language.Haskell.GhcMod.Logger (
withLogger withLogger
, withLogger' , withLogger'
@ -12,7 +14,7 @@ import Data.Ord
import Data.List import Data.List
import Data.Maybe import Data.Maybe
import Data.Function import Data.Function
import Control.Monad.Reader (Reader, asks, runReader) import Control.Monad.Reader (Reader, ask, runReader)
import Data.IORef (IORef, newIORef, readIORef, writeIORef, modifyIORef) import Data.IORef (IORef, newIORef, readIORef, writeIORef, modifyIORef)
import System.FilePath (normalise) import System.FilePath (normalise)
import Text.PrettyPrint import Text.PrettyPrint
@ -23,6 +25,8 @@ import HscTypes
import Outputable import Outputable
import qualified GHC as G import qualified GHC as G
import Bag import Bag
import SrcLoc
import FastString
import Language.Haskell.GhcMod.Convert import Language.Haskell.GhcMod.Convert
import Language.Haskell.GhcMod.Doc (showPage) import Language.Haskell.GhcMod.Doc (showPage)
@ -57,15 +61,13 @@ readAndClearLogRef (LogRef ref) = do
writeIORef ref emptyLog writeIORef ref emptyLog
return $ b [] return $ b []
appendLogRef :: (FilePath -> FilePath) -> DynFlags -> LogRef -> DynFlags -> Severity -> SrcSpan -> PprStyle -> SDoc -> IO () appendLogRef :: (FilePath -> FilePath) -> DynFlags -> LogRef -> Gap.GmLogAction
appendLogRef rfm df (LogRef ref) _ sev src st msg = do appendLogRef map_file df (LogRef ref) _reason _df sev src st msg = do
modifyIORef ref update modifyIORef ref update
where where
gpe = GmPprEnv { -- TODO: get rid of ppMsg and just do more or less what ghc's
gpeDynFlags = df -- defaultLogAction does
, gpeMapFile = rfm l = ppMsg map_file df st src sev msg
}
l = runReader (ppMsg st src sev msg) gpe
update lg@(Log ls b) update lg@(Log ls b)
| l `elem` ls = lg | l `elem` ls = lg
@ -132,38 +134,51 @@ sortMsgBag bag = sortBy (compare `on` Gap.errorMsgSpan) $ bagToList bag
ppErrMsg :: ErrMsg -> GmPprEnvM String ppErrMsg :: ErrMsg -> GmPprEnvM String
ppErrMsg err = do ppErrMsg err = do
dflags <- asks gpeDynFlags GmPprEnv {..} <- ask
let unqual = errMsgContext err let unqual = errMsgContext err
st = Gap.mkErrStyle' dflags unqual st = Gap.mkErrStyle' gpeDynFlags unqual
let ext = showPage dflags st (errMsgExtraInfo err) err' = Gap.setErrorMsgSpan err $ mapSrcSpanFile gpeMapFile (Gap.errorMsgSpan err)
m <- ppMsg st spn SevError msg return $ showPage gpeDynFlags st $ pprLocErrMsg err'
return $ m ++ (if null ext then "" else "\n" ++ ext)
where
spn = Gap.errorMsgSpan err
msg = errMsgShortDoc err
ppMsg :: PprStyle -> SrcSpan -> Severity -> SDoc -> GmPprEnvM String mapSrcSpanFile :: (FilePath -> FilePath) -> SrcSpan -> SrcSpan
ppMsg st spn sev msg = do mapSrcSpanFile map_file (RealSrcSpan s) =
dflags <- asks gpeDynFlags RealSrcSpan $ mapRealSrcSpanFile map_file s
let cts = showPage dflags st msg mapSrcSpanFile _ (UnhelpfulSpan s) =
prefix <- ppMsgPrefix spn sev cts UnhelpfulSpan s
return $ prefix ++ cts
ppMsgPrefix :: SrcSpan -> Severity -> String -> GmPprEnvM String mapRealSrcSpanFile :: (FilePath -> FilePath) -> RealSrcSpan -> RealSrcSpan
ppMsgPrefix spn sev cts = do mapRealSrcSpanFile map_file s = let
dflags <- asks gpeDynFlags start = mapRealSrcLocFile map_file $ realSrcSpanStart s
mr <- asks gpeMapFile end = mapRealSrcLocFile map_file $ realSrcSpanEnd s
let defaultPrefix in
| Gap.isDumpSplices dflags = "" mkRealSrcSpan start end
| otherwise = checkErrorPrefix
return $ fromMaybe defaultPrefix $ do mapRealSrcLocFile :: (FilePath -> FilePath) -> RealSrcLoc -> RealSrcLoc
(line,col,_,_) <- Gap.getSrcSpan spn mapRealSrcLocFile map_file l = let
file <- mr <$> normalise <$> Gap.getSrcFile spn file = mkFastString $ map_file $ unpackFS $ srcLocFile l
let severityCaption = Gap.showSeverityCaption sev line = srcLocLine l
pref0 | or (map (\x -> x `isPrefixOf` cts) warningAsErrorPrefixes) col = srcLocCol l
= file ++ ":" ++ show line ++ ":" ++ show col ++ ":" in
| otherwise = file ++ ":" ++ show line ++ ":" ++ show col ++ ":" ++ severityCaption mkRealSrcLoc file line col
return pref0
ppMsg :: (FilePath -> FilePath) -> DynFlags -> PprStyle -> SrcSpan -> Severity -> SDoc -> String
ppMsg map_file df st spn sev msg = let
cts = showPage df st msg
in
ppMsgPrefix map_file df spn sev cts ++ cts
ppMsgPrefix :: (FilePath -> FilePath) -> DynFlags -> SrcSpan -> Severity -> String -> String
ppMsgPrefix map_file df spn sev cts =
let
defaultPrefix = if Gap.isDumpSplices df then "" else checkErrorPrefix
in
fromMaybe defaultPrefix $ do
(line,col,_,_) <- Gap.getSrcSpan spn
file <- map_file <$> normalise <$> Gap.getSrcFile spn
return $ file ++ ":" ++ show line ++ ":" ++ show col ++ ":" ++
if or (map (\x -> x `isPrefixOf` cts) warningAsErrorPrefixes)
then ""
else Gap.showSeverityCaption sev
checkErrorPrefix :: String checkErrorPrefix :: String
checkErrorPrefix = "Dummy:0:0:Error:" checkErrorPrefix = "Dummy:0:0:Error:"

View File

@ -103,7 +103,7 @@ runGmOutT opts ma = do
(const $ liftIO $ flushStdoutGateway gmoChan) (const $ liftIO $ flushStdoutGateway gmoChan)
action action
runGmOutT' :: IOish m => GhcModOut -> GmOutT m a -> m a runGmOutT' :: GhcModOut -> GmOutT m a -> m a
runGmOutT' gmo ma = flip runReaderT gmo $ unGmOutT ma runGmOutT' gmo ma = flip runReaderT gmo $ unGmOutT ma
-- | Run a @GhcModT m@ computation. -- | Run a @GhcModT m@ computation.

View File

@ -124,7 +124,7 @@ instance MonadTrans GmlT where
-- GmT ------------------------------------------ -- GmT ------------------------------------------
instance forall r m. MonadReader r m => MonadReader r (GmT m) where instance MonadReader r m => MonadReader r (GmT m) where
local f ma = gmLiftWithInner (\run -> local f (run ma)) local f ma = gmLiftWithInner (\run -> local f (run ma))
ask = gmLiftInner ask ask = gmLiftInner ask

View File

@ -1,4 +1,5 @@
{-# LANGUAGE TupleSections, FlexibleInstances, Rank2Types #-} -- TODO: remove CPP once Gap(ed)
{-# LANGUAGE CPP, TupleSections, FlexibleInstances, Rank2Types #-}
{-# OPTIONS_GHC -fno-warn-orphans #-} {-# OPTIONS_GHC -fno-warn-orphans #-}
module Language.Haskell.GhcMod.SrcUtils where module Language.Haskell.GhcMod.SrcUtils where
@ -6,11 +7,14 @@ module Language.Haskell.GhcMod.SrcUtils where
import Control.Applicative import Control.Applicative
import CoreUtils (exprType) import CoreUtils (exprType)
import Data.Generics import Data.Generics
import Data.Maybe (fromMaybe) import Data.Maybe
import Data.Ord as O import Data.Ord as O
import GHC (LHsExpr, LPat, Id, DynFlags, SrcSpan, Type, Located, ParsedSource, RenamedSource, TypecheckedSource, GenLocated(L)) import GHC (LHsExpr, LPat, Id, DynFlags, SrcSpan, Type, Located, ParsedSource, RenamedSource, TypecheckedSource, GenLocated(L))
import Var (Var)
import qualified GHC as G import qualified GHC as G
import GHC.SYB.Utils (Stage(..), everythingStaged) import qualified Var as G
import qualified Type as G
import GHC.SYB.Utils
import GhcMonad import GhcMonad
import qualified Language.Haskell.Exts.Annotated as HE import qualified Language.Haskell.Exts.Annotated as HE
import Language.Haskell.GhcMod.Doc import Language.Haskell.GhcMod.Doc
@ -20,6 +24,10 @@ import OccName (OccName)
import Outputable (PprStyle) import Outputable (PprStyle)
import TcHsSyn (hsPatType) import TcHsSyn (hsPatType)
import Prelude import Prelude
import Control.Monad
import Data.List (nub)
import Control.Arrow
import qualified Data.Map as M
---------------------------------------------------------------- ----------------------------------------------------------------
@ -34,6 +42,101 @@ instance HasType (LPat Id) where
---------------------------------------------------------------- ----------------------------------------------------------------
-- | Stores mapping from monomorphic to polymorphic types
type CstGenQS = M.Map Var Type
-- | Generic type to simplify SYB definition
type CstGenQT a = forall m. GhcMonad m => a Id -> CstGenQS -> (m [(SrcSpan, Type)], CstGenQS)
collectSpansTypes :: (GhcMonad m) => Bool -> G.TypecheckedModule -> (Int, Int) -> m [(SrcSpan, Type)]
collectSpansTypes withConstraints tcs lc =
-- This walks AST top-down, left-to-right, while carrying CstGenQS down the tree
-- (but not left-to-right)
everythingStagedWithContext TypeChecker M.empty (liftM2 (++))
(return [])
((return [],)
`mkQ` (hsBind :: CstGenQT G.LHsBind) -- matches on binds
`extQ` (genericCT :: CstGenQT G.LHsExpr) -- matches on expressions
`extQ` (genericCT :: CstGenQT G.LPat) -- matches on patterns
)
(G.tm_typechecked_source tcs)
where
-- Helper function to insert mapping into CstGenQS
insExp x = M.insert (G.abe_mono x) (G.varType $ G.abe_poly x)
-- If there is AbsBinds here, insert mapping into CstGenQS if needed
hsBind (L _ G.AbsBinds{abs_exports = es'}) s
| withConstraints = (return [], foldr insExp s es')
| otherwise = (return [], s)
#if __GLASGOW_HASKELL__ >= 800
-- TODO: move to Gap
-- Note: this deals with bindings with explicit type signature, e.g.
-- double :: Num a => a -> a
-- double x = 2*x
hsBind (L _ G.AbsBindsSig{abs_sig_export = poly, abs_sig_bind = bind}) s
| withConstraints =
let new_s =
case bind of
G.L _ G.FunBind{fun_id = i} -> M.insert (G.unLoc i) (G.varType poly) s
_ -> s
in (return [], new_s)
| otherwise = (return [], s)
#endif
-- Otherwise, it's the same as other cases
hsBind x s = genericCT x s
-- Generic SYB function to get type
genericCT x s
| withConstraints
= (maybe [] (uncurry $ constrainedType (collectBinders x) s) <$> getType' x, s)
| otherwise = (maybeToList <$> getType' x, s)
-- Collects everything with Id from LHsBind, LHsExpr, or LPat
collectBinders :: Data a => a -> [Id]
collectBinders = listifyStaged TypeChecker (const True)
-- Gets monomorphic type with location
getType' x@(L spn _)
| G.isGoodSrcSpan spn && spn `G.spans` lc
= getType tcs x
| otherwise = return Nothing
-- Gets constrained type
constrainedType :: [Var] -- ^ Binders in expression, i.e. anything with Id
-> CstGenQS -- ^ Map from Id to polymorphic type
-> SrcSpan -- ^ extent of expression, copied to result
-> Type -- ^ monomorphic type
-> [(SrcSpan, Type)] -- ^ result
constrainedType pids s spn genTyp =
let
-- runs build on every binder.
ctys = mapMaybe build (nub pids)
-- Computes constrained type for x. Returns (constraints, substitutions)
-- Substitutions are needed because type variables don't match
-- between polymorphic and monomorphic types.
-- E.g. poly type might be `Monad m => m ()`, while monomorphic might be `f ()`
build x | Just cti <- x `M.lookup` s
= let
(preds', ctt) = getPreds cti
-- list of type variables in monomorphic type
vts = listifyStaged TypeChecker G.isTyVar $ G.varType x
-- list of type variables in polymorphic type
tvm = listifyStaged TypeChecker G.isTyVarTy ctt
in Just (preds', zip vts tvm)
| otherwise = Nothing
-- list of constraints
preds = concatMap fst ctys
-- Type variable substitutions
#if __GLASGOW_HASKELL__ >= 800
-- TODO: move to Gap
subs = G.mkTvSubstPrs $ concatMap snd ctys
#else
subs = G.mkTopTvSubst $ concatMap snd ctys
#endif
-- Constrained type
ty = G.substTy subs $ G.mkFunTys preds genTyp
in [(spn, ty)]
-- Splits a given type into list of constraints and simple type. Drops foralls.
getPreds :: Type -> ([Type], Type)
getPreds x | G.isForAllTy x = getPreds $ G.dropForAlls x
| Just (c, t) <- G.splitFunTy_maybe x
, G.isPredTy c = first (c:) $ getPreds t
| otherwise = ([], x)
listifySpans :: Typeable a => TypecheckedSource -> (Int, Int) -> [Located a] listifySpans :: Typeable a => TypecheckedSource -> (Int, Int) -> [Located a]
listifySpans tcs lc = listifyStaged TypeChecker p tcs listifySpans tcs lc = listifyStaged TypeChecker p tcs
where where

View File

@ -75,12 +75,12 @@ findExecutablesInStackBinPath exe StackEnv {..} =
findExecutablesInDirectories' :: [FilePath] -> String -> IO [FilePath] findExecutablesInDirectories' :: [FilePath] -> String -> IO [FilePath]
findExecutablesInDirectories' path binary = findExecutablesInDirectories' path binary =
U.findFilesWith' isExecutable path (binary <.> exeExtension) U.findFilesWith' isExecutable path (binary <.> exeExtension')
where isExecutable file = do where isExecutable file = do
perms <- getPermissions file perms <- getPermissions file
return $ executable perms return $ executable perms
exeExtension = if isWindows then "exe" else "" exeExtension' = if isWindows then "exe" else ""
readStack :: (IOish m, GmOut m, GmLog m) => [String] -> MaybeT m String readStack :: (IOish m, GmOut m, GmLog m) => [String] -> MaybeT m String
readStack args = do readStack args = do

View File

@ -21,6 +21,9 @@ import Control.Arrow
import Control.Applicative import Control.Applicative
import Control.Category ((.)) import Control.Category ((.))
import GHC import GHC
#if __GLASGOW_HASKELL__ >= 800
import GHC.LanguageExtensions
#endif
import GHC.Paths (libdir) import GHC.Paths (libdir)
import SysTools import SysTools
import DynFlags import DynFlags
@ -287,8 +290,7 @@ findCandidates scns = foldl1 Set.intersection scns
pickComponent :: Set ChComponentName -> ChComponentName pickComponent :: Set ChComponentName -> ChComponentName
pickComponent scn = Set.findMin scn pickComponent scn = Set.findMin scn
packageGhcOptions :: (Applicative m, IOish m, Gm m) packageGhcOptions :: (IOish m, Applicative m, Gm m) => m [GHCOption]
=> m [GHCOption]
packageGhcOptions = do packageGhcOptions = do
crdl <- cradle crdl <- cradle
case cradleProject crdl of case cradleProject crdl of
@ -491,11 +493,17 @@ loadTargets opts targetStrs = do
needsHscInterpreted :: ModuleGraph -> Bool needsHscInterpreted :: ModuleGraph -> Bool
needsHscInterpreted = any $ \ms -> needsHscInterpreted = any $ \ms ->
let df = ms_hspp_opts ms in let df = ms_hspp_opts ms in
#if __GLASGOW_HASKELL__ >= 800
TemplateHaskell `xopt` df
|| QuasiQuotes `xopt` df
|| PatternSynonyms `xopt` df
#else
Opt_TemplateHaskell `xopt` df Opt_TemplateHaskell `xopt` df
|| Opt_QuasiQuotes `xopt` df || Opt_QuasiQuotes `xopt` df
#if __GLASGOW_HASKELL__ >= 708 #if __GLASGOW_HASKELL__ >= 708
|| (Opt_PatternSynonyms `xopt` df) || (Opt_PatternSynonyms `xopt` df)
#endif #endif
#endif
cabalResolvedComponents :: (IOish m) => cabalResolvedComponents :: (IOish m) =>
GhcModT m (Map ChComponentName (GmComponent 'GMCResolved (Set ModulePath))) GhcModT m (Map ChComponentName (GmComponent 'GMCResolved (Set ModulePath)))

View File

@ -71,7 +71,7 @@ data OutputStyle = LispStyle -- ^ S expression style.
newtype LineSeparator = LineSeparator String deriving (Show) newtype LineSeparator = LineSeparator String deriving (Show)
data FileMapping = FileMapping {fmPath :: FilePath, fmTemp :: Bool} data FileMapping = FileMapping {fmPath :: FilePath, fmTemp :: Bool}
deriving Show deriving (Eq, Show)
type FileMappingMap = Map FilePath FileMapping type FileMappingMap = Map FilePath FileMapping
@ -271,7 +271,7 @@ instance Binary GmModuleGraph where
mpGraph = Map.map (Set.map intToMp) $ Map.mapKeys intToMp graph mpGraph = Map.map (Set.map intToMp) $ Map.mapKeys intToMp graph
return $ GmModuleGraph mpGraph return $ GmModuleGraph mpGraph
where where
swapMap :: (Ord k, Ord v) => Map k v -> Map v k swapMap :: Ord v => Map k v -> Map v k
swapMap = Map.fromList . map (\(x, y) -> (y, x)) . Map.toList swapMap = Map.fromList . map (\(x, y) -> (y, x)) . Map.toList
instance Monoid GmModuleGraph where instance Monoid GmModuleGraph where
@ -388,13 +388,15 @@ data BrowseOpts = BrowseOpts {
-- ^ If 'True', "browseWith" also returns operators. -- ^ If 'True', "browseWith" also returns operators.
, optBrowseDetailed :: Bool , optBrowseDetailed :: Bool
-- ^ If 'True', "browseWith" also returns types. -- ^ If 'True', "browseWith" also returns types.
, optBrowseParents :: Bool
-- ^ If 'True', "browseWith" also returns parents.
, optBrowseQualified :: Bool , optBrowseQualified :: Bool
-- ^ If 'True', "browseWith" will return fully qualified name -- ^ If 'True', "browseWith" will return fully qualified name
} deriving (Show) } deriving (Show)
-- | Default "BrowseOpts" instance -- | Default "BrowseOpts" instance
defaultBrowseOpts :: BrowseOpts defaultBrowseOpts :: BrowseOpts
defaultBrowseOpts = BrowseOpts False False False defaultBrowseOpts = BrowseOpts False False False False
mkLabel ''GhcModCaches mkLabel ''GhcModCaches
mkLabel ''GhcModState mkLabel ''GhcModState

View File

@ -19,6 +19,7 @@ data World = World {
, worldCabalFile :: Maybe TimedFile , worldCabalFile :: Maybe TimedFile
, worldCabalConfig :: Maybe TimedFile , worldCabalConfig :: Maybe TimedFile
, worldCabalSandboxConfig :: Maybe TimedFile , worldCabalSandboxConfig :: Maybe TimedFile
, worldMappedFiles :: FileMappingMap
} deriving (Eq) } deriving (Eq)
timedPackageCaches :: IOish m => GhcModT m [TimedFile] timedPackageCaches :: IOish m => GhcModT m [TimedFile]
@ -34,12 +35,14 @@ getCurrentWorld = do
mCabalFile <- liftIO $ timeFile `traverse` cradleCabalFile crdl mCabalFile <- liftIO $ timeFile `traverse` cradleCabalFile crdl
mCabalConfig <- liftIO $ timeMaybe (setupConfigFile crdl) mCabalConfig <- liftIO $ timeMaybe (setupConfigFile crdl)
mCabalSandboxConfig <- liftIO $ timeMaybe (sandboxConfigFile crdl) mCabalSandboxConfig <- liftIO $ timeMaybe (sandboxConfigFile crdl)
mFileMap <- getMMappedFiles
return World { return World {
worldPackageCaches = pkgCaches worldPackageCaches = pkgCaches
, worldCabalFile = mCabalFile , worldCabalFile = mCabalFile
, worldCabalConfig = mCabalConfig , worldCabalConfig = mCabalConfig
, worldCabalSandboxConfig = mCabalSandboxConfig , worldCabalSandboxConfig = mCabalSandboxConfig
, worldMappedFiles = mFileMap
} }
didWorldChange :: IOish m => World -> GhcModT m Bool didWorldChange :: IOish m => World -> GhcModT m Bool

View File

@ -133,7 +133,7 @@ boundNames decl =
#endif #endif
map ((,) TcClsName) (conNames ctor) map ((,) TcClsName) (conNames ctor)
InstanceD _ _ty _ -> InstanceD {} -> -- _ _ty _
error "notcpp: Instance declarations are not supported yet" error "notcpp: Instance declarations are not supported yet"
ForeignD _ -> ForeignD _ ->
error "notcpp: Foreign declarations are not supported yet" error "notcpp: Foreign declarations are not supported yet"

View File

@ -1,4 +1,5 @@
{-# LANGUAGE CPP, TemplateHaskell #-} {-# LANGUAGE CPP #-}
{-# LANGUAGE TemplateHaskell #-}
-- | This module uses scope lookup techniques to either export -- | This module uses scope lookup techniques to either export
-- 'lookupValueName' from @Language.Haskell.TH@, or define -- 'lookupValueName' from @Language.Haskell.TH@, or define
-- its own 'lookupValueName', which attempts to do the -- its own 'lookupValueName', which attempts to do the
@ -39,9 +40,5 @@ bestValueGuess s = do
err = fail . showString "NotCPP.bestValueGuess: " . unwords err = fail . showString "NotCPP.bestValueGuess: " . unwords
$(recover [d| lookupValueName = bestValueGuess |] $ do $(recover [d| lookupValueName = bestValueGuess |] $ do
#if __GLASGOW_HASKELL__ >= 800 VarI{} <- reify (mkName "lookupValueName")
VarI _ _ _ <- reify (mkName "lookupValueName")
#else
VarI _ _ _ _ <- reify (mkName "lookupValueName")
#endif
return []) return [])

View File

@ -1,4 +1,5 @@
{-# LANGUAGE CPP, TemplateHaskell #-} {-# LANGUAGE CPP #-}
{-# LANGUAGE TemplateHaskell #-}
module NotCPP.Utils where module NotCPP.Utils where
import Control.Applicative ((<$>)) import Control.Applicative ((<$>))
@ -24,19 +25,11 @@ recoverMaybe q = recover (return Nothing) (Just <$> q)
-- | Returns @'Just' ('VarE' n)@ if the info relates to a value called -- | Returns @'Just' ('VarE' n)@ if the info relates to a value called
-- @n@, or 'Nothing' if it relates to a different sort of thing. -- @n@, or 'Nothing' if it relates to a different sort of thing.
infoToExp :: Info -> Maybe Exp infoToExp :: Info -> Maybe Exp
#if __GLASGOW_HASKELL__ >= 800 #if __GLASGOW_HASKELL__ >= 800
infoToExp (VarI n _ _) = infoToExp (VarI n _ _) = Just (VarE n)
infoToExp (DataConI n _ _) = Just (ConE n)
#else #else
infoToExp (VarI n _ _ _) = infoToExp (VarI n _ _ _) = Just (VarE n)
infoToExp (DataConI n _ _ _) = Just (ConE n)
#endif #endif
Just (VarE n)
#if __GLASGOW_HASKELL__ >= 800
infoToExp (DataConI n _ _) =
#else
infoToExp (DataConI n _ _ _) =
#endif
Just (ConE n)
infoToExp _ = Nothing infoToExp _ = Nothing

View File

@ -28,7 +28,7 @@
(< emacs-minor-version minor))) (< emacs-minor-version minor)))
(error "ghc-mod requires at least Emacs %d.%d" major minor))) (error "ghc-mod requires at least Emacs %d.%d" major minor)))
(defconst ghc-version "5.5.0.0") (defconst ghc-version "5.6.0.0")
(defgroup ghc-mod '() "ghc-mod customization") (defgroup ghc-mod '() "ghc-mod customization")

View File

@ -1,5 +1,5 @@
Name: ghc-mod Name: ghc-mod
Version: 5.5.0.0 Version: 5.6.0.0
Author: Kazu Yamamoto <kazu@iij.ad.jp>, Author: Kazu Yamamoto <kazu@iij.ad.jp>,
Daniel Gröber <dxld@darkboxed.org>, Daniel Gröber <dxld@darkboxed.org>,
Alejandro Serrano <trupill@gmail.com>, Alejandro Serrano <trupill@gmail.com>,
@ -95,6 +95,15 @@ Extra-Source-Files: ChangeLog
test/data/stack-project/src/*.hs test/data/stack-project/src/*.hs
test/data/stack-project/test/*.hs test/data/stack-project/test/*.hs
Custom-Setup
Setup-Depends: base
, Cabal < 1.25
, containers
, filepath
, process
, template-haskell
, transformers
Library Library
Default-Language: Haskell2010 Default-Language: Haskell2010
GHC-Options: -Wall -fno-warn-deprecations GHC-Options: -Wall -fno-warn-deprecations
@ -165,7 +174,7 @@ Library
, bytestring < 0.11 , bytestring < 0.11
, binary < 0.9 && >= 0.5.1.0 , binary < 0.9 && >= 0.5.1.0
, containers < 0.6 , containers < 0.6
, cabal-helper < 0.8 && >= 0.7.0.1 , cabal-helper < 0.8 && >= 0.7.1.0
, deepseq < 1.5 , deepseq < 1.5
, directory < 1.3 , directory < 1.3
, filepath < 1.5 , filepath < 1.5
@ -197,6 +206,8 @@ Library
, syb , syb
if impl(ghc < 7.8) if impl(ghc < 7.8)
Build-Depends: convertible Build-Depends: convertible
if impl(ghc >= 8.0)
Build-Depends: ghc-boot
Executable ghc-mod Executable ghc-mod
Default-Language: Haskell2010 Default-Language: Haskell2010

View File

@ -151,7 +151,7 @@ ghcCommands (CmdBrowse opts ms) = concat <$> browse opts `mapM` ms
ghcCommands (CmdCheck files) = checkSyntax files ghcCommands (CmdCheck files) = checkSyntax files
ghcCommands (CmdExpand files) = expandTemplate files ghcCommands (CmdExpand files) = expandTemplate files
ghcCommands (CmdInfo file symb) = info file $ Expression symb ghcCommands (CmdInfo file symb) = info file $ Expression symb
ghcCommands (CmdType file (line, col)) = types file line col ghcCommands (CmdType wCon file (line, col)) = types wCon file line col
ghcCommands (CmdSplit file (line, col)) = splits file line col ghcCommands (CmdSplit file (line, col)) = splits file line col
ghcCommands (CmdSig file (line, col)) = sig file line col ghcCommands (CmdSig file (line, col)) = sig file line col
ghcCommands (CmdAuto file (line, col)) = auto file line col ghcCommands (CmdAuto file (line, col)) = auto file line col

View File

@ -51,7 +51,7 @@ data GhcModCommands =
| CmdCheck [FilePath] | CmdCheck [FilePath]
| CmdExpand [FilePath] | CmdExpand [FilePath]
| CmdInfo FilePath Symbol | CmdInfo FilePath Symbol
| CmdType FilePath Point | CmdType Bool FilePath Point
| CmdSplit FilePath Point | CmdSplit FilePath Point
| CmdSig FilePath Point | CmdSig FilePath Point
| CmdAuto FilePath Point | CmdAuto FilePath Point
@ -215,12 +215,12 @@ interactiveCommandsSpec =
strArg :: String -> Parser String strArg :: String -> Parser String
strArg = argument str . metavar strArg = argument str . metavar
filesArgsSpec :: ([String] -> b) -> Parser b filesArgsSpec :: Parser ([String] -> b) -> Parser b
filesArgsSpec x = x <$> some (strArg "FILES..") filesArgsSpec x = x <*> some (strArg "FILES..")
locArgSpec :: (String -> (Int, Int) -> b) -> Parser b locArgSpec :: Parser (String -> (Int, Int) -> b) -> Parser b
locArgSpec x = x locArgSpec x = x
<$> strArg "FILE" <*> strArg "FILE"
<*> ( (,) <*> ( (,)
<$> argument int (metavar "LINE") <$> argument int (metavar "LINE")
<*> argument int (metavar "COL") <*> argument int (metavar "COL")
@ -255,23 +255,31 @@ browseArgSpec = CmdBrowse
$$ long "detailed" $$ long "detailed"
<=> short 'd' <=> short 'd'
<=> help "Print symbols with accompanying signature" <=> help "Print symbols with accompanying signature"
<*> switch
$$ long "parents"
<=> short 'p'
<=> help "Print symbols parents"
<*> switch <*> switch
$$ long "qualified" $$ long "qualified"
<=> short 'q' <=> short 'q'
<=> help "Qualify symbols" <=> help "Qualify symbols"
) )
<*> some (strArg "MODULE") <*> some (strArg "MODULE")
debugComponentArgSpec = filesArgsSpec CmdDebugComponent debugComponentArgSpec = filesArgsSpec (pure CmdDebugComponent)
checkArgSpec = filesArgsSpec CmdCheck checkArgSpec = filesArgsSpec (pure CmdCheck)
expandArgSpec = filesArgsSpec CmdExpand expandArgSpec = filesArgsSpec (pure CmdExpand)
infoArgSpec = CmdInfo infoArgSpec = CmdInfo
<$> strArg "FILE" <$> strArg "FILE"
<*> strArg "SYMBOL" <*> strArg "SYMBOL"
typeArgSpec = locArgSpec CmdType typeArgSpec = locArgSpec $ CmdType <$>
autoArgSpec = locArgSpec CmdAuto switch
splitArgSpec = locArgSpec CmdSplit $$ long "constraints"
sigArgSpec = locArgSpec CmdSig <=> short 'c'
refineArgSpec = locArgSpec CmdRefine <*> strArg "SYMBOL" <=> help "Include constraints into type signature"
autoArgSpec = locArgSpec (pure CmdAuto)
splitArgSpec = locArgSpec (pure CmdSplit)
sigArgSpec = locArgSpec (pure CmdSig)
refineArgSpec = locArgSpec (pure CmdRefine) <*> strArg "SYMBOL"
mapArgSpec = CmdMapFile <$> strArg "FILE" mapArgSpec = CmdMapFile <$> strArg "FILE"
unmapArgSpec = CmdUnmapFile <$> strArg "FILE" unmapArgSpec = CmdUnmapFile <$> strArg "FILE"
legacyInteractiveArgSpec = const CmdLegacyInteractive <$> legacyInteractiveArgSpec = const CmdLegacyInteractive <$>

5
stack-8.yaml Normal file
View File

@ -0,0 +1,5 @@
flags: {}
packages:
- '.'
extra-deps: []
resolver: nightly-2016-06-04

View File

@ -33,7 +33,11 @@ pkgOptions (x:y:xs) | x == "-package-id" = [name y] ++ pkgOptions xs
| otherwise = pkgOptions (y:xs) | otherwise = pkgOptions (y:xs)
where where
stripDash s = maybe s id $ (flip drop s . (+1) <$> findIndex (=='-') s) stripDash s = maybe s id $ (flip drop s . (+1) <$> findIndex (=='-') s)
#if __GLASGOW_HASKELL__ >= 800
name s = reverse $ stripDash $ reverse s
#else
name s = reverse $ stripDash $ stripDash $ reverse s name s = reverse $ stripDash $ stripDash $ reverse s
#endif
idirOpts :: [(c, [String])] -> [(c, [String])] idirOpts :: [(c, [String])] -> [(c, [String])]
idirOpts = map (second $ map (drop 2) . filter ("-i"`isPrefixOf`)) idirOpts = map (second $ map (drop 2) . filter ("-i"`isPrefixOf`))
@ -69,7 +73,7 @@ spec = do
it "extracts build dependencies" $ do it "extracts build dependencies" $ do
let tdir = "test/data/cabal-project" let tdir = "test/data/cabal-project"
opts <- map gmcGhcOpts <$> runD' tdir getComponents opts <- map gmcGhcOpts <$> runD' tdir getComponents
let ghcOpts = head opts let ghcOpts:_ = opts
pkgs = pkgOptions ghcOpts pkgs = pkgOptions ghcOpts
pkgs `shouldBe` ["Cabal","base","template-haskell"] pkgs `shouldBe` ["Cabal","base","template-haskell"]

View File

@ -1,3 +1,4 @@
{-# LANGUAGE CPP #-}
module CaseSplitSpec where module CaseSplitSpec where
import Language.Haskell.GhcMod import Language.Haskell.GhcMod
@ -12,6 +13,7 @@ main = do
spec :: Spec spec :: Spec
spec = do spec = do
describe "case split" $ do describe "case split" $ do
#if __GLASGOW_HASKELL__ >= 708
it "does not blow up on HsWithBndrs panic" $ do it "does not blow up on HsWithBndrs panic" $ do
withDirectory_ "test/data/case-split" $ do withDirectory_ "test/data/case-split" $ do
res <- runD $ splits "Vect.hs" 24 10 res <- runD $ splits "Vect.hs" 24 10
@ -39,3 +41,41 @@ spec = do
res `shouldBe` "38 21 38 59"++ res `shouldBe` "38 21 38 59"++
" \"mlReverse' Nil accum = _mlReverse_body\NUL"++ " \"mlReverse' Nil accum = _mlReverse_body\NUL"++
" mlReverse' (Cons xs'1 xs'2) accum = _mlReverse_body\"\n" " mlReverse' (Cons xs'1 xs'2) accum = _mlReverse_body\"\n"
#else
it "does not blow up on HsWithBndrs panic" $ do
withDirectory_ "test/data/case-split" $ do
res <- runD $ splits "Vect706.hs" 24 10
res `shouldBe` "24 1 24 25"++
" \"mlAppend Nil y = undefined\NUL"++
"mlAppend (Cons x1 x2) y = undefined\"\n"
it "works with case expressions" $ do
withDirectory_ "test/data/case-split" $ do
res <- runD $ splits "Vect706.hs" 28 20
res `shouldBe` "28 19 28 34"++
" \"Nil -> undefined\NUL"++
" (Cons x'1 x'2) -> undefined\"\n"
it "works with where clauses" $ do
withDirectory_ "test/data/case-split" $ do
res <- runD $ splits "Vect706.hs" 34 17
res `shouldBe` "34 5 34 37"++
" \"mlReverse' Nil accum = undefined\NUL"++
" mlReverse' (Cons xs'1 xs'2) accum = undefined\"\n"
it "works with let bindings" $ do
withDirectory_ "test/data/case-split" $ do
res <- runD $ splits "Vect706.hs" 38 33
res `shouldBe` "38 21 38 53"++
" \"mlReverse' Nil accum = undefined\NUL"++
" mlReverse' (Cons xs'1 xs'2) accum = undefined\"\n"
#endif
it "doesn't crash when source doesn't make sense" $
withDirectory_ "test/data/case-split" $ do
res <- runD $ splits "Crash.hs" 4 6
#if __GLASGOW_HASKELL__ < 710
res `shouldBe` "4 1 4 19 \"test x = undefined\"\n"
#else
res `shouldBe` ""
#endif

View File

@ -58,7 +58,7 @@ spec = do
it "emits warnings generated in GHC's desugar stage" $ do it "emits warnings generated in GHC's desugar stage" $ do
withDirectory_ "test/data/check-missing-warnings" $ do withDirectory_ "test/data/check-missing-warnings" $ do
res <- runD $ checkSyntax ["DesugarWarnings.hs"] res <- runD $ checkSyntax ["DesugarWarnings.hs"]
res `shouldBe` "DesugarWarnings.hs:4:9:Warning: Pattern match(es) are non-exhaustive\NULIn a case alternative: Patterns not matched: _ : _\n" res `shouldSatisfy` ("DesugarWarnings.hs:4:9:Warning: Pattern match(es) are non-exhaustive\NULIn a case alternative: Patterns not matched:" `isPrefixOf`)
#endif #endif
it "works with cabal builtin preprocessors" $ do it "works with cabal builtin preprocessors" $ do
@ -71,7 +71,9 @@ spec = do
it "Uses the right qualification style" $ do it "Uses the right qualification style" $ do
withDirectory_ "test/data/nice-qualification" $ do withDirectory_ "test/data/nice-qualification" $ do
res <- runD $ checkSyntax ["NiceQualification.hs"] res <- runD $ checkSyntax ["NiceQualification.hs"]
#if __GLASGOW_HASKELL__ >= 708 #if __GLASGOW_HASKELL__ >= 800
res `shouldBe` "NiceQualification.hs:4:8:\8226 Couldn't match expected type \8216IO ()\8217 with actual type \8216[Char]\8217\NUL\8226 In the expression: \"wrong type\"\NUL In an equation for \8216main\8217: main = \"wrong type\"\n"
#elif __GLASGOW_HASKELL__ >= 708
res `shouldBe` "NiceQualification.hs:4:8:Couldn't match expected type \8216IO ()\8217 with actual type \8216[Char]\8217\NULIn the expression: \"wrong type\"\NULIn an equation for \8216main\8217: main = \"wrong type\"\n" res `shouldBe` "NiceQualification.hs:4:8:Couldn't match expected type \8216IO ()\8217 with actual type \8216[Char]\8217\NULIn the expression: \"wrong type\"\NULIn an equation for \8216main\8217: main = \"wrong type\"\n"
#else #else
res `shouldBe` "NiceQualification.hs:4:8:Couldn't match expected type `IO ()' with actual type `[Char]'\NULIn the expression: \"wrong type\"\NULIn an equation for `main': main = \"wrong type\"\n" res `shouldBe` "NiceQualification.hs:4:8:Couldn't match expected type `IO ()' with actual type `[Char]'\NULIn the expression: \"wrong type\"\NULIn an equation for `main': main = \"wrong type\"\n"

View File

@ -134,13 +134,19 @@ spec = do
let tdir = "test/data/file-mapping" let tdir = "test/data/file-mapping"
res <- runD' tdir $ do res <- runD' tdir $ do
loadMappedFile "File.hs" "File_Redir_Lint.hs" loadMappedFile "File.hs" "File_Redir_Lint.hs"
types "File.hs" 4 12 types False "File.hs" 4 12
res `shouldBe` "4 12 4 15 \"a -> a -> a\"\n4 12 4 17 \"a -> a\"\n4 12 4 19 \"a\"\n4 1 4 19 \"a -> a -> a\"\n" res `shouldBe` "4 12 4 15 \"a -> a -> a\"\n4 12 4 17 \"a -> a\"\n4 12 4 19 \"a\"\n4 1 4 19 \"a -> a -> a\"\n"
it "shows types of the expression with constraints for redirected files" $ do --
let tdir = "test/data/file-mapping"
res <- runD' tdir $ do
loadMappedFile "File.hs" "File_Redir_Lint.hs"
types True "File.hs" 4 12
res `shouldBe` "4 12 4 15 \"a -> a -> a\"\n4 12 4 17 \"a -> a\"\n4 12 4 19 \"a\"\n4 1 4 19 \"Num a => a -> a -> a\"\n"
it "shows types of the expression for in-memory files" $ do it "shows types of the expression for in-memory files" $ do
let tdir = "test/data/file-mapping" let tdir = "test/data/file-mapping"
res <- runD' tdir $ do res <- runD' tdir $ do
loadMappedFileSource "File.hs" "main = putStrLn \"Hello!\"" loadMappedFileSource "File.hs" "main = putStrLn \"Hello!\""
types "File.hs" 1 14 types False "File.hs" 1 14
res `shouldBe` "1 8 1 16 \"String -> IO ()\"\n1 8 1 25 \"IO ()\"\n1 1 1 25 \"IO ()\"\n" res `shouldBe` "1 8 1 16 \"String -> IO ()\"\n1 8 1 25 \"IO ()\"\n1 1 1 25 \"IO ()\"\n"
it "shows info for the expression for redirected files" $ do it "shows info for the expression for redirected files" $ do
let tdir = "test/data/file-mapping" let tdir = "test/data/file-mapping"
@ -234,7 +240,7 @@ spec = do
,("Bar.hs", tmpdir </> "Bar_Redir.hs")] ,("Bar.hs", tmpdir </> "Bar_Redir.hs")]
res <- run defaultOptions $ do res <- run defaultOptions $ do
mapM_ (uncurry loadMappedFile) fm mapM_ (uncurry loadMappedFile) fm
types "Bar.hs" 5 1 types False "Bar.hs" 5 1
res `shouldBe` unlines ["5 1 5 20 \"[Char]\""] res `shouldBe` unlines ["5 1 5 20 \"[Char]\""]
it "works with a memory module using TemplateHaskell" $ do it "works with a memory module using TemplateHaskell" $ do
srcFoo <- readFile "test/data/template-haskell/Foo.hs" srcFoo <- readFile "test/data/template-haskell/Foo.hs"
@ -244,5 +250,5 @@ spec = do
,("Bar.hs", srcBar)] ,("Bar.hs", srcBar)]
res <- run defaultOptions $ do res <- run defaultOptions $ do
mapM_ (uncurry loadMappedFileSource) fm mapM_ (uncurry loadMappedFileSource) fm
types "Bar.hs" 5 1 types False "Bar.hs" 5 1
res `shouldBe` unlines ["5 1 5 20 \"[Char]\""] res `shouldBe` unlines ["5 1 5 20 \"[Char]\""]

View File

@ -9,6 +9,6 @@ import Prelude
spec :: Spec spec :: Spec
spec = do spec = do
describe "flags" $ do describe "flags" $ do
it "contains at least `-fno-warn-orphans'" $ do it "contains at least `-fprint-explicit-foralls" $ do
f <- runD $ lines <$> flags f <- runD $ lines <$> flags
f `shouldContain` ["-fno-warn-orphans"] f `shouldContain` ["-fprint-explicit-foralls"]

View File

@ -19,17 +19,31 @@ spec = do
describe "types" $ do describe "types" $ do
it "shows types of the expression and its outers" $ do it "shows types of the expression and its outers" $ do
let tdir = "test/data/ghc-mod-check" let tdir = "test/data/ghc-mod-check"
res <- runD' tdir $ types "lib/Data/Foo.hs" 9 5 res <- runD' tdir $ types False "lib/Data/Foo.hs" 9 5
#if __GLASGOW_HASKELL__ >= 800
res `shouldBe` "9 5 11 40 \"Int -> t -> t -> t\"\n7 1 11 40 \"Int -> Integer\"\n"
#else
res `shouldBe` "9 5 11 40 \"Int -> a -> a -> a\"\n7 1 11 40 \"Int -> Integer\"\n" res `shouldBe` "9 5 11 40 \"Int -> a -> a -> a\"\n7 1 11 40 \"Int -> Integer\"\n"
#endif
it "shows types of the expression with constraints and its outers" $ do
let tdir = "test/data/ghc-mod-check"
res <- runD' tdir $ types True "lib/Data/Foo.hs" 9 5
#if __GLASGOW_HASKELL__ >= 800
res `shouldBe` "9 5 11 40 \"Num t => Int -> t -> t -> t\"\n7 1 11 40 \"Int -> Integer\"\n"
#else
res `shouldBe` "9 5 11 40 \"Num a => Int -> a -> a -> a\"\n7 1 11 40 \"Int -> Integer\"\n"
#endif
it "works with a module using TemplateHaskell" $ do it "works with a module using TemplateHaskell" $ do
let tdir = "test/data/template-haskell" let tdir = "test/data/template-haskell"
res <- runD' tdir $ types "Bar.hs" 5 1 res <- runD' tdir $ types False "Bar.hs" 5 1
res `shouldBe` unlines ["5 1 5 20 \"[Char]\""] res `shouldBe` unlines ["5 1 5 20 \"[Char]\""]
it "works with a module that imports another module using TemplateHaskell" $ do it "works with a module that imports another module using TemplateHaskell" $ do
let tdir = "test/data/template-haskell" let tdir = "test/data/template-haskell"
res <- runD' tdir $ types "ImportsTH.hs" 3 8 res <- runD' tdir $ types False "ImportsTH.hs" 3 8
res `shouldBe` unlines ["3 8 3 16 \"String -> IO ()\"", "3 8 3 20 \"IO ()\"", "3 1 3 20 \"IO ()\""] res `shouldBe` unlines ["3 8 3 16 \"String -> IO ()\"", "3 8 3 20 \"IO ()\"", "3 1 3 20 \"IO ()\""]
describe "info" $ do describe "info" $ do

View File

@ -23,16 +23,18 @@ spec = do
mv_ex :: MVar (Either SomeException ()) mv_ex :: MVar (Either SomeException ())
<- newEmptyMVar <- newEmptyMVar
mv_startup_barrier :: MVar () <- newEmptyMVar mv_startup_barrier :: MVar ()
<- newEmptyMVar
_t1 <- forkOS $ do _t1 <- forkOS $ do
putMVar mv_startup_barrier ()
-- wait (inside GhcModT) for t2 to receive the exception -- wait (inside GhcModT) for t2 to receive the exception
_ <- runD $ liftIO $ readMVar mv_ex _ <- runD $ liftIO $ do
putMVar mv_startup_barrier ()
readMVar mv_ex
return () return ()
_t2 <- forkOS $ do _t2 <- forkOS $ do
readMVar mv_startup_barrier -- wait for t1 to start up readMVar mv_startup_barrier -- wait for t1 to be in GhcModT
res <- try $ runD $ return () res <- try $ runD $ return ()
res' <- evaluate res res' <- evaluate res
putMVar mv_ex res' putMVar mv_ex res'

View File

@ -0,0 +1,4 @@
module Crash where
test :: Maybe a
test x = undefined

View File

@ -0,0 +1,39 @@
{-# LANGUAGE DataKinds, TypeFamilies, TypeOperators, GADTs, KindSignatures #-}
module Vect706 where
data Nat = Z | S Nat
type family (n :: Nat) :+ (m :: Nat) :: Nat
type instance Z :+ m = m
type instance S n :+ m = S (n :+ m)
data Vect :: Nat -> * -> * where
VNil :: Vect Z a
(:::) :: a -> Vect n a -> Vect (S n) a
vAppend :: Vect n a -> Vect m a -> Vect (n :+ m) a
vAppend x y = undefined
lAppend :: [a] -> [a] -> [a]
lAppend x y = undefined
data MyList a = Nil | Cons a (MyList a)
mlAppend :: MyList a -> MyList a -> MyList a
mlAppend x y = undefined
mlAppend2 :: MyList a -> MyList a -> MyList a
mlAppend2 x y = case x of
x' -> undefined
mlReverse :: MyList a -> MyList a
mlReverse xs = mlReverse' xs Nil
where
mlReverse' :: MyList a -> MyList a -> MyList a
mlReverse' xs' accum = undefined
mlReverse2 :: MyList a -> MyList a
mlReverse2 xs = let mlReverse' :: MyList a -> MyList a -> MyList a
mlReverse' xs' accum = undefined
in mlReverse' xs Nil

View File

@ -1,4 +1,5 @@
{-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE PatternSynonyms #-}
module A where module A where
data SomeType a b = SomeType (a,b) data SomeType a b = SomeType (a,b)

View File

@ -22,4 +22,6 @@ library
build-depends: base build-depends: base
-- hs-source-dirs: -- hs-source-dirs:
default-language: Haskell2010 default-language: Haskell2010
ghc-options: -Wall ghc-options: -Wall
if impl(ghc >= 8.0.1)
ghc-options: -Wno-missing-pattern-synonym-signatures

View File

@ -16,7 +16,7 @@ cabal-version: >=1.10
library library
hs-source-dirs: src hs-source-dirs: src
exposed-modules: Lib exposed-modules: Lib
build-depends: base >= 4.7 && < 5 build-depends: base
default-language: Haskell2010 default-language: Haskell2010
executable new-template-exe executable new-template-exe