1
1
{-# LANGUAGE DisambiguateRecordFields #-}
2
+ {-# LANGUAGE LambdaCase #-}
2
3
{-# LANGUAGE NamedFieldPuns #-}
4
+ {-# LANGUAGE OverloadedLabels #-}
3
5
{-# LANGUAGE OverloadedStrings #-}
4
6
{-# LANGUAGE TypeOperators #-}
5
7
{-# LANGUAGE ViewPatterns #-}
6
-
7
8
module Main
8
9
( main
9
10
) where
10
11
11
- import Data.Foldable (find , forM_ )
12
+ import Control.Lens ((^.) )
13
+ import Data.Either.Extra
14
+ import Data.Foldable (find )
15
+ import Data.Row ((.+) , (.==) )
12
16
import Data.Text (Text )
13
17
import qualified Data.Text as T
14
18
import qualified Ide.Plugin.ExplicitImports as ExplicitImports
19
+ import qualified Language.LSP.Protocol.Lens as L
15
20
import Language.LSP.Protocol.Message
16
- import System.FilePath ((<.>) , (< />) )
21
+ import System.FilePath ((</>) )
17
22
import Test.Hls
18
23
19
24
explicitImportsPlugin :: PluginTestDescriptor ExplicitImports. Log
20
25
explicitImportsPlugin = mkPluginTestDescriptor ExplicitImports. descriptor " explicitImports"
21
26
22
- longModule :: T. Text
23
- longModule = " F" <> T. replicate 80 " o"
24
-
25
27
main :: IO ()
26
28
main = defaultTestRunner $
27
29
testGroup
28
30
" Make imports explicit"
29
- [ codeActionGoldenTest " UsualCase" 3 0
31
+ [ codeActionAllGoldenTest " UsualCase" 3 0
32
+ , codeActionAllResolveGoldenTest " UsualCase" 3 0
33
+ , codeActionOnlyGoldenTest " OnlyThis" 3 0
34
+ , codeActionOnlyResolveGoldenTest " OnlyThis" 3 0
30
35
, codeLensGoldenTest " UsualCase" 0
36
+ , codeActionBreakFile " BreakFile" 4 0
37
+ , codeActionStaleAction " StaleAction" 4 0
31
38
, testCase " No CodeAction when exported" $
32
39
runSessionWithServer explicitImportsPlugin testDataDir $ do
33
40
doc <- openDoc " Exported.hs" " haskell"
@@ -65,12 +72,74 @@ main = defaultTestRunner $
65
72
66
73
-- code action tests
67
74
68
- codeActionGoldenTest :: FilePath -> Int -> Int -> TestTree
69
- codeActionGoldenTest fp l c = goldenWithExplicitImports fp $ \ doc -> do
75
+ codeActionAllGoldenTest :: FilePath -> Int -> Int -> TestTree
76
+ codeActionAllGoldenTest fp l c = goldenWithExplicitImports " code action" fp codeActionNoResolveCaps $ \ doc -> do
77
+ actions <- getCodeActions doc (pointRange l c)
78
+ case find ((== Just " Make all imports explicit" ) . caTitle) actions of
79
+ Just (InR x) -> executeCodeAction x
80
+ _ -> liftIO $ assertFailure " Unable to find CodeAction"
81
+
82
+ codeActionBreakFile :: FilePath -> Int -> Int -> TestTree
83
+ codeActionBreakFile fp l c = goldenWithExplicitImports " code action" fp codeActionNoResolveCaps $ \ doc -> do
84
+ _ <- waitForDiagnostics
85
+ changeDoc doc [edit]
70
86
actions <- getCodeActions doc (pointRange l c)
71
87
case find ((== Just " Make all imports explicit" ) . caTitle) actions of
72
88
Just (InR x) -> executeCodeAction x
73
89
_ -> liftIO $ assertFailure " Unable to find CodeAction"
90
+ where edit = TextDocumentContentChangeEvent $ InL $ # range .== pointRange 2 21
91
+ .+ # rangeLength .== Nothing
92
+ .+ # text .== " x"
93
+
94
+ codeActionStaleAction :: FilePath -> Int -> Int -> TestTree
95
+ codeActionStaleAction fp l c = goldenWithExplicitImports " code action" fp codeActionResolveCaps $ \ doc -> do
96
+ _ <- waitForDiagnostics
97
+ actions <- getCodeActions doc (pointRange l c)
98
+ changeDoc doc [edit]
99
+ _ <- waitForDiagnostics
100
+ case find ((== Just " Make this import explicit" ) . caTitle) actions of
101
+ Just (InR x) ->
102
+ maybeResolveCodeAction x >>=
103
+ \ case Just _ -> liftIO $ assertFailure " Code action still valid"
104
+ Nothing -> pure ()
105
+ _ -> liftIO $ assertFailure " Unable to find CodeAction"
106
+ where edit = TextDocumentContentChangeEvent $ InL $ # range .== Range (Position 6 0 ) (Position 6 0 )
107
+ .+ # rangeLength .== Nothing
108
+ .+ # text .== " \n testing = undefined"
109
+
110
+ codeActionAllResolveGoldenTest :: FilePath -> Int -> Int -> TestTree
111
+ codeActionAllResolveGoldenTest fp l c = goldenWithExplicitImports " code action resolve" fp codeActionResolveCaps $ \ doc -> do
112
+ actions <- getCodeActions doc (pointRange l c)
113
+ Just (InR x) <- pure $ find ((== Just " Make all imports explicit" ) . caTitle) actions
114
+ resolved <- resolveCodeAction x
115
+ executeCodeAction resolved
116
+
117
+ codeActionOnlyGoldenTest :: FilePath -> Int -> Int -> TestTree
118
+ codeActionOnlyGoldenTest fp l c = goldenWithExplicitImports " code action" fp codeActionNoResolveCaps $ \ doc -> do
119
+ actions <- getCodeActions doc (pointRange l c)
120
+ case find ((== Just " Make this import explicit" ) . caTitle) actions of
121
+ Just (InR x) -> executeCodeAction x
122
+ _ -> liftIO $ assertFailure " Unable to find CodeAction"
123
+
124
+ codeActionOnlyResolveGoldenTest :: FilePath -> Int -> Int -> TestTree
125
+ codeActionOnlyResolveGoldenTest fp l c = goldenWithExplicitImports " code action resolve" fp codeActionResolveCaps $ \ doc -> do
126
+ actions <- getCodeActions doc (pointRange l c)
127
+ Just (InR x) <- pure $ find ((== Just " Make this import explicit" ) . caTitle) actions
128
+ resolved <- resolveCodeAction x
129
+ executeCodeAction resolved
130
+
131
+ -- TODO: use the one from lsp-test once that's released
132
+ resolveCodeAction :: CodeAction -> Session CodeAction
133
+ resolveCodeAction ca = do
134
+ resolveResponse <- request SMethod_CodeActionResolve ca
135
+ Right resolved <- pure $ resolveResponse ^. L. result
136
+ pure resolved
137
+
138
+ maybeResolveCodeAction :: CodeAction -> Session (Maybe CodeAction )
139
+ maybeResolveCodeAction ca = do
140
+ resolveResponse <- request SMethod_CodeActionResolve ca
141
+ let resolved = resolveResponse ^. L. result
142
+ pure $ eitherToMaybe resolved
74
143
75
144
caTitle :: (Command |? CodeAction ) -> Maybe Text
76
145
caTitle (InR CodeAction {_title}) = Just _title
@@ -79,18 +148,17 @@ caTitle _ = Nothing
79
148
-- code lens tests
80
149
81
150
codeLensGoldenTest :: FilePath -> Int -> TestTree
82
- codeLensGoldenTest fp codeLensIdx = goldenWithExplicitImports fp $ \ doc -> do
83
- codeLens <- (!! codeLensIdx) <$> getCodeLensesBy isExplicitImports doc
84
- mapM_ executeCmd
85
- [c | CodeLens {_command = Just c} <- [codeLens]]
86
-
87
- getCodeLensesBy :: (CodeLens -> Bool ) -> TextDocumentIdentifier -> Session [CodeLens ]
88
- getCodeLensesBy f doc = filter f <$> getCodeLenses doc
89
-
90
- isExplicitImports :: CodeLens -> Bool
91
- isExplicitImports (CodeLens _ (Just (Command _ cmd _)) _)
92
- | " :explicitImports:" `T.isInfixOf` cmd = True
93
- isExplicitImports _ = False
151
+ codeLensGoldenTest fp _ = goldenWithExplicitImports " code lens" fp codeActionNoResolveCaps $ \ doc -> do
152
+ (codeLens: _) <- getCodeLenses doc
153
+ CodeLens {_command = Just c} <- resolveCodeLens codeLens
154
+ executeCmd c
155
+
156
+ -- TODO: use the one from lsp-test once that's released
157
+ resolveCodeLens :: CodeLens -> Session CodeLens
158
+ resolveCodeLens cl = do
159
+ resolveResponse <- request SMethod_CodeLensResolve cl
160
+ Right resolved <- pure $ resolveResponse ^. L. result
161
+ pure resolved
94
162
95
163
-- Execute command and wait for result
96
164
executeCmd :: Command -> Session ()
@@ -102,8 +170,8 @@ executeCmd cmd = do
102
170
103
171
-- helpers
104
172
105
- goldenWithExplicitImports :: FilePath -> (TextDocumentIdentifier -> Session () ) -> TestTree
106
- goldenWithExplicitImports fp = goldenWithHaskellDoc explicitImportsPlugin (fp <> " (golden)" ) testDataDir fp " expected" " hs"
173
+ goldenWithExplicitImports :: String -> FilePath -> ClientCapabilities -> (TextDocumentIdentifier -> Session () ) -> TestTree
174
+ goldenWithExplicitImports title fp caps = goldenWithHaskellAndCaps caps explicitImportsPlugin (fp <> title <> " (golden)" ) testDataDir fp " expected" " hs"
107
175
108
176
testDataDir :: String
109
177
testDataDir = " test" </> " testdata"
0 commit comments