weedClassMethod :: Method -> WeedError
weedClassMethod (MTD modifiers var params definition info)
  | (nub modifiers) /= modifiers = Just $ "Method modifiers cannot be repeated" ++ show info
  | length (filter (`elem` modifiers) ["public", "protected"]) /= 1 = Just $ "One and only one access modifier is allowed" ++ show info
  | all (`elem` modifiers) ["static", "final"] = Just $ "A static method cannot be final" ++ show info
  | ("native" `elem` modifiers) && not ("static" `elem` modifiers) = Just $ "Native methods must be static" ++ show info
  | "private" `elem` modifiers = Just $ "Methods cannot be private" ++ show info
  | "abstract" `elem` modifiers && "static" `elem` modifiers = Just $ "Abstract methods cannot be static" ++ show info
  | "abstract" `elem` modifiers && "final" `elem` modifiers = Just $ "Abstract methods cannot be final" ++ show info
  | "abstract" `elem` modifiers && "native" `elem` modifiers = Just $ "Abstract methods cannot be native" ++ show info
  | "abstract" `elem` modifiers && "strictfp" `elem` modifiers = Just $ "Abstract methods cannot be strictfp" ++ show info
  | "abstract" `elem` modifiers && "synchronized" `elem` modifiers = Just $ "Abstract methods cannot be synchronized" ++ show info
  | "native" `elem` modifiers && "strictfp" `elem` modifiers = Just $ "Native methods cannot be strictfp" ++ show info
  | any (`elem` modifiers) ["abstract", "native"] && isJust definition = Just $ "Abstract/Native methods cannot have a body" ++ show info
  | not (any (`elem` modifiers) ["abstract", "native"]) && isNothing definition = Just $ "Non-abstract non-native methods must have a body" ++ show info
  | isJust bodyError = bodyError
  | otherwise = Nothing
  where bodyError = weedStatementBlock definition
weedClassMethod :: Method -> WeedError
weedClassMethod (MTD modifiers var params definition info)
  | (nub modifiers) /= modifiers = Just $ "Method modifiers cannot be repeated" ++ show info
  | length (filter (`elem` modifiers) ["public", "protected"]) /= 1 = Just $ "One and only one access modifier is allowed" ++ show info
  | all (`elem` modifiers) ["static", "final"] = Just $ "A static method cannot be final" ++ show info
  | ("native" `elem` modifiers) && not ("static" `elem` modifiers) = Just $ "Native methods must be static" ++ show info
  | "private" `elem` modifiers = Just $ "Methods cannot be private" ++ show info
  | "abstract" `elem` modifiers && "static" `elem` modifiers = Just $ "Abstract methods cannot be static" ++ show info
  | "abstract" `elem` modifiers && "final" `elem` modifiers = Just $ "Abstract methods cannot be final" ++ show info
  | "abstract" `elem` modifiers && "native" `elem` modifiers = Just $ "Abstract methods cannot be native" ++ show info
  | "abstract" `elem` modifiers && "strictfp" `elem` modifiers = Just $ "Abstract methods cannot be strictfp" ++ show info
  | "abstract" `elem` modifiers && "synchronized" `elem` modifiers = Just $ "Abstract methods cannot be synchronized" ++ show info
  | "native" `elem` modifiers && "strictfp" `elem` modifiers = Just $ "Native methods cannot be strictfp" ++ show info
  | any (`elem` modifiers) ["abstract", "native"] && isJust definition = Just $ "Abstract/Native methods cannot have a body" ++ show info
  | not (any (`elem` modifiers) ["abstract", "native"]) && isNothing definition = Just $ "Non-abstract non-native methods must have a body" ++ show info
  | isJust bodyError = bodyError
  | otherwise = Nothing
  where bodyError = weedStatementBlock definition
weedClassMethod (MTD modifiers var params definition info)
  | (nub modifiers) /= modifiers = Just $ "Method modifiers cannot be repeated" ++ show info
  | length (filter (`elem` modifiers) ["public", "protected"]) /= 1 = Just $ "One and only one access modifier is allowed" ++ show info
  | all (`elem` modifiers) ["static", "final"] = Just $ "A static method cannot be final" ++ show info
  | ("native" `elem` modifiers) && not ("static" `elem` modifiers) = Just $ "Native methods must be static" ++ show info
  | "private" `elem` modifiers = Just $ "Methods cannot be private" ++ show info
  | "abstract" `elem` modifiers && "static" `elem` modifiers = Just $ "Abstract methods cannot be static" ++ show info
  | "abstract" `elem` modifiers && "final" `elem` modifiers = Just $ "Abstract methods cannot be final" ++ show info
  | "abstract" `elem` modifiers && "native" `elem` modifiers = Just $ "Abstract methods cannot be native" ++ show info
  | "abstract" `elem` modifiers && "strictfp" `elem` modifiers = Just $ "Abstract methods cannot be strictfp" ++ show info
  | "abstract" `elem` modifiers && "synchronized" `elem` modifiers = Just $ "Abstract methods cannot be synchronized" ++ show info
  | "native" `elem` modifiers && "strictfp" `elem` modifiers = Just $ "Native methods cannot be strictfp" ++ show info
  | any (`elem` modifiers) ["abstract", "native"] && isJust definition = Just $ "Abstract/Native methods cannot have a body" ++ show info
  | not (any (`elem` modifiers) ["abstract", "native"]) && isNothing definition = Just $ "Non-abstract non-native methods must have a body" ++ show info
  | isJust bodyError = bodyError
  | otherwise = Nothing
  where bodyError = weedStatementBlock definition