@@ -58,6 +58,9 @@ import Development.IDE.Plugin.CodeAction.Util
5858import Development.IDE.Plugin.Completions.Types
5959import qualified Development.IDE.Plugin.Plugins.AddArgument
6060import Development.IDE.Plugin.Plugins.Diagnostic
61+ import Development.IDE.Plugin.Plugins.FillHole (suggestFillHole )
62+ import Development.IDE.Plugin.Plugins.FillTypeWildcard (suggestFillTypeWildcard )
63+ import Development.IDE.Plugin.Plugins.ImportUtils
6164import Development.IDE.Plugin.TypeLenses (suggestSignature )
6265import Development.IDE.Types.Exports
6366import Development.IDE.Types.Location
@@ -72,7 +75,7 @@ import qualified Language.LSP.Server as LSP
7275import Language.LSP.Types (ApplyWorkspaceEditParams (.. ),
7376 CodeAction (.. ),
7477 CodeActionContext (CodeActionContext , _diagnostics ),
75- CodeActionKind (CodeActionQuickFix , CodeActionUnknown ),
78+ CodeActionKind (CodeActionQuickFix ),
7679 CodeActionParams (CodeActionParams ),
7780 Command ,
7881 Diagnostic (.. ),
@@ -90,8 +93,7 @@ import Language.LSP.Types (ApplyWorkspa
9093import Language.LSP.VFS (VirtualFile ,
9194 _file_text )
9295import qualified Text.Fuzzy.Parallel as TFP
93- import Text.Regex.TDFA (mrAfter ,
94- (=~) , (=~~) )
96+ import Text.Regex.TDFA ((=~) , (=~~) )
9597#if MIN_VERSION_ghc(9,2,0)
9698import GHC (AddEpAnn (AddEpAnn ),
9799 Anchor (anchor_op ),
@@ -915,17 +917,6 @@ newDefinitionAction IdeOptions {..} parsedModule Range {_start} name typ
915917 ParsedModule {pm_parsed_source = L _ HsModule {hsmodDecls}} = parsedModule
916918
917919
918- suggestFillTypeWildcard :: Diagnostic -> [(T. Text , TextEdit )]
919- suggestFillTypeWildcard Diagnostic {_range= _range,.. }
920- -- Foo.hs:3:8: error:
921- -- * Found type wildcard `_' standing for `p -> p1 -> p'
922-
923- | " Found type wildcard" `T.isInfixOf` _message
924- , " standing for " `T.isInfixOf` _message
925- , typeSignature <- extractWildCardTypeSignature _message
926- = [(" Use type signature: ‘" <> typeSignature <> " ’" , TextEdit _range typeSignature)]
927- | otherwise = []
928-
929920{- Handles two variants with different formatting
930921
9319221. Could not find module ‘Data.Cha’
@@ -953,88 +944,6 @@ suggestModuleTypo Diagnostic{_range=_range,..}
953944 _ -> Nothing
954945
955946
956- suggestFillHole :: Diagnostic -> [(T. Text , TextEdit )]
957- suggestFillHole Diagnostic {_range= _range,.. }
958- | Just holeName <- extractHoleName _message
959- , (holeFits, refFits) <- processHoleSuggestions (T. lines _message) =
960- let isInfixHole = _message =~ addBackticks holeName :: Bool in
961- map (proposeHoleFit holeName False isInfixHole) holeFits
962- ++ map (proposeHoleFit holeName True isInfixHole) refFits
963- | otherwise = []
964- where
965- extractHoleName = fmap head . flip matchRegexUnifySpaces " Found hole: ([^ ]*)"
966- addBackticks text = " `" <> text <> " `"
967- addParens text = " (" <> text <> " )"
968- proposeHoleFit holeName parenthise isInfixHole name =
969- let isInfixOperator = T. head name == ' ('
970- name' = getOperatorNotation isInfixHole isInfixOperator name in
971- ( " replace " <> holeName <> " with " <> name
972- , TextEdit _range (if parenthise then addParens name' else name')
973- )
974- getOperatorNotation True False name = addBackticks name
975- getOperatorNotation True True name = T. drop 1 (T. dropEnd 1 name)
976- getOperatorNotation _isInfixHole _isInfixOperator name = name
977-
978- processHoleSuggestions :: [T. Text ] -> ([T. Text ], [T. Text ])
979- processHoleSuggestions mm = (holeSuggestions, refSuggestions)
980- {-
981- • Found hole: _ :: LSP.Handlers
982-
983- Valid hole fits include def
984- Valid refinement hole fits include
985- fromMaybe (_ :: LSP.Handlers) (_ :: Maybe LSP.Handlers)
986- fromJust (_ :: Maybe LSP.Handlers)
987- haskell-lsp-types-0.22.0.0:Language.LSP.Types.Window.$sel:_value:ProgressParams (_ :: ProgressParams
988- LSP.Handlers)
989- T.foldl (_ :: LSP.Handlers -> Char -> LSP.Handlers)
990- (_ :: LSP.Handlers)
991- (_ :: T.Text)
992- T.foldl' (_ :: LSP.Handlers -> Char -> LSP.Handlers)
993- (_ :: LSP.Handlers)
994- (_ :: T.Text)
995- -}
996- where
997- t = id @ T. Text
998- holeSuggestions = do
999- -- get the text indented under Valid hole fits
1000- validHolesSection <-
1001- getIndentedGroupsBy (=~ t " *Valid (hole fits|substitutions) include" ) mm
1002- -- the Valid hole fits line can contain a hole fit
1003- holeFitLine <-
1004- mapHead
1005- (mrAfter . (=~ t " *Valid (hole fits|substitutions) include" ))
1006- validHolesSection
1007- let holeFit = T. strip $ T. takeWhile (/= ' :' ) holeFitLine
1008- guard (not $ T. null holeFit)
1009- return holeFit
1010- refSuggestions = do -- @[]
1011- -- get the text indented under Valid refinement hole fits
1012- refinementSection <-
1013- getIndentedGroupsBy (=~ t " *Valid refinement hole fits include" ) mm
1014- -- get the text for each hole fit
1015- holeFitLines <- getIndentedGroups (tail refinementSection)
1016- let holeFit = T. strip $ T. unwords holeFitLines
1017- guard $ not $ holeFit =~ t " Some refinement hole fits suppressed"
1018- return holeFit
1019-
1020- mapHead f (a: aa) = f a : aa
1021- mapHead _ [] = []
1022-
1023- -- > getIndentedGroups [" H1", " l1", " l2", " H2", " l3"] = [[" H1,", " l1", " l2"], [" H2", " l3"]]
1024- getIndentedGroups :: [T. Text ] -> [[T. Text ]]
1025- getIndentedGroups [] = []
1026- getIndentedGroups ll@ (l: _) = getIndentedGroupsBy ((== indentation l) . indentation) ll
1027- -- |
1028- -- > getIndentedGroupsBy (" H" `isPrefixOf`) [" H1", " l1", " l2", " H2", " l3"] = [[" H1", " l1", " l2"], [" H2", " l3"]]
1029- getIndentedGroupsBy :: (T. Text -> Bool ) -> [T. Text ] -> [[T. Text ]]
1030- getIndentedGroupsBy pred inp = case dropWhile (not . pred ) inp of
1031- (l: ll) -> case span (\ l' -> indentation l < indentation l') ll of
1032- (indented, rest) -> (l: indented) : getIndentedGroupsBy pred rest
1033- _ -> []
1034-
1035- indentation :: T. Text -> Int
1036- indentation = T. length . T. takeWhile isSpace
1037-
1038947#if !MIN_VERSION_ghc(9,3,0)
1039948suggestExtendImport :: ExportsMap -> ParsedSource -> Diagnostic -> [(T. Text , CodeActionKind , Rewrite )]
1040949suggestExtendImport exportsMap (L _ HsModule {hsmodImports}) Diagnostic {_range= _range,.. }
@@ -1845,64 +1754,6 @@ mkRenameEdit contents range name
18451754 curr <- textInRange range <$> contents
18461755 pure $ " '" `T.isPrefixOf` curr
18471756
1848- -- | Extract the type and surround it in parentheses except in obviously safe cases.
1849- --
1850- -- Inferring when parentheses are actually needed around the type signature would
1851- -- require understanding both the precedence of the context of the hole and of
1852- -- the signature itself. Inserting them (almost) unconditionally is ugly but safe.
1853- extractWildCardTypeSignature :: T. Text -> T. Text
1854- extractWildCardTypeSignature msg
1855- | enclosed || not isApp || isToplevelSig = sig
1856- | otherwise = " (" <> sig <> " )"
1857- where
1858- msgSigPart = snd $ T. breakOnEnd " standing for " msg
1859- (sig, rest) = T. span (/= ' ’' ) . T. dropWhile (== ' ‘' ) . T. dropWhile (/= ' ‘' ) $ msgSigPart
1860- -- If we're completing something like ‘foo :: _’ parens can be safely omitted.
1861- isToplevelSig = errorMessageRefersToToplevelHole rest
1862- -- Parenthesize type applications, e.g. (Maybe Char).
1863- isApp = T. any isSpace sig
1864- -- Do not add extra parentheses to lists, tuples and already parenthesized types.
1865- enclosed = not (T. null sig) && (T. head sig, T. last sig) `elem` [(' (' , ' )' ), (' [' , ' ]' )]
1866-
1867- -- | Detect whether user wrote something like @foo :: _@ or @foo :: (_, Int)@.
1868- -- The former is considered toplevel case for which the function returns 'True',
1869- -- the latter is not toplevel and the returned value is 'False'.
1870- --
1871- -- When type hole is at toplevel then there’s a line starting with
1872- -- "• In the type signature" which ends with " :: _" like in the
1873- -- following snippet:
1874- --
1875- -- source/library/Language/Haskell/Brittany/Internal.hs:131:13: error:
1876- -- • Found type wildcard ‘_’ standing for ‘HsDecl GhcPs’
1877- -- To use the inferred type, enable PartialTypeSignatures
1878- -- • In the type signature: decl :: _
1879- -- In an equation for ‘splitAnnots’:
1880- -- splitAnnots m@HsModule {hsmodAnn, hsmodDecls}
1881- -- = undefined
1882- -- where
1883- -- ann :: SrcSpanAnnA
1884- -- decl :: _
1885- -- L ann decl = head hsmodDecls
1886- -- • Relevant bindings include
1887- -- [REDACTED]
1888- --
1889- -- When type hole is not at toplevel there’s a stack of where
1890- -- the hole was located ending with "In the type signature":
1891- --
1892- -- source/library/Language/Haskell/Brittany/Internal.hs:130:20: error:
1893- -- • Found type wildcard ‘_’ standing for ‘GhcPs’
1894- -- To use the inferred type, enable PartialTypeSignatures
1895- -- • In the first argument of ‘HsDecl’, namely ‘_’
1896- -- In the type ‘HsDecl _’
1897- -- In the type signature: decl :: HsDecl _
1898- -- • Relevant bindings include
1899- -- [REDACTED]
1900- errorMessageRefersToToplevelHole :: T. Text -> Bool
1901- errorMessageRefersToToplevelHole msg =
1902- not (T. null prefix) && " :: _" `T.isSuffixOf` T. takeWhile (/= ' \n ' ) rest
1903- where
1904- (prefix, rest) = T. breakOn " • In the type signature:" msg
1905-
19061757extractRenamableTerms :: T. Text -> [T. Text ]
19071758extractRenamableTerms msg
19081759 -- Account for both "Variable not in scope" and "Not in scope"
@@ -2054,71 +1905,3 @@ matchRegExMultipleImports message = do
20541905 imps <- regExImports imports
20551906 return (binding, imps)
20561907
2057- -- | Possible import styles for an 'IdentInfo'.
2058- --
2059- -- The first 'Text' parameter corresponds to the 'rendered' field of the
2060- -- 'IdentInfo'.
2061- data ImportStyle
2062- = ImportTopLevel T. Text
2063- -- ^ Import a top-level export from a module, e.g., a function, a type, a
2064- -- class.
2065- --
2066- -- > import M (?)
2067- --
2068- -- Some exports that have a parent, like a type-class method or an
2069- -- associated type/data family, can still be imported as a top-level
2070- -- import.
2071- --
2072- -- Note that this is not the case for constructors, they must always be
2073- -- imported as part of their parent data type.
2074-
2075- | ImportViaParent T. Text T. Text
2076- -- ^ Import an export (first parameter) through its parent (second
2077- -- parameter).
2078- --
2079- -- import M (P(?))
2080- --
2081- -- @P@ and @?@ can be a data type and a constructor, a class and a method,
2082- -- a class and an associated type/data family, etc.
2083-
2084- | ImportAllConstructors T. Text
2085- -- ^ Import all constructors for a specific data type.
2086- --
2087- -- import M (P(..))
2088- --
2089- -- @P@ can be a data type or a class.
2090- deriving Show
2091-
2092- importStyles :: IdentInfo -> NonEmpty ImportStyle
2093- importStyles IdentInfo {parent, rendered, isDatacon}
2094- | Just p <- parent
2095- -- Constructors always have to be imported via their parent data type, but
2096- -- methods and associated type/data families can also be imported as
2097- -- top-level exports.
2098- = ImportViaParent rendered p
2099- :| [ImportTopLevel rendered | not isDatacon]
2100- <> [ImportAllConstructors p]
2101- | otherwise
2102- = ImportTopLevel rendered :| []
2103-
2104- -- | Used for adding new imports
2105- renderImportStyle :: ImportStyle -> T. Text
2106- renderImportStyle (ImportTopLevel x) = x
2107- renderImportStyle (ImportViaParent x p@ (T. uncons -> Just (' (' , _))) = " type " <> p <> " (" <> x <> " )"
2108- renderImportStyle (ImportViaParent x p) = p <> " (" <> x <> " )"
2109- renderImportStyle (ImportAllConstructors p) = p <> " (..)"
2110-
2111- -- | Used for extending import lists
2112- unImportStyle :: ImportStyle -> (Maybe String , String )
2113- unImportStyle (ImportTopLevel x) = (Nothing , T. unpack x)
2114- unImportStyle (ImportViaParent x y) = (Just $ T. unpack y, T. unpack x)
2115- unImportStyle (ImportAllConstructors x) = (Just $ T. unpack x, wildCardSymbol)
2116-
2117-
2118- quickFixImportKind' :: T. Text -> ImportStyle -> CodeActionKind
2119- quickFixImportKind' x (ImportTopLevel _) = CodeActionUnknown $ " quickfix.import." <> x <> " .list.topLevel"
2120- quickFixImportKind' x (ImportViaParent _ _) = CodeActionUnknown $ " quickfix.import." <> x <> " .list.withParent"
2121- quickFixImportKind' x (ImportAllConstructors _) = CodeActionUnknown $ " quickfix.import." <> x <> " .list.allConstructors"
2122-
2123- quickFixImportKind :: T. Text -> CodeActionKind
2124- quickFixImportKind x = CodeActionUnknown $ " quickfix.import." <> x
0 commit comments