Skip to content

Commit 881bcc8

Browse files
dyniecVeryMilkyJoe
authored andcommitted
Add code action for incorrect field names
1 parent d331019 commit 881bcc8

File tree

3 files changed

+77
-0
lines changed

3 files changed

+77
-0
lines changed

haskell-language-server.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ library hls-cabal-plugin
242242
Ide.Plugin.Cabal.Completion.Completions
243243
Ide.Plugin.Cabal.Completion.Data
244244
Ide.Plugin.Cabal.Completion.Types
245+
Ide.Plugin.Cabal.FieldSuggest
245246
Ide.Plugin.Cabal.LicenseSuggest
246247
Ide.Plugin.Cabal.Orphans
247248
Ide.Plugin.Cabal.Parse

plugins/hls-cabal-plugin/src/Ide/Plugin/Cabal.hs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import qualified Ide.Plugin.Cabal.Completion.Types as Types
4040
import qualified Ide.Plugin.Cabal.Diagnostics as Diagnostics
4141
import qualified Ide.Plugin.Cabal.LicenseSuggest as LicenseSuggest
4242
import Ide.Plugin.Cabal.Orphans ()
43+
import qualified Ide.Plugin.Cabal.FieldSuggest as FieldSuggest
4344
import qualified Ide.Plugin.Cabal.Parse as Parse
4445
import Ide.Types
4546
import qualified Language.LSP.Protocol.Lens as JL
@@ -89,6 +90,7 @@ descriptor recorder plId =
8990
mconcat
9091
[ mkPluginHandler LSP.SMethod_TextDocumentCodeAction licenseSuggestCodeAction
9192
, mkPluginHandler LSP.SMethod_TextDocumentCompletion $ completion recorder
93+
, mkPluginHandler LSP.SMethod_TextDocumentCodeAction fieldSuggestCodeAction
9294
]
9395
, pluginNotificationHandlers =
9496
mconcat
@@ -238,6 +240,10 @@ licenseSuggestCodeAction ideState _ (CodeActionParams _ _ (TextDocumentIdentifie
238240
maxCompls <- fmap maxCompletions . liftIO $ runAction "cabal-plugin.suggestLicense" ideState getClientConfigAction
239241
pure $ InL $ diags >>= (fmap InR . LicenseSuggest.licenseErrorAction maxCompls uri)
240242

243+
fieldSuggestCodeAction :: PluginMethodHandler IdeState 'LSP.Method_TextDocumentCodeAction
244+
fieldSuggestCodeAction _ _ (CodeActionParams _ _ (TextDocumentIdentifier uri) _range CodeActionContext{_diagnostics=diags}) =
245+
pure $ InL $ diags >>= (fmap InR . FieldSuggest.fieldErrorAction uri)
246+
241247
-- ----------------------------------------------------------------
242248
-- Cabal file of Interest rules and global variable
243249
-- ----------------------------------------------------------------
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
{-# LANGUAGE AllowAmbiguousTypes #-}
2+
{-# LANGUAGE ExplicitNamespaces #-}
3+
{-# LANGUAGE FlexibleContexts #-}
4+
{-# LANGUAGE LambdaCase #-}
5+
{-# LANGUAGE OverloadedStrings #-}
6+
module Ide.Plugin.Cabal.FieldSuggest
7+
( fieldErrorSuggestion
8+
, fieldErrorAction
9+
-- * Re-exports
10+
, T.Text
11+
, Diagnostic(..)
12+
)
13+
where
14+
15+
import qualified Data.Map.Strict as Map
16+
import qualified Data.Text as T
17+
import Language.LSP.Protocol.Types (CodeAction (CodeAction),
18+
CodeActionKind (..),
19+
Diagnostic (..),
20+
Position (Position),
21+
Range (Range),
22+
TextEdit (TextEdit), Uri,
23+
WorkspaceEdit (WorkspaceEdit))
24+
import Text.Regex.TDFA
25+
26+
-- | Given a diagnostic returned by 'Ide.Plugin.Cabal.Diag.errorDiagnostic',
27+
-- if it represents an "Unknown field"-error along
28+
-- with a incorrect field, then return a 'CodeAction' for replacing the
29+
-- the incorrect field with the suggestion.
30+
-- It should be context sensitive, but for now it isn't
31+
fieldErrorAction
32+
:: Uri
33+
-- ^ File for which the diagnostic was generated
34+
-> Diagnostic
35+
-- ^ Output of 'Ide.Plugin.Cabal.Diag.errorDiagnostic'
36+
-> [CodeAction]
37+
fieldErrorAction uri diag =
38+
mkCodeAction <$> fieldErrorSuggestion diag
39+
where
40+
mkCodeAction (original, suggestion) =
41+
let
42+
-- Range returned by cabal here represents fragment from start of
43+
-- offending identifier to end of line, we modify it to the end of identifier
44+
adjustRange (Range rangeFrom@(Position line col) _) =
45+
Range rangeFrom (Position line (col + fromIntegral (T.length original)))
46+
title = "Replace with " <> suggestion
47+
tedit = [TextEdit (adjustRange $ _range diag) suggestion]
48+
edit = WorkspaceEdit (Just $ Map.singleton uri tedit) Nothing Nothing
49+
in CodeAction title (Just CodeActionKind_QuickFix) (Just []) Nothing Nothing (Just edit) Nothing Nothing
50+
51+
-- | Given a diagnostic returned by 'Ide.Plugin.Cabal.Diag.errorDiagnostic',
52+
-- if it represents an "Unknown field"- error with incorrect identifier
53+
-- then return the suggestion (for now placeholder "name")
54+
-- along with the incorrect identifier.
55+
--
56+
fieldErrorSuggestion
57+
:: Diagnostic
58+
-- ^ Output of 'Ide.Plugin.Cabal.Diag.errorDiagnostic'
59+
-> [(T.Text, T.Text)]
60+
-- ^ (Original (incorrect) license identifier, suggested replacement)
61+
fieldErrorSuggestion diag =
62+
mSuggestion (_message diag) >>= \case
63+
[original] -> [(original, "name")]
64+
_ -> []
65+
where
66+
regex :: T.Text
67+
regex = "Unknown field: \"(.*)\""
68+
mSuggestion msg = getMatch <$> (msg :: T.Text) =~~ regex
69+
getMatch :: (T.Text, T.Text, T.Text, [T.Text]) -> [T.Text]
70+
getMatch (_, _, _, results) = results

0 commit comments

Comments
 (0)