Make better check in presence of typed holes
This commit is contained in:
		
							parent
							
								
									637fd7e66f
								
							
						
					
					
						commit
						fdbecdddce
					
				| @ -36,10 +36,14 @@ checkSyntax files = withErrorHandler sessionName $ | |||||||
| check :: IOish m | check :: IOish m | ||||||
|       => [FilePath]  -- ^ The target files. |       => [FilePath]  -- ^ The target files. | ||||||
|       -> GhcModT m (Either String String) |       -> GhcModT m (Either String String) | ||||||
| check fileNames = overrideGhcUserOptions $ \ghcOpts -> | check fileNames = overrideGhcUserOptions $ \ghcOpts -> do | ||||||
|   withLogger (setAllWaringFlags . setNoMaxRelevantBindings . Gap.setWarnTypedHoles . Gap.setDeferTypeErrors) $ do |   withLoggerTwice | ||||||
|     _ <- G.setSessionDynFlags =<< addCmdOpts ghcOpts =<< G.getSessionDynFlags |     setAllWaringFlags | ||||||
|     setTargetFiles fileNames |     (do _ <- G.setSessionDynFlags =<< addCmdOpts ghcOpts =<< G.getSessionDynFlags | ||||||
|  |         setTargetFiles fileNames) | ||||||
|  |     (setAllWaringFlags . setNoMaxRelevantBindings . Gap.setWarnTypedHoles) | ||||||
|  |     (do _ <- G.setSessionDynFlags =<< addCmdOpts ghcOpts =<< G.getSessionDynFlags | ||||||
|  |         setTargetFiles fileNames) | ||||||
| 
 | 
 | ||||||
| ---------------------------------------------------------------- | ---------------------------------------------------------------- | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -2,14 +2,15 @@ | |||||||
| 
 | 
 | ||||||
| module Language.Haskell.GhcMod.Logger ( | module Language.Haskell.GhcMod.Logger ( | ||||||
|     withLogger |     withLogger | ||||||
|  |   , withLoggerTwice | ||||||
|   , checkErrorPrefix |   , checkErrorPrefix | ||||||
|   ) where |   ) where | ||||||
| 
 | 
 | ||||||
| import Bag (Bag, bagToList) | import Bag (Bag, bagToList, filterBag, unionBags) | ||||||
| import Control.Applicative ((<$>)) | import Control.Applicative ((<$>)) | ||||||
| import Data.IORef (IORef, newIORef, readIORef, writeIORef, modifyIORef) | import Data.IORef (IORef, newIORef, readIORef, writeIORef, modifyIORef) | ||||||
| import Data.List (isPrefixOf) | import Data.List (isPrefixOf, find) | ||||||
| import Data.Maybe (fromMaybe) | import Data.Maybe (fromMaybe, isJust) | ||||||
| import ErrUtils (ErrMsg, errMsgShortDoc, errMsgExtraInfo) | import ErrUtils (ErrMsg, errMsgShortDoc, errMsgExtraInfo) | ||||||
| import Exception (ghandle) | import Exception (ghandle) | ||||||
| import GHC (DynFlags, SrcSpan, Severity(SevError)) | import GHC (DynFlags, SrcSpan, Severity(SevError)) | ||||||
| @ -71,20 +72,70 @@ withLogger setDF body = ghandle sourceError $ do | |||||||
|   where |   where | ||||||
|     setLogger logref df = Gap.setLogAction df $ appendLogRef df logref |     setLogger logref df = Gap.setLogAction df $ appendLogRef df logref | ||||||
| 
 | 
 | ||||||
|  | withLoggerTwice :: IOish m | ||||||
|  |                 => (DynFlags -> DynFlags) | ||||||
|  |                 -> GhcModT m () | ||||||
|  |                 -> (DynFlags -> DynFlags) | ||||||
|  |                 -> GhcModT m () | ||||||
|  |                 -> GhcModT m (Either String String) | ||||||
|  | withLoggerTwice setDF1 body1 setDF2 body2 = do | ||||||
|  |   err1 <- ghandle sourceErrorBag $ do | ||||||
|  |     logref <- liftIO newLogRef | ||||||
|  |     wflags <- filter ("-fno-warn" `isPrefixOf`) . ghcUserOptions <$> options | ||||||
|  |     withDynFlags (setLogger logref . setDF1) $ | ||||||
|  |         withCmdFlags wflags $ do | ||||||
|  |             body1 | ||||||
|  |             Right <$> readAndClearLogRef logref | ||||||
|  |   err2 <- ghandle sourceErrorBag $ do | ||||||
|  |     logref <- liftIO newLogRef | ||||||
|  |     wflags <- filter ("-fno-warn" `isPrefixOf`) . ghcUserOptions <$> options | ||||||
|  |     withDynFlags (setLogger logref . setDF2) $ | ||||||
|  |         withCmdFlags wflags $ do | ||||||
|  |             body2 | ||||||
|  |             Right <$> readAndClearLogRef logref | ||||||
|  |   case (err1, err2) of | ||||||
|  |     (Right x, Right _) -> return $ Right x | ||||||
|  |     (Left b1, Right _) -> errBagToStr b1 | ||||||
|  |     (Right _, Left b2) -> errBagToStr b2 | ||||||
|  |     (Left b1, Left b2) -> do dflags <- G.getSessionDynFlags | ||||||
|  |                              style <- toGhcModT getStyle | ||||||
|  |                              let merged = mergeErrors dflags style b1 b2 | ||||||
|  |                              errBagToStr merged | ||||||
|  |   where | ||||||
|  |     setLogger logref df = Gap.setLogAction df $ appendLogRef df logref | ||||||
| 
 | 
 | ||||||
| ---------------------------------------------------------------- | ---------------------------------------------------------------- | ||||||
| 
 | 
 | ||||||
| -- | Converting 'SourceError' to 'String'. | -- | Converting 'SourceError' to 'String'. | ||||||
| sourceError :: IOish m => SourceError -> GhcModT m (Either String String) | sourceError :: IOish m => SourceError -> GhcModT m (Either String String) | ||||||
| sourceError err = do | sourceError err = errBagToStr (srcErrorMessages err) | ||||||
|  | 
 | ||||||
|  | errBagToStr :: IOish m => Bag ErrMsg -> GhcModT m (Either String String) | ||||||
|  | errBagToStr err = do | ||||||
|     dflags <- G.getSessionDynFlags |     dflags <- G.getSessionDynFlags | ||||||
|     style <- toGhcModT getStyle |     style <- toGhcModT getStyle | ||||||
|     ret <- convert' (errBagToStrList dflags style . srcErrorMessages $ err) |     ret <- convert' (errBagToStrList dflags style err) | ||||||
|     return $ Left ret |     return $ Left ret | ||||||
| 
 | 
 | ||||||
| errBagToStrList :: DynFlags -> PprStyle -> Bag ErrMsg -> [String] | errBagToStrList :: DynFlags -> PprStyle -> Bag ErrMsg -> [String] | ||||||
| errBagToStrList dflag style = map (ppErrMsg dflag style) . reverse . bagToList | errBagToStrList dflag style = map (ppErrMsg dflag style) . reverse . bagToList | ||||||
| 
 | 
 | ||||||
|  | sourceErrorBag :: IOish m => SourceError -> GhcModT m (Either (Bag ErrMsg) String) | ||||||
|  | sourceErrorBag err = return $ Left (srcErrorMessages err) | ||||||
|  | 
 | ||||||
|  | mergeErrors :: DynFlags -> PprStyle -> Bag ErrMsg -> Bag ErrMsg -> Bag ErrMsg | ||||||
|  | mergeErrors dflag style b1 b2 = | ||||||
|  |   let b1List = bagToList b1 | ||||||
|  |       findInB1 = \pr2 msg2 err1 -> | ||||||
|  |                     let pr1  = ppMsgPrefix (Gap.errorMsgSpan err1) G.SevWarning dflag style | ||||||
|  |                         msg1 = showPage dflag style (errMsgExtraInfo err1) | ||||||
|  |                      in pr1 == pr2 && msg1 == msg2 | ||||||
|  |       mustBeB2 = \err2 -> | ||||||
|  |                     let pr2  = ppMsgPrefix (Gap.errorMsgSpan err2) G.SevWarning dflag style | ||||||
|  |                         msg2 = showPage dflag style (errMsgExtraInfo err2) | ||||||
|  |                      in not . isJust $ find (findInB1 pr2 msg2) b1List | ||||||
|  |    in b1 `unionBags` filterBag mustBeB2 b2 | ||||||
|  | 
 | ||||||
| ---------------------------------------------------------------- | ---------------------------------------------------------------- | ||||||
| 
 | 
 | ||||||
| ppErrMsg :: DynFlags -> PprStyle -> ErrMsg -> String | ppErrMsg :: DynFlags -> PprStyle -> ErrMsg -> String | ||||||
| @ -98,22 +149,18 @@ ppMsg :: SrcSpan -> Severity-> DynFlags -> PprStyle -> SDoc -> String | |||||||
| ppMsg spn sev dflag style msg = prefix ++ cts | ppMsg spn sev dflag style msg = prefix ++ cts | ||||||
|   where |   where | ||||||
|     cts  = showPage dflag style msg |     cts  = showPage dflag style msg | ||||||
|     defaultPrefix |     prefix = ppMsgPrefix spn sev dflag style | ||||||
|  | 
 | ||||||
|  | ppMsgPrefix :: SrcSpan -> Severity-> DynFlags -> PprStyle -> String | ||||||
|  | ppMsgPrefix spn sev dflag _style = | ||||||
|  |   let defaultPrefix | ||||||
|         | Gap.isDumpSplices dflag = "" |         | Gap.isDumpSplices dflag = "" | ||||||
|         | otherwise               = checkErrorPrefix |         | otherwise               = checkErrorPrefix | ||||||
|     prefix = fromMaybe defaultPrefix $ do |    in fromMaybe defaultPrefix $ do | ||||||
|         (line,col,_,_) <- Gap.getSrcSpan spn |         (line,col,_,_) <- Gap.getSrcSpan spn | ||||||
|         file <- normalise <$> Gap.getSrcFile spn |         file <- normalise <$> Gap.getSrcFile spn | ||||||
|         let severityCaption = Gap.showSeverityCaption sev |         let severityCaption = Gap.showSeverityCaption sev | ||||||
|             pref0 |         return $ file ++ ":" ++ show line ++ ":" ++ show col ++ ":" ++ severityCaption | ||||||
|               | typeWarning1 `isPrefixOf` cts || |  | ||||||
|                 typeWarning2 `isPrefixOf` cts = file ++ ":" ++ show line ++ ":" ++ show col ++ ":" |  | ||||||
|               | otherwise                     = file ++ ":" ++ show line ++ ":" ++ show col ++ ":" ++ severityCaption |  | ||||||
|         return pref0 |  | ||||||
|     -- DeferTypeErrors turns a type error to a warning. |  | ||||||
|     -- So, let's turns it the error again. |  | ||||||
|     typeWarning1 = "Couldn't match expected type" |  | ||||||
|     typeWarning2 = "Couldn't match type" |  | ||||||
| 
 | 
 | ||||||
| checkErrorPrefix :: String | checkErrorPrefix :: String | ||||||
| checkErrorPrefix = "Dummy:0:0:Error:" | checkErrorPrefix = "Dummy:0:0:Error:" | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Alejandro Serrano
						Alejandro Serrano