@@ -1561,15 +1561,57 @@ mkRenameEdit contents range name =
15611561-- require understanding both the precedence of the context of the hole and of
15621562-- the signature itself. Inserting them (almost) unconditionally is ugly but safe.
15631563extractWildCardTypeSignature :: T. Text -> T. Text
1564- extractWildCardTypeSignature msg = (if enclosed || not application then id else bracket) signature
1564+ extractWildCardTypeSignature msg
1565+ | enclosed || not isApp || isToplevelSig = sig
1566+ | otherwise = " (" <> sig <> " )"
15651567 where
1566- msgSigPart = snd $ T. breakOnEnd " standing for " msg
1567- signature = T. takeWhile (/= ' ’' ) . T. dropWhile (== ' ‘' ) . T. dropWhile (/= ' ‘' ) $ msgSigPart
1568- -- parenthesize type applications, e.g. (Maybe Char)
1569- application = any isSpace . T. unpack $ signature
1570- -- do not add extra parentheses to lists, tuples and already parenthesized types
1571- enclosed = not (T. null signature) && (T. head signature, T. last signature) `elem` [(' (' ,' )' ), (' [' ,' ]' )]
1572- bracket = (" (" `T.append` ) . (`T.append` " )" )
1568+ msgSigPart = snd $ T. breakOnEnd " standing for " msg
1569+ (sig, rest) = T. span (/= ' ’' ) . T. dropWhile (== ' ‘' ) . T. dropWhile (/= ' ‘' ) $ msgSigPart
1570+ -- If we're completing something like ‘foo :: _’ parens can be safely omitted.
1571+ isToplevelSig = errorMessageRefersToToplevelHole rest
1572+ -- Parenthesize type applications, e.g. (Maybe Char).
1573+ isApp = T. any isSpace sig
1574+ -- Do not add extra parentheses to lists, tuples and already parenthesized types.
1575+ enclosed = not (T. null sig) && (T. head sig, T. last sig) `elem` [(' (' , ' )' ), (' [' , ' ]' )]
1576+
1577+ -- | Detect whether user wrote something like @foo :: _@ or @foo :: (_, Int)@.
1578+ -- The former is considered toplevel case for which the function returns 'True',
1579+ -- the latter is not toplevel and the returned value is 'False'.
1580+ --
1581+ -- When type hole is at toplevel then there’s a line starting with
1582+ -- "• In the type signature" which ends with " :: _" like in the
1583+ -- following snippet:
1584+ --
1585+ -- source/library/Language/Haskell/Brittany/Internal.hs:131:13: error:
1586+ -- • Found type wildcard ‘_’ standing for ‘HsDecl GhcPs’
1587+ -- To use the inferred type, enable PartialTypeSignatures
1588+ -- • In the type signature: decl :: _
1589+ -- In an equation for ‘splitAnnots’:
1590+ -- splitAnnots m@HsModule {hsmodAnn, hsmodDecls}
1591+ -- = undefined
1592+ -- where
1593+ -- ann :: SrcSpanAnnA
1594+ -- decl :: _
1595+ -- L ann decl = head hsmodDecls
1596+ -- • Relevant bindings include
1597+ -- [REDACTED]
1598+ --
1599+ -- When type hole is not at toplevel there’s a stack of where
1600+ -- the hole was located ending with "In the type signature":
1601+ --
1602+ -- source/library/Language/Haskell/Brittany/Internal.hs:130:20: error:
1603+ -- • Found type wildcard ‘_’ standing for ‘GhcPs’
1604+ -- To use the inferred type, enable PartialTypeSignatures
1605+ -- • In the first argument of ‘HsDecl’, namely ‘_’
1606+ -- In the type ‘HsDecl _’
1607+ -- In the type signature: decl :: HsDecl _
1608+ -- • Relevant bindings include
1609+ -- [REDACTED]
1610+ errorMessageRefersToToplevelHole :: T. Text -> Bool
1611+ errorMessageRefersToToplevelHole msg =
1612+ not (T. null prefix) && " :: _" `T.isSuffixOf` T. takeWhile (/= ' \n ' ) rest
1613+ where
1614+ (prefix, rest) = T. breakOn " • In the type signature:" msg
15731615
15741616extractRenamableTerms :: T. Text -> [T. Text ]
15751617extractRenamableTerms msg
0 commit comments