module Language.Haskell.Tools.Refactor.Builtin.GetMatches where
import Language.Haskell.Tools.Refactor
import Control.Monad.Writer
import Control.Reference
import Data.Aeson
import Outputable as GHC
import SrcLoc as GHC
import Id as GHC
import Type as GHC
import TyCon as GHC
import DataCon as GHC
getMatchesQuery :: QueryChoice
getMatchesQuery = LocationQuery "GetMatches" getMatches
getMatches :: RealSrcSpan -> ModuleDom -> [ModuleDom] -> QueryMonad Value
getMatches sp (_,mod) _
= case selectedName of [n] -> do ctors <- getCtors $ idType $ semanticsId n
return $ toJSON ctors
[] -> queryError "No name is selected."
_ -> queryError "Multiple names are selected."
where
selectedName :: [QualifiedName]
selectedName = mod ^? nodesContaining sp
getCtors :: GHC.Type -> QueryMonad [(String, [String])]
-- | TODO: unpack forall, context types
-- | TODO: care for infix constructors
getCtors t | Just (tc, _) <- splitTyConApp_maybe t
= maybe (queryError (noSuccessMsg t)) (return . map formatCtor) (tyConDataCons_maybe tc)
getCtors t = queryError (noSuccessMsg t)
noSuccessMsg :: GHC.Type -> String
noSuccessMsg t = "Cannot find the constructors of type " ++ showSDocUnsafe (ppr t)
formatCtor :: DataCon -> (String, [String])
formatCtor dc = (showSDocUnsafe $ ppr $ dataConName dc, createArgNames (dataConOrigArgTys dc))
-- | TODO: Check for names in scope
-- | TODO: Create names based on the type
createArgNames :: [GHC.Type] -> [String]
createArgNames tys = map (\i -> "p" ++ show i) [1..length tys]