weedTypeDec :: String -> TypeDec -> WeedError
weedTypeDec filename (CLS modifiers name _ _ constructors fields methods info)
  | all (`elem` modifiers) ["abstract", "final"] = Just $ "Cannot have a class that is abstract AND final" ++ show info
  | (nub modifiers) /= modifiers = Just $ "Class modifiers cannot be repeated" ++ show info
  | "private" `elem` modifiers = Just $ "Classes cannot be private" ++ show info
  | not (any (`elem` modifiers) ["public", "protected"]) = Just $ "Class must have acces modifier" ++ show info
  | methodError /= Nothing = methodError
  | fieldError /= Nothing = fieldError
  | constructorError /= Nothing = constructorError
  | name /= correctName = Just $ "Expected class to be named '" ++ correctName ++ "' but saw '" ++ name ++ "'" ++ show info
  | shouldBeAbstract && not ("abstract" `elem` modifiers) = Just $ name ++ " has an abstract method but isn't abstract"
  | otherwise = Nothing
  where methodError = weedClassMethods methods
        fieldError = weedFields fields
        constructorError = msum $ map weedConstructor constructors
        fileName = last $ splitOneOf "/" filename
        fileNameSplit = splitOneOf "." fileName
        correctName = foldl (++) "" (take ((length fileNameSplit) - 1) fileNameSplit)
        shouldBeAbstract = any (\mthd -> "abstract" `elem` (methodModifiers mthd)) methods
weedTypeDec :: String -> TypeDec -> WeedError
weedTypeDec filename (CLS modifiers name _ _ constructors fields methods info)
  | all (`elem` modifiers) ["abstract", "final"] = Just $ "Cannot have a class that is abstract AND final" ++ show info
  | (nub modifiers) /= modifiers = Just $ "Class modifiers cannot be repeated" ++ show info
  | "private" `elem` modifiers = Just $ "Classes cannot be private" ++ show info
  | not (any (`elem` modifiers) ["public", "protected"]) = Just $ "Class must have acces modifier" ++ show info
  | methodError /= Nothing = methodError
  | fieldError /= Nothing = fieldError
  | constructorError /= Nothing = constructorError
  | name /= correctName = Just $ "Expected class to be named '" ++ correctName ++ "' but saw '" ++ name ++ "'" ++ show info
  | shouldBeAbstract && not ("abstract" `elem` modifiers) = Just $ name ++ " has an abstract method but isn't abstract"
  | otherwise = Nothing
  where methodError = weedClassMethods methods
        fieldError = weedFields fields
        constructorError = msum $ map weedConstructor constructors
        fileName = last $ splitOneOf "/" filename
        fileNameSplit = splitOneOf "." fileName
        correctName = foldl (++) "" (take ((length fileNameSplit) - 1) fileNameSplit)
        shouldBeAbstract = any (\mthd -> "abstract" `elem` (methodModifiers mthd)) methods
weedTypeDec filename (CLS modifiers name _ _ constructors fields methods info)
  | all (`elem` modifiers) ["abstract", "final"] = Just $ "Cannot have a class that is abstract AND final" ++ show info
  | (nub modifiers) /= modifiers = Just $ "Class modifiers cannot be repeated" ++ show info
  | "private" `elem` modifiers = Just $ "Classes cannot be private" ++ show info
  | not (any (`elem` modifiers) ["public", "protected"]) = Just $ "Class must have acces modifier" ++ show info
  | methodError /= Nothing = methodError
  | fieldError /= Nothing = fieldError
  | constructorError /= Nothing = constructorError
  | name /= correctName = Just $ "Expected class to be named '" ++ correctName ++ "' but saw '" ++ name ++ "'" ++ show info
  | shouldBeAbstract && not ("abstract" `elem` modifiers) = Just $ name ++ " has an abstract method but isn't abstract"
  | otherwise = Nothing
  where methodError = weedClassMethods methods
        fieldError = weedFields fields
        constructorError = msum $ map weedConstructor constructors
        fileName = last $ splitOneOf "/" filename
        fileNameSplit = splitOneOf "." fileName
        correctName = foldl (++) "" (take ((length fileNameSplit) - 1) fileNameSplit)
        shouldBeAbstract = any (\mthd -> "abstract" `elem` (methodModifiers mthd)) methods