@@ -11,8 +11,11 @@ module Ide.Plugin.Pragmas
11
11
) where
12
12
13
13
import Control.Lens hiding (List )
14
+ import Control.Applicative ((<|>) )
14
15
import qualified Data.HashMap.Strict as H
15
16
import qualified Data.Text as T
17
+ import Data.Maybe (listToMaybe , fromMaybe )
18
+ import Data.List (findIndex )
16
19
import Development.IDE as D
17
20
import Ide.Types
18
21
import Language.Haskell.LSP.Types
@@ -40,16 +43,17 @@ descriptor plId = (defaultPluginDescriptor plId)
40
43
-- Pragma is added to the first line of the Uri.
41
44
-- It is assumed that the pragma name is a valid pragma,
42
45
-- thus, not validated.
43
- mkPragmaEdit :: Uri -> T. Text -> WorkspaceEdit
44
- mkPragmaEdit uri pragmaName = res where
46
+ mkPragmaEdit :: Uri -> T. Text -> Maybe ParsedModule -> Maybe WorkspaceEdit
47
+ mkPragmaEdit uri pragmaName mpm = res mpm where
45
48
pos = J. Position 0 0
46
- textEdits = J. List
47
- [J. TextEdit (J. Range pos pos )
49
+ textEdits pm = J. List
50
+ [J. TextEdit (endOfModuleHeader pm Nothing )
48
51
(" {-# LANGUAGE " <> pragmaName <> " #-}\n " )
49
52
]
50
- res = J. WorkspaceEdit
51
- (Just $ H. singleton uri textEdits)
53
+ res ( Just pm) = Just $ J. WorkspaceEdit
54
+ (Just . H. singleton uri $ textEdits pm )
52
55
Nothing
56
+ res Nothing = Nothing
53
57
54
58
-- ---------------------------------------------------------------------
55
59
-- | Offer to add a missing Language Pragma to the top of a file.
@@ -61,14 +65,14 @@ codeActionProvider _ state _plId docId _ (J.CodeActionContext (J.List diags) _mo
61
65
let dflags = ms_hspp_opts . pm_mod_summary <$> pm
62
66
-- Get all potential Pragmas for all diagnostics.
63
67
pragmas = nubOrd $ concatMap (\ d -> genPragma dflags (d ^. J. message)) diags
64
- cmds <- mapM mkCodeAction pragmas
68
+ cmds <- mapM ( mkCodeAction pm) pragmas
65
69
return $ Right $ List cmds
66
70
where
67
- mkCodeAction pragmaName = do
71
+ mkCodeAction pm pragmaName = do
68
72
let
69
- codeAction = J. CACodeAction $ J. CodeAction title (Just J. CodeActionQuickFix ) (Just (J. List [] )) (Just edit) Nothing
73
+ codeAction = J. CACodeAction $ J. CodeAction title (Just J. CodeActionQuickFix ) (Just (J. List [] )) (Just =<< edit) Nothing
70
74
title = " Add \" " <> pragmaName <> " \" "
71
- edit = mkPragmaEdit (docId ^. J. uri) pragmaName
75
+ edit = mkPragmaEdit (docId ^. J. uri) pragmaName pm
72
76
return codeAction
73
77
74
78
genPragma mDynflags target =
@@ -164,3 +168,17 @@ completion lspFuncs _ide complParams = do
164
168
_xdata = Nothing
165
169
}
166
170
_ -> return $ Completions $ List []
171
+
172
+ -- | Find the first non-blank line before the first of (module name / imports / declarations).
173
+ -- Useful for inserting pragmas.
174
+ endOfModuleHeader :: ParsedModule -> Maybe T. Text -> Range
175
+ endOfModuleHeader pm contents =
176
+ let mod = unLoc $ pm_parsed_source pm
177
+ modNameLoc = getLoc <$> hsmodName mod
178
+ firstImportLoc = getLoc <$> listToMaybe (hsmodImports mod )
179
+ firstDeclLoc = getLoc <$> listToMaybe (hsmodDecls mod )
180
+ line = fromMaybe 0 $ firstNonBlankBefore . _line . _start =<< srcSpanToRange =<<
181
+ modNameLoc <|> firstImportLoc <|> firstDeclLoc
182
+ firstNonBlankBefore n = (n - ) . fromMaybe 0 . findIndex (not . T. null ) . reverse . take n . T. lines <$> contents
183
+ loc = Position line 0
184
+ in Range loc loc
0 commit comments