Skip to content

Commit 8fed630

Browse files
committed
Add code action for incorrect field names
1 parent 7563439 commit 8fed630

File tree

3 files changed

+77
-0
lines changed

3 files changed

+77
-0
lines changed

haskell-language-server.cabal

+1
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ library hls-cabal-plugin
240240
Ide.Plugin.Cabal.Completion.Completions
241241
Ide.Plugin.Cabal.Completion.Data
242242
Ide.Plugin.Cabal.Completion.Types
243+
Ide.Plugin.Cabal.FieldSuggest
243244
Ide.Plugin.Cabal.LicenseSuggest
244245
Ide.Plugin.Cabal.Orphans
245246
Ide.Plugin.Cabal.Parse

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

+6
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import qualified Ide.Plugin.Cabal.Completion.Types as Types
3838
import qualified Ide.Plugin.Cabal.Diagnostics as Diagnostics
3939
import qualified Ide.Plugin.Cabal.LicenseSuggest as LicenseSuggest
4040
import Ide.Plugin.Cabal.Orphans ()
41+
import qualified Ide.Plugin.Cabal.FieldSuggest as FieldSuggest
4142
import qualified Ide.Plugin.Cabal.Parse as Parse
4243
import Ide.Types
4344
import qualified Language.LSP.Protocol.Lens as JL
@@ -88,6 +89,7 @@ descriptor recorder plId =
8889
mconcat
8990
[ mkPluginHandler LSP.SMethod_TextDocumentCodeAction licenseSuggestCodeAction
9091
, mkPluginHandler LSP.SMethod_TextDocumentCompletion $ completion recorder
92+
, mkPluginHandler LSP.SMethod_TextDocumentCodeAction fieldSuggestCodeAction
9193
]
9294
, pluginNotificationHandlers =
9395
mconcat
@@ -228,6 +230,10 @@ licenseSuggestCodeAction :: PluginMethodHandler IdeState 'LSP.Method_TextDocumen
228230
licenseSuggestCodeAction _ _ (CodeActionParams _ _ (TextDocumentIdentifier uri) _range CodeActionContext{_diagnostics=diags}) =
229231
pure $ InL $ diags >>= (fmap InR . LicenseSuggest.licenseErrorAction uri)
230232

233+
fieldSuggestCodeAction :: PluginMethodHandler IdeState 'LSP.Method_TextDocumentCodeAction
234+
fieldSuggestCodeAction _ _ (CodeActionParams _ _ (TextDocumentIdentifier uri) _range CodeActionContext{_diagnostics=diags}) =
235+
pure $ InL $ diags >>= (fmap InR . FieldSuggest.fieldErrorAction uri)
236+
231237
-- ----------------------------------------------------------------
232238
-- Cabal file of Interest rules and global variable
233239
-- ----------------------------------------------------------------
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)