Commit cfdc35fb authored by Oleg Grenrus's avatar Oleg Grenrus
Browse files

Recognise elif if cabal-version >= 2.1

parent 8efdd7af
...@@ -34,6 +34,7 @@ extra-source-files: ...@@ -34,6 +34,7 @@ extra-source-files:
-- BEGIN gen-extra-source-files -- BEGIN gen-extra-source-files
tests/ParserTests/regressions/Octree-0.5.cabal tests/ParserTests/regressions/Octree-0.5.cabal
tests/ParserTests/regressions/elif.cabal tests/ParserTests/regressions/elif.cabal
tests/ParserTests/regressions/elif2.cabal
tests/ParserTests/regressions/encoding-0.8.cabal tests/ParserTests/regressions/encoding-0.8.cabal
tests/ParserTests/regressions/generics-sop.cabal tests/ParserTests/regressions/generics-sop.cabal
tests/ParserTests/regressions/issue-774.cabal tests/ParserTests/regressions/issue-774.cabal
......
...@@ -149,25 +149,55 @@ parseGenericPackageDescription' lexWarnings fs = do ...@@ -149,25 +149,55 @@ parseGenericPackageDescription' lexWarnings fs = do
-- Sections -- Sections
let gpd = emptyGpd & L.packageDescription .~ pd let gpd = emptyGpd & L.packageDescription .~ pd
execStateT (goSections sectionFields) gpd
-- elif conditional is accepted if spec version is >= 2.1
let hasElif = if specVersion pd >= mkVersion [2,1] then HasElif else NoElif
execStateT (goSections hasElif sectionFields) gpd
where where
emptyGpd :: GenericPackageDescription
emptyGpd = GenericPackageDescription emptyPackageDescription [] Nothing [] [] [] [] []
newSyntaxVersion :: Version
newSyntaxVersion = mkVersion [1, 2]
maybeWarnCabalVersion :: Syntax -> PackageDescription -> ParseResult ()
maybeWarnCabalVersion syntax pkg
| syntax == NewSyntax && specVersion pkg < newSyntaxVersion
= parseWarning (Position 0 0) PWTNewSyntax $
"A package using section syntax must specify at least\n"
++ "'cabal-version: >= 1.2'."
maybeWarnCabalVersion syntax pkg
| syntax == OldSyntax && specVersion pkg >= newSyntaxVersion
= parseWarning (Position 0 0) PWTOldSyntax $
"A package using 'cabal-version: "
++ displaySpecVersion (specVersionRaw pkg)
++ "' must use section syntax. See the Cabal user guide for details."
where
displaySpecVersion (Left version) = display version
displaySpecVersion (Right versionRange) =
case asVersionIntervals versionRange of
[] {- impossible -} -> display versionRange
((LowerBound version _, _):_) -> display (orLaterVersion version)
maybeWarnCabalVersion _ _ = return ()
-- Sections -- Sections
goSections :: [Field Position] -> M () goSections :: HasElif -> [Field Position] -> M ()
goSections [] = pure () goSections hasElif = traverse_ process
goSections (Field (Name pos name) _ : fields) = do where
inM $ parseWarning pos PWTTrailingFields $ "Ignoring trailing fields after sections: " ++ show name process (Field (Name pos name) _) =
goSections fields inM $ parseWarning pos PWTTrailingFields $
goSections (Section name args secFields : fields) = do "Ignoring trailing fields after sections: " ++ show name
process (Section name args secFields) =
parseSection name args secFields parseSection name args secFields
goSections fields
emptyGpd :: GenericPackageDescription snoc x xs = xs ++ [x]
emptyGpd = GenericPackageDescription emptyPackageDescription [] Nothing [] [] [] [] []
parseSection :: Name Position -> [SectionArg Position] -> [Field Position] -> M () parseSection :: Name Position -> [SectionArg Position] -> [Field Position] -> M ()
parseSection (Name pos name) args fields parseSection (Name pos name) args fields
| name == "library" && null args = do | name == "library" && null args = do
lib <- inM $ parseCondTree (libraryFieldGrammar Nothing) (targetBuildDepends . libBuildInfo) fields lib <- inM $ parseCondTree hasElif (libraryFieldGrammar Nothing) (targetBuildDepends . libBuildInfo) fields
-- TODO: check that library is defined once -- TODO: check that library is defined once
L.condLibrary ?= lib L.condLibrary ?= lib
...@@ -175,32 +205,32 @@ parseGenericPackageDescription' lexWarnings fs = do ...@@ -175,32 +205,32 @@ parseGenericPackageDescription' lexWarnings fs = do
| name == "library" = do | name == "library" = do
-- TODO: check cabal-version -- TODO: check cabal-version
name' <- parseUnqualComponentName pos args name' <- parseUnqualComponentName pos args
lib <- inM $ parseCondTree (libraryFieldGrammar $ Just name') (targetBuildDepends . libBuildInfo) fields lib <- inM $ parseCondTree hasElif (libraryFieldGrammar $ Just name') (targetBuildDepends . libBuildInfo) fields
-- TODO check duplicate name here? -- TODO check duplicate name here?
L.condSubLibraries %= snoc (name', lib) L.condSubLibraries %= snoc (name', lib)
| name == "foreign-library" = do | name == "foreign-library" = do
name' <- parseUnqualComponentName pos args name' <- parseUnqualComponentName pos args
flib <- inM $ parseCondTree (foreignLibFieldGrammar name') (targetBuildDepends . foreignLibBuildInfo) fields flib <- inM $ parseCondTree hasElif (foreignLibFieldGrammar name') (targetBuildDepends . foreignLibBuildInfo) fields
-- TODO check duplicate name here? -- TODO check duplicate name here?
L.condForeignLibs %= snoc (name', flib) L.condForeignLibs %= snoc (name', flib)
| name == "executable" = do | name == "executable" = do
name' <- parseUnqualComponentName pos args name' <- parseUnqualComponentName pos args
exe <- inM $ parseCondTree (executableFieldGrammar name') (targetBuildDepends . buildInfo) fields exe <- inM $ parseCondTree hasElif (executableFieldGrammar name') (targetBuildDepends . buildInfo) fields
-- TODO check duplicate name here? -- TODO check duplicate name here?
L.condExecutables %= snoc (name', exe) L.condExecutables %= snoc (name', exe)
| name == "test-suite" = do | name == "test-suite" = do
name' <- parseUnqualComponentName pos args name' <- parseUnqualComponentName pos args
testStanza <- inM $ parseCondTree testSuiteFieldGrammar (targetBuildDepends . _testStanzaBuildInfo) fields testStanza <- inM $ parseCondTree hasElif testSuiteFieldGrammar (targetBuildDepends . _testStanzaBuildInfo) fields
testSuite <- inM $ traverse (validateTestSuite pos) testStanza testSuite <- inM $ traverse (validateTestSuite pos) testStanza
-- TODO check duplicate name here? -- TODO check duplicate name here?
L.condTestSuites %= snoc (name', testSuite) L.condTestSuites %= snoc (name', testSuite)
| name == "benchmark" = do | name == "benchmark" = do
name' <- parseUnqualComponentName pos args name' <- parseUnqualComponentName pos args
benchStanza <- inM $ parseCondTree benchmarkFieldGrammar (targetBuildDepends . _benchmarkStanzaBuildInfo) fields benchStanza <- inM $ parseCondTree hasElif benchmarkFieldGrammar (targetBuildDepends . _benchmarkStanzaBuildInfo) fields
bench <- inM $ traverse (validateBenchmark pos) benchStanza bench <- inM $ traverse (validateBenchmark pos) benchStanza
-- TODO check duplicate name here? -- TODO check duplicate name here?
L.condBenchmarks %= snoc (name', bench) L.condBenchmarks %= snoc (name', bench)
...@@ -233,33 +263,6 @@ parseGenericPackageDescription' lexWarnings fs = do ...@@ -233,33 +263,6 @@ parseGenericPackageDescription' lexWarnings fs = do
| otherwise = inM $ | otherwise = inM $
parseWarning pos PWTUnknownSection $ "Ignoring section: " ++ show name parseWarning pos PWTUnknownSection $ "Ignoring section: " ++ show name
snoc x xs = xs ++ [x]
newSyntaxVersion :: Version
newSyntaxVersion = mkVersion [1, 2]
maybeWarnCabalVersion :: Syntax -> PackageDescription -> ParseResult ()
maybeWarnCabalVersion syntax pkg
| syntax == NewSyntax && specVersion pkg < newSyntaxVersion
= parseWarning (Position 0 0) PWTNewSyntax $
"A package using section syntax must specify at least\n"
++ "'cabal-version: >= 1.2'."
maybeWarnCabalVersion syntax pkg
| syntax == OldSyntax && specVersion pkg >= newSyntaxVersion
= parseWarning (Position 0 0) PWTOldSyntax $
"A package using 'cabal-version: "
++ displaySpecVersion (specVersionRaw pkg)
++ "' must use section syntax. See the Cabal user guide for details."
where
displaySpecVersion (Left version) = display version
displaySpecVersion (Right versionRange) =
case asVersionIntervals versionRange of
[] {- impossible -} -> display versionRange
((LowerBound version _, _):_) -> display (orLaterVersion version)
maybeWarnCabalVersion _ _ = return ()
parseName :: Position -> [SectionArg Position] -> M String parseName :: Position -> [SectionArg Position] -> M String
parseName pos args = case args of parseName pos args = case args of
[SecArgName _pos secName] -> [SecArgName _pos secName] ->
...@@ -291,12 +294,18 @@ warnInvalidSubsection :: Section Position -> ParseResult () ...@@ -291,12 +294,18 @@ warnInvalidSubsection :: Section Position -> ParseResult ()
warnInvalidSubsection (MkSection (Name pos name) _ _) = warnInvalidSubsection (MkSection (Name pos name) _ _) =
void (parseFailure pos $ "invalid subsection " ++ show name) void (parseFailure pos $ "invalid subsection " ++ show name)
data HasElif = HasElif | NoElif
deriving (Eq, Show)
parseCondTree parseCondTree
:: forall a c. ParsecFieldGrammar' a -- ^ grammar :: forall a c.
-> (a -> c) -- ^ condition extractor HasElif -- ^ accept @elif@
-> ParsecFieldGrammar' a -- ^ grammar
-> (a -> c) -- ^ condition extractor
-> [Field Position] -> [Field Position]
-> ParseResult (CondTree ConfVar c a) -> ParseResult (CondTree ConfVar c a)
parseCondTree grammar cond = go parseCondTree hasElif grammar cond = go
where where
go fields = do go fields = do
let (fs, ss) = partitionFields fields let (fs, ss) = partitionFields fields
...@@ -326,8 +335,8 @@ parseCondTree grammar cond = go ...@@ -326,8 +335,8 @@ parseCondTree grammar cond = go
elseFields <- go fields elseFields <- go fields
sections' <- parseIfs sections sections' <- parseIfs sections
return (Just elseFields, sections') return (Just elseFields, sections')
{-
parseElseIfs (MkSection (Name _ name) test fields : sections) | name == "elif" = do parseElseIfs (MkSection (Name _ name) test fields : sections) | hasElif == HasElif, name == "elif" = do
-- TODO: check cabal-version -- TODO: check cabal-version
test' <- parseConditionConfVar test test' <- parseConditionConfVar test
fields' <- go fields fields' <- go fields
...@@ -335,7 +344,7 @@ parseCondTree grammar cond = go ...@@ -335,7 +344,7 @@ parseCondTree grammar cond = go
-- we parse an empty 'Fields', to get empty value for a node -- we parse an empty 'Fields', to get empty value for a node
a <- parseFieldGrammar mempty grammar a <- parseFieldGrammar mempty grammar
return (Just $ CondNode a (cond a) [CondBranch test' fields' elseFields], sections') return (Just $ CondNode a (cond a) [CondBranch test' fields' elseFields], sections')
-}
parseElseIfs sections = (,) Nothing <$> parseIfs sections parseElseIfs sections = (,) Nothing <$> parseIfs sections
{- Note [Accumulating parser] {- Note [Accumulating parser]
......
...@@ -80,6 +80,7 @@ regressionTests = testGroup "regressions" ...@@ -80,6 +80,7 @@ regressionTests = testGroup "regressions"
, regressionTest "issue-774.cabal" , regressionTest "issue-774.cabal"
, regressionTest "generics-sop.cabal" , regressionTest "generics-sop.cabal"
, regressionTest "elif.cabal" , regressionTest "elif.cabal"
, regressionTest "elif2.cabal"
, regressionTest "shake.cabal" , regressionTest "shake.cabal"
] ]
......
name: elif
version: 0
synopsis: The elif demo
build-type: Simple
cabal-version: >=2.1
source-repository head
Type: git
Location: https://github.com/hvr/-.git
library
default-language: Haskell2010
exposed-modules: ElseIf
if os(linux)
build-depends: unix
elif os(windows)
build-depends: Win32
else
buildable: False
name: elif
version: 0
synopsis: The elif demo
cabal-version: >=2.1
build-type: Simple
source-repository head
type: git
location: https://github.com/hvr/-.git
library
exposed-modules:
ElseIf
default-language: Haskell2010
if os(linux)
build-depends:
unix -any
else
if os(windows)
build-depends:
Win32 -any
else
buildable: False
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment