module Helium.StaticAnalysis.Messages.Warnings where
import Helium.Syntax.UHA_Range (getNameRange, showRange, sortRanges)
import Helium.Syntax.UHA_Syntax
import Helium.Syntax.UHA_Utils
import Top.Types
import Helium.StaticAnalysis.Messages.Messages
import Data.List (intercalate)
import qualified Helium.Syntax.UHA_Pretty as PP (sem_Pattern, wrap_Pattern, Inh_Pattern (..), Syn_Pattern (..), sem_LeftHandSide, wrap_LeftHandSide, Inh_LeftHandSide (..), Syn_LeftHandSide (..), sem_Expression, wrap_Expression, Inh_Expression (..), Syn_Expression (..))
import qualified Text.PrettyPrint.Leijen as PPrint
type Warnings = [Warning]
data Warning = NoTypeDef Name TpScheme Bool Bool
| Shadow Name Name
| Unused Entity Name
| SimilarFunctionBindings Name Name
| SuspiciousTypeVariable Name Name
| ReduceContext Range Predicates Predicates
| MissingPatterns Range (Maybe Name) Tp [[Pattern]] String String
| UnreachablePatternCase Range Pattern
| UnreachablePatternLHS LeftHandSide
| UnreachableGuard Range Expression
| FallThrough Range
| SignatureTooSpecific Name TpScheme TpScheme
instance HasMessage Warning where
getMessage x = let (oneliner, hints) = showWarning x
firstLine = MessageOneLiner (MessageCompose [MessageString "Warning: ", oneliner])
in [firstLine, MessageHints "Hint" hints]
getRanges warning = case warning of
NoTypeDef name _ _ _ -> [getNameRange name]
Shadow _ name -> [getNameRange name]
Unused _ name -> [getNameRange name]
SimilarFunctionBindings n1 n2 -> sortRanges [getNameRange n1, getNameRange n2]
SuspiciousTypeVariable name _ -> [getNameRange name]
ReduceContext rng _ _ -> [rng]
MissingPatterns rng _ _ _ _ _ -> [rng]
UnreachablePatternCase rng _ -> [rng]
UnreachableGuard rng _ -> [rng]
FallThrough rng -> [rng]
UnreachablePatternLHS (LeftHandSide_Function rng _ _ ) -> [rng]
UnreachablePatternLHS (LeftHandSide_Infix rng _ _ _) -> [rng]
UnreachablePatternLHS (LeftHandSide_Parenthesized rng _ _ ) -> [rng]
SignatureTooSpecific name _ _ -> [getNameRange name]
showWarning :: Warning -> (MessageBlock , MessageBlocks )
showWarning warning = case warning of
NoTypeDef name tpscheme _ simplePat ->
( MessageString ("Missing type signature: " ++ showNameAsVariable name ++ " :: " ++ show tpscheme)
, let hint = "Because " ++ showNameAsVariable name ++ " has an overloaded type, computations may be repeated. " ++
"Insert the missing type signature if this is indeed your intention."
in [ MessageString hint | simplePat ]
)
Shadow shadowee shadower ->
( MessageString ("Variable " ++ show (show shadower) ++ " shadows the one at " ++ showRange (getNameRange shadowee))
, []
)
Unused entity name ->
( MessageString (capitalize (show entity) ++ " " ++ show (show name) ++ " is not used")
, []
)
SimilarFunctionBindings suspect witness ->
( let [n1, n2] = sortNamesByRange [suspect, witness]
in MessageString ("Suspicious adjacent functions " ++ (show.show) n1 ++ " and " ++ (show.show) n2)
, []
)
SuspiciousTypeVariable varName conName ->
( MessageString ("Suspicious type variable " ++ (show.show) varName)
, [ MessageString ("Did you mean the type constructor " ++ (show.show) conName ++ " ?") ]
)
ReduceContext _ predicates reduced ->
let showPredicates ps = "(" ++ intercalate ", " (map show ps) ++ ")"
in ( MessageString ( "The context " ++ showPredicates predicates ++ " has superfluous predicates." )
, [ MessageString ("You may change it into " ++ showPredicates reduced ++ ".") ]
)
MissingPatterns _ Nothing _ pss place sym ->
let text = "Missing " ++ plural pss "pattern" ++ " in " ++ place ++ ": "
++ concatMap (("\n " ++).(++ (sym ++ " ...")).concatMap ((++ " ").show.semP)) pss
in (MessageString text, [])
MissingPatterns _ (Just n) _ pss place sym
| isOperatorName n ->
let name = getNameName n
text = "Missing " ++ plural pss "pattern" ++ " in " ++ place ++ ": "
++ concatMap (\[l, r] -> "\n " ++ (show.semP) l ++ " " ++ name ++ " "
++ (show.semP) r ++ " " ++ sym ++ " ...") pss
in (MessageString text, [])
| otherwise ->
let name = getNameName n
text = "Missing " ++ plural pss "pattern" ++ " in " ++ place ++ ": "
++ concatMap (("\n " ++).(name ++).(' ' :).(++ (sym ++ " ...")).concatMap ((++ " ").show.semP)) pss
in (MessageString text, [])
UnreachablePatternLHS lhs ->
( MessageString ("Unreachable pattern: " ++ show (PP.text_Syn_LeftHandSide (PP.wrap_LeftHandSide (PP.sem_LeftHandSide lhs) PP.Inh_LeftHandSide)))
, []
)
UnreachablePatternCase _ p ->
( MessageString ("Unreachable pattern: " ++ (show.semP ) p)
, []
)
UnreachableGuard _ e ->
( MessageString ("Unreachable guard: | " ++ show (PP.text_Syn_Expression (PP.wrap_Expression (PP.sem_Expression e) PP.Inh_Expression)))
, []
)
FallThrough _ ->
( MessageString "It is good practise to have 'otherwise' as the last guard"
, []
)
SignatureTooSpecific name signature scheme ->
( MessageCompose
[ MessageString (
"Declared type signature for "++show (show name)++" could be more general\n"++
" declared type : ")
, MessageType signature
, MessageString ('\n' : " inferred type : ")
, MessageType scheme
]
, []
)
plural :: [a] -> String -> String
plural [_] = id
plural _ = (++ "s")
semP :: Pattern -> PPrint.Doc
semP p = PP.text_Syn_Pattern (PP.wrap_Pattern (PP.sem_Pattern p) PP.Inh_Pattern)