Skip to content

Backquote rendering #1493

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/Config/Type.hs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import Language.Haskell.GhclibParserEx.GHC.Hs.ExtendInstances
import Deriving.Aeson
import System.Console.CmdArgs.Implicit
import Data.Aeson hiding (Error)
import Util (backquote)

getSeverity :: String -> Maybe Severity
getSeverity "ignore" = Just Ignore
Expand Down Expand Up @@ -82,8 +83,8 @@ instance Show Note where
show IncreasesLaziness = "increases laziness"
show DecreasesLaziness = "decreases laziness"
show (RemovesError x) = "removes error " ++ x
show (ValidInstance x y) = "requires a valid `" ++ x ++ "` instance for `" ++ y ++ "`"
show (RequiresExtension x) = "may require `{-# LANGUAGE " ++ x ++ " #-}` adding to the top of the file"
show (ValidInstance x y) = unwords ["requires a valid", backquote x, "instance for", backquote y]
show (RequiresExtension x) = unwords ["may require adding", backquote $ unwords ["{-# LANGUAGE", x, "#-}"], "to the top of the file"]
show (Note x) = x


Expand Down
2 changes: 1 addition & 1 deletion src/Hint/Lambda.hs
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ lambdaExp _ o@(L _ (HsPar _ _ (view -> App2 (view -> Var_ "flip") origf@(view ->
to = nlHsPar $ noLocA $ SectionR EpAnnNotUsed origf y
op = if isSymbolRdrName (unLoc f)
then unsafePrettyPrint f
else "`" ++ unsafePrettyPrint f ++ "`"
else backquote $ unsafePrettyPrint f
var = if rdrNameStr f == "x" then "y" else "x"
r = Replace Expr (toSSA o) [(var, toSSA y)] ("(" ++ op ++ " " ++ var ++ ")")

Expand Down
39 changes: 38 additions & 1 deletion src/Hint/Monad.hs
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,19 @@ issue978 = do \
print "x" \
if False then main else do \
return ()

foo x y z = return 7 -- Demote `foo` to a pure function
foo x y z = pure 7 -- Demote `foo` to a pure function
foo x y z = pure $ x + y -- Demote `foo` to a pure function
foo x y z = negate 7
</TEST>
-}


module Hint.Monad(monadHint) where

import Hint.Type
import Util (backquote)

import GHC.Hs hiding (Warning)
import GHC.Types.Fixity
Expand All @@ -78,6 +84,7 @@ import GHC.Types.Name.Reader
import GHC.Types.Name.Occurrence
import GHC.Data.Bag
import qualified GHC.Data.Strict
import Control.Monad ( guard )

import Language.Haskell.GhclibParserEx.GHC.Hs.Pat
import Language.Haskell.GhclibParserEx.GHC.Hs.Expr
Expand All @@ -99,8 +106,11 @@ unitFuncs :: [String]
unitFuncs = ["when","unless","void"]

monadHint :: DeclHint
monadHint _ _ d = concatMap (f Nothing Nothing) $ childrenBi d
monadHint _ _ d =
baseHints <> gratuitousHints
where
baseHints = concatMap (f Nothing Nothing) $ childrenBi d
gratuitousHints = concatMap gratuitouslyMonadic $ universeBi d
decl = declName d
f parentDo parentExpr x =
monadExp decl parentDo parentExpr x ++
Expand All @@ -109,6 +119,33 @@ monadHint _ _ d = concatMap (f Nothing Nothing) $ childrenBi d
isHsDo (L _ HsDo{}) = True
isHsDo _ = False

gratuitouslyMonadic :: LHsDecl GhcPs -> [Idea]
gratuitouslyMonadic e@(L _ d) = case d of
ValD _ func@(FunBind _ (L _ n) (MG _ (L _ ms))) -> do
guard $ fname /= "main" -- Account for "main = pure ()" test
guard $ all gratuitouslyMonadicExpr $ allMatchExprs ms
pure $ rawIdea
Suggestion
"Unnecessarily monadic"
(locA $ getLoc e)
(unsafePrettyPrint e)
(Just $ unwords ["Demote", backquote fname, "to a pure function"])
[]
[]
where
fname = occNameString $ rdrNameOcc n
-- Iterate over all of the patterns of the function, as well as all of the guards
allMatchExprs ms = [expr | L _ (Match _ _ _ (GRHSs _ xs _)) <- ms, L _ (GRHS _ _ expr) <- xs]
_ -> []

-- | Handles both of:
-- pure x
-- pure $ f x
gratuitouslyMonadicExpr :: LHsExpr GhcPs -> Bool
gratuitouslyMonadicExpr x = case simplifyExp x of
L _ (HsApp _ (L _ (HsVar _ (L _ myFunc))) _) ->
occNameString (rdrNameOcc myFunc) `elem` ["pure", "return"]
_ -> False

-- | Call with the name of the declaration,
-- the nearest enclosing `do` expression
Expand Down
9 changes: 7 additions & 2 deletions src/Util.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ module Util(
forceList,
gzip, universeParentBi,
exitMessage, exitMessageImpure,
getContentsUTF8, wildcardMatch
getContentsUTF8, wildcardMatch,
backquote
) where

import System.Exit
Expand Down Expand Up @@ -41,6 +42,11 @@ getContentsUTF8 = do
hSetEncoding stdin utf8
getContents

---------------------------------------------------------------------
-- RENDERING

backquote :: String -> String
backquote s = "`" <> s <> "`"

---------------------------------------------------------------------
-- DATA.GENERICS
Expand All @@ -54,7 +60,6 @@ gzip f x y | toConstr x /= toConstr y = Nothing
-- in the same order
where op (Box x) (Box y) = f x (unsafeCoerce y)


---------------------------------------------------------------------
-- DATA.GENERICS.UNIPLATE.OPERATIONS

Expand Down