1
1
{-# LANGUAGE CPP #-}
2
2
{-# LANGUAGE OverloadedStrings #-}
3
+ {-# LANGUAGE TypeFamilies #-}
3
4
4
5
module Wingman.LanguageServer where
5
6
@@ -12,25 +13,30 @@ import Data.Coerce
12
13
import Data.Functor ((<&>) )
13
14
import Data.Generics.Aliases (mkQ )
14
15
import Data.Generics.Schemes (everything )
16
+ import qualified Data.HashMap.Strict as Map
15
17
import Data.IORef (readIORef )
16
18
import qualified Data.Map as M
17
19
import Data.Maybe
18
20
import Data.Monoid
19
21
import qualified Data.Set as S
20
22
import qualified Data.Text as T
21
23
import Data.Traversable
24
+ import Development.IDE (getFilesOfInterest , ShowDiagnostic (ShowDiag ), srcSpanToRange )
22
25
import Development.IDE (hscEnv )
26
+ import Development.IDE.Core.PositionMapping
23
27
import Development.IDE.Core.RuleTypes
28
+ import Development.IDE.Core.Rules (usePropertyAction )
24
29
import Development.IDE.Core.Service (runAction )
25
- import Development.IDE.Core.Shake (IdeState (.. ), use )
30
+ import Development.IDE.Core.Shake (IdeState (.. ), uses , define , use )
26
31
import qualified Development.IDE.Core.Shake as IDE
27
32
import Development.IDE.Core.UseStale
28
33
import Development.IDE.GHC.Compat
29
34
import Development.IDE.GHC.Error (realSrcSpanToRange )
30
35
import Development.IDE.Spans.LocalBindings (Bindings , getDefiningBindings )
31
- import Development.Shake (Action , RuleResult )
36
+ import Development.Shake (Action , RuleResult , Rules , action )
32
37
import Development.Shake.Classes (Typeable , Binary , Hashable , NFData )
33
38
import qualified FastString
39
+ import GHC.Generics (Generic )
34
40
import GhcPlugins (tupleDataCon , consDataCon , substTyAddInScope , ExternalPackageState , HscEnv (hsc_EPS ), liftIO )
35
41
import qualified Ide.Plugin.Config as Plugin
36
42
import Ide.Plugin.Properties
@@ -109,7 +115,8 @@ unsafeRunStaleIde state nfp a = do
109
115
------------------------------------------------------------------------------
110
116
111
117
properties :: Properties
112
- '[ 'PropertyKey " max_use_ctor_actions" 'TInteger
118
+ '[ 'PropertyKey " hole_severity" ('TEnum (Maybe DiagnosticSeverity ))
119
+ , 'PropertyKey " max_use_ctor_actions" 'TInteger
113
120
, 'PropertyKey " features" 'TString
114
121
, 'PropertyKey " timeout_duration" 'TInteger
115
122
]
@@ -120,6 +127,15 @@ properties = emptyProperties
120
127
" Feature set used by Wingman" " "
121
128
& defineIntegerProperty # max_use_ctor_actions
122
129
" Maximum number of `Use constructor <x>` code actions that can appear" 5
130
+ & defineEnumProperty # hole_severity
131
+ " The severity to use when showing hole diagnostics. These are noisy, but some editors don't allow jumping to all severities."
132
+ [ (Just DsError , " error" )
133
+ , (Just DsWarning , " warning" )
134
+ , (Just DsInfo , " info" )
135
+ , (Just DsHint , " hint" )
136
+ , (Nothing , " none" )
137
+ ]
138
+ Nothing
123
139
124
140
125
141
-- | Get the the plugin config
@@ -421,3 +437,61 @@ mkShowMessageParams ufm = ShowMessageParams (ufmSeverity ufm) $ T.pack $ show uf
421
437
showLspMessage :: MonadLsp cfg m => ShowMessageParams -> m ()
422
438
showLspMessage = sendNotification SWindowShowMessage
423
439
440
+
441
+ -- This rule only exists for generating file diagnostics
442
+ -- so the RuleResult is empty
443
+ data WriteDiagnostics = WriteDiagnostics
444
+ deriving (Eq , Show , Typeable , Generic )
445
+
446
+ instance Hashable WriteDiagnostics
447
+ instance NFData WriteDiagnostics
448
+ instance Binary WriteDiagnostics
449
+
450
+ type instance RuleResult WriteDiagnostics = ()
451
+
452
+ wingmanRules :: PluginId -> Rules ()
453
+ wingmanRules plId = do
454
+ define $ \ WriteDiagnostics nfp ->
455
+ usePropertyAction # hole_severity plId properties >>= \ case
456
+ Nothing -> pure (mempty , Just () )
457
+ Just severity ->
458
+ use GetParsedModule nfp >>= \ case
459
+ Nothing ->
460
+ pure ([] , Nothing )
461
+ Just pm -> do
462
+ let holes :: [Range ]
463
+ holes =
464
+ everything (<>)
465
+ (mkQ mempty $ \ case
466
+ L span (HsVar _ (L _ name))
467
+ | isHole (occName name) ->
468
+ maybeToList $ srcSpanToRange span
469
+ L span (HsUnboundVar _ (TrueExprHole occ))
470
+ | isHole occ ->
471
+ maybeToList $ srcSpanToRange span
472
+ #if __GLASGOW_HASKELL__ <= 808
473
+ L span (EWildPat _) ->
474
+ maybeToList $ srcSpanToRange span
475
+ #endif
476
+ (_ :: LHsExpr GhcPs ) -> mempty
477
+ ) $ pm_parsed_source pm
478
+ pure
479
+ ( fmap (\ r -> (nfp, ShowDiag , mkDiagnostic severity r)) holes
480
+ , Just ()
481
+ )
482
+
483
+ action $ do
484
+ files <- getFilesOfInterest
485
+ void $ uses WriteDiagnostics $ Map. keys files
486
+
487
+
488
+ mkDiagnostic :: DiagnosticSeverity -> Range -> Diagnostic
489
+ mkDiagnostic severity r =
490
+ Diagnostic r
491
+ (Just severity)
492
+ (Just $ InR " hole" )
493
+ (Just " wingman" )
494
+ " Hole"
495
+ (Just $ List [DtUnnecessary ])
496
+ Nothing
497
+
0 commit comments