{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeFamilies #-}
module Ide.Plugin.Config
    (
      getInitialConfig
    , getConfigFromNotification
    , Config(..)
    , PluginConfig(..)
    , CheckParents(..)
    ) where

import           Control.Applicative
import qualified Data.Aeson                    as A
import           Data.Aeson              hiding ( Error )
import           Data.Default
import qualified Data.Text                     as T
import           Language.Haskell.LSP.Types
import qualified Data.Map as Map
import GHC.Generics (Generic)

-- ---------------------------------------------------------------------


-- | Given a DidChangeConfigurationNotification message, this function returns the parsed

-- Config object if possible.

getConfigFromNotification :: DidChangeConfigurationNotification -> Either T.Text Config
getConfigFromNotification :: DidChangeConfigurationNotification -> Either Text Config
getConfigFromNotification (NotificationMessage Text
_ ClientMethod
_ (DidChangeConfigurationParams Value
p)) =
  case Value -> Result Config
forall a. FromJSON a => Value -> Result a
fromJSON Value
p of
    A.Success Config
c -> Config -> Either Text Config
forall a b. b -> Either a b
Right Config
c
    A.Error String
err -> Text -> Either Text Config
forall a b. a -> Either a b
Left (Text -> Either Text Config) -> Text -> Either Text Config
forall a b. (a -> b) -> a -> b
$ String -> Text
T.pack String
err

-- | Given an InitializeRequest message, this function returns the parsed

-- Config object if possible. Otherwise, it returns the default configuration

getInitialConfig :: InitializeRequest -> Either T.Text Config
getInitialConfig :: InitializeRequest -> Either Text Config
getInitialConfig (RequestMessage Text
_ LspId
_ ClientMethod
_ InitializeParams{$sel:_initializationOptions:InitializeParams :: InitializeParams -> Maybe Value
_initializationOptions = Maybe Value
Nothing }) = Config -> Either Text Config
forall a b. b -> Either a b
Right Config
forall a. Default a => a
def
getInitialConfig (RequestMessage Text
_ LspId
_ ClientMethod
_ InitializeParams{$sel:_initializationOptions:InitializeParams :: InitializeParams -> Maybe Value
_initializationOptions = Just Value
opts}) =
  case Value -> Result Config
forall a. FromJSON a => Value -> Result a
fromJSON Value
opts of
    A.Success Config
c -> Config -> Either Text Config
forall a b. b -> Either a b
Right Config
c
    A.Error String
err -> Text -> Either Text Config
forall a b. a -> Either a b
Left (Text -> Either Text Config) -> Text -> Either Text Config
forall a b. (a -> b) -> a -> b
$ String -> Text
T.pack String
err

-- ---------------------------------------------------------------------

data CheckParents
    -- Note that ordering of constructors is meaningful and must be monotonically

    -- increasing in the scenarios where parents are checked

    = NeverCheck
    | CheckOnClose
    | CheckOnSaveAndClose
    | AlwaysCheck
  deriving stock (CheckParents -> CheckParents -> Bool
(CheckParents -> CheckParents -> Bool)
-> (CheckParents -> CheckParents -> Bool) -> Eq CheckParents
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CheckParents -> CheckParents -> Bool
$c/= :: CheckParents -> CheckParents -> Bool
== :: CheckParents -> CheckParents -> Bool
$c== :: CheckParents -> CheckParents -> Bool
Eq, Eq CheckParents
Eq CheckParents
-> (CheckParents -> CheckParents -> Ordering)
-> (CheckParents -> CheckParents -> Bool)
-> (CheckParents -> CheckParents -> Bool)
-> (CheckParents -> CheckParents -> Bool)
-> (CheckParents -> CheckParents -> Bool)
-> (CheckParents -> CheckParents -> CheckParents)
-> (CheckParents -> CheckParents -> CheckParents)
-> Ord CheckParents
CheckParents -> CheckParents -> Bool
CheckParents -> CheckParents -> Ordering
CheckParents -> CheckParents -> CheckParents
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: CheckParents -> CheckParents -> CheckParents
$cmin :: CheckParents -> CheckParents -> CheckParents
max :: CheckParents -> CheckParents -> CheckParents
$cmax :: CheckParents -> CheckParents -> CheckParents
>= :: CheckParents -> CheckParents -> Bool
$c>= :: CheckParents -> CheckParents -> Bool
> :: CheckParents -> CheckParents -> Bool
$c> :: CheckParents -> CheckParents -> Bool
<= :: CheckParents -> CheckParents -> Bool
$c<= :: CheckParents -> CheckParents -> Bool
< :: CheckParents -> CheckParents -> Bool
$c< :: CheckParents -> CheckParents -> Bool
compare :: CheckParents -> CheckParents -> Ordering
$ccompare :: CheckParents -> CheckParents -> Ordering
$cp1Ord :: Eq CheckParents
Ord, Int -> CheckParents -> ShowS
[CheckParents] -> ShowS
CheckParents -> String
(Int -> CheckParents -> ShowS)
-> (CheckParents -> String)
-> ([CheckParents] -> ShowS)
-> Show CheckParents
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CheckParents] -> ShowS
$cshowList :: [CheckParents] -> ShowS
show :: CheckParents -> String
$cshow :: CheckParents -> String
showsPrec :: Int -> CheckParents -> ShowS
$cshowsPrec :: Int -> CheckParents -> ShowS
Show, (forall x. CheckParents -> Rep CheckParents x)
-> (forall x. Rep CheckParents x -> CheckParents)
-> Generic CheckParents
forall x. Rep CheckParents x -> CheckParents
forall x. CheckParents -> Rep CheckParents x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep CheckParents x -> CheckParents
$cfrom :: forall x. CheckParents -> Rep CheckParents x
Generic)
  deriving anyclass (Value -> Parser [CheckParents]
Value -> Parser CheckParents
(Value -> Parser CheckParents)
-> (Value -> Parser [CheckParents]) -> FromJSON CheckParents
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
parseJSONList :: Value -> Parser [CheckParents]
$cparseJSONList :: Value -> Parser [CheckParents]
parseJSON :: Value -> Parser CheckParents
$cparseJSON :: Value -> Parser CheckParents
FromJSON, [CheckParents] -> Encoding
[CheckParents] -> Value
CheckParents -> Encoding
CheckParents -> Value
(CheckParents -> Value)
-> (CheckParents -> Encoding)
-> ([CheckParents] -> Value)
-> ([CheckParents] -> Encoding)
-> ToJSON CheckParents
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
toEncodingList :: [CheckParents] -> Encoding
$ctoEncodingList :: [CheckParents] -> Encoding
toJSONList :: [CheckParents] -> Value
$ctoJSONList :: [CheckParents] -> Value
toEncoding :: CheckParents -> Encoding
$ctoEncoding :: CheckParents -> Encoding
toJSON :: CheckParents -> Value
$ctoJSON :: CheckParents -> Value
ToJSON)


-- | We (initially anyway) mirror the hie configuration, so that existing

-- clients can simply switch executable and not have any nasty surprises.  There

-- will be surprises relating to config options being ignored, initially though.

data Config =
  Config
    { Config -> CheckParents
checkParents                :: CheckParents
    , Config -> Bool
checkProject                :: !Bool
    , Config -> Bool
hlintOn                     :: !Bool
    , Config -> Bool
diagnosticsOnChange         :: !Bool
    , Config -> Int
maxNumberOfProblems         :: !Int
    , Config -> Int
diagnosticsDebounceDuration :: !Int
    , Config -> Bool
liquidOn                    :: !Bool
    , Config -> Bool
completionSnippetsOn        :: !Bool
    , Config -> Bool
formatOnImportOn            :: !Bool
    , Config -> Text
formattingProvider          :: !T.Text
    , Config -> Int
maxCompletions              :: !Int
    , Config -> Map Text PluginConfig
plugins                     :: !(Map.Map T.Text PluginConfig)
    } deriving (Int -> Config -> ShowS
[Config] -> ShowS
Config -> String
(Int -> Config -> ShowS)
-> (Config -> String) -> ([Config] -> ShowS) -> Show Config
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Config] -> ShowS
$cshowList :: [Config] -> ShowS
show :: Config -> String
$cshow :: Config -> String
showsPrec :: Int -> Config -> ShowS
$cshowsPrec :: Int -> Config -> ShowS
Show,Config -> Config -> Bool
(Config -> Config -> Bool)
-> (Config -> Config -> Bool) -> Eq Config
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Config -> Config -> Bool
$c/= :: Config -> Config -> Bool
== :: Config -> Config -> Bool
$c== :: Config -> Config -> Bool
Eq)

instance Default Config where
  def :: Config
def = Config :: CheckParents
-> Bool
-> Bool
-> Bool
-> Int
-> Int
-> Bool
-> Bool
-> Bool
-> Text
-> Int
-> Map Text PluginConfig
-> Config
Config
    { checkParents :: CheckParents
checkParents                = CheckParents
CheckOnSaveAndClose
    , checkProject :: Bool
checkProject                = Bool
True
    , hlintOn :: Bool
hlintOn                     = Bool
True
    , diagnosticsOnChange :: Bool
diagnosticsOnChange         = Bool
True
    , maxNumberOfProblems :: Int
maxNumberOfProblems         = Int
100
    , diagnosticsDebounceDuration :: Int
diagnosticsDebounceDuration = Int
350000
    , liquidOn :: Bool
liquidOn                    = Bool
False
    , completionSnippetsOn :: Bool
completionSnippetsOn        = Bool
True
    , formatOnImportOn :: Bool
formatOnImportOn            = Bool
True
    -- , formattingProvider          = "brittany"

    , formattingProvider :: Text
formattingProvider          = Text
"ormolu"
    -- , formattingProvider          = "floskell"

    -- , formattingProvider          = "stylish-haskell"

    , maxCompletions :: Int
maxCompletions              = Int
40
    , plugins :: Map Text PluginConfig
plugins                     = Map Text PluginConfig
forall k a. Map k a
Map.empty
    }

-- TODO: Add API for plugins to expose their own LSP config options

instance A.FromJSON Config where
  parseJSON :: Value -> Parser Config
parseJSON = String -> (Object -> Parser Config) -> Value -> Parser Config
forall a. String -> (Object -> Parser a) -> Value -> Parser a
A.withObject String
"Config" ((Object -> Parser Config) -> Value -> Parser Config)
-> (Object -> Parser Config) -> Value -> Parser Config
forall a b. (a -> b) -> a -> b
$ \Object
v -> do
    -- Officially, we use "haskell" as the section name but for

    -- backwards compatibility we also accept "languageServerHaskell"

    Value
s <- Object
v Object -> Text -> Parser Value
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"haskell" Parser Value -> Parser Value -> Parser Value
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Object
v Object -> Text -> Parser Value
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"languageServerHaskell"
    ((Object -> Parser Config) -> Value -> Parser Config)
-> Value -> (Object -> Parser Config) -> Parser Config
forall a b c. (a -> b -> c) -> b -> a -> c
flip (String -> (Object -> Parser Config) -> Value -> Parser Config
forall a. String -> (Object -> Parser a) -> Value -> Parser a
A.withObject String
"Config.settings") Value
s ((Object -> Parser Config) -> Parser Config)
-> (Object -> Parser Config) -> Parser Config
forall a b. (a -> b) -> a -> b
$ \Object
o -> CheckParents
-> Bool
-> Bool
-> Bool
-> Int
-> Int
-> Bool
-> Bool
-> Bool
-> Text
-> Int
-> Map Text PluginConfig
-> Config
Config
      (CheckParents
 -> Bool
 -> Bool
 -> Bool
 -> Int
 -> Int
 -> Bool
 -> Bool
 -> Bool
 -> Text
 -> Int
 -> Map Text PluginConfig
 -> Config)
-> Parser CheckParents
-> Parser
     (Bool
      -> Bool
      -> Bool
      -> Int
      -> Int
      -> Bool
      -> Bool
      -> Bool
      -> Text
      -> Int
      -> Map Text PluginConfig
      -> Config)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Object
o Object -> Text -> Parser (Maybe CheckParents)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"checkParents" Parser (Maybe CheckParents)
-> Parser (Maybe CheckParents) -> Parser (Maybe CheckParents)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Object
v Object -> Text -> Parser (Maybe CheckParents)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"checkParents") Parser (Maybe CheckParents) -> CheckParents -> Parser CheckParents
forall a. Parser (Maybe a) -> a -> Parser a
.!= Config -> CheckParents
checkParents Config
forall a. Default a => a
def
      Parser
  (Bool
   -> Bool
   -> Bool
   -> Int
   -> Int
   -> Bool
   -> Bool
   -> Bool
   -> Text
   -> Int
   -> Map Text PluginConfig
   -> Config)
-> Parser Bool
-> Parser
     (Bool
      -> Bool
      -> Int
      -> Int
      -> Bool
      -> Bool
      -> Bool
      -> Text
      -> Int
      -> Map Text PluginConfig
      -> Config)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Object
o Object -> Text -> Parser (Maybe Bool)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"checkProject" Parser (Maybe Bool) -> Parser (Maybe Bool) -> Parser (Maybe Bool)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Object
v Object -> Text -> Parser (Maybe Bool)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"checkProject") Parser (Maybe Bool) -> Bool -> Parser Bool
forall a. Parser (Maybe a) -> a -> Parser a
.!= Config -> Bool
checkProject Config
forall a. Default a => a
def
      Parser
  (Bool
   -> Bool
   -> Int
   -> Int
   -> Bool
   -> Bool
   -> Bool
   -> Text
   -> Int
   -> Map Text PluginConfig
   -> Config)
-> Parser Bool
-> Parser
     (Bool
      -> Int
      -> Int
      -> Bool
      -> Bool
      -> Bool
      -> Text
      -> Int
      -> Map Text PluginConfig
      -> Config)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser (Maybe Bool)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"hlintOn"                                 Parser (Maybe Bool) -> Bool -> Parser Bool
forall a. Parser (Maybe a) -> a -> Parser a
.!= Config -> Bool
hlintOn Config
forall a. Default a => a
def
      Parser
  (Bool
   -> Int
   -> Int
   -> Bool
   -> Bool
   -> Bool
   -> Text
   -> Int
   -> Map Text PluginConfig
   -> Config)
-> Parser Bool
-> Parser
     (Int
      -> Int
      -> Bool
      -> Bool
      -> Bool
      -> Text
      -> Int
      -> Map Text PluginConfig
      -> Config)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser (Maybe Bool)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"diagnosticsOnChange"                     Parser (Maybe Bool) -> Bool -> Parser Bool
forall a. Parser (Maybe a) -> a -> Parser a
.!= Config -> Bool
diagnosticsOnChange Config
forall a. Default a => a
def
      Parser
  (Int
   -> Int
   -> Bool
   -> Bool
   -> Bool
   -> Text
   -> Int
   -> Map Text PluginConfig
   -> Config)
-> Parser Int
-> Parser
     (Int
      -> Bool
      -> Bool
      -> Bool
      -> Text
      -> Int
      -> Map Text PluginConfig
      -> Config)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser (Maybe Int)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"maxNumberOfProblems"                     Parser (Maybe Int) -> Int -> Parser Int
forall a. Parser (Maybe a) -> a -> Parser a
.!= Config -> Int
maxNumberOfProblems Config
forall a. Default a => a
def
      Parser
  (Int
   -> Bool
   -> Bool
   -> Bool
   -> Text
   -> Int
   -> Map Text PluginConfig
   -> Config)
-> Parser Int
-> Parser
     (Bool
      -> Bool -> Bool -> Text -> Int -> Map Text PluginConfig -> Config)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser (Maybe Int)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"diagnosticsDebounceDuration"             Parser (Maybe Int) -> Int -> Parser Int
forall a. Parser (Maybe a) -> a -> Parser a
.!= Config -> Int
diagnosticsDebounceDuration Config
forall a. Default a => a
def
      Parser
  (Bool
   -> Bool -> Bool -> Text -> Int -> Map Text PluginConfig -> Config)
-> Parser Bool
-> Parser
     (Bool -> Bool -> Text -> Int -> Map Text PluginConfig -> Config)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser (Maybe Bool)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"liquidOn"                                Parser (Maybe Bool) -> Bool -> Parser Bool
forall a. Parser (Maybe a) -> a -> Parser a
.!= Config -> Bool
liquidOn Config
forall a. Default a => a
def
      Parser
  (Bool -> Bool -> Text -> Int -> Map Text PluginConfig -> Config)
-> Parser Bool
-> Parser (Bool -> Text -> Int -> Map Text PluginConfig -> Config)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser (Maybe Bool)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"completionSnippetsOn"                    Parser (Maybe Bool) -> Bool -> Parser Bool
forall a. Parser (Maybe a) -> a -> Parser a
.!= Config -> Bool
completionSnippetsOn Config
forall a. Default a => a
def
      Parser (Bool -> Text -> Int -> Map Text PluginConfig -> Config)
-> Parser Bool
-> Parser (Text -> Int -> Map Text PluginConfig -> Config)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser (Maybe Bool)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"formatOnImportOn"                        Parser (Maybe Bool) -> Bool -> Parser Bool
forall a. Parser (Maybe a) -> a -> Parser a
.!= Config -> Bool
formatOnImportOn Config
forall a. Default a => a
def
      Parser (Text -> Int -> Map Text PluginConfig -> Config)
-> Parser Text -> Parser (Int -> Map Text PluginConfig -> Config)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser (Maybe Text)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"formattingProvider"                      Parser (Maybe Text) -> Text -> Parser Text
forall a. Parser (Maybe a) -> a -> Parser a
.!= Config -> Text
formattingProvider Config
forall a. Default a => a
def
      Parser (Int -> Map Text PluginConfig -> Config)
-> Parser Int -> Parser (Map Text PluginConfig -> Config)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser (Maybe Int)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"maxCompletions"                          Parser (Maybe Int) -> Int -> Parser Int
forall a. Parser (Maybe a) -> a -> Parser a
.!= Config -> Int
maxCompletions Config
forall a. Default a => a
def
      Parser (Map Text PluginConfig -> Config)
-> Parser (Map Text PluginConfig) -> Parser Config
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser (Maybe (Map Text PluginConfig))
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"plugin"                                  Parser (Maybe (Map Text PluginConfig))
-> Map Text PluginConfig -> Parser (Map Text PluginConfig)
forall a. Parser (Maybe a) -> a -> Parser a
.!= Config -> Map Text PluginConfig
plugins Config
forall a. Default a => a
def

-- 2017-10-09 23:22:00.710515298 [ThreadId 11] - ---> {"jsonrpc":"2.0","method":"workspace/didChangeConfiguration","params":{"settings":{"haskell":{"maxNumberOfProblems":100,"hlintOn":true}}}}

-- 2017-10-09 23:22:00.710667381 [ThreadId 15] - reactor:got didChangeConfiguration notification:

-- NotificationMessage

--   {_jsonrpc = "2.0"

--   , _method = WorkspaceDidChangeConfiguration

--   , _params = DidChangeConfigurationParams

--                 {_settings = Object (fromList [("haskell",Object (fromList [("hlintOn",Bool True)

--                                                                            ,("maxNumberOfProblems",Number 100.0)]))])}}


instance A.ToJSON Config where
  toJSON :: Config -> Value
toJSON Config{Bool
Int
Text
Map Text PluginConfig
CheckParents
plugins :: Map Text PluginConfig
maxCompletions :: Int
formattingProvider :: Text
formatOnImportOn :: Bool
completionSnippetsOn :: Bool
liquidOn :: Bool
diagnosticsDebounceDuration :: Int
maxNumberOfProblems :: Int
diagnosticsOnChange :: Bool
hlintOn :: Bool
checkProject :: Bool
checkParents :: CheckParents
plugins :: Config -> Map Text PluginConfig
maxCompletions :: Config -> Int
formattingProvider :: Config -> Text
formatOnImportOn :: Config -> Bool
completionSnippetsOn :: Config -> Bool
liquidOn :: Config -> Bool
diagnosticsDebounceDuration :: Config -> Int
maxNumberOfProblems :: Config -> Int
diagnosticsOnChange :: Config -> Bool
hlintOn :: Config -> Bool
checkProject :: Config -> Bool
checkParents :: Config -> CheckParents
..} =
      [Pair] -> Value
object [ Text
"haskell" Text -> Value -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Value
r ]
    where
      r :: Value
r = [Pair] -> Value
object [ Text
"checkParents"                Text -> CheckParents -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= CheckParents
checkParents
                 , Text
"checkProject"                Text -> Bool -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Bool
checkProject
                 , Text
"hlintOn"                     Text -> Bool -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Bool
hlintOn
                 , Text
"diagnosticsOnChange"         Text -> Bool -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Bool
diagnosticsOnChange
                 , Text
"maxNumberOfProblems"         Text -> Int -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Int
maxNumberOfProblems
                 , Text
"diagnosticsDebounceDuration" Text -> Int -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Int
diagnosticsDebounceDuration
                 , Text
"liquidOn"                    Text -> Bool -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Bool
liquidOn
                 , Text
"completionSnippetsOn"        Text -> Bool -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Bool
completionSnippetsOn
                 , Text
"formatOnImportOn"            Text -> Bool -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Bool
formatOnImportOn
                 , Text
"formattingProvider"          Text -> Text -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
formattingProvider
                 , Text
"plugin"                      Text -> Map Text PluginConfig -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Map Text PluginConfig
plugins
                 ]

-- ---------------------------------------------------------------------


-- | A PluginConfig is a generic configuration for a given HLS plugin.  It

-- provides a "big switch" to turn it on or off as a whole, as well as small

-- switches per feature, and a slot for custom config.

-- This provides a regular naming scheme for all plugin config.

data PluginConfig =
    PluginConfig
      { PluginConfig -> Bool
plcGlobalOn      :: !Bool
      , PluginConfig -> Bool
plcCodeActionsOn :: !Bool
      , PluginConfig -> Bool
plcCodeLensOn    :: !Bool
      , PluginConfig -> Bool
plcDiagnosticsOn :: !Bool
      , PluginConfig -> Bool
plcHoverOn       :: !Bool
      , PluginConfig -> Bool
plcSymbolsOn     :: !Bool
      , PluginConfig -> Bool
plcCompletionOn  :: !Bool
      , PluginConfig -> Bool
plcRenameOn      :: !Bool
      , PluginConfig -> Object
plcConfig        :: !A.Object
      } deriving (Int -> PluginConfig -> ShowS
[PluginConfig] -> ShowS
PluginConfig -> String
(Int -> PluginConfig -> ShowS)
-> (PluginConfig -> String)
-> ([PluginConfig] -> ShowS)
-> Show PluginConfig
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PluginConfig] -> ShowS
$cshowList :: [PluginConfig] -> ShowS
show :: PluginConfig -> String
$cshow :: PluginConfig -> String
showsPrec :: Int -> PluginConfig -> ShowS
$cshowsPrec :: Int -> PluginConfig -> ShowS
Show,PluginConfig -> PluginConfig -> Bool
(PluginConfig -> PluginConfig -> Bool)
-> (PluginConfig -> PluginConfig -> Bool) -> Eq PluginConfig
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PluginConfig -> PluginConfig -> Bool
$c/= :: PluginConfig -> PluginConfig -> Bool
== :: PluginConfig -> PluginConfig -> Bool
$c== :: PluginConfig -> PluginConfig -> Bool
Eq)

instance Default PluginConfig where
  def :: PluginConfig
def = PluginConfig :: Bool
-> Bool
-> Bool
-> Bool
-> Bool
-> Bool
-> Bool
-> Bool
-> Object
-> PluginConfig
PluginConfig
      { plcGlobalOn :: Bool
plcGlobalOn      = Bool
True
      , plcCodeActionsOn :: Bool
plcCodeActionsOn = Bool
True
      , plcCodeLensOn :: Bool
plcCodeLensOn    = Bool
True
      , plcDiagnosticsOn :: Bool
plcDiagnosticsOn = Bool
True
      , plcHoverOn :: Bool
plcHoverOn       = Bool
True
      , plcSymbolsOn :: Bool
plcSymbolsOn     = Bool
True
      , plcCompletionOn :: Bool
plcCompletionOn  = Bool
True
      , plcRenameOn :: Bool
plcRenameOn      = Bool
True
      , plcConfig :: Object
plcConfig        = Object
forall a. Monoid a => a
mempty
      }

instance A.ToJSON PluginConfig where
    toJSON :: PluginConfig -> Value
toJSON (PluginConfig Bool
g Bool
ca Bool
cl Bool
d Bool
h Bool
s Bool
c Bool
rn Object
cfg) = Value
r
      where
        r :: Value
r = [Pair] -> Value
object [ Text
"globalOn"      Text -> Bool -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Bool
g
                   , Text
"codeActionsOn" Text -> Bool -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Bool
ca
                   , Text
"codeLensOn"    Text -> Bool -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Bool
cl
                   , Text
"diagnosticsOn" Text -> Bool -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Bool
d
                   , Text
"hoverOn"       Text -> Bool -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Bool
h
                   , Text
"symbolsOn"     Text -> Bool -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Bool
s
                   , Text
"completionOn"  Text -> Bool -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Bool
c
                   , Text
"renameOn"      Text -> Bool -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Bool
rn
                   , Text
"config"        Text -> Object -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Object
cfg
                   ]

instance A.FromJSON PluginConfig where
  parseJSON :: Value -> Parser PluginConfig
parseJSON = String
-> (Object -> Parser PluginConfig) -> Value -> Parser PluginConfig
forall a. String -> (Object -> Parser a) -> Value -> Parser a
A.withObject String
"PluginConfig" ((Object -> Parser PluginConfig) -> Value -> Parser PluginConfig)
-> (Object -> Parser PluginConfig) -> Value -> Parser PluginConfig
forall a b. (a -> b) -> a -> b
$ \Object
o  -> Bool
-> Bool
-> Bool
-> Bool
-> Bool
-> Bool
-> Bool
-> Bool
-> Object
-> PluginConfig
PluginConfig
      (Bool
 -> Bool
 -> Bool
 -> Bool
 -> Bool
 -> Bool
 -> Bool
 -> Bool
 -> Object
 -> PluginConfig)
-> Parser Bool
-> Parser
     (Bool
      -> Bool
      -> Bool
      -> Bool
      -> Bool
      -> Bool
      -> Bool
      -> Object
      -> PluginConfig)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Text -> Parser (Maybe Bool)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"globalOn"      Parser (Maybe Bool) -> Bool -> Parser Bool
forall a. Parser (Maybe a) -> a -> Parser a
.!= PluginConfig -> Bool
plcGlobalOn PluginConfig
forall a. Default a => a
def
      Parser
  (Bool
   -> Bool
   -> Bool
   -> Bool
   -> Bool
   -> Bool
   -> Bool
   -> Object
   -> PluginConfig)
-> Parser Bool
-> Parser
     (Bool
      -> Bool -> Bool -> Bool -> Bool -> Bool -> Object -> PluginConfig)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser (Maybe Bool)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"codeActionsOn" Parser (Maybe Bool) -> Bool -> Parser Bool
forall a. Parser (Maybe a) -> a -> Parser a
.!= PluginConfig -> Bool
plcCodeActionsOn PluginConfig
forall a. Default a => a
def
      Parser
  (Bool
   -> Bool -> Bool -> Bool -> Bool -> Bool -> Object -> PluginConfig)
-> Parser Bool
-> Parser
     (Bool -> Bool -> Bool -> Bool -> Bool -> Object -> PluginConfig)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser (Maybe Bool)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"codeLensOn"    Parser (Maybe Bool) -> Bool -> Parser Bool
forall a. Parser (Maybe a) -> a -> Parser a
.!= PluginConfig -> Bool
plcCodeLensOn    PluginConfig
forall a. Default a => a
def
      Parser
  (Bool -> Bool -> Bool -> Bool -> Bool -> Object -> PluginConfig)
-> Parser Bool
-> Parser (Bool -> Bool -> Bool -> Bool -> Object -> PluginConfig)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser (Maybe Bool)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"diagnosticsOn" Parser (Maybe Bool) -> Bool -> Parser Bool
forall a. Parser (Maybe a) -> a -> Parser a
.!= PluginConfig -> Bool
plcDiagnosticsOn PluginConfig
forall a. Default a => a
def -- AZ

      Parser (Bool -> Bool -> Bool -> Bool -> Object -> PluginConfig)
-> Parser Bool
-> Parser (Bool -> Bool -> Bool -> Object -> PluginConfig)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser (Maybe Bool)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"hoverOn"       Parser (Maybe Bool) -> Bool -> Parser Bool
forall a. Parser (Maybe a) -> a -> Parser a
.!= PluginConfig -> Bool
plcHoverOn       PluginConfig
forall a. Default a => a
def
      Parser (Bool -> Bool -> Bool -> Object -> PluginConfig)
-> Parser Bool -> Parser (Bool -> Bool -> Object -> PluginConfig)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser (Maybe Bool)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"symbolsOn"     Parser (Maybe Bool) -> Bool -> Parser Bool
forall a. Parser (Maybe a) -> a -> Parser a
.!= PluginConfig -> Bool
plcSymbolsOn     PluginConfig
forall a. Default a => a
def
      Parser (Bool -> Bool -> Object -> PluginConfig)
-> Parser Bool -> Parser (Bool -> Object -> PluginConfig)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser (Maybe Bool)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"completionOn"  Parser (Maybe Bool) -> Bool -> Parser Bool
forall a. Parser (Maybe a) -> a -> Parser a
.!= PluginConfig -> Bool
plcCompletionOn  PluginConfig
forall a. Default a => a
def
      Parser (Bool -> Object -> PluginConfig)
-> Parser Bool -> Parser (Object -> PluginConfig)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser (Maybe Bool)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"renameOn"      Parser (Maybe Bool) -> Bool -> Parser Bool
forall a. Parser (Maybe a) -> a -> Parser a
.!= PluginConfig -> Bool
plcRenameOn      PluginConfig
forall a. Default a => a
def
      Parser (Object -> PluginConfig)
-> Parser Object -> Parser PluginConfig
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser (Maybe Object)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"config"        Parser (Maybe Object) -> Object -> Parser Object
forall a. Parser (Maybe a) -> a -> Parser a
.!= PluginConfig -> Object
plcConfig        PluginConfig
forall a. Default a => a
def

-- ---------------------------------------------------------------------