diff --git a/app/Main.hs b/app/Main.hs index c8dbf9f..2ee4c7a 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -1,4 +1,27 @@ module Main (main) where +import Control.Monad +import Ormolu.Parser +import System.Environment (getArgs) +import qualified Outputable as GHC + main :: IO () -main = return () +main = do + (path:_) <- getArgs + input <- readFile path + (ws, r) <- parseModule [] path input + unless (null ws) $ + putStrLn "dynamic option warnings:" + -- TODO print ws + case r of + Left (srcSpan, err) -> do + putStrLn (showOutputable srcSpan) + putStrLn err + Right (anns, parsedModule) -> do + putStrLn "\nannotations:\n" + putStrLn (showOutputable anns) + putStrLn "\nparsed module:\n" + putStrLn (showOutputable parsedModule) + +showOutputable :: GHC.Outputable o => o -> String +showOutputable = GHC.showSDocUnsafe . GHC.ppr diff --git a/ormolu.cabal b/ormolu.cabal index a4a978f..15034c2 100644 --- a/ormolu.cabal +++ b/ormolu.cabal @@ -25,7 +25,11 @@ flag dev library hs-source-dirs: src - build-depends: base + build-depends: base >= 4.8 && < 5.0 + , data-default-class + , ghc >= 8.4.3 + , ghc-boot-th >= 8.4.3 + , ghc-exactprint >= 0.5.6 exposed-modules: Ormolu , Ormolu.Parser , Ormolu.Printer @@ -45,7 +49,7 @@ test-suite tests main-is: Main.hs hs-source-dirs: tests type: exitcode-stdio-1.0 - build-depends: base + build-depends: base >= 4.8 && < 5.0 , ormolu if flag(dev) ghc-options: -Wall -Werror @@ -56,7 +60,8 @@ test-suite tests executable ormolu main-is: Main.hs hs-source-dirs: app - build-depends: base + build-depends: base >= 4.8 && < 5.0 + , ghc >= 8.4.3 , ormolu if flag(dev) ghc-options: -Wall -Werror -Wcompat diff --git a/src/Ormolu/Parser.hs b/src/Ormolu/Parser.hs index 65de79a..96a4cd3 100644 --- a/src/Ormolu/Parser.hs +++ b/src/Ormolu/Parser.hs @@ -1,3 +1,22 @@ module Ormolu.Parser - ( ) + ( parseModule ) where + +import Language.Haskell.GHC.ExactPrint.Parsers hiding (parseModule) +import Language.Haskell.GHC.ExactPrint.Types +import Ormolu.Type +import qualified CmdLineParser as GHC +import qualified DynFlags as GHC +import qualified GHC hiding (parseModule) + +-- | Parse a complete module from string. + +parseModule + :: [DynOption] -- ^ Dynamic options that affect parsing + -> FilePath -- ^ File name (only for source location annotations) + -> String -- ^ Input for parser + -> IO ([GHC.Warn], Either (GHC.SrcSpan, String) (Anns, GHC.ParsedSource)) +parseModule dynOpts path input = ghcWrapper $ do + dynFlags0 <- initDynFlagsPure path input + (dynFlags1, _, ws) <- GHC.parseDynamicFilePragma dynFlags0 (dynOption <$> dynOpts) + return (ws, parseModuleFromStringInternal dynFlags1 path input) diff --git a/src/Ormolu/Type.hs b/src/Ormolu/Type.hs index 3a4ecef..302a874 100644 --- a/src/Ormolu/Type.hs +++ b/src/Ormolu/Type.hs @@ -1,3 +1,35 @@ module Ormolu.Type - ( ) + ( Config (..) + , DynOption (..) + , dynOption + ) where + +import Data.Default.Class +import qualified SrcLoc as GHC + +-- | Ormolu configuration. + +data Config = Config + { cfgLineWidth :: Int + , cfgIndentStep :: Int + , cfgDynOptions :: [DynOption] + } + +instance Default Config where + def = Config + { cfgLineWidth = 80 + , cfgIndentStep = 2 + , cfgDynOptions = [] + } + +-- | A wrapper for dynamic options. + +newtype DynOption = DynOption + { unDynOption :: String + } deriving (Eq, Ord, Show) + +-- | Convert 'DynOption' to @'GHC.Located' 'String'@. + +dynOption :: DynOption -> GHC.Located String +dynOption (DynOption o) = GHC.L GHC.noSrcSpan o