Skip to content

Commit 3591109

Browse files
fridewaldfendor
andauthored
gracefully handle errors for unsupported cabal version (#4425)
* Safely handle linenumbering for errors in the first line of cabal files * add integration test for unsupported cabal version Signed-off-by: Julian Kalema Lukwata <julianlukwata@posteo.de> * cast unsupported cabal version as warning * add better warning text * Add supported cabal-versions to the error message --------- Signed-off-by: Julian Kalema Lukwata <julianlukwata@posteo.de> Co-authored-by: Fendor <fendor@posteo.de>
1 parent 1ec65ee commit 3591109

File tree

5 files changed

+49
-8
lines changed

5 files changed

+49
-8
lines changed

plugins/hls-cabal-plugin/src/Ide/Plugin/Cabal.hs

+31-5
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@ import qualified Data.ByteString as BS
1717
import Data.Hashable
1818
import Data.HashMap.Strict (HashMap)
1919
import qualified Data.HashMap.Strict as HashMap
20+
import qualified Data.List as List
2021
import qualified Data.List.NonEmpty as NE
2122
import qualified Data.Maybe as Maybe
23+
import qualified Data.Text ()
2224
import qualified Data.Text as T
2325
import qualified Data.Text.Encoding as Encoding
2426
import Data.Text.Utf16.Rope.Mixed as Rope
@@ -33,17 +35,21 @@ import Development.IDE.Graph (Key,
3335
import Development.IDE.LSP.HoverDefinition (foundHover)
3436
import qualified Development.IDE.Plugin.Completions.Logic as Ghcide
3537
import Development.IDE.Types.Shake (toKey)
38+
import qualified Distribution.CabalSpecVersion as Cabal
3639
import qualified Distribution.Fields as Syntax
3740
import Distribution.Package (Dependency)
3841
import Distribution.PackageDescription (allBuildDepends,
3942
depPkgName,
4043
unPackageName)
4144
import Distribution.PackageDescription.Configuration (flattenPackageDescription)
45+
import Distribution.Parsec.Error
4246
import qualified Distribution.Parsec.Position as Syntax
4347
import GHC.Generics
48+
import qualified Ide.Plugin.Cabal.CabalAdd as CabalAdd
4449
import Ide.Plugin.Cabal.Completion.CabalFields as CabalFields
4550
import qualified Ide.Plugin.Cabal.Completion.Completer.Types as CompleterTypes
4651
import qualified Ide.Plugin.Cabal.Completion.Completions as Completions
52+
import qualified Ide.Plugin.Cabal.Completion.Data as Data
4753
import Ide.Plugin.Cabal.Completion.Types (ParseCabalCommonSections (ParseCabalCommonSections),
4854
ParseCabalFields (..),
4955
ParseCabalFile (..))
@@ -63,10 +69,6 @@ import Language.LSP.Protocol.Types
6369
import qualified Language.LSP.VFS as VFS
6470
import Text.Regex.TDFA
6571

66-
67-
import qualified Data.Text ()
68-
import qualified Ide.Plugin.Cabal.CabalAdd as CabalAdd
69-
7072
data Log
7173
= LogModificationTime NormalizedFilePath FileVersion
7274
| LogShake Shake.Log
@@ -247,7 +249,31 @@ cabalRules recorder plId = do
247249
let warningDiags = fmap (Diagnostics.warningDiagnostic file) pWarnings
248250
case pm of
249251
Left (_cabalVersion, pErrorNE) -> do
250-
let errorDiags = NE.toList $ NE.map (Diagnostics.errorDiagnostic file) pErrorNE
252+
let regex :: T.Text
253+
-- We don't support the cabal version, this should not be an error, as the
254+
-- user did not do anything wrong. Instead we cast it to a warning
255+
regex = "Unsupported cabal-version [0-9]+.[0-9]*"
256+
unsupportedCabalHelpText = unlines
257+
[ "The used cabal version is not fully supported by HLS. This means that some functionality might not work as expected."
258+
, "If you face any issues try to downgrade to a supported cabal version."
259+
, ""
260+
, "Supported versions are: " <>
261+
List.intercalate ", "
262+
(fmap Cabal.showCabalSpecVersion Data.supportedCabalVersions)
263+
]
264+
errorDiags =
265+
NE.toList $
266+
NE.map
267+
( \pe@(PError pos text) ->
268+
if text =~ regex
269+
then Diagnostics.warningDiagnostic file (Syntax.PWarning Syntax.PWTOther pos $
270+
unlines
271+
[ text
272+
, unsupportedCabalHelpText
273+
])
274+
else Diagnostics.errorDiagnostic file pe
275+
)
276+
pErrorNE
251277
allDiags = errorDiags <> warningDiags
252278
pure (allDiags, Nothing)
253279
Right gpd -> do

plugins/hls-cabal-plugin/src/Ide/Plugin/Cabal/Completion/Data.hs

+4-1
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,17 @@ import Ide.Plugin.Cabal.LicenseSuggest (licenseNames)
2323
-- Completion Data
2424
-- ----------------------------------------------------------------
2525

26+
supportedCabalVersions :: [CabalSpecVersion]
27+
supportedCabalVersions = [CabalSpecV2_2 .. maxBound]
28+
2629
-- | Keyword for cabal version; required to be the top line in a cabal file
2730
cabalVersionKeyword :: Map KeyWordName Completer
2831
cabalVersionKeyword =
2932
Map.singleton "cabal-version:" $
3033
constantCompleter $
3134
-- We only suggest cabal versions newer than 2.2
3235
-- since we don't recommend using older ones.
33-
map (T.pack . showCabalSpecVersion) [CabalSpecV2_2 .. maxBound]
36+
map (T.pack . showCabalSpecVersion) supportedCabalVersions
3437

3538
-- | Top level keywords of a cabal file.
3639
--

plugins/hls-cabal-plugin/src/Ide/Plugin/Cabal/Diagnostics.hs

+3-2
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,9 @@ positionFromCabalPosition :: Syntax.Position -> Position
6363
positionFromCabalPosition (Syntax.Position line column) = Position (fromIntegral line') (fromIntegral col')
6464
where
6565
-- LSP is zero-based, Cabal is one-based
66-
line' = line-1
67-
col' = column-1
66+
-- Cabal can return line 0 for errors in the first line
67+
line' = if line <= 0 then 0 else line-1
68+
col' = if column <= 0 then 0 else column-1
6869

6970
-- | Create a 'FileDiagnostic'
7071
mkDiag

plugins/hls-cabal-plugin/test/Main.hs

+8
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,14 @@ pluginTests =
107107
length diags @?= 1
108108
unknownLicenseDiag ^. L.range @?= Range (Position 3 24) (Position 4 0)
109109
unknownLicenseDiag ^. L.severity @?= Just DiagnosticSeverity_Error
110+
, runCabalTestCaseSession "Publishes Diagnostics on unsupported cabal version as Warning" "" $ do
111+
_ <- openDoc "unsupportedVersion.cabal" "cabal"
112+
diags <- cabalCaptureKick
113+
unknownVersionDiag <- liftIO $ inspectDiagnostic diags ["Unsupported cabal-version 99999.0"]
114+
liftIO $ do
115+
length diags @?= 1
116+
unknownVersionDiag ^. L.range @?= Range (Position 0 0) (Position 1 0)
117+
unknownVersionDiag ^. L.severity @?= Just DiagnosticSeverity_Warning
110118
, runCabalTestCaseSession "Clears diagnostics" "" $ do
111119
doc <- openDoc "invalid.cabal" "cabal"
112120
diags <- cabalCaptureKick
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
cabal-version: 99999.0
2+
name: invalid
3+
version: 0.1.0.0

0 commit comments

Comments
 (0)