Skip to content

Commit cb5539a

Browse files
committed
feat: introduced plugins' custom config params autogenerated docs
Introduces plugins-custom-config-markdown-reference subcommand which extracts plugins' custom config parameters and renders a Markdown table with all the reference information.
1 parent b1966ff commit cb5539a

File tree

9 files changed

+396
-3
lines changed

9 files changed

+396
-3
lines changed

hls-plugin-api/src/Ide/Plugin/ConfigUtils.hs

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,15 @@ import qualified Data.Dependent.Sum as DSum
1818
import Data.List.Extra (nubOrd)
1919
import Data.String (IsString (fromString))
2020
import qualified Data.Text as T
21+
import GHC.TypeLits (symbolVal)
2122
import Ide.Plugin.Config
22-
import Ide.Plugin.Properties (toDefaultJSON,
23+
import Ide.Plugin.Properties (KeyNameProxy, MetaData (..),
24+
PluginCustomConfig (..),
25+
PluginCustomConfigParam (..),
26+
Properties (..),
27+
SPropertyKey (..),
28+
SomePropertyKeyWithMetaData (..),
29+
toDefaultJSON,
2330
toVSCodeExtensionSchema)
2431
import Ide.Types
2532
import Language.LSP.Protocol.Message
@@ -143,3 +150,92 @@ pluginsToVSCodeExtensionSchema IdePlugins {..} = A.object $ mconcat $ singlePlug
143150
]
144151
withIdPrefix x = "haskell.plugin." <> pId <> "." <> x
145152
toKey' = fromString . T.unpack . withIdPrefix
153+
154+
155+
-- | Generates markdown tables for custom config
156+
pluginsCustomConfigToMarkdownTables :: IdePlugins a -> T.Text
157+
pluginsCustomConfigToMarkdownTables IdePlugins {..} = T.unlines
158+
$ map renderCfg
159+
$ filter (\(PluginCustomConfig _ params) -> not $ null params)
160+
$ map toPluginCustomConfig ipMap
161+
where
162+
toPluginCustomConfig :: PluginDescriptor ideState -> PluginCustomConfig
163+
toPluginCustomConfig PluginDescriptor {pluginConfigDescriptor = ConfigDescriptor {configCustomConfig = c}, pluginId = PluginId pId} =
164+
PluginCustomConfig { pcc'Name = pId, pcc'Params = toPluginCustomConfigParams c}
165+
toPluginCustomConfigParams :: CustomConfig -> [PluginCustomConfigParam]
166+
toPluginCustomConfigParams (CustomConfig p) = toPluginCustomConfigParams' p
167+
toPluginCustomConfigParams' :: Properties r -> [PluginCustomConfigParam]
168+
toPluginCustomConfigParams' EmptyProperties = []
169+
toPluginCustomConfigParams' (ConsProperties (keyNameProxy :: KeyNameProxy s) (k :: SPropertyKey k) (m :: MetaData t) xs) =
170+
toEntry (SomePropertyKeyWithMetaData k m) : toPluginCustomConfigParams' xs
171+
where
172+
toEntry :: SomePropertyKeyWithMetaData -> PluginCustomConfigParam
173+
toEntry (SomePropertyKeyWithMetaData SNumber MetaData {..}) =
174+
PluginCustomConfigParam {
175+
pccp'Name = T.pack $ symbolVal keyNameProxy,
176+
pccp'Description = description,
177+
pccp'Default = T.pack $ show defaultValue,
178+
pccp'EnumValues = []
179+
}
180+
toEntry (SomePropertyKeyWithMetaData SInteger MetaData {..}) =
181+
PluginCustomConfigParam {
182+
pccp'Name = T.pack $ symbolVal keyNameProxy,
183+
pccp'Description = description,
184+
pccp'Default = T.pack $ show defaultValue,
185+
pccp'EnumValues = []
186+
}
187+
toEntry (SomePropertyKeyWithMetaData SString MetaData {..}) =
188+
PluginCustomConfigParam {
189+
pccp'Name = T.pack $ symbolVal keyNameProxy,
190+
pccp'Description = description,
191+
pccp'Default = T.pack $ show defaultValue,
192+
pccp'EnumValues = []
193+
}
194+
toEntry (SomePropertyKeyWithMetaData SBoolean MetaData {..}) =
195+
PluginCustomConfigParam {
196+
pccp'Name = T.pack $ symbolVal keyNameProxy,
197+
pccp'Description = description,
198+
pccp'Default = T.pack $ show defaultValue,
199+
pccp'EnumValues = []
200+
}
201+
toEntry (SomePropertyKeyWithMetaData (SObject _) MetaData {..}) =
202+
PluginCustomConfigParam {
203+
pccp'Name = T.pack $ symbolVal keyNameProxy,
204+
pccp'Description = description,
205+
pccp'Default = "TODO: nested object", -- T.pack $ show defaultValue,
206+
pccp'EnumValues = []
207+
}
208+
toEntry (SomePropertyKeyWithMetaData (SArray _) MetaData {..}) =
209+
PluginCustomConfigParam {
210+
pccp'Name = T.pack $ symbolVal keyNameProxy,
211+
pccp'Description = description,
212+
pccp'Default = "TODO: Array values", -- T.pack $ show defaultValue,
213+
pccp'EnumValues = []
214+
}
215+
toEntry (SomePropertyKeyWithMetaData (SEnum _) EnumMetaData {..}) =
216+
PluginCustomConfigParam {
217+
pccp'Name = T.pack $ symbolVal keyNameProxy,
218+
pccp'Description = description,
219+
pccp'Default = T.pack $ show defaultValue,
220+
pccp'EnumValues = map (T.pack . show) enumValues
221+
}
222+
toEntry (SomePropertyKeyWithMetaData SProperties PropertiesMetaData {..}) =
223+
PluginCustomConfigParam {
224+
pccp'Name = T.pack $ symbolVal keyNameProxy,
225+
pccp'Description = description,
226+
pccp'Default = T.pack $ show defaultValue,
227+
pccp'EnumValues = []
228+
}
229+
renderCfg :: PluginCustomConfig -> T.Text
230+
renderCfg (PluginCustomConfig pId pccParams) =
231+
T.unlines (pluginHeader : tableHeader : rows pccParams)
232+
where
233+
pluginHeader = "## " <> pId
234+
tableHeader =
235+
"| Property | Description | Default | Allowed values |" <> "\n" <>
236+
"| --- | --- | --- | --- |"
237+
rows = map renderRow
238+
renderRow PluginCustomConfigParam {..} =
239+
"| `" <> pccp'Name <> "` | " <> pccp'Description <> " | `" <> pccp'Default <> "` | " <> renderEnum pccp'EnumValues <> " |"
240+
renderEnum [] = " &nbsp; " -- Placeholder to prevent missing cells
241+
renderEnum vs = "<ul> " <> (T.intercalate " " $ map (\x -> "<li><code>" <> x <> "</code></li>") vs) <> " </ul>"

hls-plugin-api/src/Ide/Plugin/Properties.hs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,10 @@ module Ide.Plugin.Properties
2121
MetaData (..),
2222
PropertyKey (..),
2323
SPropertyKey (..),
24+
SomePropertyKeyWithMetaData (..),
2425
KeyNameProxy (..),
2526
KeyNamePath (..),
26-
Properties,
27+
Properties(..),
2728
HasProperty,
2829
HasPropertyByPath,
2930
emptyProperties,
@@ -42,6 +43,8 @@ module Ide.Plugin.Properties
4243
usePropertyByPathEither,
4344
usePropertyByPath,
4445
(&),
46+
PluginCustomConfig(..),
47+
PluginCustomConfigParam(..),
4548
)
4649
where
4750

@@ -516,3 +519,15 @@ toVSCodeExtensionSchema' ps = case ps of
516519
]
517520
(SomePropertyKeyWithMetaData SProperties PropertiesMetaData {..}) ->
518521
map (first Just) $ toVSCodeExtensionSchema' childrenProperties
522+
523+
data PluginCustomConfig = PluginCustomConfig {
524+
pcc'Name :: T.Text,
525+
pcc'Params :: [PluginCustomConfigParam]
526+
}
527+
data PluginCustomConfigParam = PluginCustomConfigParam {
528+
pccp'Name :: T.Text,
529+
pccp'Description :: T.Text,
530+
pccp'Default :: T.Text,
531+
pccp'EnumValues :: [T.Text]
532+
}
533+

src/Ide/Arguments.hs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ data Arguments
3333
| BiosMode BiosAction
3434
| Ghcide GhcideArguments
3535
| VSCodeExtensionSchemaMode
36+
| PluginsCustomConfigMarkdownReferenceMode
3637
| DefaultConfigurationMode
3738
| PrintLibDir
3839

@@ -69,6 +70,7 @@ getArguments exeName plugins = execParser opts
6970
<|> hsubparser
7071
( command "vscode-extension-schema" extensionSchemaCommand
7172
<> command "generate-default-config" generateDefaultConfigCommand
73+
<> command "plugins-custom-config-markdown-reference" pluginsCustomConfigMarkdownReferenceCommand
7274
)
7375
<|> listPluginsParser
7476
<|> BiosMode <$> biosParser
@@ -86,6 +88,9 @@ getArguments exeName plugins = execParser opts
8688
generateDefaultConfigCommand =
8789
info (pure DefaultConfigurationMode)
8890
(fullDesc <> progDesc "Print config supported by the server with default values")
91+
pluginsCustomConfigMarkdownReferenceCommand =
92+
info (pure PluginsCustomConfigMarkdownReferenceMode)
93+
(fullDesc <> progDesc "Print markdown reference for plugins custom config")
8994

9095
printVersionParser :: String -> Parser PrintVersion
9196
printVersionParser exeName =

src/Ide/Main.hs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import Data.Function ((&))
1515
import Data.List (sortOn)
1616
import Data.Text (Text)
1717
import qualified Data.Text as T
18+
import qualified Data.Text.IO as T (putStrLn)
1819
import Data.Text.Lazy.Encoding (decodeUtf8)
1920
import qualified Data.Text.Lazy.IO as LT
2021
import Development.IDE.Core.Rules hiding (Log)
@@ -28,7 +29,8 @@ import HIE.Bios.Types hiding (Log)
2829
import qualified HIE.Bios.Types as HieBios
2930
import Ide.Arguments
3031
import Ide.Logger as G
31-
import Ide.Plugin.ConfigUtils (pluginsToDefaultConfig,
32+
import Ide.Plugin.ConfigUtils (pluginsCustomConfigToMarkdownTables,
33+
pluginsToDefaultConfig,
3234
pluginsToVSCodeExtensionSchema)
3335
import Ide.Types (IdePlugins, PluginId (PluginId),
3436
describePlugin, ipMap, pluginId)
@@ -103,6 +105,8 @@ defaultMain recorder args idePlugins = do
103105

104106
VSCodeExtensionSchemaMode -> do
105107
LT.putStrLn $ decodeUtf8 $ encodePrettySorted $ pluginsToVSCodeExtensionSchema idePlugins
108+
PluginsCustomConfigMarkdownReferenceMode -> do
109+
T.putStrLn $ pluginsCustomConfigToMarkdownTables idePlugins
106110
DefaultConfigurationMode -> do
107111
LT.putStrLn $ decodeUtf8 $ encodePrettySorted $ pluginsToDefaultConfig idePlugins
108112
PrintLibDir -> do

test/functional/ConfigSchema.hs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ tests = testGroup "generate schema"
3131
, goldenGitDiff "generate-default-config" (defaultConfigFp ghcVersion) $ do
3232
stdout <- readProcess hlsExeCommand ["generate-default-config"] ""
3333
pure $ BS.pack stdout
34+
, goldenGitDiff "plugins-custom-config-markdown-reference" (markdownReferenceFp ghcVersion) $ do
35+
stdout <- readProcess hlsExeCommand ["plugins-custom-config-markdown-reference"] ""
36+
pure $ BS.pack stdout
3437
]
3538

3639
vscodeSchemaFp :: GhcVersion -> FilePath
@@ -39,11 +42,17 @@ vscodeSchemaFp ghcVer = "test" </> "testdata" </> "schema" </> prettyGhcVersion
3942
defaultConfigFp :: GhcVersion -> FilePath
4043
defaultConfigFp ghcVer = "test" </> "testdata" </> "schema" </> prettyGhcVersion ghcVer </> generateDefaultConfigJson
4144

45+
markdownReferenceFp :: GhcVersion -> FilePath
46+
markdownReferenceFp ghcVer = "test" </> "testdata" </> "schema" </> prettyGhcVersion ghcVer </> markdownReferenceMd
47+
4248
vscodeSchemaJson :: FilePath
4349
vscodeSchemaJson = "vscode-extension-schema.golden.json"
4450

4551
generateDefaultConfigJson :: FilePath
4652
generateDefaultConfigJson = "default-config.golden.json"
4753

54+
markdownReferenceMd :: FilePath
55+
markdownReferenceMd = "markdown-reference.md"
56+
4857
prettyGhcVersion :: GhcVersion -> String
4958
prettyGhcVersion ghcVer = map toLower (show ghcVer)

0 commit comments

Comments
 (0)