1
- {-# LANGUAGE ViewPatterns #-}
1
+ {-# LANGUAGE CPP #-}
2
+ {-# LANGUAGE DeriveAnyClass #-}
2
3
{-# LANGUAGE DeriveGeneric #-}
3
4
{-# LANGUAGE DuplicateRecordFields #-}
4
5
{-# LANGUAGE FlexibleContexts #-}
@@ -15,31 +16,21 @@ module Ide.Plugin.Hlint
15
16
-- , provider
16
17
) where
17
18
18
- -- import DA.Daml.DocTest
19
- -- import Development.IDE.Core.Service.Daml
20
- -- import qualified DA.Daml.LF.Ast as LF
21
- -- import qualified DA.Daml.LF.ScenarioServiceClient as SS
22
- -- import Control.Exception.Safe
23
- -- import Development.IDE.Core.RuleTypes.Daml
24
- -- import Development.IDE.Core.Rules
25
- -- import Development.IDE.Core.Service.Daml
26
- -- import Development.IDE.Types.Location
27
- -- import qualified DA.Daml.LF.Ast as LF
28
- -- import qualified DA.Daml.Visual as Visual
29
- -- import qualified Data.NameMap as NM
30
19
import Control.DeepSeq
31
20
import Control.Exception
21
+ import Control.Lens ((^.) )
32
22
import Control.Monad
33
23
import Control.Monad.Extra
34
24
import Control.Monad.Trans.Maybe
35
25
import qualified Data.Aeson as Aeson
36
- import Data.Aeson.Types (toJSON , fromJSON , Value (.. ), Result (.. ))
26
+ import Data.Aeson.Types (ToJSON ( .. ), FromJSON ( .. ) , Value (.. ), Result (.. ))
37
27
import Data.Binary
38
28
import qualified Data.ByteString as BS
39
29
import Data.Either.Extra
40
30
import Data.Foldable
41
31
import Data.Functor
42
32
import qualified Data.HashMap.Strict as Map
33
+ import qualified Data.HashSet as HashSet
43
34
import Data.Hashable
44
35
import Data.List
45
36
import Data.Map.Strict (Map )
@@ -65,9 +56,10 @@ import Development.Shake
65
56
import GHC
66
57
import GHC.Generics
67
58
import GHC.Generics (Generic )
59
+ import SrcLoc
68
60
import HscTypes (ModIface , ModSummary )
69
61
import Ide.Types
70
- import qualified Language.Haskell.Exts.SrcLoc as HSE
62
+ import Ide.Plugin
71
63
import Language.Haskell.HLint
72
64
import Language.Haskell.HLint as Hlint
73
65
import qualified Language.Haskell.LSP.Core as LSP
@@ -82,8 +74,6 @@ import System.FilePath
82
74
import System.IO.Error
83
75
import Text.Regex.TDFA.Text ()
84
76
85
-
86
- -- import "ghc-lib-parser" Module (UnitId)
87
77
-- ---------------------------------------------------------------------
88
78
89
79
descriptor :: PluginId -> PluginDescriptor
@@ -93,7 +83,7 @@ descriptor plId = (defaultPluginDescriptor plId)
93
83
-- [ PluginCommand "applyOne" "Apply a single hint" applyOneCmd
94
84
-- , PluginCommand "applyAll" "Apply all hints to the file" applyAllCmd
95
85
-- ]
96
- -- , pluginCodeActionProvider = Just codeActionProvider
86
+ -- , pluginCodeActionProvider = Just codeActionProvider
97
87
}
98
88
99
89
data GetHlintDiagnostics = GetHlintDiagnostics
@@ -107,37 +97,71 @@ type instance RuleResult GetHlintDiagnostics = ()
107
97
rules :: Rules ()
108
98
rules = do
109
99
define $ \ GetHlintDiagnostics file -> do
110
- pm <- use_ GetParsedModule file
111
- let anns = pm_annotations pm
112
- let modu = pm_parsed_source pm
113
100
(classify, hint) <- useNoFile_ GetHlintSettings
114
- let ideas = applyHints classify hint [createModuleEx anns modu]
115
- return ([diagnostic file i | i <- ideas, ideaSeverity i /= Ignore ], Just () )
101
+ eModuleEx <- getModuleEx file
102
+ let getIdeas moduleEx = applyHints classify hint [moduleEx]
103
+ return $ (diagnostics file (fmap getIdeas eModuleEx), Just () )
104
+
105
+ hlintDataDir <- liftIO getExecutablePath
106
+
107
+ getHlintSettingsRule (HlintEnabled hlintDataDir True )
116
108
117
109
action $ do
118
110
files <- getFilesOfInterest
119
- void $ uses GetHlintDiagnostics $ Set . toList files
111
+ void $ uses GetHlintDiagnostics $ HashSet . toList files
120
112
121
113
where
122
- srcSpanToRange :: HSE. SrcSpan -> LSP. Range
123
- srcSpanToRange span = Range {
114
+
115
+ getModuleEx :: NormalizedFilePath -> Action (Either ParseError ModuleEx )
116
+ getModuleEx fp = do
117
+ #ifndef GHC_LIB
118
+ pm <- use_ GetParsedModule fp
119
+ let anns = pm_annotations pm
120
+ let modu = pm_parsed_source pm
121
+ return $ Right (createModuleEx anns modu)
122
+ #else
123
+ liftIO $ parseModuleEx defaultParseFlags (fromNormalizedFilePath fp) Nothing
124
+ #endif
125
+
126
+ diagnostics :: NormalizedFilePath -> Either ParseError [Idea ] -> [FileDiagnostic ]
127
+ diagnostics file (Right ideas) =
128
+ [(file, ShowDiag , ideaToDiagnostic i) | i <- ideas, ideaSeverity i /= Ignore ]
129
+ diagnostics file (Left parseErr) =
130
+ [(file, ShowDiag , parseErrorToDiagnostic parseErr)]
131
+
132
+ ideaToDiagnostic :: Idea -> Diagnostic
133
+ ideaToDiagnostic idea =
134
+ LSP. Diagnostic {
135
+ _range = srcSpanToRange $ ideaSpan idea
136
+ , _severity = Just LSP. DsInfo
137
+ , _code = Just (LSP. StringValue $ T. pack $ ideaHint idea)
138
+ , _source = Just " hlint"
139
+ , _message = T. pack $ show idea
140
+ , _relatedInformation = Nothing
141
+ }
142
+
143
+ parseErrorToDiagnostic :: ParseError -> Diagnostic
144
+ parseErrorToDiagnostic (Hlint. ParseError l msg contents) =
145
+ LSP. Diagnostic {
146
+ _range = srcSpanToRange l
147
+ , _severity = Just LSP. DsInfo
148
+ , _code = Just (LSP. StringValue " parser" )
149
+ , _source = Just " hlint"
150
+ , _message = T. unlines [T. pack msg,T. pack contents]
151
+ , _relatedInformation = Nothing
152
+ }
153
+ -- This one is defined in Development.IDE.GHC.Error but here
154
+ -- the types could come from ghc-lib or ghc
155
+ srcSpanToRange :: SrcSpan -> LSP. Range
156
+ srcSpanToRange (RealSrcSpan span ) = Range {
124
157
_start = LSP. Position {
125
- _line = HSE. srcSpanStartLine span - 1
126
- , _character = HSE. srcSpanStartColumn span - 1 }
158
+ _line = srcSpanStartLine span - 1
159
+ , _character = srcSpanStartCol span - 1 }
127
160
, _end = LSP. Position {
128
- _line = HSE. srcSpanEndLine span - 1
129
- , _character = HSE. srcSpanEndColumn span - 1 }
161
+ _line = srcSpanEndLine span - 1
162
+ , _character = srcSpanEndCol span - 1 }
130
163
}
131
- diagnostic :: NormalizedFilePath -> Idea -> FileDiagnostic
132
- diagnostic file i =
133
- (file, ShowDiag , LSP. Diagnostic {
134
- _range = srcSpanToRange $ ideaSpan i
135
- , _severity = Just LSP. DsInfo
136
- , _code = Nothing
137
- , _source = Just " hlint"
138
- , _message = T. pack $ show i
139
- , _relatedInformation = Nothing
140
- })
164
+ srcSpanToRange (UnhelpfulSpan _) = noRange
141
165
142
166
-- ---------------------------------------------------------------------
143
167
@@ -189,7 +213,8 @@ hlintSettings hlintDataDir enableOverrides = do
189
213
foldMapM f = foldlM (\ acc a -> do w <- f a; return $! mappend acc w) mempty
190
214
191
215
-- ---------------------------------------------------------------------
192
- -- ---------------------------------------------------------------------
216
+
217
+
193
218
-- ---------------------------------------------------------------------
194
219
{-
195
220
{- # LANGUAGE CPP #-}
0 commit comments