-
-
Notifications
You must be signed in to change notification settings - Fork 392
Merge definitions from all plugins for Document(Type)Definition message #3846
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
Changes from 10 commits
e57c19c
613fd5a
415ce13
941b8f4
b7ee494
b696f09
f1a69a5
8b1eb65
08ccbd4
6751e93
27caea4
30bfe49
d04091e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,14 +6,14 @@ | |
{-# LANGUAGE DeriveAnyClass #-} | ||
{-# LANGUAGE DeriveGeneric #-} | ||
{-# LANGUAGE DerivingStrategies #-} | ||
{-# LANGUAGE DuplicateRecordFields #-} | ||
{-# LANGUAGE FlexibleContexts #-} | ||
{-# LANGUAGE FlexibleInstances #-} | ||
{-# LANGUAGE GADTs #-} | ||
{-# LANGUAGE GeneralizedNewtypeDeriving #-} | ||
{-# LANGUAGE MonadComprehensions #-} | ||
{-# LANGUAGE MultiParamTypeClasses #-} | ||
{-# LANGUAGE NamedFieldPuns #-} | ||
{-# LANGUAGE OverloadedLabels #-} | ||
{-# LANGUAGE OverloadedStrings #-} | ||
{-# LANGUAGE PatternSynonyms #-} | ||
{-# LANGUAGE PolyKinds #-} | ||
|
@@ -76,6 +76,7 @@ import Data.Default | |
import Data.Dependent.Map (DMap) | ||
import qualified Data.Dependent.Map as DMap | ||
import qualified Data.DList as DList | ||
import Data.Foldable (foldl') | ||
import Data.GADT.Compare | ||
import Data.Hashable (Hashable) | ||
import Data.HashMap.Strict (HashMap) | ||
|
@@ -560,7 +561,7 @@ instance PluginRequestMethod Method_TextDocumentCodeAction where | |
-- should check whether the requested kind is a *prefix* of the action kind. | ||
-- That means, for example, we will return actions with kinds `quickfix.import` and | ||
-- `quickfix.somethingElse` if the requested kind is `quickfix`. | ||
, Just caKind <- ca ^. L.kind = any (\k -> k `codeActionKindSubsumes` caKind) allowed | ||
, Just caKind <- ca ^. L.kind = any (`codeActionKindSubsumes` caKind) allowed | ||
| otherwise = False | ||
|
||
instance PluginRequestMethod Method_CodeActionResolve where | ||
|
@@ -569,10 +570,14 @@ instance PluginRequestMethod Method_CodeActionResolve where | |
combineResponses _ _ _ _ (x :| _) = x | ||
|
||
instance PluginRequestMethod Method_TextDocumentDefinition where | ||
combineResponses _ _ _ _ (x :| _) = x | ||
combineResponses _ _ caps _ (x :| xs) | ||
| Just (Just True) <- caps ^? (L.textDocument . _Just . L.definition . _Just . L.linkSupport) = foldl' mergeDefinitions x xs | ||
| otherwise = downgradeLinks $ foldl' mergeDefinitions x xs | ||
|
||
instance PluginRequestMethod Method_TextDocumentTypeDefinition where | ||
combineResponses _ _ _ _ (x :| _) = x | ||
combineResponses _ _ caps _ (x :| xs) | ||
| Just (Just True) <- caps ^? (L.textDocument . _Just . L.typeDefinition . _Just . L.linkSupport) = foldl' mergeDefinitions x xs | ||
| otherwise = downgradeLinks $ foldl' mergeDefinitions x xs | ||
|
||
instance PluginRequestMethod Method_TextDocumentDocumentHighlight where | ||
|
||
|
@@ -693,6 +698,45 @@ nullToMaybe' :: (a |? (b |? Null)) -> Maybe (a |? b) | |
nullToMaybe' (InL x) = Just $ InL x | ||
nullToMaybe' (InR (InL x)) = Just $ InR x | ||
nullToMaybe' (InR (InR _)) = Nothing | ||
|
||
type Definitions = (Definition |? ([DefinitionLink] |? Null)) | ||
|
||
-- | Merges two definition responses (TextDocumentDefinition | TextDocumentTypeDefinition) | ||
-- into one preserving all locations and their order (including order of the responses). | ||
-- Upgrades Location(s) into LocationLink(s) when one of the responses is LocationLink(s). With following fields: | ||
-- * LocationLink.originSelectionRange = Nothing | ||
-- * LocationLink.targetUri = Location.Uri | ||
-- * LocationLink.targetRange = Location.Range | ||
-- * LocationLink.targetSelectionRange = Location.Range | ||
-- Ignores Null responses. | ||
mergeDefinitions :: Definitions -> Definitions -> Definitions | ||
mergeDefinitions definitions1 definitions2 = case (definitions1, definitions2) of | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's are client capabilities controlling whether location links are supported. Ideally we should check those and if they're not sent we should instead downgrade the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I created a new |
||
(InR (InR Null), def2) -> def2 | ||
(def1, InR (InR Null)) -> def1 | ||
(InL def1, InL def2) -> InL $ mergeDefs def1 def2 | ||
(InL def1, InR (InL links)) -> InR $ InL (defToLinks def1 ++ links) | ||
(InR (InL links), InL def2) -> InR $ InL (links ++ defToLinks def2) | ||
(InR (InL links1), InR (InL links2)) -> InR $ InL (links1 ++ links2) | ||
where | ||
defToLinks :: Definition -> [DefinitionLink] | ||
defToLinks (Definition (InL location)) = [locationToDefinitionLink location] | ||
defToLinks (Definition (InR locations)) = map locationToDefinitionLink locations | ||
|
||
locationToDefinitionLink :: Location -> DefinitionLink | ||
locationToDefinitionLink Location{_uri, _range} = DefinitionLink LocationLink{_originSelectionRange = Nothing, _targetUri = _uri, _targetRange = _range, _targetSelectionRange = _range} | ||
|
||
mergeDefs :: Definition -> Definition -> Definition | ||
mergeDefs (Definition (InL loc1)) (Definition (InL loc2)) = Definition $ InR [loc1, loc2] | ||
mergeDefs (Definition (InR locs1)) (Definition (InL loc2)) = Definition $ InR (locs1 ++ [loc2]) | ||
mergeDefs (Definition (InL loc1)) (Definition (InR locs2)) = Definition $ InR (loc1 : locs2) | ||
mergeDefs (Definition (InR locs1)) (Definition (InR locs2)) = Definition $ InR (locs1 ++ locs2) | ||
|
||
downgradeLinks :: Definitions -> Definitions | ||
downgradeLinks (InR (InL links)) = InL . Definition . InR . map linkToLocation $ links | ||
where | ||
linkToLocation :: DefinitionLink -> Location | ||
linkToLocation (DefinitionLink LocationLink{_targetUri, _targetRange}) = Location {_uri = _targetUri, _range = _targetRange} | ||
downgradeLinks defs = defs | ||
-- --------------------------------------------------------------------- | ||
-- Plugin Notifications | ||
-- --------------------------------------------------------------------- | ||
|
@@ -942,7 +986,7 @@ mkResolveHandler m f = mkPluginHandler m $ \ideState plId params -> do | |
-- as this is filtered out in `pluginEnabled` | ||
_ -> throwError $ PluginInternalError invalidRequest | ||
where invalidRequest = "The resolve request incorrectly got routed to the wrong resolve handler!" | ||
parseError value err = "Unable to decode: " <> (T.pack $ show value) <> ". Error: " <> (T.pack $ show err) | ||
parseError value err = "Unable to decode: " <> T.pack (show value) <> ". Error: " <> T.pack (show err) | ||
|
||
wrapResolveData :: L.HasData_ a (Maybe Value) => PluginId -> Uri -> a -> a | ||
wrapResolveData pid uri hasData = | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some haddock explaining what this does, especially what the merging rules are would be great!