Skip to content

Extract an hls-brittany-plugin package #1422

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

Merged
merged 10 commits into from
Mar 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,9 @@ jobs:
if: ${{ matrix.test }}
run: LSP_TEST_LOG_COLOR=0 LSP_TEST_LOG_MESSAGES=true LSP_TEST_LOG_STDERR=true cabal test hls-tactics-plugin --test-options="-j1"

- name: Test brittany plugin
if: ${{ matrix.test }}
env:
HLS_TEST_EXE: hls
HLS_WRAPPER_TEST_EXE: hls-wrapper
run: cabal test hls-brittany-plugin || cabal test hls-brittany-plugin --test-options="-j1"
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ For example, `haskell-language-server` allows you to choose the formatting provi
This option obviously would not make sense for language servers for other languages, or even for other Haskell language servers (which need not even support formatting).

Here is a list of the additional settings currently supported by `haskell-language-server`, along with their setting key (you may not need to know this) and default:
- Formatting provider (`haskell.formattingProvider`, default `ormolu`): what formatter to use; one of `floskell`, `ormolu`, `fourmolu`, `stylish-haskell`, or `brittany` (if compiled with AGPL)
- Formatting provider (`haskell.formattingProvider`, default `ormolu`): what formatter to use; one of `floskell`, `ormolu`, `fourmolu`, `stylish-haskell`, or `brittany` (if compiled with the brittany plugin)
- Format on imports (`haskell.formatOnImportOn`, default true): whether to format after adding an import
- Maximum number of problems to report (`haskell.maxNumberOfProblems`, default 100): the maximum number of problems the server will send to the client
- Diagnostics on change (`haskell.diagnosticsOnChange`, default true): (currently unused)
Expand Down Expand Up @@ -648,7 +648,7 @@ This issue should be fixed in Stack versions >= 2.5.
#### Problems with dynamic linking

As haskell-language-server prebuilt binaries are statically linked, they don't play well with projects using dynamic linking.
An usual symptom is the presence of errors containing `unknown symbol` and it is typical in arch linux, where a dynamically linked version of ghc is used.
An usual symptom is the presence of errors containing `unknown symbol` and it is typical in arch linux, where a dynamically linked version of ghc is used.

The workaround is to use a version of haskell-language-server compiled from source with `-dynamic` enabled`. See more details [here](https://github.com/haskell/haskell-language-server/issues/1160#issuecomment-756566273).

Expand Down
1 change: 1 addition & 0 deletions cabal.project
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ packages:
./ghcide
./hls-plugin-api
./plugins/hls-tactics-plugin
./plugins/hls-brittany-plugin
./plugins/hls-class-plugin
./plugins/hls-eval-plugin
./plugins/hls-explicit-imports-plugin
Expand Down
2 changes: 0 additions & 2 deletions docs/plugin-tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,7 @@ idePlugins = pluginDescToIdePlugins allPlugins
, Ormolu.descriptor "ormolu"
, StylishHaskell.descriptor "stylish-haskell"
, Retrie.descriptor "retrie"
#if AGPL
, Brittany.descriptor "brittany"
#endif
, Eval.descriptor "eval"
]
```
Expand Down
2 changes: 1 addition & 1 deletion exe/Plugins.hs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ import Ide.Plugin.Ormolu as Ormolu
import Ide.Plugin.StylishHaskell as StylishHaskell
#endif

#if AGPL && brittany
#if brittany
import Ide.Plugin.Brittany as Brittany
#endif

Expand Down
2 changes: 1 addition & 1 deletion ghcide/exe/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ main = do
Typecheck x | not argLSP -> Just x
_ -> Nothing

,Main.argsLogger = logger
,Main.argsLogger = pure logger

,Main.argsRules = do
-- install the main and ghcide-plugin rules
Expand Down
2 changes: 1 addition & 1 deletion ghcide/ghcide.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ cabal-version: 2.2
build-type: Simple
category: Development
name: ghcide
version: 1.0.0.0
version: 1.1.0.0
license: Apache-2.0
license-file: LICENSE
author: Digital Asset and Ghcide contributors
Expand Down
157 changes: 88 additions & 69 deletions ghcide/src/Development/IDE/Main.hs
Original file line number Diff line number Diff line change
@@ -1,73 +1,83 @@
module Development.IDE.Main (Arguments(..), defaultMain) where
import Control.Concurrent.Extra (readVar)
import Control.Exception.Safe (Exception (displayException),
catchAny)
import Control.Monad.Extra (concatMapM, unless, when)
import Data.Default (Default (def))
import qualified Data.HashMap.Strict as HashMap
import Data.List.Extra (intercalate, isPrefixOf,
nub, nubOrd, partition)
import Data.Maybe (catMaybes, fromMaybe,
isJust)
import qualified Data.Text as T
import Development.IDE (Action, Rules, noLogging)
import Development.IDE.Core.Debouncer (newAsyncDebouncer)
import Development.IDE.Core.FileStore (makeVFSHandle)
import Development.IDE.Core.OfInterest (FileOfInterestStatus (OnDisk),
kick, setFilesOfInterest)
import Development.IDE.Core.RuleTypes (GenerateCore (GenerateCore),
GetHieAst (GetHieAst),
GhcSession (GhcSession),
GhcSessionDeps (GhcSessionDeps),
TypeCheck (TypeCheck))
import Development.IDE.Core.Rules (GhcSessionIO (GhcSessionIO),
mainRule)
import Development.IDE.Core.Service (initialise, runAction)
import Development.IDE.Core.Shake (IdeState (shakeExtras),
ShakeExtras (state), uses)
import Development.IDE.Core.Tracing (measureMemory)
import Development.IDE.Core.IdeConfiguration (registerIdeConfiguration, IdeConfiguration(..))
import Development.IDE.LSP.LanguageServer (runLanguageServer)
import Development.IDE.Plugin (Plugin (pluginHandlers, pluginRules))
import Development.IDE.Plugin.HLS (asGhcIdePlugin)
import qualified Development.IDE.Plugin.HLS.GhcIde as Ghcide
import Development.IDE.Session (SessionLoadingOptions,
getHieDbLoc,
loadSessionWithOptions,
runWithDb,
setInitialDynFlags)
import Development.IDE.Types.Location (toNormalizedFilePath')
import Development.IDE.Types.Logger (Logger)
import Development.IDE.Types.Options (IdeGhcSession,
IdeOptions (optCheckParents, optCheckProject, optReportProgress),
clientSupportsProgress,
defaultIdeOptions)
import Development.IDE.Types.Shake (Key (Key))
import Development.Shake (action)
import HIE.Bios.Cradle (findCradle)
import Ide.Plugin.Config (CheckParents (NeverCheck),
Config,
getConfigFromNotification)
import Ide.PluginUtils (allLspCmdIds',
getProcessID,
pluginDescToIdePlugins)
import Ide.Types (IdePlugins)
import qualified Language.LSP.Server as LSP
import qualified System.Directory.Extra as IO
import System.Exit (ExitCode (ExitFailure),
exitWith)
import System.FilePath (takeExtension,
takeFileName)
import System.IO (hPutStrLn, hSetEncoding,
stderr, stdout, utf8)
import System.Time.Extra (offsetTime, showDuration)
import Text.Printf (printf)
import Data.Hashable (hashed)
import Control.Concurrent.Extra (newLock, readVar,
withLock)
import Control.Exception.Safe (Exception (displayException),
catchAny)
import Control.Monad.Extra (concatMapM, unless,
when)
import Data.Default (Default (def))
import qualified Data.HashMap.Strict as HashMap
import Data.Hashable (hashed)
import Data.List.Extra (intercalate, isPrefixOf,
nub, nubOrd, partition)
import Data.Maybe (catMaybes, fromMaybe,
isJust)
import qualified Data.Text as T
import qualified Data.Text.IO as T
import Development.IDE (Action, Rules)
import Development.IDE.Core.Debouncer (newAsyncDebouncer)
import Development.IDE.Core.FileStore (makeVFSHandle)
import Development.IDE.Core.IdeConfiguration (IdeConfiguration (..),
registerIdeConfiguration)
import Development.IDE.Core.OfInterest (FileOfInterestStatus (OnDisk),
kick,
setFilesOfInterest)
import Development.IDE.Core.RuleTypes (GenerateCore (GenerateCore),
GetHieAst (GetHieAst),
GhcSession (GhcSession),
GhcSessionDeps (GhcSessionDeps),
TypeCheck (TypeCheck))
import Development.IDE.Core.Rules (GhcSessionIO (GhcSessionIO),
mainRule)
import Development.IDE.Core.Service (initialise, runAction)
import Development.IDE.Core.Shake (IdeState (shakeExtras),
ShakeExtras (state),
uses)
import Development.IDE.Core.Tracing (measureMemory)
import Development.IDE.LSP.LanguageServer (runLanguageServer)
import Development.IDE.Plugin (Plugin (pluginHandlers, pluginRules))
import Development.IDE.Plugin.HLS (asGhcIdePlugin)
import qualified Development.IDE.Plugin.HLS.GhcIde as Ghcide
import Development.IDE.Session (SessionLoadingOptions,
getHieDbLoc,
loadSessionWithOptions,
runWithDb,
setInitialDynFlags)
import Development.IDE.Types.Location (toNormalizedFilePath')
import Development.IDE.Types.Logger (Logger (Logger))
import Development.IDE.Types.Options (IdeGhcSession,
IdeOptions (optCheckParents, optCheckProject, optReportProgress),
clientSupportsProgress,
defaultIdeOptions)
import Development.IDE.Types.Shake (Key (Key))
import Development.Shake (action)
import HIE.Bios.Cradle (findCradle)
import Ide.Plugin.Config (CheckParents (NeverCheck),
Config,
getConfigFromNotification)
import Ide.PluginUtils (allLspCmdIds',
getProcessID,
pluginDescToIdePlugins)
import Ide.Types (IdePlugins)
import qualified Language.LSP.Server as LSP
import qualified System.Directory.Extra as IO
import System.Exit (ExitCode (ExitFailure),
exitWith)
import System.FilePath (takeExtension,
takeFileName)
import System.IO (BufferMode (LineBuffering),
hPutStrLn,
hSetBuffering,
hSetEncoding, stderr,
stdout, utf8)
import System.Time.Extra (offsetTime,
showDuration)
import Text.Printf (printf)

data Arguments = Arguments
{ argsOTMemoryProfiling :: Bool
, argFiles :: Maybe [FilePath] -- ^ Nothing: lsp server ; Just: typecheck and exit
, argsLogger :: Logger
, argsLogger :: IO Logger
, argsRules :: Rules ()
, argsHlsPlugins :: IdePlugins IdeState
, argsGhcidePlugin :: Plugin Config -- ^ Deprecated
Expand All @@ -82,7 +92,7 @@ instance Default Arguments where
def = Arguments
{ argsOTMemoryProfiling = False
, argFiles = Nothing
, argsLogger = noLogging
, argsLogger = stderrLogger
, argsRules = mainRule >> action kick
, argsGhcidePlugin = mempty
, argsHlsPlugins = pluginDescToIdePlugins Ghcide.descriptors
Expand All @@ -93,9 +103,18 @@ instance Default Arguments where
, argsGetHieDbLoc = getHieDbLoc
}

-- | Cheap stderr logger that relies on LineBuffering
stderrLogger :: IO Logger
stderrLogger = do
lock <- newLock
return $ Logger $ \p m -> withLock lock $
T.hPutStrLn stderr $ "[" <> T.pack (show p) <> "] " <> m

defaultMain :: Arguments -> IO ()
defaultMain Arguments{..} = do
pid <- T.pack . show <$> getProcessID
logger <- argsLogger
hSetBuffering stderr LineBuffering

let hlsPlugin = asGhcIdePlugin argsDefaultHlsConfig argsHlsPlugins
hlsCommands = allLspCmdIds' pid argsHlsPlugins
Expand Down Expand Up @@ -134,7 +153,7 @@ defaultMain Arguments{..} = do
argsDefaultHlsConfig
rules
(Just env)
argsLogger
logger
debouncer
options
vfs
Expand Down Expand Up @@ -171,7 +190,7 @@ defaultMain Arguments{..} = do
{ optCheckParents = pure NeverCheck
, optCheckProject = pure False
}
ide <- initialise argsDefaultHlsConfig rules Nothing argsLogger debouncer options vfs hiedb hieChan
ide <- initialise argsDefaultHlsConfig rules Nothing logger debouncer options vfs hiedb hieChan
registerIdeConfiguration (shakeExtras ide) $ IdeConfiguration mempty (hashed Nothing)

putStrLn "\nStep 4/4: Type checking the files"
Expand Down Expand Up @@ -199,7 +218,7 @@ defaultMain Arguments{..} = do
Key GhcSessionDeps :
[k | (_, k) <- HashMap.keys values, k /= Key GhcSessionIO]
++ [Key GhcSessionIO]
measureMemory argsLogger [keys] consoleObserver valuesRef
measureMemory logger [keys] consoleObserver valuesRef

unless (null failed) (exitWith $ ExitFailure (length failed))
{-# ANN defaultMain ("HLint: ignore Use nubOrd" :: String) #-}
Expand Down
31 changes: 9 additions & 22 deletions haskell-language-server.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,6 @@ extra-source-files:
ChangeLog.md
include/ghc-api-version.h

flag agpl
description: Enable AGPL dependencies
default: True
manual: True

flag pedantic
description: Enable -Werror
default: False
Expand All @@ -34,10 +29,6 @@ source-repository head
type: git
location: https://github.com/haskell/haskell-language-server

common agpl
if flag(agpl)
cpp-options: -DAGPL

common common-deps
build-depends:
, base >=4.12 && <5
Expand All @@ -47,7 +38,7 @@ common common-deps
, text

library
import: agpl, common-deps
import: common-deps
exposed-modules:
Ide.Arguments
Ide.Main
Expand All @@ -64,7 +55,7 @@ library
, cryptohash-sha1
, data-default
, ghc
, ghcide ^>= 1.0.0.0
, ghcide ^>= 1.1.0.0
, gitrev
, lsp
, hie-bios
Expand Down Expand Up @@ -269,15 +260,11 @@ common stylishHaskell
cpp-options: -DstylishHaskell

common brittany
if (flag(brittany) || flag(all-formatters)) && flag(agpl)
hs-source-dirs: plugins/default/src
other-modules: Ide.Plugin.Brittany
build-depends: brittany >= 0.13.1.0
cpp-options: -Dbrittany
if (flag(brittany) || flag(all-formatters))
build-depends: hls-brittany-plugin ^>= 1.0.0.0

executable haskell-language-server
import: agpl
, common-deps
import: common-deps
-- plugins
, example-plugins
, class
Expand Down Expand Up @@ -349,7 +336,7 @@ executable haskell-language-server
default-extensions: DataKinds, TypeOperators

executable haskell-language-server-wrapper
import: agpl, common-deps
import: common-deps
main-is: Wrapper.hs
hs-source-dirs: exe
other-modules: Paths_haskell_language_server
Expand Down Expand Up @@ -382,7 +369,7 @@ executable haskell-language-server-wrapper
-- We removed it due to issues with stack when loading the project using a stack based hie.yaml
-- See https://github.com/haskell/haskell-language-server/issues/114
common hls-test-utils
import: agpl, common-deps
import: common-deps
hs-source-dirs: test/utils
other-modules: Test.Hls.Util
build-depends:
Expand Down Expand Up @@ -414,7 +401,7 @@ common hls-test-utils
default-language: Haskell2010

test-suite func-test
import: agpl, common-deps, hls-test-utils
import: common-deps, hls-test-utils
type: exitcode-stdio-1.0
default-language: Haskell2010
build-tool-depends:
Expand Down Expand Up @@ -471,7 +458,7 @@ test-suite func-test
ghc-options: -Werror -Wredundant-constraints

test-suite wrapper-test
import: agpl, hls-test-utils
import: hls-test-utils
type: exitcode-stdio-1.0
build-tool-depends:
haskell-language-server:haskell-language-server-wrapper -any
Expand Down
1 change: 1 addition & 0 deletions nix/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ let
shake-bench = gitignoreSource ../shake-bench;
hie-compat = gitignoreSource ../hie-compat;
hls-plugin-api = gitignoreSource ../hls-plugin-api;
hls-brittany-plugin = gitignoreSource ../plugins/hls-brittany-plugin;
hls-class-plugin = gitignoreSource ../plugins/hls-class-plugin;
hls-haddock-comments-plugin = gitignoreSource ../plugins/hls-haddock-comments-plugin;
hls-eval-plugin = gitignoreSource ../plugins/hls-eval-plugin;
Expand Down
Loading