@@ -42,12 +42,12 @@ import qualified Development.IDE.GHC.ExactPrint as E
4242import Development.IDE.Plugin.CodeAction
4343import Development.IDE.Spans.AtPoint
4444import Development.IDE.Types.Location
45- import GHC (isGoodSrcSpan )
4645import GHC.Iface.Ext.Types (HieAST (.. ),
4746 HieASTs (.. ),
4847 NodeOrigin (.. ),
4948 SourcedNodeInfo (.. ))
5049import GHC.Iface.Ext.Utils (generateReferencesMap )
50+ import HieDb ((:.) (.. ))
5151import HieDb.Query
5252import HieDb.Types (RefRow (refIsGenerated ))
5353import Ide.Logger (Pretty (.. ),
@@ -97,7 +97,9 @@ prepareRenameProvider state _pluginId (PrepareRenameParams (TextDocumentIdentifi
9797 let spansWithNamesUnderCursor =
9898 [ srcSpan
9999 | (names, srcSpan) <- getNamesSpansAtPoint' hieAst pos
100- , not (null names)]
100+ , not (null names)
101+ , positionInSpan pos srcSpan -- cursor must be within the trimmed span
102+ ]
101103 -- When this handler says that rename is invalid, VSCode shows "The element can't be renamed"
102104 -- and doesn't even allow you to create full rename request.
103105 -- This handler deliberately approximates "things that definitely can't be renamed"
@@ -110,6 +112,15 @@ prepareRenameProvider state _pluginId (PrepareRenameParams (TextDocumentIdentifi
110112 [] -> InR Null
111113 srcSpan : _ -> InL $ PrepareRenameResult $ InL (realSrcSpanToRange srcSpan)
112114
115+ positionInSpan :: Position -> RealSrcSpan -> Bool
116+ positionInSpan (Position l c) sp =
117+ let start = realSrcSpanStart sp
118+ end = realSrcSpanEnd sp
119+ line = fromIntegral l + 1 -- LSP is 0-based, GHC is 1-based
120+ col = fromIntegral c + 1
121+ in (line, col) >= (srcLocLine start, srcLocCol start)
122+ && (line, col) <= (srcLocLine end, srcLocCol end)
123+
113124renameProvider :: PluginMethodHandler IdeState Method_TextDocumentRename
114125renameProvider state pluginId (RenameParams _prog (TextDocumentIdentifier uri) pos newNameText) = do
115126 nfp <- getNormalizedFilePathE uri
@@ -296,29 +307,28 @@ refsAtName ::
296307 NormalizedFilePath ->
297308 Name ->
298309 ExceptT PluginError m [Location ]
299- refsAtName state nfp targetName = do
300- HAR {refMap} <- handleGetHieAst state nfp
301-
302- let localRefs =
303- case M. lookup (Right targetName) refMap of
304- Nothing -> []
305- Just spans -> [ realSrcSpanToLocation sp | (sp, _) <- spans]
306-
307- let defLoc = nameSrcSpan targetName
308- defLocations = case srcSpanToLocation defLoc of
309- Just loc | isGoodSrcSpan defLoc -> [loc]
310- _ -> []
311-
312- -- Only query HieDb if it's a global name
313- globalRefs <-
314- case nameModule_maybe targetName of
315- Nothing -> pure []
316- Just mod -> do
317- ShakeExtras {withHieDb} <- liftIO $ runAction " Rename.HieDb" state getShakeExtras
318- liftIO $ withHieDb $ \ hieDb ->
319- fmap (mapMaybe rowToLoc) $ findReferences hieDb True (nameOccName targetName) (Just $ moduleName mod ) (Just $ moduleUnit mod ) []
320-
321- pure (defLocations ++ localRefs ++ globalRefs)
310+ refsAtName state nfp name = do
311+ ShakeExtras {withHieDb} <- liftIO $ runAction " Rename.HieDb" state getShakeExtras
312+ ast <- handleGetHieAst state nfp
313+ dbRefs <- case nameModule_maybe name of
314+ Nothing -> pure []
315+ Just mod -> liftIO $ mapMaybe rowToLoc <$> withHieDb (\ hieDb ->
316+ -- See Note [Generated references]
317+ filter (\ (refRow HieDb. :. _) -> not (refIsGenerated refRow)) <$>
318+ findReferences
319+ hieDb
320+ True
321+ (nameOccName name)
322+ (Just $ moduleName mod )
323+ (Just $ moduleUnit mod )
324+ [fromNormalizedFilePath nfp]
325+ )
326+ pure $ nameLocs name ast ++ dbRefs
327+
328+ nameLocs :: Name -> HieAstResult -> [Location ]
329+ nameLocs name (HAR _ _ rm _ _) =
330+ concatMap (map (realSrcSpanToLocation . fst ))
331+ (M. lookup (Right name) rm)
322332---------------------------------------------------------------------------------------------------
323333-- Util
324334
@@ -370,11 +380,35 @@ getNamesAtPoint' :: HieASTs a -> Position -> [Name]
370380getNamesAtPoint' hf pos =
371381 concat $ pointCommand hf pos (rights . M. keys . getNodeIds)
372382
373- -- | A variant of `getNamesAtPoint'` that also returns source spans.
383+ -- | A variant of `getNamesAtPoint'` that also returns source spans,
384+ -- trimmed to just the unqualified identifier (excluding any "Module." prefix).
374385getNamesSpansAtPoint' :: HieASTs a -> Position -> [([Name ], RealSrcSpan )]
375386getNamesSpansAtPoint' hf pos =
376387 pointCommand hf pos $
377- \ astNode -> (rights . M. keys . getNodeIds $ astNode, nodeSpan astNode)
388+ \ astNode ->
389+ let names = rights . M. keys . getNodeIds $ astNode
390+ srcSpan = nodeSpan astNode
391+ trimmed = trimQualifierSpan names srcSpan
392+ in (names, trimmed)
393+
394+ -- | Advance the start column of a span past any "Qualifier." prefix,
395+ -- using the OccName length of the first Name to find where the
396+ -- identifier begins.
397+ trimQualifierSpan :: [Name ] -> RealSrcSpan -> RealSrcSpan
398+ trimQualifierSpan (n: _) sp
399+ | qualLen > 0
400+ = mkRealSrcSpan
401+ (mkRealSrcLoc file startLine (startCol + qualLen))
402+ (realSrcSpanEnd sp)
403+ | otherwise = sp
404+ where
405+ spanLen = srcLocCol (realSrcSpanEnd sp) - srcLocCol (realSrcSpanStart sp)
406+ identLen = length (occNameString (nameOccName n))
407+ qualLen = spanLen - identLen
408+ file = srcSpanFile sp
409+ startLine = srcLocLine (realSrcSpanStart sp)
410+ startCol = srcLocCol (realSrcSpanStart sp)
411+ trimQualifierSpan [] sp = sp
378412
379413locToUri :: Location -> Uri
380414locToUri (Location uri _) = uri
@@ -407,16 +441,14 @@ exportNameLocs pm names = do
407441#else
408442 IEVar _ ieWrapped -> matchWrapped (getLoc export) ieWrapped
409443#endif
410- IEThingAll {} -> unsupported
411- IEThingWith {} -> unsupported
412- IEModuleContents {} -> unsupported
413- IEThingAbs {} -> unsupported
414- IEGroup {} -> unsupported
415- IEDoc {} -> unsupported
416- IEDocNamed {} -> unsupported
444+ IEThingAll {} -> pure []
445+ IEThingWith {} -> pure []
446+ IEModuleContents {} -> pure []
447+ IEThingAbs {} -> pure []
448+ IEGroup {} -> pure []
449+ IEDoc {} -> pure []
450+ IEDocNamed {} -> pure []
417451 where
418- unsupported = throwError $ PluginInternalError " Renaming is unsupported for complex export forms"
419-
420452 matchWrapped :: SrcSpan -> LIEWrappedName GhcPs -> ExceptT PluginError (HandlerM config ) [Location ]
421453 matchWrapped l ieWrapped =
422454 case unwrapIEWrappedName (unLoc ieWrapped) of
0 commit comments