Skip to content

Commit 507dac7

Browse files
authored
Merge branch 'master' into test-temp-dir
2 parents 0df9923 + 6f6f75b commit 507dac7

File tree

29 files changed

+1007
-177
lines changed

29 files changed

+1007
-177
lines changed

docs/features.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ Completions for language pragmas.
111111
## Formatting
112112

113113
Format your code with various Haskell code formatters.
114+
The default Haskell code formatter is `ormolu`, and the Haskell formatter can be configured via the `formattingProvider` option.
114115

115116
| Formatter | Provided by |
116117
| --------------- | ---------------------------- |
@@ -119,12 +120,17 @@ Format your code with various Haskell code formatters.
119120
| Ormolu | `hls-ormolu-plugin` |
120121
| Stylish Haskell | `hls-stylish-haskell-plugin` |
121122

123+
---
124+
122125
Format your cabal files with a cabal code formatter.
126+
The default cabal code formatter is `cabal-gild`, which needs to be available on the `$PATH`,
127+
or the location needs to be explicitly provided.
128+
To change the cabal formatter, edit the `cabalFormattingProvider` option.
123129

124130
| Formatter | Provided by |
125131
|-----------------|------------------------------|
126132
| cabal-fmt | `hls-cabal-fmt-plugin` |
127-
133+
| cabal-gild | `hls-cabal-gild-plugin` |
128134

129135
## Document symbols
130136

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import Development.IDE.Graph
2929
import Control.Concurrent.STM.Stats (atomically,
3030
modifyTVar')
3131
import Data.Aeson (toJSON)
32+
import qualified Data.Aeson as Aeson
3233
import qualified Data.ByteString as BS
3334
import Data.Maybe (catMaybes)
3435
import Development.IDE.Core.ProgressReporting

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

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,8 @@ module Development.IDE.Core.Shake(
7373
garbageCollectDirtyKeysOlderThan,
7474
Log(..),
7575
VFSModified(..), getClientConfigAction,
76-
ThreadQueue(..)
76+
ThreadQueue(..),
77+
runWithSignal
7778
) where
7879

7980
import Control.Concurrent.Async
@@ -123,6 +124,10 @@ import Development.IDE.Core.FileUtils (getModTime)
123124
import Development.IDE.Core.PositionMapping
124125
import Development.IDE.Core.ProgressReporting
125126
import Development.IDE.Core.RuleTypes
127+
import Development.IDE.Types.Options as Options
128+
import qualified Language.LSP.Protocol.Message as LSP
129+
import qualified Language.LSP.Server as LSP
130+
126131
import Development.IDE.Core.Tracing
127132
import Development.IDE.Core.WorkerThread
128133
import Development.IDE.GHC.Compat (NameCache,
@@ -147,11 +152,11 @@ import qualified Development.IDE.Types.Exports as ExportsMap
147152
import Development.IDE.Types.KnownTargets
148153
import Development.IDE.Types.Location
149154
import Development.IDE.Types.Monitoring (Monitoring (..))
150-
import Development.IDE.Types.Options
151155
import Development.IDE.Types.Shake
152156
import qualified Focus
153157
import GHC.Fingerprint
154158
import GHC.Stack (HasCallStack)
159+
import GHC.TypeLits (KnownSymbol)
155160
import HieDb.Types
156161
import Ide.Logger hiding (Priority)
157162
import qualified Ide.Logger as Logger
@@ -165,7 +170,6 @@ import qualified Language.LSP.Protocol.Lens as L
165170
import Language.LSP.Protocol.Message
166171
import Language.LSP.Protocol.Types
167172
import qualified Language.LSP.Protocol.Types as LSP
168-
import qualified Language.LSP.Server as LSP
169173
import Language.LSP.VFS hiding (start)
170174
import qualified "list-t" ListT
171175
import OpenTelemetry.Eventlog hiding (addEvent)
@@ -1350,29 +1354,28 @@ updateFileDiagnostics recorder fp ver k ShakeExtras{diagnostics, hiddenDiagnosti
13501354
let uri' = filePathToUri' fp
13511355
let delay = if null newDiags then 0.1 else 0
13521356
registerEvent debouncer delay uri' $ withTrace ("report diagnostics " <> fromString (fromNormalizedFilePath fp)) $ \tag -> do
1353-
join $ mask_ $ do
1354-
lastPublish <- atomicallyNamed "diagnostics - publish" $ STM.focus (Focus.lookupWithDefault [] <* Focus.insert newDiags) uri' publishedDiagnostics
1355-
let action = when (lastPublish /= newDiags) $ case lspEnv of
1357+
join $ mask_ $ do
1358+
lastPublish <- atomicallyNamed "diagnostics - publish" $ STM.focus (Focus.lookupWithDefault [] <* Focus.insert newDiags) uri' publishedDiagnostics
1359+
let action = when (lastPublish /= newDiags) $ case lspEnv of
13561360
Nothing -> -- Print an LSP event.
13571361
logWith recorder Info $ LogDiagsDiffButNoLspEnv (map (fp, ShowDiag,) newDiags)
13581362
Just env -> LSP.runLspT env $ do
13591363
liftIO $ tag "count" (show $ Prelude.length newDiags)
13601364
liftIO $ tag "key" (show k)
13611365
LSP.sendNotification SMethod_TextDocumentPublishDiagnostics $
13621366
LSP.PublishDiagnosticsParams (fromNormalizedUri uri') (fmap fromIntegral ver) newDiags
1363-
return action
1367+
return action
13641368
where
13651369
diagsFromRule :: Diagnostic -> Diagnostic
13661370
diagsFromRule c@Diagnostic{_range}
13671371
| coerce ideTesting = c & L.relatedInformation ?~
1368-
[
1369-
DiagnosticRelatedInformation
1372+
[ DiagnosticRelatedInformation
13701373
(Location
13711374
(filePathToUri $ fromNormalizedFilePath fp)
13721375
_range
13731376
)
13741377
(T.pack $ show k)
1375-
]
1378+
]
13761379
| otherwise = c
13771380

13781381

@@ -1444,3 +1447,19 @@ updatePositionMappingHelper ver changes mappingForUri = snd $
14441447
EM.mapAccumRWithKey (\acc _k (delta, _) -> let new = addOldDelta delta acc in (new, (delta, acc)))
14451448
zeroMapping
14461449
(EM.insert ver (mkDelta changes, zeroMapping) mappingForUri)
1450+
1451+
-- | sends a signal whenever shake session is run/restarted
1452+
-- being used in cabal and hlint plugin tests to know when its time
1453+
-- to look for file diagnostics
1454+
kickSignal :: KnownSymbol s => Bool -> Maybe (LSP.LanguageContextEnv c) -> [NormalizedFilePath] -> Proxy s -> Action ()
1455+
kickSignal testing lspEnv files msg = when testing $ liftIO $ mRunLspT lspEnv $
1456+
LSP.sendNotification (LSP.SMethod_CustomMethod msg) $
1457+
toJSON $ map fromNormalizedFilePath files
1458+
1459+
-- | Add kick start/done signal to rule
1460+
runWithSignal :: (KnownSymbol s0, KnownSymbol s1, IdeRule k v) => Proxy s0 -> Proxy s1 -> [NormalizedFilePath] -> k -> Action ()
1461+
runWithSignal msgStart msgEnd files rule = do
1462+
ShakeExtras{ideTesting = Options.IdeTesting testing, lspEnv} <- getShakeExtras
1463+
kickSignal testing lspEnv files msgStart
1464+
void $ uses rule files
1465+
kickSignal testing lspEnv files msgEnd

haskell-language-server.cabal

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,8 +242,10 @@ library hls-cabal-plugin
242242
Ide.Plugin.Cabal.Completion.Completions
243243
Ide.Plugin.Cabal.Completion.Data
244244
Ide.Plugin.Cabal.Completion.Types
245+
Ide.Plugin.Cabal.FieldSuggest
245246
Ide.Plugin.Cabal.LicenseSuggest
246247
Ide.Plugin.Cabal.Orphans
248+
Ide.Plugin.Cabal.Outline
247249
Ide.Plugin.Cabal.Parse
248250

249251

@@ -281,10 +283,12 @@ test-suite hls-cabal-plugin-tests
281283
Completer
282284
Context
283285
Utils
286+
Outline
284287
build-depends:
285288
, base
286289
, bytestring
287290
, Cabal-syntax >= 3.7
291+
, extra
288292
, filepath
289293
, ghcide
290294
, haskell-language-server:hls-cabal-plugin
@@ -712,7 +716,6 @@ library hls-hlint-plugin
712716
, hlint >= 3.5 && < 3.9
713717
, hls-plugin-api == 2.9.0.1
714718
, lens
715-
, lsp
716719
, mtl
717720
, refact
718721
, regex-tdfa
@@ -723,6 +726,8 @@ library hls-hlint-plugin
723726
, unordered-containers
724727
, ghc-lib-parser-ex
725728
, apply-refact
729+
--
730+
, lsp-types
726731

727732
if flag(ghc-lib)
728733
cpp-options: -DGHC_LIB

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

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,17 @@ module Test.Hls
6161
WithPriority(..),
6262
Recorder,
6363
Priority(..),
64-
TestConfig(..),
64+
captureKickDiagnostics,
65+
kick,
66+
TestConfig(..)
6567
)
6668
where
6769

6870
import Control.Applicative.Combinators
6971
import Control.Concurrent.Async (async, cancel, wait)
7072
import Control.Concurrent.Extra
7173
import Control.Exception.Safe
74+
import Control.Lens ((^.))
7275
import Control.Lens.Extras (is)
7376
import Control.Monad (guard, unless, void)
7477
import Control.Monad.Extra (forM)
@@ -80,7 +83,7 @@ import qualified Data.Aeson as A
8083
import Data.ByteString.Lazy (ByteString)
8184
import Data.Default (Default, def)
8285
import qualified Data.Map as M
83-
import Data.Maybe (fromMaybe)
86+
import Data.Maybe (fromMaybe, mapMaybe)
8487
import Data.Proxy (Proxy (Proxy))
8588
import qualified Data.Text as T
8689
import qualified Data.Text.Lazy as TL
@@ -114,6 +117,7 @@ import Ide.PluginUtils (idePluginsToPluginDes
114117
pluginDescToIdePlugins)
115118
import Ide.Types
116119
import Language.LSP.Protocol.Capabilities
120+
import qualified Language.LSP.Protocol.Lens as L
117121
import Language.LSP.Protocol.Message
118122
import qualified Language.LSP.Protocol.Message as LSP
119123
import Language.LSP.Protocol.Types hiding (Null)
@@ -232,14 +236,14 @@ goldenWithTestConfig
232236
:: Pretty b
233237
=> TestConfig b
234238
-> TestName
235-
-> FilePath
239+
-> VirtualFileTree
236240
-> FilePath
237241
-> FilePath
238242
-> FilePath
239243
-> (TextDocumentIdentifier -> Session ())
240244
-> TestTree
241-
goldenWithTestConfig config title testDataDir path desc ext act =
242-
goldenGitDiff title (testDataDir </> path <.> desc <.> ext)
245+
goldenWithTestConfig config title tree path desc ext act =
246+
goldenGitDiff title (vftOriginalRoot tree </> path <.> desc <.> ext)
243247
$ runSessionWithTestConfig config $ const
244248
$ TL.encodeUtf8 . TL.fromStrict
245249
<$> do
@@ -870,6 +874,17 @@ setHlsConfig config = do
870874
-- requests!
871875
skipManyTill anyMessage (void configurationRequest)
872876

877+
captureKickDiagnostics :: Session () -> Session () -> Session [Diagnostic]
878+
captureKickDiagnostics start done = do
879+
_ <- skipManyTill anyMessage start
880+
messages <- manyTill anyMessage done
881+
pure $ concat $ mapMaybe diagnostics messages
882+
where
883+
diagnostics :: FromServerMessage' a -> Maybe [Diagnostic]
884+
diagnostics = \msg -> case msg of
885+
FromServerMess SMethod_TextDocumentPublishDiagnostics diags -> Just (diags ^. L.params . L.diagnostics)
886+
_ -> Nothing
887+
873888
waitForKickDone :: Session ()
874889
waitForKickDone = void $ skipManyTill anyMessage nonTrivialKickDone
875890

@@ -882,9 +897,11 @@ nonTrivialKickDone = kick (Proxy @"kick/done") >>= guard . not . null
882897
nonTrivialKickStart :: Session ()
883898
nonTrivialKickStart = kick (Proxy @"kick/start") >>= guard . not . null
884899

900+
885901
kick :: KnownSymbol k => Proxy k -> Session [FilePath]
886902
kick proxyMsg = do
887903
NotMess TNotificationMessage{_params} <- customNotification proxyMsg
888904
case fromJSON _params of
889905
Success x -> return x
890906
other -> error $ "Failed to parse kick/done details: " <> show other
907+

0 commit comments

Comments
 (0)