module Development.IDE.Plugin.Plugins.FillTypeWildcard
( suggestFillTypeWildcard
) where
import Data.Char
import qualified Data.Text as T
import Language.LSP.Types (Diagnostic (..), TextEdit (TextEdit))
suggestFillTypeWildcard :: Diagnostic -> [(T.Text, TextEdit)]
suggestFillTypeWildcard :: Diagnostic -> [(Text, TextEdit)]
suggestFillTypeWildcard Diagnostic{$sel:_range:Diagnostic :: Diagnostic -> Range
_range=Range
_range,Maybe Text
Maybe (List DiagnosticTag)
Maybe (List DiagnosticRelatedInformation)
Maybe DiagnosticSeverity
Maybe (Int32 |? Text)
Text
$sel:_relatedInformation:Diagnostic :: Diagnostic -> Maybe (List DiagnosticRelatedInformation)
$sel:_tags:Diagnostic :: Diagnostic -> Maybe (List DiagnosticTag)
$sel:_message:Diagnostic :: Diagnostic -> Text
$sel:_source:Diagnostic :: Diagnostic -> Maybe Text
$sel:_code:Diagnostic :: Diagnostic -> Maybe (Int32 |? Text)
$sel:_severity:Diagnostic :: Diagnostic -> Maybe DiagnosticSeverity
_relatedInformation :: Maybe (List DiagnosticRelatedInformation)
_tags :: Maybe (List DiagnosticTag)
_message :: Text
_source :: Maybe Text
_code :: Maybe (Int32 |? Text)
_severity :: Maybe DiagnosticSeverity
..}
| Text
"Found type wildcard" Text -> Text -> Bool
`T.isInfixOf` Text
_message
, Text
" standing for " Text -> Text -> Bool
`T.isInfixOf` Text
_message
, Text
typeSignature <- Text -> Text
extractWildCardTypeSignature Text
_message
= [(Text
"Use type signature: ‘" forall a. Semigroup a => a -> a -> a
<> Text
typeSignature forall a. Semigroup a => a -> a -> a
<> Text
"’", Range -> Text -> TextEdit
TextEdit Range
_range Text
typeSignature)]
| Bool
otherwise = []
extractWildCardTypeSignature :: T.Text -> T.Text
Text
msg
| Bool
enclosed Bool -> Bool -> Bool
|| Bool -> Bool
not Bool
isApp Bool -> Bool -> Bool
|| Bool
isToplevelSig = Text
sig
| Bool
otherwise = Text
"(" forall a. Semigroup a => a -> a -> a
<> Text
sig forall a. Semigroup a => a -> a -> a
<> Text
")"
where
msgSigPart :: Text
msgSigPart = forall a b. (a, b) -> b
snd forall a b. (a -> b) -> a -> b
$ Text -> Text -> (Text, Text)
T.breakOnEnd Text
"standing for " Text
msg
(Text
sig, Text
rest) = (Char -> Bool) -> Text -> (Text, Text)
T.span (forall a. Eq a => a -> a -> Bool
/=Char
'’') forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> Text -> Text
T.dropWhile (forall a. Eq a => a -> a -> Bool
==Char
'‘') forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> Text -> Text
T.dropWhile (forall a. Eq a => a -> a -> Bool
/=Char
'‘') forall a b. (a -> b) -> a -> b
$ Text
msgSigPart
isToplevelSig :: Bool
isToplevelSig = Text -> Bool
errorMessageRefersToToplevelHole Text
rest
isApp :: Bool
isApp = (Char -> Bool) -> Text -> Bool
T.any Char -> Bool
isSpace Text
sig
enclosed :: Bool
enclosed =
case Text -> Maybe (Char, Text)
T.uncons Text
sig of
Maybe (Char, Text)
Nothing -> forall a. HasCallStack => [Char] -> a
error [Char]
"GHC provided invalid type"
Just (Char
firstChr, Text
_) -> Bool -> Bool
not (Text -> Bool
T.null Text
sig) Bool -> Bool -> Bool
&& (Char
firstChr, Text -> Char
T.last Text
sig) forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [(Char
'(', Char
')'), (Char
'[', Char
']')]
errorMessageRefersToToplevelHole :: T.Text -> Bool
errorMessageRefersToToplevelHole :: Text -> Bool
errorMessageRefersToToplevelHole Text
msg =
Bool -> Bool
not (Text -> Bool
T.null Text
prefix) Bool -> Bool -> Bool
&& Text
" :: _" Text -> Text -> Bool
`T.isSuffixOf` (Char -> Bool) -> Text -> Text
T.takeWhile (forall a. Eq a => a -> a -> Bool
/= Char
'\n') Text
rest
where
(Text
prefix, Text
rest) = Text -> Text -> (Text, Text)
T.breakOn Text
"• In the type signature:" Text
msg