Skip to content

Commit 69c8ac3

Browse files
committed
Inline code action
1 parent a7ab9eb commit 69c8ac3

23 files changed

+609
-137
lines changed

ghcide/src/Development/IDE/Core/Actions.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ module Development.IDE.Core.Actions
1010
, useNoFileE
1111
, usesE
1212
, workspaceSymbols
13+
, lookupMod
1314
) where
1415

1516
import Control.Monad.Reader

ghcide/src/Development/IDE/Core/Shake.hs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -982,7 +982,10 @@ usesWithStale_ key files = do
982982
--
983983
-- Run via 'runIdeAction'.
984984
newtype IdeAction a = IdeAction { runIdeActionT :: (ReaderT ShakeExtras IO) a }
985-
deriving newtype (MonadReader ShakeExtras, MonadIO, Functor, Applicative, Monad)
985+
deriving newtype (MonadReader ShakeExtras, MonadIO, Functor, Applicative, Monad, Semigroup)
986+
987+
-- https://hub.darcs.net/ross/transformers/issue/86
988+
deriving instance (Semigroup (m a)) => Semigroup (ReaderT r m a)
986989

987990
runIdeAction :: String -> ShakeExtras -> IdeAction a -> IO a
988991
runIdeAction _herald s i = runReaderT (runIdeActionT i) s

ghcide/src/Development/IDE/GHC/Compat/Core.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,7 @@ module Development.IDE.GHC.Compat.Core (
447447
-- * Syntax re-exports
448448
#if MIN_VERSION_ghc(9,0,0)
449449
module GHC.Hs,
450+
module GHC.Hs.Binds,
450451
module GHC.Parser,
451452
module GHC.Parser.Header,
452453
module GHC.Parser.Lexer,
@@ -786,6 +787,7 @@ import qualified Finder as GHC
786787
-- (until the CPP extension is actually needed).
787788
import GHC.LanguageExtensions.Type hiding (Cpp)
788789

790+
import GHC.Hs.Binds
789791

790792
mkHomeModLocation :: DynFlags -> ModuleName -> FilePath -> IO Module.ModLocation
791793
#if MIN_VERSION_ghc(9,3,0)

ghcide/src/Development/IDE/Spans/AtPoint.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ module Development.IDE.Spans.AtPoint (
2020
, getNamesAtPoint
2121
, toCurrentLocation
2222
, rowToLoc
23+
, nameToLocation
24+
, LookupModule
2325
) where
2426

2527
import Development.IDE.GHC.Error

plugins/hls-retrie-plugin/hls-retrie-plugin.cabal

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ library
3131
, ghcide ^>=1.9
3232
, hashable
3333
, hls-plugin-api ^>=1.6
34+
, hls-refactor-plugin
3435
, lsp
3536
, lsp-types
3637
, retrie >=0.1.1.0
@@ -46,3 +47,24 @@ library
4647
TypeOperators
4748

4849
ghc-options: -Wno-unticked-promoted-constructors
50+
51+
test-suite tests
52+
if impl(ghc >= 9.3)
53+
buildable: False
54+
else
55+
buildable: True
56+
type: exitcode-stdio-1.0
57+
default-language: Haskell2010
58+
hs-source-dirs: test
59+
main-is: Main.hs
60+
ghc-options: -threaded -rtsopts -with-rtsopts=-N
61+
build-depends:
62+
, aeson
63+
, base
64+
, containers
65+
, filepath
66+
, hls-plugin-api
67+
, hls-refactor-plugin
68+
, hls-retrie-plugin
69+
, hls-test-utils ^>=1.5
70+
, text

plugins/hls-retrie-plugin/src/Ide/Plugin/Retrie.hs

Lines changed: 393 additions & 136 deletions
Large diffs are not rendered by default.
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
{-# LANGUAGE DisambiguateRecordFields #-}
2+
{-# LANGUAGE NamedFieldPuns #-}
3+
{-# LANGUAGE OverloadedStrings #-}
4+
{-# LANGUAGE PartialTypeSignatures #-}
5+
{-# LANGUAGE TypeOperators #-}
6+
7+
module Main (main) where
8+
9+
import Control.Concurrent (threadDelay)
10+
import Control.Monad (void)
11+
import Data.Aeson
12+
import qualified Data.Map as M
13+
import Data.Text (Text)
14+
import qualified Development.IDE.GHC.ExactPrint
15+
import qualified Development.IDE.Plugin.CodeAction as Refactor
16+
import Ide.Plugin.Config
17+
import qualified Ide.Plugin.Retrie as Retrie
18+
import Ide.Types (IdePlugins (IdePlugins))
19+
import System.FilePath
20+
import Test.Hls
21+
import Test.Hls (PluginTestDescriptor)
22+
23+
main :: IO ()
24+
main = defaultTestRunner tests
25+
26+
retriePlugin :: PluginTestDescriptor a
27+
retriePlugin = mkPluginTestDescriptor' Retrie.descriptor "retrie"
28+
29+
refactorPlugin :: PluginTestDescriptor Development.IDE.GHC.ExactPrint.Log
30+
refactorPlugin = mkPluginTestDescriptor Refactor.iePluginDescriptor "refactor"
31+
32+
tests :: TestTree
33+
tests = testGroup "Retrie"
34+
[ inlineThisTests
35+
]
36+
37+
inlineThisTests :: TestTree
38+
inlineThisTests = testGroup "Inline this"
39+
[
40+
testGroup "provider" [
41+
testProvider "lhs" "Identity" 4 1 ["Unfold function", "Unfold function in current file", "Fold function", "Fold function in current file"],
42+
testProvider "identifier" "Identity" 4 16 ["Inline identity"],
43+
testProvider "imported identifier" "Imported" 4 12 ["Inline identity"],
44+
testProvider "nested where" "NestedWhere" 4 16 ["Inline identity"],
45+
testProvider "nested let" "NestedLet" 6 12 ["Inline identity"],
46+
testProvider "class member" "Class" 5 16 [],
47+
testProvider "operator" "Operator" 4 16 ["Inline */"]
48+
],
49+
testGroup "command" [
50+
testCommand "top level function" "Identity" 4 16,
51+
testCommand "top level function in another file" "Imported" 4 12,
52+
testCommand "nested where function" "NestedWhere" 4 16,
53+
testCommand "nested let function" "NestedLet" 6 12,
54+
testCommand "operator" "Operator" 4 16
55+
]
56+
]
57+
58+
59+
testProvider title file line row expected = testCase title $ runWithRetrie $ do
60+
adoc <- openDoc (file <.> "hs") "haskell"
61+
waitForTypecheck adoc
62+
let position = Position line row
63+
codeActions <- getCodeActions adoc $ Range position position
64+
liftIO $ map codeActionTitle codeActions @?= map Just expected
65+
66+
testCommand :: TestName -> FilePath -> UInt -> UInt -> TestTree
67+
testCommand title file row col = goldenWithRetrie title file $ \adoc -> do
68+
waitForTypecheck adoc
69+
let p = Position row col
70+
codeActions <- getCodeActions adoc $ Range p p
71+
case codeActions of
72+
[InR ca] -> do
73+
executeCodeAction ca
74+
void $ skipManyTill anyMessage $ getDocumentEdit adoc
75+
[] -> error "No code actions found"
76+
77+
codeActionTitle :: (Command |? CodeAction) -> Maybe Text
78+
codeActionTitle (InR CodeAction {_title}) = Just _title
79+
codeActionTitle _ = Nothing
80+
81+
goldenWithRetrie :: TestName -> FilePath -> (TextDocumentIdentifier -> Session ()) -> TestTree
82+
goldenWithRetrie title path act =
83+
goldenWithHaskellDoc testPlugins title testDataDir path "expected" "hs" $ \doc -> do
84+
sendConfigurationChanged $ toJSON $
85+
def { plugins = M.fromList [("retrie", def)] }
86+
act doc
87+
88+
runWithRetrie :: Session a -> IO a
89+
runWithRetrie = runSessionWithServer testPlugins testDataDir
90+
91+
testPlugins :: PluginTestDescriptor _
92+
testPlugins =
93+
retriePlugin <>
94+
refactorPlugin -- needed for the GetAnnotatedParsedSource rule
95+
96+
testDataDir :: FilePath
97+
testDataDir = "test" </> "testdata"
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module Class where
2+
3+
class Identity x where
4+
identity :: x -> x
5+
identity x = x
6+
7+
function x = identity x
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module Identity where
2+
3+
identity x = x
4+
5+
function x = x
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module Identity where
2+
3+
identity x = x
4+
5+
function x = identity x
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module Imported where
2+
3+
import Identity
4+
5+
f x = x
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module Imported where
2+
3+
import Identity
4+
5+
f x = identity x
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module Nested where
2+
3+
4+
5+
function x = x
6+
where
7+
identity x = x
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module NestedLet where
2+
3+
4+
5+
function x =
6+
let identity x = x
7+
in x
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module NestedLet where
2+
3+
4+
5+
function x =
6+
let identity x = x
7+
in identity x
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
module NestedNested where
3+
4+
5+
6+
function x = meme x
7+
where
8+
meme x = identity x
9+
identity x = x
10+
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module NestedWhere where
2+
3+
4+
5+
function x = x
6+
where
7+
identity x = x
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module NestedWhere where
2+
3+
4+
5+
function x = identity x
6+
where
7+
identity x = x
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module Operator where
2+
3+
x */ y = x
4+
5+
function x = x
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module Operator where
2+
3+
x */ y = x
4+
5+
function x = x */ ()
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
cradle:
2+
bios:
3+
shell: |
4+
find . -name "*.hs" > $HIE_BIOS_OUTPUT

src/Ide/Main.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,3 +137,4 @@ runLspMode recorder ghcideArgs@GhcideArguments{..} idePlugins = withTelemetryLog
137137
let defOptions = IDEMain.argsIdeOptions args config sessionLoader
138138
in defOptions { Ghcide.optShakeProfiling = argsShakeProfiling }
139139
}
140+

src/Ide/Version.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
-- and the current project's version
88
module Ide.Version where
99

10+
1011
import Data.Maybe (listToMaybe)
1112
import Data.Version
1213
import GitHash (giCommitCount, tGitInfoCwdTry)

0 commit comments

Comments
 (0)