Add cabal-gild as a cabal file formatter plugin (#4101)

* Add cabal-gild as a cabal file formatter plugin

* Add support for multiple cabal formatters

In addition, allow different cabal file formatter provider to specify an
explicit file path, instead of searching only on $PATH.

* Fix cabal formatter test flags
This commit is contained in:
fendor 2024-03-11 18:23:29 +01:00 committed by GitHub
parent 03d418c92c
commit 16912ccebd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
26 changed files with 483 additions and 19 deletions

View File

@ -230,6 +230,10 @@ jobs:
name: Test hls-cabal-fmt-plugin test suite
run: cabal test hls-cabal-fmt-plugin-tests --flag=isolateCabalfmtTests || cabal test hls-cabal-fmt-plugin-tests --flag=isolateCabalfmtTests
- if: matrix.test
name: Test hls-cabal-gild-plugin test suite
run: cabal test hls-cabal-gild-plugin-tests --flag=isolateCabalGildTests || cabal test hls-cabal-gild-plugin-tests --flag=isolateCabalGildTests
- if: matrix.test
name: Test hls-cabal-plugin test suite
run: cabal test hls-cabal-plugin-tests || cabal test hls-cabal-plugin-tests

View File

@ -14,10 +14,11 @@
# Plugins
/plugins/hls-alternate-number-format-plugin @drsooch
/plugins/hls-cabal-fmt-plugin @VeryMilkyJoe @fendor
/plugins/hls-cabal-gild-plugin @fendor
/plugins/hls-cabal-plugin @fendor
/plugins/hls-call-hierarchy-plugin @July541
/plugins/hls-change-type-signature-plugin
/plugins/hls-class-plugin
/plugins/hls-class-plugin
/plugins/hls-code-range-plugin @kokobd
/plugins/hls-eval-plugin
/plugins/hls-explicit-fixity-plugin
@ -34,7 +35,7 @@
/plugins/hls-pragmas-plugin @eddiemundo
/plugins/hls-qualify-imported-names-plugin @eddiemundo
/plugins/hls-refactor-plugin @santiweight
/plugins/hls-rename-plugin
/plugins/hls-rename-plugin
/plugins/hls-retrie-plugin @pepeiborra
/plugins/hls-semantic-tokens-plugin @soulomoon
/plugins/hls-splice-plugin @konn
@ -49,7 +50,7 @@
/docs @michaelpj
# CI
/.circleci
/.circleci
/.github @michaelpj @fendor
# Build

View File

@ -146,6 +146,58 @@ test-suite hls-cabal-fmt-plugin-tests
if flag(isolateCabalfmtTests)
build-tool-depends: cabal-fmt:cabal-fmt ^>=0.1.6
cpp-options: -Dhls_isolate_cabalfmt_tests
-----------------------------
-- cabal-gild plugin
-----------------------------
flag cabalgild
description: Enable cabal-gild plugin
default: True
manual: True
common cabalgild
if flag(cabalgild)
build-depends: haskell-language-server:hls-cabal-gild-plugin
cpp-options: -Dhls_cabalgild
flag isolateCabalGildTests
description: Should tests search for 'cabal-gild' on the $PATH or shall we install it via build-tool-depends?
-- By default, search on the PATH
default: False
manual: True
library hls-cabal-gild-plugin
import: defaults, pedantic, warnings
exposed-modules: Ide.Plugin.CabalGild
hs-source-dirs: plugins/hls-cabal-gild-plugin/src
build-depends:
, base >=4.12 && <5
, directory
, filepath
, ghcide == 2.7.0.0
, hls-plugin-api == 2.7.0.0
, lsp-types
, text
, mtl
, process-extras
test-suite hls-cabal-gild-plugin-tests
import: defaults, pedantic, test-defaults, warnings
type: exitcode-stdio-1.0
hs-source-dirs: plugins/hls-cabal-gild-plugin/test
main-is: Main.hs
build-depends:
, base
, directory
, filepath
, haskell-language-server:hls-cabal-gild-plugin
, hls-test-utils == 2.7.0.0
if flag(isolateCabalGildTests)
build-tool-depends: cabal-gild:cabal-gild ^>=1.1
cpp-options: -Dhls_isolate_cabalgild_tests
-----------------------------
-- cabal plugin
@ -1699,6 +1751,7 @@ library
, cabal
, callHierarchy
, cabalfmt
, cabalgild
, changeTypeSignature
, class
, eval

View File

@ -178,6 +178,7 @@ instance ToJSON Config where
object [ "checkParents" .= checkParents
, "checkProject" .= checkProject
, "formattingProvider" .= formattingProvider
, "cabalFormattingProvider" .= cabalFormattingProvider
, "maxCompletions" .= maxCompletions
, "plugin" .= Map.mapKeysMonotonic (\(PluginId p) -> p) plugins
]
@ -189,7 +190,8 @@ instance Default Config where
, formattingProvider = "ormolu"
-- , formattingProvider = "floskell"
-- , formattingProvider = "stylish-haskell"
, cabalFormattingProvider = "cabal-fmt"
, cabalFormattingProvider = "cabal-gild"
-- , cabalFormattingProvider = "cabal-fmt"
-- this string value needs to kept in sync with the value provided in HlsPlugins
, maxCompletions = 40
, plugins = mempty

View File

@ -1,4 +1,6 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedLabels #-}
{-# LANGUAGE OverloadedStrings #-}
module Ide.Plugin.CabalFmt where
@ -9,6 +11,7 @@ import Control.Monad.IO.Class
import qualified Data.Text as T
import Development.IDE hiding (pluginHandlers)
import Ide.Plugin.Error (PluginError (PluginInternalError, PluginInvalidParams))
import Ide.Plugin.Properties
import Ide.PluginUtils
import Ide.Types
import qualified Language.LSP.Protocol.Lens as L
@ -24,7 +27,7 @@ data Log
= LogProcessInvocationFailure Int
| LogReadCreateProcessInfo T.Text [String]
| LogInvalidInvocationInfo
| LogCabalFmtNotFound
| LogFormatterBinNotFound FilePath
deriving (Show)
instance Pretty Log where
@ -35,29 +38,39 @@ instance Pretty Log where
["Invocation of cabal-fmt with arguments" <+> pretty args]
++ ["failed with standard error:" <+> pretty stdErrorOut | not (T.null stdErrorOut)]
LogInvalidInvocationInfo -> "Invocation of cabal-fmt with range was called but is not supported."
LogCabalFmtNotFound -> "Couldn't find executable 'cabal-fmt'"
LogFormatterBinNotFound fp -> "Couldn't find formatter executable 'cabal-fmt' at:" <+> pretty fp
descriptor :: Recorder (WithPriority Log) -> PluginId -> PluginDescriptor IdeState
descriptor recorder plId =
(defaultCabalPluginDescriptor plId "Provides formatting of cabal files with cabal-fmt")
{ pluginHandlers = mkFormattingHandlers (provider recorder)
{ pluginHandlers = mkFormattingHandlers (provider recorder plId)
, pluginConfigDescriptor = defaultConfigDescriptor{configCustomConfig = mkCustomConfig properties}
}
properties :: Properties '[ 'PropertyKey "path" 'TString]
properties =
emptyProperties
& defineStringProperty
#path
"Set path to 'cabal-fmt' executable"
"cabal-fmt"
-- | Formatter provider of cabal fmt.
-- Formats the given source in either a given Range or the whole Document.
-- If the provider fails an error is returned that can be displayed to the user.
provider :: Recorder (WithPriority Log) -> FormattingHandler IdeState
provider recorder _ _ (FormatRange _) _ _ _ = do
provider :: Recorder (WithPriority Log) -> PluginId -> FormattingHandler IdeState
provider recorder _ _ _ (FormatRange _) _ _ _ = do
logWith recorder Info LogInvalidInvocationInfo
throwError $ PluginInvalidParams "You cannot format a text-range using cabal-fmt."
provider recorder _ide _ FormatText contents nfp opts = do
provider recorder plId ideState _ FormatText contents nfp opts = do
let cabalFmtArgs = [ "--indent", show tabularSize]
x <- liftIO $ findExecutable "cabal-fmt"
cabalFmtExePath <- fmap T.unpack $ liftIO $ runAction "cabal-gild" ideState $ usePropertyAction #path plId properties
x <- liftIO $ findExecutable cabalFmtExePath
case x of
Just _ -> do
(exitCode, out, err) <-
liftIO $ Process.readCreateProcessWithExitCode
( proc "cabal-fmt" cabalFmtArgs
( proc cabalFmtExePath cabalFmtArgs
)
{ cwd = Just $ takeDirectory fp
}
@ -71,8 +84,8 @@ provider recorder _ide _ FormatText contents nfp opts = do
let fmtDiff = makeDiffTextEdit contents out
pure $ InL fmtDiff
Nothing -> do
log Error LogCabalFmtNotFound
throwError (PluginInternalError "No installation of cabal-fmt could be found. Please install it into your global environment.")
log Error $ LogFormatterBinNotFound cabalFmtExePath
throwError (PluginInternalError "No installation of cabal-gild could be found. Please install it globally, or provide the full path to the executable")
where
fp = fromNormalizedFilePath nfp
tabularSize = opts ^. L.tabSize

View File

@ -12,7 +12,7 @@ import Test.Hls
data CabalFmtFound = Found | NotFound
isTestIsolated :: Bool
#if isolateTests
#if hls_isolate_cabalfmt_tests
isTestIsolated = True
#else
isTestIsolated = False
@ -21,7 +21,7 @@ isTestIsolated = False
isCabalFmtFound :: IO CabalFmtFound
isCabalFmtFound = case isTestIsolated of
True -> pure Found
False-> do
False -> do
cabalFmt <- findExecutable "cabal-fmt"
pure $ maybe NotFound (const Found) cabalFmt
@ -51,7 +51,7 @@ cabalFmtGolden :: CabalFmtFound -> TestName -> FilePath -> FilePath -> (TextDocu
cabalFmtGolden NotFound title _ _ _ =
testCase title $
assertFailure $ "Couldn't find cabal-fmt on PATH or this is not an isolated run. "
<> "Use cabal flag 'isolateTests' to make it isolated or install cabal-fmt locally."
<> "Use cabal flag 'isolateCabalFmtTests' to make it isolated or install cabal-fmt locally."
cabalFmtGolden Found title path desc act = goldenWithCabalDocFormatter def cabalFmtPlugin "cabal-fmt" conf title testDataDir path desc "cabal" act
where
conf = def

View File

@ -0,0 +1,92 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedLabels #-}
{-# LANGUAGE OverloadedStrings #-}
module Ide.Plugin.CabalGild where
import Control.Monad.Except (throwError)
import Control.Monad.IO.Class
import qualified Data.Text as T
import Development.IDE hiding (pluginHandlers)
import Ide.Plugin.Error (PluginError (PluginInternalError, PluginInvalidParams))
import Ide.Plugin.Properties
import Ide.PluginUtils
import Ide.Types
import Language.LSP.Protocol.Types
import Prelude hiding (log)
import System.Directory
import System.Exit
import System.FilePath
import System.Process.ListLike
import qualified System.Process.Text as Process
data Log
= LogProcessInvocationFailure Int T.Text
| LogReadCreateProcessInfo [String]
| LogInvalidInvocationInfo
| LogFormatterBinNotFound FilePath
deriving (Show)
instance Pretty Log where
pretty = \case
LogProcessInvocationFailure exitCode err ->
vcat
[ "Invocation of cabal-gild failed with code" <+> pretty exitCode
, "Stderr:" <+> pretty err
]
LogReadCreateProcessInfo args ->
"Formatter invocation: cabal-gild " <+> pretty args
LogInvalidInvocationInfo -> "Invocation of cabal-gild with range was called but is not supported."
LogFormatterBinNotFound fp -> "Couldn't find formatter executable 'cabal-gild' at:" <+> pretty fp
descriptor :: Recorder (WithPriority Log) -> PluginId -> PluginDescriptor IdeState
descriptor recorder plId =
(defaultCabalPluginDescriptor plId "Provides formatting of cabal files with cabal-gild")
{ pluginHandlers = mkFormattingHandlers (provider recorder plId)
, pluginConfigDescriptor = defaultConfigDescriptor{configCustomConfig = mkCustomConfig properties}
}
properties :: Properties '[ 'PropertyKey "path" 'TString]
properties =
emptyProperties
& defineStringProperty
#path
"Set path to 'cabal-gild' executable"
"cabal-gild"
-- | Formatter provider of cabal gild.
-- Formats the given source in either a given Range or the whole Document.
-- If the provider fails an error is returned that can be displayed to the user.
provider :: Recorder (WithPriority Log) -> PluginId -> FormattingHandler IdeState
provider recorder _ _ _ (FormatRange _) _ _ _ = do
logWith recorder Info LogInvalidInvocationInfo
throwError $ PluginInvalidParams "You cannot format a text-range using cabal-gild."
provider recorder plId ideState _ FormatText contents nfp _ = do
let cabalGildArgs = ["--stdin=" <> fp, "--input=-"] -- < Read from stdin
cabalGildExePath <- fmap T.unpack $ liftIO $ runAction "cabal-gild" ideState $ usePropertyAction #path plId properties
x <- liftIO $ findExecutable cabalGildExePath
case x of
Just _ -> do
log Debug $ LogReadCreateProcessInfo cabalGildArgs
(exitCode, out, err) <-
liftIO $ Process.readCreateProcessWithExitCode
( proc cabalGildExePath cabalGildArgs
)
{ cwd = Just $ takeDirectory fp
}
contents
case exitCode of
ExitFailure code -> do
log Error $ LogProcessInvocationFailure code err
throwError (PluginInternalError "Failed to invoke cabal-gild")
ExitSuccess -> do
let fmtDiff = makeDiffTextEdit contents out
pure $ InL fmtDiff
Nothing -> do
log Error $ LogFormatterBinNotFound cabalGildExePath
throwError (PluginInternalError "No installation of cabal-gild could be found. Please install it globally, or provide the full path to the executable.")
where
fp = fromNormalizedFilePath nfp
log = logWith recorder

View File

@ -0,0 +1,58 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
module Main
( main
) where
import qualified Ide.Plugin.CabalGild as CabalGild
import System.Directory (findExecutable)
import System.FilePath
import Test.Hls
data CabalGildFound = Found | NotFound
isTestIsolated :: Bool
#if hls_isolate_cabalgild_tests
isTestIsolated = True
#else
isTestIsolated = False
#endif
isCabalFmtFound :: IO CabalGildFound
isCabalFmtFound = case isTestIsolated of
True -> pure Found
False -> do
cabalGild <- findExecutable "cabal-gild"
pure $ maybe NotFound (const Found) cabalGild
main :: IO ()
main = do
foundCabalFmt <- isCabalFmtFound
defaultTestRunner (tests foundCabalFmt)
cabalGildPlugin :: PluginTestDescriptor CabalGild.Log
cabalGildPlugin = mkPluginTestDescriptor CabalGild.descriptor "cabal-gild"
tests :: CabalGildFound -> TestTree
tests found = testGroup "cabal-gild"
[ cabalGildGolden found "formats a simple document" "simple_testdata" "formatted_document" $ \doc -> do
formatDoc doc (FormattingOptions 2 True Nothing Nothing Nothing)
, cabalGildGolden found "formats a document with expand:src comment" "commented_testdata" "formatted_document" $ \doc -> do
formatDoc doc (FormattingOptions 2 True Nothing Nothing Nothing)
, cabalGildGolden found "formats a document with lib information" "lib_testdata" "formatted_document" $ \doc -> do
formatDoc doc (FormattingOptions 10 True Nothing Nothing Nothing)
]
cabalGildGolden :: CabalGildFound -> TestName -> FilePath -> FilePath -> (TextDocumentIdentifier -> Session ()) -> TestTree
cabalGildGolden NotFound title _ _ _ =
testCase title $
assertFailure $ "Couldn't find cabal-gild on PATH or this is not an isolated run. "
<> "Use cabal flag 'isolateCabalGildTests' to make it isolated or install cabal-gild locally."
cabalGildGolden Found title path desc act = goldenWithCabalDocFormatter def cabalGildPlugin "cabal-gild" conf title testDataDir path desc "cabal" act
where
conf = def
testDataDir :: FilePath
testDataDir = "plugins" </> "hls-cabal-gild-plugin" </> "test" </> "testdata"

View File

@ -0,0 +1,12 @@
cabal-version: 2.4
name: testdata
version: 0.1.0.0
author: Banana
extra-source-files: CHANGELOG.md
library
-- cabal-gild: discover src
exposed-modules: MyLib
build-depends: base ^>=4.14.1.0
hs-source-dirs: src
default-language: Haskell2010

View File

@ -0,0 +1,15 @@
cabal-version: 2.4
name: testdata
version: 0.1.0.0
author: Banana
extra-source-files: CHANGELOG.md
library
-- cabal-gild: discover src
exposed-modules:
MyLib
MyOtherLib
build-depends: base ^>=4.14.1.0
hs-source-dirs: src
default-language: Haskell2010

View File

@ -0,0 +1,3 @@
cradle:
direct:
arguments: []

View File

@ -0,0 +1,19 @@
cabal-version: 2.4
name: testdata
version: 0.1.0.0
author: Gregg
extra-source-files: CHANGELOG.md
library
exposed-modules: MyLib
build-depends: base ^>=4.14.1.0
hs-source-dirs: src
default-language: Haskell2010
executable testdata
main-is: Main.hs
build-depends:
base ^>=4.14.1.0,testdata
hs-source-dirs: app
default-language:
Haskell2010

View File

@ -0,0 +1,20 @@
cabal-version: 2.4
name: testdata
version: 0.1.0.0
author: Gregg
extra-source-files: CHANGELOG.md
library
exposed-modules: MyLib
build-depends: base ^>=4.14.1.0
hs-source-dirs: src
default-language: Haskell2010
executable testdata
main-is: Main.hs
build-depends:
base ^>=4.14.1.0,
testdata,
hs-source-dirs: app
default-language: Haskell2010

View File

@ -0,0 +1,36 @@
cabal-version: 2.4
name: testdata
version: 0.1.0.0
-- A short (one-line) description of the package.
-- synopsis:
-- A longer description of the package.
-- description:
-- A URL where users can report bugs.
-- bug-reports:
-- The license under which the package is released.
-- license:
author: Milky
-- An email address to which users can send suggestions, bug reports, and patches.
-- maintainer:
-- A copyright notice.
-- copyright:
-- category:
extra-source-files: CHANGELOG.md
executable testdata
main-is: Main.hs
-- Modules included in this executable, other than Main.
-- other-modules:
-- LANGUAGE extensions used by modules in this package.
-- other-extensions:
build-depends: base ^>=4.14.1.0
hs-source-dirs: app
default-language: Haskell2010

View File

@ -0,0 +1,28 @@
cabal-version: 2.4
name: testdata
version: 0.1.0.0
-- A short (one-line) description of the package.
-- synopsis:
-- A longer description of the package.
-- description:
-- A URL where users can report bugs.
-- bug-reports:
-- The license under which the package is released.
-- license:
author: Milky
-- An email address to which users can send suggestions, bug reports, and patches.
-- maintainer:
-- A copyright notice.
-- copyright:
-- category:
extra-source-files: CHANGELOG.md
executable testdata
main-is: Main.hs
-- Modules included in this executable, other than Main.
-- other-modules:
-- LANGUAGE extensions used by modules in this package.
-- other-extensions:
build-depends: base ^>=4.14.1.0
hs-source-dirs: app
default-language: Haskell2010

View File

@ -0,0 +1,4 @@
module MyLib (someFunc) where
someFunc :: IO ()
someFunc = putStrLn "someFunc"

View File

@ -0,0 +1,3 @@
module MyOtherLib where
bar = 2

View File

@ -111,6 +111,10 @@ import qualified Ide.Plugin.Fourmolu as Fourmolu
import qualified Ide.Plugin.CabalFmt as CabalFmt
#endif
#if hls_cabalgild
import qualified Ide.Plugin.CabalGild as CabalGild
#endif
#if hls_ormolu
import qualified Ide.Plugin.Ormolu as Ormolu
#endif
@ -161,11 +165,16 @@ idePlugins recorder = pluginDescToIdePlugins allPlugins
let pId = "fourmolu" in Fourmolu.descriptor (pluginRecorder pId) pId:
#endif
#if hls_cabalfmt
-- this pId needs to be kept in sync with the hardcoded
-- cabalFormattingProvider in the Default Config
let pId = "cabal-fmt" in CabalFmt.descriptor (pluginRecorder pId) pId:
#endif
#if hls_cabalgild
-- this pId needs to be kept in sync with the hardcoded
-- cabalFormattingProvider in the Default Config
let pId = "cabal-gild" in CabalGild.descriptor (pluginRecorder pId) pId:
#endif
#if hls_ormolu
-- this pId needs to be kept in sync with the hardcoded
-- haskellFormattingProvider in the Default Config
let pId = "ormolu" in Ormolu.descriptor (pluginRecorder pId) pId :
#endif
#if hls_stylishHaskell

View File

@ -1,4 +1,5 @@
{
"cabalFormattingProvider": "cabal-gild",
"checkParents": "CheckOnSave",
"checkProject": true,
"formattingProvider": "ormolu",
@ -12,6 +13,16 @@
"completionOn": true,
"diagnosticsOn": true
},
"cabal-fmt": {
"config": {
"path": "cabal-fmt"
}
},
"cabal-gild": {
"config": {
"path": "cabal-gild"
}
},
"callHierarchy": {
"globalOn": true
},

View File

@ -5,6 +5,18 @@
"scope": "resource",
"type": "boolean"
},
"haskell.plugin.cabal-fmt.config.path": {
"default": "cabal-fmt",
"markdownDescription": "Set path to 'cabal-fmt' executable",
"scope": "resource",
"type": "string"
},
"haskell.plugin.cabal-gild.config.path": {
"default": "cabal-gild",
"markdownDescription": "Set path to 'cabal-gild' executable",
"scope": "resource",
"type": "string"
},
"haskell.plugin.cabal.codeActionsOn": {
"default": true,
"description": "Enables cabal code actions",

View File

@ -1,4 +1,5 @@
{
"cabalFormattingProvider": "cabal-gild",
"checkParents": "CheckOnSave",
"checkProject": true,
"formattingProvider": "ormolu",
@ -12,6 +13,16 @@
"completionOn": true,
"diagnosticsOn": true
},
"cabal-fmt": {
"config": {
"path": "cabal-fmt"
}
},
"cabal-gild": {
"config": {
"path": "cabal-gild"
}
},
"callHierarchy": {
"globalOn": true
},

View File

@ -5,6 +5,18 @@
"scope": "resource",
"type": "boolean"
},
"haskell.plugin.cabal-fmt.config.path": {
"default": "cabal-fmt",
"markdownDescription": "Set path to 'cabal-fmt' executable",
"scope": "resource",
"type": "string"
},
"haskell.plugin.cabal-gild.config.path": {
"default": "cabal-gild",
"markdownDescription": "Set path to 'cabal-gild' executable",
"scope": "resource",
"type": "string"
},
"haskell.plugin.cabal.codeActionsOn": {
"default": true,
"description": "Enables cabal code actions",

View File

@ -1,4 +1,5 @@
{
"cabalFormattingProvider": "cabal-gild",
"checkParents": "CheckOnSave",
"checkProject": true,
"formattingProvider": "ormolu",
@ -12,6 +13,16 @@
"completionOn": true,
"diagnosticsOn": true
},
"cabal-fmt": {
"config": {
"path": "cabal-fmt"
}
},
"cabal-gild": {
"config": {
"path": "cabal-gild"
}
},
"callHierarchy": {
"globalOn": true
},

View File

@ -5,6 +5,18 @@
"scope": "resource",
"type": "boolean"
},
"haskell.plugin.cabal-fmt.config.path": {
"default": "cabal-fmt",
"markdownDescription": "Set path to 'cabal-fmt' executable",
"scope": "resource",
"type": "string"
},
"haskell.plugin.cabal-gild.config.path": {
"default": "cabal-gild",
"markdownDescription": "Set path to 'cabal-gild' executable",
"scope": "resource",
"type": "string"
},
"haskell.plugin.cabal.codeActionsOn": {
"default": true,
"description": "Enables cabal code actions",

View File

@ -1,4 +1,5 @@
{
"cabalFormattingProvider": "cabal-gild",
"checkParents": "CheckOnSave",
"checkProject": true,
"formattingProvider": "ormolu",
@ -12,6 +13,16 @@
"completionOn": true,
"diagnosticsOn": true
},
"cabal-fmt": {
"config": {
"path": "cabal-fmt"
}
},
"cabal-gild": {
"config": {
"path": "cabal-gild"
}
},
"callHierarchy": {
"globalOn": true
},

View File

@ -5,6 +5,18 @@
"scope": "resource",
"type": "boolean"
},
"haskell.plugin.cabal-fmt.config.path": {
"default": "cabal-fmt",
"markdownDescription": "Set path to 'cabal-fmt' executable",
"scope": "resource",
"type": "string"
},
"haskell.plugin.cabal-gild.config.path": {
"default": "cabal-gild",
"markdownDescription": "Set path to 'cabal-gild' executable",
"scope": "resource",
"type": "string"
},
"haskell.plugin.cabal.codeActionsOn": {
"default": true,
"description": "Enables cabal code actions",