@@ -36,6 +36,7 @@ import Development.IDE.Core.PositionMapping (PositionResult (..),
36
36
positionResultToMaybe ,
37
37
toCurrent )
38
38
import Development.IDE.Core.Shake (Q (.. ))
39
+ import Development.IDE.Main as IDE
39
40
import Development.IDE.GHC.Util
40
41
import Development.IDE.Plugin.Completions.Types (extendImportCommandId )
41
42
import Development.IDE.Plugin.TypeLenses (typeLensCommandId )
@@ -75,7 +76,7 @@ import qualified System.IO.Extra
75
76
import System.Info.Extra (isWindows )
76
77
import System.Process.Extra (CreateProcess (cwd ),
77
78
proc ,
78
- readCreateProcessWithExitCode )
79
+ readCreateProcessWithExitCode , createPipe )
79
80
import Test.QuickCheck
80
81
-- import Test.QuickCheck.Instances ()
81
82
import Control.Lens ((^.) )
@@ -92,6 +93,14 @@ import Test.Tasty.ExpectedFailure
92
93
import Test.Tasty.HUnit
93
94
import Test.Tasty.Ingredients.Rerun
94
95
import Test.Tasty.QuickCheck
96
+ import Data.IORef
97
+ import Ide.PluginUtils (pluginDescToIdePlugins )
98
+ import Control.Concurrent.Async
99
+ import Ide.Types
100
+ import Data.String (IsString (fromString ))
101
+ import qualified Language.LSP.Types as LSP
102
+ import Data.IORef.Extra (atomicModifyIORef_ )
103
+ import qualified Development.IDE.Plugin.HLS.GhcIde as Ghcide
95
104
96
105
waitForProgressBegin :: Session ()
97
106
waitForProgressBegin = skipManyTill anyMessage $ satisfyMaybe $ \ case
@@ -179,7 +188,7 @@ initializeResponseTests = withResource acquire release tests where
179
188
, chk " NO doc link" _documentLinkProvider Nothing
180
189
, chk " NO color" _colorProvider (Just $ InL False )
181
190
, chk " NO folding range" _foldingRangeProvider (Just $ InL False )
182
- , che " execute command" _executeCommandProvider [blockCommandId, extendImportCommandId, typeLensCommandId]
191
+ , che " execute command" _executeCommandProvider [extendImportCommandId, typeLensCommandId, blockCommandId ]
183
192
, chk " workspace" _workspace (Just $ WorkspaceServerCapabilities (Just WorkspaceFoldersServerCapabilities {_supported = Just True , _changeNotifications = Just ( InR True )}))
184
193
, chk " NO experimental" _experimental Nothing
185
194
] where
@@ -5145,21 +5154,26 @@ runInDir' dir startExeIn startSessionIn extraOptions s = do
5145
5154
-- HIE calls getXgdDirectory which assumes that HOME is set.
5146
5155
-- Only sets HOME if it wasn't already set.
5147
5156
setEnv " HOME" " /homeless-shelter" False
5148
- let lspTestCaps = fullCaps { _window = Just $ WindowClientCapabilities $ Just True }
5157
+ conf <- getConfigFromEnv
5158
+ runSessionWithConfig conf cmd lspTestCaps projDir s
5159
+
5160
+ getConfigFromEnv :: IO SessionConfig
5161
+ getConfigFromEnv = do
5149
5162
logColor <- fromMaybe True <$> checkEnv " LSP_TEST_LOG_COLOR"
5150
5163
timeoutOverride <- fmap read <$> getEnv " LSP_TIMEOUT"
5151
- let conf = defaultConfig{messageTimeout = fromMaybe (messageTimeout defaultConfig) timeoutOverride}
5152
- -- uncomment this or set LSP_TEST_LOG_STDERR=1 to see all logging
5153
- -- { logStdErr = True }
5154
- -- uncomment this or set LSP_TEST_LOG_MESSAGES=1 to see all messages
5155
- -- { logMessages = True }
5156
- runSessionWithConfig conf{logColor} cmd lspTestCaps projDir s
5164
+ return defaultConfig
5165
+ { messageTimeout = fromMaybe (messageTimeout defaultConfig) timeoutOverride
5166
+ , logColor
5167
+ }
5157
5168
where
5158
5169
checkEnv :: String -> IO (Maybe Bool )
5159
5170
checkEnv s = fmap convertVal <$> getEnv s
5160
5171
convertVal " 0" = False
5161
5172
convertVal _ = True
5162
5173
5174
+ lspTestCaps :: ClientCapabilities
5175
+ lspTestCaps = fullCaps { _window = Just $ WindowClientCapabilities $ Just True }
5176
+
5163
5177
openTestDataDoc :: FilePath -> Session TextDocumentIdentifier
5164
5178
openTestDataDoc path = do
5165
5179
source <- liftIO $ readFileUtf8 $ " test/data" </> path
@@ -5227,8 +5241,39 @@ unitTests = do
5227
5241
let expected = " 1:2-3:4"
5228
5242
assertBool (unwords [" expected to find range" , expected, " in diagnostic" , shown]) $
5229
5243
expected `isInfixOf` shown
5244
+ , testCase " notification handlers run sequentially" $ do
5245
+ orderRef <- newIORef []
5246
+ let plugins = pluginDescToIdePlugins $
5247
+ [ (defaultPluginDescriptor $ fromString $ show i)
5248
+ { pluginNotificationHandlers = mconcat
5249
+ [ mkPluginNotificationHandler LSP. STextDocumentDidOpen $ \ _ _ _ ->
5250
+ liftIO $ atomicModifyIORef_ orderRef (i: )
5251
+ ]
5252
+ }
5253
+ | i <- [(1 :: Int ).. 20 ]
5254
+ ] ++ Ghcide. descriptors
5255
+
5256
+ testIde def{argsHlsPlugins = plugins} $ do
5257
+ _ <- createDoc " haskell" " A.hs" " module A where"
5258
+ waitForProgressDone
5259
+ actualOrder <- liftIO $ readIORef orderRef
5260
+
5261
+ liftIO $ actualOrder @?= reverse [(1 :: Int ).. 20 ]
5230
5262
]
5231
5263
5264
+ testIde :: Arguments -> Session () -> IO ()
5265
+ testIde arguments session = do
5266
+ config <- getConfigFromEnv
5267
+ (hInRead, hInWrite) <- createPipe
5268
+ (hOutRead, hOutWrite) <- createPipe
5269
+ let server = IDE. defaultMain arguments
5270
+ { argsHandleIn = pure hInRead
5271
+ , argsHandleOut = pure hOutWrite
5272
+ }
5273
+
5274
+ withAsync server $ \ _ ->
5275
+ runSessionWithHandles hInWrite hOutRead config lspTestCaps " ." session
5276
+
5232
5277
positionMappingTests :: TestTree
5233
5278
positionMappingTests =
5234
5279
testGroup " position mapping"
0 commit comments