@@ -38,7 +38,6 @@ import Data.Ord (comparing)
38
38
import qualified Data.Set as S
39
39
import qualified Data.Text as T
40
40
import qualified Data.Text.Utf16.Rope as Rope
41
- import Data.Tuple.Extra (first )
42
41
import Development.IDE.Core.Rules
43
42
import Development.IDE.Core.RuleTypes
44
43
import Development.IDE.Core.Service
@@ -57,6 +56,7 @@ import Development.IDE.Plugin.CodeAction.ExactPrint
57
56
import Development.IDE.Plugin.CodeAction.PositionIndexed
58
57
import Development.IDE.Plugin.CodeAction.Util
59
58
import Development.IDE.Plugin.Completions.Types
59
+ import qualified Development.IDE.Plugin.Plugins.AddArgument
60
60
import Development.IDE.Plugin.TypeLenses (suggestSignature )
61
61
import Development.IDE.Types.Exports
62
62
import Development.IDE.Types.Location
@@ -65,8 +65,7 @@ import Development.IDE.Types.Logger hiding
65
65
import Development.IDE.Types.Options
66
66
import GHC.Exts (fromList )
67
67
import qualified GHC.LanguageExtensions as Lang
68
- import Ide.PluginUtils (makeDiffTextEdit ,
69
- subRange )
68
+ import Ide.PluginUtils (subRange )
70
69
import Ide.Types
71
70
import qualified Language.LSP.Server as LSP
72
71
import Language.LSP.Types (ApplyWorkspaceEditParams (.. ),
@@ -92,15 +91,8 @@ import Language.LSP.VFS (VirtualFile,
92
91
import qualified Text.Fuzzy.Parallel as TFP
93
92
import Text.Regex.TDFA (mrAfter ,
94
93
(=~) , (=~~) )
95
- #if MIN_VERSION_ghc(9,2,1)
96
- import Data.Either.Extra (maybeToEither )
97
- import GHC.Types.SrcLoc (generatedSrcSpan )
98
- import Language.Haskell.GHC.ExactPrint (noAnnSrcSpanDP1 ,
99
- runTransformT )
100
- #endif
101
94
#if MIN_VERSION_ghc(9,2,0)
102
- import Control.Monad.Except (lift )
103
- import Debug.Trace
95
+ import Development.IDE.Plugin.Plugins.Diagnostic
104
96
import GHC (AddEpAnn (AddEpAnn ),
105
97
Anchor (anchor_op ),
106
98
AnchorOperation (.. ),
@@ -109,17 +101,7 @@ import GHC (AddEpAnn (Ad
109
101
EpAnn (.. ),
110
102
EpaLocation (.. ),
111
103
LEpaComment ,
112
- LocatedA ,
113
- SrcSpanAnn' (SrcSpanAnn ),
114
- SrcSpanAnnA ,
115
- SrcSpanAnnN ,
116
- TrailingAnn (.. ),
117
- addTrailingAnnToA ,
118
- emptyComments ,
119
- noAnn )
120
- import GHC.Hs (IsUnicodeSyntax (.. ))
121
- import Language.Haskell.GHC.ExactPrint.Transform (d1 )
122
-
104
+ LocatedA )
123
105
#else
124
106
import Language.Haskell.GHC.ExactPrint.Types (Annotation (annsDP ),
125
107
DeltaPos ,
@@ -190,7 +172,7 @@ bindingsPluginDescriptor recorder plId = mkExactprintPluginDescriptor recorder $
190
172
#endif
191
173
, wrap suggestNewDefinition
192
174
#if MIN_VERSION_ghc(9,2,1)
193
- , wrap suggestAddArgument
175
+ , wrap Development.IDE.Plugin.Plugins.AddArgument. plugin
194
176
#endif
195
177
, wrap suggestDeleteUnusedBinding
196
178
]
@@ -905,34 +887,6 @@ suggestReplaceIdentifier contents Diagnostic{_range=_range,..}
905
887
= [ (" Replace with ‘" <> name <> " ’" , [mkRenameEdit contents _range name]) | name <- renameSuggestions ]
906
888
| otherwise = []
907
889
908
- matchVariableNotInScope :: T. Text -> Maybe (T. Text , Maybe T. Text )
909
- matchVariableNotInScope message
910
- -- * Variable not in scope:
911
- -- suggestAcion :: Maybe T.Text -> Range -> Range
912
- -- * Variable not in scope:
913
- -- suggestAcion
914
- | Just (name, typ) <- matchVariableNotInScopeTyped message = Just (name, Just typ)
915
- | Just name <- matchVariableNotInScopeUntyped message = Just (name, Nothing )
916
- | otherwise = Nothing
917
- where
918
- matchVariableNotInScopeTyped message
919
- | Just [name, typ] <- matchRegexUnifySpaces message " Variable not in scope: ([^ ]+) :: ([^*•]+)" =
920
- Just (name, typ)
921
- | otherwise = Nothing
922
- matchVariableNotInScopeUntyped message
923
- | Just [name] <- matchRegexUnifySpaces message " Variable not in scope: ([^ ]+)" =
924
- Just name
925
- | otherwise = Nothing
926
-
927
- matchFoundHole :: T. Text -> Maybe (T. Text , T. Text )
928
- matchFoundHole message
929
- | Just [name, typ] <- matchRegexUnifySpaces message " Found hole: _([^ ]+) :: ([^*•]+) Or perhaps" =
930
- Just (name, typ)
931
- | otherwise = Nothing
932
-
933
- matchFoundHoleIncludeUnderscore :: T. Text -> Maybe (T. Text , T. Text )
934
- matchFoundHoleIncludeUnderscore message = first (" _" <> ) <$> matchFoundHole message
935
-
936
890
suggestNewDefinition :: IdeOptions -> ParsedModule -> Maybe T. Text -> Diagnostic -> [(T. Text , [TextEdit ])]
937
891
suggestNewDefinition ideOptions parsedModule contents Diagnostic {_message, _range}
938
892
| Just (name, typ) <- matchVariableNotInScope message =
@@ -962,121 +916,6 @@ newDefinitionAction IdeOptions {..} parsedModule Range {_start} name typ
962
916
sig = name <> colon <> T. dropWhileEnd isSpace (fromMaybe " _" typ)
963
917
ParsedModule {pm_parsed_source = L _ HsModule {hsmodDecls}} = parsedModule
964
918
965
- #if MIN_VERSION_ghc(9,2,1)
966
- -- When GHC tells us that a variable is not bound, it will tell us either:
967
- -- - there is an unbound variable with a given type
968
- -- - there is an unbound variable (GHC provides no type suggestion)
969
- --
970
- -- When we receive either of these errors, we produce a text edit that will add a new argument (as a new pattern in the
971
- -- last position of each LHS of the top-level bindings for this HsDecl).
972
- --
973
- -- NOTE When adding a new argument to a declaration, the corresponding argument's type in declaration's signature might
974
- -- not be the last type in the signature, such as:
975
- -- foo :: a -> b -> c -> d
976
- -- foo a b = \c -> ...
977
- -- In this case a new argument would have to add its type between b and c in the signature.
978
- suggestAddArgument :: ParsedModule -> Diagnostic -> Either ResponseError [(T. Text , [TextEdit ])]
979
- suggestAddArgument parsedModule Diagnostic {_message, _range}
980
- | Just (name, typ) <- matchVariableNotInScope message = addArgumentAction parsedModule _range name typ
981
- | Just (name, typ) <- matchFoundHoleIncludeUnderscore message = addArgumentAction parsedModule _range name (Just typ)
982
- | otherwise = pure []
983
- where
984
- message = unifySpaces _message
985
-
986
- -- Given a name for the new binding, add a new pattern to the match in the last position,
987
- -- returning how many patterns there were in this match prior to the transformation:
988
- -- addArgToMatch "foo" `bar arg1 arg2 = ...`
989
- -- => (`bar arg1 arg2 foo = ...`, 2)
990
- addArgToMatch :: T. Text -> GenLocated l (Match GhcPs body ) -> (GenLocated l (Match GhcPs body ), Int )
991
- addArgToMatch name (L locMatch (Match xMatch ctxMatch pats rhs)) =
992
- let unqualName = mkRdrUnqual $ mkVarOcc $ T. unpack name
993
- newPat = L (noAnnSrcSpanDP1 generatedSrcSpan) $ VarPat NoExtField (noLocA unqualName)
994
- in (L locMatch (Match xMatch ctxMatch (pats <> [newPat]) rhs), length pats)
995
-
996
- -- Attempt to insert a binding pattern into each match for the given LHsDecl; succeeds only if the function is a FunBind.
997
- -- Also return:
998
- -- - the declaration's name
999
- -- - the number of bound patterns in the declaration's matches prior to the transformation
1000
- --
1001
- -- For example:
1002
- -- insertArg "new_pat" `foo bar baz = 1`
1003
- -- => (`foo bar baz new_pat = 1`, Just ("foo", 2))
1004
- appendFinalPatToMatches :: T. Text -> LHsDecl GhcPs -> TransformT (Either ResponseError ) (LHsDecl GhcPs , Maybe (GenLocated SrcSpanAnnN RdrName , Int ))
1005
- appendFinalPatToMatches name = \ case
1006
- (L locDecl (ValD xVal (FunBind xFunBind idFunBind mg coreFunBind))) -> do
1007
- (mg', numPatsMay) <- modifyMgMatchesT' mg (pure . second Just . addArgToMatch name) Nothing combineMatchNumPats
1008
- numPats <- lift $ maybeToEither (responseError " Unexpected empty match group in HsDecl" ) numPatsMay
1009
- let decl' = L locDecl (ValD xVal (FunBind xFunBind idFunBind mg' coreFunBind))
1010
- pure (decl', Just (idFunBind, numPats))
1011
- decl -> pure (decl, Nothing )
1012
- where
1013
- combineMatchNumPats Nothing other = pure other
1014
- combineMatchNumPats other Nothing = pure other
1015
- combineMatchNumPats (Just l) (Just r)
1016
- | l == r = pure (Just l)
1017
- | otherwise = Left $ responseError " Unexpected different numbers of patterns in HsDecl MatchGroup"
1018
-
1019
- -- The add argument works as follows:
1020
- -- 1. Attempt to add the given name as the last pattern of the declaration that contains `range`.
1021
- -- 2. If such a declaration exists, use that declaration's name to modify the signature of said declaration, if it
1022
- -- has a type signature.
1023
- --
1024
- -- NOTE For the following situation, the type signature is not updated (it's unclear what should happen):
1025
- -- type FunctionTySyn = () -> Int
1026
- -- foo :: FunctionTySyn
1027
- -- foo () = new_def
1028
- --
1029
- -- TODO instead of inserting a typed hole; use GHC's suggested type from the error
1030
- addArgumentAction :: ParsedModule -> Range -> T. Text -> Maybe T. Text -> Either ResponseError [(T. Text , [TextEdit ])]
1031
- addArgumentAction (ParsedModule _ moduleSrc _ _) range name _typ = do
1032
- (newSource, _, _) <- runTransformT $ do
1033
- (moduleSrc', join -> matchedDeclNameMay) <- addNameAsLastArgOfMatchingDecl (makeDeltaAst moduleSrc)
1034
- case matchedDeclNameMay of
1035
- Just (matchedDeclName, numPats) -> modifySigWithM (unLoc matchedDeclName) (addTyHoleToTySigArg numPats) moduleSrc'
1036
- Nothing -> pure moduleSrc'
1037
- let diff = makeDiffTextEdit (T. pack $ exactPrint moduleSrc) (T. pack $ exactPrint newSource)
1038
- pure [(" Add argument ‘" <> name <> " ’ to function" , fromLspList diff)]
1039
- where
1040
- addNameAsLastArgOfMatchingDecl = modifySmallestDeclWithM spanContainsRangeOrErr addNameAsLastArg
1041
- addNameAsLastArg = fmap (first (: [] )) . appendFinalPatToMatches name
1042
-
1043
- spanContainsRangeOrErr = maybeToEither (responseError " SrcSpan was not valid range" ) . (`spanContainsRange` range)
1044
-
1045
- -- Transform an LHsType into a list of arguments and return type, to make transformations easier.
1046
- hsTypeToFunTypeAsList :: LHsType GhcPs -> ([(SrcSpanAnnA , XFunTy GhcPs , HsArrow GhcPs , LHsType GhcPs )], LHsType GhcPs )
1047
- hsTypeToFunTypeAsList = \ case
1048
- L spanAnnA (HsFunTy xFunTy arrow lhs rhs) ->
1049
- let (rhsArgs, rhsRes) = hsTypeToFunTypeAsList rhs
1050
- in ((spanAnnA, xFunTy, arrow, lhs): rhsArgs, rhsRes)
1051
- ty -> ([] , ty)
1052
-
1053
- -- The inverse of `hsTypeToFunTypeAsList`
1054
- hsTypeFromFunTypeAsList :: ([(SrcSpanAnnA , XFunTy GhcPs , HsArrow GhcPs , LHsType GhcPs )], LHsType GhcPs ) -> LHsType GhcPs
1055
- hsTypeFromFunTypeAsList (args, res) =
1056
- foldr (\ (spanAnnA, xFunTy, arrow, argTy) res -> L spanAnnA $ HsFunTy xFunTy arrow argTy res) res args
1057
-
1058
- -- Add a typed hole to a type signature in the given argument position:
1059
- -- 0 `foo :: ()` => foo :: _ -> ()
1060
- -- 2 `foo :: FunctionTySyn` => foo :: FunctionTySyn
1061
- -- 1 `foo :: () -> () -> Int` => foo :: () -> _ -> () -> Int
1062
- addTyHoleToTySigArg :: Int -> LHsSigType GhcPs -> (LHsSigType GhcPs )
1063
- addTyHoleToTySigArg loc (L annHsSig (HsSig xHsSig tyVarBndrs lsigTy)) =
1064
- let (args, res) = hsTypeToFunTypeAsList lsigTy
1065
- wildCardAnn = SrcSpanAnn (EpAnn genAnchor1 (AnnListItem [AddRarrowAnn d1]) emptyComments) generatedSrcSpan
1066
- newArg = (SrcSpanAnn mempty generatedSrcSpan, noAnn, HsUnrestrictedArrow NormalSyntax , L wildCardAnn $ HsWildCardTy noExtField)
1067
- -- NOTE if the location that the argument wants to be placed at is not one more than the number of arguments
1068
- -- in the signature, then we return the original type signature.
1069
- -- This situation most likely occurs due to a function type synonym in the signature
1070
- insertArg n _ | n < 0 = error " Not possible"
1071
- insertArg 0 as = newArg: as
1072
- insertArg _ [] = []
1073
- insertArg n (a: as) = a : insertArg (n - 1 ) as
1074
- lsigTy' = hsTypeFromFunTypeAsList (insertArg loc args, res)
1075
- in L annHsSig (HsSig xHsSig tyVarBndrs lsigTy')
1076
-
1077
- fromLspList :: List a -> [a ]
1078
- fromLspList (List a) = a
1079
- #endif
1080
919
1081
920
suggestFillTypeWildcard :: Diagnostic -> [(T. Text , TextEdit )]
1082
921
suggestFillTypeWildcard Diagnostic {_range= _range,.. }
@@ -2169,29 +2008,16 @@ rangesForBinding' b (L (locA -> l) (IEThingWith _ thing _ inners))
2169
2008
#endif
2170
2009
rangesForBinding' _ _ = []
2171
2010
2172
- -- | 'matchRegex' combined with 'unifySpaces'
2173
- matchRegexUnifySpaces :: T. Text -> T. Text -> Maybe [T. Text ]
2174
- matchRegexUnifySpaces message = matchRegex (unifySpaces message)
2175
-
2176
2011
-- | 'allMatchRegex' combined with 'unifySpaces'
2177
2012
allMatchRegexUnifySpaces :: T. Text -> T. Text -> Maybe [[T. Text ]]
2178
2013
allMatchRegexUnifySpaces message =
2179
2014
allMatchRegex (unifySpaces message)
2180
2015
2181
- -- | Returns Just (the submatches) for the first capture, or Nothing.
2182
- matchRegex :: T. Text -> T. Text -> Maybe [T. Text ]
2183
- matchRegex message regex = case message =~~ regex of
2184
- Just (_ :: T. Text , _ :: T. Text , _ :: T. Text , bindings ) -> Just bindings
2185
- Nothing -> Nothing
2186
-
2187
2016
-- | Returns Just (all matches) for the first capture, or Nothing.
2188
2017
allMatchRegex :: T. Text -> T. Text -> Maybe [[T. Text ]]
2189
2018
allMatchRegex message regex = message =~~ regex
2190
2019
2191
2020
2192
- unifySpaces :: T. Text -> T. Text
2193
- unifySpaces = T. unwords . T. words
2194
-
2195
2021
-- functions to help parse multiple import suggestions
2196
2022
2197
2023
-- | Returns the first match if found
0 commit comments