Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 43 additions & 23 deletions Cabal-syntax/src/Distribution/FieldGrammar/Parsec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ instance FieldGrammar Parsec ParsecFieldGrammar where

parseOne v (MkNamelessField pos fls)
| null fls = pure Nothing
| v >= CabalSpecV3_0 = pure (Just (fieldlinesToFreeText3 pos fls))
| v >= CabalSpecV3_0 = Just <$> fieldlinesToFreeText3 pos fls
| otherwise = pure (Just (fieldlinesToFreeText fls))

freeTextFieldDef fn _ = ParsecFG (Set.singleton fn) Set.empty parser
Expand All @@ -249,7 +249,7 @@ instance FieldGrammar Parsec ParsecFieldGrammar where

parseOne v (MkNamelessField pos fls)
| null fls = pure ""
| v >= CabalSpecV3_0 = pure (fieldlinesToFreeText3 pos fls)
| v >= CabalSpecV3_0 = fieldlinesToFreeText3 pos fls
| otherwise = pure (fieldlinesToFreeText fls)

-- freeTextFieldDefST = defaultFreeTextFieldDefST
Expand All @@ -267,7 +267,7 @@ instance FieldGrammar Parsec ParsecFieldGrammar where
[] -> pure mempty
[FieldLine _ bs] -> pure (ShortText.unsafeFromUTF8BS bs)
_
| v >= CabalSpecV3_0 -> pure (ShortText.toShortText $ fieldlinesToFreeText3 pos fls)
| v >= CabalSpecV3_0 -> ShortText.toShortText <$> fieldlinesToFreeText3 pos fls
| otherwise -> pure (ShortText.toShortText $ fieldlinesToFreeText fls)

monoidalFieldAla fn _pack _extract = ParsecFG (Set.singleton fn) Set.empty parser
Expand Down Expand Up @@ -411,45 +411,65 @@ fieldlinesToFreeText fls = intercalate "\n" (map go fls)
where
s = trim (fromUTF8BS bs)

fieldlinesToFreeText3 :: Position -> [FieldLine Position] -> String
fieldlinesToFreeText3 _ [] = ""
fieldlinesToFreeText3 _ [FieldLine _ bs] = fromUTF8BS bs
fieldlinesToFreeText3 :: Position -> [FieldLine Position] -> ParseResult src String
fieldlinesToFreeText3 _ [] = pure ""
fieldlinesToFreeText3 _ [FieldLine _ bs] = pure $ fromUTF8BS bs
fieldlinesToFreeText3 pos (FieldLine pos1 bs1 : fls2@(FieldLine pos2 _ : _))
-- if first line is on the same line with field name:
-- the indentation level is either
-- 1. the indentation of left most line in rest fields
-- 2. the indentation of the first line
-- whichever is leftmost
| positionRow pos == positionRow pos1 =
concat $
fromUTF8BS bs1
: mealy (mk mcol1) pos1 fls2
| positionRow pos == positionRow pos1 = do
s1 <- parseLine3 pos1 bs1
xs <- mealy (mk mcol1) pos1 fls2
pure $ concat (s1 : xs)
-- otherwise, also indent the first line
| otherwise =
concat $
replicate (positionCol pos1 - mcol2) ' '
: fromUTF8BS bs1
: mealy (mk mcol2) pos1 fls2
| otherwise = do
s1 <- parseLine3 pos1 bs1
xs <- mealy (mk mcol2) pos1 fls2
pure $
concat $
replicate (positionCol pos1 - mcol2) ' '
: s1
: xs
where
mcol1 = foldl' (\a b -> min a $ positionCol $ fieldLineAnn b) (min (positionCol pos1) (positionCol pos2)) fls2
mcol2 = foldl' (\a b -> min a $ positionCol $ fieldLineAnn b) (positionCol pos1) fls2

mk :: Int -> Position -> FieldLine Position -> (Position, String)
mk :: Int -> Position -> FieldLine Position -> ParseResult src (Position, String)
mk col p (FieldLine q bs) =
( q
, replicate newlines '\n'
++ replicate indent ' '
++ fromUTF8BS bs
( \s ->
( q
, replicate newlines '\n'
++ replicate indent ' '
++ s
)
)
<$> parseLine3 q bs
where
newlines = positionRow q - positionRow p
indent = positionCol q - col

mealy :: (s -> a -> (s, b)) -> s -> [a] -> [b]
parseLine3 :: Position -> BS.ByteString -> ParseResult src String
parseLine3 p bs = do
when (s' == ".") $ parseWarning p PWTDotline msg
pure s
where
s = fromUTF8BS bs
s' = trim s

msg =
"Empty lines with a dot '.' are unnecessary for creating newlines "
++ "(and treated literally) in cabal 3.0+"

mealy :: Monad m => (s -> a -> m (s, b)) -> s -> [a] -> m [b]
mealy f = go
where
go _ [] = []
go s (x : xs) = let ~(s', y) = f s x in y : go s' xs
go _ [] = pure []
go s (x : xs) = do
~(s', y) <- f s x
(y :) <$> go s' xs

fieldLinesToStream :: [FieldLine ann] -> FieldLineStream
fieldLinesToStream [] = fieldLineStreamEnd
Expand Down
5 changes: 5 additions & 0 deletions Cabal-syntax/src/Distribution/Parsec/Warning.hs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ data PWarnType
PWTInconsistentIndentation
| -- | Experimental feature
PWTExperimental
| -- | A line whose only non-whitespace is a dot '.'. Prior to cabal 3.0,
-- this was the only way to force a newline for haddock rendering. With
-- cabal 3.0, such dots no longer render as newlines hence should be
-- removed.
PWTDotline
deriving (Eq, Ord, Show, Enum, Bounded, Generic)

instance Binary PWarnType
Expand Down
4 changes: 4 additions & 0 deletions Cabal-tests/tests/ParserTests/ipi/issue-2276-ghc-9885.format
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
.:23:5: Empty lines with a dot '.' are unnecessary for creating newlines (and treated literally) in cabal 3.0+
.:19:5: Empty lines with a dot '.' are unnecessary for creating newlines (and treated literally) in cabal 3.0+
.:16:5: Empty lines with a dot '.' are unnecessary for creating newlines (and treated literally) in cabal 3.0+
.:14:5: Empty lines with a dot '.' are unnecessary for creating newlines (and treated literally) in cabal 3.0+
name: transformers
version: 0.5.2.0
visibility: public
Expand Down
4 changes: 4 additions & 0 deletions Cabal-tests/tests/ParserTests/ipi/transformers.format
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
.:23:5: Empty lines with a dot '.' are unnecessary for creating newlines (and treated literally) in cabal 3.0+
.:19:5: Empty lines with a dot '.' are unnecessary for creating newlines (and treated literally) in cabal 3.0+
.:16:5: Empty lines with a dot '.' are unnecessary for creating newlines (and treated literally) in cabal 3.0+
.:14:5: Empty lines with a dot '.' are unnecessary for creating newlines (and treated literally) in cabal 3.0+
name: transformers
version: 0.5.2.0
visibility: public
Expand Down
3 changes: 3 additions & 0 deletions Cabal-tests/tests/ParserTests/regressions/indentation.format
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
indentation.cabal:14:3: Empty lines with a dot '.' are unnecessary for creating newlines (and treated literally) in cabal 3.0+
indentation.cabal:13:3: Empty lines with a dot '.' are unnecessary for creating newlines (and treated literally) in cabal 3.0+
indentation.cabal:12:3: Empty lines with a dot '.' are unnecessary for creating newlines (and treated literally) in cabal 3.0+
cabal-version: 3.0
name: indentation
version: 0
Expand Down
12 changes: 12 additions & 0 deletions cabal-testsuite/PackageTests/DotlineWarning/Post3.0/cabal.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# cabal v2-build
Warning: The package description file ./main.cabal has warnings:
main.cabal:21:3: Empty lines with a dot '.' are unnecessary for creating newlines (and treated literally) in cabal 3.0+
main.cabal:19:3: Empty lines with a dot '.' are unnecessary for creating newlines (and treated literally) in cabal 3.0+
main.cabal:17:3: Empty lines with a dot '.' are unnecessary for creating newlines (and treated literally) in cabal 3.0+
main.cabal:15:3: Empty lines with a dot '.' are unnecessary for creating newlines (and treated literally) in cabal 3.0+
main.cabal:12:3: Empty lines with a dot '.' are unnecessary for creating newlines (and treated literally) in cabal 3.0+
main.cabal:10:3: Empty lines with a dot '.' are unnecessary for creating newlines (and treated literally) in cabal 3.0+
Resolving dependencies...
Build profile: -w ghc-<GHCVER> -O1
In order, the following would be built:
- main-0.1 (lib) (first run)
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import Test.Cabal.Prelude

main = cabalTest $ do
cabal "v2-build" ["--dry-run"]
26 changes: 26 additions & 0 deletions cabal-testsuite/PackageTests/DotlineWarning/Post3.0/main.cabal
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
cabal-version: 3.0

name: main
version: 0.1
build-type: Simple
category: Test
maintainer: Joe
synopsis:
Test input
.
with
.
lines
description:
.
Some . description
.
spanning .
.
multiple lines.
.
license: BSD-3-Clause

library
build-depends: base
default-language: Haskell2010
5 changes: 5 additions & 0 deletions cabal-testsuite/PackageTests/DotlineWarning/Pre3.0/cabal.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# cabal v2-build
Resolving dependencies...
Build profile: -w ghc-<GHCVER> -O1
In order, the following would be built:
- main-0.1 (lib) (first run)
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import Test.Cabal.Prelude

main = cabalTest $ do
cabal "v2-build" ["--dry-run"]
26 changes: 26 additions & 0 deletions cabal-testsuite/PackageTests/DotlineWarning/Pre3.0/main.cabal
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
cabal-version: 2.4

name: main
version: 0.1
build-type: Simple
category: Test
maintainer: Joe
synopsis:
Test input
.
with
.
lines
description:
.
Some . description
.
spanning .
.
multiple lines.
.
license: BSD-3-Clause

library
build-depends: base
default-language: Haskell2010
21 changes: 21 additions & 0 deletions changelog.d/pr-11571
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
synopsis: Warning for "dotlines" with cabal 3.0+.
packages: cabal-install Cabal-syntax
prs: #11571
issues: #11518
significance:

description: {

Cabal 3.0 changed the parser for "free text" fields (e.g. description) such
that:

1. Empty lines and indentation are preserved.

2. Empty lines with a dot '.' (and possible whitespace) are
interpreted literally; they are no longer interpreted as an
empty line.

Consequently, dotlines no longer serve a purpose and only add extra noise,
hence these are now a warning with `cabal check`.

}
Loading