@@ -58,6 +58,9 @@ import Development.IDE.Plugin.CodeAction.Util
58
58
import Development.IDE.Plugin.Completions.Types
59
59
import qualified Development.IDE.Plugin.Plugins.AddArgument
60
60
import 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
61
64
import Development.IDE.Plugin.TypeLenses (suggestSignature )
62
65
import Development.IDE.Types.Exports
63
66
import Development.IDE.Types.Location
@@ -72,7 +75,7 @@ import qualified Language.LSP.Server as LSP
72
75
import Language.LSP.Types (ApplyWorkspaceEditParams (.. ),
73
76
CodeAction (.. ),
74
77
CodeActionContext (CodeActionContext , _diagnostics ),
75
- CodeActionKind (CodeActionQuickFix , CodeActionUnknown ),
78
+ CodeActionKind (CodeActionQuickFix ),
76
79
CodeActionParams (CodeActionParams ),
77
80
Command ,
78
81
Diagnostic (.. ),
@@ -90,8 +93,7 @@ import Language.LSP.Types (ApplyWorkspa
90
93
import Language.LSP.VFS (VirtualFile ,
91
94
_file_text )
92
95
import qualified Text.Fuzzy.Parallel as TFP
93
- import Text.Regex.TDFA (mrAfter ,
94
- (=~) , (=~~) )
96
+ import Text.Regex.TDFA ((=~) , (=~~) )
95
97
#if MIN_VERSION_ghc(9,2,0)
96
98
import GHC (AddEpAnn (AddEpAnn ),
97
99
Anchor (anchor_op ),
@@ -915,17 +917,6 @@ newDefinitionAction IdeOptions {..} parsedModule Range {_start} name typ
915
917
ParsedModule {pm_parsed_source = L _ HsModule {hsmodDecls}} = parsedModule
916
918
917
919
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
-
929
920
{- Handles two variants with different formatting
930
921
931
922
1. Could not find module ‘Data.Cha’
@@ -953,88 +944,6 @@ suggestModuleTypo Diagnostic{_range=_range,..}
953
944
_ -> Nothing
954
945
955
946
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
-
1038
947
#if !MIN_VERSION_ghc(9,3,0)
1039
948
suggestExtendImport :: ExportsMap -> ParsedSource -> Diagnostic -> [(T. Text , CodeActionKind , Rewrite )]
1040
949
suggestExtendImport exportsMap (L _ HsModule {hsmodImports}) Diagnostic {_range= _range,.. }
@@ -1845,64 +1754,6 @@ mkRenameEdit contents range name
1845
1754
curr <- textInRange range <$> contents
1846
1755
pure $ " '" `T.isPrefixOf` curr
1847
1756
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
-
1906
1757
extractRenamableTerms :: T. Text -> [T. Text ]
1907
1758
extractRenamableTerms msg
1908
1759
-- Account for both "Variable not in scope" and "Not in scope"
@@ -2054,71 +1905,3 @@ matchRegExMultipleImports message = do
2054
1905
imps <- regExImports imports
2055
1906
return (binding, imps)
2056
1907
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