ghc-lib-parser-ex 0.20200102 → 0.20200201
raw patch · 10 files changed
+342/−127 lines, 10 filesdep ~ghc-lib-parserdep ~tastyPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: ghc-lib-parser, tasty
API changes (from Hackage documentation)
- Language.Haskell.GhclibParserEx.Parse: fakeLlvmConfig :: LlvmConfig
- Language.Haskell.GhclibParserEx.Parse: fakeSettings :: Settings
- Language.Haskell.GhclibParserEx.Parse: parseExpr :: String -> DynFlags -> ParseResult ECP
- Language.Haskell.GhclibParserEx.Parse: parsePragmasIntoDynFlags :: DynFlags -> FilePath -> String -> IO (Either String DynFlags)
+ Language.Haskell.GhclibParserEx.Config: fakeLlvmConfig :: (LlvmTargets, LlvmPasses)
+ Language.Haskell.GhclibParserEx.Config: fakeSettings :: Settings
+ Language.Haskell.GhclibParserEx.DynFlags: parsePragmasIntoDynFlags :: DynFlags -> ([Extension], [Extension]) -> FilePath -> String -> IO (Either String DynFlags)
+ Language.Haskell.GhclibParserEx.HsExtendInstances: HsExtendInstances :: a -> HsExtendInstances a
+ Language.Haskell.GhclibParserEx.HsExtendInstances: [unextendInstances] :: HsExtendInstances a -> a
+ Language.Haskell.GhclibParserEx.HsExtendInstances: astEq :: Data a => a -> a -> Bool
+ Language.Haskell.GhclibParserEx.HsExtendInstances: astListEq :: Data a => [a] -> [a] -> Bool
+ Language.Haskell.GhclibParserEx.HsExtendInstances: extendInstances :: a -> HsExtendInstances a
+ Language.Haskell.GhclibParserEx.HsExtendInstances: instance Data.Data.Data a => GHC.Classes.Eq (Language.Haskell.GhclibParserEx.HsExtendInstances.HsExtendInstances a)
+ Language.Haskell.GhclibParserEx.HsExtendInstances: instance Data.Data.Data a => GHC.Classes.Ord (Language.Haskell.GhclibParserEx.HsExtendInstances.HsExtendInstances a)
+ Language.Haskell.GhclibParserEx.HsExtendInstances: instance Outputable.Outputable a => GHC.Show.Show (Language.Haskell.GhclibParserEx.HsExtendInstances.HsExtendInstances a)
+ Language.Haskell.GhclibParserEx.HsExtendInstances: instance Outputable.Outputable a => Outputable.Outputable (Language.Haskell.GhclibParserEx.HsExtendInstances.HsExtendInstances a)
+ Language.Haskell.GhclibParserEx.HsExtendInstances: newtype HsExtendInstances a
+ Language.Haskell.GhclibParserEx.Parse: parseBackpack :: String -> DynFlags -> ParseResult [LHsUnit PackageName]
+ Language.Haskell.GhclibParserEx.Parse: parseExpression :: String -> DynFlags -> ParseResult (LHsExpr GhcPs)
+ Language.Haskell.GhclibParserEx.Parse: parseHeader :: String -> DynFlags -> ParseResult (Located (HsModule GhcPs))
+ Language.Haskell.GhclibParserEx.Parse: parseIdentifier :: String -> DynFlags -> ParseResult (Located RdrName)
+ Language.Haskell.GhclibParserEx.Parse: parseModule :: String -> DynFlags -> ParseResult (Located (HsModule GhcPs))
+ Language.Haskell.GhclibParserEx.Parse: parsePattern :: String -> DynFlags -> ParseResult (LPat GhcPs)
+ Language.Haskell.GhclibParserEx.Parse: parseSignature :: String -> DynFlags -> ParseResult (Located (HsModule GhcPs))
+ Language.Haskell.GhclibParserEx.Parse: parseStatement :: String -> DynFlags -> ParseResult (LStmt GhcPs (LHsExpr GhcPs))
+ Language.Haskell.GhclibParserEx.Parse: parseStmt :: String -> DynFlags -> ParseResult (Maybe (LStmt GhcPs (LHsExpr GhcPs)))
+ Language.Haskell.GhclibParserEx.Parse: parseType :: String -> DynFlags -> ParseResult (LHsType GhcPs)
+ Language.Haskell.GhclibParserEx.Parse: parseTypeSignature :: String -> DynFlags -> ParseResult (LHsDecl GhcPs)
Files
- ChangeLog.md +15/−1
- README.md +14/−9
- cbits/ghclib_api.h +1/−1
- ghc-lib-parser-ex.cabal +9/−6
- src/Language/Haskell/GhclibParserEx/Config.hs +75/−0
- src/Language/Haskell/GhclibParserEx/DynFlags.hs +32/−0
- src/Language/Haskell/GhclibParserEx/Fixity.hs +2/−2
- src/Language/Haskell/GhclibParserEx/HsExtendInstances.hs +50/−0
- src/Language/Haskell/GhclibParserEx/Parse.hs +64/−87
- test/Test.hs +80/−21
ChangeLog.md view
@@ -1,3 +1,17 @@ # Changelog for ghc-lib-parser-ex -## 8.8.1.20191204, released 2020-01-18+## Unreleased changes++## 0.20200201 released 2020-02-01+- New modules:+ - `Language.Haskell.GhclibparserEx.HsExtendInstances`.++## 8.8.3.0 released 2020-01-25+- Change in versioning scheme;+- New modules:+ - `Language.Haskell.GhclibParserEx.Config`+ - `Language.Haskell.GhclibParserEx.DynFlags`+- `parsePragmasIntoDynFlags` signature change.++## 8.8.1.20191204, 8.8.2, 0.20200102 released 2020-01-18+- First releases
README.md view
@@ -1,4 +1,4 @@-# ghc-lib-parser-ex [](https://shayne-fletcher.visualstudio.com/ghc-lib-parser-ex/_build/latest?definitionId=1&branchName=master)+# ghc-lib-parser-ex [](http://opensource.org/licenses/BSD-3-Clause) [](https://hackage.haskell.org/package/ghc-lib-parser-ex) [](https://www.stackage.org/package/ghc-lib-parser-ex) [](https://shayne-fletcher.visualstudio.com/ghc-lib-parser-ex/_build/latest?definitionId=1&branchName=master) Copyright © 2020, Shayne Fletcher. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -6,22 +6,27 @@ ## Using `ghc-lib-parser-ex` -The package `ghc-lib-parser-ex` is available on [Hackage](https://hackage.haskell.org/) e.g. `cabal install ghc-lib-parser-ex`. There are two release streams within the `ghc-lib-parser-ex` name (tracking released `ghc-lib-parser` versions exactly):+Package `ghc-lib-parser-ex` is on [Hackage](https://hackage.haskell.org/package/ghc-lib-parser-ex) e.g. `cabal install ghc-lib-parser-ex`. Like `ghc-lib-parser`, there are two release streams within the `ghc-lib-parser-ex` name. -* Version 8.10.1 will be the `ghc-lib-parser-ex` for use against `ghc-lib-parser-8.10.1`(or the released GHC 8.10.1);-* Version 0.20190204 is for use against [`ghc-lib-parser-0.20190204`](http://hackage.haskell.org/package/ghc-lib-0.20190204).+Version numbers are of the form α.β.γ.δ where α.β corresponds to a GHC series and γ.δ are the major and minor parts of the `ghc-lib-ex-parser` package release. Examples:+* Version 8.10.1.3 is compatible with any `ghc-lib-parser-8.10.*` (or `ghc-8.10.*`) package;+* Version 0.20190204.2.0 is compatible with [`ghc-lib-parser-0.20190204`](http://hackage.haskell.org/package/ghc-lib-0.20190204). -### Building `ghc-lib-parser-ex`+The major part γ of the release number indicates an interface breaking change from the previous release. The minor part δ indicates a non-interface breaking change from the previous release. -You can build with `stack build` and test with `stack test`. You can also produce `ghc-lib-parser-ex` package distributions by executing the CI script (which incidentally builds everything and runs the tests).+## Building `ghc-lib-parser-ex`++You can build with `stack build` and test with `stack test`. Produce `ghc-lib-parser-ex` package distributions by executing the CI script: ```bash # Setup git clone git@github.com:shayne-fletcher/ghc-lib-parser-ex.git cd ghc-lib-parser-ex stack runhaskell --package extra --package optparse-applicative CI.hs ```-Run `stack runhaskell --package extra --package optparse-applicative CI.hs -- --help` for more configurability options.+Run `stack runhaskell --package extra --package optparse-applicative CI.hs -- --help` for more options. -## Releasing `ghc-lib` (notes for maintainers)+To run [`hlint`](https://github.com/ndmitchell/hlint) on this repository, `hlint --cpp-include cbits --cpp-define GHCLIB_API_XXX .` (where `XXX` at this time is one of `808`, `810` or `811`). -Build `ghc-lib-parser-ex` using the [above instructions](#building-ghc-lib-parser-ex) and upload the resulting `.tar.gz` files to [Hackage](https://hackage.haskell.org/upload).+## Releasing `ghc-lib-parser-ex` (notes for maintainers)++Update the [changelog](./ChangeLog.md), `git tag <version> && git push origin <version>` then build via the [above instructions](#building-ghc-lib-parser-ex) and upload the resulting `.tar.gz` files to [Hackage](https://hackage.haskell.org/upload).
cbits/ghclib_api.h view
@@ -6,7 +6,7 @@ #if !defined(GHCLIB_API_H) # define GHCLIB_API_H -# if !defined(GHCLIB_API_811) && !defined(GHCLIBAPI_810) && !defined(GHCLIB_API_808)+# if !defined(GHCLIB_API_811) && !defined(GHCLIB_API_810) && !defined(GHCLIB_API_808) # if defined(MIN_VERSION_ghc_lib_parser) # if !MIN_VERSION_ghc_lib_parser(1, 0, 0) # define GHCLIB_API_811
ghc-lib-parser-ex.cabal view
@@ -1,6 +1,6 @@ cabal-version: >= 1.18 name: ghc-lib-parser-ex-version: 0.20200102+version: 0.20200201 description: Please see the README on GitHub at <https://github.com/shayne-fletcher/ghc-lib-parser-ex#readme> homepage: https://github.com/shayne-fletcher/ghc-lib-parser-ex#readme bug-reports: https://github.com/shayne-fletcher/ghc-lib-parser-ex/issues@@ -12,11 +12,11 @@ category: Development synopsis: Algorithms on GHC parse trees build-type: Simple+tested-with: GHC==8.8.2, GHC==8.6.5 extra-source-files: README.md ChangeLog.md-extra-source-files:- cbits/ghclib_api.h+ cbits/ghclib_api.h source-repository head type: git@@ -29,6 +29,9 @@ library exposed-modules:+ Language.Haskell.GhclibParserEx.Config+ Language.Haskell.GhclibParserEx.DynFlags+ Language.Haskell.GhclibParserEx.HsExtendInstances Language.Haskell.GhclibParserEx.Parse Language.Haskell.GhclibParserEx.Outputable Language.Haskell.GhclibParserEx.Dump@@ -47,7 +50,7 @@ ghc-boot-th else build-depends:- ghc-lib-parser == 0.20200102+ ghc-lib-parser include-dirs: cbits install-includes:@@ -67,7 +70,7 @@ ghc-options: -threaded -rtsopts -with-rtsopts=-N build-depends: base >=4.7 && <5- , tasty >= 1.2.3+ , tasty >= 1.2 , tasty-hunit >= 0.10.0 , directory >= 1.3.3 , filepath >= 1.4.2@@ -79,5 +82,5 @@ ghc-boot-th else build-depends:- ghc-lib-parser == 0.20200102+ ghc-lib-parser default-language: Haskell2010
+ src/Language/Haskell/GhclibParserEx/Config.hs view
@@ -0,0 +1,75 @@+-- Copyright (c) 2020, Shayne Fletcher. All rights reserved.+-- SPDX-License-Identifier: BSD-3-Clause.++{-# OPTIONS_GHC -Wno-missing-fields #-}+{-# LANGUAGE CPP #-}+#include "ghclib_api.h"++module Language.Haskell.GhclibParserEx.Config(+ fakeSettings+ , fakeLlvmConfig+ )+ where++import Config+import DynFlags+import Fingerprint++#if defined (GHCLIB_API_811) || defined (GHCLIB_API_810)+import GHC.Platform+import ToolSettings+#else+import Platform+#endif++fakeSettings :: Settings+fakeSettings = Settings+#if defined (GHCLIB_API_811) || defined (GHCLIB_API_810)+ { sGhcNameVersion=ghcNameVersion+ , sFileSettings=fileSettings+ , sTargetPlatform=platform+ , sPlatformMisc=platformMisc+ , sPlatformConstants=platformConstants+ , sToolSettings=toolSettings+ }+#else+ { sTargetPlatform=platform+ , sPlatformConstants=platformConstants+ , sProjectVersion=cProjectVersion+ , sProgramName="ghc"+ , sOpt_P_fingerprint=fingerprint0+ }+#endif+ where+#if defined (GHCLIB_API_811) || defined (GHCLIB_API_810)+ toolSettings = ToolSettings {+ toolSettings_opt_P_fingerprint=fingerprint0+ }+ fileSettings = FileSettings {}+ platformMisc = PlatformMisc {}+ ghcNameVersion =+ GhcNameVersion{ghcNameVersion_programName="ghc"+ ,ghcNameVersion_projectVersion=cProjectVersion+ }+#endif+ platform =+ Platform{+#if defined (GHCLIB_API_811) || defined (GHCLIB_API_810)+ platformWordSize = PW8+ , platformMini = PlatformMini {platformMini_arch=ArchUnknown, platformMini_os=OSUnknown}+#else+ platformWordSize=8+ , platformOS=OSUnknown+#endif+ , platformUnregisterised=True+ }+ platformConstants =+ PlatformConstants{pc_DYNAMIC_BY_DEFAULT=False,pc_WORD_SIZE=8}++#if defined (GHCLIB_API_811) || defined (GHCLIB_API_810)+fakeLlvmConfig :: LlvmConfig+fakeLlvmConfig = LlvmConfig [] []+#else+fakeLlvmConfig :: (LlvmTargets, LlvmPasses)+fakeLlvmConfig = ([], [])+#endif
+ src/Language/Haskell/GhclibParserEx/DynFlags.hs view
@@ -0,0 +1,32 @@+-- Copyright (c) 2020, Shayne Fletcher. All rights reserved.+-- SPDX-License-Identifier: BSD-3-Clause.++module Language.Haskell.GhclibParserEx.DynFlags(+ parsePragmasIntoDynFlags+ ) where++import DynFlags+import Panic+import HeaderInfo+import StringBuffer+import HscTypes+import GHC.LanguageExtensions.Type+import Data.List++parsePragmasIntoDynFlags :: DynFlags+ -> ([Extension], [Extension])+ -> FilePath+ -> String+ -> IO (Either String DynFlags)+parsePragmasIntoDynFlags flags (enable, disable) file str =+ catchErrors $ do+ let opts = getOptions flags (stringToStringBuffer str) file+ (flags, _, _) <- parseDynamicFilePragma flags opts+ let flags' = foldl' xopt_set flags enable+ let flags'' = foldl' xopt_unset flags' disable+ return $ Right (flags'' `gopt_set` Opt_KeepRawTokenStream)+ where+ catchErrors :: IO (Either String DynFlags) -> IO (Either String DynFlags)+ catchErrors act = handleGhcException reportErr+ (handleSourceError reportErr act)+ reportErr e = return $ Left (show e)
src/Language/Haskell/GhclibParserEx/Fixity.hs view
@@ -67,7 +67,7 @@ #if defined (GHCLIB_API_811) || defined (GHCLIB_API_810) | associate_right = ConPatIn op1 (InfixCon p11 (L loc (mkConOpPat fs op2 fix2 p12 p2))) #else- | associate_right = let new_p = mkConOpPat fs op2 fix2 p12 p2 in ConPatIn op1 (InfixCon p11 (cL loc new_p))+ | associate_right = ConPatIn op1 (InfixCon p11 (cL loc (mkConOpPat fs op2 fix2 p12 p2))) #endif | otherwise = ConPatIn op2 (InfixCon p1 p2) where@@ -109,7 +109,7 @@ getIdent (unLoc -> HsVar _ (L _ n)) = occNameString . rdrNameOcc $ n getIdent _ = error "Must be HsVar" --- If there are no fixities provided, give 'baseFixities.+-- If there are no fixities, give 'baseFixities'. getFixities :: [(String, Fixity)] -> [(String, Fixity)] getFixities fixities = if null fixities then baseFixities else fixities
+ src/Language/Haskell/GhclibParserEx/HsExtendInstances.hs view
@@ -0,0 +1,50 @@+-- Copyright (c) 2020, Shayne Fletcher. All rights reserved.+-- SPDX-License-Identifier: BSD-3-Clause.++{-# LANGUAGE GeneralizedNewtypeDeriving #-}++module Language.Haskell.GhclibParserEx.HsExtendInstances (+ HsExtendInstances(..), extendInstances, astEq, astListEq)+where++-- At times, there are terms in Haskell syntax we work with that are+-- not in `Eq`, `Show` or `Ord` and we need them to be.++-- This work-around resorts to implementing Eq and Ord via+-- lexicographic string comparisons. As long as two different terms+-- never map to the same string, basing `Eq` and `Ord` on their string+-- representations rather than the terms themselves, leads to+-- identical results.++import Outputable+import Data.Data+import Data.Function++import Language.Haskell.GhclibParserEx.Dump++newtype HsExtendInstances a =+ HsExtendInstances { unextendInstances :: a }+ deriving Outputable++extendInstances :: a -> HsExtendInstances a+extendInstances = HsExtendInstances++-- Use 'showAstData'. This is preferable to 'ppr' in that trees that+-- only differ in arrangement due to fixities will produce differing+-- string representations.+toStr :: Data a => HsExtendInstances a -> String+toStr (HsExtendInstances e) =+ Outputable.showSDocUnsafe $ showAstData BlankSrcSpan e++instance Data a => Eq (HsExtendInstances a) where (==) a b = toStr a == toStr b+instance Data a => Ord (HsExtendInstances a) where compare = compare `on` toStr++astEq :: Data a => a -> a -> Bool+astEq a b = extendInstances a == extendInstances b++astListEq :: Data a => [a] -> [a] -> Bool+astListEq as bs = length as == length bs && all (uncurry astEq) (zip as bs)++-- Use 'ppr' for 'Show'.+instance Outputable a => Show (HsExtendInstances a) where+ show (HsExtendInstances e) = Outputable.showSDocUnsafe $ Outputable.ppr e
src/Language/Haskell/GhclibParserEx/Parse.hs view
@@ -6,14 +6,21 @@ #include "ghclib_api.h" module Language.Haskell.GhclibParserEx.Parse(- parse- , parseExpr+ parseFile+ , parseModule+ , parseSignature , parseImport+ , parseStatement+ , parseBackpack , parseDeclaration- , parseFile- , parsePragmasIntoDynFlags- , fakeSettings- , fakeLlvmConfig+ , parseExpression+ , parsePattern+ , parseTypeSignature+ , parseStmt+ , parseIdentifier+ , parseType+ , parseHeader+ , parse ) where @@ -23,76 +30,19 @@ #else import HsSyn #endif-import Config import DynFlags import StringBuffer-import Fingerprint import Lexer import qualified Parser import FastString import SrcLoc-import Panic-import HscTypes-import HeaderInfo--#if defined (GHCLIB_API_811) || defined (GHCLIB_API_810)-import GHC.Platform-import ToolSettings-#else-import Platform-#endif--fakeSettings :: Settings-fakeSettings = Settings-#if defined (GHCLIB_API_811) || defined (GHCLIB_API_810)- { sGhcNameVersion=ghcNameVersion- , sFileSettings=fileSettings- , sTargetPlatform=platform- , sPlatformMisc=platformMisc- , sPlatformConstants=platformConstants- , sToolSettings=toolSettings- }-#else- { sTargetPlatform=platform- , sPlatformConstants=platformConstants- , sProjectVersion=cProjectVersion- , sProgramName="ghc"- , sOpt_P_fingerprint=fingerprint0- }-#endif- where-#if defined (GHCLIB_API_811) || defined (GHCLIB_API_810)- toolSettings = ToolSettings {- toolSettings_opt_P_fingerprint=fingerprint0- }- fileSettings = FileSettings {}- platformMisc = PlatformMisc {}- ghcNameVersion =- GhcNameVersion{ghcNameVersion_programName="ghc"- ,ghcNameVersion_projectVersion=cProjectVersion- }-#endif- platform =- Platform{-#if defined (GHCLIB_API_811) || defined (GHCLIB_API_810)- platformWordSize = PW8- , platformMini = PlatformMini {platformMini_arch=ArchUnknown, platformMini_os=OSUnknown}-#else- platformWordSize=8- , platformOS=OSUnknown-#endif- , platformUnregisterised=True- }- platformConstants =- PlatformConstants{pc_DYNAMIC_BY_DEFAULT=False,pc_WORD_SIZE=8}--#if defined (GHCLIB_API_811) || defined (GHCLIB_API_810)-fakeLlvmConfig :: LlvmConfig-fakeLlvmConfig = LlvmConfig [] []+import BkpSyn+#if defined (GHCLIB_API_811)+import UnitInfo #else-fakeLlvmConfig :: (LlvmTargets, LlvmPasses)-fakeLlvmConfig = ([], [])+import PackageConfig #endif+import RdrName parse :: P a -> String -> DynFlags -> ParseResult a parse p str flags =@@ -103,19 +53,61 @@ parseState = mkPState flags buffer location #if defined (GHCLIB_API_811)-parseExpr :: String -> DynFlags -> ParseResult RdrHsSyn.ECP+parseModule :: String -> DynFlags -> ParseResult (Located HsModule) #else-parseExpr :: String -> DynFlags -> ParseResult (LHsExpr GhcPs)+parseModule :: String -> DynFlags -> ParseResult (Located (HsModule GhcPs)) #endif-parseExpr = parse Parser.parseExpression+parseModule = parse Parser.parseModule +#if defined (GHCLIB_API_811)+parseSignature :: String -> DynFlags -> ParseResult (Located HsModule)+#else+parseSignature :: String -> DynFlags -> ParseResult (Located (HsModule GhcPs))+#endif+parseSignature = parse Parser.parseSignature+ parseImport :: String -> DynFlags -> ParseResult (LImportDecl GhcPs) parseImport = parse Parser.parseImport +parseStatement :: String -> DynFlags -> ParseResult (LStmt GhcPs (LHsExpr GhcPs))+parseStatement = parse Parser.parseStatement++parseBackpack :: String -> DynFlags -> ParseResult [LHsUnit PackageName]+parseBackpack = parse Parser.parseBackpack+ parseDeclaration :: String -> DynFlags -> ParseResult (LHsDecl GhcPs) parseDeclaration = parse Parser.parseDeclaration -#if defined (GHC_API_811)+#if defined (GHCLIB_API_811)+parseExpression :: String -> DynFlags -> ParseResult RdrHsSyn.ECP+#else+parseExpression :: String -> DynFlags -> ParseResult (LHsExpr GhcPs)+#endif+parseExpression = parse Parser.parseExpression++parsePattern :: String -> DynFlags -> ParseResult (LPat GhcPs)+parsePattern = parse Parser.parsePattern++parseTypeSignature :: String -> DynFlags -> ParseResult (LHsDecl GhcPs)+parseTypeSignature = parse Parser.parseTypeSignature++parseStmt :: String -> DynFlags -> ParseResult (Maybe (LStmt GhcPs (LHsExpr GhcPs)))+parseStmt = parse Parser.parseStmt++parseIdentifier :: String -> DynFlags -> ParseResult (Located RdrName)+parseIdentifier = parse Parser.parseIdentifier++parseType :: String -> DynFlags -> ParseResult (LHsType GhcPs)+parseType = parse Parser.parseType++#if defined(GHCLIB_API_811)+parseHeader :: String -> DynFlags -> ParseResult (Located HsModule)+#else+parseHeader :: String -> DynFlags -> ParseResult (Located (HsModule GhcPs))+#endif+parseHeader = parse Parser.parseHeader++#if defined (GHCLIB_API_811) parseFile :: String -> DynFlags -> String@@ -132,18 +124,3 @@ location = mkRealSrcLoc (mkFastString filename) 1 1 buffer = stringToStringBuffer str parseState = mkPState flags buffer location--parsePragmasIntoDynFlags :: DynFlags- -> FilePath- -> String- -> IO (Either String DynFlags)-parsePragmasIntoDynFlags flags file str =- catchErrors $ do- let opts = getOptions flags (stringToStringBuffer str) file- (flags, _, _) <- parseDynamicFilePragma flags opts- return $ Right (flags `gopt_set` Opt_KeepRawTokenStream)- where- catchErrors :: IO (Either String DynFlags) -> IO (Either String DynFlags)- catchErrors act = handleGhcException reportErr- (handleSourceError reportErr act)- reportErr e = return $ Left (show e)
test/Test.hs view
@@ -13,20 +13,21 @@ import System.IO.Extra import Control.Monad +import Language.Haskell.GhclibParserEx.Config+import Language.Haskell.GhclibParserEx.DynFlags+import Language.Haskell.GhclibParserEx.HsExtendInstances import Language.Haskell.GhclibParserEx.Parse import Language.Haskell.GhclibParserEx.Dump import Language.Haskell.GhclibParserEx.Fixity #if defined (GHCLIB_API_811) || defined (GHCLIB_API_810) import GHC.Hs-#else-import HsSyn+import RdrHsSyn #endif import DynFlags import Lexer import Outputable import ErrUtils-import RdrHsSyn #if defined (GHCLIB_API_808) import Bag #endif@@ -38,7 +39,7 @@ defaultMain tests tests :: TestTree-tests = testGroup " All tests" [parseTests, fixityTests]+tests = testGroup " All tests" [parseTests, fixityTests, extendInstancesTests] chkParseResult :: (DynFlags -> WarningMessages -> String) -> DynFlags -> ParseResult a -> IO () chkParseResult report flags = \case@@ -55,36 +56,59 @@ parseTests :: TestTree parseTests = testGroup "Parse tests" [- testCase "Expression" $ do- let flags = defaultDynFlags fakeSettings fakeLlvmConfig+ testCase "Module" $ chkParseResult report flags $- parseExpr "unfoldr $ listToMaybe . concatMap reads . tails" flags- , testCase "Import" $ do- let flags = defaultDynFlags fakeSettings fakeLlvmConfig+ parseModule (unlines+ [ "module Foo (readMany) where"+ , "import Data.List"+ , "import Data.Maybe"+ , "readMany = unfoldr $ listToMaybe . concatMap reads . tails"+ ]) flags+ , testCase "Signature" $ chkParseResult report flags $+ parseSignature (unlines+ [ "signature Str where"+ , "data Str"+ , "empty :: Str"+ , "append :: Str -> Str -> Str"+ ]) flags+ , testCase "Import" $+ chkParseResult report flags $ parseImport "import qualified \"foo-lib\" Foo as Bar hiding ((<.>))" flags- , testCase "Declaration" $ do- let flags = defaultDynFlags fakeSettings fakeLlvmConfig+ , testCase "Statement" $ chkParseResult report flags $- parseDeclaration (- unlines [- "fact :: Int -> Int"- , "fact n = if n <= 1 then 1 else n * fact (n - 1)"- ]) flags+ parseStatement "Foo foo <- bar" flags+ , testCase "Backpack" $+ chkParseResult report flags $+ parseBackpack (unlines+ [ "unit main where"+ , " module Main where"+ , " main = putStrLn \"Hello world!\""+ ]) flags+ , testCase "Expression" $+ chkParseResult report flags $+ parseExpression "unfoldr $ listToMaybe . concatMap reads . tails" flags+ , testCase "Declaration (1)" $+ chkParseResult report flags $+ parseDeclaration "fact n = if n <= 1 then 1 else n * fact (n - 1)" flags+ , testCase "Declaration (2)" $ -- Example from https://github.com/ndmitchell/hlint/issues/842.+ chkParseResult report flags $+ parseDeclaration "infixr 4 <%@~" flags , testCase "File" $ do foo <- makeFile "Foo.hs" $ unlines- [ "module Foo (readMany) where"+ ["{-# LANGUAGE ScopedTypeVariables #-}"+ , "module Foo (readMany) where" , "import Data.List" , "import Data.Maybe" , "readMany = unfoldr $ listToMaybe . concatMap reads . tails" ] s <- readFile' foo- parsePragmasIntoDynFlags (defaultDynFlags fakeSettings fakeLlvmConfig) foo s >>= \case+ parsePragmasIntoDynFlags flags ([], []) foo s >>= \case Left msg -> assertFailure msg- Right flags ->- chkParseResult report flags $ parseFile foo (flags `gopt_set` Opt_KeepRawTokenStream) s+ Right flags -> chkParseResult report flags $ parseFile foo flags s ] where+ flags = unsafeGlobalDynFlags report flags msgs = concat [ showSDoc flags msg | msg <- pprErrMsgBagWithLoc msgs ] fixityTests :: TestTree@@ -92,8 +116,12 @@ [ testCase "Expression" $ do let flags = defaultDynFlags fakeSettings fakeLlvmConfig- case parseExpr "1 + 2 * 3" flags of+ case parseExpression "1 + 2 * 3" flags of+#if defined (GHCLIB_API_811) || defined (GHCLIB_API_810) POk s e ->+#else+ POk _ e ->+#endif #if defined (GHCLIB_API_811) || defined (GHCLIB_API_810) case unP (runECP_P e >>= \e -> return e) s :: ParseResult (LHsExpr GhcPs) of POk _ e ->@@ -120,3 +148,34 @@ Directory.createDirectoryIfMissing True $ FilePath.takeDirectory relPath writeFile relPath contents return relPath++extendInstancesTests :: TestTree+extendInstancesTests = testGroup "Extend instances tests"+ [+ testCase "Eq, Ord" $ do+ let flags = defaultDynFlags fakeSettings fakeLlvmConfig+ case parseExpression "1 + 2 * 3" flags of+#if defined (GHCLIB_API_811) || defined (GHCLIB_API_810)+ POk s e ->+#else+ POk _ e ->+#endif+#if defined (GHCLIB_API_811) || defined (GHCLIB_API_810)+ case unP (runECP_P e >>= \e -> return e) s :: ParseResult (LHsExpr GhcPs) of+ POk _ e ->+#endif+ do+ e' <- return $ applyFixities [] e+ assertBool "astEq" $ astEq e e+ assertBool "astEq" $ not (astEq e e')+ e <- return $ extendInstances e+ e' <- return $ extendInstances e'+ assertBool "==" $ e == e+ assertBool "/=" $ e /= e'+ assertBool "< " $ e' < e+ assertBool ">=" $ e >= e'+#if defined (GHCLIB_API_811) || defined (GHCLIB_API_810)+ _ -> assertFailure "ecp failure"+#endif+ _ -> assertFailure "parse error"+ ]