Description
Any time that expansion is used, for example, because of a dot record, the renamed ast includes an HsExpanded
expression that contains both the original and generated expressions. This is problematic because an ordinary syb traversal of the ast usually traverses both sets of expressions, causing duplicate returns. In explicit record fields, this causes duplicate codeActions, for example.
Steps to reproduce
This small modification of one of explicit record fields tests was able to trigger the issue
{-# LANGUAGE Haskell2010 #-}
{-# LANGUAGE RecordWildCards #-}
{-# Language OverloadedRecordDot #-}
module Construction where
data MyRec = MyRec
{ foo :: Int
, bar :: Int
, baz :: Char
}
convertMe :: () -> Int
convertMe _ =
let foo = 3
bar = 5
baz = 'a'
in MyRec {..}.foo
Expected behavior
In this case, instead of the expected one codeAction offering to rewrite the wildcard when clicking upon MyRec, there were two completely identical ones.
If using everything
, this can be fixed with using everythingBut
, manually starting traversal on one of the branches when HsExpanded
is found, and at the same time returning True
, which keeps the first everything from traversing any more on that branch.
For example, this is how I did it on the overloaded-record-dot-plugin
I, unfortunately, opened a pull request on the main branch of my fork of hls, so until that closes, I won't be able to submit a fix for explicit record fields. This bug may also affect other plugins, but probably only if they used the Renamed or TypeChecked ast.