@@ -26,7 +26,6 @@ import Development.IDE.Core.Shake (restartShakeSessio
26
26
import qualified Development.IDE.Core.Shake as Shake
27
27
import Development.IDE.Graph (alwaysRerun )
28
28
import qualified Development.IDE.Plugin.Completions.Logic as Ghcide
29
- import qualified Development.IDE.Plugin.Completions.Types as Ghcide
30
29
import GHC.Generics
31
30
import qualified Ide.Plugin.Cabal.Completion.Completer.Types as CompleterTypes
32
31
import qualified Ide.Plugin.Cabal.Completion.Completions as Completions
@@ -41,6 +40,9 @@ import qualified Language.LSP.Protocol.Message as LSP
41
40
import Language.LSP.Protocol.Types
42
41
import Language.LSP.Server (getVirtualFile )
43
42
import qualified Language.LSP.VFS as VFS
43
+ import qualified Data.Text as T
44
+ import Data.Maybe (mapMaybe )
45
+ import Data.Text.Utf16.Rope.Mixed (Rope )
44
46
45
47
data Log
46
48
= LogModificationTime NormalizedFilePath FileVersion
@@ -84,7 +86,7 @@ descriptor recorder plId =
84
86
mconcat
85
87
[ mkPluginHandler LSP. SMethod_TextDocumentCodeAction licenseSuggestCodeAction
86
88
, mkPluginHandler LSP. SMethod_TextDocumentCompletion $ completion recorder
87
- , mkPluginHandler LSP. SMethod_TextDocumentCodeAction fieldSuggestCodeAction
89
+ , mkPluginHandler LSP. SMethod_TextDocumentCodeAction $ fieldSuggestCodeAction recorder
88
90
]
89
91
, pluginNotificationHandlers =
90
92
mconcat
@@ -199,9 +201,26 @@ licenseSuggestCodeAction :: PluginMethodHandler IdeState 'LSP.Method_TextDocumen
199
201
licenseSuggestCodeAction _ _ (CodeActionParams _ _ (TextDocumentIdentifier uri) _range CodeActionContext {_diagnostics= diags}) =
200
202
pure $ InL $ diags >>= (fmap InR . LicenseSuggest. licenseErrorAction uri)
201
203
202
- fieldSuggestCodeAction :: PluginMethodHandler IdeState 'LSP.Method_TextDocumentCodeAction
203
- fieldSuggestCodeAction _ _ (CodeActionParams _ _ (TextDocumentIdentifier uri) _range CodeActionContext {_diagnostics= diags}) =
204
- pure $ InL $ diags >>= (fmap InR . FieldSuggest. fieldErrorAction uri)
204
+ -- | CodeActions for misspelled fields in cabal files
205
+ -- both for toplevel fields, and fields in stanzas.
206
+ -- uses same logic as completions but reacts on diagnostics from cabal
207
+ fieldSuggestCodeAction :: Recorder (WithPriority Log ) -> PluginMethodHandler IdeState 'LSP.Method_TextDocumentCodeAction
208
+ fieldSuggestCodeAction recorder ide _ (CodeActionParams _ _ (TextDocumentIdentifier uri) _ CodeActionContext {_diagnostics= diags}) = do
209
+ vfileM <- lift (getVirtualFile $ toNormalizedUri uri)
210
+ case liftA2 (,) vfileM (uriToFilePath' uri) of
211
+ Nothing -> pure $ InL []
212
+ Just (vfile, path) -> do
213
+ let fields = mapMaybe FieldSuggest. fieldErrorName diags
214
+ results <- forM fields (getSuggestion vfile path)
215
+ pure $ InL $ map InR $ concat results
216
+ where
217
+ getSuggestion vfile fp (field,Diagnostic { _range= _range@ (Range (Position lineNr col) _) })= do
218
+ let fakeLspCursorPosition = Position lineNr (col + fromIntegral (T. length field))
219
+ lspPrefixInfo = Ghcide. getCompletionPrefix fakeLspCursorPosition vfile
220
+ cabalPrefixInfo = Completions. getCabalPrefixInfo fp lspPrefixInfo
221
+ completions <- liftIO $ computeCompletionsAt recorder cabalPrefixInfo (vfile ^. VFS. file_text) (shakeExtras ide)
222
+ let completionTexts = (fmap (^. JL. label) completions)
223
+ pure $ FieldSuggest. fieldErrorAction uri field completionTexts _range
205
224
206
225
-- ----------------------------------------------------------------
207
226
-- Cabal file of Interest rules and global variable
@@ -287,32 +306,32 @@ completion recorder ide _ complParams = do
287
306
contents <- lift $ getVirtualFile $ toNormalizedUri uri
288
307
case (contents, uriToFilePath' uri) of
289
308
(Just cnts, Just path) -> do
290
- let pref = Ghcide. getCompletionPrefix position cnts
291
- let res = result pref path cnts
292
- liftIO $ fmap InL res
309
+ let lspPrefixInfo = Ghcide. getCompletionPrefix position cnts
310
+ cabalPrefixInfo = Completions. getCabalPrefixInfo path lspPrefixInfo
311
+ let compls = computeCompletionsAt recorder cabalPrefixInfo (cnts ^. VFS. file_text) (shakeExtras ide)
312
+ liftIO $ fmap InL compls
293
313
_ -> pure . InR $ InR Null
294
- where
295
- result :: Ghcide. PosPrefixInfo -> FilePath -> VFS. VirtualFile -> IO [CompletionItem ]
296
- result prefix fp cnts = do
297
- runMaybeT context >>= \ case
298
- Nothing -> pure []
299
- Just ctx -> do
300
- logWith recorder Debug $ LogCompletionContext ctx pos
301
- let completer = Completions. contextToCompleter ctx
302
- let completerData = CompleterTypes. CompleterData
303
- { getLatestGPD = do
304
- mGPD <- runIdeAction " cabal-plugin.modulesCompleter.gpd" (shakeExtras ide) $ useWithStaleFast Types. GetCabalDiagnostics $ toNormalizedFilePath fp
305
- pure $ fmap fst mGPD
306
- , cabalPrefixInfo = prefInfo
307
- , stanzaName =
308
- case fst ctx of
309
- Types. Stanza _ name -> name
310
- _ -> Nothing
311
- }
312
- completions <- completer completerRecorder completerData
313
- pure completions
314
- where
315
- completerRecorder = cmapWithPrio LogCompletions recorder
316
- pos = Ghcide. cursorPos prefix
317
- context = Completions. getContext completerRecorder prefInfo (cnts ^. VFS. file_text)
318
- prefInfo = Completions. getCabalPrefixInfo fp prefix
314
+
315
+ computeCompletionsAt :: Recorder (WithPriority Log ) -> Types. CabalPrefixInfo -> Rope -> ShakeExtras -> IO [CompletionItem ]
316
+ computeCompletionsAt recorder cabalPrefixInfo fileRope extras = do
317
+ runMaybeT context >>= \ case
318
+ Nothing -> pure []
319
+ Just ctx -> do
320
+ logWith recorder Debug $ LogCompletionContext ctx pos
321
+ let completer = Completions. contextToCompleter ctx
322
+ let completerData = CompleterTypes. CompleterData
323
+ { getLatestGPD = do
324
+ mGPD <- runIdeAction " computeCompletionsAt.gpd" extras $ useWithStaleFast Types. GetCabalDiagnostics $ toNormalizedFilePath fp
325
+ pure $ fmap fst mGPD
326
+ , cabalPrefixInfo = cabalPrefixInfo
327
+ , stanzaName =
328
+ case fst ctx of
329
+ Types. Stanza _ name -> name
330
+ _ -> Nothing
331
+ }
332
+ completions <- completer completerRecorder completerData
333
+ pure completions
334
+ where
335
+ completerRecorder = cmapWithPrio LogCompletions recorder
336
+ pos = Types. completionCursorPosition cabalPrefixInfo
337
+ context = Completions. getContext completerRecorder cabalPrefixInfo fileRope
0 commit comments