2
2
{-# LANGUAGE DeriveGeneric #-}
3
3
{-# LANGUAGE DeriveAnyClass #-}
4
4
{-# LANGUAGE TupleSections #-}
5
+ {-# LANGUAGE LambdaCase #-}
5
6
module Haskell.Ide.Engine.Plugin.HsImport where
6
7
7
8
import Control.Lens.Operators
@@ -72,7 +73,6 @@ importModule uri importList modName =
72
73
tmpDir <- liftIO getTemporaryDirectory
73
74
(output, outputH) <- liftIO $ openTempFile tmpDir " hsimportOutput"
74
75
liftIO $ hClose outputH
75
-
76
76
let args = defaultArgs { moduleName = T. unpack modName
77
77
, inputSrcFile = input
78
78
, symbolName = T. unpack $ fromMaybe " " importList
@@ -107,16 +107,38 @@ importModule uri importList modName =
107
107
return $ IdeResultOk (J. WorkspaceEdit mChanges mDocChanges)
108
108
109
109
Just (_, provider) -> do
110
- let formatEdit :: J. TextEdit -> IdeGhcM J. TextEdit
110
+ let
111
+ -- | Dirty little hack.
112
+ -- Necessary in the following case:
113
+ -- We want to add an item to an existing import-list.
114
+ -- The diff algorithm does not count the newline character
115
+ -- as part of the diff between new and old text.
116
+ -- However, some formatters (Brittany), add a trailing
117
+ -- newline nevertheless.
118
+ -- This leads to the problem that an additional
119
+ -- newline is inserted into the source.
120
+ -- This function makes sure, that if the original text
121
+ -- did not have a newline, none will be added, assuming
122
+ -- that the diff algorithm continues to not count newlines
123
+ -- as part of the diff.
124
+ -- This is only save to do in this very specific environment.
125
+ -- In any other case, this function may not be copy-pasted
126
+ -- to solve a similar problem.
127
+ renormalise :: T. Text -> T. Text -> T. Text
128
+ renormalise orig formatted
129
+ | T. null orig || T. null formatted = orig <> formatted
130
+ | T. last orig /= ' \n ' && T. last formatted == ' \n ' = T. init formatted
131
+ | otherwise = formatted
132
+
133
+ formatEdit :: J. TextEdit -> IdeGhcM J. TextEdit
111
134
formatEdit origEdit@ (J. TextEdit r t) = do
112
135
-- TODO: are these default FormattingOptions ok?
113
- res <- liftToGhc $ provider t uri FormatText ( FormattingOptions 2 True )
114
- let formatEdits = case res of
115
- IdeResultOk xs -> xs
116
- _ -> [origEdit]
136
+ formatEdits <-
137
+ liftToGhc $ provider t uri FormatText ( FormattingOptions 2 True ) >>= \ case
138
+ IdeResultOk xs -> return xs
139
+ _ -> return [origEdit]
117
140
-- let edits = foldl' J.editTextEdit origEdit formatEdits -- TODO: this seems broken.
118
- -- liftIO $ hPutStrLn stderr $ "Text Edits: " ++ show formatEdits
119
- return (J. TextEdit r (J. _newText $ head formatEdits))
141
+ return (J. TextEdit r (renormalise t . J. _newText $ head formatEdits))
120
142
121
143
-- behold: the legendary triple mapM
122
144
newChanges <- (mapM . mapM . mapM ) formatEdit mChanges
@@ -186,7 +208,7 @@ codeActionProvider plId docId _ context = do
186
208
applySearchStyle Exact term = " is:exact " <> term
187
209
applySearchStyle ExactName term = case T. words term of
188
210
[] -> term
189
- (x: _) -> " is:exact " <> x
211
+ (x : _) -> " is:exact " <> x
190
212
applySearchStyle (Relax relax) term = relax term
191
213
192
214
-- | Turn a search term with function name into Import Actions.
@@ -206,7 +228,7 @@ codeActionProvider plId docId _ context = do
206
228
termToActions style functionName (diagnostic, termName) = do
207
229
let useImportList = case style of
208
230
Relax _ -> Nothing
209
- _ -> Just (mkImportAction (Just functionName) diagnostic termName)
231
+ _ -> Just (mkImportAction (Just functionName) diagnostic termName)
210
232
catMaybes <$> sequenceA
211
233
(mkImportAction Nothing diagnostic termName : maybeToList useImportList)
212
234
0 commit comments