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

Add sig lens for where clauses #2966

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 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
10 changes: 10 additions & 0 deletions ghcide/src/Development/IDE/GHC/Compat/Core.hs
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,9 @@ module Development.IDE.GHC.Compat.Core (
gre_par,
#if MIN_VERSION_ghc(9,2,0)
collectHsBindsBinders,
NHsValBindsLR(..),
#endif
grhssLocalBindsCompat,
-- * Util Module re-exports
#if MIN_VERSION_ghc(9,0,0)
module GHC.Builtin.Names,
Expand Down Expand Up @@ -482,6 +484,7 @@ import GHC.Types.Unique.FM
#if MIN_VERSION_ghc(9,2,0)
import GHC.Data.Bag
import GHC.Core.Multiplicity (scaledThing)
import GHC.Hs.Binds (NHsValBindsLR(..))
#else
import GHC.Core.Ppr.TyThing hiding (pprFamInst)
import GHC.Core.TyCo.Rep (scaledThing)
Expand Down Expand Up @@ -1084,3 +1087,10 @@ pattern LetStmt xlet localBinds <- GHC.LetStmt xlet (SrcLoc.unLoc -> localBinds)
rationalFromFractionalLit :: FractionalLit -> Rational
rationalFromFractionalLit = fl_value
#endif

grhssLocalBindsCompat :: GRHSs p body -> HsLocalBinds p
#if MIN_VERSION_ghc(9,2,0)
grhssLocalBindsCompat = grhssLocalBinds
#else
grhssLocalBindsCompat = SrcLoc.unLoc . grhssLocalBinds
#endif
206 changes: 183 additions & 23 deletions ghcide/src/Development/IDE/Plugin/TypeLenses.hs

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions ghcide/test/data/local-sig-lens/Infix.expected.hs
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
6 changes: 6 additions & 0 deletions ghcide/test/data/local-sig-lens/Infix.hs
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
6 changes: 6 additions & 0 deletions ghcide/test/data/local-sig-lens/Inline.expected.hs
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
5 changes: 5 additions & 0 deletions ghcide/test/data/local-sig-lens/Inline.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module Inline where

f :: a
f = undefined
where g = True
10 changes: 10 additions & 0 deletions ghcide/test/data/local-sig-lens/Nest.expected.hs
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
7 changes: 7 additions & 0 deletions ghcide/test/data/local-sig-lens/Nest.hs
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
13 changes: 13 additions & 0 deletions ghcide/test/data/local-sig-lens/NoLens.expected.hs
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
13 changes: 13 additions & 0 deletions ghcide/test/data/local-sig-lens/NoLens.hs
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
7 changes: 7 additions & 0 deletions ghcide/test/data/local-sig-lens/Operator.expected.hs
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 = ($)
6 changes: 6 additions & 0 deletions ghcide/test/data/local-sig-lens/Operator.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module Operator where

f :: a
f = undefined
where
g = ($)
9 changes: 9 additions & 0 deletions ghcide/test/data/local-sig-lens/Qualified.expected.hs
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'
8 changes: 8 additions & 0 deletions ghcide/test/data/local-sig-lens/Qualified.hs
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'
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
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It fails as you may guess...

7 changes: 7 additions & 0 deletions ghcide/test/data/local-sig-lens/ScopedTypeVariables.hs
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
7 changes: 7 additions & 0 deletions ghcide/test/data/local-sig-lens/Simple.expected.hs
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
6 changes: 6 additions & 0 deletions ghcide/test/data/local-sig-lens/Simple.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module Simple where

f :: a
f = undefined
where
g = True
8 changes: 8 additions & 0 deletions ghcide/test/data/local-sig-lens/Tuple.expected.hs
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)
6 changes: 6 additions & 0 deletions ghcide/test/data/local-sig-lens/Tuple.hs
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)
7 changes: 7 additions & 0 deletions ghcide/test/data/local-sig-lens/Typeclass.expected.hs
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
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Num a lost here, the same method can show constraints for top-level bindings...

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you saying that the lens cannot deduce Num a => here if the signature is not present?
I find that ok, constraints belong at the top level, not in local type signatures

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for ignoring this...

Are you saying that the lens cannot deduce Num a => here if the signature is not present?

Yes.

I find that ok, constraints belong at the top level, not in local type signatures

But it's not correct without constraints.

6 changes: 6 additions & 0 deletions ghcide/test/data/local-sig-lens/Typeclass.hs
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
56 changes: 56 additions & 0 deletions ghcide/test/exe/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -848,6 +848,7 @@ codeActionHelperFunctionTests = testGroup "code action helpers"
codeLensesTests :: TestTree
codeLensesTests = testGroup "code lenses"
[ addSigLensesTests
, addSigLensesForWhereClausesTests
]

watchedFilesTests :: TestTree
Expand Down Expand Up @@ -4230,6 +4231,61 @@ addSigLensesTests =
]
]

addSigLensesForWhereClausesTests :: TestTree
addSigLensesForWhereClausesTests = testGroup
"add signature for where clauses"
[ testSession "No lens if disbled" $ do
let content = T.unlines
[ "module Sigs where"
, "f :: b"
, "f = undefined"
, " where"
July541 marked this conversation as resolved.
Show resolved Hide resolved
, " g = True"
]
sendNotification SWorkspaceDidChangeConfiguration
$ DidChangeConfigurationParams
$ A.object
["haskell" A..= A.object
["plugin" A..= A.object
["ghcide-type-lenses" A..= A.object
["config" A..= A.object
["whereLensOn" A..= A.Bool False]]]]]
doc <- createDoc "Sigs.hs" "haskell" content
waitForProgressDone
lenses <- getCodeLenses doc
liftIO $ length lenses @?= 0
, test "Simple" "Simple"
, test "Tuple" "Tuple"
, test "Inline" "Inline"
, test "Infix" "Infix"
, test "Operator" "Operator"
, expectFail $ test "ScopedTypeVariables" "ScopedTypeVariables"
, test "Nest" "Nest"
, test "No lens" "NoLens"
, expectFail $ test "Typeclass" "Typeclass"
, test "Quqlified" "Qualified"
]
where
test :: String -> FilePath -> TestTree
test title file = testSessionWithExtraFiles "local-sig-lens" title $ \dir -> do
doc <- openDoc (dir </> file ++ ".hs") "haskell"
executeAllLens doc
real <- documentContents doc
expectedDoc <- openDoc (dir </> file ++ ".expected.hs") "haskell"
expected <- documentContents expectedDoc
liftIO $ real @?= expected

executeAllLens :: TextDocumentIdentifier -> Session ()
executeAllLens doc = do
void $ waitForTypecheck doc
lenses <- getCodeLenses doc
let cmds = mapMaybe (^. L.command) lenses
unless (null cmds) $ do
let cmd = head cmds
executeCommand cmd
void $ skipManyTill anyMessage (getDocumentEdit doc)
executeAllLens doc

linkToLocation :: [LocationLink] -> [Location]
linkToLocation = map (\LocationLink{_targetUri,_targetRange} -> Location _targetUri _targetRange)

Expand Down