@@ -22,8 +22,7 @@ import Control.Arrow (second,
22
22
(&&&) ,
23
23
(>>>) )
24
24
import Control.Concurrent.STM.Stats (atomically )
25
- import Control.Monad (guard , join ,
26
- msum )
25
+ import Control.Monad (guard , join )
27
26
import Control.Monad.IO.Class
28
27
import Data.Char
29
28
import qualified Data.DList as DL
@@ -34,21 +33,19 @@ import qualified Data.HashSet as Set
34
33
import Data.List.Extra
35
34
import Data.List.NonEmpty (NonEmpty ((:|) ))
36
35
import qualified Data.List.NonEmpty as NE
37
- import qualified Data.Map as M
36
+ import qualified Data.Map.Strict as M
38
37
import Data.Maybe
39
38
import Data.Ord (comparing )
40
39
import qualified Data.Rope.UTF16 as Rope
41
40
import qualified Data.Set as S
42
41
import qualified Data.Text as T
43
42
import Data.Tuple.Extra (fst3 )
44
- import Debug.Trace
45
43
import Development.IDE.Core.Rules
46
44
import Development.IDE.Core.RuleTypes
47
45
import Development.IDE.Core.Service
48
46
import Development.IDE.GHC.Compat
49
47
import Development.IDE.GHC.Compat.Util
50
48
import Development.IDE.GHC.Error
51
- import Development.IDE.GHC.ExactPrint
52
49
import Development.IDE.GHC.Util (printOutputable ,
53
50
printRdrName ,
54
51
traceAst )
@@ -59,12 +56,6 @@ import Development.IDE.Plugin.TypeLenses (suggestSigna
59
56
import Development.IDE.Types.Exports
60
57
import Development.IDE.Types.Location
61
58
import Development.IDE.Types.Options
62
- import GHC (AddEpAnn (AddEpAnn ),
63
- Anchor (anchor ),
64
- AnnsModule (am_main ),
65
- DeltaPos (.. ),
66
- EpAnn (.. ),
67
- EpaLocation (.. ))
68
59
import qualified GHC.LanguageExtensions as Lang
69
60
import Ide.PluginUtils (subRange )
70
61
import Ide.Types
@@ -87,6 +78,22 @@ import Language.LSP.Types (CodeAction (
87
78
import Language.LSP.VFS
88
79
import Text.Regex.TDFA (mrAfter ,
89
80
(=~) , (=~~) )
81
+ #if MIN_VERSION_ghc(9,2,0)
82
+ import GHC (AddEpAnn (AddEpAnn ),
83
+ AnnsModule (am_main ),
84
+ DeltaPos (.. ),
85
+ EpAnn (.. ),
86
+ EpaLocation (.. ),
87
+ LocatedA )
88
+
89
+ import Control.Monad (msum )
90
+ #else
91
+ import Language.Haskell.GHC.ExactPrint.Types (Annotation (annsDP ),
92
+ DeltaPos ,
93
+ KeywordId (G ),
94
+ deltaRow ,
95
+ mkAnnKey )
96
+ #endif
90
97
91
98
-------------------------------------------------------------------------------------------------
92
99
@@ -234,10 +241,8 @@ findInstanceHead df instanceHead decls =
234
241
235
242
#if MIN_VERSION_ghc(9,2,0)
236
243
findDeclContainingLoc :: Foldable t => Position -> t (GenLocated (SrcSpanAnn' a ) e ) -> Maybe (GenLocated (SrcSpanAnn' a ) e )
237
- #elif MIN_VERSION_ghc(8,10,0)
238
- findDeclContainingLoc :: Foldable t => Position -> t (GenLocated SrcSpan e ) -> Maybe (GenLocated SrcSpan e )
239
244
#else
240
- -- TODO populate this type signature for GHC versions <8.10
245
+ findDeclContainingLoc :: Foldable t => Position -> t ( GenLocated SrcSpan e ) -> Maybe ( GenLocated SrcSpan e )
241
246
#endif
242
247
findDeclContainingLoc loc = find (\ (L l _) -> loc `isInsideSrcSpan` locA l)
243
248
@@ -250,8 +255,8 @@ findDeclContainingLoc loc = find (\(L l _) -> loc `isInsideSrcSpan` locA l)
250
255
-- imported from ‘Data.ByteString’ at B.hs:6:1-22
251
256
-- imported from ‘Data.ByteString.Lazy’ at B.hs:8:1-27
252
257
-- imported from ‘Data.Text’ at B.hs:7:1-16
253
- suggestHideShadow :: ParsedSource -> T. Text -> Maybe TcModuleResult -> Maybe HieAstResult -> Diagnostic -> [(T. Text , [Either TextEdit Rewrite ])]
254
- suggestHideShadow ps@ ( L _ HsModule {hsmodImports}) fileContents mTcM mHar Diagnostic {_message, _range}
258
+ suggestHideShadow :: Annotated ParsedSource -> T. Text -> Maybe TcModuleResult -> Maybe HieAstResult -> Diagnostic -> [(T. Text , [Either TextEdit Rewrite ])]
259
+ suggestHideShadow ps fileContents mTcM mHar Diagnostic {_message, _range}
255
260
| Just [identifier, modName, s] <-
256
261
matchRegexUnifySpaces
257
262
_message
@@ -268,6 +273,8 @@ suggestHideShadow ps@(L _ HsModule {hsmodImports}) fileContents mTcM mHar Diagno
268
273
result <> [hideAll]
269
274
| otherwise = []
270
275
where
276
+ L _ HsModule {hsmodImports} = astA ps
277
+
271
278
suggests identifier modName s
272
279
| Just tcM <- mTcM,
273
280
Just har <- mHar,
@@ -947,11 +954,11 @@ isPreludeImplicit = xopt Lang.ImplicitPrelude
947
954
suggestImportDisambiguation ::
948
955
DynFlags ->
949
956
Maybe T. Text ->
950
- ParsedSource ->
957
+ Annotated ParsedSource ->
951
958
T. Text ->
952
959
Diagnostic ->
953
960
[(T. Text , [Either TextEdit Rewrite ])]
954
- suggestImportDisambiguation df (Just txt) ps@ ( L _ HsModule {hsmodImports}) fileContents diag@ Diagnostic {.. }
961
+ suggestImportDisambiguation df (Just txt) ps fileContents diag@ Diagnostic {.. }
955
962
| Just [ambiguous] <-
956
963
matchRegexUnifySpaces
957
964
_message
@@ -963,6 +970,8 @@ suggestImportDisambiguation df (Just txt) ps@(L _ HsModule {hsmodImports}) fileC
963
970
suggestions ambiguous modules (isJust local)
964
971
| otherwise = []
965
972
where
973
+ L _ HsModule {hsmodImports} = astA ps
974
+
966
975
locDic =
967
976
fmap (NE. fromList . DL. toList) $
968
977
Map. fromListWith (<>) $
@@ -1055,21 +1064,21 @@ targetModuleName (ExistingImp _) =
1055
1064
error " Cannot happen!"
1056
1065
1057
1066
disambiguateSymbol ::
1058
- ParsedSource ->
1067
+ Annotated ParsedSource ->
1059
1068
T. Text ->
1060
1069
Diagnostic ->
1061
1070
T. Text ->
1062
1071
HidingMode ->
1063
1072
[Either TextEdit Rewrite ]
1064
- disambiguateSymbol pm fileContents Diagnostic {.. } (T. unpack -> symbol) = \ case
1073
+ disambiguateSymbol ps fileContents Diagnostic {.. } (T. unpack -> symbol) = \ case
1065
1074
(HideOthers hiddens0) ->
1066
1075
[ Right $ hideSymbol symbol idecl
1067
1076
| ExistingImp idecls <- hiddens0
1068
1077
, idecl <- NE. toList idecls
1069
1078
]
1070
1079
++ mconcat
1071
1080
[ if null imps
1072
- then maybeToList $ Left . snd <$> newImportToEdit (hideImplicitPreludeSymbol $ T. pack symbol) pm fileContents
1081
+ then maybeToList $ Left . snd <$> newImportToEdit (hideImplicitPreludeSymbol $ T. pack symbol) ps fileContents
1073
1082
else Right . hideSymbol symbol <$> imps
1074
1083
| ImplicitPrelude imps <- hiddens0
1075
1084
]
@@ -1299,7 +1308,7 @@ removeRedundantConstraints df (L _ HsModule {hsmodDecls}) Diagnostic{..}
1299
1308
1300
1309
-------------------------------------------------------------------------------------------------
1301
1310
1302
- suggestNewOrExtendImportForClassMethod :: ExportsMap -> ParsedSource -> T. Text -> Diagnostic -> [(T. Text , CodeActionKind , [Either TextEdit Rewrite ])]
1311
+ suggestNewOrExtendImportForClassMethod :: ExportsMap -> Annotated ParsedSource -> T. Text -> Diagnostic -> [(T. Text , CodeActionKind , [Either TextEdit Rewrite ])]
1303
1312
suggestNewOrExtendImportForClassMethod packageExportsMap ps fileContents Diagnostic {_message}
1304
1313
| Just [methodName, className] <-
1305
1314
matchRegexUnifySpaces
@@ -1313,7 +1322,7 @@ suggestNewOrExtendImportForClassMethod packageExportsMap ps fileContents Diagnos
1313
1322
where
1314
1323
suggest identInfo@ IdentInfo {moduleNameText}
1315
1324
| importStyle <- NE. toList $ importStyles identInfo,
1316
- mImportDecl <- findImportDeclByModuleName (hsmodImports $ unLoc ps) (T. unpack moduleNameText) =
1325
+ mImportDecl <- findImportDeclByModuleName (hsmodImports . unLoc . astA $ ps) (T. unpack moduleNameText) =
1317
1326
case mImportDecl of
1318
1327
-- extend
1319
1328
Just decl ->
@@ -1335,8 +1344,8 @@ suggestNewOrExtendImportForClassMethod packageExportsMap ps fileContents Diagnos
1335
1344
<> [(quickFixImportKind " new.all" , newImportAll moduleNameText)]
1336
1345
| otherwise -> []
1337
1346
1338
- suggestNewImport :: ExportsMap -> ParsedSource -> T. Text -> Diagnostic -> [(T. Text , CodeActionKind , TextEdit )]
1339
- suggestNewImport packageExportsMap ps@ ( L _ HsModule { .. }) fileContents Diagnostic {_message}
1347
+ suggestNewImport :: ExportsMap -> Annotated ParsedSource -> T. Text -> Diagnostic -> [(T. Text , CodeActionKind , TextEdit )]
1348
+ suggestNewImport packageExportsMap ps fileContents Diagnostic {_message}
1340
1349
| msg <- unifySpaces _message
1341
1350
, Just thingMissing <- extractNotInScopeName msg
1342
1351
, qual <- extractQualifiedModuleName msg
@@ -1351,6 +1360,8 @@ suggestNewImport packageExportsMap ps@(L _ HsModule {..}) fileContents Diagnosti
1351
1360
= sortOn fst3 [(imp, kind, TextEdit range (imp <> " \n " <> T. replicate indent " " ))
1352
1361
| (kind, unNewImport -> imp) <- constructNewImportSuggestions packageExportsMap (qual <|> qual', thingMissing) extendImportSuggestions
1353
1362
]
1363
+ where
1364
+ L _ HsModule {.. } = astA ps
1354
1365
suggestNewImport _ _ _ _ = []
1355
1366
1356
1367
constructNewImportSuggestions
@@ -1378,7 +1389,7 @@ constructNewImportSuggestions exportsMap (qual, thingMissing) notTheseModules =
1378
1389
newtype NewImport = NewImport { unNewImport :: T. Text}
1379
1390
deriving (Show , Eq , Ord )
1380
1391
1381
- newImportToEdit :: NewImport -> ParsedSource -> T. Text -> Maybe (T. Text , TextEdit )
1392
+ newImportToEdit :: NewImport -> Annotated ParsedSource -> T. Text -> Maybe (T. Text , TextEdit )
1382
1393
newImportToEdit (unNewImport -> imp) ps fileContents
1383
1394
| Just (range, indent) <- newImportInsertRange ps fileContents
1384
1395
= Just (imp, TextEdit range (imp <> " \n " <> T. replicate indent " " ))
@@ -1392,54 +1403,71 @@ newImportToEdit (unNewImport -> imp) ps fileContents
1392
1403
-- * If the file has neither existing imports nor a module declaration,
1393
1404
-- the import will be inserted at line zero if there are no pragmas,
1394
1405
-- * otherwise inserted one line after the last file-header pragma
1406
+ #if MIN_VERSION_ghc(9,2,0)
1395
1407
newImportInsertRange :: ParsedSource -> T. Text -> Maybe (Range , Int )
1396
1408
newImportInsertRange ps@ (L _ HsModule {.. }) fileContents
1409
+ #else
1410
+ newImportInsertRange :: Annotated ParsedSource -> T. Text -> Maybe (Range , Int )
1411
+ newImportInsertRange ps fileContents
1412
+ #endif
1397
1413
| Just ((l, c), col) <- case hsmodImports of
1398
1414
[] -> (\ line -> ((line, 0 ), 0 )) <$> findPositionNoImports ps fileContents
1399
1415
_ -> findPositionFromImportsOrModuleDecl (map reLoc hsmodImports) last
1400
1416
, let insertPos = Position (fromIntegral l) (fromIntegral c)
1401
1417
= Just (Range insertPos insertPos, col)
1402
1418
| otherwise = Nothing
1419
+ where
1420
+ L _ HsModule {.. } = astA ps
1403
1421
1404
1422
-- | Insert the import under the Module declaration exports if they exist, otherwise just under the module declaration.
1405
1423
-- If no module declaration exists, then no exports will exist either, in that case
1406
1424
-- insert the import after any file-header pragmas or at position zero if there are no pragmas
1407
- findPositionNoImports :: ParsedSource -> T. Text -> Maybe Int
1408
- findPositionNoImports (L _ HsModule {.. }) fileContents =
1409
- case hsmodName of
1410
- Nothing -> Just $ findNextPragmaPosition fileContents
1411
- Just hsmodName' -> case hsmodAnn of
1412
- EpAnn _ annsModule _ ->
1413
- let prevSrcSpan = maybe (getLoc hsmodName') getLoc hsmodExports
1414
- in do
1415
- whereLocation <- fmap NE. head . NE. nonEmpty . mapMaybe filterWhere . am_main $ annsModule
1416
- epaLocationToLine prevSrcSpan whereLocation
1417
- EpAnnNotUsed -> Nothing
1425
+ findPositionNoImports :: Annotated ParsedSource -> T. Text -> Maybe Int
1426
+ findPositionNoImports ps fileContents =
1427
+ maybe (Just (findNextPragmaPosition fileContents)) (findPositionAfterModuleName ps) hsmodName
1418
1428
where
1419
- filterWhere (AddEpAnn AnnWhere loc) = Just loc
1420
- filterWhere _ = Nothing
1429
+ L _ HsModule {.. } = astA ps
1421
1430
1422
- epaLocationToLine :: SrcSpan -> EpaLocation -> Maybe Int
1423
- epaLocationToLine _ (EpaSpan sp) =
1424
- let loc = realSrcSpanEnd sp
1425
- in Just $ srcLocLine loc
1426
- epaLocationToLine (UnhelpfulSpan _) _ = Nothing
1427
- epaLocationToLine (RealSrcSpan prevSrcSpan _) (EpaDelta deltaPos _) =
1428
- case deltaPos of
1429
- SameLine _ -> Just prevEndLine
1430
- DifferentLine line _ -> Just $ prevEndLine + line
1431
- where
1432
- prevEndLine = srcLocLine (realSrcSpanEnd prevSrcSpan)
1431
+ #if MIN_VERSION_ghc(9,2,0)
1432
+ findPositionAfterModuleName :: ParsedSource -> LocatedA ModuleName -> Maybe Int
1433
+ #else
1434
+ findPositionAfterModuleName :: Annotated ParsedSource -> Located ModuleName -> Maybe Int
1435
+ #endif
1436
+ findPositionAfterModuleName ps hsmodName' = do
1437
+ lineOffset <- whereKeywordLineOffset
1438
+ case prevSrcSpan of
1439
+ UnhelpfulSpan _ -> Nothing
1440
+ (RealSrcSpan prevSrcSpan' _) ->
1441
+ Just $ srcLocLine (realSrcSpanEnd prevSrcSpan') + lineOffset
1442
+ where
1443
+ L _ HsModule {.. } = astA ps
1433
1444
1434
- showAddEpAnns :: [AddEpAnn ] -> String
1435
- showAddEpAnns = unlines . fmap showAddEpAnn
1445
+ prevSrcSpan = maybe (getLoc hsmodName') getLoc hsmodExports
1436
1446
1437
- showAddEpAnn :: AddEpAnn -> String
1438
- showAddEpAnn (AddEpAnn keywordId loc) = show keywordId ++ " ," ++ showEpaLocation loc
1447
+ whereKeywordLineOffset :: Maybe Int
1448
+ #if MIN_VERSION_ghc(9,2,0)
1449
+ whereKeywordLineOffset = case hsmodAnn of
1450
+ EpAnn _ annsModule _ -> do
1451
+ whereLocation <- fmap NE. head . NE. nonEmpty . mapMaybe filterWhere . am_main $ annsModule
1452
+ epaLocationToLine whereLocation
1453
+ EpAnnNotUsed -> Nothing
1454
+ filterWhere (AddEpAnn AnnWhere loc) = Just loc
1455
+ filterWhere _ = Nothing
1439
1456
1440
- showEpaLocation :: EpaLocation -> String
1441
- showEpaLocation (EpaDelta pos _) = show pos
1442
- showEpaLocation _ = error " should not be EpaSpan"
1457
+ epaLocationToLine :: EpaLocation -> Maybe Int
1458
+ epaLocationToLine (EpaSpan sp) = Just . srcLocLine . realSrcSpanEnd $ sp
1459
+ epaLocationToLine (EpaDelta (SameLine _) _) = Just 0
1460
+ epaLocationToLine (EpaDelta (DifferentLine line _) _) = Just line
1461
+ #else
1462
+ whereKeywordLineOffset = do
1463
+ ann <- annsA ps M. !? mkAnnKey (astA ps)
1464
+ deltaPos <- fmap NE. head . NE. nonEmpty . mapMaybe filterWhere $ annsDP ann
1465
+ pure $ deltaRow deltaPos
1466
+
1467
+ filterWhere :: (KeywordId , DeltaPos ) -> Maybe DeltaPos
1468
+ filterWhere (keywordId, deltaPos) =
1469
+ if keywordId == G AnnWhere then Just deltaPos else Nothing
1470
+ #endif
1443
1471
1444
1472
findPositionFromImportsOrModuleDecl :: HasSrcSpan a => t -> (t -> a ) -> Maybe ((Int , Int ), Int )
1445
1473
findPositionFromImportsOrModuleDecl hsField f = case getLoc (f hsField) of
0 commit comments