Skip to content

Commit

Permalink
gracefully handle errors for unsupported cabal version (haskell#4425)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>

* cast unsupported cabal version as warning

* add better warning text

* Add supported cabal-versions to the error message

---------

Signed-off-by: Julian Kalema Lukwata <[email protected]>
Co-authored-by: Fendor <[email protected]>
  • Loading branch information
2 people authored and noughtmare committed Oct 23, 2024
1 parent 469d8a7 commit eb96929
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 8 deletions.
36 changes: 31 additions & 5 deletions plugins/hls-cabal-plugin/src/Ide/Plugin/Cabal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ import qualified Data.ByteString as BS
import Data.Hashable
import Data.HashMap.Strict (HashMap)
import qualified Data.HashMap.Strict as HashMap
import qualified Data.List as List
import qualified Data.List.NonEmpty as NE
import qualified Data.Maybe as Maybe
import qualified Data.Text ()
import qualified Data.Text as T
import qualified Data.Text.Encoding as Encoding
import Data.Text.Utf16.Rope.Mixed as Rope
Expand All @@ -33,17 +35,21 @@ import Development.IDE.Graph (Key,
import Development.IDE.LSP.HoverDefinition (foundHover)
import qualified Development.IDE.Plugin.Completions.Logic as Ghcide
import Development.IDE.Types.Shake (toKey)
import qualified Distribution.CabalSpecVersion as Cabal
import qualified Distribution.Fields as Syntax
import Distribution.Package (Dependency)
import Distribution.PackageDescription (allBuildDepends,
depPkgName,
unPackageName)
import Distribution.PackageDescription.Configuration (flattenPackageDescription)
import Distribution.Parsec.Error
import qualified Distribution.Parsec.Position as Syntax
import GHC.Generics
import qualified Ide.Plugin.Cabal.CabalAdd as CabalAdd
import Ide.Plugin.Cabal.Completion.CabalFields as CabalFields
import qualified Ide.Plugin.Cabal.Completion.Completer.Types as CompleterTypes
import qualified Ide.Plugin.Cabal.Completion.Completions as Completions
import qualified Ide.Plugin.Cabal.Completion.Data as Data
import Ide.Plugin.Cabal.Completion.Types (ParseCabalCommonSections (ParseCabalCommonSections),
ParseCabalFields (..),
ParseCabalFile (..))
Expand All @@ -63,10 +69,6 @@ import Language.LSP.Protocol.Types
import qualified Language.LSP.VFS as VFS
import Text.Regex.TDFA


import qualified Data.Text ()
import qualified Ide.Plugin.Cabal.CabalAdd as CabalAdd

data Log
= LogModificationTime NormalizedFilePath FileVersion
| LogShake Shake.Log
Expand Down Expand Up @@ -247,7 +249,31 @@ cabalRules recorder plId = do
let warningDiags = fmap (Diagnostics.warningDiagnostic file) pWarnings
case pm of
Left (_cabalVersion, pErrorNE) -> do
let errorDiags = NE.toList $ NE.map (Diagnostics.errorDiagnostic file) pErrorNE
let regex :: T.Text
-- We don't support the cabal version, this should not be an error, as the
-- user did not do anything wrong. Instead we cast it to a warning
regex = "Unsupported cabal-version [0-9]+.[0-9]*"
unsupportedCabalHelpText = unlines
[ "The used cabal version is not fully supported by HLS. This means that some functionality might not work as expected."
, "If you face any issues try to downgrade to a supported cabal version."
, ""
, "Supported versions are: " <>
List.intercalate ", "
(fmap Cabal.showCabalSpecVersion Data.supportedCabalVersions)
]
errorDiags =
NE.toList $
NE.map
( \pe@(PError pos text) ->
if text =~ regex
then Diagnostics.warningDiagnostic file (Syntax.PWarning Syntax.PWTOther pos $
unlines
[ text
, unsupportedCabalHelpText
])
else Diagnostics.errorDiagnostic file pe
)
pErrorNE
allDiags = errorDiags <> warningDiags
pure (allDiags, Nothing)
Right gpd -> do
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,17 @@ import Ide.Plugin.Cabal.LicenseSuggest (licenseNames)
-- Completion Data
-- ----------------------------------------------------------------

supportedCabalVersions :: [CabalSpecVersion]
supportedCabalVersions = [CabalSpecV2_2 .. maxBound]

-- | Keyword for cabal version; required to be the top line in a cabal file
cabalVersionKeyword :: Map KeyWordName Completer
cabalVersionKeyword =
Map.singleton "cabal-version:" $
constantCompleter $
-- We only suggest cabal versions newer than 2.2
-- since we don't recommend using older ones.
map (T.pack . showCabalSpecVersion) [CabalSpecV2_2 .. maxBound]
map (T.pack . showCabalSpecVersion) supportedCabalVersions

-- | Top level keywords of a cabal file.
--
Expand Down
5 changes: 3 additions & 2 deletions plugins/hls-cabal-plugin/src/Ide/Plugin/Cabal/Diagnostics.hs
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,9 @@ positionFromCabalPosition :: Syntax.Position -> Position
positionFromCabalPosition (Syntax.Position line column) = Position (fromIntegral line') (fromIntegral col')
where
-- LSP is zero-based, Cabal is one-based
line' = line-1
col' = column-1
-- Cabal can return line 0 for errors in the first line
line' = if line <= 0 then 0 else line-1
col' = if column <= 0 then 0 else column-1

-- | Create a 'FileDiagnostic'
mkDiag
Expand Down
8 changes: 8 additions & 0 deletions plugins/hls-cabal-plugin/test/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,14 @@ pluginTests =
length diags @?= 1
unknownLicenseDiag ^. L.range @?= Range (Position 3 24) (Position 4 0)
unknownLicenseDiag ^. L.severity @?= Just DiagnosticSeverity_Error
, runCabalTestCaseSession "Publishes Diagnostics on unsupported cabal version as Warning" "" $ do
_ <- openDoc "unsupportedVersion.cabal" "cabal"
diags <- cabalCaptureKick
unknownVersionDiag <- liftIO $ inspectDiagnostic diags ["Unsupported cabal-version 99999.0"]
liftIO $ do
length diags @?= 1
unknownVersionDiag ^. L.range @?= Range (Position 0 0) (Position 1 0)
unknownVersionDiag ^. L.severity @?= Just DiagnosticSeverity_Warning
, runCabalTestCaseSession "Clears diagnostics" "" $ do
doc <- openDoc "invalid.cabal" "cabal"
diags <- cabalCaptureKick
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
cabal-version: 99999.0
name: invalid
version: 0.1.0.0

0 comments on commit eb96929

Please sign in to comment.