Skip to content

Use ghc-lib-parser with stylish-haskell #293

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 81 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
3946b64
Add initial parsing logic for using ghc-lib-parser instead of haskell…
felixmulder Jul 13, 2020
e9f63dc
Add comments parsing capability
felixmulder Jul 14, 2020
4278c11
Restructure interface to be a bit more similar to old stylish
felixmulder Jul 14, 2020
0005bba
Only do module header in stylish step
felixmulder Jul 14, 2020
97a9c57
Print both imports and module header in stylish regular path
felixmulder Jul 14, 2020
dc92f92
Hook up old stylish to new one
felixmulder Jul 15, 2020
03e3e39
Finish implemntation of module header
felixmulder Jul 15, 2020
bf38e53
Print more helpful error message when encountering a parser error
felixmulder Jul 15, 2020
196f445
Implement missing printer for IEThingWith
felixmulder Jul 15, 2020
f2a0cd6
Make sure that imports respect grouping
felixmulder Jul 15, 2020
58424cd
Fix issue where 'where' might be repeated due to not being a part of AST
felixmulder Jul 16, 2020
0c7072f
Start moving printers into steps
felixmulder Jul 17, 2020
627448a
Remove unused decl printer
felixmulder Jul 17, 2020
bb8e157
Move imports printer to step
felixmulder Jul 17, 2020
5ea2bbe
Enable more of the old steps and list which one need to be fixed
felixmulder Jul 17, 2020
f66b9f2
Make sure that module imports don't bother rest of file
felixmulder Jul 17, 2020
d36cced
Factor out function to associate comments with groups of expressions
felixmulder Jul 17, 2020
b989066
Make sure imports respect groups and preserve comments
felixmulder Jul 17, 2020
8032ebb
Add ability to save return value of running printer
felixmulder Jul 18, 2020
da96a3b
Add GHC module for utility functions
felixmulder Jul 18, 2020
a1e7cf9
Make sure imports step respects groupings
felixmulder Jul 18, 2020
0516749
Fix hiding getting an extra space
felixmulder Jul 18, 2020
9e72c96
Move baseDynFlags to GHC util module
felixmulder Jul 18, 2020
30c68a0
Fix printing of exports that are symbolic
felixmulder Jul 18, 2020
d02f0b6
Add span to error message for hint on where error is
felixmulder Jul 18, 2020
f555e4f
Add config option to emit non-zero exit code when reformatting
felixmulder Jul 19, 2020
3beaf57
Implement data decl step
felixmulder Jul 21, 2020
abae160
Add records step to list of finished steps
felixmulder Jul 21, 2020
afb226e
Implement deriving via printing
felixmulder Jul 21, 2020
be7cdb9
Fix indentation on enums with deriving clauses
felixmulder Jul 21, 2020
db7c1fa
Fix multi decl formatting and newtype formatting
felixmulder Jul 22, 2020
2e9a291
Handle infix constructors when printing data decls
felixmulder Jul 22, 2020
24e7c44
Make sure docstrings are included if they precede `=` sign
felixmulder Jul 22, 2020
257e24a
Homogenize handling of comments between type name and `=` sign
felixmulder Jul 22, 2020
92068f0
Make sure newtypes are broken before `=` sign if indent eq is set
felixmulder Jul 22, 2020
cdcd2c5
Add support for indenting via clauses
felixmulder Jul 22, 2020
9152671
Fix function printing in data decl step
felixmulder Jul 23, 2020
5d63611
Print type literals in a uniform way
felixmulder Jul 23, 2020
137d048
Print type operators in a uniform way
felixmulder Jul 23, 2020
f022ac2
Make sure nested type literals are properly printed
felixmulder Jul 23, 2020
01a8dbd
Fix printing of promoted constructors
felixmulder Jul 23, 2020
4be10fa
Move type printing to printer module
felixmulder Jul 23, 2020
34c5c2b
Move around and document a few functions
felixmulder Jul 23, 2020
2822e25
Fix double space after infix type name
felixmulder Jul 23, 2020
6b636c8
Allow old steps to be run alongside new ones
felixmulder Jul 23, 2020
b8677cd
Fix issue where comment is not printed after type name and newline
felixmulder Jul 23, 2020
8826da3
Add missing EOL comment printing to constructors
felixmulder Jul 23, 2020
126577e
Rename step to show that it's using ghc-lib-parser
felixmulder Jul 23, 2020
1749866
Fix incorrect error string in parseModuleHSE
felixmulder Jul 23, 2020
0271e8a
Fix off-by-one error
felixmulder Jul 23, 2020
e406fa1
Work around edge-case where there are comments _in_ a deriving block
felixmulder Jul 23, 2020
a8f91c9
Make sure previous fix is idempotent
felixmulder Jul 23, 2020
ecb69c9
Reformulate predicate for inserting comments before eq to single binding
felixmulder Jul 24, 2020
a9d6248
Implement language pragma step with ghc-lib-parser
felixmulder Jul 24, 2020
58a12b4
Add SYB query function for `Module`
felixmulder Jul 25, 2020
ff3990c
Implement redundant view/bang pattern functions using SYB query API
felixmulder Jul 25, 2020
313bc77
Fix remaining configuration tests
felixmulder Jul 25, 2020
3b77027
Bump haskell docker image to get newer version of stack
felixmulder Jul 25, 2020
32385f4
Remove outputable helper export from printer module
felixmulder Jul 25, 2020
0250597
Document Module module
felixmulder Jul 25, 2020
e39bfd1
Correct comment on language string length
felixmulder Jul 25, 2020
e5d5a0e
Add comment for `putAllSpanComments`
felixmulder Jul 25, 2020
ff35fb3
Rename `putModulePrefix` to `putModuleName`
felixmulder Jul 25, 2020
0dda96b
Document new configuration options
felixmulder Jul 25, 2020
115325a
Fix issue with incomplete pattern match on AST
felixmulder Jul 25, 2020
b47d606
Add missing documentation on how to enable module header formatting
felixmulder Jul 25, 2020
46ca865
Add configurability on curried context and implement simple GADT support
felixmulder Jul 26, 2020
3f16447
Fix typo in config file: 'parsre' -> 'parse'
felixmulder Jul 28, 2020
0611d91
Remove redundant '$'
felixmulder Jul 28, 2020
b46676d
Use `on` for compare function
felixmulder Jul 29, 2020
99ceb58
Rename `Imports'` to `ImportsGHC`
felixmulder Jul 29, 2020
98e82ee
Use CPP to get rid of monoid warning for newer GHC versions
felixmulder Jul 29, 2020
34f333b
Implement equality for `Import` decl
felixmulder Jul 29, 2020
a556f59
Implement ability to merge imports in ImportsGHC
felixmulder Jul 29, 2020
e1b7a64
Add formatting for long deriving clauses
felixmulder Aug 24, 2020
18f96cb
Pass max columns to ImportsGHC step
felixmulder Aug 24, 2020
fe97c30
Add ability to split import lines that are too long
felixmulder Aug 24, 2020
f9d5d77
Add testing function that has sane expected/got for long lines
felixmulder Aug 25, 2020
14cc117
Fix issue with multiple groups in due to abusing editor functions
felixmulder Aug 25, 2020
4208e1b
Don't split 'hiding' imports since it changes the scope
felixmulder Aug 25, 2020
d11358a
Make sure that nullary imports are not deleted
felixmulder Aug 25, 2020
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
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ workflows:
jobs:
build:
docker:
- image: 'haskell:8.6'
- image: 'haskell:8.8.3'

steps:
- checkout
Expand Down
48 changes: 48 additions & 0 deletions data/stylish-haskell.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ steps:
# # true.
# add_language_pragma: true

# Format module header
#
# Currently, this option is not configurable and will format all exports and
# module declarations to minimize diffs
#
# - module_header: {}

# Format record definitions. This is disabled by default.
#
# You can control the layout of record fields. The only rules that can't be configured
Expand Down Expand Up @@ -42,6 +49,31 @@ steps:
#
# # How many spaces to insert before "deriving" clause. Deriving clauses are always on separate lines.
# deriving: 2
#
# # How many spaces to insert before "via" clause counted from indentation of deriving clause
# # Possible values:
# # - "same_line" -- "{" and first field goes on the same line as the data constructor.
# # - "indent N" -- insert a new line and N spaces from the beginning of the data constructor
# via: "indent 2"
#
# # Wheter or not to break enums onto several lines
# #
# # Default: false
# break_enums: false
#
# # Whether or not to break single constructor data types before `=` sign
# #
# # Default: true
# break_single_constructors: true
#
# # Whether or not to curry constraints on function.
# #
# # E.g: @allValues :: Enum a => Bounded a => Proxy a -> [a]@
# #
# # Instead of @allValues :: (Enum a, Bounded a) => Proxy a -> [a]@
# #
# # Default: false
# curried_context: false

# Align the right hand side of some elements. This is quite conservative
# and only applies to statements where each element occupies a single
Expand Down Expand Up @@ -203,6 +235,22 @@ steps:
# Default: false
space_surround: false

# Enabling this argument will use the new GHC lib parse to format imports.
#
# This currently assumes a few things, it will assume that you want post
# qualified imports. It is also not as feature complete as the old
# imports formatting.
#
# It does not remove redundant lines or merge lines. As such, the full
# feature scope is still pending.
#
# It _is_ however, a fine alternative if you are using features that are
# not parseable by haskell src extensions and you're comfortable with the
# presets.
#
# Default: false
ghc_lib_parser: false

# Language pragmas
- language_pragmas:
# We can generate different styles of language pragma lists.
Expand Down
19 changes: 13 additions & 6 deletions lib/Language/Haskell/Stylish.hs
Original file line number Diff line number Diff line change
Expand Up @@ -91,14 +91,21 @@ unicodeSyntax = UnicodeSyntax.step

--------------------------------------------------------------------------------
runStep :: Extensions -> Maybe FilePath -> Lines -> Step -> Either String Lines
runStep exts mfp ls step =
stepFilter step ls <$> parseModule exts mfp (unlines ls)

runStep exts mfp ls = \case
Step _name step ->
step ls <$> parseModule exts mfp (unlines ls)
OldStep _name step ->
step ls <$> parseModuleHSE exts mfp (unlines ls)

--------------------------------------------------------------------------------
runSteps :: Extensions -> Maybe FilePath -> [Step] -> Lines
-> Either String Lines
runSteps exts mfp steps ls = foldM (runStep exts mfp) ls steps
runSteps ::
Extensions
-> Maybe FilePath
-> [Step]
-> Lines
-> Either String Lines
runSteps exts mfp steps ls =
foldM (runStep exts mfp) ls steps

newtype ConfigPath = ConfigPath { unConfigPath :: FilePath }

Expand Down
7 changes: 7 additions & 0 deletions lib/Language/Haskell/Stylish/Block.hs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ module Language.Haskell.Stylish.Block
, moveBlock
, adjacent
, merge
, mergeAdjacent
, overlapping
, groupAdjacent
) where
Expand Down Expand Up @@ -94,3 +95,9 @@ groupAdjacent = foldr go []
go (b1, x) gs = case break (adjacent b1 . fst) gs of
(_, []) -> (b1, [x]) : gs
(ys, ((b2, xs) : zs)) -> (merge b1 b2, x : xs) : (ys ++ zs)

mergeAdjacent :: [Block a] -> [Block a]
mergeAdjacent (a : b : rest) | a `adjacent` b = merge a b : mergeAdjacent rest
mergeAdjacent (a : rest) = a : mergeAdjacent rest
mergeAdjacent [] = []

75 changes: 58 additions & 17 deletions lib/Language/Haskell/Stylish/Config.hs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
--------------------------------------------------------------------------------
{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
module Language.Haskell.Stylish.Config
( Extensions
, Config (..)
, ExitCodeBehavior (..)
, defaultConfigBytes
, configFilePath
, loadConfig
Expand Down Expand Up @@ -40,6 +42,8 @@ import Language.Haskell.Stylish.Config.Internal
import Language.Haskell.Stylish.Step
import qualified Language.Haskell.Stylish.Step.Data as Data
import qualified Language.Haskell.Stylish.Step.Imports as Imports
import qualified Language.Haskell.Stylish.Step.ImportsGHC as ImportsGHC
import qualified Language.Haskell.Stylish.Step.ModuleHeader as ModuleHeader
import qualified Language.Haskell.Stylish.Step.LanguagePragmas as LanguagePragmas
import qualified Language.Haskell.Stylish.Step.SimpleAlign as SimpleAlign
import qualified Language.Haskell.Stylish.Step.Squash as Squash
Expand All @@ -60,8 +64,18 @@ data Config = Config
, configLanguageExtensions :: [String]
, configNewline :: IO.Newline
, configCabal :: Bool
, configExitCode :: ExitCodeBehavior
}

--------------------------------------------------------------------------------
data ExitCodeBehavior
= NormalExitBehavior
| ErrorOnFormatExitBehavior
deriving (Eq)

instance Show ExitCodeBehavior where
show NormalExitBehavior = "normal"
show ErrorOnFormatExitBehavior = "error_on_format"

--------------------------------------------------------------------------------
instance FromJSON Config where
Expand Down Expand Up @@ -126,6 +140,7 @@ parseConfig (A.Object o) = do
<*> (o A..:? "language_extensions" A..!= [])
<*> (o A..:? "newline" >>= parseEnum newlines IO.nativeNewline)
<*> (o A..:? "cabal" A..!= True)
<*> (o A..:? "exit_code" >>= parseEnum exitCodes NormalExitBehavior)

-- Then fill in the steps based on the partial config we already have
stepValues <- o A..: "steps" :: A.Parser [A.Value]
Expand All @@ -137,13 +152,18 @@ parseConfig (A.Object o) = do
, ("lf", IO.LF)
, ("crlf", IO.CRLF)
]
exitCodes =
[ ("normal", NormalExitBehavior)
, ("error_on_format", ErrorOnFormatExitBehavior)
]
parseConfig _ = mzero


--------------------------------------------------------------------------------
catalog :: Map String (Config -> A.Object -> A.Parser Step)
catalog = M.fromList
[ ("imports", parseImports)
, ("module_header", parseModuleHeader)
, ("records", parseRecords)
, ("language_pragmas", parseLanguagePragmas)
, ("simple_align", parseSimpleAlign)
Expand Down Expand Up @@ -172,6 +192,12 @@ parseEnum strs _ (Just k) = case lookup k strs of
Nothing -> fail $ "Unknown option: " ++ k ++ ", should be one of: " ++
intercalate ", " (map fst strs)

--------------------------------------------------------------------------------
parseModuleHeader :: Config -> A.Object -> A.Parser Step
parseModuleHeader _ _
= pure
. ModuleHeader.step
$ ModuleHeader.Config

--------------------------------------------------------------------------------
parseSimpleAlign :: Config -> A.Object -> A.Parser Step
Expand All @@ -186,13 +212,20 @@ parseSimpleAlign c o = SimpleAlign.step

--------------------------------------------------------------------------------
parseRecords :: Config -> A.Object -> A.Parser Step
parseRecords _ o = Data.step
parseRecords c o = Data.step
<$> (Data.Config
<$> (o A..: "equals" >>= parseIndent)
<*> (o A..: "first_field" >>= parseIndent)
<*> (o A..: "field_comment")
<*> (o A..: "deriving"))

<*> (o A..: "deriving")
<*> (o A..:? "break_enums" A..!= False)
<*> (o A..:? "break_single_constructors" A..!= True)
<*> (o A..: "via" >>= parseIndent)
<*> (o A..:? "curried_context" A..!= False)
<*> pure configMaxColumns)
where
configMaxColumns =
maybe Data.NoMaxColumns Data.MaxColumns (configColumns c)

parseIndent :: A.Value -> A.Parser Data.Indent
parseIndent = A.withText "Indent" $ \t ->
Expand All @@ -214,23 +247,31 @@ parseSquash _ _ = return Squash.step

--------------------------------------------------------------------------------
parseImports :: Config -> A.Object -> A.Parser Step
parseImports config o = Imports.step
<$> pure (configColumns config)
<*> (Imports.Options
<$> (o A..:? "align" >>= parseEnum aligns (def Imports.importAlign))
<*> (o A..:? "list_align" >>= parseEnum listAligns (def Imports.listAlign))
<*> (o A..:? "pad_module_names" A..!= def Imports.padModuleNames)
<*> (o A..:? "long_list_align"
>>= parseEnum longListAligns (def Imports.longListAlign))
-- Note that padding has to be at least 1. Default is 4.
<*> (o A..:? "empty_list_align"
>>= parseEnum emptyListAligns (def Imports.emptyListAlign))
<*> o A..:? "list_padding" A..!= def Imports.listPadding
<*> o A..:? "separate_lists" A..!= def Imports.separateLists
<*> o A..:? "space_surround" A..!= def Imports.spaceSurround)
parseImports config o = do
cfg <-
Imports.Options
<$> (o A..:? "align" >>= parseEnum aligns (def Imports.importAlign))
<*> (o A..:? "list_align" >>= parseEnum listAligns (def Imports.listAlign))
<*> (o A..:? "pad_module_names" A..!= def Imports.padModuleNames)
<*> (o A..:? "long_list_align" >>= parseEnum longListAligns (def Imports.longListAlign))
-- Note that padding has to be at least 1. Default is 4.
<*> (o A..:? "empty_list_align" >>= parseEnum emptyListAligns (def Imports.emptyListAlign))
<*> o A..:? "list_padding" A..!= def Imports.listPadding
<*> o A..:? "separate_lists" A..!= def Imports.separateLists
<*> o A..:? "space_surround" A..!= def Imports.spaceSurround
<*> o A..:? "ghc_lib_parser" A..!= False

pure
if Imports.useGhcLibParser cfg then
ImportsGHC.step columns cfg
else
Imports.step columns cfg

where
def f = f Imports.defaultOptions

columns = configColumns config

aligns =
[ ("global", Imports.Global)
, ("file", Imports.File)
Expand Down
101 changes: 101 additions & 0 deletions lib/Language/Haskell/Stylish/GHC.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
{-# LANGUAGE LambdaCase #-}
{-# OPTIONS_GHC -Wno-missing-fields #-}
-- | Utility functions for working with the GHC AST
module Language.Haskell.Stylish.GHC
( dropAfterLocated
, dropBeforeLocated
, dropBeforeAndAfter
-- * Unsafe getters
, getEndLineUnsafe
, getStartLineUnsafe
-- * Standard settings
, baseDynFlags
-- * Positions
, unLocated
-- * Outputable operators
, showOutputable
, compareOutputable
) where

--------------------------------------------------------------------------------
import Data.Function (on)

--------------------------------------------------------------------------------
import DynFlags (Settings(..), defaultDynFlags)
import qualified DynFlags as GHC
import FileSettings (FileSettings(..))
import GHC.Fingerprint (fingerprint0)
import GHC.Platform
import GHC.Version (cProjectVersion)
import GhcNameVersion (GhcNameVersion(..))
import PlatformConstants (PlatformConstants(..))
import SrcLoc (GenLocated(..), SrcSpan(..))
import SrcLoc (Located, RealLocated)
import SrcLoc (srcSpanStartLine, srcSpanEndLine)
import ToolSettings (ToolSettings(..))
import qualified Outputable as GHC

getStartLineUnsafe :: Located a -> Int
getStartLineUnsafe = \case
(L (RealSrcSpan s) _) -> srcSpanStartLine s
_ -> error "could not get start line of block"

getEndLineUnsafe :: Located a -> Int
getEndLineUnsafe = \case
(L (RealSrcSpan s) _) -> srcSpanEndLine s
_ -> error "could not get end line of block"

dropAfterLocated :: Maybe (Located a) -> [RealLocated b] -> [RealLocated b]
dropAfterLocated loc xs = case loc of
Just (L (RealSrcSpan rloc) _) ->
filter (\(L x _) -> srcSpanEndLine rloc >= srcSpanStartLine x) xs
_ -> xs

dropBeforeLocated :: Maybe (Located a) -> [RealLocated b] -> [RealLocated b]
dropBeforeLocated loc xs = case loc of
Just (L (RealSrcSpan rloc) _) ->
filter (\(L x _) -> srcSpanStartLine rloc <= srcSpanEndLine x) xs
_ -> xs

dropBeforeAndAfter :: Located a -> [RealLocated b] -> [RealLocated b]
dropBeforeAndAfter loc = dropBeforeLocated (Just loc) . dropAfterLocated (Just loc)

baseDynFlags :: GHC.DynFlags
baseDynFlags = defaultDynFlags fakeSettings llvmConfig
where
fakeSettings = GHC.Settings
{ sGhcNameVersion = GhcNameVersion "stylish-haskell" cProjectVersion
, sFileSettings = FileSettings {}
, sToolSettings = ToolSettings
{ toolSettings_opt_P_fingerprint = fingerprint0,
toolSettings_pgm_F = ""
}
, sPlatformConstants = PlatformConstants
{ pc_DYNAMIC_BY_DEFAULT = False
, pc_WORD_SIZE = 8
}
, sTargetPlatform = Platform
{ platformMini = PlatformMini
{ platformMini_arch = ArchUnknown
, platformMini_os = OSUnknown
}
, platformWordSize = PW8
, platformUnregisterised = True
, platformHasIdentDirective = False
, platformHasSubsectionsViaSymbols = False
, platformIsCrossCompiling = False
}
, sPlatformMisc = PlatformMisc {}
, sRawSettings = []
}

llvmConfig = GHC.LlvmConfig [] []

unLocated :: Located a -> a
unLocated (L _ a) = a

showOutputable :: GHC.Outputable a => a -> String
showOutputable = GHC.showPpr baseDynFlags

compareOutputable :: GHC.Outputable a => a -> a -> Ordering
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have any other orderings in use? If not maybe it would make sense to extract this to an orphan Ord instance for GHC.Outputable and not use this one explicitly?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is mostly used in the imports step. I think it might be a good idea here to invent our type for imports that carries the information we need. This'll probably be nice when we add support for merging imports - so then we add the ordering instance for that type.

WDYT?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I did two things, I changed the newtype representation of:

newtype Imports = Imports [LImportDecl GhcPs]

-- to:

newtype Import = Import (ImportDecl GhcPs)

This makes things a bit easier to reason about, it was possible to define equality for the import individually and I think it'll give us a more intuitive API down the line to work with imports. E.g. I added a helper function canMergeImport which is used in the equality instance. This helper could be used in the Imports step to merge imports - and get better ordering... I think I'm gonna play with that a bit today

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lukasz-golebiewski @felixmulder

Do we have any other orderings in use? If not maybe it would make sense to extract this to an orphan Ord instance for GHC.Outputable and not use this one explicitly?

This thread caught my eye as I perused this ticket. It looks to me that these lines are covering the same ground as ghc-lib-parser-ex's HsExtendInstances wrapper. I've mused before that ghc-lib-parser-ex might be useful for stylish-haskell to use/extend on its conversion from haskell-src-exts to ghc-lib-parser - would be nice to share these sorts of common utilities with e.g. HLint!

Copy link
Contributor

@shayne-fletcher shayne-fletcher Aug 20, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm c.f. showOutputable :: GHC.Outputable a => a -> String with unsafePrettyPrint (from Language.Haskell.GhclibParserEx.GHC.Utils.Outputable) too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that'd be neat 👍

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that'd be neat 👍

Let's let this land and revisit. If you're open to it moving some of this down to ghc-lib-parser-ex, I think we can eliminate this file at least in entirety.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see also that Module.hs has quite a lot of overlap with code under GHC/Util in HLint (e.g. parsing out language pragmas); most code in there hasn't been deemed general enough before now to get pulled down into ghc-lib-parser-ex but I'm starting to see opportunities to coalesce on it now.

compareOutputable = compare `on` showOutputable
Loading