2
2
{-# LANGUAGE OverloadedStrings #-}
3
3
{-# LANGUAGE RecordWildCards #-}
4
4
{-# LANGUAGE ViewPatterns #-}
5
+ {-# LANGUAGE RankNTypes #-}
5
6
6
7
module Ide.Plugin.ConfigUtils where
7
8
@@ -17,16 +18,19 @@ import Data.String (IsString (fromString))
17
18
import qualified Data.Text as T
18
19
import Ide.Plugin.Config
19
20
import Ide.Plugin.Properties (toDefaultJSON ,
20
- toVSCodeExtensionSchema )
21
+ toVSCodeExtensionSchema , Properties , PropertyKey )
21
22
import Ide.Types
22
23
import Language.LSP.Protocol.Message
24
+ import qualified Data.Aeson.Key as A
23
25
24
- -- Attention:
25
- -- 'diagnosticsOn' will never be added into the default config or the schema,
26
- -- since diagnostics emit in arbitrary shake rules -- we don't know
27
- -- whether a plugin is capable of producing diagnostics.
28
-
29
- -- | Generates a default 'Config', but remains only effective items
26
+ -- | Generates a default 'Config', but retains only effective items.
27
+ --
28
+ -- For each plugin, we automatically generate config items if they provide handlers
29
+ -- for code actions, etc...
30
+ -- Naturally, we also generate plugin specific configuration.
31
+ --
32
+ -- If a plugin is single purpose, e.g., only has a single method handler, we
33
+ -- omit the config, as it is sufficiently covered by "globalOn".
30
34
pluginsToDefaultConfig :: IdePlugins a -> A. Value
31
35
pluginsToDefaultConfig IdePlugins {.. } =
32
36
-- Use '_Object' and 'at' to get at the "plugin" key
@@ -48,88 +52,69 @@ pluginsToDefaultConfig IdePlugins {..} =
48
52
-- }
49
53
-- }
50
54
-- }
51
- singlePlugin PluginDescriptor {pluginConfigDescriptor = ConfigDescriptor {.. }, .. } =
52
- let x = genericDefaultConfig <> dedicatedDefaultConfig
53
- in [fromString (T. unpack pId) A. .= A. object x | not $ null x]
54
- where
55
- (PluginHandlers (DMap. toList -> handlers)) = pluginHandlers
56
- customConfigToDedicatedDefaultConfig (CustomConfig p) = toDefaultJSON p
57
- -- Example:
58
- --
59
- -- {
60
- -- "codeActionsOn": true,
61
- -- "codeLensOn": true
62
- -- }
63
- --
64
- genericDefaultConfig =
65
- let x = [" diagnosticsOn" A. .= True | configHasDiagnostics]
66
- <> nubOrd (mconcat
67
- (handlersToGenericDefaultConfig configInitialGenericConfig <$> handlers))
68
- in case x of
69
- -- if the plugin has only one capability, we produce globalOn instead of the specific one;
70
- -- otherwise we don't produce globalOn at all
71
- [_] -> [" globalOn" A. .= plcGlobalOn configInitialGenericConfig]
72
- _ -> x
73
- -- Example:
74
- --
75
- -- {
76
- -- "config": {
77
- -- "property1": "foo"
78
- -- }
79
- -- }
80
- dedicatedDefaultConfig =
81
- let x = customConfigToDedicatedDefaultConfig configCustomConfig
82
- in [" config" A. .= A. object x | not $ null x]
83
-
84
- (PluginId pId) = pluginId
85
-
86
- -- This function captures ide methods registered by the plugin, and then converts it to kv pairs
87
- handlersToGenericDefaultConfig :: PluginConfig -> DSum. DSum IdeMethod f -> [A. Pair ]
88
- handlersToGenericDefaultConfig PluginConfig {.. } (IdeMethod m DSum. :=> _) = case m of
89
- SMethod_TextDocumentCodeAction -> [" codeActionsOn" A. .= plcCodeActionsOn]
90
- SMethod_TextDocumentCodeLens -> [" codeLensOn" A. .= plcCodeLensOn]
91
- SMethod_TextDocumentRename -> [" renameOn" A. .= plcRenameOn]
92
- SMethod_TextDocumentHover -> [" hoverOn" A. .= plcHoverOn]
93
- SMethod_TextDocumentDocumentSymbol -> [" symbolsOn" A. .= plcSymbolsOn]
94
- SMethod_TextDocumentCompletion -> [" completionOn" A. .= plcCompletionOn]
95
- SMethod_TextDocumentPrepareCallHierarchy -> [" callHierarchyOn" A. .= plcCallHierarchyOn]
96
- _ -> []
55
+ singlePlugin pd =
56
+ let
57
+ PluginId pId = pluginId pd
58
+ x = singlePluginConfig A. fromText (const A. Bool ) toDefaultJSON pd
59
+ in
60
+ [fromString (T. unpack pId) A. .= A. object x | not $ null x]
97
61
98
62
-- | Generates json schema used in haskell vscode extension
99
63
-- Similar to 'pluginsToDefaultConfig' but simpler, since schema has a flatten structure
100
64
pluginsToVSCodeExtensionSchema :: IdePlugins a -> A. Value
101
65
pluginsToVSCodeExtensionSchema IdePlugins {.. } = A. object $ mconcat $ singlePlugin <$> ipMap
102
66
where
103
- singlePlugin PluginDescriptor {pluginConfigDescriptor = ConfigDescriptor {.. }, .. } = genericSchema <> dedicatedSchema
104
- where
105
- (PluginHandlers (DMap. toList -> handlers)) = pluginHandlers
106
- customConfigToDedicatedSchema (CustomConfig p) = toVSCodeExtensionSchema (withIdPrefix " config." ) p
107
- (PluginId pId) = pluginId
108
- genericSchema =
109
- let x =
110
- [toKey' " diagnosticsOn" A. .= schemaEntry " diagnostics" True | configHasDiagnostics]
111
- <> nubOrd (mconcat (handlersToGenericSchema configInitialGenericConfig <$> handlers))
112
- in case x of
113
- -- If the plugin has only one capability, we produce globalOn instead of the specific one;
114
- -- otherwise we don't produce globalOn at all
115
- [_] -> [toKey' " globalOn" A. .= schemaEntry " plugin" (plcGlobalOn configInitialGenericConfig)]
116
- _ -> x
117
- dedicatedSchema = customConfigToDedicatedSchema configCustomConfig
118
- handlersToGenericSchema PluginConfig {.. } (IdeMethod m DSum. :=> _) = case m of
119
- SMethod_TextDocumentCodeAction -> [toKey' " codeActionsOn" A. .= schemaEntry " code actions" plcCodeActionsOn]
120
- SMethod_TextDocumentCodeLens -> [toKey' " codeLensOn" A. .= schemaEntry " code lenses" plcCodeLensOn]
121
- SMethod_TextDocumentRename -> [toKey' " renameOn" A. .= schemaEntry " rename" plcRenameOn]
122
- SMethod_TextDocumentHover -> [toKey' " hoverOn" A. .= schemaEntry " hover" plcHoverOn]
123
- SMethod_TextDocumentDocumentSymbol -> [toKey' " symbolsOn" A. .= schemaEntry " symbols" plcSymbolsOn]
124
- SMethod_TextDocumentCompletion -> [toKey' " completionOn" A. .= schemaEntry " completions" plcCompletionOn]
125
- SMethod_TextDocumentPrepareCallHierarchy -> [toKey' " callHierarchyOn" A. .= schemaEntry " call hierarchy" plcCallHierarchyOn]
126
- _ -> []
127
- schemaEntry desc defaultVal =
128
- A. object
129
- [ " scope" A. .= A. String " resource" ,
130
- " type" A. .= A. String " boolean" ,
131
- " default" A. .= A. Bool defaultVal,
132
- " description" A. .= A. String (" Enables " <> pId <> " " <> desc)
133
- ]
134
- withIdPrefix x = " haskell.plugin." <> pId <> " ." <> x
135
- toKey' = fromString . T. unpack . withIdPrefix
67
+ singlePlugin pd =
68
+ let
69
+ (PluginId plId) = pluginId pd
70
+ in
71
+ singlePluginConfig (toKey' plId) (schemaEntry plId) (toVSCodeExtensionSchema (withIdPrefix plId " config." )) pd
72
+
73
+ schemaEntry pId desc defaultVal =
74
+ A. object
75
+ [ " scope" A. .= A. String " resource" ,
76
+ " type" A. .= A. String " boolean" ,
77
+ " default" A. .= A. Bool defaultVal,
78
+ " description" A. .= A. String (" Enables " <> pId <> " " <> desc)
79
+ ]
80
+ withIdPrefix pId x = " haskell.plugin." <> pId <> " ." <> x
81
+ toKey' pId = fromString . T. unpack . withIdPrefix pId
82
+
83
+ -- | Helper function to generate a '[A.Pair]' encoding of a singe plugin configuration.
84
+ singlePluginConfig ::
85
+ (T. Text -> A. Key ) ->
86
+ -- ^ How to modify the key in the 'A.Pair' output.
87
+ -- Called with the name of the key.
88
+ (T. Text -> Bool -> A. Value ) ->
89
+ -- ^ How to create the Value in 'A.Pair'.
90
+ -- Called with a description of the value and the default value
91
+ -- it should have.
92
+ (forall (r :: [PropertyKey ]) . Properties r -> [A. Pair ]) ->
93
+ -- ^ Specify how custom config is serialised.
94
+ PluginDescriptor ideState ->
95
+ -- ^ PluginDescriptor for the plugin to generate the config for.
96
+ [A. Pair ]
97
+ singlePluginConfig toKey valueSchemaDesc customConfigSchema PluginDescriptor {pluginConfigDescriptor = ConfigDescriptor {.. }, .. } =
98
+ genericSchema <> dedicatedSchema
99
+ where
100
+ (PluginHandlers (DMap. toList -> handlers)) = pluginHandlers
101
+ customConfigToDedicatedSchema (CustomConfig p) = customConfigSchema p
102
+ genericSchema =
103
+ let x =
104
+ [toKey " diagnosticsOn" A. .= valueSchemaDesc " diagnostics" True | configHasDiagnostics]
105
+ <> nubOrd (mconcat (handlersToGenericSchema configInitialGenericConfig <$> handlers))
106
+ in case x of
107
+ -- If the plugin has only one capability, we produce globalOn instead of the specific one;
108
+ -- otherwise we don't produce globalOn at all
109
+ [_] -> [toKey " globalOn" A. .= valueSchemaDesc " plugin" (plcGlobalOn configInitialGenericConfig)]
110
+ _ -> x
111
+ dedicatedSchema = customConfigToDedicatedSchema configCustomConfig
112
+ handlersToGenericSchema PluginConfig {.. } (IdeMethod m DSum. :=> _) = case m of
113
+ SMethod_TextDocumentCodeAction -> [toKey " codeActionsOn" A. .= valueSchemaDesc " code actions" plcCodeActionsOn]
114
+ SMethod_TextDocumentCodeLens -> [toKey " codeLensOn" A. .= valueSchemaDesc " code lenses" plcCodeLensOn]
115
+ SMethod_TextDocumentRename -> [toKey " renameOn" A. .= valueSchemaDesc " rename" plcRenameOn]
116
+ SMethod_TextDocumentHover -> [toKey " hoverOn" A. .= valueSchemaDesc " hover" plcHoverOn]
117
+ SMethod_TextDocumentDocumentSymbol -> [toKey " symbolsOn" A. .= valueSchemaDesc " symbols" plcSymbolsOn]
118
+ SMethod_TextDocumentCompletion -> [toKey " completionOn" A. .= valueSchemaDesc " completions" plcCompletionOn]
119
+ SMethod_TextDocumentPrepareCallHierarchy -> [toKey " callHierarchyOn" A. .= valueSchemaDesc " call hierarchy" plcCallHierarchyOn]
120
+ _ -> []
0 commit comments