11using System . Collections . Generic ;
22using System . Linq ;
3+ using System . Reflection ;
34using Microsoft . Extensions . Logging ;
45using Newtonsoft . Json . Linq ;
56using OmniSharp . Extensions . LanguageServer . Protocol ;
@@ -11,6 +12,7 @@ namespace OmniSharp.Extensions.LanguageServer.Server.Matchers
1112 public class ResolveCommandMatcher : IHandlerMatcher , IHandlerPostProcessorMatcher , IHandlerPostProcessor
1213 {
1314 private readonly ILogger _logger ;
15+ internal static string PrivateHandlerTypeName = "$$___handlerType___$$" ;
1416
1517 public ResolveCommandMatcher ( ILogger logger )
1618 {
@@ -27,17 +29,32 @@ public IEnumerable<ILspHandlerDescriptor> FindHandler(object parameters, IEnumer
2729 {
2830 if ( parameters is ICanBeResolved canBeResolved )
2931 {
30- var handlerType = canBeResolved . Data ? . Value < string > ( "handlerType" ) ;
32+ var handlerType = canBeResolved . Data ? . Value < string > ( PrivateHandlerTypeName ) ;
3133 if ( string . IsNullOrWhiteSpace ( handlerType ) )
3234 {
33- var descriptor = descriptors . FirstOrDefault ( ) ;
35+ foreach ( var descriptor in descriptors )
36+ {
37+ if ( descriptor . CanBeResolvedHandlerType ? . GetTypeInfo ( ) . IsAssignableFrom ( descriptor . Handler . GetType ( ) ) == true )
38+ {
39+ var method = typeof ( ResolveCommandMatcher ) . GetTypeInfo ( )
40+ . GetMethod ( nameof ( CanResolve ) , BindingFlags . NonPublic | BindingFlags . Static )
41+ . MakeGenericMethod ( descriptor . Params ) ;
42+ if ( ( bool ) method . Invoke ( null , new [ ] { descriptor . Handler , parameters } ) )
43+ {
44+ yield return descriptor ;
45+ yield break ;
46+ }
47+ }
48+ }
49+
50+ var descriptor2 = descriptors . FirstOrDefault ( ) ;
3451 _logger . LogTrace (
3552 "Resolve {Method} was called, but data did not have handle type defined. Using Handler {HandlerType}" ,
36- descriptor ? . Method ,
37- descriptor ? . Handler . GetType ( ) . FullName
53+ descriptor2 ? . Method ,
54+ descriptor2 ? . Handler . GetType ( ) . FullName
3855 ) ;
3956
40- yield return descriptor ;
57+ yield return descriptor2 ;
4158 yield break ;
4259 }
4360 foreach ( var descriptor in descriptors )
@@ -54,6 +71,12 @@ public IEnumerable<ILspHandlerDescriptor> FindHandler(object parameters, IEnumer
5471 }
5572 }
5673
74+ private static bool CanResolve < T > ( ICanBeResolvedHandler < T > handler , T value )
75+ where T : ICanBeResolved
76+ {
77+ return handler . CanResolve ( value ) ;
78+ }
79+
5780 public IEnumerable < IHandlerPostProcessor > FindPostProcessor ( ILspHandlerDescriptor descriptor , object parameters , object response )
5881 {
5982 if ( descriptor . Method == DocumentNames . CodeLens || descriptor . Method == DocumentNames . Completion )
@@ -67,7 +90,9 @@ public IEnumerable<IHandlerPostProcessor> FindPostProcessor(ILspHandlerDescripto
6790
6891 public object Process ( ILspHandlerDescriptor descriptor , object parameters , object response )
6992 {
70- if ( response is IEnumerable < ICanBeResolved > canBeResolveds )
93+ // Only pin the handler type, if we know the source handler (codelens) is also the resolver.
94+ if ( response is IEnumerable < ICanBeResolved > canBeResolveds &&
95+ descriptor . CanBeResolvedHandlerType . GetTypeInfo ( ) . IsAssignableFrom ( descriptor . Handler . GetType ( ) ) )
7196 {
7297 _logger . LogTrace ( "Updating Resolve items with wrapped data for {Method}:{Handler}" ,
7398 descriptor . Method ,
@@ -77,10 +102,10 @@ public object Process(ILspHandlerDescriptor descriptor, object parameters, objec
77102 // Originally we were going to change Data to be a JObject instead of JToken
78103 // This allows us to leave data alone by simply wrapping it
79104 // Since we're always going to intercept these items, we can control this.
80- item . Data = new JObject ( new {
81- data = item . Data ,
82- handlerType = descriptor . HandlerType . FullName
83- } ) ;
105+ var data = new JObject ( ) ;
106+ data [ "data" ] = item . Data ;
107+ data [ PrivateHandlerTypeName ] = descriptor . Handler . GetType ( ) . FullName ;
108+ item . Data = data ;
84109 }
85110 }
86111 return response ;
0 commit comments