1
+ {-# LANGUAGE TypeApplications #-}
2
+ {-# LANGUAGE ViewPatterns #-}
1
3
{-# LANGUAGE LambdaCase #-}
2
4
{-# LANGUAGE DeriveAnyClass #-}
3
5
{-# LANGUAGE DeriveGeneric #-}
@@ -24,11 +26,11 @@ module Ide.Plugin.Eval.CodeLens (
24
26
) where
25
27
26
28
import Control.Applicative (Alternative ((<|>) ))
27
- import Control.Arrow (second )
29
+ import Control.Arrow (second , (>>>) )
28
30
import qualified Control.Exception as E
29
31
import Control.Monad
30
32
( void ,
31
- when ,
33
+ when , guard
32
34
)
33
35
import Control.Monad.IO.Class (MonadIO (liftIO ))
34
36
import Control.Monad.Trans.Except
@@ -44,7 +46,7 @@ import Data.Either (isRight)
44
46
import qualified Data.HashMap.Strict as HashMap
45
47
import Data.List
46
48
(dropWhileEnd ,
47
- find
49
+ find , intercalate
48
50
)
49
51
import qualified Data.Map.Strict as Map
50
52
import Data.Maybe
@@ -75,9 +77,9 @@ import Development.IDE
75
77
toNormalizedUri ,
76
78
uriToFilePath' ,
77
79
useWithStale_ ,
78
- use_ ,
80
+ use_ , prettyPrint
79
81
)
80
- import Development.IDE.GHC.Compat (AnnotationComment (AnnBlockComment , AnnLineComment ), GenLocated (L ), HscEnv , ParsedModule (.. ), SrcSpan (RealSrcSpan ), srcSpanFile )
82
+ import Development.IDE.GHC.Compat (AnnotationComment (AnnBlockComment , AnnLineComment ), GenLocated (L ), HscEnv , ParsedModule (.. ), SrcSpan (RealSrcSpan , UnhelpfulSpan ), srcSpanFile , GhcException , setInteractiveDynFlags )
81
83
import DynamicLoading (initializePlugins )
82
84
import FastString (unpackFS )
83
85
import GHC
@@ -125,7 +127,7 @@ import GhcPlugins
125
127
updateWays ,
126
128
wayGeneralFlags ,
127
129
wayUnsetGeneralFlags ,
128
- xopt_set ,
130
+ xopt_set , parseDynamicFlagsCmdLine
129
131
)
130
132
import HscTypes
131
133
( InteractiveImport (IIModule ),
@@ -153,7 +155,7 @@ import Ide.Plugin.Eval.GHC
153
155
showDynFlags ,
154
156
)
155
157
import Ide.Plugin.Eval.Parse.Comments (commentsToSections )
156
- import Ide.Plugin.Eval.Parse.Option (langOptions )
158
+ import Ide.Plugin.Eval.Parse.Option (langOptions , parseSetFlags )
157
159
import Ide.Plugin.Eval.Types
158
160
import Ide.Plugin.Eval.Util
159
161
( asS ,
@@ -216,8 +218,11 @@ import Text.Read (readMaybe)
216
218
import Util (OverridingBool (Never ))
217
219
import Development.IDE.Core.PositionMapping (toCurrentRange )
218
220
import qualified Data.DList as DL
219
- import Control.Lens ((^.) )
221
+ import Control.Lens ((^.) , _1 , (%~) , (<&>) , _3 )
220
222
import Language.Haskell.LSP.Types.Lens (line , end )
223
+ import Control.Exception (try )
224
+ import CmdLineParser
225
+ import qualified Development.IDE.GHC.Compat as SrcLoc
221
226
222
227
{- | Code Lens provider
223
228
NOTE: Invoked every time the document is modified, not just when the document is saved.
@@ -272,9 +277,9 @@ codeLens _lsp st plId CodeLensParams{_textDocument} =
272
277
cmd <- liftIO $ mkLspCommand plId evalCommandName " Evaluate=..." (Just [] )
273
278
let lenses =
274
279
[ CodeLens testRange (Just cmd') Nothing
275
- | (section, test) <- tests
280
+ | (section, ident, test) <- tests
276
281
, let (testRange, resultRange) = testRanges test
277
- args = EvalParams (setupSections ++ [section]) _textDocument
282
+ args = EvalParams (setupSections ++ [section]) _textDocument ident
278
283
cmd' =
279
284
(cmd :: Command )
280
285
{ _arguments = Just (List [toJSON args])
@@ -308,19 +313,14 @@ evalCommandName = "evalCommand"
308
313
evalCommand :: PluginCommand IdeState
309
314
evalCommand = PluginCommand evalCommandName " evaluate" runEvalCmd
310
315
311
- -- | Specify the test section to execute
312
- data EvalParams = EvalParams
313
- { sections :: [Section ]
314
- , module_ :: ! TextDocumentIdentifier
315
- }
316
- deriving (Eq , Show , Generic , FromJSON , ToJSON )
316
+ type EvalId = Int
317
317
318
318
runEvalCmd :: CommandFunction IdeState EvalParams
319
319
runEvalCmd lsp st EvalParams {.. } =
320
320
let dbg = logWith st
321
321
perf = timed dbg
322
322
cmd = do
323
- let tests = testsBySection sections
323
+ let tests = map ( \ (a,_,b) -> (a,b)) $ testsBySection sections
324
324
325
325
let TextDocumentIdentifier {_uri} = module_
326
326
fp <- handleMaybe " uri" $ uriToFilePath' _uri
@@ -444,9 +444,12 @@ moduleText lsp uri =
444
444
lsp
445
445
(toNormalizedUri uri)
446
446
447
- testsBySection :: [Section ] -> [(Section , Test )]
447
+ testsBySection :: [Section ] -> [(Section , EvalId , Test )]
448
448
testsBySection sections =
449
- [(section, test) | section <- sections, test <- sectionTests section]
449
+ [(section, ident, test)
450
+ | (ident, section) <- zip [0 .. ] sections
451
+ , test <- sectionTests section
452
+ ]
450
453
451
454
type TEnv = (IdeState , String )
452
455
@@ -560,20 +563,36 @@ evals (st, fp) df stmts = do
560
563
dbg = logWith st
561
564
eval :: Statement -> Ghc (Maybe [Text ])
562
565
eval (Located l stmt)
563
- | -- A :set -XLanguageOption directive
564
- isRight (langOptions stmt) =
565
- either
566
- (return . Just . errorLines)
567
- ( \ es -> do
568
- dbg " {:SET" es
569
- ndf <- getInteractiveDynFlags
570
- dbg " pre set" $ showDynFlags ndf
571
- mapM_ addExtension es
572
- ndf <- getInteractiveDynFlags
573
- dbg " post set" $ showDynFlags ndf
574
- return Nothing
575
- )
576
- $ ghcOptions stmt
566
+ | -- GHCi flags
567
+ Just (words -> flags) <- parseSetFlags stmt = do
568
+ dbg " {:SET" flags
569
+ ndf <- getInteractiveDynFlags
570
+ dbg " pre set" $ showDynFlags ndf
571
+ eans <-
572
+ liftIO $ try @ GhcException $
573
+ parseDynamicFlagsCmdLine ndf
574
+ (map (L $ UnhelpfulSpan " <interactive>" ) flags)
575
+ dbg " parsed flags" $ eans
576
+ <&> (_1 %~ showDynFlags >>> _3 %~ map warnMsg)
577
+ case eans of
578
+ Left err -> pure $ Just $ errorLines $ show err
579
+ Right (df', ignoreds, warns) -> do
580
+ let warnings = do
581
+ guard $ not $ null warns
582
+ pure $ errorLines $
583
+ unlines $
584
+ map prettyWarn warns
585
+ igns = do
586
+ guard $ not $ null ignoreds
587
+ pure
588
+ [" Some flags have not been recognized: "
589
+ <> T. pack (intercalate " , " $ map SrcLoc. unLoc ignoreds)
590
+ ]
591
+ dbg " post set" $ showDynFlags df'
592
+ _ <- setSessionDynFlags df'
593
+ sessDyns <- getSessionDynFlags
594
+ setInteractiveDynFlags sessDyns
595
+ pure $ warnings <> igns
577
596
| -- A type/kind command
578
597
Just (cmd, arg) <- parseGhciLikeCmd $ T. pack stmt =
579
598
evalGhciLikeCmd cmd arg
@@ -616,6 +635,11 @@ evals (st, fp) df stmts = do
616
635
let opts = execOptions{execSourceFile = fp, execLineNumber = l}
617
636
in execStmt stmt opts
618
637
638
+ prettyWarn :: Warn -> String
639
+ prettyWarn Warn {.. } =
640
+ prettyPrint (SrcLoc. getLoc warnMsg) <> " : warning:\n "
641
+ <> " " <> SrcLoc. unLoc warnMsg
642
+
619
643
runGetSession :: MonadIO m => IdeState -> NormalizedFilePath -> m HscEnvEq
620
644
runGetSession st nfp =
621
645
liftIO $
0 commit comments