module Language.Java.Reflect.Types where
import Data.Int
import Data.Data
import Data.List (nub)
data JavaType
= JBoolean
| JChar
| JByte
| JShort
| JInt
| JLong
| JFloat
| JDouble
| JObj {
typeName :: String
}
| JArr {
componentType :: JavaType
}
deriving (Eq, Ord, Show, Read, Data, Typeable)
printJavaType :: JavaType -> String
printJavaType t = case t of
JBoolean -> "boolean"
JChar -> "char"
JByte -> "byte"
JShort -> "short"
JInt -> "int"
JLong -> "long"
JFloat -> "float"
JDouble -> "double"
JObj n -> n
JArr c -> printJavaType c ++ "[]"
data JavaClass = JavaClass {
className :: String,
classParents :: [String],
classIfaces :: [String],
classConstructors :: [JavaConstructor],
classMethods :: [JavaMethod],
classFields :: [JavaField],
classTypeParams :: [JavaTypeParam],
classEnum :: Bool,
classEnumConstants :: [(Int32, String)],
classIface :: Bool,
classAnnotation :: Bool,
classAbstract :: Bool,
classFinal :: Bool
} deriving (Eq, Show, Read, Data, Typeable)
data JavaClassType = Annotation | Interface | Enum | Class | Exception | Error
deriving (Eq, Ord, Show, Read, Data, Typeable)
classType :: JavaClass -> JavaClassType
classType clazz
| "java.lang.Error" `elem` classParents clazz = Error
| "java.lang.Exception" `elem` classParents clazz = Exception
| classAnnotation clazz = Annotation
| classIface clazz = Interface
| classEnum clazz = Enum
| otherwise = Class
classDependencies :: JavaClass -> [String]
classDependencies clazz = concat [
classParents clazz,
classIfaces clazz,
concatMap (fieldDependencies typeParams) (classFields clazz),
concatMap (methodDependencies typeParams) (classMethods clazz),
concatMap (constructorDependencies typeParams) (classConstructors clazz) ]
where typeParams = classTypeParams clazz
data JavaTypeParam = JavaTypeParam {
paramName :: TyVar,
paramBounds :: [JavaGenericType]
} deriving (Eq, Ord, Show, Read, Data, Typeable)
newtype TyVar = TyVar { tyVarName :: String }
deriving (Eq, Ord, Show, Read, Data, Typeable)
data JavaGenericType
=
Wildcard {
jgtBounds :: [JavaGenericType],
jgtLowerBounds :: [JavaGenericType]
}
|
Parameterized {
jgtBasetype :: String,
jgtParameters :: [JavaGenericType]
}
|
GenericArray {
jgtComponentType :: JavaGenericType
}
|
TypeVarReference {
jgtName :: TyVar
}
| NotSoGeneric
deriving (Eq, Ord, Show, Read, Data, Typeable)
data JavaGenericTypeType = WildcardT
| ParameterizedT
| GenericArrayT
| TypeVarReferenceT
| NotSoGenericT
jgtType :: JavaGenericType -> JavaGenericTypeType
jgtType t = case t of
(Wildcard _ _) -> WildcardT
(Parameterized _ _) -> ParameterizedT
(GenericArray _) -> GenericArrayT
(TypeVarReference _) -> TypeVarReferenceT
NotSoGeneric -> NotSoGenericT
data JavaField = JavaField {
fieldName :: String,
fieldType :: (JavaType, JavaGenericType),
fieldFinal :: Bool,
fieldStatic :: Bool
} deriving (Eq, Show, Read, Data, Typeable)
fieldDependencies :: [JavaTypeParam] -> JavaField -> [String]
fieldDependencies tvars field = dependencies tvars [fieldType field]
data JavaMethod = JavaMethod {
methodName :: String,
methodName' :: String,
methodParams :: [(JavaType, JavaGenericType)],
methodReturnType :: (Maybe JavaType, JavaGenericType),
methodExceptions :: [String],
methodTypeParams :: [JavaTypeParam],
methodStatic :: Bool,
methodAbstract :: Bool,
methodFinal :: Bool,
methodNative :: Bool,
methodSynchronized :: Bool
} deriving (Eq, Show, Read, Data, Typeable)
methodDependencies :: [JavaTypeParam] -> JavaMethod -> [String]
methodDependencies tvars method = returnDependency ++ dependencies tvars' (methodParams method)
where returnDependency = case methodReturnType method of
(Nothing, _) -> []
(Just t, gt) -> dependencies tvars' [(t, gt)]
tvars' = methodTypeParams method ++ tvars
data JavaConstructor = JavaConstructor {
constructorParams :: [(JavaType, JavaGenericType)],
constructorExceptions :: [String],
constructorTypeParams :: [JavaTypeParam]
} deriving (Eq, Show, Read, Data, Typeable)
constructorDependencies :: [JavaTypeParam] -> JavaConstructor -> [String]
constructorDependencies tvars constr = dependencies tvars' (constructorParams constr)
where tvars' = constructorTypeParams constr ++ tvars
dependencies :: [JavaTypeParam] -> [(JavaType, JavaGenericType)] -> [String]
dependencies tyvars = nub . foldr (\(t, gt) ds -> deps t ++ gdeps tyvars gt ++ ds) []
where
deps t = case t of
JObj c -> [c]
JArr c -> deps c
_ -> []
gdeps :: [JavaTypeParam] -> JavaGenericType -> [String]
gdeps tv t = case jgtType t of
WildcardT
-> concatMap (gdeps tv) (jgtBounds t ++ jgtLowerBounds t)
ParameterizedT
-> jgtBasetype t : concatMap (gdeps tv) (jgtParameters t)
GenericArrayT
-> (gdeps tv) (jgtComponentType t)
TypeVarReferenceT
-> maybe [] (concatMap (gdeps tv') . paramBounds)
(lookup tvName (zip (map paramName tv) tyvars))
NotSoGenericT -> []
where tvName = jgtName t
tv' = filter ((/= tvName) . paramName) tv