Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate custom parameters' documentation for plugins #4414

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 97 additions & 1 deletion hls-plugin-api/src/Ide/Plugin/ConfigUtils.hs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,15 @@ import qualified Data.Dependent.Sum as DSum
import Data.List.Extra (nubOrd)
import Data.String (IsString (fromString))
import qualified Data.Text as T
import GHC.TypeLits (symbolVal)
import Ide.Plugin.Config
import Ide.Plugin.Properties (toDefaultJSON,
import Ide.Plugin.Properties (KeyNameProxy, MetaData (..),
PluginCustomConfig (..),
PluginCustomConfigParam (..),
Properties (..),
SPropertyKey (..),
SomePropertyKeyWithMetaData (..),
toDefaultJSON,
toVSCodeExtensionSchema)
import Ide.Types
import Language.LSP.Protocol.Message
Expand Down Expand Up @@ -139,3 +146,92 @@ pluginsToVSCodeExtensionSchema IdePlugins {..} = A.object $ mconcat $ singlePlug
]
withIdPrefix x = "haskell.plugin." <> pId <> "." <> x
toKey' = fromString . T.unpack . withIdPrefix


-- | Generates markdown tables for custom config
pluginsCustomConfigToMarkdownTables :: IdePlugins a -> T.Text
pluginsCustomConfigToMarkdownTables IdePlugins {..} = T.unlines
$ map renderCfg
$ filter (\(PluginCustomConfig _ params) -> not $ null params)
$ map toPluginCustomConfig ipMap
where
toPluginCustomConfig :: PluginDescriptor ideState -> PluginCustomConfig
toPluginCustomConfig PluginDescriptor {pluginConfigDescriptor = ConfigDescriptor {configCustomConfig = c}, pluginId = PluginId pId} =
PluginCustomConfig { pcc'Name = pId, pcc'Params = toPluginCustomConfigParams c}
toPluginCustomConfigParams :: CustomConfig -> [PluginCustomConfigParam]
toPluginCustomConfigParams (CustomConfig p) = toPluginCustomConfigParams' p
toPluginCustomConfigParams' :: Properties r -> [PluginCustomConfigParam]
toPluginCustomConfigParams' EmptyProperties = []
toPluginCustomConfigParams' (ConsProperties (keyNameProxy :: KeyNameProxy s) (k :: SPropertyKey k) (m :: MetaData t) xs) =
toEntry (SomePropertyKeyWithMetaData k m) : toPluginCustomConfigParams' xs
where
toEntry :: SomePropertyKeyWithMetaData -> PluginCustomConfigParam
toEntry (SomePropertyKeyWithMetaData SNumber MetaData {..}) =
PluginCustomConfigParam {
pccp'Name = T.pack $ symbolVal keyNameProxy,
pccp'Description = description,
pccp'Default = T.pack $ show defaultValue,
pccp'EnumValues = []
}
toEntry (SomePropertyKeyWithMetaData SInteger MetaData {..}) =
PluginCustomConfigParam {
pccp'Name = T.pack $ symbolVal keyNameProxy,
pccp'Description = description,
pccp'Default = T.pack $ show defaultValue,
pccp'EnumValues = []
}
toEntry (SomePropertyKeyWithMetaData SString MetaData {..}) =
PluginCustomConfigParam {
pccp'Name = T.pack $ symbolVal keyNameProxy,
pccp'Description = description,
pccp'Default = T.pack $ show defaultValue,
pccp'EnumValues = []
}
toEntry (SomePropertyKeyWithMetaData SBoolean MetaData {..}) =
PluginCustomConfigParam {
pccp'Name = T.pack $ symbolVal keyNameProxy,
pccp'Description = description,
pccp'Default = T.pack $ show defaultValue,
pccp'EnumValues = []
}
toEntry (SomePropertyKeyWithMetaData (SObject _) MetaData {..}) =
PluginCustomConfigParam {
pccp'Name = T.pack $ symbolVal keyNameProxy,
pccp'Description = description,
pccp'Default = "TODO: nested object", -- T.pack $ show defaultValue,
pccp'EnumValues = []
}
toEntry (SomePropertyKeyWithMetaData (SArray _) MetaData {..}) =
PluginCustomConfigParam {
pccp'Name = T.pack $ symbolVal keyNameProxy,
pccp'Description = description,
pccp'Default = "TODO: Array values", -- T.pack $ show defaultValue,
pccp'EnumValues = []
}
toEntry (SomePropertyKeyWithMetaData (SEnum _) EnumMetaData {..}) =
PluginCustomConfigParam {
pccp'Name = T.pack $ symbolVal keyNameProxy,
pccp'Description = description,
pccp'Default = T.pack $ show defaultValue,
pccp'EnumValues = map (T.pack . show) enumValues
}
toEntry (SomePropertyKeyWithMetaData SProperties PropertiesMetaData {..}) =
PluginCustomConfigParam {
pccp'Name = T.pack $ symbolVal keyNameProxy,
pccp'Description = description,
pccp'Default = T.pack $ show defaultValue,
pccp'EnumValues = []
}
renderCfg :: PluginCustomConfig -> T.Text
renderCfg (PluginCustomConfig pId pccParams) =
T.unlines (pluginHeader : tableHeader : rows pccParams)
where
pluginHeader = "## " <> pId
tableHeader =
"| Property | Description | Default | Allowed values |" <> "\n" <>
"| --- | --- | --- | --- |"
rows = map renderRow
renderRow PluginCustomConfigParam {..} =
"| `" <> pccp'Name <> "` | " <> pccp'Description <> " | `" <> pccp'Default <> "` | " <> renderEnum pccp'EnumValues <> " |"
renderEnum [] = " &nbsp; " -- Placeholder to prevent missing cells
renderEnum vs = "<ul> " <> (T.intercalate " " $ map (\x -> "<li><code>" <> x <> "</code></li>") vs) <> " </ul>"
17 changes: 16 additions & 1 deletion hls-plugin-api/src/Ide/Plugin/Properties.hs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ module Ide.Plugin.Properties
MetaData (..),
PropertyKey (..),
SPropertyKey (..),
SomePropertyKeyWithMetaData (..),
KeyNameProxy (..),
KeyNamePath (..),
Properties,
Properties(..),
HasProperty,
HasPropertyByPath,
emptyProperties,
Expand All @@ -42,6 +43,8 @@ module Ide.Plugin.Properties
usePropertyByPathEither,
usePropertyByPath,
(&),
PluginCustomConfig(..),
PluginCustomConfigParam(..),
)
where

Expand Down Expand Up @@ -516,3 +519,15 @@ toVSCodeExtensionSchema' ps = case ps of
]
(SomePropertyKeyWithMetaData SProperties PropertiesMetaData {..}) ->
map (first Just) $ toVSCodeExtensionSchema' childrenProperties

data PluginCustomConfig = PluginCustomConfig {
pcc'Name :: T.Text,
pcc'Params :: [PluginCustomConfigParam]
}
data PluginCustomConfigParam = PluginCustomConfigParam {
pccp'Name :: T.Text,
pccp'Description :: T.Text,
pccp'Default :: T.Text,
pccp'EnumValues :: [T.Text]
}

5 changes: 5 additions & 0 deletions src/Ide/Arguments.hs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ data Arguments
| BiosMode BiosAction
| Ghcide GhcideArguments
| VSCodeExtensionSchemaMode
| PluginsCustomConfigMarkdownReferenceMode
| DefaultConfigurationMode
| PrintLibDir

Expand Down Expand Up @@ -69,6 +70,7 @@ getArguments exeName plugins = execParser opts
<|> hsubparser
( command "vscode-extension-schema" extensionSchemaCommand
<> command "generate-default-config" generateDefaultConfigCommand
<> command "plugins-custom-config-markdown-reference" pluginsCustomConfigMarkdownReferenceCommand
)
<|> listPluginsParser
<|> BiosMode <$> biosParser
Expand All @@ -86,6 +88,9 @@ getArguments exeName plugins = execParser opts
generateDefaultConfigCommand =
info (pure DefaultConfigurationMode)
(fullDesc <> progDesc "Print config supported by the server with default values")
pluginsCustomConfigMarkdownReferenceCommand =
info (pure PluginsCustomConfigMarkdownReferenceMode)
(fullDesc <> progDesc "Print markdown reference for plugins custom config")

printVersionParser :: String -> Parser PrintVersion
printVersionParser exeName =
Expand Down
6 changes: 5 additions & 1 deletion src/Ide/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import Data.Function ((&))
import Data.List (sortOn)
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.IO as T (putStrLn)
import Data.Text.Lazy.Encoding (decodeUtf8)
import qualified Data.Text.Lazy.IO as LT
import Development.IDE.Core.Rules hiding (Log)
Expand All @@ -28,7 +29,8 @@ import HIE.Bios.Types hiding (Log)
import qualified HIE.Bios.Types as HieBios
import Ide.Arguments
import Ide.Logger as G
import Ide.Plugin.ConfigUtils (pluginsToDefaultConfig,
import Ide.Plugin.ConfigUtils (pluginsCustomConfigToMarkdownTables,
pluginsToDefaultConfig,
pluginsToVSCodeExtensionSchema)
import Ide.Types (IdePlugins, PluginId (PluginId),
describePlugin, ipMap, pluginId)
Expand Down Expand Up @@ -103,6 +105,8 @@ defaultMain recorder args idePlugins = do

VSCodeExtensionSchemaMode -> do
LT.putStrLn $ decodeUtf8 $ encodePrettySorted $ pluginsToVSCodeExtensionSchema idePlugins
PluginsCustomConfigMarkdownReferenceMode -> do
T.putStrLn $ pluginsCustomConfigToMarkdownTables idePlugins
DefaultConfigurationMode -> do
LT.putStrLn $ decodeUtf8 $ encodePrettySorted $ pluginsToDefaultConfig idePlugins
PrintLibDir -> do
Expand Down
9 changes: 9 additions & 0 deletions test/functional/ConfigSchema.hs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ tests = testGroup "generate schema"
, goldenGitDiff "generate-default-config" (defaultConfigFp ghcVersion) $ do
stdout <- readProcess hlsExeCommand ["generate-default-config"] ""
pure $ BS.pack stdout
, goldenGitDiff "plugins-custom-config-markdown-reference" (markdownReferenceFp ghcVersion) $ do
stdout <- readProcess hlsExeCommand ["plugins-custom-config-markdown-reference"] ""
pure $ BS.pack stdout
]

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

markdownReferenceFp :: GhcVersion -> FilePath
markdownReferenceFp ghcVer = "test" </> "testdata" </> "schema" </> prettyGhcVersion ghcVer </> markdownReferenceMd

vscodeSchemaJson :: FilePath
vscodeSchemaJson = "vscode-extension-schema.golden.json"

generateDefaultConfigJson :: FilePath
generateDefaultConfigJson = "default-config.golden.json"

markdownReferenceMd :: FilePath
markdownReferenceMd = "markdown-reference.md"

prettyGhcVersion :: GhcVersion -> String
prettyGhcVersion ghcVer = map toLower (show ghcVer)
Loading
Loading