Skip to content

Commit c6d45c4

Browse files
committed
WIP: Speed up hls-hlint-plugin-tests
Move test data to temporary directory. Avoid `waitForDiagnosticsWithSource` as it unconditionally waits for diagnostics.
1 parent b2b41df commit c6d45c4

File tree

6 files changed

+229
-77
lines changed

6 files changed

+229
-77
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ import Ide.Logger (Pretty (pretty),
4848
logDebug)
4949
import qualified Language.LSP.Protocol.Message as LSP
5050
import qualified Language.LSP.Server as LSP
51+
import qualified Data.Aeson as Aeson
5152

5253
data Log = LogShake Shake.Log
5354
deriving Show

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

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1281,29 +1281,28 @@ updateFileDiagnostics recorder fp ver k ShakeExtras{diagnostics, hiddenDiagnosti
12811281
let uri' = filePathToUri' fp
12821282
let delay = if null newDiags then 0.1 else 0
12831283
registerEvent debouncer delay uri' $ withTrace ("report diagnostics " <> fromString (fromNormalizedFilePath fp)) $ \tag -> do
1284-
join $ mask_ $ do
1285-
lastPublish <- atomicallyNamed "diagnostics - publish" $ STM.focus (Focus.lookupWithDefault [] <* Focus.insert newDiags) uri' publishedDiagnostics
1286-
let action = when (lastPublish /= newDiags) $ case lspEnv of
1284+
join $ mask_ $ do
1285+
lastPublish <- atomicallyNamed "diagnostics - publish" $ STM.focus (Focus.lookupWithDefault [] <* Focus.insert newDiags) uri' publishedDiagnostics
1286+
let action = when (lastPublish /= newDiags) $ case lspEnv of
12871287
Nothing -> -- Print an LSP event.
12881288
logWith recorder Info $ LogDiagsDiffButNoLspEnv (map (fp, ShowDiag,) newDiags)
12891289
Just env -> LSP.runLspT env $ do
12901290
liftIO $ tag "count" (show $ Prelude.length newDiags)
12911291
liftIO $ tag "key" (show k)
12921292
LSP.sendNotification SMethod_TextDocumentPublishDiagnostics $
12931293
LSP.PublishDiagnosticsParams (fromNormalizedUri uri') (fmap fromIntegral ver) newDiags
1294-
return action
1294+
return action
12951295
where
12961296
diagsFromRule :: Diagnostic -> Diagnostic
12971297
diagsFromRule c@Diagnostic{_range}
12981298
| coerce ideTesting = c & L.relatedInformation ?~
1299-
[
1300-
DiagnosticRelatedInformation
1299+
[ DiagnosticRelatedInformation
13011300
(Location
13021301
(filePathToUri $ fromNormalizedFilePath fp)
13031302
_range
13041303
)
13051304
(T.pack $ show k)
1306-
]
1305+
]
13071306
| otherwise = c
13081307

13091308

haskell-language-server.cabal

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -691,6 +691,8 @@ library hls-hlint-plugin
691691
, unordered-containers
692692
, ghc-lib-parser-ex
693693
, apply-refact
694+
--
695+
, lsp-types
694696

695697
if flag(ghc-lib)
696698
cpp-options: -DGHC_LIB

hls-test-utils/src/Test/Hls.hs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
{-# LANGUAGE LambdaCase #-}
55
{-# LANGUAGE OverloadedLists #-}
66
{-# LANGUAGE OverloadedStrings #-}
7+
{-# LANGUAGE OverloadedStrings #-}
78
module Test.Hls
89
( module Test.Tasty.HUnit,
910
module Test.Tasty,
@@ -57,6 +58,7 @@ module Test.Hls
5758
WithPriority(..),
5859
Recorder,
5960
Priority(..),
61+
captureKickDiagnostics,
6062
)
6163
where
6264

@@ -124,6 +126,9 @@ import Test.Tasty.ExpectedFailure
124126
import Test.Tasty.Golden
125127
import Test.Tasty.HUnit
126128
import Test.Tasty.Ingredients.Rerun
129+
import Language.LSP.Protocol.Lens qualified as L
130+
import Data.Maybe (mapMaybe)
131+
import Control.Lens ((^.))
127132

128133
data Log
129134
= LogIDEMain IDEMain.Log
@@ -712,6 +717,17 @@ setHlsConfig config = do
712717
-- requests!
713718
skipManyTill anyMessage (void configurationRequest)
714719

720+
captureKickDiagnostics :: Session [Diagnostic]
721+
captureKickDiagnostics = do
722+
_ <- skipManyTill anyMessage nonTrivialKickStart2
723+
messages <- manyTill anyMessage nonTrivialKickDone2
724+
pure $ concat $ mapMaybe diagnostics messages
725+
where
726+
diagnostics :: FromServerMessage' a -> Maybe [Diagnostic]
727+
diagnostics = \msg -> case msg of
728+
FromServerMess SMethod_TextDocumentPublishDiagnostics diags -> Just (diags ^. L.params . L.diagnostics)
729+
_ -> Nothing
730+
715731
waitForKickDone :: Session ()
716732
waitForKickDone = void $ skipManyTill anyMessage nonTrivialKickDone
717733

@@ -724,9 +740,17 @@ nonTrivialKickDone = kick (Proxy @"kick/done") >>= guard . not . null
724740
nonTrivialKickStart :: Session ()
725741
nonTrivialKickStart = kick (Proxy @"kick/start") >>= guard . not . null
726742

743+
nonTrivialKickDone2 :: Session ()
744+
nonTrivialKickDone2 = kick (Proxy @"kick/done/hlint") >>= guard . not . null
745+
746+
nonTrivialKickStart2 :: Session ()
747+
nonTrivialKickStart2 = kick (Proxy @"kick/start/hlint") >>= guard . not . null
748+
749+
727750
kick :: KnownSymbol k => Proxy k -> Session [FilePath]
728751
kick proxyMsg = do
729752
NotMess TNotificationMessage{_params} <- customNotification proxyMsg
730753
case fromJSON _params of
731754
Success x -> return x
732755
other -> error $ "Failed to parse kick/done details: " <> show other
756+

plugins/hls-hlint-plugin/src/Ide/Plugin/Hlint.hs

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,11 @@ import System.Environment (setEnv,
125125
#endif
126126
import Development.IDE.Core.PluginUtils as PluginUtils
127127
import Text.Regex.TDFA.Text ()
128+
import qualified Language.LSP.Protocol.Message as LSP
129+
import qualified Language.LSP.Server as LSP
130+
import GHC.TypeLits (KnownSymbol)
131+
import qualified Development.IDE.Types.Options as Options
132+
128133
-- ---------------------------------------------------------------------
129134

130135
data Log
@@ -140,7 +145,7 @@ instance Pretty Log where
140145
LogShake log -> pretty log
141146
LogApplying fp res -> "Applying hint(s) for" <+> viaShow fp <> ":" <+> viaShow res
142147
LogGeneratedIdeas fp ideas -> "Generated hlint ideas for for" <+> viaShow fp <> ":" <+> viaShow ideas
143-
LogUsingExtensions fp exts -> "Using extensions for " <+> viaShow fp <> ":" <+> pretty exts
148+
LogUsingExtensions fp exts -> "Using extensions for " <+> viaShow fp <> ":" <> line <> indent 4 (pretty exts)
144149
LogGetIdeas fp -> "Getting hlint ideas for " <+> viaShow fp
145150
LogResolve msg -> pretty msg
146151

@@ -189,12 +194,12 @@ instance NFData GetHlintDiagnostics
189194
type instance RuleResult GetHlintDiagnostics = ()
190195

191196
-- | Hlint rules to generate file diagnostics based on hlint hints
192-
-- | This rule is recomputed when:
193-
-- | - A file has been edited via
194-
-- | - `getIdeas` -> `getParsedModule` in any case
195-
-- | - `getIdeas` -> `getFileContents` if the hls ghc does not match the hlint default ghc
196-
-- | - The client settings have changed, to honour the `hlintOn` setting, via `getClientConfigAction`
197-
-- | - The hlint specific settings have changed, via `getHlintSettingsRule`
197+
-- This rule is recomputed when:
198+
-- - A file has been edited via
199+
-- - `getIdeas` -> `getParsedModule` in any case
200+
-- - `getIdeas` -> `getFileContents` if the hls ghc does not match the hlint default ghc
201+
-- - The client settings have changed, to honour the `hlintOn` setting, via `getClientConfigAction`
202+
-- - The hlint specific settings have changed, via `getHlintSettingsRule`
198203
rules :: Recorder (WithPriority Log) -> PluginId -> Rules ()
199204
rules recorder plugin = do
200205
define (cmapWithPrio LogShake recorder) $ \GetHlintDiagnostics file -> do
@@ -208,8 +213,16 @@ rules recorder plugin = do
208213
liftIO $ argsSettings flags
209214

210215
action $ do
211-
files <- getFilesOfInterestUntracked
212-
void $ uses GetHlintDiagnostics $ Map.keys files
216+
files <- Map.keys <$> getFilesOfInterestUntracked
217+
Shake.ShakeExtras{ideTesting = Options.IdeTesting testing, lspEnv} <- Shake.getShakeExtras
218+
let signal :: KnownSymbol s => Proxy s -> Action ()
219+
signal msg = when testing $ liftIO $ Shake.mRunLspT lspEnv $
220+
LSP.sendNotification (LSP.SMethod_CustomMethod msg) $
221+
toJSON $ map fromNormalizedFilePath files
222+
223+
signal (Proxy @"kick/start/hlint")
224+
void $ uses GetHlintDiagnostics files
225+
signal (Proxy @"kick/done/hlint")
213226

214227
where
215228

0 commit comments

Comments
 (0)