Skip to content

Fix misplaced inlay hints by applying PositionMapping #4571

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import Control.Monad.Trans.Maybe
import qualified Data.Aeson as A (ToJSON (toJSON))
import Data.Aeson.Types (FromJSON)
import Data.Char (isSpace)
import Data.Functor ((<&>))
import qualified Data.IntMap as IM (IntMap, elems,
fromList, (!?))
import Data.IORef (readIORef)
Expand Down Expand Up @@ -218,16 +217,18 @@ inlayHintProvider _ state _ InlayHintParams {_textDocument = TextDocumentIdentif
-- |^-_paddingLeft
-- ^-_position
generateInlayHints :: Range -> ImportEdit -> PositionMapping -> Maybe InlayHint
generateInlayHints (Range _ end) ie pm = mkLabel ie <&> \label ->
InlayHint { _position = end
, _label = InL label
, _kind = Nothing -- neither a type nor a parameter
, _textEdits = fmap singleton $ toTEdit pm ie
, _tooltip = Just $ InL "Make this import explicit" -- simple enough, no need to resolve
, _paddingLeft = Just True -- show an extra space before the inlay hint
, _paddingRight = Nothing
, _data_ = Nothing
}
generateInlayHints (Range _ end) ie pm = do
label <- mkLabel ie
currentEnd <- toCurrentPosition pm end
return InlayHint { _position = currentEnd
, _label = InL label
, _kind = Nothing -- neither a type nor a parameter
, _textEdits = fmap singleton $ toTEdit pm ie
, _tooltip = Just $ InL "Make this import explicit" -- simple enough, no need to resolve
, _paddingLeft = Just True -- show an extra space before the inlay hint
, _paddingRight = Nothing
, _data_ = Nothing
}
mkLabel :: ImportEdit -> Maybe T.Text
mkLabel (ImportEdit{ieResType, ieText}) =
let title ExplicitImport = Just $ abbreviateImportTitleWithoutModule ieText
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ import Development.IDE (IdeState,
srcSpanToLocation,
srcSpanToRange, viaShow)
import Development.IDE.Core.PluginUtils
import Development.IDE.Core.PositionMapping (toCurrentRange)
import Development.IDE.Core.PositionMapping (PositionMapping,
toCurrentPosition,
toCurrentRange)
import Development.IDE.Core.RuleTypes (TcModuleResult (..),
TypeCheck (..))
import qualified Development.IDE.Core.Shake as Shake
Expand Down Expand Up @@ -204,19 +206,19 @@ inlayHintDotdotProvider _ state pId InlayHintParams {_textDocument = TextDocumen
| record <- records
, pos <- maybeToList $ fmap _start $ recordInfoToDotDotRange record ]
defnLocsList <- lift $ sequence locations
pure $ InL $ mapMaybe (mkInlayHint crr pragma) defnLocsList
pure $ InL $ mapMaybe (mkInlayHint crr pragma pm) defnLocsList
where
mkInlayHint :: CollectRecordsResult -> NextPragmaInfo -> (Maybe [(Location, Identifier)], RecordInfo) -> Maybe InlayHint
mkInlayHint CRR {enabledExtensions, nameMap} pragma (defnLocs, record) =
mkInlayHint :: CollectRecordsResult -> NextPragmaInfo -> PositionMapping -> (Maybe [(Location, Identifier)], RecordInfo) -> Maybe InlayHint
mkInlayHint CRR {enabledExtensions, nameMap} pragma pm (defnLocs, record) =
let range = recordInfoToDotDotRange record
textEdits = maybeToList (renderRecordInfoAsTextEdit nameMap record)
<> maybeToList (pragmaEdit enabledExtensions pragma)
names = renderRecordInfoAsDotdotLabelName record
in do
end <- fmap _end range
currentEnd <- range >>= toCurrentPosition pm . _end
names' <- names
defnLocs' <- defnLocs
let excludeDotDot (Location _ (Range _ end')) = end' /= end
let excludeDotDot (Location _ (Range _ end)) = end /= currentEnd
-- find location from dotdot definitions that name equal to label name
findLocation name locations =
let -- filter locations not within dotdot range
Expand All @@ -227,7 +229,7 @@ inlayHintDotdotProvider _ state pId InlayHintParams {_textDocument = TextDocumen
valueWithLoc = [ (T.pack $ printName name, findLocation name defnLocs') | name <- names' ]
-- use `, ` to separate labels with definition location
label = intersperse (mkInlayHintLabelPart (", ", Nothing)) $ fmap mkInlayHintLabelPart valueWithLoc
pure $ InlayHint { _position = end -- at the end of dotdot
pure $ InlayHint { _position = currentEnd -- at the end of dotdot
, _label = InR label
, _kind = Nothing -- neither a type nor a parameter
, _textEdits = Just textEdits -- same as CodeAction
Expand All @@ -248,20 +250,22 @@ inlayHintPosRecProvider _ state _pId InlayHintParams {_textDocument = TextDocume
| Just range <- [toCurrentRange pm visibleRange]
, uid <- RangeMap.elementsInRange range crCodeActions
, Just record <- [IntMap.lookup uid crCodeActionResolve] ]
pure $ InL (concatMap (mkInlayHints nameMap) records)
pure $ InL (concatMap (mkInlayHints nameMap pm) records)
where
mkInlayHints :: UniqFM Name [Name] -> RecordInfo -> [InlayHint]
mkInlayHints nameMap record@(RecordInfoApp _ (RecordAppExpr _ fla)) =
mkInlayHints :: UniqFM Name [Name] -> PositionMapping -> RecordInfo -> [InlayHint]
mkInlayHints nameMap pm record@(RecordInfoApp _ (RecordAppExpr _ fla)) =
let textEdits = renderRecordInfoAsTextEdit nameMap record
in mapMaybe (mkInlayHint textEdits) fla
mkInlayHints _ _ = []
mkInlayHint :: Maybe TextEdit -> (Located FieldLabel, HsExpr GhcTc) -> Maybe InlayHint
mkInlayHint te (label, _) =
in mapMaybe (mkInlayHint textEdits pm) fla
mkInlayHints _ _ _ = []

mkInlayHint :: Maybe TextEdit -> PositionMapping -> (Located FieldLabel, HsExpr GhcTc) -> Maybe InlayHint
mkInlayHint te pm (label, _) =
let (name, loc) = ((flSelector . unLoc) &&& (srcSpanToLocation . getLoc)) label
fieldDefLoc = srcSpanToLocation (nameSrcSpan name)
in do
(Location _ recRange) <- loc
pure InlayHint { _position = _start recRange
currentStart <- toCurrentPosition pm (_start recRange)
pure InlayHint { _position = currentStart
, _label = InR $ pure (mkInlayHintLabelPart name fieldDefLoc)
, _kind = Nothing -- neither a type nor a parameter
, _textEdits = Just (maybeToList te) -- same as CodeAction
Expand All @@ -270,6 +274,7 @@ inlayHintPosRecProvider _ state _pId InlayHintParams {_textDocument = TextDocume
, _paddingRight = Nothing
, _data_ = Nothing
}

mkInlayHintLabelPart name loc = InlayHintLabelPart (printOutputable (pprNameUnqualified name) <> "=") Nothing loc Nothing

mkTitle :: [Extension] -> Text
Expand Down
Loading