Skip to content

Commit d5e256a

Browse files
committed
Add fourmolu plugin
1 parent 531e88f commit d5e256a

14 files changed

+149
-3
lines changed

cabal.project

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,7 @@ package ghcide
1515
write-ghc-environment-files: never
1616

1717
index-state: 2020-07-27T12:40:45Z
18+
19+
allow-newer:
20+
floskell:aeson
21+
stylish-haskell:aeson

exe/Main.hs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ import Ide.Plugin.Example as Example
6767
import Ide.Plugin.Example2 as Example2
6868
import Ide.Plugin.GhcIde as GhcIde
6969
import Ide.Plugin.Floskell as Floskell
70+
import Ide.Plugin.Fourmolu as Fourmolu
7071
import Ide.Plugin.Ormolu as Ormolu
7172
import Ide.Plugin.StylishHaskell as StylishHaskell
7273
import Ide.Plugin.Retrie as Retrie
@@ -102,8 +103,9 @@ idePlugins includeExamples = pluginDescToIdePlugins allPlugins
102103
GhcIde.descriptor "ghcide"
103104
, Pragmas.descriptor "pragmas"
104105
, Floskell.descriptor "floskell"
105-
-- , genericDescriptor "generic"
106-
-- , ghcmodDescriptor "ghcmod"
106+
, Fourmolu.descriptor "fourmolu"
107+
-- , genericDescriptor "generic"
108+
-- , ghcmodDescriptor "ghcmod"
107109
, Ormolu.descriptor "ormolu"
108110
, StylishHaskell.descriptor "stylish-haskell"
109111
, Retrie.descriptor "retrie"

haskell-language-server.cabal

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ library
4545
Ide.Plugin.Eval
4646
Ide.Plugin.Example
4747
Ide.Plugin.Example2
48+
Ide.Plugin.Fourmolu
4849
Ide.Plugin.GhcIde
4950
Ide.Plugin.Ormolu
5051
Ide.Plugin.Pragmas
@@ -72,6 +73,7 @@ library
7273
, extra
7374
, filepath
7475
, floskell == 0.10.*
76+
, fourmolu ^>= 0.1
7577
, ghc
7678
, ghc-boot-th
7779
, ghcide >= 0.1

src/Ide/Plugin/Fourmolu.hs

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
{-# LANGUAGE OverloadedStrings #-}
2+
{-# LANGUAGE PackageImports #-}
3+
{-# LANGUAGE RecordWildCards #-}
4+
{-# LANGUAGE ScopedTypeVariables #-}
5+
{-# LANGUAGE TypeApplications #-}
6+
7+
module Ide.Plugin.Fourmolu
8+
(
9+
descriptor
10+
, provider
11+
)
12+
where
13+
14+
import Control.Exception
15+
import qualified Data.Text as T
16+
import Development.IDE.Core.Rules
17+
import Development.IDE.Core.RuleTypes (GhcSession (GhcSession))
18+
import Development.IDE.Core.Shake (use)
19+
import Development.IDE.GHC.Util (hscEnv)
20+
import Development.IDE.Types.Diagnostics as D
21+
import Development.IDE.Types.Location
22+
import qualified DynFlags as D
23+
import qualified EnumSet as S
24+
import GHC
25+
import GHC.LanguageExtensions.Type
26+
import GhcPlugins (HscEnv (hsc_dflags))
27+
import Ide.Plugin.Formatter
28+
import Ide.PluginUtils
29+
import Ide.Types
30+
import Language.Haskell.LSP.Core (LspFuncs (withIndefiniteProgress),
31+
ProgressCancellable (Cancellable))
32+
import Language.Haskell.LSP.Types
33+
import "fourmolu" Ormolu
34+
import System.FilePath (takeFileName)
35+
import Text.Regex.TDFA.Text ()
36+
37+
-- ---------------------------------------------------------------------
38+
39+
descriptor :: PluginId -> PluginDescriptor
40+
descriptor plId = (defaultPluginDescriptor plId)
41+
{ pluginFormattingProvider = Just provider
42+
}
43+
44+
-- ---------------------------------------------------------------------
45+
46+
provider :: FormattingProvider IO
47+
provider lf ideState typ contents fp _ = withIndefiniteProgress lf title Cancellable $ do
48+
let
49+
fromDyn :: DynFlags -> IO [DynOption]
50+
fromDyn df =
51+
let
52+
pp =
53+
let p = D.sPgm_F $ D.settings df
54+
in if null p then [] else ["-pgmF=" <> p]
55+
pm = map (("-fplugin=" <>) . moduleNameString) $ D.pluginModNames df
56+
ex = map showExtension $ S.toList $ D.extensionFlags df
57+
in
58+
return $ map DynOption $ pp <> pm <> ex
59+
60+
ghc <- runAction "Fourmolu" ideState $ use GhcSession fp
61+
let df = hsc_dflags . hscEnv <$> ghc
62+
fileOpts <- case df of
63+
Nothing -> return []
64+
Just df -> fromDyn df
65+
66+
let
67+
fullRegion = RegionIndices Nothing Nothing
68+
rangeRegion s e = RegionIndices (Just $ s + 1) (Just $ e + 1)
69+
mkConf o region = do
70+
printerOpts <- loadConfigFile True (Just fp') defaultPrinterOpts
71+
return $ defaultConfig
72+
{ cfgDynOptions = o
73+
, cfgRegion = region
74+
, cfgDebug = True
75+
, cfgPrinterOpts = printerOpts
76+
}
77+
fmt :: T.Text -> Config RegionIndices -> IO (Either OrmoluException T.Text)
78+
fmt cont conf =
79+
try @OrmoluException (ormolu conf fp' $ T.unpack cont)
80+
fp' = fromNormalizedFilePath fp
81+
82+
case typ of
83+
FormatText -> ret <$> (fmt contents =<< mkConf fileOpts fullRegion)
84+
FormatRange (Range (Position sl _) (Position el _)) ->
85+
ret <$> (fmt contents =<< mkConf fileOpts (rangeRegion sl el))
86+
where
87+
title = T.pack $ "Formatting " <> takeFileName (fromNormalizedFilePath fp)
88+
ret :: Either OrmoluException T.Text -> Either ResponseError (List TextEdit)
89+
ret (Left err) = Left
90+
(responseError (T.pack $ "fourmoluCmd: " ++ show err) )
91+
ret (Right new) = Right (makeDiffTextEdit contents new)
92+
93+
showExtension :: Extension -> String
94+
showExtension Cpp = "-XCPP"
95+
showExtension other = "-X" ++ show other

src/Ide/Plugin/Ormolu.hs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{-# LANGUAGE OverloadedStrings #-}
2+
{-# LANGUAGE PackageImports #-}
23
{-# LANGUAGE RecordWildCards #-}
34
{-# LANGUAGE ScopedTypeVariables #-}
45
{-# LANGUAGE TypeApplications #-}
@@ -29,7 +30,7 @@ import Ide.Types
2930
import Language.Haskell.LSP.Core (LspFuncs (withIndefiniteProgress),
3031
ProgressCancellable (Cancellable))
3132
import Language.Haskell.LSP.Types
32-
import Ormolu
33+
import "ormolu" Ormolu
3334
import System.FilePath (takeFileName)
3435
import Text.Regex.TDFA.Text ()
3536

stack-8.10.1.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ extra-deps:
1313
- cabal-plan-0.7.0.0
1414
- clock-0.7.2
1515
- floskell-0.10.3
16+
- fourmolu-0.1.0.0
1617
- ghc-exactprint-0.6.3
1718
- lens-4.19.1
1819
- lsp-test-0.11.0.3

stack-8.6.4.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ extra-deps:
1818
- clock-0.7.2
1919
- extra-1.7.3
2020
- floskell-0.10.3
21+
- fourmolu-0.1.0.0
2122
- fuzzy-0.1.0.0
2223
# - ghcide-0.1.0
2324
- ghc-check-0.5.0.1

stack-8.6.5.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ extra-deps:
1717
- clock-0.7.2
1818
- extra-1.7.3
1919
- floskell-0.10.3
20+
- fourmolu-0.1.0.0
2021
- fuzzy-0.1.0.0
2122
# - ghcide-0.1.0
2223
- ghc-check-0.5.0.1

stack-8.8.2.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ extra-deps:
1616
- constrained-dynamic-0.1.0.0
1717
- extra-1.7.3
1818
- floskell-0.10.3
19+
- fourmolu-0.1.0.0
1920
# - ghcide-0.1.0
2021
- ghc-check-0.5.0.1
2122
- ghc-lib-parser-8.10.1.20200523

stack-8.8.3.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ extra-deps:
1515
- constrained-dynamic-0.1.0.0
1616
- extra-1.7.3
1717
- floskell-0.10.3
18+
- fourmolu-0.1.0.0
1819
# - ghcide-0.1.0
1920
- haskell-src-exts-1.21.1
2021
- hie-bios-0.6.1

0 commit comments

Comments
 (0)