Exemplo n.º 1
0
        private HandlerDescriptor GetDescriptor(string method, Type handlerType, IJsonRpcHandler handler)
        {
            var @interface       = HandlerTypeHelpers.GetHandlerInterface(handlerType);
            var registrationType = UnwrapGenericType(typeof(IRegistration <>), handlerType);
            var capabilityType   = UnwrapGenericType(typeof(ICapability <>), handlerType);

            Type   @params             = null;
            object registrationOptions = null;

            if (@interface.GetTypeInfo().IsGenericType)
            {
                @params = @interface.GetTypeInfo().GetGenericArguments()[0];
            }

            if (registrationType != null)
            {
                registrationOptions = GetRegistrationMethod
                                      .MakeGenericMethod(registrationType)
                                      .Invoke(null, new object[] { handler });
            }

            var key = "default";

            if (handler is IRegistration <TextDocumentRegistrationOptions> handlerRegistration)
            {
                // Ensure we only do this check for the specific registartion type that was found
                if (typeof(TextDocumentRegistrationOptions).GetTypeInfo().IsAssignableFrom(registrationType))
                {
                    key = handlerRegistration?.GetRegistrationOptions()?.DocumentSelector ?? key;
                }
                // In some scenarios, users will implement both the main handler and the resolve handler to the same class
                // This allows us to get a key for those interfaces so we can register many resolve handlers
                // and then route those resolve requests to the correct handler
                if (handlerType.GetTypeInfo().ImplementedInterfaces.Any(x => x.GetTypeInfo().IsGenericType&& x.GetTypeInfo().GetGenericTypeDefinition() == typeof(ICanBeResolvedHandler <>)))
                {
                    key = handlerRegistration?.GetRegistrationOptions()?.DocumentSelector ?? key;
                }
            }

            if (string.IsNullOrWhiteSpace(key))
            {
                key = "default";
            }

            var descriptor = new HandlerDescriptor(
                method,
                key,
                handler,
                @interface,
                @params,
                registrationType,
                registrationOptions,
                registrationType != null && _supportedCapabilities.AllowsDynamicRegistration(capabilityType),
                capabilityType,
                () => {
                _handlers.RemoveWhere(d => d.Handler == handler);
            });

            return(descriptor);
        }
        internal static IDisposable DynamicallyRegisterHandlers(
            IClientLanguageServer client,
            IObservable <Unit> initializeComplete,
            IServerWorkDoneManager serverWorkDoneManager,
            ISupportedCapabilities supportedCapabilities,
            IReadOnlyList <ILspHandlerDescriptor> descriptors
            )
        {
            if (descriptors.Count == 0)
            {
                return(Disposable.Empty); // No dynamic registrations supported by client.
            }
            var disposable = new CompositeDisposable();

            var result = initializeComplete
                         .LastOrDefaultAsync()
                         .Select(
                _ => {
                var registrations = new List <Registration>();
                foreach (var descriptor in descriptors)
                {
                    if (descriptor.HasCapability && supportedCapabilities.AllowsDynamicRegistration(descriptor.CapabilityType))
                    {
                        if (descriptor.RegistrationOptions is IWorkDoneProgressOptions wdpo)
                        {
                            wdpo.WorkDoneProgress = serverWorkDoneManager.IsSupported;
                        }

                        registrations.Add(
                            new Registration {
                            Id              = descriptor.Id.ToString(),
                            Method          = descriptor.Method,
                            RegisterOptions = descriptor.RegistrationOptions
                        }
                            );
                    }
                }

                return(registrations);
            }
                )
                         .SelectMany(
                registrations => Observable.FromAsync(ct => client.RegisterCapability(new RegistrationParams {
                Registrations = registrations
            }, ct)), (a, b) => a
                )
                         .Aggregate((z, b) => z)
                         .Subscribe(
                registrations => {
                disposable.Add(
                    Disposable.Create(
                        () => {
                    client.UnregisterCapability(
                        new UnregistrationParams {
                        Unregisterations = registrations
                    }
                        ).ToObservable().Subscribe();
                }
                        )
                    );
            }
                );

            disposable.Add(result);
            return(disposable);
        }