Skip to content

Commit 6d5f4af

Browse files
committed
Merge remote-tracking branch 'upstream/master' into inlay-hints-local-binding
2 parents 20e1274 + 2253752 commit 6d5f4af

File tree

45 files changed

+1406
-102
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1406
-102
lines changed

.github/actions/setup-build/action.yml

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ runs:
3131
sudo chown -R $USER /usr/local/.ghcup
3232
shell: bash
3333

34-
- uses: haskell-actions/[email protected].5
34+
- uses: haskell-actions/[email protected].6
3535
id: HaskEnvSetup
3636
with:
3737
ghc-version : ${{ inputs.ghc }}
@@ -116,3 +116,18 @@ runs:
116116
- name: "Remove freeze file"
117117
run: rm -f cabal.project.freeze
118118
shell: bash
119+
120+
# Make sure to clear all unneeded `ghcup`` caches.
121+
# At some point, we were running out of disk space, see issue
122+
# https://github.com/haskell/haskell-language-server/issues/4386 for details.
123+
#
124+
# Using "printf" debugging (`du -sh *` and `df -h /`) and binary searching,
125+
# we figured out that `ghcup` caches are taking up a sizable portion of the
126+
# disk space.
127+
# Thus, we remove anything we don't need, especially caches and temporary files.
128+
# For got measure, we also make sure no other tooling versions are
129+
# installed besides the ones we explicitly want.
130+
- name: "Remove ghcup caches"
131+
if: runner.os == 'Linux'
132+
run: ghcup gc --ghc-old --share-dir --hls-no-ghc --cache --tmpdirs --unset
133+
shell: bash

.github/workflows/bench.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ jobs:
127127
example: ['cabal', 'lsp-types']
128128

129129
steps:
130-
- uses: haskell-actions/[email protected].3
130+
- uses: haskell-actions/[email protected].6
131131
with:
132132
ghc-version : ${{ matrix.ghc }}
133133
cabal-version: ${{ matrix.cabal }}

cabal.project

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ packages:
77
./hls-plugin-api
88
./hls-test-utils
99

10+
-- Only keep this until https://github.com/Bodigrim/cabal-add/issues/7
11+
-- is resolved
12+
source-repository-package
13+
type: git
14+
location: https://github.com/Bodigrim/cabal-add.git
15+
tag: 8c004e2a4329232f9824425f5472b2d6d7958bbd
16+
1017
index-state: 2024-06-29T00:00:00Z
1118

1219
tests: True

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

exe/Wrapper.hs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ module Main where
99

1010
import Control.Monad.Extra
1111
import Data.Default
12-
import Data.Either.Extra (eitherToMaybe)
1312
import Data.Foldable
1413
import Data.List
1514
import Data.List.Extra (trimEnd)
@@ -76,8 +75,11 @@ main = do
7675
putStrLn $ showProgramVersionOfInterest programsOfInterest
7776
putStrLn "Tool versions in your project"
7877
cradle <- findProjectCradle' recorder False
79-
ghcVersion <- runExceptT $ getRuntimeGhcVersion' cradle
80-
putStrLn $ showProgramVersion "ghc" $ mkVersion =<< eitherToMaybe ghcVersion
78+
runExceptT (getRuntimeGhcVersion' cradle) >>= \case
79+
Left err ->
80+
T.hPutStrLn stderr (prettyError err NoShorten)
81+
Right ghcVersion ->
82+
putStrLn $ showProgramVersion "ghc" $ mkVersion ghcVersion
8183

8284
VersionMode PrintVersion ->
8385
putStrLn hlsVer

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: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,9 @@ library hls-cabal-plugin
244244
Ide.Plugin.Cabal.Completion.Types
245245
Ide.Plugin.Cabal.FieldSuggest
246246
Ide.Plugin.Cabal.LicenseSuggest
247+
Ide.Plugin.Cabal.CabalAdd
247248
Ide.Plugin.Cabal.Orphans
249+
Ide.Plugin.Cabal.Outline
248250
Ide.Plugin.Cabal.Parse
249251

250252

@@ -269,6 +271,12 @@ library hls-cabal-plugin
269271
, transformers
270272
, unordered-containers >=0.2.10.0
271273
, containers
274+
, cabal-add
275+
, process
276+
, aeson
277+
, Cabal
278+
, pretty
279+
272280
hs-source-dirs: plugins/hls-cabal-plugin/src
273281

274282
test-suite hls-cabal-plugin-tests
@@ -282,6 +290,8 @@ test-suite hls-cabal-plugin-tests
282290
Completer
283291
Context
284292
Utils
293+
Outline
294+
CabalAdd
285295
build-depends:
286296
, base
287297
, bytestring
@@ -294,6 +304,7 @@ test-suite hls-cabal-plugin-tests
294304
, lens
295305
, lsp-types
296306
, text
307+
, hls-plugin-api
297308

298309
-----------------------------
299310
-- class plugin
@@ -714,7 +725,6 @@ library hls-hlint-plugin
714725
, hlint >= 3.5 && < 3.9
715726
, hls-plugin-api == 2.9.0.1
716727
, lens
717-
, lsp
718728
, mtl
719729
, refact
720730
, regex-tdfa
@@ -725,6 +735,8 @@ library hls-hlint-plugin
725735
, unordered-containers
726736
, ghc-lib-parser-ex
727737
, apply-refact
738+
--
739+
, lsp-types
728740

729741
if flag(ghc-lib)
730742
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)
@@ -231,14 +235,14 @@ goldenWithTestConfig
231235
:: Pretty b
232236
=> TestConfig b
233237
-> TestName
234-
-> FilePath
238+
-> VirtualFileTree
235239
-> FilePath
236240
-> FilePath
237241
-> FilePath
238242
-> (TextDocumentIdentifier -> Session ())
239243
-> TestTree
240-
goldenWithTestConfig config title testDataDir path desc ext act =
241-
goldenGitDiff title (testDataDir </> path <.> desc <.> ext)
244+
goldenWithTestConfig config title tree path desc ext act =
245+
goldenGitDiff title (vftOriginalRoot tree </> path <.> desc <.> ext)
242246
$ runSessionWithTestConfig config $ const
243247
$ TL.encodeUtf8 . TL.fromStrict
244248
<$> do
@@ -869,6 +873,17 @@ setHlsConfig config = do
869873
-- requests!
870874
skipManyTill anyMessage (void configurationRequest)
871875

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

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

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

0 commit comments

Comments
 (0)