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 cabal-gild as a cabal file formatter plugin #4101

Merged
merged 4 commits into from
Mar 11, 2024

Conversation

fendor
Copy link
Collaborator

@fendor fendor commented Feb 28, 2024

Closes #4082

@fendor fendor requested a review from michaelpj as a code owner February 28, 2024 20:41
provider :: Recorder (WithPriority Log) -> FormattingHandler IdeState
provider recorder _ _ (FormatRange _) _ _ _ = do
logWith recorder Info LogInvalidInvocationInfo
throwError $ PluginInvalidParams "You cannot format a text-range using cabal-gild."
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You kind of can, depending on what exactly "range" means. For example:

$ echo 'build-depends:{base>=4.19,bytestring>=0.12}' | cabal-gild
build-depends:
  base >=4.19,
  bytestring >=0.12

But I wonder if anyone would actually want this behavior anyway.

Copy link
Collaborator Author

@fendor fendor Feb 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think people could find range formatting useful. But supporting only top-level stanzas and fields... Not sure it's the most intuitive behaviour.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shall we make an issue so we can put a link to the issue in the error? 😈

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be happy to add support for formatting ranges if someone can point me to a resource that explains how it should work! As shown, Gild can format any subsection of a document that's still syntactically valid. But it can't, for example, format any arbitrary range. Like if you tried to format just the contents of the build-depends field, this is what you'd get:

$ echo 'base>=4.19,bytestring>=0.12' | cabal-gild
base >= 4.19 , bytestring >= 0.12

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be happy to add support for formatting ranges if someone can point me to a resource that explains how it should work!

You mean "The document range formatting request is sent from the client to the server to format a given range in a document" isn't good enough for you? 😂

As shown, Gild can format any subsection of a document that's still syntactically valid. But it can't, for example, format any arbitrary range.

Does it take into account the surrounding context? Perhaps it doesn't matter, but an easy way this kind of formatting could go wrong is if you format the range in isolation and therefore treat it as if it is at the top-level of the structure, which it might not be.

But otherwise I think it's fine if range formatting just doesn't do anything unless you've selected a range that includes a whole element that can be sensibly formatted.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the only way it could take surrounding context into account is to maintain leading blank spaces. Otherwise it has no way of knowing that it's "inside" a library section, for example. However that doesn't matter too much for Gild; it doesn't keep track of that context anyway. The field names are unique enough that it just looks for build-depends rather than build-depends within library. See the documentation here: https://hackage.haskell.org/package/cabal-gild-1.1.0.0/docs/CabalGild-Action-FormatFields.html#v:parsers

How does range formatting work exactly? If Gild would only get the range's content as input, then there's not much it can do. But if it gets the entire buffer's input along with a span identifying the range to format, then potentially it could do something nice. (Although that might be a lot of work for me.)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But if it gets the entire buffer's input along with a span identifying the range to format,

That's what you get, indeed.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created an issue for this: tfausak/cabal-gild#42. No idea if or when I'll get around to implementing it though.

@fendor fendor force-pushed the feature/cabal-gild-plugin branch 3 times, most recently from 9fc84c1 to eb16ba7 Compare February 29, 2024 08:04
, hls-test-utils == 2.7.0.0

if flag(isolateCabalGildTests)
build-tool-depends: cabal-gild:cabal-gild ^>=1.1
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to do it like cabal-fmt? Or can we do it more like the other formatters, where we use the library by default and have an option to use an executable optionally? I thought we did it like this because cabal-fmt was particularly difficult to build? But maybe cabal-gild is easier?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cabal-gild is easier, but it doesn't compile with ghc 9.2. We can disable the plugin for that GHC version, I don't feel strongly.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it would be terribly hard to add support for GHC 9.2. Let me see what I can do.

Aside from that, Gild doesn't really expose a high-level "format" function. That's because I primarily intended for it to be an application rather than a library. The mainWith function can be used that way, but it's not very convenient. I could add a format function. What should the type signature be? Something like ByteString -> IO ByteString?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A format function would be nice, but we need to be able to pass the FilePath option for cabal-gild: discover feature to work.
Perhaps a function Opts -> ByteString -> IO ByteString?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's because I primarily intended for it to be an application rather than a library.

That's a good reason for us to interact with it that way.

It can be nice to at least have the option to use a compiled-in library version instead of shelling out to a process, but that does lead to the dread #411

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added support for GHC 9.2 in Gild version 1.1.1.0: https://github.com/tfausak/cabal-gild/releases/tag/1.1.1.0

I'll noodle on a high level formatting function. The existing mainWith function can be used in a pure manner, it's just kind of annoying. See the test suite for an example: https://github.com/tfausak/cabal-gild/blob/747550fb20c4ab4003a199ebacd07130ce16796c/source/test-suite/Main.hs#L999

provider :: Recorder (WithPriority Log) -> FormattingHandler IdeState
provider recorder _ _ (FormatRange _) _ _ _ = do
logWith recorder Info LogInvalidInvocationInfo
throwError $ PluginInvalidParams "You cannot format a text-range using cabal-gild."
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shall we make an issue so we can put a link to the issue in the error? 😈

@michaelpj
Copy link
Collaborator

I think we should get this in, it seems nice. Happy to take whatever route you like @fendor , don't want to block this on getting a "compiled-in" alternative.

@fendor fendor force-pushed the feature/cabal-gild-plugin branch from c5922e9 to 8d1bcfe Compare March 10, 2024 14:09
@fendor fendor requested a review from VeryMilkyJoe as a code owner March 10, 2024 14:53
@fendor fendor force-pushed the feature/cabal-gild-plugin branch 2 times, most recently from 94e08f1 to cf75090 Compare March 10, 2024 14:55
Copy link
Collaborator

@jhrcek jhrcek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

@fendor
Copy link
Collaborator Author

fendor commented Mar 10, 2024

I finished the PR for now, I added explicit path parameter for both cabal-fmt and cabal-gild and additionally expose the cabalFormattingProvider field to the outside world.

I locally tested that the new config options work fine, and switching between the formatters also works. But I suppose, we should add further func tests.

@fendor fendor force-pushed the feature/cabal-gild-plugin branch from cf75090 to 5186d20 Compare March 10, 2024 15:02
fendor added 2 commits March 10, 2024 18:15
In addition, allow different cabal file formatter provider to specify an
explicit file path, instead of searching only on $PATH.
@fendor fendor force-pushed the feature/cabal-gild-plugin branch from 5186d20 to 77a4409 Compare March 10, 2024 17:15
@fendor fendor enabled auto-merge (squash) March 11, 2024 16:30
@fendor fendor merged commit 16912cc into haskell:master Mar 11, 2024
38 checks passed
@mstarodub
Copy link

mstarodub commented Jul 25, 2024

It seems like this broke cabal formatting in 2.8?
I had cabal-fmt installed previously, and saving the document auto-formatted it. Now it just complains about cabal-gild not being installed in the LSP log.

Adding

                   "plugin": {
                        "gild": {
                            "globalOn": false
                        },
                        "cabal-fmt": {
                            "globalOn": true
                        }
                    }

to my LSP configuration did nothing.

edit: adding the undocumented option

                    "cabalFormattingProvider": "cabal-fmt",

instead of disabling/enabling the plugins did the trick. I know formatting has tier 2 support, but I think it would have been better to retain the old default to not break user setups.

@fendor
Copy link
Collaborator Author

fendor commented Jul 25, 2024

@mstarodub Apologies for the unexpected breakage and also for forgetting to document the cabalFormattingProvider, that's on me! The reasoning why we changed the default is that cabal-fmt doesn't work correctly with HLS when expanding hs-source-dirs, with no prospect of fixing it. So, I thought it would be better if the default was a formatter that is responsive to our needs, such as cabal-gild, as this feels like the better long-term solution and better out-of-the-box behaviour.

@mstarodub
Copy link

Thank you for the rationale, seems totally reasonable. I'll switch my setup to gild at some point then!

netbsd-srcmastr pushed a commit to NetBSD/pkgsrc that referenced this pull request Jan 31, 2025
## 2.9.0.0

- Bindists for GHC 9.10.1 by @wz1000, @jhrcek, @michaelpj
- More hls-graph reliability improvements by @soulomoon
- Refactoring of test suite runners by @soulomoon
- Fixes in multiple home units support by @wz1000

### Pull Requests

- Fix quadratic memory usage in GetLocatedImports
  ([#4318](haskell/haskell-language-server#4318)) by @mpickering
- Bump stack configs + CI to 9.6.5 and 9.8.2
  ([#4316](haskell/haskell-language-server#4316)) by @jhrcek
- Add support for Fourmolu 0.16
  ([#4314](haskell/haskell-language-server#4314)) by @ brandonchinn178
- Code action to remove redundant record field import (fixes #4220)
  ([#4308](haskell/haskell-language-server#4308)) by @battermann
- Use restricted monad for plugins (#4057)
  ([#4304](haskell/haskell-language-server#4304)) by @awjchen
- 4301 we need to implement utility to wait for all runnning keys in hls graph done
  ([#4302](haskell/haskell-language-server#4302)) by @soulomoon
- Call useWithStale instead of useWithStaleFast when calling ParseCabalFields
  ([#4294](haskell/haskell-language-server#4294)) by @VeryMilkyJoe
- test: add test documenting #806
  ([#4292](haskell/haskell-language-server#4292)) by @develop7
- ghcide: drop ghc-check and ghc-paths dependency
  ([#4291](haskell/haskell-language-server#4291)) by @wz1000
- Limit number of valid hole fits to 10
  ([#4288](haskell/haskell-language-server#4288)) by @akshaymankar
- Add common stanza to completion data
  ([#4286](haskell/haskell-language-server#4286)) by @VeryMilkyJoe
- FindImports: ThisPkg means some home unit, not "this" unit
  ([#4284](haskell/haskell-language-server#4284)) by @wz1000
- Remove redudant absolutization in session loader
  ([#4280](haskell/haskell-language-server#4280)) by @soulomoon
- Bump to new lsp versions
  ([#4279](haskell/haskell-language-server#4279)) by @michaelpj
- Put more test code into pre-commit
  ([#4275](haskell/haskell-language-server#4275)) by @soulomoon
- Delete library ghcide test utils
  ([#4274](haskell/haskell-language-server#4274)) by @soulomoon
- Delete testUtil from ghcide-tests
  ([#4272](haskell/haskell-language-server#4272)) by @soulomoon
- CI change, only run bench on performance label
  ([#4271](haskell/haskell-language-server#4271)) by @soulomoon
- Migrate WatchedFileTests
  ([#4269](haskell/haskell-language-server#4269)) by @soulomoon
- Migrate UnitTests
  ([#4268](haskell/haskell-language-server#4268)) by @soulomoon
- Migrate SafeTests
  ([#4267](haskell/haskell-language-server#4267)) by @soulomoon
- Migrate SymlinkTests
  ([#4266](haskell/haskell-language-server#4266)) by @soulomoon
- Remove unused and outdated CHANGELOG files
  ([#4264](haskell/haskell-language-server#4264)) by @fendor
- Enable cabal flaky test
  ([#4263](haskell/haskell-language-server#4263)) by @soulomoon
- Migrate RootUriTests
  ([#4261](haskell/haskell-language-server#4261)) by @soulomoon
- Migrate PreprocessorTests
  ([#4260](haskell/haskell-language-server#4260)) by @soulomoon
- Migrate PluginSimpleTests
  ([#4259](haskell/haskell-language-server#4259)) by @soulomoon
- Migrate ClientSettingsTests
  ([#4258](haskell/haskell-language-server#4258)) by @soulomoon
- Unify critical session running in hls
  ([#4256](haskell/haskell-language-server#4256)) by @soulomoon
- Bump cachix/cachix-action from 14 to 15
  ([#4255](haskell/haskell-language-server#4255)) by @dependabot[bot]
- Bump haskell-actions/setup from 2.7.2 to 2.7.3
  ([#4254](haskell/haskell-language-server#4254)) by @dependabot[bot]
- Bump haskell-actions/setup from 2.7.2 to 2.7.3 in /.github/actions/setup-build
  ([#4253](haskell/haskell-language-server#4253)) by @dependabot[bot]
- Shorter file names completion
  ([#4252](haskell/haskell-language-server#4252)) by @VenInf
- Fix progress start delay
  ([#4249](haskell/haskell-language-server#4249)) by @michaelpj
- Bump cachix/install-nix-action from 26 to 27
  ([#4245](haskell/haskell-language-server#4245)) by @dependabot[bot]
- Bump haskell-actions/setup from 2.7.1 to 2.7.2
  ([#4244](haskell/haskell-language-server#4244)) by @dependabot[bot]
- Bump haskell-actions/setup from 2.7.1 to 2.7.2 in /.github/actions/setup-build
  ([#4243](haskell/haskell-language-server#4243)) by @dependabot[bot]
- Enable test for #717
  ([#4241](haskell/haskell-language-server#4241)) by @soulomoon
- Remove Pepe from CODEOWNERS
  ([#4239](haskell/haskell-language-server#4239)) by @michaelpj
- Fix resultBuilt(dirty mechanism) in hls-graph
  ([#4238](haskell/haskell-language-server#4238)) by @soulomoon
- Support for 9.10
  ([#4233](haskell/haskell-language-server#4233)) by @wz1000
- Refactor hls-test-util and reduce getCurrentDirectory after initilization
  ([#4231](haskell/haskell-language-server#4231)) by @soulomoon
- [Migrate BootTests] part of #4173 Migrate ghcide tests to hls test utils
  ([#4227](haskell/haskell-language-server#4227)) by @soulomoon
- Actually enable pedantic flag in ci flags job
  ([#4224](haskell/haskell-language-server#4224)) by @jhrcek
- Cleanup cabal files, ghc compat code, fix ghc warnings
  ([#4222](haskell/haskell-language-server#4222)) by @jhrcek
- Another attempt at using the lsp API for some progress reporting
  ([#4218](haskell/haskell-language-server#4218)) by @michaelpj
- [Migrate diagnosticTests] part of #4173 Migrate ghcide tests to hls test utils
  ([#4207](haskell/haskell-language-server#4207)) by @soulomoon
- Prepare release 2.8.0.0
  ([#4191](haskell/haskell-language-server#4191)) by @wz1000
- Stabilize the build system by correctly house keeping the dirtykeys and rule values [flaky test #4185 #4093]
  ([#4190](haskell/haskell-language-server#4190)) by @soulomoon
- hls-cabal-plugin: refactor context search to use `readFields`
  ([#4186](haskell/haskell-language-server#4186)) by @fendor
- 3944 extend the properties api to better support nested configuration
  ([#3952](haskell/haskell-language-server#3952)) by @soulomoon

## 2.8.0.0

- Bindists for GHC 9.6.5
- New hls-notes plugin (#4126, @jvanbruegge)
- Floskell, hlint and stylish-haskell plugins enabled for GHC 9.8
- Improvements for hls-graph increasing robustness (#4087, @soulomoon)
- Improvements to multi-component support (#4096, #4109, #4179, @wz1000, @fendor)

### Pull Requests

- Bump haskell-actions/setup from 2.7.0 to 2.7.1
  ([#4189](haskell/haskell-language-server#4189)) by @dependabot[bot]
- Bump haskell-actions/setup from 2.7.0 to 2.7.1 in /.github/actions/setup-build
  ([#4188](haskell/haskell-language-server#4188)) by @dependabot[bot]
- Fix ghcdie-tests CI
  ([#4184](haskell/haskell-language-server#4184)) by @soulomoon
- Fix ghc and hlint warnings, fix formatting
  ([#4181](haskell/haskell-language-server#4181)) by @jhrcek
- Allow users to specify whether to use `cabal`'s multi-repl feature
  ([#4179](haskell/haskell-language-server#4179)) by @fendor
- Improve parsing of import suggestions extending multiple multiline imports (fixes #4175)
  ([#4177](haskell/haskell-language-server#4177)) by @jhrcek
- move ghcide-tests to haskell-language-server.cabal and make it depend on hls-test-utils
  ([#4176](haskell/haskell-language-server#4176)) by @soulomoon
- enable ThreadId for when testing
  ([#4174](haskell/haskell-language-server#4174)) by @soulomoon
- Drop Legacy Logger from Codebase
  ([#4171](haskell/haskell-language-server#4171)) by @fendor
- get rid of the `unsafeInterleaveIO` at start up
  ([#4167](haskell/haskell-language-server#4167)) by @soulomoon
- Remove EKG
  ([#4163](haskell/haskell-language-server#4163)) by @michaelpj
- Mark plugins as not buildable if the flag is disabled
  ([#4160](haskell/haskell-language-server#4160)) by @michaelpj
- Fix references to old CPP names in tests, update tests
  ([#4159](haskell/haskell-language-server#4159)) by @jhrcek
- Bump haskell-actions/setup from 2.6.3 to 2.7.0
  ([#4158](haskell/haskell-language-server#4158)) by @dependabot[bot]
- Bump haskell-actions/setup from 2.6.3 to 2.7.0 in /.github/actions/setup-build
  ([#4157](haskell/haskell-language-server#4157)) by @dependabot[bot]
- Remove dead code in ghcide and hls-graph for priority
  ([#4151](haskell/haskell-language-server#4151)) by @soulomoon
- Bump haskell-actions/setup from 2.6.2 to 2.6.3 in /.github/actions/setup-build
  ([#4150](haskell/haskell-language-server#4150)) by @dependabot[bot]
- Bump haskell-actions/setup from 2.6.2 to 2.6.3
  ([#4149](haskell/haskell-language-server#4149)) by @dependabot[bot]
- Run ExceptionTests in temporary directory
  ([#4146](haskell/haskell-language-server#4146)) by @fendor
- hls-eval-plugin: Replicate #4139
  ([#4140](haskell/haskell-language-server#4140)) by @mattapet
- Update comment in refactor tests
  ([#4138](haskell/haskell-language-server#4138)) by @jhrcek
- Update contact info in docs
  ([#4137](haskell/haskell-language-server#4137)) by @jhrcek
- hls-notes-plugin: Do not error if no note is under the cursor
  ([#4136](haskell/haskell-language-server#4136)) by @jvanbruegge
- improve logging in semantic tokens rule
  ([#4135](haskell/haskell-language-server#4135)) by @soulomoon
- Bump softprops/action-gh-release from 1 to 2
  ([#4133](haskell/haskell-language-server#4133)) by @dependabot[bot]
- Bump cachix/install-nix-action from 25 to 26
  ([#4132](haskell/haskell-language-server#4132)) by @dependabot[bot]
- Use Set.member instead of Foldable.elem
  ([#4128](haskell/haskell-language-server#4128)) by @jhrcek
- hls-notes-plugin: Initial implementation
  ([#4126](haskell/haskell-language-server#4126)) by @jvanbruegge
- Enable floskell and hlint plugins for ghc 9.8
  ([#4125](haskell/haskell-language-server#4125)) by @jhrcek
- Integrate stylish-haskell into hls executable with ghc 9.8
  ([#4124](haskell/haskell-language-server#4124)) by @jhrcek
- Reduce usage of partial functions
  ([#4123](haskell/haskell-language-server#4123)) by @jhrcek
- Benchmark: Enable 9.6, 9.8
  ([#4118](haskell/haskell-language-server#4118)) by @soulomoon
- Bump haskell-actions/setup from 2.6.1 to 2.6.2 in /.github/actions/setup-build
  ([#4116](haskell/haskell-language-server#4116)) by @dependabot[bot]
- Bump haskell-actions/setup from 2.6.1 to 2.6.2
  ([#4115](haskell/haskell-language-server#4115)) by @dependabot[bot]
- eval: more robust way to extract comments from ParsedModule
  ([#4113](haskell/haskell-language-server#4113)) by @jhrcek
- Improve isolation of build artefacts of test runs
  ([#4112](haskell/haskell-language-server#4112)) by @fendor
- Improve handling of nonsense rename attempts
  ([#4111](haskell/haskell-language-server#4111)) by @jhrcek
- Exit with non-zero exitcode if wrapper fails to launch
  ([#4110](haskell/haskell-language-server#4110)) by @fendor
- Replace checkHomeUnitsClosed with a faster implementation
  ([#4109](haskell/haskell-language-server#4109)) by @wz1000
- Don't distribute gifs or plugin readmes
  ([#4107](haskell/haskell-language-server#4107)) by @fendor
- Remove locale workaround for Module name that conatins non-ascii characters
  ([#4106](haskell/haskell-language-server#4106)) by @fendor
- Track extra-source-files of plugins more accurately
  ([#4105](haskell/haskell-language-server#4105)) by @fendor
- remove non-ascii name
  ([#4103](haskell/haskell-language-server#4103)) by @soulomoon
- Add cabal-gild as a cabal file formatter plugin
  ([#4101](haskell/haskell-language-server#4101)) by @fendor
- Remove more workarounds for GHCs < 9.2 (#4092)
  ([#4098](haskell/haskell-language-server#4098)) by @jhrcek
- session-loader: Don't loop forever when we don't find a file in any multi component
  ([#4096](haskell/haskell-language-server#4096)) by @wz1000
- Prepare release 2.7.0.0
  ([#4095](haskell/haskell-language-server#4095)) by @fendor
- Remove more workarounds for GHCs < 9.0
  ([#4092](haskell/haskell-language-server#4092)) by @jhrcek
- Fix hls-graph: phantom dependencies invoke in branching deps (resolve #3423)
  ([#4087](haskell/haskell-language-server#4087)) by @soulomoon
- Rename only if the current module compiles (#3799)
  ([#3848](haskell/haskell-language-server#3848)) by @sgillespie
- Reintroduce ghc-lib flag for hlint plugin
  ([#3757](haskell/haskell-language-server#3757)) by @RaoulHC
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add cabal-gild as an alternative cabal file formatter
6 participants