@@ -108,16 +108,12 @@ renameProvider state pluginId (RenameParams _prog (TextDocumentIdentifier uri) p
108108 exportRefs <- exportNameLocs pm oldNames
109109 isExported <- or <$> mapM (isNameExplicitExported pm) oldNames
110110 let refs = HS. union refs' (HS. fromList exportRefs)
111- currentModule = fmap unLoc $ hsmodName $ unLoc $ pm_parsed_source pm
111+ currentModuleFull = ms_mod $ pm_mod_summary pm
112112 isLocallyDefined name =
113- case (nameModule_maybe name, currentModule) of
114- (Just nameModule, Just curMod) -> moduleName nameModule == curMod
115- -- No module means local
116- (Nothing , _) -> True
117- -- Has module but current has none = not local
118- (Just _, Nothing ) -> False
119- renamingLocalDeclaration = not (null directOldNames) && not (null oldNames) && all isLocallyDefined oldNames
120-
113+ case nameModule_maybe name of
114+ Nothing -> True
115+ Just mod -> mod == currentModuleFull
116+ renamingLocalDeclaration = not (null directOldNames) && all isLocallyDefined directOldNames
121117 -- We have to show CrossModule Disabled error ONLY when
122118 -- 1. CrossModule is Disabled
123119 -- 2. User Tries to rename Exported variable
@@ -128,7 +124,7 @@ renameProvider state pluginId (RenameParams _prog (TextDocumentIdentifier uri) p
128124 -- if variable is imported somewhere else && No explicit export => ERROR
129125 -- if variable is locally used => No ERROR
130126 let hasExplicitExportList = isJust (hsmodExports (unLoc $ pm_parsed_source pm))
131- refFiles <- forM (HS. toList refs) $ \ loc -> do
127+ refFiles <- forM (HS. toList refs' ) $ \ loc -> do
132128 (file, _) <- locToFilePos loc
133129 pure file
134130 let hasExternalRefs = any (/= nfp) refFiles
@@ -142,9 +138,10 @@ renameProvider state pluginId (RenameParams _prog (TextDocumentIdentifier uri) p
142138 -- Perform rename
143139 let newName = mkTcOcc $ T. unpack newNameText
144140 filesRefs = collectWith locToUri refs
141+ oldOccNames = HS. fromList $ map nameOccName oldNames
145142 getFileEdit (uri, locations) = do
146143 verTxtDocId <- liftIO $ runAction " rename: getVersionedTextDoc" state $ getVersionedTextDoc (TextDocumentIdentifier uri)
147- getSrcEdit state verTxtDocId (replaceRefs newName locations)
144+ getSrcEdit state verTxtDocId (replaceRefs newName locations oldOccNames )
148145 fileEdits <- mapM getFileEdit filesRefs
149146 pure $ InL $ fold fileEdits
150147
@@ -214,10 +211,10 @@ getSrcEdit state verTxtDocId updatePs = do
214211replaceRefs ::
215212 OccName ->
216213 HashSet Location ->
214+ HashSet OccName ->
217215 ParsedSource ->
218216 ParsedSource
219- replaceRefs newName refs = everywhere $
220- -- there has to be a better way...
217+ replaceRefs newName refs oldOccNames = everywhere $
221218 mkT (replaceLoc @ AnnListItem ) `extT`
222219 -- replaceLoc @AnnList `extT` -- not needed
223220 -- replaceLoc @AnnParen `extT` -- not needed
@@ -228,8 +225,11 @@ replaceRefs newName refs = everywhere $
228225 where
229226 replaceLoc :: forall an . LocatedAn an RdrName -> LocatedAn an RdrName
230227 replaceLoc (L srcSpan oldRdrName)
231- | isRef (locA srcSpan) = L srcSpan $ replace oldRdrName
228+ | isRef (locA srcSpan)
229+ , isTarget oldRdrName
230+ = L srcSpan $ replace oldRdrName
232231 replaceLoc lOldRdrName = lOldRdrName
232+
233233 replace :: RdrName -> RdrName
234234 replace (Qual modName _) = Qual modName newName
235235 replace _ = Unqual newName
@@ -239,6 +239,10 @@ replaceRefs newName refs = everywhere $
239239 Just loc -> loc `HS.member` refs
240240 Nothing -> False
241241
242+ -- Only replace RdrNames whose OccName matches a rename target, preventing
243+ -- co-located field selectors from being incorrectly renamed.
244+ isTarget :: RdrName -> Bool
245+ isTarget rdrName = rdrNameOcc rdrName `HS.member` oldOccNames
242246---------------------------------------------------------------------------------------------------
243247-- Reference finding
244248
@@ -250,38 +254,23 @@ refsAtName ::
250254 Name ->
251255 ExceptT PluginError m [Location ]
252256refsAtName state nfp targetName = do
253- -- Get local references from current file's HieAST
254- ast <- handleGetHieAst state nfp
255- let localRefs = nameLocs targetName ast
256-
257- -- Query HieDb for global matches (by OccName)
258- ShakeExtras {withHieDb} <- liftIO $ runAction " Rename.HieDb" state getShakeExtras
259- dbCandidates <- liftIO $ withHieDb $ \ hieDb ->
260- fmap (mapMaybe rowToLoc) $
261- case nameModule_maybe targetName of
262- Just mod -> findReferences hieDb True (nameOccName targetName) (Just $ moduleName mod ) (Just $ moduleUnit mod ) []
263- Nothing -> findReferences hieDb True (nameOccName targetName) Nothing Nothing []
264-
265- -- Filter candidates by exact Name identity
266- filteredDbRefs <- filterM (matchesExactName state targetName) dbCandidates
267- pure $ localRefs ++ filteredDbRefs
268-
269- matchesExactName ::
270- MonadIO m =>
271- IdeState ->
272- Name ->
273- Location ->
274- ExceptT PluginError m Bool
275- matchesExactName state targetName loc = do
276- (file, pos) <- locToFilePos loc
277- namesAtPos <- getNamesAtPos state file pos
278- pure $ targetName `elem` namesAtPos
279-
280- nameLocs :: Name -> HieAstResult -> [Location ]
281- nameLocs name (HAR _ _ rm _ _) =
282- concatMap (map (realSrcSpanToLocation . fst ))
283- (M. lookup (Right name) rm)
284-
257+ HAR {refMap} <- handleGetHieAst state nfp
258+
259+ let localRefs =
260+ case M. lookup (Right targetName) refMap of
261+ Nothing -> []
262+ Just spans -> [ realSrcSpanToLocation sp | (sp, _) <- spans]
263+
264+ -- Only query HieDb if it's a global name
265+ globalRefs <-
266+ case nameModule_maybe targetName of
267+ Nothing -> pure []
268+ Just mod -> do
269+ ShakeExtras {withHieDb} <- liftIO $ runAction " Rename.HieDb" state getShakeExtras
270+ liftIO $ withHieDb $ \ hieDb ->
271+ fmap (mapMaybe rowToLoc) $ findReferences hieDb True (nameOccName targetName) (Just $ moduleName mod ) (Just $ moduleUnit mod ) []
272+
273+ pure (localRefs ++ globalRefs)
285274---------------------------------------------------------------------------------------------------
286275-- Util
287276
0 commit comments