From a5ad6a05d7c271489933f3fd48757388716c17ff Mon Sep 17 00:00:00 2001 From: Veronika Romashkina Date: Fri, 14 Oct 2022 14:50:08 +0100 Subject: [PATCH] [#70] Tripped by comments before pragmas Resolves #70 --- CHANGELOG.md | 6 ++++++ src/Extensions/Module.hs | 17 ++++++++++------- test/Test/Extensions/Module.hs | 16 ++++++++++++++++ 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b116fc4..907b78e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,12 @@ `extensions` uses [PVP Versioning][1]. The changelog is available [on GitHub][2]. +## Unreleased + +* [#70](https://github.com/kowainik/extensions/issues/70): + Parse empty lines and spaces in before comments and pragmas in the beginning + of the file. + ## 0.0.0.1 — May 9, 2020 🎖️ * Handle one more parsing case. diff --git a/src/Extensions/Module.hs b/src/Extensions/Module.hs index d727f77..f1475fd 100644 --- a/src/Extensions/Module.hs +++ b/src/Extensions/Module.hs @@ -31,7 +31,7 @@ import Data.List (nub) import Data.List.NonEmpty (NonEmpty (..)) import System.Directory (doesFileExist) import Text.Parsec (alphaNum, between, char, eof, many, many1, manyTill, noneOf, oneOf, parse, - sepBy1, try, (<|>)) + sepBy1, skipMany, try, (<|>)) import Text.Parsec.ByteString (Parser) import Text.Parsec.Char (anyChar, endOfLine, letter, newline, space, spaces, string) import Text.Read (readMaybe) @@ -106,9 +106,12 @@ It parses language pragmas or comments until end of file or the first line with the function/import/module name. -} extensionsP :: Parser [ParsedExtension] -extensionsP = concat <$> manyTill - (try singleExtensionsP <|> try optionsGhcP <|> try commentP <|> try cppP) - (eof <|> (() <$ manyTill endOfLine letter)) +extensionsP = concat <$> + ( newLines *> + manyTill + (try singleExtensionsP <|> try optionsGhcP <|> try commentP <|> try cppP) + (eof <|> (() <$ manyTill endOfLine letter)) + ) {- | Single LANGUAGE pragma parser. @@ -124,7 +127,7 @@ singleExtensionsP = languagePragmaP (commaSep (nonExtP *> extensionP <* nonExtP) <* spaces) nonExtP :: Parser () -nonExtP = () <$ many (try cppP <|> try commentP) +nonExtP = skipMany (try cppP <|> try commentP) {- | Parses all known and unknown 'OnOffExtension's or 'SafeHaskellExtension's. -} @@ -165,7 +168,7 @@ pragmaP pragmaNameP p = between -- | Comma separated parser. Newlines and spaces are allowed around comma. commaSep :: Parser a -> Parser [a] -commaSep p = p `sepBy1` (try $ newLines *> char ',' <* newLines) +commaSep p = p `sepBy1` try (newLines *> char ',' <* newLines) {- | Haskell comment parser. Supports both single-line comments: @@ -211,4 +214,4 @@ cppP = -- | Any combination of spaces and newlines. newLines :: Parser () -newLines = () <$ many (space <|> endOfLine) +newLines = skipMany (space <|> endOfLine) diff --git a/test/Test/Extensions/Module.hs b/test/Test/Extensions/Module.hs index 4fab2e2..3f57b65 100644 --- a/test/Test/Extensions/Module.hs +++ b/test/Test/Extensions/Module.hs @@ -176,6 +176,22 @@ multiLineCommentsSpec = describe "Parsing extensions with multi-line comments" $ itShouldParse "{- Haskelll -} {-# {- extension -} LANGUAGE {- called -} LambdaCase {- and nothing else -} #-} {- matters -}" [LambdaCase] + itShouldParse (unlines + [ "" + , "{- |" + , "Hello" + , "-}" + , "{-# LANGUAGE CPP #-}" + ]) + [Cpp] + itShouldParse (unlines + [ "" + , "-- | Hey" + , "-- Hello" + , "--" + , "module Abc" + ]) + [] itShouldParse (unlines [ "{-# LANGUAGE TypeApplications , LambdaCase #-}" , "{- hello -}"