-
-
Notifications
You must be signed in to change notification settings - Fork 367
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
Add sig inlay hints for where clause #4368
Open
jetjinser
wants to merge
30
commits into
haskell:master
Choose a base branch
from
jetjinser:inlay-hints-local-binding
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
30 commits
Select commit
Hold shift + click to select a range
ba2d544
Add sig lens for where clauses
July541 7bf07ca
Compat
July541 51ef231
Golden tests
July541 cd34e8c
Merge branch 'master' into local-binding-type-lens
pepeiborra c9daf86
Merge branch 'master' into local-binding-type-lens
July541 232e6ba
Merge remote-tracking branch 'upstream/master' into inlay-hints-local…
jetjinser f401ff2
Provide where sigs in inlay hints
jetjinser 287f7fa
add offset for FunBind since infix function
jetjinser 228d669
add ghcide InlayHintTests
jetjinser 52ea29f
use liftZonkM in GHC > 9.7.0
jetjinser e61663d
Fix accidentally broken codeLens
jetjinser 8b6f15e
Add Inlay Hints payload test for type lens
jetjinser e544187
update testdata schema
jetjinser 5fa456d
Apply suggestions from code review
jetjinser 561d082
refactor: bindToSig just return signature string
jetjinser b226661
fix: renamed existingSigNames
jetjinser 837ee45
chore: correct schema property `whereInlayHintOn`
jetjinser 96417e0
fix: typo
jetjinser 20e1274
refactor: rewrite where bindings sig as Rules
jetjinser 6d5f4af
Merge remote-tracking branch 'upstream/master' into inlay-hints-local…
jetjinser efc434b
feat: show local binding instead of just where clause
jetjinser d065a0a
refactor: correct comment location
jetjinser 2d221d8
ignore things that don't have signatures
jetjinser 953db22
refactor
jetjinser 0df54d2
update local-binding inlayHints config desc
jetjinser 59d56bc
update TypeLenses plugin desc
jetjinser 0e69f46
update TypeLenses test/data dirname
jetjinser 2f27e9a
HsLet compatible
jetjinser 80184f8
Merge remote-tracking branch 'upstream/master' into inlay-hints-local…
jetjinser 94c6841
Merge remote-tracking branch 'upstream/master' into inlay-hints-local…
jetjinser File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
module Infix where | ||
|
||
f :: a | ||
f = undefined | ||
where | ||
g :: p1 -> p -> p1 | ||
a `g` b = a |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
module Infix where | ||
|
||
f :: a | ||
f = undefined | ||
where | ||
a `g` b = a |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
module Inline where | ||
|
||
f :: a | ||
f = undefined | ||
where g :: Bool | ||
g = True |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
module Inline where | ||
|
||
f :: a | ||
f = undefined | ||
where g = True |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
module Nest where | ||
|
||
f :: Int | ||
f = g | ||
where | ||
g :: Int | ||
g = h | ||
h :: Int | ||
h = k where k :: Int | ||
k = 3 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
module Nest where | ||
|
||
f :: Int | ||
f = g | ||
where | ||
g = h | ||
h = k where k = 3 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
module NoLens where | ||
|
||
f :: a | ||
f = undefined | ||
where | ||
g = 3 | ||
|
||
|
||
|
||
|
||
|
||
|
||
g :: Int |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
module NoLens where | ||
|
||
f :: a | ||
f = undefined | ||
where | ||
g = 3 | ||
|
||
|
||
|
||
|
||
|
||
|
||
g :: Int |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
module Operator where | ||
|
||
f :: a | ||
f = undefined | ||
where | ||
g :: (a -> b) -> a -> b | ||
g = ($) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
module Operator where | ||
|
||
f :: a | ||
f = undefined | ||
where | ||
g = ($) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
module Qualified where | ||
|
||
import qualified Data.Map as Map | ||
|
||
f :: a | ||
f = undefined | ||
where | ||
g :: Map.Map Bool Char | ||
g = Map.singleton True 'c' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
module Qualified where | ||
|
||
import qualified Data.Map as Map | ||
|
||
f :: a | ||
f = undefined | ||
where | ||
g = Map.singleton True 'c' |
8 changes: 8 additions & 0 deletions
8
ghcide/test/data/local-sig-inlay-hints/ScopedTypeVariables.expected.hs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{-# LANGUAGE ExplicitForAll #-} | ||
module ScopedTypeVariables where | ||
|
||
f :: forall a b. a -> b -> (a, b) | ||
f aa bb = (aa, ida bb) | ||
where | ||
ida :: b -> b | ||
ida = id |
7 changes: 7 additions & 0 deletions
7
ghcide/test/data/local-sig-inlay-hints/ScopedTypeVariables.hs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{-# LANGUAGE ExplicitForAll #-} | ||
module ScopedTypeVariables where | ||
|
||
f :: forall a b. a -> b -> (a, b) | ||
f aa bb = (aa, ida bb) | ||
where | ||
ida = id |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
module Simple where | ||
|
||
f :: a | ||
f = undefined | ||
where | ||
g :: Bool | ||
g = True |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
module Simple where | ||
|
||
f :: a | ||
f = undefined | ||
where | ||
g = True |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
module Typle where | ||
|
||
f :: a | ||
f = undefined | ||
where | ||
g :: Integer | ||
h :: Bool | ||
(g, h) = (1, True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
module Typle where | ||
|
||
f :: a | ||
f = undefined | ||
where | ||
(g, h) = (1, True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
module Typeclass where | ||
|
||
f :: a | ||
f = undefined | ||
where | ||
g :: Num a => a -> a -> a | ||
g a b = a + b |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
module Typeclass where | ||
|
||
f :: a | ||
f = undefined | ||
where | ||
g a b = a + b |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
{-# LANGUAGE ExplicitNamespaces #-} | ||
|
||
module InlayHintTests (tests) where | ||
|
||
import Config (mkIdeTestFs, testWithDummyPlugin, | ||
testWithDummyPluginEmpty) | ||
import Control.Monad (void) | ||
import Control.Monad.IO.Class (MonadIO (liftIO)) | ||
import qualified Data.Aeson as A | ||
import Data.Maybe (mapMaybe) | ||
import qualified Data.Text as T | ||
import Language.LSP.Protocol.Types (InlayHint (..), | ||
Position (Position), | ||
Range (Range, _end, _start), | ||
TextDocumentIdentifier (TextDocumentIdentifier), | ||
TextEdit (TextEdit, _newText, _range), | ||
UInt, | ||
VersionedTextDocumentIdentifier (_uri), | ||
type (|?) (..)) | ||
import Language.LSP.Test (applyEdit, createDoc, | ||
documentContents, getInlayHints, | ||
openDoc, setConfigSection) | ||
import Test.Hls (Assertion, Session, expectFail, | ||
waitForTypecheck) | ||
import Test.Hls.FileSystem (copyDir) | ||
import Test.Tasty (TestTree, testGroup) | ||
import Test.Tasty.HUnit ((@=?), (@?=)) | ||
|
||
tests :: TestTree | ||
tests = testGroup "inlay hints" | ||
[ whereInlayHintsTests | ||
] | ||
|
||
whereInlayHintsTests :: TestTree | ||
whereInlayHintsTests = testGroup "add signature for where clauses" | ||
[ testWithDummyPluginEmpty "No where inlay hints if disabled" $ do | ||
let content = T.unlines | ||
[ "module Sigs where" | ||
, "f :: b" | ||
, "f = undefined" | ||
, " where" | ||
, " g = True" | ||
] | ||
range = Range { _start = Position 4 0 | ||
, _end = Position 4 1000 | ||
} | ||
doc <- createDoc "Sigs.hs" "haskell" content | ||
setConfigSection "haskell" (createConfig False) | ||
inlayHints <- getInlayHints doc range | ||
liftIO $ length inlayHints @?= 0 | ||
, testGroup "apply EditText" | ||
[ editTest "Simple" | ||
, editTest "Tuple" | ||
, editTest "Inline" | ||
, editTest "Infix" | ||
, editTest "Operator" | ||
, expectFail $ editTest "ScopedTypeVariables" | ||
, editTest "Nest" | ||
, editTest "NoLens" | ||
, expectFail $ editTest "Typeclass" | ||
, editTest "Qualified" | ||
] | ||
, testGroup "apply EditText" | ||
[ hintTest "Simple" $ (@=?) | ||
[defInlayHint { _position = Position 5 9 | ||
, _label = InL ":: Bool" | ||
, _textEdits = Just [mkTextEdit 5 8 "g :: Bool\n "] | ||
}] | ||
, hintTest "Tuple" $ (@=?) | ||
[ defInlayHint { _position = Position 5 10 | ||
, _label = InL ":: Integer" | ||
, _textEdits = Just [mkTextEdit 5 8 "g :: Integer\n "] | ||
} | ||
, defInlayHint { _position = Position 5 13 | ||
, _label = InL ":: Bool" | ||
, _textEdits = Just [mkTextEdit 5 8 "h :: Bool\n "] | ||
} | ||
] | ||
, hintTest "Inline" $ (@=?) | ||
[defInlayHint { _position = Position 4 11 | ||
, _label = InL ":: Bool" | ||
, _textEdits = Just [mkTextEdit 4 10 "g :: Bool\n "] | ||
}] | ||
, hintTest "Infix" $ (@=?) | ||
[defInlayHint { _position = Position 5 13 | ||
, _label = InL ":: p1 -> p -> p1" | ||
, _textEdits = Just [mkTextEdit 5 8 "g :: p1 -> p -> p1\n "] | ||
}] | ||
, hintTest "Operator" $ (@=?) | ||
[defInlayHint { _position = Position 5 9 | ||
, _label = InL ":: (a -> b) -> a -> b" | ||
, _textEdits = Just [mkTextEdit 5 8 "g :: (a -> b) -> a -> b\n "] | ||
}] | ||
, hintTest "Nest" $ (@=?) | ||
[ defInlayHint { _position = Position 6 9 | ||
, _label = InL ":: Int" | ||
, _textEdits = Just [mkTextEdit 6 8 "h :: Int\n "] | ||
} | ||
, defInlayHint { _position = Position 5 9 | ||
, _label = InL ":: Int" | ||
, _textEdits = Just [mkTextEdit 5 8 "g :: Int\n "] | ||
} | ||
, defInlayHint { _position = Position 6 21 | ||
, _label = InL ":: Int" | ||
, _textEdits = Just [mkTextEdit 6 20 "k :: Int\n "] | ||
} | ||
] | ||
, hintTest "NoLens" $ (@=?) [] | ||
, hintTest "Qualified" $ (@=?) | ||
[ defInlayHint { _position = Position 7 10 | ||
, _label = InL ":: Map.Map Bool Char" | ||
, _textEdits = Just [mkTextEdit 7 9 "g :: Map.Map Bool Char\n "] | ||
} | ||
] | ||
] | ||
] | ||
|
||
editTest :: String -> TestTree | ||
editTest file = | ||
testWithDummyPlugin (file <> " (InlayHint EditText)") (mkIdeTestFs [copyDir "local-sig-inlay-hints"]) $ do | ||
doc <- openDoc (file ++ ".hs") "haskell" | ||
executeAllHints doc globalRange | ||
real <- documentContents doc | ||
expectedDoc <- openDoc (file ++ ".expected.hs") "haskell" | ||
expected <- documentContents expectedDoc | ||
liftIO $ real @?= expected | ||
|
||
hintTest :: String -> ([InlayHint] -> Assertion) -> TestTree | ||
hintTest file assert = | ||
testWithDummyPlugin (file <> " (InlayHint)") (mkIdeTestFs [copyDir "local-sig-inlay-hints"]) $ do | ||
doc <- openDoc (file ++ ".hs") "haskell" | ||
hints <- getInlayHints doc globalRange | ||
liftIO $ assert hints | ||
|
||
|
||
createConfig :: Bool -> A.Value | ||
createConfig on = | ||
A.object [ "plugin" | ||
A..= A.object [ "ghcide-type-lenses" | ||
A..= A.object [ "config" | ||
A..= A.object [ "localBindingInlayHintOn" A..= A.Bool on ]]]] | ||
|
||
|
||
executeAllHints :: TextDocumentIdentifier -> Range -> Session () | ||
executeAllHints doc range = do | ||
void $ waitForTypecheck doc | ||
hints <- getInlayHints doc range | ||
let edits = concat $ mapMaybe _textEdits hints | ||
case edits of | ||
[] -> pure () | ||
edit : _ -> do | ||
newDoc <- applyEdit doc edit | ||
executeAllHints (TextDocumentIdentifier $ _uri newDoc) range | ||
|
||
defInlayHint :: InlayHint | ||
defInlayHint = | ||
InlayHint { _position = Position 0 0 | ||
, _label = InL "" | ||
, _kind = Nothing | ||
, _textEdits = Nothing | ||
, _tooltip = Nothing | ||
, _paddingLeft = Just True | ||
, _paddingRight = Nothing | ||
, _data_ = Nothing | ||
} | ||
|
||
mkTextEdit :: UInt -> UInt -> T.Text -> TextEdit | ||
mkTextEdit x y text = | ||
TextEdit { _range = pointRange x y | ||
, _newText = text | ||
} | ||
|
||
pointRange :: UInt -> UInt -> Range | ||
pointRange x y = Range (Position x y) (Position x y) | ||
|
||
globalRange :: Range | ||
globalRange = Range { _start = Position 0 0 | ||
, _end = Position 1000 0 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we should display the hints on the previous line rather than right after the binding. i.e. make the hint look like the edit currently does.
Advantages:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think inlay hints can do this.
I found this issue: microsoft/language-server-protocol#1821.
AFAIK, standard inlay hints cannot be in virtual line.
It's more like a fixed position code lens?