packages feed

hls-plugin-api 2.5.0.0 → 2.6.0.0

raw patch · 8 files changed

+311/−228 lines, 8 filesdep ~hls-graphPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: hls-graph

API changes (from Hackage documentation)

- Ide.PluginUtils: pluginEnabled :: PluginMethod k m => SMethod m -> MessageParams m -> PluginDescriptor c -> Config -> Bool
- Ide.Types: pluginEnabled :: (PluginMethod k m, HasTextDocument (MessageParams m) doc, HasUri doc Uri) => SMethod m -> MessageParams m -> PluginDescriptor c -> Config -> Bool
- Ide.Types: pluginEnabledConfig :: (PluginConfig -> Bool) -> PluginConfig -> Bool
+ Ide.Plugin.Config: [$sel:plcSemanticTokensOn:PluginConfig] :: PluginConfig -> !Bool
+ Ide.Plugin.HandleRequestTypes: DisabledGlobally :: RejectionReason
+ Ide.Plugin.HandleRequestTypes: DoesNotHandleRequest :: RejectionReason -> HandleRequestResult
+ Ide.Plugin.HandleRequestTypes: DoesNotSupportFileType :: Text -> RejectionReason
+ Ide.Plugin.HandleRequestTypes: FeatureDisabled :: RejectionReason
+ Ide.Plugin.HandleRequestTypes: HandlesRequest :: HandleRequestResult
+ Ide.Plugin.HandleRequestTypes: NotFormattingProvider :: Text -> RejectionReason
+ Ide.Plugin.HandleRequestTypes: NotResolveOwner :: Text -> RejectionReason
+ Ide.Plugin.HandleRequestTypes: data HandleRequestResult
+ Ide.Plugin.HandleRequestTypes: data RejectionReason
+ Ide.Plugin.HandleRequestTypes: instance GHC.Base.Semigroup Ide.Plugin.HandleRequestTypes.HandleRequestResult
+ Ide.Plugin.HandleRequestTypes: instance GHC.Classes.Eq Ide.Plugin.HandleRequestTypes.HandleRequestResult
+ Ide.Plugin.HandleRequestTypes: instance GHC.Classes.Eq Ide.Plugin.HandleRequestTypes.RejectionReason
+ Ide.Plugin.HandleRequestTypes: instance Prettyprinter.Internal.Pretty Ide.Plugin.HandleRequestTypes.HandleRequestResult
+ Ide.Plugin.HandleRequestTypes: instance Prettyprinter.Internal.Pretty Ide.Plugin.HandleRequestTypes.RejectionReason
+ Ide.Plugin.Properties: instance ('GHC.Types.False GHC.Types.~ Ide.Plugin.Properties.IsPropertySymbol s k, Ide.Plugin.Properties.FindPropertyMeta s ks t) => Ide.Plugin.Properties.FindPropertyMetaIf 'GHC.Types.False s k ks t
+ Ide.Plugin.Properties: instance (k GHC.Types.~ 'Ide.Plugin.Properties.PropertyKey s t) => Ide.Plugin.Properties.FindPropertyMetaIf 'GHC.Types.True s k ks t
+ Ide.Plugin.Properties: instance Ide.Plugin.Properties.FindPropertyMetaIf (Ide.Plugin.Properties.IsPropertySymbol symbol k) symbol k ks t => Ide.Plugin.Properties.FindPropertyMeta symbol (k : ks) t
+ Ide.PluginUtils: handlesRequest :: PluginMethod k m => SMethod m -> MessageParams m -> PluginDescriptor c -> Config -> HandleRequestResult
+ Ide.Types: [$sel:plcSemanticTokensOn:PluginConfig] :: PluginConfig -> !Bool
+ Ide.Types: [$sel:pluginDescription:PluginDescriptor] :: PluginDescriptor (ideState :: Type) -> !Text
+ Ide.Types: describePlugin :: PluginDescriptor c -> Doc ann
+ Ide.Types: handlesRequest :: (PluginMethod k m, HasTextDocument (MessageParams m) doc, HasUri doc Uri) => SMethod m -> MessageParams m -> PluginDescriptor c -> Config -> HandleRequestResult
+ Ide.Types: instance Ide.Types.PluginMethod 'Language.LSP.Protocol.Message.Meta.Request 'Language.LSP.Protocol.Internal.Method.Method_TextDocumentSemanticTokensFull
+ Ide.Types: instance Ide.Types.PluginRequestMethod 'Language.LSP.Protocol.Internal.Method.Method_TextDocumentSemanticTokensFull
- Ide.Plugin.Config: PluginConfig :: !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Object -> PluginConfig
+ Ide.Plugin.Config: PluginConfig :: !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Object -> PluginConfig
- Ide.Plugin.Error: PluginRequestRefused :: Text -> PluginError
+ Ide.Plugin.Error: PluginRequestRefused :: RejectionReason -> PluginError
- Ide.Plugin.Properties: type HasProperty s k t r = (k ~ 'PropertyKey s t, Elem s r, FindByKeyName s r ~ t, KnownSymbol s)
+ Ide.Plugin.Properties: type HasProperty s k t r = (k ~ 'PropertyKey s t, Elem s r, FindByKeyName s r ~ t, KnownSymbol s, FindPropertyMeta s r t)
- Ide.Types: PluginConfig :: !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Object -> PluginConfig
+ Ide.Types: PluginConfig :: !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Object -> PluginConfig
- Ide.Types: PluginDescriptor :: !PluginId -> Natural -> !Rules () -> ![PluginCommand ideState] -> PluginHandlers ideState -> ConfigDescriptor -> PluginNotificationHandlers ideState -> DynFlagsModifications -> Maybe (ParserInfo (IdeCommand ideState)) -> [Text] -> PluginDescriptor (ideState :: Type)
+ Ide.Types: PluginDescriptor :: !PluginId -> !Text -> Natural -> !Rules () -> ![PluginCommand ideState] -> PluginHandlers ideState -> ConfigDescriptor -> PluginNotificationHandlers ideState -> DynFlagsModifications -> Maybe (ParserInfo (IdeCommand ideState)) -> [Text] -> PluginDescriptor (ideState :: Type)
- Ide.Types: defaultCabalPluginDescriptor :: PluginId -> PluginDescriptor ideState
+ Ide.Types: defaultCabalPluginDescriptor :: PluginId -> Text -> PluginDescriptor ideState
- Ide.Types: defaultPluginDescriptor :: PluginId -> PluginDescriptor ideState
+ Ide.Types: defaultPluginDescriptor :: PluginId -> Text -> PluginDescriptor ideState

Files

hls-plugin-api.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name:          hls-plugin-api-version:       2.5.0.0+version:       2.6.0.0 synopsis:      Haskell Language Server API for plugin communication description:   Please see the README on GitHub at <https://github.com/haskell/haskell-language-server#readme>@@ -38,6 +38,7 @@     Ide.Plugin.Config     Ide.Plugin.ConfigUtils     Ide.Plugin.Error+    Ide.Plugin.HandleRequestTypes     Ide.Plugin.Properties     Ide.Plugin.RangeMap     Ide.Plugin.Resolve@@ -59,7 +60,7 @@     , filepath     , ghc     , hashable-    , hls-graph             == 2.5.0.0+    , hls-graph             == 2.6.0.0     , lens     , lens-aeson     , lsp                   ^>=2.3
src/Ide/Plugin/Config.hs view
@@ -66,6 +66,7 @@ parsePluginConfig def = A.withObject "PluginConfig" $ \o  -> PluginConfig       <$> o .:? "globalOn"         .!= plcGlobalOn def       <*> o .:? "callHierarchyOn"  .!= plcCallHierarchyOn def+      <*> o .:? "semanticTokensOn" .!= plcSemanticTokensOn def       <*> o .:? "codeActionsOn"    .!= plcCodeActionsOn def       <*> o .:? "codeLensOn"       .!= plcCodeLensOn    def       <*> o .:? "diagnosticsOn"    .!= plcDiagnosticsOn def -- AZ
src/Ide/Plugin/ConfigUtils.hs view
@@ -93,6 +93,7 @@           SMethod_TextDocumentDocumentSymbol       -> ["symbolsOn" A..= plcSymbolsOn]           SMethod_TextDocumentCompletion           -> ["completionOn" A..= plcCompletionOn]           SMethod_TextDocumentPrepareCallHierarchy -> ["callHierarchyOn" A..= plcCallHierarchyOn]+          SMethod_TextDocumentSemanticTokensFull   -> ["semanticTokensOn" A..= plcSemanticTokensOn]           _                                 -> []  -- | Generates json schema used in haskell vscode extension@@ -107,28 +108,29 @@         (PluginId pId) = pluginId         genericSchema =           let x =-                [toKey' "diagnosticsOn" A..= schemaEntry "diagnostics" | configHasDiagnostics]-                  <> nubOrd (mconcat (handlersToGenericSchema <$> handlers))+                [toKey' "diagnosticsOn" A..= schemaEntry "diagnostics" True | configHasDiagnostics]+                  <> nubOrd (mconcat (handlersToGenericSchema configInitialGenericConfig <$> handlers))            in case x of                 -- If the plugin has only one capability, we produce globalOn instead of the specific one;                 -- otherwise we don't produce globalOn at all-                [_] -> [toKey' "globalOn" A..= schemaEntry "plugin"]+                [_] -> [toKey' "globalOn" A..= schemaEntry "plugin" (plcGlobalOn configInitialGenericConfig)]                 _   -> x         dedicatedSchema = customConfigToDedicatedSchema configCustomConfig-        handlersToGenericSchema (IdeMethod m DSum.:=> _) = case m of-          SMethod_TextDocumentCodeAction -> [toKey' "codeActionsOn" A..= schemaEntry "code actions"]-          SMethod_TextDocumentCodeLens -> [toKey' "codeLensOn" A..= schemaEntry "code lenses"]-          SMethod_TextDocumentRename -> [toKey' "renameOn" A..= schemaEntry "rename"]-          SMethod_TextDocumentHover -> [toKey' "hoverOn" A..= schemaEntry "hover"]-          SMethod_TextDocumentDocumentSymbol -> [toKey' "symbolsOn" A..= schemaEntry "symbols"]-          SMethod_TextDocumentCompletion -> [toKey' "completionOn" A..= schemaEntry "completions"]-          SMethod_TextDocumentPrepareCallHierarchy -> [toKey' "callHierarchyOn" A..= schemaEntry "call hierarchy"]-          _ -> []-        schemaEntry desc =+        handlersToGenericSchema PluginConfig{..} (IdeMethod m DSum.:=> _) = case m of+          SMethod_TextDocumentCodeAction           -> [toKey' "codeActionsOn" A..= schemaEntry "code actions" plcCodeActionsOn]+          SMethod_TextDocumentCodeLens             -> [toKey' "codeLensOn" A..= schemaEntry "code lenses" plcCodeLensOn]+          SMethod_TextDocumentRename               -> [toKey' "renameOn" A..= schemaEntry "rename" plcRenameOn]+          SMethod_TextDocumentHover                -> [toKey' "hoverOn" A..= schemaEntry "hover" plcHoverOn]+          SMethod_TextDocumentDocumentSymbol       -> [toKey' "symbolsOn" A..= schemaEntry "symbols" plcSymbolsOn]+          SMethod_TextDocumentCompletion           -> [toKey' "completionOn" A..= schemaEntry "completions" plcCompletionOn]+          SMethod_TextDocumentPrepareCallHierarchy -> [toKey' "callHierarchyOn" A..= schemaEntry "call hierarchy" plcCallHierarchyOn]+          SMethod_TextDocumentSemanticTokensFull   -> [toKey' "semanticTokensOn" A..= schemaEntry "semantic tokens" plcSemanticTokensOn]+          _                                        -> []+        schemaEntry desc defaultVal =           A.object             [ "scope" A..= A.String "resource",               "type" A..= A.String "boolean",-              "default" A..= True,+              "default" A..= A.Bool defaultVal,               "description" A..= A.String ("Enables " <> pId <> " " <> desc)             ]         withIdPrefix x = "haskell.plugin." <> pId <> "." <> x
src/Ide/Plugin/Error.hs view
@@ -11,11 +11,12 @@     getNormalizedFilePathE, ) where -import           Control.Monad.Extra         (maybeM)-import           Control.Monad.Trans.Class   (lift)-import           Control.Monad.Trans.Except  (ExceptT (..), throwE)-import qualified Data.Text                   as T+import           Control.Monad.Extra           (maybeM)+import           Control.Monad.Trans.Class     (lift)+import           Control.Monad.Trans.Except    (ExceptT (..), throwE)+import qualified Data.Text                     as T import           Ide.Logger+import           Ide.Plugin.HandleRequestTypes (RejectionReason) import           Language.LSP.Protocol.Types  -- ----------------------------------------------------------------------------@@ -79,13 +80,13 @@   | PluginInvalidUserState T.Text     -- |PluginRequestRefused allows your handler to inspect a request before     -- rejecting it. In effect it allows your plugin to act make a secondary-    -- `pluginEnabled` decision after receiving the request. This should only be+    -- `handlesRequest` decision after receiving the request. This should only be     -- used if the decision to accept the request can not be made in-    -- `pluginEnabled`.+    -- `handlesRequest`.     --     -- This error will be with Debug. If it's the only response to a request,-    -- HLS will respond as if no plugins passed the `pluginEnabled` stage.-  | PluginRequestRefused T.Text+    -- HLS will respond as if no plugins passed the `handlesRequest` stage.+  | PluginRequestRefused RejectionReason     -- |PluginRuleFailed should be thrown when a Rule your response depends on     -- fails.     --
+ src/Ide/Plugin/HandleRequestTypes.hs view
@@ -0,0 +1,46 @@+{-# LANGUAGE OverloadedStrings #-}++module Ide.Plugin.HandleRequestTypes where++import           Data.Text+import           Prettyprinter++-- | Reasons why a plugin could reject a specific request.+data RejectionReason =+  -- | The resolve request is not meant for this plugin or handler. The text+  -- field should contain the identifier for the plugin who owns this resolve+  -- request.+  NotResolveOwner Text+  -- | The plugin is disabled globally in the users config.+  | DisabledGlobally+  -- | The feature in the plugin that responds to this request is disabled in+  -- the users config+  | FeatureDisabled+  -- | This plugin is not the formatting provider selected in the users config.+  -- The text should be the formatting provider in your config.+  | NotFormattingProvider Text+  -- | This plugin does not support the file type. The text field here should+  -- contain the filetype of the rejected request.+  | DoesNotSupportFileType Text+  deriving (Eq)++-- | Whether a plugin will handle a request or not.+data HandleRequestResult = HandlesRequest | DoesNotHandleRequest RejectionReason+  deriving (Eq)++instance Pretty HandleRequestResult where+  pretty HandlesRequest                = "handles this request"+  pretty (DoesNotHandleRequest reason) = pretty reason++instance Pretty RejectionReason where+  pretty (NotResolveOwner s) = "does not handle resolve requests for " <> pretty s <> ")."+  pretty DisabledGlobally = "is disabled globally in your config."+  pretty FeatureDisabled = "'s feature that handles this request is disabled in your config."+  pretty (NotFormattingProvider s) = "is not the formatting provider ("<> pretty s<>") you chose in your config."+  pretty (DoesNotSupportFileType s) = "does not support " <> pretty s <> " filetypes)."++-- We always want to keep the leftmost disabled reason+instance Semigroup HandleRequestResult where+  HandlesRequest <> HandlesRequest = HandlesRequest+  DoesNotHandleRequest r <> _      = DoesNotHandleRequest r+  _ <> DoesNotHandleRequest r      = DoesNotHandleRequest r
src/Ide/Plugin/Properties.hs view
@@ -11,8 +11,6 @@ {-# LANGUAGE TypeFamilies          #-} {-# LANGUAGE TypeOperators         #-} {-# LANGUAGE UndecidableInstances  #-}--- See Note [Constraints]-{-# OPTIONS_GHC -Wno-redundant-constraints #-}  module Ide.Plugin.Properties   ( PropertyType (..),@@ -44,13 +42,11 @@ import           Data.Either          (fromRight) import           Data.Function        ((&)) import           Data.Kind            (Constraint, Type)-import qualified Data.Map.Strict      as Map import           Data.Proxy           (Proxy (..)) import           Data.String          (IsString (fromString)) import qualified Data.Text            as T import           GHC.OverloadedLabels (IsLabel (..)) import           GHC.TypeLits-import           Unsafe.Coerce        (unsafeCoerce)  -- | Types properties may have data PropertyType@@ -114,7 +110,10 @@ -- A property is an immediate child of the json object in each plugin's "config" section. -- It was designed to be compatible with vscode's settings UI. -- Use 'emptyProperties' and 'useProperty' to create and consume 'Properties'.-newtype Properties (r :: [PropertyKey]) = Properties (Map.Map String SomePropertyKeyWithMetaData)+data Properties (r :: [PropertyKey]) where+    ConsProperties :: (k ~ 'PropertyKey s t, KnownSymbol s, NotElem s ks)+        => KeyNameProxy s -> (SPropertyKey k) -> (MetaData t) -> Properties ks -> Properties (k : ks)+    EmptyProperties :: Properties '[]  -- | A proxy type in order to allow overloaded labels as properties' names at the call site data KeyNameProxy (s :: Symbol) = KnownSymbol s => KeyNameProxy@@ -132,6 +131,10 @@   FindByKeyName s ('PropertyKey s t ': _) = t   FindByKeyName s (_ ': xs) = FindByKeyName s xs +type family IsPropertySymbol (s :: Symbol) (r :: PropertyKey) :: Bool where+    IsPropertySymbol s ('PropertyKey s _) = 'True+    IsPropertySymbol s _ = 'False+ type family Elem (s :: Symbol) (r :: [PropertyKey]) :: Constraint where   Elem s ('PropertyKey s _ ': _) = ()   Elem s (_ ': xs) = Elem s xs@@ -143,7 +146,17 @@   NotElem s '[] = ()  -- | In row @r@, there is a 'PropertyKey' @k@, which has name @s@ and carries haskell type @t@-type HasProperty s k t r = (k ~ 'PropertyKey s t, Elem s r, FindByKeyName s r ~ t, KnownSymbol s)+type HasProperty s k t r = (k ~ 'PropertyKey s t, Elem s r, FindByKeyName s r ~ t, KnownSymbol s, FindPropertyMeta s r t)+class FindPropertyMeta (s :: Symbol) (r :: [PropertyKey]) t where+    findSomePropertyKeyWithMetaData :: KeyNameProxy s -> Properties r -> (SPropertyKey ('PropertyKey s t), MetaData t)+instance (FindPropertyMetaIf (IsPropertySymbol symbol k) symbol k ks t) => FindPropertyMeta symbol (k : ks) t where+  findSomePropertyKeyWithMetaData = findSomePropertyKeyWithMetaDataIf+class (bool ~ IsPropertySymbol symbol k) => FindPropertyMetaIf bool symbol k ks t where+  findSomePropertyKeyWithMetaDataIf :: KeyNameProxy symbol -> Properties (k : ks) -> (SPropertyKey ('PropertyKey symbol t), MetaData t)+instance (k ~ 'PropertyKey s t) => FindPropertyMetaIf 'True s k ks t where+  findSomePropertyKeyWithMetaDataIf _ (ConsProperties _ k m _) = (k, m)+instance ('False ~ IsPropertySymbol s k, FindPropertyMeta s ks t) => FindPropertyMetaIf 'False s k ks t where+  findSomePropertyKeyWithMetaDataIf s (ConsProperties _ _ _ ks) = findSomePropertyKeyWithMetaData s ks  -- --------------------------------------------------------------------- @@ -164,7 +177,7 @@ -- @  emptyProperties :: Properties '[]-emptyProperties = Properties Map.empty+emptyProperties = EmptyProperties  insert ::   (k ~ 'PropertyKey s t, NotElem s r, KnownSymbol s) =>@@ -173,30 +186,14 @@   MetaData t ->   Properties r ->   Properties (k ': r)-insert kn key metadata (Properties old) =-  Properties-    ( Map.insert-        (symbolVal kn)-        (SomePropertyKeyWithMetaData key metadata)-        old-    )+insert = ConsProperties  find ::   (HasProperty s k t r) =>   KeyNameProxy s ->   Properties r ->   (SPropertyKey k, MetaData t)-find kn (Properties p) = case p Map.! symbolVal kn of-  (SomePropertyKeyWithMetaData sing metadata) ->-    -- Note [Constraints]-    -- It's safe to use unsafeCoerce here:-    --   Since each property name is unique that the redefinition will be prevented by predication on the type level list,-    --   the value we get from the name-indexed map must be exactly the singleton and metadata corresponding to the type.-    -- We drop this information at type level: some of the above type families return '() :: Constraint',-    -- so GHC will consider them as redundant.-    -- But we encode it using semantically identical 'Map' at term level,-    -- which avoids inducting on the list by defining a new type class.-    unsafeCoerce (sing, metadata)+find = findSomePropertyKeyWithMetaData  -- --------------------------------------------------------------------- @@ -350,7 +347,10 @@  -- | Converts a properties definition into kv pairs with default values from 'MetaData' toDefaultJSON :: Properties r -> [A.Pair]-toDefaultJSON (Properties p) = [toEntry s v | (s, v) <- Map.toList p]+toDefaultJSON pr = case pr of+    EmptyProperties -> []+    ConsProperties keyNameProxy k m xs ->+        toEntry (symbolVal keyNameProxy) (SomePropertyKeyWithMetaData k m) : toDefaultJSON xs   where     toEntry :: String -> SomePropertyKeyWithMetaData -> A.Pair     toEntry s = \case@@ -371,8 +371,10 @@  -- | Converts a properties definition into kv pairs as vscode schema toVSCodeExtensionSchema :: T.Text -> Properties r -> [A.Pair]-toVSCodeExtensionSchema prefix (Properties p) =-  [fromString (T.unpack prefix <> k) A..= toEntry v | (k, v) <- Map.toList p]+toVSCodeExtensionSchema prefix ps = case ps of+    EmptyProperties -> []+    ConsProperties (keyNameProxy :: KeyNameProxy s) (k :: SPropertyKey k) (m :: MetaData t) xs ->+       fromString (T.unpack prefix <> symbolVal keyNameProxy) A..= toEntry (SomePropertyKeyWithMetaData k m) : toVSCodeExtensionSchema prefix xs   where     toEntry :: SomePropertyKeyWithMetaData -> A.Value     toEntry = \case
src/Ide/PluginUtils.hs view
@@ -20,7 +20,7 @@     getClientConfig,     getPluginConfig,     configForPlugin,-    pluginEnabled,+    handlesRequest,     extractTextInRange,     fullRange,     mkLspCommand,
src/Ide/Types.hs view
@@ -25,13 +25,14 @@ module Ide.Types ( PluginDescriptor(..), defaultPluginDescriptor, defaultCabalPluginDescriptor , defaultPluginPriority+, describePlugin , IdeCommand(..) , IdeMethod(..) , IdeNotification(..) , IdePlugins(IdePlugins, ipMap) , DynFlagsModifications(..) , Config(..), PluginConfig(..), CheckParents(..)-, ConfigDescriptor(..), defaultConfigDescriptor, configForPlugin, pluginEnabledConfig+, ConfigDescriptor(..), defaultConfigDescriptor, configForPlugin , CustomConfig(..), mkCustomConfig , FallbackCodeActionParams(..) , FormattingType(..), FormattingMethod, FormattingHandler, mkFormattingHandlers@@ -66,7 +67,8 @@  import           Control.Applicative           ((<|>)) import           Control.Arrow                 ((&&&))-import           Control.Lens                  (_Just, (.~), (?~), (^.), (^?))+import           Control.Lens                  (_Just, view, (.~), (?~), (^.),+                                                (^?)) import           Control.Monad                 (void) import           Control.Monad.Error.Class     (MonadError (throwError)) import           Control.Monad.Trans.Class     (MonadTrans (lift))@@ -95,6 +97,7 @@ import           GHC                           (DynFlags) import           GHC.Generics import           Ide.Plugin.Error+import           Ide.Plugin.HandleRequestTypes import           Ide.Plugin.Properties import qualified Language.LSP.Protocol.Lens    as L import           Language.LSP.Protocol.Message@@ -104,6 +107,7 @@ import           Numeric.Natural import           OpenTelemetry.Eventlog import           Options.Applicative           (ParserInfo)+import           Prettyprinter                 as PP import           System.FilePath import           System.IO.Unsafe import           Text.Regex.TDFA.Text          ()@@ -226,6 +230,7 @@       , plcRenameOn         :: !Bool       , plcSelectionRangeOn :: !Bool       , plcFoldingRangeOn   :: !Bool+      , plcSemanticTokensOn :: !Bool       , plcConfig           :: !Object       } deriving (Show,Eq) @@ -241,12 +246,13 @@       , plcCompletionOn     = True       , plcRenameOn         = True       , plcSelectionRangeOn = True-      , plcFoldingRangeOn = True+      , plcFoldingRangeOn   = True+      , plcSemanticTokensOn = True       , plcConfig           = mempty       }  instance ToJSON PluginConfig where-    toJSON (PluginConfig g ch ca cl d h s c rn sr fr cfg) = r+    toJSON (PluginConfig g ch ca cl d h s c rn sr fr st cfg) = r       where         r = object [ "globalOn"         .= g                    , "callHierarchyOn"  .= ch@@ -259,6 +265,7 @@                    , "renameOn"         .= rn                    , "selectionRangeOn" .= sr                    , "foldingRangeOn"   .= fr+                   , "semanticTokensOn" .= st                    , "config"           .= cfg                    ] @@ -266,6 +273,7 @@  data PluginDescriptor (ideState :: Type) =   PluginDescriptor { pluginId           :: !PluginId+                   , pluginDescription  :: !T.Text                    -- ^ Unique identifier of the plugin.                    , pluginPriority     :: Natural                    -- ^ Plugin handlers are called in priority order, higher priority first@@ -283,17 +291,14 @@                    --   The file extension must have a leading '.'.                    } --- | Check whether the given plugin descriptor is responsible for the file with the given path.---   Compares the file extension of the file at the given path with the file extension---   the plugin is responsible for.-pluginResponsible :: Uri -> PluginDescriptor c -> Bool-pluginResponsible uri pluginDesc-    | Just fp <- mfp-    , T.pack (takeExtension fp) `elem` pluginFileType pluginDesc = True-    | otherwise = False-    where-      mfp = uriToFilePath uri+describePlugin :: PluginDescriptor c -> Doc ann+describePlugin p =+  let+    PluginId pid = pluginId p+    pdesc = pluginDescription p+  in pretty pid <> ":" <> nest 4 (PP.line <> pretty pdesc) + -- | An existential wrapper of 'Properties' data CustomConfig = forall r. CustomConfig (Properties r) @@ -334,26 +339,72 @@ defaultConfigDescriptor =     ConfigDescriptor Data.Default.def False (mkCustomConfig emptyProperties) +-- | Lookup the current config for a plugin+configForPlugin :: Config -> PluginDescriptor c -> PluginConfig+configForPlugin config PluginDescriptor{..}+    = Map.findWithDefault (configInitialGenericConfig pluginConfigDescriptor) pluginId (plugins config)++-- | Checks that a specific plugin is globally enabled in order to respond to+-- requests+pluginEnabledGlobally :: PluginDescriptor c -> Config -> HandleRequestResult+pluginEnabledGlobally desc conf = if plcGlobalOn (configForPlugin conf desc)+                           then HandlesRequest+                           else DoesNotHandleRequest DisabledGlobally++-- | Checks that a specific feature for a given plugin is enabled in order+-- to respond to requests+pluginFeatureEnabled :: (PluginConfig -> Bool) -> PluginDescriptor c -> Config -> HandleRequestResult+pluginFeatureEnabled f desc conf = if f (configForPlugin conf desc)+                                      then HandlesRequest+                                      else DoesNotHandleRequest FeatureDisabled++-- |Determine whether this request should be routed to the plugin. Fails closed+-- if we can't determine which plugin it should be routed to.+pluginResolverResponsible :: L.HasData_ m (Maybe Value) => m -> PluginDescriptor c -> HandleRequestResult+pluginResolverResponsible+  (view L.data_ -> (Just (fromJSON -> (Success (PluginResolveData o@(PluginId ot) _ _)))))+  pluginDesc =+  if pluginId pluginDesc == o+    then HandlesRequest+    else DoesNotHandleRequest $ NotResolveOwner ot+-- If we can't determine who this request belongs to, then we don't want any plugin+-- to handle it.+pluginResolverResponsible _ _ = DoesNotHandleRequest $ NotResolveOwner "(unable to determine resolve owner)"++-- | Check whether the given plugin descriptor supports the file with+-- the given path. Compares the file extension from the msgParams with the+-- file extension the plugin is responsible for.+-- We are passing the msgParams here even though we only need the URI URI here.+-- If in the future we need to be able to provide only an URI it can be+-- separated again.+pluginSupportsFileType :: (L.HasTextDocument m doc, L.HasUri doc Uri) => m -> PluginDescriptor c -> HandleRequestResult+pluginSupportsFileType msgParams pluginDesc =+  case mfp of+    Just fp | T.pack (takeExtension fp) `elem` pluginFileType pluginDesc -> HandlesRequest+    _ -> DoesNotHandleRequest $ DoesNotSupportFileType (maybe "(unable to determine file type)" (T.pack . takeExtension) mfp)+    where+      mfp = uriToFilePath uri+      uri = msgParams ^. L.textDocument . L.uri+ -- | Methods that can be handled by plugins. -- 'ExtraParams' captures any extra data the IDE passes to the handlers for this method -- Only methods for which we know how to combine responses can be instances of 'PluginMethod' class HasTracing (MessageParams m) => PluginMethod (k :: MessageKind) (m :: Method ClientToServer k) where -  -- | Parse the configuration to check if this plugin is enabled.-  -- Perform sanity checks on the message to see whether the plugin is enabled-  -- for this message in particular.-  -- If a plugin is not enabled, its handlers, commands, etc. will not be-  -- run for the given message.+  -- | Parse the configuration to check if this plugin is globally enabled, and+  -- if the feature which handles this method is enabled. Perform sanity checks+  -- on the message to see whether the plugin handles this message in particular.+  -- This class is only used to determine whether a plugin can handle a specific+  -- request. Commands and rules do not use this logic to determine whether or+  -- not they are run.   ---  -- Semantically, this method describes whether a plugin is enabled configuration wise-  -- and is allowed to respond to the message. This might depend on the URI that is-  -- associated to the Message Parameters. There are requests-  -- with no associated URI that, consequentially, cannot inspect the URI.   ---  -- A common reason why a plugin might not be allowed to respond although it is enabled:+  -- A common reason why a plugin won't handle a request even though it is enabled:   --   * The plugin cannot handle requests associated with the specific URI   --     * Since the implementation of [cabal plugins](https://github.com/haskell/haskell-language-server/issues/2940)   --       HLS knows plugins specific to Haskell and specific to [Cabal file descriptions](https://cabal.readthedocs.io/en/3.6/cabal-package.html)+  --   * The resolve request is not routed to that specific plugin. Each resolve+  --     request needs to be routed to only one plugin.   --   -- Strictly speaking, we are conflating two concepts here:   --   * Dynamically enabled (e.g. on a per-message basis)@@ -361,7 +412,7 @@   --     * Strictly speaking, this might also change dynamically   --   -- But there is no use to split it up into two different methods for now.-  pluginEnabled+  handlesRequest     :: SMethod m     -- ^ Method type.     -> MessageParams m@@ -373,169 +424,184 @@     -> Config     -- ^ Generic config description, expected to contain 'PluginConfig' configuration     -- for this plugin-    -> Bool+    -> HandleRequestResult     -- ^ Is this plugin enabled and allowed to respond to the given request     -- with the given parameters? -  default pluginEnabled :: (L.HasTextDocument (MessageParams m) doc, L.HasUri doc Uri)-                              => SMethod m -> MessageParams m -> PluginDescriptor c -> Config -> Bool-  pluginEnabled _ params desc conf = pluginResponsible uri desc && plcGlobalOn (configForPlugin conf desc)-    where-        uri = params ^. L.textDocument . L.uri---- ------------------------------------------------------------------------ Plugin Requests--- ---------------------------------------------------------------------+  default handlesRequest :: (L.HasTextDocument (MessageParams m) doc, L.HasUri doc Uri)+                              => SMethod m -> MessageParams m -> PluginDescriptor c -> Config -> HandleRequestResult+  handlesRequest _ params desc conf =+    pluginEnabledGlobally desc conf <> pluginSupportsFileType params desc -class PluginMethod Request m => PluginRequestMethod (m :: Method ClientToServer Request) where-  -- | How to combine responses from different plugins.-  ---  -- For example, for Hover requests, we might have multiple producers of-  -- Hover information. We do not want to decide which one to display to the user-  -- but instead allow to define how to merge two hover request responses into one-  -- glorious hover box.-  ---  -- However, as sometimes only one handler of a request can realistically exist-  -- (such as TextDocumentFormatting), it is safe to just unconditionally report-  -- back one arbitrary result (arbitrary since it should only be one anyway).-  combineResponses-    :: SMethod m-    -> Config -- ^ IDE Configuration-    -> ClientCapabilities-    -> MessageParams m-    -> NonEmpty (MessageResult m) -> MessageResult m+-- | Check if a plugin is enabled, if one of it's specific config's is enabled,+-- and if it supports the file+pluginEnabledWithFeature :: (L.HasTextDocument (MessageParams m) doc, L.HasUri doc Uri)+                              => (PluginConfig -> Bool) -> SMethod m -> MessageParams m+                              -> PluginDescriptor c -> Config -> HandleRequestResult+pluginEnabledWithFeature feature _ msgParams pluginDesc config =+  pluginEnabledGlobally pluginDesc config+  <> pluginFeatureEnabled feature pluginDesc config+  <> pluginSupportsFileType msgParams pluginDesc -  default combineResponses :: Semigroup (MessageResult m)-    => SMethod m -> Config -> ClientCapabilities -> MessageParams m -> NonEmpty (MessageResult m) -> MessageResult m-  combineResponses _method _config _caps _params = sconcat+-- | Check if a plugin is enabled, if one of it's specific configs is enabled,+-- and if it's the plugin responsible for a resolve request.+pluginEnabledResolve :: L.HasData_ s (Maybe Value) => (PluginConfig -> Bool) -> p -> s -> PluginDescriptor c -> Config -> HandleRequestResult+pluginEnabledResolve feature _ msgParams pluginDesc config =+    pluginEnabledGlobally pluginDesc config+    <> pluginFeatureEnabled feature pluginDesc config+    <> pluginResolverResponsible msgParams pluginDesc  instance PluginMethod Request Method_TextDocumentCodeAction where-  pluginEnabled _ msgParams pluginDesc config =-    pluginResponsible uri pluginDesc && pluginEnabledConfig plcCodeActionsOn (configForPlugin config pluginDesc)-    where-      uri = msgParams ^. L.textDocument . L.uri+  handlesRequest = pluginEnabledWithFeature plcCodeActionsOn  instance PluginMethod Request Method_CodeActionResolve where   -- See Note [Resolve in PluginHandlers]-  pluginEnabled _ msgParams pluginDesc config =-    pluginResolverResponsible (msgParams ^. L.data_) pluginDesc-    && pluginEnabledConfig plcCodeActionsOn (configForPlugin config pluginDesc)+  handlesRequest = pluginEnabledResolve plcCodeActionsOn  instance PluginMethod Request Method_TextDocumentDefinition where-  pluginEnabled _ msgParams pluginDesc _ =-    pluginResponsible uri pluginDesc-    where-      uri = msgParams ^. L.textDocument . L.uri+  handlesRequest _ msgParams pluginDesc _ = pluginSupportsFileType msgParams pluginDesc  instance PluginMethod Request Method_TextDocumentTypeDefinition where-  pluginEnabled _ msgParams pluginDesc _ =-    pluginResponsible uri pluginDesc-    where-      uri = msgParams ^. L.textDocument . L.uri+  handlesRequest _ msgParams pluginDesc _ = pluginSupportsFileType msgParams pluginDesc  instance PluginMethod Request Method_TextDocumentDocumentHighlight where-  pluginEnabled _ msgParams pluginDesc _ =-    pluginResponsible uri pluginDesc-    where-      uri = msgParams ^. L.textDocument . L.uri+  handlesRequest _ msgParams pluginDesc _ = pluginSupportsFileType msgParams pluginDesc  instance PluginMethod Request Method_TextDocumentReferences where-  pluginEnabled _ msgParams pluginDesc _ =-    pluginResponsible uri pluginDesc-    where-      uri = msgParams ^. L.textDocument . L.uri+  handlesRequest _ msgParams pluginDesc _ = pluginSupportsFileType msgParams pluginDesc  instance PluginMethod Request Method_WorkspaceSymbol where   -- Unconditionally enabled, but should it really be?-  pluginEnabled _ _ _ _ = True+  handlesRequest _ _ _ _ = HandlesRequest  instance PluginMethod Request Method_TextDocumentCodeLens where-  pluginEnabled _ msgParams pluginDesc config = pluginResponsible uri pluginDesc-      && pluginEnabledConfig plcCodeLensOn (configForPlugin config pluginDesc)-    where-      uri = msgParams ^. L.textDocument . L.uri+  handlesRequest = pluginEnabledWithFeature plcCodeLensOn  instance PluginMethod Request Method_CodeLensResolve where   -- See Note [Resolve in PluginHandlers]-  pluginEnabled _ msgParams pluginDesc config =-    pluginResolverResponsible (msgParams ^. L.data_) pluginDesc-    && pluginEnabledConfig plcCodeActionsOn (configForPlugin config pluginDesc)+  handlesRequest = pluginEnabledResolve plcCodeLensOn  instance PluginMethod Request Method_TextDocumentRename where-  pluginEnabled _ msgParams pluginDesc config = pluginResponsible uri pluginDesc-      && pluginEnabledConfig plcRenameOn (configForPlugin config pluginDesc)-   where-      uri = msgParams ^. L.textDocument . L.uri+  handlesRequest = pluginEnabledWithFeature plcRenameOn+ instance PluginMethod Request Method_TextDocumentHover where-  pluginEnabled _ msgParams pluginDesc config = pluginResponsible uri pluginDesc-      && pluginEnabledConfig plcHoverOn (configForPlugin config pluginDesc)-   where-      uri = msgParams ^. L.textDocument . L.uri+  handlesRequest = pluginEnabledWithFeature plcHoverOn  instance PluginMethod Request Method_TextDocumentDocumentSymbol where-  pluginEnabled _ msgParams pluginDesc config = pluginResponsible uri pluginDesc-      && pluginEnabledConfig plcSymbolsOn (configForPlugin config pluginDesc)-    where-      uri = msgParams ^. L.textDocument . L.uri+  handlesRequest = pluginEnabledWithFeature plcSymbolsOn  instance PluginMethod Request Method_CompletionItemResolve where   -- See Note [Resolve in PluginHandlers]-  pluginEnabled _ msgParams pluginDesc config = pluginResolverResponsible (msgParams ^. L.data_) pluginDesc-    && pluginEnabledConfig plcCompletionOn (configForPlugin config pluginDesc)+  handlesRequest = pluginEnabledResolve plcCompletionOn  instance PluginMethod Request Method_TextDocumentCompletion where-  pluginEnabled _ msgParams pluginDesc config = pluginResponsible uri pluginDesc-      && pluginEnabledConfig plcCompletionOn (configForPlugin config pluginDesc)-    where-      uri = msgParams ^. L.textDocument . L.uri+  handlesRequest = pluginEnabledWithFeature plcCompletionOn  instance PluginMethod Request Method_TextDocumentFormatting where-  pluginEnabled SMethod_TextDocumentFormatting msgParams pluginDesc conf =-    pluginResponsible uri pluginDesc-      && (PluginId (formattingProvider conf) == pid || PluginId (cabalFormattingProvider conf) == pid)+  handlesRequest _ msgParams pluginDesc conf =+    (if PluginId (formattingProvider conf) == pid+          || PluginId (cabalFormattingProvider conf) == pid+        then HandlesRequest+        else DoesNotHandleRequest (NotFormattingProvider (formattingProvider conf)) )+    <> pluginSupportsFileType msgParams pluginDesc     where-      uri = msgParams ^. L.textDocument . L.uri       pid = pluginId pluginDesc  instance PluginMethod Request Method_TextDocumentRangeFormatting where-  pluginEnabled _ msgParams pluginDesc conf = pluginResponsible uri pluginDesc-      && (PluginId (formattingProvider conf) == pid || PluginId (cabalFormattingProvider conf) == pid)+  handlesRequest _ msgParams pluginDesc conf =+    (if PluginId (formattingProvider conf) == pid+          || PluginId (cabalFormattingProvider conf) == pid+        then HandlesRequest+        else DoesNotHandleRequest (NotFormattingProvider (formattingProvider conf)))+    <> pluginSupportsFileType msgParams pluginDesc     where-      uri = msgParams ^. L.textDocument . L.uri       pid = pluginId pluginDesc +instance PluginMethod Request Method_TextDocumentSemanticTokensFull where+  handlesRequest = pluginEnabledWithFeature plcSemanticTokensOn+ instance PluginMethod Request Method_TextDocumentPrepareCallHierarchy where-  pluginEnabled _ msgParams pluginDesc conf = pluginResponsible uri pluginDesc-      && pluginEnabledConfig plcCallHierarchyOn (configForPlugin conf pluginDesc)-    where-      uri = msgParams ^. L.textDocument . L.uri+  handlesRequest = pluginEnabledWithFeature plcCallHierarchyOn  instance PluginMethod Request Method_TextDocumentSelectionRange where-  pluginEnabled _ msgParams pluginDesc conf = pluginResponsible uri pluginDesc-      && pluginEnabledConfig plcSelectionRangeOn (configForPlugin conf pluginDesc)-    where-      uri = msgParams ^. L.textDocument . L.uri+  handlesRequest = pluginEnabledWithFeature plcSelectionRangeOn  instance PluginMethod Request Method_TextDocumentFoldingRange where-  pluginEnabled _ msgParams pluginDesc conf = pluginResponsible uri pluginDesc-      && pluginEnabledConfig plcFoldingRangeOn (configForPlugin conf pluginDesc)-    where-      uri = msgParams ^. L.textDocument . L.uri+  handlesRequest = pluginEnabledWithFeature plcFoldingRangeOn  instance PluginMethod Request Method_CallHierarchyIncomingCalls where   -- This method has no URI parameter, thus no call to 'pluginResponsible'-  pluginEnabled _ _ pluginDesc conf = pluginEnabledConfig plcCallHierarchyOn (configForPlugin conf pluginDesc)+  handlesRequest _ _ pluginDesc conf =+      pluginEnabledGlobally pluginDesc conf+    <> pluginFeatureEnabled plcCallHierarchyOn pluginDesc conf  instance PluginMethod Request Method_CallHierarchyOutgoingCalls where   -- This method has no URI parameter, thus no call to 'pluginResponsible'-  pluginEnabled _ _ pluginDesc conf = pluginEnabledConfig plcCallHierarchyOn (configForPlugin conf pluginDesc)+  handlesRequest _ _ pluginDesc conf =+      pluginEnabledGlobally pluginDesc conf+    <> pluginFeatureEnabled plcCallHierarchyOn pluginDesc conf  instance PluginMethod Request Method_WorkspaceExecuteCommand where-  pluginEnabled _ _ _ _= True+  handlesRequest _ _ _ _= HandlesRequest  instance PluginMethod Request (Method_CustomMethod m) where-  pluginEnabled _ _ _ _ = True+  handlesRequest _ _ _ _ = HandlesRequest +-- Plugin Notifications++instance PluginMethod Notification Method_TextDocumentDidOpen where++instance PluginMethod Notification Method_TextDocumentDidChange where++instance PluginMethod Notification Method_TextDocumentDidSave where++instance PluginMethod Notification Method_TextDocumentDidClose where++instance PluginMethod Notification Method_WorkspaceDidChangeWatchedFiles where+  -- This method has no URI parameter, thus no call to 'pluginResponsible'.+  handlesRequest _ _ desc conf = pluginEnabledGlobally desc conf++instance PluginMethod Notification Method_WorkspaceDidChangeWorkspaceFolders where+  -- This method has no URI parameter, thus no call to 'pluginResponsible'.+  handlesRequest _ _ desc conf = pluginEnabledGlobally desc conf++instance PluginMethod Notification Method_WorkspaceDidChangeConfiguration where+  -- This method has no URI parameter, thus no call to 'pluginResponsible'.+  handlesRequest _ _ desc conf = pluginEnabledGlobally desc conf++instance PluginMethod Notification Method_Initialized where+  -- This method has no URI parameter, thus no call to 'pluginResponsible'.+  handlesRequest _ _ desc conf = pluginEnabledGlobally desc conf+++-- ---------------------------------------------------------------------+-- Plugin Requests+-- ---------------------------------------------------------------------++class PluginMethod Request m => PluginRequestMethod (m :: Method ClientToServer Request) where+  -- | How to combine responses from different plugins.+  --+  -- For example, for Hover requests, we might have multiple producers of+  -- Hover information. We do not want to decide which one to display to the user+  -- but instead allow to define how to merge two hover request responses into one+  -- glorious hover box.+  --+  -- However, as sometimes only one handler of a request can realistically exist+  -- (such as TextDocumentFormatting), it is safe to just unconditionally report+  -- back one arbitrary result (arbitrary since it should only be one anyway).+  combineResponses+    :: SMethod m+    -> Config -- ^ IDE Configuration+    -> ClientCapabilities+    -> MessageParams m+    -> NonEmpty (MessageResult m) -> MessageResult m++  default combineResponses :: Semigroup (MessageResult m)+    => SMethod m -> Config -> ClientCapabilities -> MessageParams m -> NonEmpty (MessageResult m) -> MessageResult m+  combineResponses _method _config _caps _params = sconcat+++ --- instance PluginRequestMethod Method_TextDocumentCodeAction where   combineResponses _method _config (ClientCapabilities _ textDocCaps _ _ _ _) (CodeActionParams _ _ _ _ context) resps =@@ -691,6 +757,9 @@ instance PluginRequestMethod (Method_CustomMethod m) where   combineResponses _ _ _ _ (x :| _) = x +instance PluginRequestMethod Method_TextDocumentSemanticTokensFull where+  combineResponses _ _ _ _ (x :| _) = x+ takeLefts :: [a |? b] -> [a] takeLefts = mapMaybe (\x -> [res | (InL res) <- Just x]) @@ -746,31 +815,6 @@ class PluginMethod Notification m => PluginNotificationMethod (m :: Method ClientToServer Notification)  where  -instance PluginMethod Notification Method_TextDocumentDidOpen where--instance PluginMethod Notification Method_TextDocumentDidChange where--instance PluginMethod Notification Method_TextDocumentDidSave where--instance PluginMethod Notification Method_TextDocumentDidClose where--instance PluginMethod Notification Method_WorkspaceDidChangeWatchedFiles where-  -- This method has no URI parameter, thus no call to 'pluginResponsible'.-  pluginEnabled _ _ desc conf = plcGlobalOn $ configForPlugin conf desc--instance PluginMethod Notification Method_WorkspaceDidChangeWorkspaceFolders where-  -- This method has no URI parameter, thus no call to 'pluginResponsible'.-  pluginEnabled _ _ desc conf = plcGlobalOn $ configForPlugin conf desc--instance PluginMethod Notification Method_WorkspaceDidChangeConfiguration where-  -- This method has no URI parameter, thus no call to 'pluginResponsible'.-  pluginEnabled _ _ desc conf = plcGlobalOn $ configForPlugin conf desc--instance PluginMethod Notification Method_Initialized where-  -- This method has no URI parameter, thus no call to 'pluginResponsible'.-  pluginEnabled _ _ desc conf = plcGlobalOn $ configForPlugin conf desc-- instance PluginNotificationMethod Method_TextDocumentDidOpen where  instance PluginNotificationMethod Method_TextDocumentDidChange where@@ -894,10 +938,11 @@ -- -- and handlers will be enabled for files with the appropriate file -- extensions.-defaultPluginDescriptor :: PluginId -> PluginDescriptor ideState-defaultPluginDescriptor plId =+defaultPluginDescriptor :: PluginId -> T.Text -> PluginDescriptor ideState+defaultPluginDescriptor plId desc =   PluginDescriptor     plId+    desc     defaultPluginPriority     mempty     mempty@@ -914,10 +959,11 @@ -- -- Handles files with the following extensions: --   * @.cabal@-defaultCabalPluginDescriptor :: PluginId -> PluginDescriptor ideState-defaultCabalPluginDescriptor plId =+defaultCabalPluginDescriptor :: PluginId -> T.Text -> PluginDescriptor ideState+defaultCabalPluginDescriptor plId desc =   PluginDescriptor     plId+    desc     defaultPluginPriority     mempty     mempty@@ -965,7 +1011,7 @@   -> PluginHandlers ideState mkResolveHandler m f = mkPluginHandler m $ \ideState plId params -> do   case fromJSON <$> (params ^. L.data_) of-    (Just (Success (PluginResolveData owner uri value) )) -> do+    (Just (Success (PluginResolveData owner@(PluginId ownerName) uri value) )) -> do       if owner == plId       then         case fromJSON value of@@ -975,7 +1021,8 @@           Error msg ->             -- We are assuming that if we can't decode the data, that this             -- request belongs to another resolve handler for this plugin.-            throwError (PluginRequestRefused (T.pack ("Unable to decode payload for handler, assuming that it's for a different handler" <> msg)))+            throwError (PluginRequestRefused+                           (NotResolveOwner (ownerName <> ": error decoding payload:" <> T.pack msg)))       -- If we are getting an owner that isn't us, this means that there is an       -- error, as we filter these our in `pluginEnabled`       else throwError $ PluginInternalError invalidRequest@@ -1011,16 +1058,7 @@ instance IsString PluginId where   fromString = PluginId . T.pack --- | Lookup the current config for a plugin-configForPlugin :: Config -> PluginDescriptor c -> PluginConfig-configForPlugin config PluginDescriptor{..}-    = Map.findWithDefault (configInitialGenericConfig pluginConfigDescriptor) pluginId (plugins config) --- | Checks that a given plugin is both enabled and the specific feature is--- enabled-pluginEnabledConfig :: (PluginConfig -> Bool) -> PluginConfig -> Bool-pluginEnabledConfig f pluginConfig = plcGlobalOn pluginConfig && f pluginConfig- -- ---------------------------------------------------------------------  -- | Format the given Text as a whole or only a @Range@ of it.@@ -1143,14 +1181,6 @@  installSigUsr1Handler h = void $ installHandler sigUSR1 (Catch h) Nothing #endif---- |Determine whether this request should be routed to the plugin. Fails closed--- if we can't determine which plugin it should be routed to.-pluginResolverResponsible :: Maybe Value -> PluginDescriptor c -> Bool-pluginResolverResponsible (Just (fromJSON -> (Success (PluginResolveData o _ _)))) pluginDesc =-  pluginId pluginDesc == o--- We want to fail closed-pluginResolverResponsible _ _ = False  {- Note [Resolve in PluginHandlers]   Resolve methods have a few guarantees that need to be made by HLS,