Skip to content

Commit 5dbbd85

Browse files
runeksvendsenfendorhasufellmergify[bot]
authored
Parse .cabal files; show error and warning diagnostics (#2954)
* Extract cabal plugin in its own package * hls-cabal-plugin: Add plugin Add golden parse test for test/testdata/simple.cabal Add module Ide.Plugin.Cabal.Diag Also: add -Wall Add parseCabalFileContents Use VFS for cabal file contents Diagnostics * Parse and display Errors * Parse and display Warnings Code Actions * Code Action for License Field * Add CI workflow * Add test-suite for hls-cabal-plugin * Fix various cabal issues * Update Codeowners file for hls-cabal-plugin * Document Bytestring is UTF-8 encoded Co-authored-by: Julian Ospald <[email protected]> * Remove code duplication * Add cabal files of interest and kick function Configure a "kick" function for cabal files that is run when the shake queue needs to be restarted. Copy pastes from ghcide and 'files of interest'. Maybe more abstraction needed. * Add more documentation * Mark flaky test-case as flaky with issue ref * Make fendor the only CODEOWNER for hls-cabal-plugin * Add missing extra-source-files for hls-cabal-plugin * Add proper CHANGELOG entry for the first version of hls-cabal-plugin * Add support for Cabal 3.8 * Set diagnostics source to cabal * Remove unused function * Add unit tests for code action utilities * Remove overly specific logging of diagnostics from hls-cabal-plugin * Improve logging for Cabal FOIs * Add Range manipulation functions * Use Range manipulation functions from hls-plugin-api * Add more documentation for crucial shake restart function * Add hls-cabal-plugin features to features.md * Re-use existing GetFileContents rule Co-authored-by: Fendor <[email protected]> Co-authored-by: fendor <[email protected]> Co-authored-by: Julian Ospald <[email protected]> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
1 parent 0d06786 commit 5dbbd85

26 files changed

+867
-7
lines changed

Diff for: .github/workflows/hackage.yml

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ jobs:
2828
matrix:
2929
package: ["hie-compat", "hls-graph", "shake-bench",
3030
"hls-plugin-api", "ghcide", "hls-test-utils",
31+
"hls-cabal-plugin",
3132
"hls-brittany-plugin", "hls-floskell-plugin", "hls-fourmolu-plugin",
3233
"hls-ormolu-plugin", "hls-stylish-haskell-plugin",
3334
"hls-class-plugin", "hls-eval-plugin", "hls-explicit-imports-plugin",

Diff for: .github/workflows/test.yml

+4
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,10 @@ jobs:
259259
name: Test hls-cabal-fmt-plugin test suite
260260
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"
261261

262+
- if: matrix.test
263+
name: Test hls-cabal-plugin test suite
264+
run: cabal test hls-cabal-plugin --test-options="$TEST_OPTS" || LSP_TEST_LOG_COLOR=0 LSP_TEST_LOG_MESSAGES=true LSP_TEST_LOG_STDERR=true cabal test hls-cabal-plugin --test-options="$TEST_OPTS"
265+
262266
test_post_job:
263267
if: always()
264268
runs-on: ubuntu-latest

Diff for: CODEOWNERS

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
# Plugins
1010
/plugins/hls-alternate-number-format-plugin @drsooch
1111
/plugins/hls-brittany-plugin @fendor
12+
/plugins/hls-cabal-plugin @fendor
1213
/plugins/hls-cabal-fmt-plugin @VeryMilkyJoe @fendor
1314
/plugins/hls-call-hierarchy-plugin @July541
1415
/plugins/hls-class-plugin @Ailrun

Diff for: cabal.project

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ packages:
88
./ghcide/test
99
./hls-plugin-api
1010
./hls-test-utils
11+
./plugins/hls-cabal-plugin
1112
./plugins/hls-cabal-fmt-plugin
1213
./plugins/hls-tactics-plugin
1314
./plugins/hls-brittany-plugin

Diff for: docs/features.md

+14
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ Provided by: `hls-stan-plugin`
4444

4545
Provides Stan hints as diagnostics.
4646

47+
### Cabal parse errors and warnings
48+
49+
Provided by: `hls-cabal-plugin`
50+
51+
Provides errors and warnings from Cabal as diagnostics
52+
4753
## Hovers
4854

4955
Provided by: `ghcide`
@@ -308,6 +314,14 @@ Expand record wildcards, explicitly listing all record fields as field puns.
308314

309315
![Explicit Wildcard Demo](../plugins/hls-explicit-record-fields-plugin/wildcard.gif)
310316

317+
### Unknown SPDX License suggestion
318+
319+
Provided by: `hls-cabal-plugin`
320+
321+
Code action kind: `quickfix`
322+
323+
Correct common misspelling of SPDX Licenses such as `BSD-3-Clause`.
324+
311325
## Code lenses
312326

313327
### Add type signature

Diff for: haskell-language-server.cabal

+12
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,12 @@ flag ignore-plugins-ghc-bounds
6363
default: False
6464
manual: True
6565

66+
67+
flag cabal
68+
description: Enable cabal plugin
69+
default: True
70+
manual: True
71+
6672
flag class
6773
description: Enable class plugin
6874
default: True
@@ -215,6 +221,11 @@ common cabalfmt
215221
build-depends: hls-cabal-fmt-plugin ^>= 0.1.0.0
216222
cpp-options: -Dhls_cabalfmt
217223

224+
common cabal
225+
if flag(cabal)
226+
build-depends: hls-cabal-plugin ^>= 0.1
227+
cpp-options: -Dhls_cabal
228+
218229
common class
219230
if flag(class)
220231
build-depends: hls-class-plugin ^>= 1.1
@@ -358,6 +369,7 @@ library
358369
, warnings
359370
, pedantic
360371
-- plugins
372+
, cabal
361373
, callHierarchy
362374
, cabalfmt
363375
, changeTypeSignature

Diff for: hls-plugin-api/src/Ide/PluginUtils.hs

+25-4
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22
{-# LANGUAGE OverloadedStrings #-}
33
{-# LANGUAGE TypeFamilies #-}
44
module Ide.PluginUtils
5-
( WithDeletions(..),
6-
getProcessID,
5+
( -- * LSP Range manipulation functions
76
normalize,
7+
extendNextLine,
8+
extendLineStart,
9+
WithDeletions(..),
10+
getProcessID,
811
makeDiffTextEdit,
912
makeDiffTextEditAdditive,
1013
diffText,
@@ -67,9 +70,27 @@ import qualified Text.Megaparsec.Char.Lexer as P
6770
-- ---------------------------------------------------------------------
6871

6972
-- | Extend to the line below and above to replace newline character.
73+
--
74+
-- >>> normalize (Range (Position 5 5) (Position 5 10))
75+
-- Range (Position 5 0) (Position 6 0)
7076
normalize :: Range -> Range
71-
normalize (Range (Position sl _) (Position el _)) =
72-
Range (Position sl 0) (Position (el + 1) 0)
77+
normalize = extendLineStart . extendNextLine
78+
79+
-- | Extend 'Range' to the start of the next line.
80+
--
81+
-- >>> extendNextLine (Range (Position 5 5) (Position 5 10))
82+
-- Range (Position 5 5) (Position 6 0)
83+
extendNextLine :: Range -> Range
84+
extendNextLine (Range s (Position el _)) =
85+
Range s (Position (el + 1) 0)
86+
87+
-- | Extend 'Range' to the start of the current line.
88+
--
89+
-- >>> extendLineStart (Range (Position 5 5) (Position 5 10))
90+
-- Range (Position 5 0) (Position 5 10)
91+
extendLineStart :: Range -> Range
92+
extendLineStart (Range (Position sl _) e) =
93+
Range (Position sl 0) e
7394

7495
-- ---------------------------------------------------------------------
7596

Diff for: hls-test-utils/src/Test/Hls.hs

+26-2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ module Test.Hls
1616
defaultTestRunner,
1717
goldenGitDiff,
1818
goldenWithHaskellDoc,
19+
goldenWithCabalDoc,
1920
goldenWithHaskellDocFormatter,
2021
goldenWithCabalDocFormatter,
2122
def,
@@ -124,12 +125,35 @@ goldenWithHaskellDoc
124125
-> FilePath
125126
-> (TextDocumentIdentifier -> Session ())
126127
-> TestTree
127-
goldenWithHaskellDoc plugin title testDataDir path desc ext act =
128+
goldenWithHaskellDoc = goldenWithDoc "haskell"
129+
130+
goldenWithCabalDoc
131+
:: PluginDescriptor IdeState
132+
-> TestName
133+
-> FilePath
134+
-> FilePath
135+
-> FilePath
136+
-> FilePath
137+
-> (TextDocumentIdentifier -> Session ())
138+
-> TestTree
139+
goldenWithCabalDoc = goldenWithDoc "cabal"
140+
141+
goldenWithDoc
142+
:: T.Text
143+
-> PluginDescriptor IdeState
144+
-> TestName
145+
-> FilePath
146+
-> FilePath
147+
-> FilePath
148+
-> FilePath
149+
-> (TextDocumentIdentifier -> Session ())
150+
-> TestTree
151+
goldenWithDoc fileType plugin title testDataDir path desc ext act =
128152
goldenGitDiff title (testDataDir </> path <.> desc <.> ext)
129153
$ runSessionWithServer plugin testDataDir
130154
$ TL.encodeUtf8 . TL.fromStrict
131155
<$> do
132-
doc <- openDoc (path <.> ext) "haskell"
156+
doc <- openDoc (path <.> ext) fileType
133157
void waitForBuildQueue
134158
act doc
135159
documentContents doc

Diff for: plugins/hls-cabal-plugin/CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Revision history for hls-cabal-plugin
2+
3+
## 0.1.0.0 -- YYYY-mm-dd
4+
5+
* Provide Diagnostics on parse errors and warnings for .cabal files
6+
* Provide CodeAction for the common SPDX License mistake "BSD3" instead of "BSD-3-Clause"

Diff for: plugins/hls-cabal-plugin/LICENSE

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Copyright (c) 2022 Fendor
2+
3+
Permission is hereby granted, free of charge, to any person obtaining
4+
a copy of this software and associated documentation files (the
5+
"Software"), to deal in the Software without restriction, including
6+
without limitation the rights to use, copy, modify, merge, publish,
7+
distribute, sublicense, and/or sell copies of the Software, and to
8+
permit persons to whom the Software is furnished to do so, subject to
9+
the following conditions:
10+
11+
The above copyright notice and this permission notice shall be included
12+
in all copies or substantial portions of the Software.
13+
14+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Diff for: plugins/hls-cabal-plugin/hls-cabal-plugin.cabal

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
cabal-version: 3.0
2+
name: hls-cabal-plugin
3+
version: 0.1.0.0
4+
synopsis: Cabal integration plugin with Haskell Language Server
5+
description:
6+
Please see the README on GitHub at <https://github.com/haskell/haskell-language-server#readme>
7+
8+
homepage:
9+
license: MIT
10+
license-file: LICENSE
11+
author: Fendor
12+
maintainer: [email protected]
13+
category: Development
14+
extra-source-files:
15+
CHANGELOG.md
16+
test/testdata/*.cabal
17+
test/testdata/simple-cabal/A.hs
18+
test/testdata/simple-cabal/cabal.project
19+
test/testdata/simple-cabal/hie.yaml
20+
test/testdata/simple-cabal/simple-cabal.cabal
21+
22+
common warnings
23+
ghc-options: -Wall
24+
25+
library
26+
import: warnings
27+
exposed-modules:
28+
Ide.Plugin.Cabal
29+
Ide.Plugin.Cabal.Diagnostics
30+
Ide.Plugin.Cabal.LicenseSuggest
31+
Ide.Plugin.Cabal.Parse
32+
33+
build-depends:
34+
, base >=4.12 && <5
35+
, bytestring
36+
-- Ideally, we only want to support a single Cabal version, supporting
37+
-- older versions is completely pointless since Cabal is backwards compatible,
38+
-- the latest Cabal version can parse all versions of the Cabal file format.
39+
--
40+
-- However, stack is making this difficult, if we change the version of Cabal,
41+
-- we essentially need to make sure all other packages in the snapshot have their
42+
-- Cabal dependency version relaxed.
43+
-- Most packages have a Hackage revision, but stack won't pick these up (for sensible reasons)
44+
-- automatically, forcing us to manually update the packages revision id.
45+
-- This is a lot of work for almost zero benefit, so we just allow more versions here
46+
-- and we eventually completely drop support for building HLS with stack.
47+
, Cabal ^>=3.2 || ^>=3.4 || ^>=3.6 || ^>= 3.8
48+
, deepseq
49+
, directory
50+
, extra >=1.7.4
51+
, ghcide ^>= 1.8
52+
, hashable
53+
, hls-plugin-api ^>=1.5
54+
, hls-graph ^>=1.8
55+
, lsp ^>=1.6.0.0
56+
, lsp-types ^>=1.6.0.0
57+
, regex-tdfa ^>=1.3.1
58+
, stm
59+
, text
60+
, unordered-containers >=0.2.10.0
61+
62+
hs-source-dirs: src
63+
default-language: Haskell2010
64+
65+
test-suite tests
66+
import: warnings
67+
default-language: Haskell2010
68+
type: exitcode-stdio-1.0
69+
hs-source-dirs: test
70+
main-is: Main.hs
71+
build-depends:
72+
, base
73+
, bytestring
74+
, filepath
75+
, ghcide
76+
, hls-cabal-plugin
77+
, hls-test-utils ^>=1.4
78+
, lens
79+
, lsp-types
80+
, tasty-hunit
81+
, text

0 commit comments

Comments
 (0)