@@ -116,7 +116,7 @@ codeAction lsp state (TextDocumentIdentifier uri) _range CodeActionContext{_diag
116
116
| x <- xs
117
117
, Just ps <- [annotatedPS]
118
118
, Just dynflags <- [df]
119
- , (title, graft) <- suggestExactAction dynflags ps x
119
+ , (title, graft) <- suggestExactAction exportsMap dynflags ps x
120
120
, let edit = either error id $
121
121
rewriteToEdit dynflags uri (annsA ps) graft
122
122
]
@@ -173,14 +173,16 @@ commandHandler lsp _ideState ExecuteCommandParams{..}
173
173
= return (Right Null , Nothing )
174
174
175
175
suggestExactAction ::
176
+ ExportsMap ->
176
177
DynFlags ->
177
178
Annotated ParsedSource ->
178
179
Diagnostic ->
179
180
[(T. Text , Rewrite )]
180
- suggestExactAction df ps x =
181
+ suggestExactAction exportsMap df ps x =
181
182
concat
182
183
[ suggestConstraint df (astA ps) x
183
184
, suggestImplicitParameter (astA ps) x
185
+ , suggestExtendImport exportsMap (astA ps) x
184
186
]
185
187
186
188
suggestAction
@@ -193,7 +195,6 @@ suggestAction
193
195
suggestAction packageExports ideOptions parsedModule text diag = concat
194
196
-- Order these suggestions by priority
195
197
[ suggestSignature True diag
196
- , suggestExtendImport packageExports text diag
197
198
, suggestFillTypeWildcard diag
198
199
, suggestFixConstructorImport text diag
199
200
, suggestModuleTypo diag
@@ -725,32 +726,31 @@ getIndentedGroupsBy pred inp = case dropWhile (not.pred) inp of
725
726
indentation :: T. Text -> Int
726
727
indentation = T. length . T. takeWhile isSpace
727
728
728
- suggestExtendImport :: ExportsMap -> Maybe T. Text -> Diagnostic -> [(T. Text , [ TextEdit ] )]
729
- suggestExtendImport exportsMap contents Diagnostic {_range= _range,.. }
729
+ suggestExtendImport :: ExportsMap -> ParsedSource -> Diagnostic -> [(T. Text , Rewrite )]
730
+ suggestExtendImport exportsMap ( L _ HsModule {hsmodImports}) Diagnostic {_range= _range,.. }
730
731
| Just [binding, mod , srcspan] <-
731
732
matchRegexUnifySpaces _message
732
733
" Perhaps you want to add ‘([^’]*)’ to the import list in the import of ‘([^’]*)’ *\\ ((.*)\\ ).$"
733
- , Just c <- contents
734
- = suggestions c binding mod srcspan
734
+ = suggestions hsmodImports binding mod srcspan
735
735
| Just (binding, mod_srcspan) <-
736
736
matchRegExMultipleImports _message
737
- , Just c <- contents
738
- = mod_srcspan >>= (\ (x, y) -> suggestions c binding x y)
737
+ = mod_srcspan >>= uncurry (suggestions hsmodImports binding)
739
738
| otherwise = []
740
739
where
741
- suggestions c binding mod srcspan
740
+ unImportStyle (ImportTopLevel x) = (Nothing , T. unpack x)
741
+ unImportStyle (ImportViaParent x y) = (Just $ T. unpack y, T. unpack x)
742
+ suggestions decls binding mod srcspan
742
743
| range <- case [ x | (x," " ) <- readSrcSpan (T. unpack srcspan)] of
743
744
[s] -> let x = realSrcSpanToRange s
744
745
in x{_end = (_end x){_character = succ (_character (_end x))}}
745
746
_ -> error " bug in srcspan parser" ,
746
- importLine <- textInRange range c ,
747
+ Just decl <- findImportDeclByRange decls range ,
747
748
Just ident <- lookupExportMap binding mod
748
- = [ ( " Add " <> rendered <> " to the import list of " <> mod
749
- , [ TextEdit range result]
749
+ = [ ( " Add " <> renderImportStyle importStyle <> " to the import list of " <> mod
750
+ , uncurry extendImport (unImportStyle importStyle) decl
750
751
)
751
752
| importStyle <- NE. toList $ importStyles ident
752
- , let rendered = renderImportStyle importStyle
753
- , result <- maybeToList $ addBindingToImportList importStyle importLine]
753
+ ]
754
754
| otherwise = []
755
755
lookupExportMap binding mod
756
756
| Just match <- Map. lookup binding (getExportsMap exportsMap)
@@ -765,6 +765,9 @@ suggestExtendImport exportsMap contents Diagnostic{_range=_range,..}
765
765
, parent = Nothing
766
766
, isDatacon = False }
767
767
768
+ findImportDeclByRange :: [LImportDecl GhcPs ] -> Range -> Maybe (LImportDecl GhcPs )
769
+ findImportDeclByRange xs range = find (\ (L l _)-> srcSpanToRange l == Just range) xs
770
+
768
771
suggestFixConstructorImport :: Maybe T. Text -> Diagnostic -> [(T. Text , [TextEdit ])]
769
772
suggestFixConstructorImport _ Diagnostic {_range= _range,.. }
770
773
-- ‘Success’ is a data constructor of ‘Result’
@@ -1187,49 +1190,6 @@ rangesForBinding' b (L l (IEThingWith _ thing _ inners labels))
1187
1190
[ l' | L l' x <- labels, showSDocUnsafe (ppr x) == b]
1188
1191
rangesForBinding' _ _ = []
1189
1192
1190
- -- | Extends an import list with a new binding.
1191
- -- Assumes an import statement of the form:
1192
- -- import (qualified) A (..) ..
1193
- -- Places the new binding first, preserving whitespace.
1194
- -- Copes with multi-line import lists
1195
- addBindingToImportList :: ImportStyle -> T. Text -> Maybe T. Text
1196
- addBindingToImportList importStyle importLine =
1197
- case T. breakOn " (" importLine of
1198
- (pre, T. uncons -> Just (_, rest)) ->
1199
- case importStyle of
1200
- ImportTopLevel rendered ->
1201
- -- the binding has no parent, add it to the head of import list
1202
- Just $ T. concat [pre, " (" , rendered, addCommaIfNeeds rest]
1203
- ImportViaParent rendered parent -> case T. breakOn parent rest of
1204
- -- the binding has a parent, and the current import list contains the
1205
- -- parent
1206
- --
1207
- -- `rest'` could be 1. `,...)`
1208
- -- or 2. `(),...)`
1209
- -- or 3. `(ConsA),...)`
1210
- -- or 4. `)`
1211
- (leading, T. stripPrefix parent -> Just rest') -> case T. uncons (T. stripStart rest') of
1212
- -- case 1: no children and parentheses, e.g. `import A(Foo,...)` --> `import A(Foo(Cons), ...)`
1213
- Just (' ,' , rest'') -> Just $ T. concat [pre, " (" , leading, parent, " (" , rendered, " )" , addCommaIfNeeds rest'']
1214
- -- case 2: no children but parentheses, e.g. `import A(Foo(),...)` --> `import A(Foo(Cons), ...)`
1215
- Just (' (' , T. uncons -> Just (' )' , rest'')) -> Just $ T. concat [pre, " (" , leading, parent, " (" , rendered, " )" , rest'']
1216
- -- case 3: children with parentheses, e.g. `import A(Foo(ConsA),...)` --> `import A(Foo(Cons, ConsA), ...)`
1217
- Just (' (' , T. breakOn " )" -> (children, rest''))
1218
- | not (T. null children),
1219
- -- ignore A(Foo({-...-}), ...)
1220
- not $ " {-" `T.isPrefixOf` T. stripStart children
1221
- -> Just $ T. concat [pre, " (" , leading, parent, " (" , rendered, " , " , children, rest'']
1222
- -- case 4: no trailing, e.g. `import A(..., Foo)` --> `import A(..., Foo(Cons))`
1223
- Just (' )' , _) -> Just $ T. concat [pre, " (" , leading, parent, " (" , rendered, " )" , rest']
1224
- _ -> Nothing
1225
- -- current import list does not contain the parent, e.g. `import A(...)` --> `import A(Foo(Cons), ...)`
1226
- _ -> Just $ T. concat [pre, " (" , parent, " (" , rendered, " )" , addCommaIfNeeds rest]
1227
- _ -> Nothing
1228
- where
1229
- addCommaIfNeeds r = case T. uncons (T. stripStart r) of
1230
- Just (' )' , _) -> r
1231
- _ -> " , " <> r
1232
-
1233
1193
-- | 'matchRegex' combined with 'unifySpaces'
1234
1194
matchRegexUnifySpaces :: T. Text -> T. Text -> Maybe [T. Text ]
1235
1195
matchRegexUnifySpaces message = matchRegex (unifySpaces message)
@@ -1321,6 +1281,7 @@ data ImportStyle
1321
1281
--
1322
1282
-- @P@ and @?@ can be a data type and a constructor, a class and a method,
1323
1283
-- a class and an associated type/data family, etc.
1284
+ deriving Show
1324
1285
1325
1286
importStyles :: IdentInfo -> NonEmpty ImportStyle
1326
1287
importStyles IdentInfo {parent, rendered, isDatacon}
0 commit comments