Skip to content

Commit 6eafe90

Browse files
committed
Fix parens
1 parent 66f1094 commit 6eafe90

File tree

1 file changed

+48
-16
lines changed

1 file changed

+48
-16
lines changed

ghcide/src/Development/IDE/Plugin/CodeAction/ExactPrint.hs

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import Language.Haskell.GHC.ExactPrint
3030
import Language.Haskell.GHC.ExactPrint.Types (DeltaPos (DP), KeywordId (G), mkAnnKey)
3131
import Language.Haskell.LSP.Types
3232
import OccName
33+
import Outputable (ppr, showSDocUnsafe)
3334

3435
------------------------------------------------------------------------------
3536

@@ -176,12 +177,26 @@ lastMaybe :: [a] -> Maybe a
176177
lastMaybe [] = Nothing
177178
lastMaybe other = Just $ last other
178179

180+
liftMaybe :: String -> Maybe a -> TransformT (Either String) a
181+
liftMaybe _ (Just x) = return x
182+
liftMaybe s _ = lift $ Left s
183+
184+
-- | Copy anns attached to a into b with modification, then delete anns of a
185+
transferAnn :: (Data a, Data b) => Located a -> Located b -> (Annotation -> Annotation) -> TransformT (Either String) ()
186+
transferAnn la lb f = do
187+
anns <- getAnnsT
188+
let oldKey = mkAnnKey la
189+
newKey = mkAnnKey lb
190+
oldValue <- liftMaybe "Unable to find ann" $ Map.lookup oldKey anns
191+
putAnnsT $ Map.delete oldKey $ Map.insert newKey (f oldValue) anns
192+
179193
------------------------------------------------------------------------------
180194
extendImport :: Maybe String -> String -> LImportDecl GhcPs -> Rewrite
181-
extendImport mparent identifier lDecl@(L l _) = Rewrite l $ \df -> do
182-
case mparent of
183-
Just parent -> extendImportViaParent df parent identifier lDecl
184-
_ -> extendImportTopLevel df identifier lDecl
195+
extendImport mparent identifier lDecl@(L l _) =
196+
Rewrite l $ \df -> do
197+
case mparent of
198+
Just parent -> extendImportViaParent df parent identifier lDecl
199+
_ -> extendImportTopLevel df identifier lDecl
185200

186201
-- | Add an identifier to import list
187202
--
@@ -201,7 +216,11 @@ extendImportTopLevel df idnetifier (L l it@ImportDecl {..})
201216
when hasSibling $
202217
addTrailingCommaT (last lies)
203218
addSimpleAnnT x (DP (0, if hasSibling then 1 else 0)) []
204-
addSimpleAnnT rdr dp00 [(G AnnVal, dp00)]
219+
addSimpleAnnT rdr dp00 $ unqalDP $ hasParen idnetifier
220+
-- Parens are attachted to `lies`, so if `lies` was empty previously,
221+
-- we need change the ann key from `[]` to `:` to keep parens and other anns.
222+
unless hasSibling $
223+
transferAnn (L l' lies) (L l' [x]) id
205224
return $ L l it {ideclHiding = Just (hide, L l' $ lies ++ [x])}
206225
extendImportTopLevel _ _ _ = lift $ Left "Unable to extend the import list"
207226

@@ -219,21 +238,18 @@ extendImportViaParent df parent child (L l it@ImportDecl {..})
219238
where
220239
go :: Bool -> SrcSpan -> [LIE GhcPs] -> [LIE GhcPs] -> TransformT (Either String) (LImportDecl GhcPs)
221240
go hide l' pre (lAbs@(L ll' (IEThingAbs _ absIE@(L _ ie))) : xs)
222-
-- ThingAbs => ThingWith ie child
241+
-- ThingAbs ie => ThingWith ie child
223242
| parent == unIEWrappedName ie = do
224243
srcChild <- uniqueSrcSpanT
225244
childRdr <- liftParseAST df child
226245
let childLIE = L srcChild $ IEName childRdr
227246
x :: LIE GhcPs = L ll' $ IEThingWith noExtField absIE NoIEWildcard [childLIE] []
228-
modifyAnnsT $ \anns ->
229-
let oldKey = mkAnnKey lAbs
230-
oldValue = anns Map.! oldKey
231-
newKey = mkAnnKey x
232-
in Map.insert newKey oldValue {annsDP = annsDP oldValue ++ [(G AnnOpenP, DP (0, 1)), (G AnnCloseP, dp00)]} $ Map.delete oldKey anns
247+
-- take anns from ThingAbs, and attatch parens to it
248+
transferAnn lAbs x $ \old -> old {annsDP = annsDP old ++ [(G AnnOpenP, DP (0, 1)), (G AnnCloseP, dp00)]}
233249
addSimpleAnnT childRdr dp00 [(G AnnVal, dp00)]
234250
return $ L l it {ideclHiding = Just (hide, L l' $ reverse pre ++ [x] ++ xs)}
235251
go hide l' pre ((L l'' (IEThingWith _ twIE@(L _ ie) _ lies' _)) : xs)
236-
-- ThingWith ie => ThingWith ie (lies' ++ [child])
252+
-- ThingWith ie lies' => ThingWith ie (lies' ++ [child])
237253
| parent == unIEWrappedName ie,
238254
hasSibling <- not $ null lies' =
239255
do
@@ -242,7 +258,7 @@ extendImportViaParent df parent child (L l it@ImportDecl {..})
242258
when hasSibling $
243259
addTrailingCommaT (last lies')
244260
let childLIE = L srcChild $ IEName childRdr
245-
addSimpleAnnT childRdr (DP (0, if hasSibling then 1 else 0)) [(G AnnVal, dp00)]
261+
addSimpleAnnT childRdr (DP (0, if hasSibling then 1 else 0)) $ unqalDP $ hasParen child
246262
return $ L l it {ideclHiding = Just (hide, L l' $ reverse pre ++ [L l'' (IEThingWith noExtField twIE NoIEWildcard (lies' ++ [childLIE]) [])] ++ xs)}
247263
go hide l' pre (x : xs) = go hide l' (x : pre) xs
248264
go hide l' pre []
@@ -258,11 +274,27 @@ extendImportViaParent df parent child (L l it@ImportDecl {..})
258274
let parentLIE = L srcParent $ IEName parentRdr
259275
childLIE = L srcChild $ IEName childRdr
260276
x :: LIE GhcPs = L l'' $ IEThingWith noExtField parentLIE NoIEWildcard [childLIE] []
261-
addSimpleAnnT parentRdr (DP (0, if hasSibling then 1 else 0)) [(G AnnVal, DP (0, 0))]
262-
addSimpleAnnT childRdr (DP (0, 0)) [(G AnnVal, DP (0, 0))]
277+
addSimpleAnnT parentRdr (DP (0, if hasSibling then 1 else 0)) $ unqalDP $ hasParen parent
278+
addSimpleAnnT childRdr (DP (0, 0)) $ unqalDP $ hasParen child
263279
addSimpleAnnT x (DP (0, 0)) [(G AnnOpenP, DP (0, 1)), (G AnnCloseP, DP (0, 0))]
280+
-- Parens are attachted to `pre`, so if `pre` was empty previously,
281+
-- we need change the ann key from `[]` to `:` to keep parens and other anns.
282+
unless hasSibling $
283+
transferAnn (L l' $ reverse pre) (L l' [x]) id
264284
return $ L l it {ideclHiding = Just (hide, L l' $ reverse pre ++ [x])}
265285
extendImportViaParent _ _ _ _ = lift $ Left "Unable to extend the import list via parent"
266286

267287
unIEWrappedName :: IEWrappedName (IdP GhcPs) -> String
268-
unIEWrappedName = occNameString . occName
288+
unIEWrappedName (occName -> occ) = showSDocUnsafe $ parenSymOcc occ (ppr occ)
289+
290+
hasParen :: String -> Bool
291+
hasParen ('(' : _) = True
292+
hasParen _ = False
293+
294+
unqalDP :: Bool -> [(KeywordId, DeltaPos)]
295+
unqalDP paren =
296+
( if paren
297+
then \x -> (G AnnOpenP, dp00) : x : [(G AnnCloseP, dp00)]
298+
else pure
299+
)
300+
(G AnnVal, dp00)

0 commit comments

Comments
 (0)