Skip to content

Commit d83afa2

Browse files
dyniecfendor
authored andcommitted
Add code action for incorrect field names
1 parent 3822586 commit d83afa2

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
@@ -237,6 +237,7 @@ library hls-cabal-plugin
237237
Ide.Plugin.Cabal.Completion.Completions
238238
Ide.Plugin.Cabal.Completion.Data
239239
Ide.Plugin.Cabal.Completion.Types
240+
Ide.Plugin.Cabal.FieldSuggest
240241
Ide.Plugin.Cabal.LicenseSuggest
241242
Ide.Plugin.Cabal.Parse
242243

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import qualified Ide.Plugin.Cabal.Completion.Completions as Completions
3333
import qualified Ide.Plugin.Cabal.Completion.Types as Types
3434
import qualified Ide.Plugin.Cabal.Diagnostics as Diagnostics
3535
import qualified Ide.Plugin.Cabal.LicenseSuggest as LicenseSuggest
36+
import qualified Ide.Plugin.Cabal.FieldSuggest as FieldSuggest
3637
import qualified Ide.Plugin.Cabal.Parse as Parse
3738
import Ide.Types
3839
import qualified Language.LSP.Protocol.Lens as JL
@@ -83,6 +84,7 @@ descriptor recorder plId =
8384
mconcat
8485
[ mkPluginHandler LSP.SMethod_TextDocumentCodeAction licenseSuggestCodeAction
8586
, mkPluginHandler LSP.SMethod_TextDocumentCompletion $ completion recorder
87+
, mkPluginHandler LSP.SMethod_TextDocumentCodeAction fieldSuggestCodeAction
8688
]
8789
, pluginNotificationHandlers =
8890
mconcat
@@ -197,6 +199,10 @@ licenseSuggestCodeAction :: PluginMethodHandler IdeState 'LSP.Method_TextDocumen
197199
licenseSuggestCodeAction _ _ (CodeActionParams _ _ (TextDocumentIdentifier uri) _range CodeActionContext{_diagnostics=diags}) =
198200
pure $ InL $ diags >>= (fmap InR . LicenseSuggest.licenseErrorAction uri)
199201

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)
205+
200206
-- ----------------------------------------------------------------
201207
-- Cabal file of Interest rules and global variable
202208
-- ----------------------------------------------------------------
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)