Skip to content

Commit

Permalink
better handling of whitespaces when parsing mixin stanza.
Browse files Browse the repository at this point in the history
  • Loading branch information
piyush-kurur authored and phadej committed Mar 2, 2019
1 parent d5be732 commit 7b6627f
Show file tree
Hide file tree
Showing 17 changed files with 534 additions and 24 deletions.
17 changes: 15 additions & 2 deletions Cabal/Cabal.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ extra-source-files:
tests/ParserTests/errors/leading-comma-2c.errors
tests/ParserTests/errors/leading-comma.cabal
tests/ParserTests/errors/leading-comma.errors
tests/ParserTests/errors/mixin-1.cabal
tests/ParserTests/errors/mixin-1.errors
tests/ParserTests/errors/mixin-2.cabal
tests/ParserTests/errors/mixin-2.errors
tests/ParserTests/errors/multiple-libs.cabal
tests/ParserTests/errors/multiple-libs.errors
tests/ParserTests/errors/noVersion.cabal
Expand All @@ -73,6 +77,8 @@ extra-source-files:
tests/ParserTests/errors/spdx-2.errors
tests/ParserTests/errors/spdx-3.cabal
tests/ParserTests/errors/spdx-3.errors
tests/ParserTests/errors/undefined-flag.cabal
tests/ParserTests/errors/undefined-flag.errors
tests/ParserTests/errors/version-sets-1.cabal
tests/ParserTests/errors/version-sets-1.errors
tests/ParserTests/errors/version-sets-2.cabal
Expand All @@ -81,8 +87,6 @@ extra-source-files:
tests/ParserTests/errors/version-sets-3.errors
tests/ParserTests/errors/version-sets-4.cabal
tests/ParserTests/errors/version-sets-4.errors
tests/ParserTests/errors/undefined-flag.cabal
tests/ParserTests/errors/undefined-flag.errors
tests/ParserTests/ipi/Includes2.cabal
tests/ParserTests/ipi/Includes2.expr
tests/ParserTests/ipi/Includes2.format
Expand Down Expand Up @@ -152,6 +156,15 @@ extra-source-files:
tests/ParserTests/regressions/leading-comma.cabal
tests/ParserTests/regressions/leading-comma.expr
tests/ParserTests/regressions/leading-comma.format
tests/ParserTests/regressions/mixin-1.cabal
tests/ParserTests/regressions/mixin-1.expr
tests/ParserTests/regressions/mixin-1.format
tests/ParserTests/regressions/mixin-2.cabal
tests/ParserTests/regressions/mixin-2.expr
tests/ParserTests/regressions/mixin-2.format
tests/ParserTests/regressions/mixin-3.cabal
tests/ParserTests/regressions/mixin-3.expr
tests/ParserTests/regressions/mixin-3.format
tests/ParserTests/regressions/multiple-libs-2.cabal
tests/ParserTests/regressions/multiple-libs-2.check
tests/ParserTests/regressions/multiple-libs-2.expr
Expand Down
69 changes: 47 additions & 22 deletions Cabal/Distribution/Types/ModuleRenaming.hs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE RankNTypes #-}

module Distribution.Types.ModuleRenaming (
ModuleRenaming(..),
Expand All @@ -8,6 +9,7 @@ module Distribution.Types.ModuleRenaming (
isDefaultRenaming,
) where

import Distribution.CabalSpecVersion
import Distribution.Compat.Prelude hiding (empty)
import Prelude ()

Expand Down Expand Up @@ -64,6 +66,8 @@ isDefaultRenaming :: ModuleRenaming -> Bool
isDefaultRenaming DefaultRenaming = True
isDefaultRenaming _ = False



instance Binary ModuleRenaming where

instance NFData ModuleRenaming where rnf = genericRnf
Expand All @@ -81,27 +85,48 @@ instance Pretty ModuleRenaming where
| otherwise = pretty orig <+> text "as" <+> pretty new

instance Parsec ModuleRenaming where
-- NB: try not necessary as the first token is obvious
parsec = P.choice [ parseRename, parseHiding, return DefaultRenaming ]
parsec = do
csv <- askCabalSpecVersion
if csv >= CabalSpecV3_0
then moduleRenamingParsec parensLax lexemeParsec
else moduleRenamingParsec parensStrict parsec
where
parseRename = do
rns <- P.between (P.char '(') (P.char ')') parseList
P.spaces
return (ModuleRenaming rns)
parseHiding = do
_ <- P.string "hiding"
P.spaces
hides <- P.between (P.char '(') (P.char ')')
(P.sepBy parsec (P.char ',' >> P.spaces))
return (HidingRenaming hides)
parseList =
P.sepBy parseEntry (P.char ',' >> P.spaces)
parseEntry = do
orig <- parsec
-- For cabal spec versions < 3.0 white spaces were not skipped after the '('
-- and ')' tokens in the mixin field. This parser checks the cabal file version
-- and does the correct skipping of spaces.
parensLax p = P.between (P.char '(' >> P.spaces) (P.char ')' >> P.spaces) p
parensStrict p = P.between (P.char '(' >> warnSpaces) (P.char ')') p

warnSpaces = P.optional $
P.space *> fail "space after parenthesis, use cabal-version: 3.0 or higher"

moduleRenamingParsec
:: CabalParsing m
=> (forall a. m a -> m a) -- ^ between parens
-> m ModuleName -- ^ module name parser
-> m ModuleRenaming
moduleRenamingParsec bp mn =
-- NB: try not necessary as the first token is obvious
P.choice [ parseRename, parseHiding, return DefaultRenaming ]
where
cma = P.char ',' >> P.spaces
parseRename = do
rns <- bp parseList
P.spaces
return (ModuleRenaming rns)
parseHiding = do
_ <- P.string "hiding"
P.spaces -- space isn't strictly required as next is an open paren
hides <- bp (P.sepBy mn cma)
return (HidingRenaming hides)
parseList =
P.sepBy parseEntry cma
parseEntry = do
orig <- parsec
P.spaces
P.option (orig, orig) $ do
_ <- P.string "as"
P.skipSpaces1 -- require space after "as"
new <- parsec
P.spaces
P.option (orig, orig) $ do
_ <- P.string "as"
P.spaces
new <- parsec
P.spaces
return (orig, new)
return (orig, new)
2 changes: 2 additions & 0 deletions Cabal/doc/file-format-changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ relative to the respective preceding *published* version.
* New set-notation syntax for ``==`` and ``^>=`` operators, see
:pkg-field:`build-depends` field documentation for examples.

* Allow more whitespace in :pkg-field: `mixins` field

``cabal-version: 2.4``
----------------------

Expand Down
5 changes: 5 additions & 0 deletions Cabal/tests/ParserTests.hs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ errorTests = testGroup "errors"
, errorTest "version-sets-3.cabal"
, errorTest "version-sets-4.cabal"
, errorTest "undefined-flag.cabal"
, errorTest "mixin-1.cabal"
, errorTest "mixin-2.cabal"
]

errorTest :: FilePath -> TestTree
Expand Down Expand Up @@ -165,6 +167,9 @@ regressionTests = testGroup "regressions"
, regressionTest "hidden-main-lib.cabal"
, regressionTest "jaeger-flamegraph.cabal"
, regressionTest "version-sets.cabal"
, regressionTest "mixin-1.cabal"
, regressionTest "mixin-2.cabal"
, regressionTest "mixin-3.cabal"
]

regressionTest :: FilePath -> TestTree
Expand Down
15 changes: 15 additions & 0 deletions Cabal/tests/ParserTests/errors/mixin-1.cabal
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
cabal-version: 2.4
name: mixin
version: 0

-- mixin field:
-- in 2.2 we got leading/trailing commas
-- in 3.0 we got lax space parsing
--
-- This should fail
executable str-example
main-is: Main.hs
build-depends: base, str-string, str-bytestring
mixins: str-string ( Str as Str.String ),
str-bytestring ( Str as Str.ByteString ),
hs-source-dirs: str-example
4 changes: 4 additions & 0 deletions Cabal/tests/ParserTests/errors/mixin-1.errors
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
VERSION: Just (mkVersion [2,4])
mixin-1.cabal:13:41:
unexpected space after parenthesis, use cabal-version: 3.0 or higher

14 changes: 14 additions & 0 deletions Cabal/tests/ParserTests/errors/mixin-2.cabal
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
cabal-version: 2.2
name: mixin
version: 0

-- mixin field:
-- in 2.2 we got leading/trailing commas
-- in 2.2 we got lax space parsing
--
-- This should fail
executable str-example
main-is: Main.hs
build-depends: base, str-string, str-bytestring
mixins: str-string hiding ( Foo )
hs-source-dirs: str-example
4 changes: 4 additions & 0 deletions Cabal/tests/ParserTests/errors/mixin-2.errors
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
VERSION: Just (mkVersion [2,2])
mixin-2.cabal:13:48:
unexpected space after parenthesis, use cabal-version: 3.0 or higher

10 changes: 10 additions & 0 deletions Cabal/tests/ParserTests/regressions/mixin-1.cabal
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
cabal-version: 2.0
name: mixin
version: 0

executable str-example
main-is: Main.hs
build-depends: base, str-string, str-bytestring
mixins: str-string (Str as Str.String),
str-bytestring (Str as Str.ByteString)
hs-source-dirs: str-example
118 changes: 118 additions & 0 deletions Cabal/tests/ParserTests/regressions/mixin-1.expr
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
GenericPackageDescription
{condBenchmarks = [],
condExecutables = [_×_
`UnqualComponentName "str-example"`
CondNode
{condTreeComponents = [],
condTreeConstraints = [Dependency
`PackageName "base"`
AnyVersion
(Set.fromList [LMainLibName]),
Dependency
`PackageName "str-string"`
AnyVersion
(Set.fromList [LMainLibName]),
Dependency
`PackageName "str-bytestring"`
AnyVersion
(Set.fromList [LMainLibName])],
condTreeData = Executable
{buildInfo = BuildInfo
{asmOptions = [],
asmSources = [],
autogenModules = [],
buildToolDepends = [],
buildTools = [],
buildable = True,
cSources = [],
ccOptions = [],
cmmOptions = [],
cmmSources = [],
cppOptions = [],
customFieldsBI = [],
cxxOptions = [],
cxxSources = [],
defaultExtensions = [],
defaultLanguage = Nothing,
extraBundledLibs = [],
extraDynLibFlavours = [],
extraFrameworkDirs = [],
extraGHCiLibs = [],
extraLibDirs = [],
extraLibFlavours = [],
extraLibs = [],
frameworks = [],
hsSourceDirs = ["str-example"],
includeDirs = [],
includes = [],
installIncludes = [],
jsSources = [],
ldOptions = [],
mixins = [`Mixin {mixinPackageName = PackageName "str-string", mixinIncludeRenaming = IncludeRenaming {includeProvidesRn = ModuleRenaming [(ModuleName ["Str"],ModuleName ["Str","String"])], includeRequiresRn = DefaultRenaming}}`,
`Mixin {mixinPackageName = PackageName "str-bytestring", mixinIncludeRenaming = IncludeRenaming {includeProvidesRn = ModuleRenaming [(ModuleName ["Str"],ModuleName ["Str","ByteString"])], includeRequiresRn = DefaultRenaming}}`],
oldExtensions = [],
options = PerCompilerFlavor [] [],
otherExtensions = [],
otherLanguages = [],
otherModules = [],
pkgconfigDepends = [],
profOptions = PerCompilerFlavor [] [],
sharedOptions = PerCompilerFlavor [] [],
staticOptions = PerCompilerFlavor [] [],
targetBuildDepends = [Dependency
`PackageName "base"`
AnyVersion
(Set.fromList
[LMainLibName]),
Dependency
`PackageName "str-string"`
AnyVersion
(Set.fromList
[LMainLibName]),
Dependency
`PackageName "str-bytestring"`
AnyVersion
(Set.fromList
[LMainLibName])],
virtualModules = []},
exeName = `UnqualComponentName "str-example"`,
exeScope = ExecutablePublic,
modulePath = "Main.hs"}}],
condForeignLibs = [],
condLibrary = Nothing,
condSubLibraries = [],
condTestSuites = [],
genPackageFlags = [],
packageDescription = PackageDescription
{author = "",
benchmarks = [],
bugReports = "",
buildTypeRaw = Nothing,
category = "",
copyright = "",
customFieldsPD = [],
dataDir = "",
dataFiles = [],
description = "",
executables = [],
extraDocFiles = [],
extraSrcFiles = [],
extraTmpFiles = [],
foreignLibs = [],
homepage = "",
library = Nothing,
licenseFiles = [],
licenseRaw = Left NONE,
maintainer = "",
package = PackageIdentifier
{pkgName = `PackageName "mixin"`,
pkgVersion = `mkVersion [0]`},
pkgUrl = "",
setupBuildInfo = Nothing,
sourceRepos = [],
specVersionRaw = Left `mkVersion [2,0]`,
stability = "",
subLibraries = [],
synopsis = "",
testSuites = [],
testedWith = []}}
14 changes: 14 additions & 0 deletions Cabal/tests/ParserTests/regressions/mixin-1.format
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
cabal-version: 2.0
name: mixin
version: 0

executable str-example
main-is: Main.hs
hs-source-dirs: str-example
build-depends:
base -any,
str-string -any,
str-bytestring -any
mixins:
str-string (Str as Str.String),
str-bytestring (Str as Str.ByteString)
13 changes: 13 additions & 0 deletions Cabal/tests/ParserTests/regressions/mixin-2.cabal
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
cabal-version: 3.0
name: mixin
version: 0

-- mixin field:
-- in 2.2 we got leading/trailing commas
-- in 3.0 we got lax space parsing
executable str-example
main-is: Main.hs
build-depends: base, str-string, str-bytestring
mixins: str-string ( Str as Str.String ),
str-bytestring ( Str as Str.ByteString ),
hs-source-dirs: str-example
Loading

0 comments on commit 7b6627f

Please sign in to comment.