Skip to content
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

Support Inlay hints for record wildcards #4351

Merged
merged 60 commits into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
b7da1f5
Provide explicit import in inlay hints
jetjinser May 16, 2024
3305973
Filter explict imports inlay hints by visible range
jetjinser Jun 14, 2024
245049a
Update lsp dep by source-repository-package
jetjinser Jun 14, 2024
0598138
Add test for hls-explicit-imports-plugin inlay hints
jetjinser Jun 14, 2024
a27c5c8
Comment inlay hints start position
jetjinser Jun 17, 2024
6b3e5aa
Use `isSubrangeOf` to test if the range is visible
jetjinser Jun 17, 2024
f9f1207
Remove inlayHintsResolveProvider placeholder for now
jetjinser Jun 17, 2024
8e28076
Use explicit InlayHintKind_Type
jetjinser Jun 17, 2024
d0f27c2
Revert "Update lsp dep by source-repository-package"
jetjinser Jun 17, 2024
3e9d5a1
Combine InlayHints by sconcat them
jetjinser Jun 17, 2024
8d94c51
Merge remote-tracking branch 'upstream/master' into inlay-hints-imports
jetjinser Jun 21, 2024
2e869db
Merge remote-tracking branch 'upstream/master' into inlay-hints-imports
jetjinser Jun 21, 2024
dbd7508
compress multiple spaces in abbr import tilte
jetjinser Jun 22, 2024
d0fe221
update test to match inlay hints kind
jetjinser Jun 22, 2024
75b0ecb
rename squashedAbbreviateImportTitle to abbreviateImportTitleWithoutM…
jetjinser Jun 22, 2024
e0543b9
Request inlay hints with testEdits
jetjinser Jun 22, 2024
a6b7556
ExplicitImports fallback to codelens when inlay hints not support
jetjinser Jun 22, 2024
2085635
fix explicitImports inlayHints test
jetjinser Jun 23, 2024
ccf2d8f
simplify isInlayHintsSupported
jetjinser Jun 25, 2024
fb52cee
comment fallback
jetjinser Jun 25, 2024
6e5f746
empty list instead of null codeLens
jetjinser Jun 25, 2024
f4c2ea2
clearify name `paddingLeft`
jetjinser Jun 25, 2024
62a51ce
fix clientCapabilities
jetjinser Jun 25, 2024
f70e402
add test for inlay hints without its client caps
jetjinser Jun 25, 2024
57ef0db
use codeActionNoInlayHintsCaps to avoid error
jetjinser Jun 28, 2024
f8b1993
simplify isInlayHintSupported
jetjinser Jun 29, 2024
a50b148
comment about paddingLeft
jetjinser Jun 29, 2024
af635f7
use null as inlay hints kind
jetjinser Jun 29, 2024
0fab728
add tooltip for explicit imports inlay hints to improve UX
jetjinser Jun 29, 2024
4c7313d
chore comments
jetjinser Jun 29, 2024
ffdb94c
refactor
jetjinser Jun 29, 2024
0a876c3
comment InL [] to indicate no info
jetjinser Jul 1, 2024
c11e356
ignore refine inlay hints
jetjinser Jul 1, 2024
599ebcf
add plcInlayHintsOn config
jetjinser Jul 1, 2024
2a2b516
Merge remote-tracking branch 'upstream/master' into inlay-hints-imports
jetjinser Jul 2, 2024
3e5b88f
update func-test
jetjinser Jul 2, 2024
6cfafd5
keep order to make Parser works
jetjinser Jul 2, 2024
ce761e7
always provide refine in code lens
jetjinser Jul 5, 2024
2f3b57b
Merge branch 'master' into inlay-hints-imports
michaelpj Jul 6, 2024
d1451b8
init explicit record fields inlay hints
jetjinser Jul 7, 2024
72ee091
Merge remote-tracking branch 'upstream/master' into inlay-hints-recor…
jetjinser Jul 10, 2024
9a4d7f5
dotdot location in label part
jetjinser Jul 15, 2024
f229b81
update test for dotdot location in label part
jetjinser Jul 16, 2024
6a51da6
Merge remote-tracking branch 'upstream/master' into inlay-hints-recor…
jetjinser Jul 16, 2024
7f8ee62
get(Type)Definition with its Identifier
jetjinser Jul 21, 2024
0dd9ef3
add flipped filterByRange
jetjinser Jul 21, 2024
1810a67
filter label with name
jetjinser Jul 21, 2024
a4103bd
update test
jetjinser Jul 21, 2024
96a2550
Merge remote-tracking branch 'upstream/master' into inlay-hints-recor…
jetjinser Aug 9, 2024
931ae0e
re-generate schema
jetjinser Aug 10, 2024
9ba894b
fix explict-record-fields plugin in GHC 910
jetjinser Aug 21, 2024
1c2e3b7
fix use correct currentPosition
jetjinser Aug 21, 2024
a0a35b7
comment
jetjinser Aug 21, 2024
4faf1d0
rename flippedFilterByRange to elementsInRange
jetjinser Aug 21, 2024
6967f67
refactor: lift
jetjinser Aug 21, 2024
7bc5843
refactor: break pointfree
jetjinser Aug 21, 2024
ab3f84a
refactor
jetjinser Aug 21, 2024
d786549
recover accidentally deleted macros
jetjinser Aug 21, 2024
1c74d0c
Merge branch 'master' into inlay-hints-record-wildcards
jetjinser Aug 21, 2024
13b9144
Merge branch 'master' into inlay-hints-record-wildcards
mergify[bot] Aug 28, 2024
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
69 changes: 36 additions & 33 deletions ghcide/src/Development/IDE/Core/Actions.hs
Original file line number Diff line number Diff line change
Expand Up @@ -66,56 +66,59 @@ getAtPoint file pos = runMaybeT $ do
!pos' <- MaybeT (return $ fromCurrentPosition mapping pos)
MaybeT $ liftIO $ fmap (first (toCurrentRange mapping =<<)) <$> AtPoint.atPoint opts hf dkMap env pos'

-- | For each Location, determine if we have the PositionMapping
-- for the correct file. If not, get the correct position mapping
-- and then apply the position mapping to the location.
toCurrentLocations
-- | Converts locations in the source code to their current positions,
-- taking into account changes that may have occurred due to edits.
toCurrentLocation
:: PositionMapping
-> NormalizedFilePath
-> [Location]
-> IdeAction [Location]
toCurrentLocations mapping file = mapMaybeM go
-> Location
-> IdeAction (Maybe Location)
toCurrentLocation mapping file (Location uri range) =
-- The Location we are going to might be in a different
-- file than the one we are calling gotoDefinition from.
-- So we check that the location file matches the file
-- we are in.
if nUri == normalizedFilePathToUri file
-- The Location matches the file, so use the PositionMapping
-- we have.
then pure $ Location uri <$> toCurrentRange mapping range
-- The Location does not match the file, so get the correct
-- PositionMapping and use that instead.
else do
otherLocationMapping <- fmap (fmap snd) $ runMaybeT $ do
otherLocationFile <- MaybeT $ pure $ uriToNormalizedFilePath nUri
useWithStaleFastMT GetHieAst otherLocationFile
pure $ Location uri <$> (flip toCurrentRange range =<< otherLocationMapping)
where
go :: Location -> IdeAction (Maybe Location)
go (Location uri range) =
-- The Location we are going to might be in a different
-- file than the one we are calling gotoDefinition from.
-- So we check that the location file matches the file
-- we are in.
if nUri == normalizedFilePathToUri file
-- The Location matches the file, so use the PositionMapping
-- we have.
then pure $ Location uri <$> toCurrentRange mapping range
-- The Location does not match the file, so get the correct
-- PositionMapping and use that instead.
else do
otherLocationMapping <- fmap (fmap snd) $ runMaybeT $ do
otherLocationFile <- MaybeT $ pure $ uriToNormalizedFilePath nUri
useWithStaleFastMT GetHieAst otherLocationFile
pure $ Location uri <$> (flip toCurrentRange range =<< otherLocationMapping)
where
nUri :: NormalizedUri
nUri = toNormalizedUri uri
nUri :: NormalizedUri
nUri = toNormalizedUri uri

-- | Goto Definition.
getDefinition :: NormalizedFilePath -> Position -> IdeAction (Maybe [Location])
getDefinition :: NormalizedFilePath -> Position -> IdeAction (Maybe [(Location, Identifier)])
getDefinition file pos = runMaybeT $ do
ide@ShakeExtras{ withHieDb, hiedbWriter } <- ask
opts <- liftIO $ getIdeOptionsIO ide
(HAR _ hf _ _ _, mapping) <- useWithStaleFastMT GetHieAst file
(ImportMap imports, _) <- useWithStaleFastMT GetImportMap file
!pos' <- MaybeT (pure $ fromCurrentPosition mapping pos)
locations <- AtPoint.gotoDefinition withHieDb (lookupMod hiedbWriter) opts imports hf pos'
MaybeT $ Just <$> toCurrentLocations mapping file locations
locationsWithIdentifier <- AtPoint.gotoDefinition withHieDb (lookupMod hiedbWriter) opts imports hf pos'
mapMaybeM (\(location, identifier) -> do
fixedLocation <- MaybeT $ toCurrentLocation mapping file location
pure $ Just (fixedLocation, identifier)
) locationsWithIdentifier

getTypeDefinition :: NormalizedFilePath -> Position -> IdeAction (Maybe [Location])

getTypeDefinition :: NormalizedFilePath -> Position -> IdeAction (Maybe [(Location, Identifier)])
getTypeDefinition file pos = runMaybeT $ do
ide@ShakeExtras{ withHieDb, hiedbWriter } <- ask
opts <- liftIO $ getIdeOptionsIO ide
(hf, mapping) <- useWithStaleFastMT GetHieAst file
!pos' <- MaybeT (return $ fromCurrentPosition mapping pos)
locations <- AtPoint.gotoTypeDefinition withHieDb (lookupMod hiedbWriter) opts hf pos'
MaybeT $ Just <$> toCurrentLocations mapping file locations
locationsWithIdentifier <- AtPoint.gotoTypeDefinition withHieDb (lookupMod hiedbWriter) opts hf pos'
mapMaybeM (\(location, identifier) -> do
fixedLocation <- MaybeT $ toCurrentLocation mapping file location
pure $ Just (fixedLocation, identifier)
) locationsWithIdentifier

highlightAtPoint :: NormalizedFilePath -> Position -> IdeAction (Maybe [DocumentHighlight])
highlightAtPoint file pos = runMaybeT $ do
Expand Down
2 changes: 2 additions & 0 deletions ghcide/src/Development/IDE/GHC/Compat/Core.hs
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,7 @@
moduleUnit, toUnitId)
import qualified GHC.Unit.Module as Module
import GHC.Unit.State (ModuleOrigin (..))
import GHC.Utils.Error (Severity (..), emptyMessages)

Check warning on line 482 in ghcide/src/Development/IDE/GHC/Compat/Core.hs

View workflow job for this annotation

GitHub Actions / Hlint check run

Warning in module Development.IDE.GHC.Compat.Core: Use fewer imports ▫︎ Found: "import GHC.Utils.Error ( Severity(..), emptyMessages )\nimport GHC.Utils.Error ( mkPlainErrorMsgEnvelope )\n" ▫︎ Perhaps: "import GHC.Utils.Error\n ( Severity(..), emptyMessages, mkPlainErrorMsgEnvelope )\n"
import GHC.Utils.Panic hiding (try)
import qualified GHC.Utils.Panic.Plain as Plain

Expand Down Expand Up @@ -633,6 +633,8 @@
#if MIN_VERSION_ghc(9,9,0)
instance HasSrcSpan (SrcLoc.GenLocated (EpAnn ann) a) where
getLoc (L l _) = getLoc l
instance HasSrcSpan (SrcLoc.GenLocated (GHC.EpaLocation) a) where
getLoc = GHC.getHasLoc
#else
instance HasSrcSpan (SrcSpanAnn' ann) where
getLoc = GHC.locA
Expand Down
6 changes: 6 additions & 0 deletions ghcide/src/Development/IDE/GHC/Orphans.hs
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,12 @@ instance NFData (HsExpr (GhcPass Renamed)) where
instance NFData (Pat (GhcPass Renamed)) where
rnf = rwhnf

instance NFData (HsExpr (GhcPass Typechecked)) where
rnf = rwhnf

instance NFData (Pat (GhcPass Typechecked)) where
rnf = rwhnf

instance NFData Extension where
rnf = rwhnf

Expand Down
4 changes: 2 additions & 2 deletions ghcide/src/Development/IDE/LSP/HoverDefinition.hs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ gotoDefinition :: Recorder (WithPriority Log) -> IdeState -> TextDocumentPos
hover :: Recorder (WithPriority Log) -> IdeState -> TextDocumentPositionParams -> ExceptT PluginError (HandlerM c) (Hover |? Null)
gotoTypeDefinition :: Recorder (WithPriority Log) -> IdeState -> TextDocumentPositionParams -> ExceptT PluginError (HandlerM c) (MessageResult Method_TextDocumentTypeDefinition)
documentHighlight :: Recorder (WithPriority Log) -> IdeState -> TextDocumentPositionParams -> ExceptT PluginError (HandlerM c) ([DocumentHighlight] |? Null)
gotoDefinition = request "Definition" getDefinition (InR $ InR Null) (InL . Definition. InR)
gotoTypeDefinition = request "TypeDefinition" getTypeDefinition (InR $ InR Null) (InL . Definition. InR)
gotoDefinition = request "Definition" getDefinition (InR $ InR Null) (InL . Definition. InR . map fst)
gotoTypeDefinition = request "TypeDefinition" getTypeDefinition (InR $ InR Null) (InL . Definition. InR . map fst)
hover = request "Hover" getAtPoint (InR Null) foundHover
documentHighlight = request "DocumentHighlight" highlightAtPoint (InR Null) InL

Expand Down
22 changes: 14 additions & 8 deletions ghcide/src/Development/IDE/Spans/AtPoint.hs
Original file line number Diff line number Diff line change
Expand Up @@ -179,14 +179,15 @@ documentHighlight hf rf pos = pure highlights
then DocumentHighlightKind_Write
else DocumentHighlightKind_Read

-- | Locate the type definition of the name at a given position.
gotoTypeDefinition
:: MonadIO m
=> WithHieDb
-> LookupModule m
-> IdeOptions
-> HieAstResult
-> Position
-> MaybeT m [Location]
-> MaybeT m [(Location, Identifier)]
gotoTypeDefinition withHieDb lookupModule ideOpts srcSpans pos
= lift $ typeLocationsAtPoint withHieDb lookupModule ideOpts pos srcSpans

Expand All @@ -199,7 +200,7 @@ gotoDefinition
-> M.Map ModuleName NormalizedFilePath
-> HieASTs a
-> Position
-> MaybeT m [Location]
-> MaybeT m [(Location, Identifier)]
gotoDefinition withHieDb getHieFile ideOpts imports srcSpans pos
= lift $ locationsAtPoint withHieDb getHieFile ideOpts imports pos srcSpans

Expand Down Expand Up @@ -306,6 +307,7 @@ atPoint IdeOptions{} (HAR _ hf _ _ (kind :: HieKind hietype)) (DKMap dm km) env
UnhelpfulLoc {} | isInternalName name || isSystemName name -> Nothing
_ -> Just $ "*Defined " <> printOutputable (pprNameDefnLoc name) <> "*"

-- | Find 'Location's of type definition at a specific point and return them along with their 'Identifier's.
typeLocationsAtPoint
:: forall m
. MonadIO m
Expand All @@ -314,7 +316,7 @@ typeLocationsAtPoint
-> IdeOptions
-> Position
-> HieAstResult
-> m [Location]
-> m [(Location, Identifier)]
fendor marked this conversation as resolved.
Show resolved Hide resolved
typeLocationsAtPoint withHieDb lookupModule _ideOptions pos (HAR _ ast _ _ hieKind) =
case hieKind of
HieFromDisk hf ->
Expand All @@ -332,12 +334,12 @@ typeLocationsAtPoint withHieDb lookupModule _ideOptions pos (HAR _ ast _ _ hieKi
HQualTy a b -> getTypes' [a,b]
HCastTy a -> getTypes' [a]
_ -> []
in fmap nubOrd $ concatMapM (fmap (fromMaybe []) . nameToLocation withHieDb lookupModule) (getTypes' ts)
in fmap nubOrd $ concatMapM (\n -> fmap (maybe [] (fmap (,Right n))) (nameToLocation withHieDb lookupModule n)) (getTypes' ts)
HieFresh ->
let ts = concat $ pointCommand ast pos getts
getts x = nodeType ni ++ (mapMaybe identType $ M.elems $ nodeIdentifiers ni)
where ni = nodeInfo x
in fmap nubOrd $ concatMapM (fmap (fromMaybe []) . nameToLocation withHieDb lookupModule) (getTypes ts)
in fmap nubOrd $ concatMapM (\n -> fmap (maybe [] (fmap (,Right n))) (nameToLocation withHieDb lookupModule n)) (getTypes ts)

namesInType :: Type -> [Name]
namesInType (TyVarTy n) = [varName n]
Expand All @@ -352,6 +354,7 @@ namesInType _ = []
getTypes :: [Type] -> [Name]
getTypes ts = concatMap namesInType ts

-- | Find 'Location's of definition at a specific point and return them along with their 'Identifier's.
locationsAtPoint
:: forall m a
. MonadIO m
Expand All @@ -361,13 +364,16 @@ locationsAtPoint
-> M.Map ModuleName NormalizedFilePath
-> Position
-> HieASTs a
-> m [Location]
-> m [(Location, Identifier)]
fendor marked this conversation as resolved.
Show resolved Hide resolved
locationsAtPoint withHieDb lookupModule _ideOptions imports pos ast =
let ns = concat $ pointCommand ast pos (M.keys . getNodeIds)
zeroPos = Position 0 0
zeroRange = Range zeroPos zeroPos
modToLocation m = fmap (\fs -> pure $ Location (fromNormalizedUri $ filePathToUri' fs) zeroRange) $ M.lookup m imports
in fmap (nubOrd . concat) $ mapMaybeM (either (pure . modToLocation) $ nameToLocation withHieDb lookupModule) ns
modToLocation m = fmap (\fs -> pure (Location (fromNormalizedUri $ filePathToUri' fs) zeroRange)) $ M.lookup m imports
in fmap (nubOrd . concat) $ mapMaybeM
(either (\m -> pure ((fmap $ fmap (,Left m)) (modToLocation m)))
(\n -> fmap (fmap $ fmap (,Right n)) (nameToLocation withHieDb lookupModule n)))
ns

-- | Given a 'Name' attempt to find the location where it is defined.
nameToLocation :: MonadIO m => WithHieDb -> LookupModule m -> Name -> m (Maybe [Location])
Expand Down
1 change: 1 addition & 0 deletions haskell-language-server.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -1360,6 +1360,7 @@ test-suite hls-explicit-record-fields-plugin-tests
, base
, filepath
, text
, ghcide
, haskell-language-server:hls-explicit-record-fields-plugin
, hls-test-utils == 2.9.0.1

Expand Down
9 changes: 9 additions & 0 deletions hls-plugin-api/src/Ide/Plugin/RangeMap.hs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ module Ide.Plugin.RangeMap
fromList,
fromList',
filterByRange,
elementsInRange,
) where

import Development.IDE.Graph.Classes (NFData)
Expand Down Expand Up @@ -67,6 +68,14 @@ filterByRange range = map snd . IM.dominators (rangeToInterval range) . unRangeM
filterByRange range = map snd . filter (isSubrangeOf range . fst) . unRangeMap
#endif

-- | Extracts all elements from a 'RangeMap' that fall within a given 'Range'.
elementsInRange :: Range -> RangeMap a -> [a]
#ifdef USE_FINGERTREE
elementsInRange range = map snd . IM.intersections (rangeToInterval range) . unRangeMap
#else
elementsInRange range = map snd . filter (flip isSubrangeOf range . fst) . unRangeMap
#endif

#ifdef USE_FINGERTREE
-- NOTE(ozkutuk): In itself, this conversion is wrong. As Michael put it:
-- "LSP Ranges have exclusive upper bounds, whereas the intervals here are
Expand Down
Loading
Loading