ormolu
ormolu copied to clipboard
Allow GHC DynFlags to passed directly to the API
Is your feature request related to a problem? Please describe.
Currently in the Ormolu plugin in haskell-language-server, we have access to the GHC ParsedModule
. The whole plugin is short enough to include here so here it is in all its glory:
provider :: FormattingProvider IO
provider _lf ideState typ contents fp _ = do
let
fromDyn :: ParsedModule -> IO [DynOption]
fromDyn pmod =
let
df = ms_hspp_opts $ pm_mod_summary pmod
pp =
let p = D.sPgm_F $ D.settings df
in if null p then [] else ["-pgmF=" <> p]
pm = map (("-fplugin=" <>) . moduleNameString) $ D.pluginModNames df
ex = map (("-X" <>) . show) $ S.toList $ D.extensionFlags df
in
return $ map DynOption $ pp <> pm <> ex
m_parsed <- runAction "Ormolu" ideState $ getParsedModule fp
fileOpts <- case m_parsed of
Nothing -> return []
Just pm -> fromDyn pm
let
fullRegion = RegionIndices Nothing Nothing
rangeRegion s e = RegionIndices (Just s) (Just e)
mkConf o region = defaultConfig { cfgDynOptions = o, cfgRegion = region }
fmt :: T.Text -> Config RegionIndices -> IO (Either OrmoluException T.Text)
fmt cont conf =
try @OrmoluException (ormolu conf (fromNormalizedFilePath fp) $ T.unpack cont)
case typ of
FormatText -> ret <$> fmt contents (mkConf fileOpts fullRegion)
FormatRange r ->
let
Range (Position sl _) (Position el _) = normalize r
in
ret <$> fmt contents (mkConf fileOpts (rangeRegion sl el))
One hairy thing is that although we have direct access to the ParsedModule
's DynFlags
, we still need to print it to a string with this hacky fromDyn
flag, to then parse to Ormolu.
Describe the solution you'd like
To avoid this workaround it would be nice if the public API exposed a field that allowed DynFlags
to be set directly instead of doing this roundtrip from DynFlags
to strings back to DynFlags
, which seem to get converted back here:
https://github.com/tweag/ormolu/blob/35f4fb39326ab7d4847c5c8940f4d4185f3d3d24/src/Ormolu/Parser.hs#L193-L207
Something like
data Config region = Config
{ -- | Dynamic options to pass to GHC parser
cfgDynOptions :: !(Either DynFlags [DynOption]),
-- | Do formatting faster but without automatic detection of defects
cfgUnsafe :: !Bool,
-- | Output information useful for debugging
cfgDebug :: !Bool,
-- | Checks if re-formatting the result is idempotent
cfgCheckIdempotence :: !Bool,
-- | Region selection
cfgRegion :: !region
}
deriving (Eq, Show, Functor)
Even if these were the ghc-lib-parser
DynFlags
and not GHC
's, it would still be something to work with
Can you open a PR?