Accept multiple argument types inside brackets

This commit is contained in:
James Parker 2017-03-27 02:42:47 -04:00
parent adf89bcf84
commit 997714f4c2
3 changed files with 19 additions and 23 deletions

View File

@ -16,15 +16,13 @@ import Language.Haskell.TH.Syntax
import qualified Network.Wai as W import qualified Network.Wai as W
import Data.ByteString.Lazy.Char8 () import Data.ByteString.Lazy.Char8 ()
import Data.Char (isLower)
import Data.List (foldl', uncons) import Data.List (foldl', uncons)
#if __GLASGOW_HASKELL__ < 710 #if __GLASGOW_HASKELL__ < 710
import Control.Applicative ((<$>)) import Control.Applicative ((<$>))
#endif #endif
import Control.Monad (replicateM, void) import Control.Monad (replicateM, void)
import Data.Either (partitionEithers) import Data.Either (partitionEithers)
import Text.Parsec (parse, many1, many, eof, try, (<|>), option, sepBy1) import Text.Parsec (parse, many1, many, eof, try, option, sepBy1)
import Text.Parsec.Token (symbol)
import Text.ParserCombinators.Parsec.Char (alphaNum, spaces, string, char) import Text.ParserCombinators.Parsec.Char (alphaNum, spaces, string, char)
import Yesod.Routes.TH import Yesod.Routes.TH
@ -154,10 +152,8 @@ mkYesodGeneral' appCxt' namestr args isSub f resS = do
let (argtypes,cxt) = (\(ns,r,cs) -> (ns ++ fmap VarT r, cs)) $ let (argtypes,cxt) = (\(ns,r,cs) -> (ns ++ fmap VarT r, cs)) $
foldr (\arg (xs,vns',cs) -> foldr (\arg (xs,vns',cs) ->
case arg of case arg of
Left t@(h:_) | isLower h ->
( VarT (mkName t):xs, vns', cs )
Left t -> Left t ->
( ConT (mkName t):xs, vns', cs ) ( nameToType t:xs, vns', cs )
Right ts -> Right ts ->
let (n, ns) = maybe (error "mkYesodGeneral: Should be unreachable.") id $ uncons vns' in let (n, ns) = maybe (error "mkYesodGeneral: Should be unreachable.") id $ uncons vns' in
( VarT n : xs, ns ( VarT n : xs, ns
@ -170,7 +166,7 @@ mkYesodGeneral' appCxt' namestr args isSub f resS = do
) ts ++ cs ) ) ts ++ cs )
) ([],vns,[]) args ) ([],vns,[]) args
site = foldl' AppT (ConT name) argtypes site = foldl' AppT (ConT name) argtypes
res = map (fmap parseType) resS res = map (fmap (parseType . dropBracket)) resS
renderRouteDec <- mkRenderRouteInstance' appCxt site res renderRouteDec <- mkRenderRouteInstance' appCxt site res
routeAttrsDec <- mkRouteAttrsInstance' appCxt site res routeAttrsDec <- mkRouteAttrsInstance' appCxt site res
dispatchDec <- mkDispatchInstance site cxt f res dispatchDec <- mkDispatchInstance site cxt f res
@ -190,10 +186,6 @@ mkYesodGeneral' appCxt' namestr args isSub f resS = do
] ]
return (dataDec, dispatchDec) return (dataDec, dispatchDec)
where
nameToType t@(h:_) | isLower h = VarT $ mkName t
nameToType t = ConT $ mkName t
mkMDS :: (Exp -> Q Exp) -> Q Exp -> MkDispatchSettings a site b mkMDS :: (Exp -> Q Exp) -> Q Exp -> MkDispatchSettings a site b
mkMDS f rh = MkDispatchSettings mkMDS f rh = MkDispatchSettings
{ mdsRunHandler = rh { mdsRunHandler = rh

View File

@ -10,6 +10,8 @@ module Yesod.Routes.Parse
, parseType , parseType
, parseTypeTree , parseTypeTree
, TypeTree (..) , TypeTree (..)
, dropBracket
, nameToType
) where ) where
import Language.Haskell.TH.Syntax import Language.Haskell.TH.Syntax
@ -252,15 +254,18 @@ toTypeTree orig = do
gos' (front . (t:)) xs' gos' (front . (t:)) xs'
ttToType :: TypeTree -> Type ttToType :: TypeTree -> Type
ttToType (TTTerm s@(h:_)) | isLower h = VarT $ mkName s ttToType (TTTerm s) = nameToType s
ttToType (TTTerm s) = ConT $ mkName s
ttToType (TTApp x y) = ttToType x `AppT` ttToType y ttToType (TTApp x y) = ttToType x `AppT` ttToType y
ttToType (TTList t) = ListT `AppT` ttToType t ttToType (TTList t) = ListT `AppT` ttToType t
nameToType :: String -> Type
nameToType t@(h:_) | isLower h = VarT $ mkName t
nameToType t = ConT $ mkName t
pieceFromString :: String -> Either (CheckOverlap, String) (CheckOverlap, Piece String) pieceFromString :: String -> Either (CheckOverlap, String) (CheckOverlap, Piece String)
pieceFromString ('#':'!':x) = Right $ (False, dynamicPieceFromString x) pieceFromString ('#':'!':x) = Right $ (False, Dynamic $ dropBracket x)
pieceFromString ('!':'#':x) = Right $ (False, dynamicPieceFromString x) -- https://github.com/yesodweb/yesod/issues/652 pieceFromString ('!':'#':x) = Right $ (False, Dynamic $ dropBracket x) -- https://github.com/yesodweb/yesod/issues/652
pieceFromString ('#':x) = Right $ (True, dynamicPieceFromString x) pieceFromString ('#':x) = Right $ (True, Dynamic $ dropBracket x)
pieceFromString ('*':'!':x) = Left (False, x) pieceFromString ('*':'!':x) = Left (False, x)
pieceFromString ('+':'!':x) = Left (False, x) pieceFromString ('+':'!':x) = Left (False, x)
@ -274,9 +279,9 @@ pieceFromString ('+':x) = Left (True, x)
pieceFromString ('!':x) = Right $ (False, Static x) pieceFromString ('!':x) = Right $ (False, Static x)
pieceFromString x = Right $ (True, Static x) pieceFromString x = Right $ (True, Static x)
dynamicPieceFromString :: String -> Piece String dropBracket :: String -> String
dynamicPieceFromString str@('{':x) = case break (== '}') x of dropBracket str@('{':x) = case break (== '}') x of
(s, "}") -> Dynamic s (s, "}") -> s
_ -> error $ "Invalid path piece: " ++ str _ -> error $ "Unclosed bracket ('{'): " ++ str
dynamicPieceFromString x = Dynamic x dropBracket x = x
-- JP: Should we check if there are curly brackets or other invalid characters?

View File

@ -3,7 +3,6 @@ module Yesod.Routes.TH.RenderRoute
( -- ** RenderRoute ( -- ** RenderRoute
mkRenderRouteInstance mkRenderRouteInstance
, mkRenderRouteInstance' , mkRenderRouteInstance'
, mkRenderRouteInstance'
, mkRouteCons , mkRouteCons
, mkRenderRouteClauses , mkRenderRouteClauses
) where ) where