module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.MultiParamTypeClassesChecker where
import Control.Reference ((^.))
import Language.Haskell.Tools.Refactor
import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.ExtMonad
chkMultiParamTypeClassesDecl :: CheckNode Decl
chkMultiParamTypeClassesDecl = conditional chkMultiParamTypeClassesDecl' MultiParamTypeClasses
chkMultiParamTypeClassesDecl' :: CheckNode Decl
chkMultiParamTypeClassesDecl' cd@(ClassDecl _ dh _ _)
| n <- length . collectTyVars $ dh
, n /= 1 = addEvidence MultiParamTypeClasses dh >> return cd
chkMultiParamTypeClassesDecl' i@(InstanceDecl rule _)
| isMultiParamNeeded (rule ^. irHead)
= addEvidence MultiParamTypeClasses rule >> return i
chkMultiParamTypeClassesDecl' d = return d
collectTyVars :: DeclHead -> [TyVar]
collectTyVars (ParenDeclHead dh) = collectTyVars dh
collectTyVars (DeclHeadApp dh tv) = tv : collectTyVars dh
collectTyVars (InfixDeclHead lhs _ rhs) = [lhs,rhs]
collectTyVars _ = []
isMultiParamNeeded :: InstanceHead -> Bool
isMultiParamNeeded InstanceHead{} = True
isMultiParamNeeded InfixInstanceHead{} = True
isMultiParamNeeded (ParenInstanceHead ih) = isMultiParamNeeded ih
isMultiParamNeeded (AppInstanceHead f _) = isMultiParamNeeded' f
where isMultiParamNeeded' InstanceHead{} = False
isMultiParamNeeded' InfixInstanceHead{} = True
isMultiParamNeeded' (ParenInstanceHead ih) = isMultiParamNeeded' ih
isMultiParamNeeded' (AppInstanceHead _ _) = True