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

Add formatting plugin for cabal files which uses cabal-fmt #2047

Merged
merged 4 commits into from
Nov 11, 2022
Merged
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
5 changes: 5 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,11 @@ jobs:
name: Test hls-explicit-record-fields-plugin test suite
run: cabal test hls-explicit-record-fields-plugin --test-options="$TEST_OPTS" || LSP_TEST_LOG_COLOR=0 LSP_TEST_LOG_MESSAGES=true LSP_TEST_LOG_STDERR=true cabal test hls-explicit-record-fields-plugin --test-options="$TEST_OPTS"

## version needs to be limited since the tests depend on cabal-fmt which only builds using specific ghc versions
fendor marked this conversation as resolved.
Show resolved Hide resolved
- if: matrix.test && matrix.ghc == '8.10.7'
name: Test hls-cabal-fmt-plugin test suite
run: cabal test hls-cabal-fmt-plugin --flag=isolateTests --test-options="$TEST_OPTS" || cabal test hls-cabal-fmt-plugin --flag=isolateTests --test-options="$TEST_OPTS" || LSP_TEST_LOG_COLOR=0 LSP_TEST_LOG_MESSAGES=true LSP_TEST_LOG_STDERR=true cabal test hls-cabal-fmt-plugin --flag=isolateTests --test-options="$TEST_OPTS"

test_post_job:
if: always()
runs-on: ubuntu-latest
Expand Down
1 change: 1 addition & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
# Plugins
/plugins/hls-alternate-number-format-plugin @drsooch
/plugins/hls-brittany-plugin @fendor
/plugins/hls-cabal-fmt-plugin @VeryMilkyJoe @fendor
/plugins/hls-call-hierarchy-plugin @July541
/plugins/hls-class-plugin @Ailrun
/plugins/hls-eval-plugin
Expand Down
1 change: 1 addition & 0 deletions cabal.project
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ packages:
./ghcide/test
./hls-plugin-api
./hls-test-utils
./plugins/hls-cabal-fmt-plugin
./plugins/hls-tactics-plugin
./plugins/hls-brittany-plugin
./plugins/hls-stylish-haskell-plugin
Expand Down
7 changes: 7 additions & 0 deletions docs/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,13 @@ Format your code with various Haskell code formatters.
| Ormolu | `hls-ormolu-plugin` |
| Stylish Haskell | `hls-stylish-haskell-plugin` |

Format your cabal files with a cabal code formatter.

| Formatter | Provided by |
|-----------------|------------------------------|
| cabal-fmt | `hls-cabal-fmt-plugin` |


## Document symbols

Provided by: `ghcide`
Expand Down
1 change: 1 addition & 0 deletions docs/support/plugin-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ For example, a plugin to provide a formatter which has itself been abandoned has
| `hls-pragmas-plugin` | 1 | |
| `hls-refactor-plugin` | 1 | 9.4 |
| `hls-alternate-number-plugin` | 2 | |
| `hls-cabal-fmt-plugin` | 2 | |
| `hls-class-plugin` | 2 | |
| `hls-change-type-signature-plugin` | 2 | |
| `hls-eval-plugin` | 2 | 9.4 |
Expand Down
10 changes: 10 additions & 0 deletions haskell-language-server.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,16 @@ flag dynamic
default: True
manual: True

flag cabalfmt
description: Enable cabal-fmt plugin
default: True
manual: True

common cabalfmt
if flag(cabalfmt)
build-depends: hls-cabal-fmt-plugin ^>= 0.1.0.0
cpp-options: -Dhls_cabalfmt

common class
if flag(class)
build-depends: hls-class-plugin ^>= 1.1
Expand Down
13 changes: 8 additions & 5 deletions hls-plugin-api/src/Ide/Plugin/Config.hs
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,12 @@ data CheckParents
-- will be surprises relating to config options being ignored, initially though.
data Config =
Config
{ checkParents :: CheckParents
, checkProject :: !Bool
, formattingProvider :: !T.Text
, maxCompletions :: !Int
, plugins :: !(Map.Map T.Text PluginConfig)
{ checkParents :: CheckParents
, checkProject :: !Bool
, formattingProvider :: !T.Text
, cabalFormattingProvider :: !T.Text
fendor marked this conversation as resolved.
Show resolved Hide resolved
, maxCompletions :: !Int
, plugins :: !(Map.Map T.Text PluginConfig)
} deriving (Show,Eq)

instance Default Config where
Expand All @@ -62,6 +63,7 @@ instance Default Config where
, formattingProvider = "ormolu"
-- , formattingProvider = "floskell"
-- , formattingProvider = "stylish-haskell"
, cabalFormattingProvider = "cabal-fmt"
VeryMilkyJoe marked this conversation as resolved.
Show resolved Hide resolved
, maxCompletions = 40
, plugins = Map.empty
}
Expand All @@ -78,6 +80,7 @@ parseConfig defValue = A.withObject "Config" $ \v -> do
<$> (o .:? "checkParents" <|> v .:? "checkParents") .!= checkParents defValue
<*> (o .:? "checkProject" <|> v .:? "checkProject") .!= checkProject defValue
<*> o .:? "formattingProvider" .!= formattingProvider defValue
<*> o .:? "cabalFormattingProvider" .!= cabalFormattingProvider defValue
<*> o .:? "maxCompletions" .!= maxCompletions defValue
<*> o .:? "plugin" .!= plugins defValue

Expand Down
5 changes: 3 additions & 2 deletions hls-plugin-api/src/Ide/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -403,14 +403,15 @@ instance PluginMethod Request TextDocumentCompletion where

instance PluginMethod Request TextDocumentFormatting where
pluginEnabled STextDocumentFormatting msgParams pluginDesc conf =
pluginResponsible uri pluginDesc && PluginId (formattingProvider conf) == pid
pluginResponsible uri pluginDesc
&& (PluginId (formattingProvider conf) == pid || PluginId (cabalFormattingProvider conf) == pid)
where
uri = msgParams ^. J.textDocument . J.uri
pid = pluginId pluginDesc

instance PluginMethod Request TextDocumentRangeFormatting where
pluginEnabled _ msgParams pluginDesc conf = pluginResponsible uri pluginDesc
&& PluginId (formattingProvider conf) == pid
&& (PluginId (formattingProvider conf) == pid || PluginId (cabalFormattingProvider conf) == pid)
where
uri = msgParams ^. J.textDocument . J.uri
pid = pluginId pluginDesc
Expand Down
60 changes: 48 additions & 12 deletions hls-test-utils/src/Test/Hls.hs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ module Test.Hls
goldenGitDiff,
goldenWithHaskellDoc,
goldenWithHaskellDocFormatter,
goldenWithCabalDocFormatter,
def,
runSessionWithServer,
runSessionWithServerFormatter,
runSessionWithCabalServerFormatter,
runSessionWithServer',
waitForProgressDone,
waitForAllProgressDone,
Expand Down Expand Up @@ -70,6 +72,7 @@ import Development.IDE.Types.Options
import GHC.IO.Handle
import GHC.Stack (emptyCallStack)
import Ide.Plugin.Config (Config, PluginConfig,
cabalFormattingProvider,
formattingProvider, plugins)
import Ide.PluginUtils (idePluginsToPluginDesc,
pluginDescToIdePlugins)
Expand Down Expand Up @@ -130,15 +133,30 @@ goldenWithHaskellDoc plugin title testDataDir path desc ext act =
act doc
documentContents doc


runSessionWithServer :: PluginDescriptor IdeState -> FilePath -> Session a -> IO a
runSessionWithServer plugin = runSessionWithServer' [plugin] def def fullCaps

runSessionWithServerFormatter :: PluginDescriptor IdeState -> String -> PluginConfig -> FilePath -> Session a -> IO a
runSessionWithServerFormatter plugin formatter conf =
runSessionWithServer'
[plugin]
def
{ formattingProvider = T.pack formatter
, plugins = M.singleton (T.pack formatter) conf
}
def
fullCaps

goldenWithHaskellDocFormatter
:: PluginDescriptor IdeState
-> String
:: PluginDescriptor IdeState -- ^ Formatter plugin to be used
-> String -- ^ Name of the formatter to be used
-> PluginConfig
-> TestName
-> FilePath
-> FilePath
-> FilePath
-> FilePath
-> TestName -- ^ Title of the test
-> FilePath -- ^ Directory of the test data to be used
-> FilePath -- ^ Path to the testdata to be used within the directory
-> FilePath -- ^ Additional suffix to be appended to the output file
-> FilePath -- ^ Extension of the output file
-> (TextDocumentIdentifier -> Session ())
-> TestTree
goldenWithHaskellDocFormatter plugin formatter conf title testDataDir path desc ext act =
Expand All @@ -151,15 +169,33 @@ goldenWithHaskellDocFormatter plugin formatter conf title testDataDir path desc
act doc
documentContents doc

runSessionWithServer :: PluginDescriptor IdeState -> FilePath -> Session a -> IO a
runSessionWithServer plugin = runSessionWithServer' [plugin] def def fullCaps
goldenWithCabalDocFormatter
:: PluginDescriptor IdeState -- ^ Formatter plugin to be used
-> String -- ^ Name of the formatter to be used
-> PluginConfig
-> TestName -- ^ Title of the test
-> FilePath -- ^ Directory of the test data to be used
-> FilePath -- ^ Path to the testdata to be used within the directory
-> FilePath -- ^ Additional suffix to be appended to the output file
-> FilePath -- ^ Extension of the output file
-> (TextDocumentIdentifier -> Session ())
-> TestTree
goldenWithCabalDocFormatter plugin formatter conf title testDataDir path desc ext act =
goldenGitDiff title (testDataDir </> path <.> desc <.> ext)
$ runSessionWithCabalServerFormatter plugin formatter conf testDataDir
$ TL.encodeUtf8 . TL.fromStrict
<$> do
doc <- openDoc (path <.> ext) "cabal"
void waitForBuildQueue
act doc
documentContents doc
VeryMilkyJoe marked this conversation as resolved.
Show resolved Hide resolved

runSessionWithServerFormatter :: PluginDescriptor IdeState -> String -> PluginConfig -> FilePath -> Session a -> IO a
runSessionWithServerFormatter plugin formatter conf =
runSessionWithCabalServerFormatter :: PluginDescriptor IdeState -> String -> PluginConfig -> FilePath -> Session a -> IO a
runSessionWithCabalServerFormatter plugin formatter conf =
runSessionWithServer'
[plugin]
def
{ formattingProvider = T.pack formatter
{ cabalFormattingProvider = T.pack formatter
, plugins = M.singleton (T.pack formatter) conf
}
def
Expand Down
Loading