Skip to content

Commit 32d683c

Browse files
authored
Merge branch 'master' into dependabot/github_actions/haskell-actions/setup-2.11.0
2 parents 1fc4b5b + 2a30435 commit 32d683c

30 files changed

Lines changed: 446 additions & 251 deletions

File tree

bench/config.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,16 +95,22 @@ experiments:
9595
- "edit"
9696
- "hover"
9797
- "semanticTokens"
98+
- "semanticTokens after typing burst"
9899
- "hover after edit"
100+
- "hover after typing burst"
99101
# - "hover after cradle edit"
100102
- "getDefinition"
101103
- "getDefinition after edit"
104+
- "getDefinition after typing burst"
102105
- "completions"
103106
- "completions after edit"
107+
- "completions after typing burst"
104108
- "code actions"
105109
- "code actions after edit"
110+
- "code actions after typing burst"
106111
- "code actions after cradle edit"
107112
- "documentSymbols after edit"
113+
- "documentSymbols after typing burst"
108114
- "hole fit suggestions"
109115
- "eval execute single-line code lens"
110116
- "eval execute multi-line code lens"

ghcide-bench/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ Currently the following experiments are defined:
4747
- *code actions*: makes an edit that breaks typechecking and asks for code actions
4848
- *hole fit suggestions*: measures the performance of hole fits
4949
- *X after edit*: combines the *edit* and X experiments
50+
- *X after typing burst*: makes five hygienic edits with a 250 ms delay between
51+
edits, then waits for the X response
5052
- *X after cradle edit*: combines the X experiments with an edit to the `hie.yaml` file
5153

5254
One can define additional experiments easily, for e.g. formatting, code lenses, renames, etc.

ghcide-bench/src/Experiments.hs

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,12 @@ headerEdit =
8383
, _text = "-- header comment \n"
8484
}
8585

86+
typingBurstEditCount :: Int
87+
typingBurstEditCount = 5
88+
89+
typingBurstDelay :: Seconds
90+
typingBurstDelay = 0.25
91+
8692
data DocumentPositions = DocumentPositions {
8793
-- | A position that can be used to generate non null goto-def and completion responses
8894
identifierP :: Maybe Position,
@@ -100,6 +106,14 @@ allWithIdentifierPos f docs = case applicableDocs of
100106
where
101107
applicableDocs = filter (isJust . identifierP) docs
102108

109+
applyTypingBurst :: [DocumentPositions] -> Session ()
110+
applyTypingBurst docs =
111+
forM_ [1..typingBurstEditCount] $ \n -> do
112+
forM_ docs $ \DocumentPositions{..} ->
113+
changeDoc doc [charEdit stringLiteralP]
114+
when (n < typingBurstEditCount) $
115+
liftIO $ sleep typingBurstDelay
116+
103117
experiments :: HasConfig => [Bench]
104118
experiments =
105119
[
@@ -115,6 +129,15 @@ experiments =
115129
Nothing -> return False
116130
return $ and r,
117131
---------------------------------------------------------------------------------------
132+
bench "semanticTokens after typing burst" $ \docs -> do
133+
applyTypingBurst docs
134+
r <- forM docs $ \DocumentPositions{..} -> do
135+
tks <- getSemanticTokens doc
136+
case tks ^? LSP._L of
137+
Just _ -> return True
138+
Nothing -> return False
139+
return $ and r,
140+
---------------------------------------------------------------------------------------
118141
bench "hover" $ allWithIdentifierPos $ \DocumentPositions{..} ->
119142
isJust <$> getHover doc (fromJust identifierP),
120143
---------------------------------------------------------------------------------------
@@ -124,6 +147,11 @@ experiments =
124147
flip allWithIdentifierPos docs $ \DocumentPositions{..} ->
125148
isJust <$> getHover doc (fromJust identifierP),
126149
---------------------------------------------------------------------------------------
150+
bench "hover after typing burst" $ \docs -> do
151+
applyTypingBurst docs
152+
flip allWithIdentifierPos docs $ \DocumentPositions{..} ->
153+
isJust <$> getHover doc (fromJust identifierP),
154+
---------------------------------------------------------------------------------------
127155
bench
128156
"hover after cradle edit"
129157
(\docs -> do
@@ -158,10 +186,15 @@ experiments =
158186
hasDefinitions <$> getDefinitions doc (fromJust identifierP),
159187
---------------------------------------------------------------------------------------
160188
bench "getDefinition after edit" $ \docs -> do
161-
forM_ docs $ \DocumentPositions{..} ->
162-
changeDoc doc [charEdit stringLiteralP]
163-
flip allWithIdentifierPos docs $ \DocumentPositions{..} ->
164-
hasDefinitions <$> getDefinitions doc (fromJust identifierP),
189+
forM_ docs $ \DocumentPositions{..} ->
190+
changeDoc doc [charEdit stringLiteralP]
191+
flip allWithIdentifierPos docs $ \DocumentPositions{..} ->
192+
hasDefinitions <$> getDefinitions doc (fromJust identifierP),
193+
---------------------------------------------------------------------------------------
194+
bench "getDefinition after typing burst" $ \docs -> do
195+
applyTypingBurst docs
196+
flip allWithIdentifierPos docs $ \DocumentPositions{..} ->
197+
hasDefinitions <$> getDefinitions doc (fromJust identifierP),
165198
---------------------------------------------------------------------------------------
166199
bench "documentSymbols" $ allM $ \DocumentPositions{..} -> do
167200
fmap (either (not . null) (not . null)) . getDocumentSymbols $ doc,
@@ -172,6 +205,11 @@ experiments =
172205
flip allM docs $ \DocumentPositions{..} ->
173206
either (not . null) (not . null) <$> getDocumentSymbols doc,
174207
---------------------------------------------------------------------------------------
208+
bench "documentSymbols after typing burst" $ \docs -> do
209+
applyTypingBurst docs
210+
flip allM docs $ \DocumentPositions{..} ->
211+
either (not . null) (not . null) <$> getDocumentSymbols doc,
212+
---------------------------------------------------------------------------------------
175213
bench "completions" $ \docs -> do
176214
flip allWithIdentifierPos docs $ \DocumentPositions{..} ->
177215
not . null <$> getCompletions doc (fromJust identifierP),
@@ -182,6 +220,11 @@ experiments =
182220
flip allWithIdentifierPos docs $ \DocumentPositions{..} ->
183221
not . null <$> getCompletions doc (fromJust identifierP),
184222
---------------------------------------------------------------------------------------
223+
bench "completions after typing burst" $ \docs -> do
224+
applyTypingBurst docs
225+
flip allWithIdentifierPos docs $ \DocumentPositions{..} ->
226+
not . null <$> getCompletions doc (fromJust identifierP),
227+
---------------------------------------------------------------------------------------
185228
bench
186229
"code actions"
187230
( \docs -> do
@@ -206,6 +249,17 @@ experiments =
206249
getCodeActions doc (Range p p))
207250
),
208251
---------------------------------------------------------------------------------------
252+
bench
253+
"code actions after typing burst"
254+
( \docs -> do
255+
unless (any (isJust . identifierP) docs) $
256+
error "None of the example modules is suitable for this experiment"
257+
applyTypingBurst docs
258+
not . null . catMaybes <$> forM docs (\DocumentPositions{..} -> do
259+
forM identifierP $ \p ->
260+
getCodeActions doc (Range p p))
261+
),
262+
---------------------------------------------------------------------------------------
209263
bench
210264
"code actions after cradle edit"
211265
( \docs -> do
@@ -383,7 +437,7 @@ configP =
383437

384438
packageP = ExamplePackage
385439
<$> strOption (long "example-package-name" <> value "Cabal")
386-
<*> option versionP (long "example-package-version" <> value (makeVersion [3,6,0,0]))
440+
<*> option versionP (long "example-package-version" <> value (makeVersion [3,16,1,0]))
387441
pathOrScriptP = ExamplePath <$> strOption (long "example-path")
388442
<|> ExampleScript <$> strOption (long "example-script") <*> many (strOption (long "example-script-args" <> help "arguments for the example generation script"))
389443

ghcide-bench/test/Main.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ benchmarkTests =
3636
| e <- Bench.experiments
3737
, Bench.name e /= "edit" -- the edit experiment does not ever fail
3838
, Bench.name e /= "hole fit suggestions" -- is too slow!
39+
, not ("semanticTokens" `isInfixOf` Bench.name e) -- ghcide does not load the semantic-tokens plugin
40+
, not ("code actions" `isInfixOf` Bench.name e) -- ghcide does not load the code-action plugin
3941
-- the cradle experiments are way too slow
4042
, not ("cradle" `isInfixOf` Bench.name e)
4143
]

ghcide-test/exe/FindDefinitionAndHoverTests.hs

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import Control.Lens ((^.))
1818
import Development.IDE.Test (expectDiagnostics,
1919
standardizeQuotes)
2020
import Hover
21+
import Ide.Types (Config (..), OptLinkTo (..))
2122
import Test.Hls
2223
import Test.Hls.FileSystem (copyDir)
2324
import Text.Regex.TDFA ((=~))
@@ -104,7 +105,9 @@ tests = let
104105
, ( "GotoHover.hs", [(DiagnosticSeverity_Error, (65, 8), "Found hole: _", Just "GHC-88464")])
105106
]]
106107
, testGroup "type-definition" typeDefinitionTests
107-
, testGroup "hover-record-dot-syntax" recordDotSyntaxTests ]
108+
, testGroup "hover-record-dot-syntax" recordDotSyntaxTests
109+
, testGroup "source-and-doc-links" linkToTests
110+
]
108111

109112
typeDefinitionTests = [ tst (getTypeDefinitions, checkDefs) aaaL14 sourceFilePath (pure tcData) "Saturated data con"
110113
, tst (getTypeDefinitions, checkDefs) aL20 sourceFilePath (pure [ExpectNoDefinitions]) "Polymorphic variable"]
@@ -253,3 +256,63 @@ checkFileCompiles fp diag =
253256
testWithDummyPlugin ("hover: Does " ++ fp ++ " compile") (mkIdeTestFs [copyDir "hover"]) $ do
254257
_ <- openDoc fp "haskell"
255258
diag
259+
260+
linkToTests :: [TestTree]
261+
linkToTests =
262+
[ testGroup "LinkToHackage" linkToHackageTests
263+
, testGroup "LinkToLocal" linkToLocalTests
264+
]
265+
where
266+
linkToHackageTests =
267+
[ testGroup "doc link uses hackage URL"
268+
[ testWithConfig "function" (hoverConfig (def { linkDocTo = LinkToHackage })) $
269+
hoverCheck (Position 24 8) "GotoHover.hs"
270+
[ ExpectHoverTextRegex (hackageUrlRegex "Documentation" "text" "v:pack") ]
271+
, testWithConfig "type" (hoverConfig (def { linkDocTo = LinkToHackage })) $
272+
hoverCheck (Position 8 11) "GotoHover.hs"
273+
[ ExpectHoverTextRegex (hackageUrlRegex "Documentation" "text" "t:Text") ]
274+
]
275+
, testGroup "source link uses hackage URL"
276+
[ testWithConfig "function" (hoverConfig (def { linkSourceTo = LinkToHackage })) $
277+
hoverCheck (Position 24 8) "GotoHover.hs"
278+
[ ExpectHoverTextRegex (hackageUrlRegex "Source" "text" "pack") ]
279+
, testWithConfig "type" (hoverConfig (def { linkSourceTo = LinkToHackage })) $
280+
hoverCheck (Position 8 11) "GotoHover.hs"
281+
[ ExpectHoverTextRegex (hackageUrlRegex "Source" "text" "Text") ]
282+
]
283+
]
284+
linkToLocalTests =
285+
[ testGroup "doc link does not use hackage URL"
286+
[ testWithConfig "function" (hoverConfig (def { linkDocTo = LinkToLocal })) $
287+
hoverCheck (Position 24 8) "GotoHover.hs"
288+
[ ExpectHoverExcludeText [hackageUrlPrefix "Documentation"] ]
289+
, testWithConfig "type" (hoverConfig (def { linkDocTo = LinkToLocal })) $
290+
hoverCheck (Position 8 11) "GotoHover.hs"
291+
[ ExpectHoverExcludeText [hackageUrlPrefix "Documentation"] ]
292+
]
293+
, testGroup "source link does not use hackage URL"
294+
[ testWithConfig "function" (hoverConfig (def { linkSourceTo = LinkToLocal })) $
295+
hoverCheck (Position 24 8) "GotoHover.hs"
296+
[ ExpectHoverExcludeText [hackageUrlPrefix "Source"] ]
297+
, testWithConfig "type" (hoverConfig (def { linkSourceTo = LinkToLocal })) $
298+
hoverCheck (Position 8 11) "GotoHover.hs"
299+
[ ExpectHoverExcludeText [hackageUrlPrefix "Source"] ]
300+
]
301+
]
302+
hackageUrlPrefix linkText = "\\[" <> linkText <> "\\]\\(https://hackage\\.haskell\\.org/package/"
303+
hackageUrlRegex linkText pkg anchor
304+
= hackageUrlPrefix linkText
305+
<> pkg <> "-[0-9\\.]+/docs/[^#)]+\\.html#" <> anchor
306+
hoverConfig lspConf = def
307+
{ testPluginDescriptor = dummyPlugin
308+
, testDirLocation = Right (mkIdeTestFs [copyDir "hover"])
309+
, testConfigCaps = lspTestCaps
310+
, testShiftRoot = True
311+
, testLspConfig = lspConf
312+
}
313+
hoverCheck pos fp expects = do
314+
doc <- openDoc fp "haskell"
315+
waitForProgressDone
316+
_ <- waitForTypecheck doc
317+
hover <- getHover doc pos
318+
checkHover hover expects

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -584,8 +584,11 @@ getDocMapRule recorder =
584584
(tmrTypechecked -> tc, _) <- useWithStale_ TypeCheck file
585585
(hscEnv -> hsc, _) <- useWithStale_ GhcSessionDeps file
586586
(HAR{refMap=rf}, _) <- useWithStale_ GetHieAst file
587-
588-
dkMap <- liftIO $ mkDocMap hsc rf tc
587+
cfg <- getClientConfigAction
588+
dkMap <- liftIO $ mkDocMap hsc rf tc $ LinkTargets
589+
{ linkSource = linkSourceTo cfg
590+
, linkDoc = linkDocTo cfg
591+
}
589592
return ([],Just dkMap)
590593

591594
-- | Persistent rule to ensure that hover doesn't block on startup

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,9 @@ getIdeOptions = do
454454
Just env -> do
455455
config <- liftIO $ LSP.runLspT env HLS.getClientConfig
456456
return x{optCheckProject = pure $ checkProject config,
457-
optCheckParents = pure $ checkParents config
457+
optCheckParents = pure $ checkParents config,
458+
optLinkSourceTo = linkSourceTo config,
459+
optLinkDocTo = linkDocTo config
458460
}
459461

460462
getIdeOptionsIO :: ShakeExtras -> IO IdeOptions

ghcide/src/Development/IDE/GHC/Compat/Core.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ module Development.IDE.GHC.Compat.Core (
334334

335335
module GHC.Tc.Instance.Family,
336336
module GHC.Tc.Module,
337+
module GHC.Tc.TyCl.Class,
337338
module GHC.Tc.Types,
338339
module GHC.Tc.Types.Evidence,
339340
module GHC.Tc.Utils.Env,
@@ -445,6 +446,7 @@ import GHC.Rename.Splice
445446
import qualified GHC.Runtime.Interpreter as GHCi
446447
import GHC.Tc.Instance.Family
447448
import GHC.Tc.Module
449+
import GHC.Tc.TyCl.Class
448450
import GHC.Tc.Types
449451
import GHC.Tc.Types.Evidence hiding ((<.>))
450452
import GHC.Tc.Utils.Env

ghcide/src/Development/IDE/Plugin/Completions.hs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ import Development.IDE.Core.Rules (usePropertyAction)
5656

5757
import qualified Ide.Plugin.Config as Config
5858

59+
import Development.IDE.Types.Options (LinkTargets (..),
60+
linkTargets)
5961
import qualified GHC.LanguageExtensions as LangExt
6062

6163
data Log = LogShake Shake.Log deriving Show
@@ -136,7 +138,9 @@ resolveCompletion ide _pid comp@CompletionItem{_detail,_documentation,_data_} ur
136138
Nothing -> (mempty, mempty)
137139
doc <- case lookupNameEnv dm name of
138140
Just doc -> pure $ spanDocToMarkdown doc
139-
Nothing -> liftIO $ spanDocToMarkdown . fst <$> getDocumentationTryGhc (hscEnv sess) name
141+
Nothing -> liftIO $ do
142+
ltgts <- linkTargets <$> getIdeOptionsIO (shakeExtras ide)
143+
spanDocToMarkdown . fst <$> getDocumentationTryGhc (hscEnv sess) ltgts name
140144
typ <- case lookupNameEnv km name of
141145
_ | not needType -> pure Nothing
142146
Just ty -> pure (safeTyThingType True ty)

0 commit comments

Comments
 (0)