Skip to content

Commit 8a91d03

Browse files
authored
Import disambiguation: Corrects handling of fully-applied and one-sided sectioned operators in qualifying strategy (#1294)
* disambiguation: Corrects infix and one-sided section operator qualification * Renames `expected` files to have `.hs` extension * Just use parensed only
1 parent d602e45 commit 8a91d03

17 files changed

+77
-21
lines changed

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

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ suggestAction packageExports ideOptions parsedModule text df annSource diag =
132132
[ suggestSignature True diag
133133
, rewrite df annSource $ \_ ps -> suggestExtendImport packageExports ps diag
134134
, rewrite df annSource $ \df ps ->
135-
suggestImportDisambiguation df ps diag
135+
suggestImportDisambiguation df text ps diag
136136
, suggestFillTypeWildcard diag
137137
, suggestFixConstructorImport text diag
138138
, suggestModuleTypo diag
@@ -705,8 +705,12 @@ suggestExtendImport exportsMap (L _ HsModule {hsmodImports}) Diagnostic{_range=_
705705
, parent = Nothing
706706
, isDatacon = False}
707707

708-
data HidingMode = HideOthers [ModuleTarget]
709-
| ToQualified ModuleName
708+
data HidingMode
709+
= HideOthers [ModuleTarget]
710+
| ToQualified
711+
Bool
712+
-- ^ Parenthesised?
713+
ModuleName
710714
deriving (Show)
711715

712716
data ModuleTarget
@@ -730,10 +734,11 @@ isPreludeImplicit = xopt Lang.ImplicitPrelude
730734
-- | Suggests disambiguation for ambiguous symbols.
731735
suggestImportDisambiguation ::
732736
DynFlags ->
737+
Maybe T.Text ->
733738
ParsedSource ->
734739
Diagnostic ->
735740
[(T.Text, [Rewrite])]
736-
suggestImportDisambiguation df ps@(L _ HsModule {hsmodImports}) diag@Diagnostic {..}
741+
suggestImportDisambiguation df (Just txt) ps@(L _ HsModule {hsmodImports}) diag@Diagnostic {..}
737742
| Just [ambiguous] <-
738743
matchRegexUnifySpaces
739744
_message
@@ -759,7 +764,8 @@ suggestImportDisambiguation df ps@(L _ HsModule {hsmodImports}) diag@Diagnostic
759764
= Just $ ImplicitPrelude $
760765
maybe [] NE.toList (Map.lookup "Prelude" locDic)
761766
toModuleTarget mName = ExistingImp <$> Map.lookup mName locDic
762-
767+
parensed =
768+
"(" `T.isPrefixOf` T.strip (textInRange _range txt)
763769
suggestions symbol mods
764770
| Just targets <- mapM toModuleTarget mods =
765771
sortOn fst
@@ -771,12 +777,12 @@ suggestImportDisambiguation df ps@(L _ HsModule {hsmodImports}) diag@Diagnostic
771777
modNameText = T.pack $ moduleNameString modName
772778
, mode <-
773779
HideOthers restImports :
774-
[ ToQualified qual
780+
[ ToQualified parensed qual
775781
| ExistingImp imps <- [modTarget]
776782
, L _ qual <- nubOrd $ mapMaybe (ideclAs . unLoc)
777783
$ NE.toList imps
778784
]
779-
++ [ToQualified modName
785+
++ [ToQualified parensed modName
780786
| any (occursUnqualified symbol . unLoc)
781787
(targetImports modTarget)
782788
|| case modTarget of
@@ -787,11 +793,12 @@ suggestImportDisambiguation df ps@(L _ HsModule {hsmodImports}) diag@Diagnostic
787793
| otherwise = []
788794
renderUniquify HideOthers {} modName symbol =
789795
"Use " <> modName <> " for " <> symbol <> ", hiding other imports"
790-
renderUniquify (ToQualified qual) _ symbol =
796+
renderUniquify (ToQualified _ qual) _ symbol =
791797
"Replace with qualified: "
792798
<> T.pack (moduleNameString qual)
793799
<> "."
794800
<> symbol
801+
suggestImportDisambiguation _ _ _ _ = []
795802

796803
occursUnqualified :: T.Text -> ImportDecl GhcPs -> Bool
797804
occursUnqualified symbol ImportDecl{..}
@@ -832,14 +839,18 @@ disambiguateSymbol pm Diagnostic {..} (T.unpack -> symbol) = \case
832839
else hideSymbol symbol <$> imps
833840
| ImplicitPrelude imps <- hiddens0
834841
]
835-
(ToQualified qualMod) ->
842+
(ToQualified parensed qualMod) ->
836843
let occSym = mkVarOcc symbol
837844
rdr = Qual qualMod occSym
838-
in [ Rewrite (rangeToSrcSpan "<dummy>" _range) $ \df -> do
839-
liftParseAST @(HsExpr GhcPs) df $
845+
in [ if parensed
846+
then Rewrite (rangeToSrcSpan "<dummy>" _range) $ \df ->
847+
liftParseAST @(HsExpr GhcPs) df $
840848
prettyPrint $
841849
HsVar @GhcPs noExtField $
842850
L (UnhelpfulSpan "") rdr
851+
else Rewrite (rangeToSrcSpan "<dummy>" _range) $ \df ->
852+
liftParseAST @RdrName df $
853+
prettyPrint $ L (UnhelpfulSpan "") rdr
843854
]
844855

845856
findImportDeclByRange :: [LImportDecl GhcPs] -> Range -> Maybe (LImportDecl GhcPs)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module HideQualifyInfix where
2+
3+
import AVec
4+
5+
infixed xs ys = xs Prelude.++ ys
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module HideQualifyInfix where
2+
3+
import AVec
4+
5+
infixed xs ys = xs ++ ys
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module HideQualifySectionLeft where
2+
3+
import AVec
4+
5+
sectLeft xs = (Prelude.++ xs)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module HideQualifySectionLeft where
2+
3+
import AVec
4+
5+
sectLeft xs = (++ xs)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module HideQualifySectionRight where
2+
3+
import AVec
4+
5+
sectLeft xs = (xs Prelude.++)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module HideQualifySectionRight where
2+
3+
import AVec
4+
5+
sectLeft xs = (xs ++)

ghcide/test/exe/Main.hs

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1483,38 +1483,38 @@ suggestImportDisambiguationTests = testGroup "suggest import disambiguation acti
14831483
[ testCase "AVec" $
14841484
compareHideFunctionTo [(8,9),(10,8)]
14851485
"Use AVec for fromList, hiding other imports"
1486-
"HideFunction.hs.expected.fromList.A"
1486+
"HideFunction.expected.fromList.A.hs"
14871487
, testCase "BVec" $
14881488
compareHideFunctionTo [(8,9),(10,8)]
14891489
"Use BVec for fromList, hiding other imports"
1490-
"HideFunction.hs.expected.fromList.B"
1490+
"HideFunction.expected.fromList.B.hs"
14911491
]
14921492
, testGroup "(++)"
14931493
[ testCase "EVec" $
14941494
compareHideFunctionTo [(8,9),(10,8)]
14951495
"Use EVec for ++, hiding other imports"
1496-
"HideFunction.hs.expected.append.E"
1496+
"HideFunction.expected.append.E.hs"
14971497
, testCase "Prelude" $
14981498
compareHideFunctionTo [(8,9),(10,8)]
14991499
"Use Prelude for ++, hiding other imports"
1500-
"HideFunction.hs.expected.append.Prelude"
1500+
"HideFunction.expected.append.Prelude.hs"
15011501
, testCase "AVec, indented" $
15021502
compareTwo "HidePreludeIndented.hs" [(3,8)]
15031503
"Use AVec for ++, hiding other imports"
1504-
"HidePreludeIndented.hs.expected"
1504+
"HidePreludeIndented.expected.hs"
15051505

15061506
]
15071507
, testGroup "Vec (type)"
15081508
[ testCase "AVec" $
15091509
compareTwo
15101510
"HideType.hs" [(8,15)]
15111511
"Use AVec for Vec, hiding other imports"
1512-
"HideType.hs.expected.A"
1512+
"HideType.expected.A.hs"
15131513
, testCase "EVec" $
15141514
compareTwo
15151515
"HideType.hs" [(8,15)]
15161516
"Use EVec for Vec, hiding other imports"
1517-
"HideType.hs.expected.E"
1517+
"HideType.expected.E.hs"
15181518
]
15191519
]
15201520
, testGroup "Qualify strategy"
@@ -1536,13 +1536,28 @@ suggestImportDisambiguationTests = testGroup "suggest import disambiguation acti
15361536
[ testCase "EVec" $
15371537
compareHideFunctionTo [(8,9),(10,8)]
15381538
"Replace with qualified: E.fromList"
1539-
"HideFunction.hs.expected.qualified.fromList.E"
1539+
"HideFunction.expected.qualified.fromList.E.hs"
15401540
]
15411541
, testGroup "(++)"
1542-
[ testCase "Prelude" $
1542+
[ testCase "Prelude, parensed" $
15431543
compareHideFunctionTo [(8,9),(10,8)]
15441544
"Replace with qualified: Prelude.++"
1545-
"HideFunction.hs.expected.qualified.append.Prelude"
1545+
"HideFunction.expected.qualified.append.Prelude.hs"
1546+
, testCase "Prelude, infix" $
1547+
compareTwo
1548+
"HideQualifyInfix.hs" [(4,19)]
1549+
"Replace with qualified: Prelude.++"
1550+
"HideQualifyInfix.expected.hs"
1551+
, testCase "Prelude, left section" $
1552+
compareTwo
1553+
"HideQualifySectionLeft.hs" [(4,15)]
1554+
"Replace with qualified: Prelude.++"
1555+
"HideQualifySectionLeft.expected.hs"
1556+
, testCase "Prelude, right section" $
1557+
compareTwo
1558+
"HideQualifySectionRight.hs" [(4,18)]
1559+
"Replace with qualified: Prelude.++"
1560+
"HideQualifySectionRight.expected.hs"
15461561
]
15471562
]
15481563
]

0 commit comments

Comments
 (0)