diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 0034de2f5..bfc4fb743 100755 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -11,6 +11,7 @@ + diff --git a/build-tools/jsonrpc/.gitignore b/build-tools/jsonrpc/.gitignore deleted file mode 100644 index 42afabfd2..000000000 --- a/build-tools/jsonrpc/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/build-tools/jsonrpc/build.gradle b/build-tools/jsonrpc/build.gradle deleted file mode 100644 index 39cea4efd..000000000 --- a/build-tools/jsonrpc/build.gradle +++ /dev/null @@ -1,31 +0,0 @@ -/* - * This file is part of AndroidIDE. - * - * AndroidIDE is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * AndroidIDE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with AndroidIDE. If not, see . - */ - -plugins { - id 'java-library' -} - -java { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 -} - -dependencies { - implementation google.gson - implementation project (path: ':build-tools:logger') - implementation project (path: ':build-tools:tooling-api-model') -} \ No newline at end of file diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/CancelChecker.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/CancelChecker.java deleted file mode 100644 index 330276b9b..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/CancelChecker.java +++ /dev/null @@ -1,39 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc; - -import java.util.concurrent.CancellationException; - -/** - * Used for processing requests with cancellation support. - */ -public interface CancelChecker { - - /** - * Throw a {@link CancellationException} if the currently processed request - * has been canceled. - */ - void checkCanceled(); - - /** - * Check for cancellation without throwing an exception. - */ - default boolean isCanceled() { - try { - checkCanceled(); - } catch (CancellationException ce) { - return true; - } - return false; - } - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/CompletableFutures.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/CompletableFutures.java deleted file mode 100644 index 44682f9d8..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/CompletableFutures.java +++ /dev/null @@ -1,69 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc; - -import java.util.concurrent.CancellationException; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Executor; -import java.util.function.Function; - -public final class CompletableFutures { - private CompletableFutures() {} - - /** - * A utility method to create a {@link CompletableFuture} with cancellation support. - * - * @param code a function that accepts a {@link CancelChecker} and returns the to be computed value - * @return a future - */ - public static CompletableFuture computeAsync(Function code) { - CompletableFuture start = new CompletableFuture<>(); - CompletableFuture result = start.thenApplyAsync(code); - start.complete(new FutureCancelChecker(result)); - return result; - } - - /** - * A utility method to create a {@link CompletableFuture} with cancellation support. - * - * @param code a function that accepts a {@link CancelChecker} and returns the to be computed value - * @return a future - */ - public static CompletableFuture computeAsync(Executor executor, Function code) { - CompletableFuture start = new CompletableFuture<>(); - CompletableFuture result = start.thenApplyAsync(code, executor); - start.complete(new FutureCancelChecker(result)); - return result; - } - - public static class FutureCancelChecker implements CancelChecker { - - private final CompletableFuture future; - - public FutureCancelChecker(CompletableFuture future) { - this.future = future; - } - - @Override - public void checkCanceled() { - if (future.isCancelled()) - throw new CancellationException(); - } - - @Override - public boolean isCanceled() { - return future.isCancelled(); - } - - } - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/Endpoint.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/Endpoint.java deleted file mode 100644 index 82cac6c7d..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/Endpoint.java +++ /dev/null @@ -1,25 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc; - -import java.util.concurrent.CompletableFuture; - -/** - * An endpoint is a generic interface that accepts jsonrpc requests and notifications. - */ -public interface Endpoint { - - CompletableFuture request(String method, Object parameter); - - void notify(String method, Object parameter); - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/JsonRpcException.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/JsonRpcException.java deleted file mode 100644 index 7cbc786aa..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/JsonRpcException.java +++ /dev/null @@ -1,44 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2018 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc; - -import java.io.IOException; -import java.io.InterruptedIOException; -import java.net.SocketException; -import java.nio.channels.ClosedChannelException; - -/** - * An exception thrown when accessing the JSON-RPC communication channel fails. - */ -public class JsonRpcException extends RuntimeException { - - /** - * Whether the given exception indicates that the currently accessed stream has been closed. - */ - public static boolean indicatesStreamClosed(Throwable thr) { - return thr instanceof InterruptedIOException - || thr instanceof ClosedChannelException - || thr instanceof IOException && "Pipe closed".equals(thr.getMessage()) - || thr instanceof SocketException && - ("Connection reset".equals(thr.getMessage()) || - "Socket closed".equals(thr.getMessage()) || - "Broken pipe (Write failed)".equals(thr.getMessage())) - || thr instanceof JsonRpcException && indicatesStreamClosed(thr.getCause()); - } - - private static final long serialVersionUID = -7952794305289314670L; - - public JsonRpcException(Throwable cause) { - super(cause); - } - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/Launcher.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/Launcher.java deleted file mode 100644 index b543a739e..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/Launcher.java +++ /dev/null @@ -1,442 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016-2018 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc; - -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PrintWriter; -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.function.Consumer; -import java.util.function.Function; - -import org.eclipse.lsp4j.jsonrpc.json.ConcurrentMessageProcessor; -import org.eclipse.lsp4j.jsonrpc.json.JsonRpcMethod; -import org.eclipse.lsp4j.jsonrpc.json.JsonRpcMethodProvider; -import org.eclipse.lsp4j.jsonrpc.json.MessageJsonHandler; -import org.eclipse.lsp4j.jsonrpc.json.StreamMessageConsumer; -import org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer; -import org.eclipse.lsp4j.jsonrpc.messages.ResponseError; -import org.eclipse.lsp4j.jsonrpc.services.ServiceEndpoints; -import org.eclipse.lsp4j.jsonrpc.validation.ReflectiveMessageValidator; - -import com.google.gson.GsonBuilder; - -/** - * This is the entry point for applications that use LSP4J. A Launcher does all the wiring that is necessary to connect - * your endpoint via an input stream and an output stream. - * - * @param remote service interface type - */ -public interface Launcher { - - /** - * Create a new Launcher for a given local service object, a given remote interface and an input and output stream. - * - * @param localService - the object that receives method calls from the remote service - * @param remoteInterface - an interface on which RPC methods are looked up - * @param in - input stream to listen for incoming messages - * @param out - output stream to send outgoing messages - */ - static Launcher createLauncher(Object localService, Class remoteInterface, InputStream in, OutputStream out) { - return new Builder() - .setLocalService(localService) - .setRemoteInterface(remoteInterface) - .setInput(in) - .setOutput(out) - .create(); - } - - /** - * Create a new Launcher for a given local service object, a given remote interface and an input and output stream, - * and set up message validation and tracing. - * - * @param localService - the object that receives method calls from the remote service - * @param remoteInterface - an interface on which RPC methods are looked up - * @param in - input stream to listen for incoming messages - * @param out - output stream to send outgoing messages - * @param validate - whether messages should be validated with the {@link ReflectiveMessageValidator} - * @param trace - a writer to which incoming and outgoing messages are traced, or {@code null} to disable tracing - */ - static Launcher createLauncher(Object localService, Class remoteInterface, InputStream in, OutputStream out, - boolean validate, PrintWriter trace) { - return new Builder() - .setLocalService(localService) - .setRemoteInterface(remoteInterface) - .setInput(in) - .setOutput(out) - .validateMessages(validate) - .traceMessages(trace) - .create(); - } - - /** - * Create a new Launcher for a given local service object, a given remote interface and an input and output stream. - * Threads are started with the given executor service. The wrapper function is applied to the incoming and - * outgoing message streams so additional message handling such as validation and tracing can be included. - * - * @param localService - the object that receives method calls from the remote service - * @param remoteInterface - an interface on which RPC methods are looked up - * @param in - input stream to listen for incoming messages - * @param out - output stream to send outgoing messages - * @param executorService - the executor service used to start threads - * @param wrapper - a function for plugging in additional message consumers - */ - static Launcher createLauncher(Object localService, Class remoteInterface, InputStream in, OutputStream out, - ExecutorService executorService, Function wrapper) { - return createIoLauncher(localService, remoteInterface, in, out, executorService, wrapper); - } - - /** - * Create a new Launcher for a given local service object, a given remote interface and an input and output stream. - * Threads are started with the given executor service. The wrapper function is applied to the incoming and - * outgoing message streams so additional message handling such as validation and tracing can be included. - * - * @param localService - the object that receives method calls from the remote service - * @param remoteInterface - an interface on which RPC methods are looked up - * @param in - input stream to listen for incoming messages - * @param out - output stream to send outgoing messages - * @param executorService - the executor service used to start threads - * @param wrapper - a function for plugging in additional message consumers - */ - static Launcher createIoLauncher(Object localService, Class remoteInterface, InputStream in, OutputStream out, - ExecutorService executorService, Function wrapper) { - return new Builder() - .setLocalService(localService) - .setRemoteInterface(remoteInterface) - .setInput(in) - .setOutput(out) - .setExecutorService(executorService) - .wrapMessages(wrapper) - .create(); - } - - /** - * Create a new Launcher for a given local service object, a given remote interface and an input and output stream. - * Threads are started with the given executor service. The wrapper function is applied to the incoming and - * outgoing message streams so additional message handling such as validation and tracing can be included. - * The {@code configureGson} function can be used to register additional type adapters in the {@link GsonBuilder} - * in order to support protocol classes that cannot be handled by Gson's reflective capabilities. - * - * @param localService - the object that receives method calls from the remote service - * @param remoteInterface - an interface on which RPC methods are looked up - * @param in - input stream to listen for incoming messages - * @param out - output stream to send outgoing messages - * @param executorService - the executor service used to start threads - * @param wrapper - a function for plugging in additional message consumers - * @param configureGson - a function for Gson configuration - */ - static Launcher createIoLauncher(Object localService, Class remoteInterface, InputStream in, OutputStream out, - ExecutorService executorService, Function wrapper, Consumer configureGson) { - return new Builder() - .setLocalService(localService) - .setRemoteInterface(remoteInterface) - .setInput(in) - .setOutput(out) - .setExecutorService(executorService) - .wrapMessages(wrapper) - .configureGson(configureGson) - .create(); - } - - /** - * Create a new Launcher for a given local service object, a given remote interface and an input and output stream. - * Threads are started with the given executor service. The wrapper function is applied to the incoming and - * outgoing message streams so additional message handling such as validation and tracing can be included. - * The {@code configureGson} function can be used to register additional type adapters in the {@link GsonBuilder} - * in order to support protocol classes that cannot be handled by Gson's reflective capabilities. - * - * @param localService - the object that receives method calls from the remote service - * @param remoteInterface - an interface on which RPC methods are looked up - * @param in - input stream to listen for incoming messages - * @param out - output stream to send outgoing messages - * @param validate - whether messages should be validated with the {@link ReflectiveMessageValidator} - * @param executorService - the executor service used to start threads - * @param wrapper - a function for plugging in additional message consumers - * @param configureGson - a function for Gson configuration - */ - static Launcher createIoLauncher(Object localService, Class remoteInterface, InputStream in, OutputStream out, boolean validate, - ExecutorService executorService, Function wrapper, Consumer configureGson) { - return new Builder() - .setLocalService(localService) - .setRemoteInterface(remoteInterface) - .setInput(in) - .setOutput(out) - .validateMessages(validate) - .setExecutorService(executorService) - .wrapMessages(wrapper) - .configureGson(configureGson) - .create(); - } - - /** - * Create a new Launcher for a collection of local service objects, a collection of remote interfaces and an - * input and output stream. Threads are started with the given executor service. The wrapper function is applied - * to the incoming and outgoing message streams so additional message handling such as validation and tracing - * can be included. The {@code configureGson} function can be used to register additional type adapters in - * the {@link GsonBuilder} in order to support protocol classes that cannot be handled by Gson's reflective - * capabilities. - * - * @param localServices - the objects that receive method calls from the remote services - * @param remoteInterfaces - interfaces on which RPC methods are looked up - * @param classLoader - a class loader that is able to resolve all given interfaces - * @param in - input stream to listen for incoming messages - * @param out - output stream to send outgoing messages - * @param executorService - the executor service used to start threads - * @param wrapper - a function for plugging in additional message consumers - * @param configureGson - a function for Gson configuration - */ - static Launcher createIoLauncher(Collection localServices, Collection> remoteInterfaces, ClassLoader classLoader, - InputStream in, OutputStream out, ExecutorService executorService, Function wrapper, - Consumer configureGson) { - return new Builder() - .setLocalServices(localServices) - .setRemoteInterfaces(remoteInterfaces) - .setClassLoader(classLoader) - .setInput(in) - .setOutput(out) - .setExecutorService(executorService) - .wrapMessages(wrapper) - .configureGson(configureGson) - .create(); - } - - - //------------------------------ Builder Class ------------------------------// - - /** - * The launcher builder wires up all components for JSON-RPC communication. - * - * @param remote service interface type - */ - public static class Builder { - - protected Collection localServices; - protected Collection> remoteInterfaces; - protected InputStream input; - protected OutputStream output; - protected ExecutorService executorService; - protected Function messageWrapper; - protected Function exceptionHandler; - protected boolean validateMessages; - protected Consumer configureGson; - protected ClassLoader classLoader; - protected MessageTracer messageTracer; - - public Builder setLocalService(Object localService) { - this.localServices = Collections.singletonList(localService); - return this; - } - - public Builder setLocalServices(Collection localServices) { - this.localServices = localServices; - return this; - } - - public Builder setRemoteInterface(Class remoteInterface) { - this.remoteInterfaces = Collections.singletonList(remoteInterface); - return this; - } - - public Builder setRemoteInterfaces(Collection> remoteInterfaces) { - this.remoteInterfaces = remoteInterfaces; - return this; - } - - public Builder setInput(InputStream input) { - this.input = input; - return this; - } - - public Builder setOutput(OutputStream output) { - this.output = output; - return this; - } - - public Builder setExecutorService(ExecutorService executorService) { - this.executorService = executorService; - return this; - } - - public Builder setClassLoader(ClassLoader classLoader) { - this.classLoader = classLoader; - return this; - } - - public Builder wrapMessages(Function wrapper) { - this.messageWrapper = wrapper; - return this; - } - - public Builder setExceptionHandler(Function exceptionHandler) { - this.exceptionHandler = exceptionHandler; - return this; - } - - public Builder validateMessages(boolean validate) { - this.validateMessages = validate; - return this; - } - - public Builder traceMessages(PrintWriter tracer) { - if (tracer != null) { - this.messageTracer = new MessageTracer(tracer); - } - return this; - } - - public Builder configureGson(Consumer configureGson) { - this.configureGson = configureGson; - return this; - } - - public Launcher create() { - // Validate input - if (input == null) - throw new IllegalStateException("Input stream must be configured."); - if (output == null) - throw new IllegalStateException("Output stream must be configured."); - if (localServices == null) - throw new IllegalStateException("Local service must be configured."); - if (remoteInterfaces == null) - throw new IllegalStateException("Remote interface must be configured."); - - // Create the JSON handler, remote endpoint and remote proxy - MessageJsonHandler jsonHandler = createJsonHandler(); - RemoteEndpoint remoteEndpoint = createRemoteEndpoint(jsonHandler); - T remoteProxy = createProxy(remoteEndpoint); - - // Create the message processor - StreamMessageProducer reader = new StreamMessageProducer(input, jsonHandler, remoteEndpoint); - MessageConsumer messageConsumer = wrapMessageConsumer(remoteEndpoint); - ConcurrentMessageProcessor msgProcessor = createMessageProcessor(reader, messageConsumer, remoteProxy); - ExecutorService execService = executorService != null ? executorService : Executors.newCachedThreadPool(); - return createLauncher(execService, remoteProxy, remoteEndpoint, msgProcessor); - } - - /** - * Create the JSON handler for messages between the local and remote services. - */ - protected MessageJsonHandler createJsonHandler() { - Map supportedMethods = getSupportedMethods(); - if (configureGson != null) - return new MessageJsonHandler(supportedMethods, configureGson); - else - return new MessageJsonHandler(supportedMethods); - } - - /** - * Create the remote endpoint that communicates with the local services. - */ - protected RemoteEndpoint createRemoteEndpoint(MessageJsonHandler jsonHandler) { - MessageConsumer outgoingMessageStream = new StreamMessageConsumer(output, jsonHandler); - outgoingMessageStream = wrapMessageConsumer(outgoingMessageStream); - Endpoint localEndpoint = ServiceEndpoints.toEndpoint(localServices); - RemoteEndpoint remoteEndpoint; - if (exceptionHandler == null) - remoteEndpoint = new RemoteEndpoint(outgoingMessageStream, localEndpoint); - else - remoteEndpoint = new RemoteEndpoint(outgoingMessageStream, localEndpoint, exceptionHandler); - jsonHandler.setMethodProvider(remoteEndpoint); - return remoteEndpoint; - } - - /** - * Create the proxy for calling methods on the remote service. - */ - @SuppressWarnings("unchecked") - protected T createProxy(RemoteEndpoint remoteEndpoint) { - if (localServices.size() == 1 && remoteInterfaces.size() == 1) { - return ServiceEndpoints.toServiceObject(remoteEndpoint, remoteInterfaces.iterator().next()); - } else { - return (T) ServiceEndpoints.toServiceObject(remoteEndpoint, (Collection>) (Object) remoteInterfaces, classLoader); - } - } - - /** - * Create the message processor that listens to the input stream. - */ - protected ConcurrentMessageProcessor createMessageProcessor(MessageProducer reader, - MessageConsumer messageConsumer, T remoteProxy) { - return new ConcurrentMessageProcessor(reader, messageConsumer); - } - - protected Launcher createLauncher(ExecutorService execService, T remoteProxy, RemoteEndpoint remoteEndpoint, - ConcurrentMessageProcessor msgProcessor) { - return new StandardLauncher(execService, remoteProxy, remoteEndpoint, msgProcessor); - } - - protected MessageConsumer wrapMessageConsumer(MessageConsumer consumer) { - MessageConsumer result = consumer; - if (messageTracer != null) { - result = messageTracer.apply(consumer); - } - if (validateMessages) { - result = new ReflectiveMessageValidator(result); - } - if (messageWrapper != null) { - result = messageWrapper.apply(result); - } - return result; - } - - /** - * Gather all JSON-RPC methods from the local and remote services. - */ - protected Map getSupportedMethods() { - Map supportedMethods = new LinkedHashMap<>(); - // Gather the supported methods of remote interfaces - for (Class interface_ : remoteInterfaces) { - supportedMethods.putAll(ServiceEndpoints.getSupportedMethods(interface_)); - } - - // Gather the supported methods of local services - for (Object localService : localServices) { - if (localService instanceof JsonRpcMethodProvider) { - JsonRpcMethodProvider rpcMethodProvider = (JsonRpcMethodProvider) localService; - supportedMethods.putAll(rpcMethodProvider.supportedMethods()); - } else { - supportedMethods.putAll(ServiceEndpoints.getSupportedMethods(localService.getClass())); - } - } - - return supportedMethods; - } - } - - - //---------------------------- Interface Methods ----------------------------// - - /** - * Start a thread that listens to the input stream. The thread terminates when the stream is closed. - * - * @return a future that returns {@code null} when the listener thread is terminated - */ - Future startListening(); - - /** - * Returns the proxy instance that implements the remote service interfaces. - */ - T getRemoteProxy(); - - /** - * Returns the remote endpoint. Use this one to send generic {@code request} or {@code notify} methods - * to the remote services. - */ - RemoteEndpoint getRemoteEndpoint(); - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/MessageConsumer.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/MessageConsumer.java deleted file mode 100644 index eb494658b..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/MessageConsumer.java +++ /dev/null @@ -1,26 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc; - -import org.eclipse.lsp4j.jsonrpc.messages.Message; - -public interface MessageConsumer { - - /** - * Consume a single message. - * - * @throws MessageIssueException when an issue is found that prevents further processing of the message - * @throws JsonRpcException when accessing the JSON-RPC communication channel fails - */ - void consume(Message message) throws MessageIssueException, JsonRpcException; - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/MessageIssueException.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/MessageIssueException.java deleted file mode 100644 index 58dec38a4..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/MessageIssueException.java +++ /dev/null @@ -1,64 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2018 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.eclipse.lsp4j.jsonrpc.messages.Message; -import org.eclipse.lsp4j.jsonrpc.messages.MessageIssue; - -/** - * An exception thrown to notify the caller of a {@link MessageConsumer} that one or more issues were - * found while parsing or validating a message. This information can be passed to a {@link MessageIssueHandler} - * in order to construct a proper response. - */ -public class MessageIssueException extends RuntimeException { - - private static final long serialVersionUID = 1118210473728652711L; - - private final Message rpcMessage; - private final List issues; - - public MessageIssueException(Message rpcMessage, MessageIssue issue) { - this.rpcMessage = rpcMessage; - this.issues = Collections.singletonList(issue); - } - - public MessageIssueException(Message rpcMessage, Collection issues) { - this.rpcMessage = rpcMessage; - this.issues = Collections.unmodifiableList(new ArrayList<>(issues)); - } - - public MessageIssueException(Message rpcMessage, Stream issueStream) { - this.rpcMessage = rpcMessage; - this.issues = Collections.unmodifiableList(issueStream.collect(Collectors.toList())); - } - - @Override - public String getMessage() { - return issues.stream().map(issue -> issue.getText()).collect(Collectors.joining("\n")); - } - - public Message getRpcMessage() { - return rpcMessage; - } - - public List getIssues() { - return issues; - } - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/MessageIssueHandler.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/MessageIssueHandler.java deleted file mode 100644 index 768465b65..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/MessageIssueHandler.java +++ /dev/null @@ -1,26 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2018 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc; - -import java.util.List; - -import org.eclipse.lsp4j.jsonrpc.messages.Message; -import org.eclipse.lsp4j.jsonrpc.messages.MessageIssue; - -public interface MessageIssueHandler { - - /** - * Handle issues found while parsing or validating a message. The list of issues must not be empty. - */ - void handle(Message message, List issues); - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/MessageProducer.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/MessageProducer.java deleted file mode 100644 index 30b2e5146..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/MessageProducer.java +++ /dev/null @@ -1,24 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc; - -public interface MessageProducer { - - /** - * Listen to a message source and forward all messages to the given consumer. Typically this method - * blocks until the message source is unable to deliver more messages. - * - * @throws JsonRpcException when accessing the JSON-RPC communication channel fails - */ - void listen(MessageConsumer messageConsumer) throws JsonRpcException; - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/MessageTracer.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/MessageTracer.java deleted file mode 100644 index 8398f6f19..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/MessageTracer.java +++ /dev/null @@ -1,41 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016-2019 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc; - -import org.eclipse.lsp4j.jsonrpc.TracingMessageConsumer.RequestMetadata; - -import java.io.PrintWriter; -import java.time.Clock; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.function.Function; - -/** - * Wraps a {@link MessageConsumer} with one that logs in a way that the LSP Inspector can parse. * - * https://microsoft.github.io/language-server-protocol/inspector/ - */ -public class MessageTracer implements Function { - private final PrintWriter printWriter; - private final Map sentRequests = new HashMap<>(); - private final Map receivedRequests = new HashMap<>(); - - MessageTracer(PrintWriter printWriter) { - this.printWriter = Objects.requireNonNull(printWriter); - } - - @Override - public MessageConsumer apply(MessageConsumer messageConsumer) { - return new TracingMessageConsumer( - messageConsumer, sentRequests, receivedRequests, printWriter, Clock.systemDefaultZone()); - } -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/RemoteEndpoint.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/RemoteEndpoint.java deleted file mode 100644 index 0907da8e3..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/RemoteEndpoint.java +++ /dev/null @@ -1,399 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc; - -import java.io.ByteArrayOutputStream; -import java.io.PrintWriter; -import java.lang.reflect.InvocationTargetException; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CancellationException; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Function; -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.eclipse.lsp4j.jsonrpc.json.MessageConstants; -import org.eclipse.lsp4j.jsonrpc.json.MessageJsonHandler; -import org.eclipse.lsp4j.jsonrpc.json.MethodProvider; -import org.eclipse.lsp4j.jsonrpc.messages.CancelParams; -import org.eclipse.lsp4j.jsonrpc.messages.Either; -import org.eclipse.lsp4j.jsonrpc.messages.Message; -import org.eclipse.lsp4j.jsonrpc.messages.MessageIssue; -import org.eclipse.lsp4j.jsonrpc.messages.NotificationMessage; -import org.eclipse.lsp4j.jsonrpc.messages.RequestMessage; -import org.eclipse.lsp4j.jsonrpc.messages.ResponseError; -import org.eclipse.lsp4j.jsonrpc.messages.ResponseErrorCode; -import org.eclipse.lsp4j.jsonrpc.messages.ResponseMessage; - -/** - * An endpoint that can be used to send messages to a given {@link MessageConsumer} by calling - * {@link #request(String, Object)} or {@link #notify(String, Object)}. When connected to a {@link MessageProducer}, - * this class forwards received messages to the local {@link Endpoint} given in the constructor. - */ -public class RemoteEndpoint implements Endpoint, MessageConsumer, MessageIssueHandler, MethodProvider { - - private static final Logger LOG = Logger.getLogger(RemoteEndpoint.class.getName()); - - public static final Function DEFAULT_EXCEPTION_HANDLER = (throwable) -> { - if (throwable instanceof ResponseErrorException) { - return ((ResponseErrorException) throwable).getResponseError(); - } else if ((throwable instanceof CompletionException || throwable instanceof InvocationTargetException) - && throwable.getCause() instanceof ResponseErrorException) { - return ((ResponseErrorException) throwable.getCause()).getResponseError(); - } else { - return fallbackResponseError("Internal error", throwable); - } - }; - - private static ResponseError fallbackResponseError(String header, Throwable throwable) { - LOG.log(Level.SEVERE, header + ": " + throwable.getMessage(), throwable); - ResponseError error = new ResponseError(); - error.setMessage(header + "."); - error.setCode(ResponseErrorCode.InternalError); - ByteArrayOutputStream stackTrace = new ByteArrayOutputStream(); - PrintWriter stackTraceWriter = new PrintWriter(stackTrace); - throwable.printStackTrace(stackTraceWriter); - stackTraceWriter.flush(); - error.setData(stackTrace.toString()); - return error; - } - - private final MessageConsumer out; - private final Endpoint localEndpoint; - private final Function exceptionHandler; - - private final AtomicInteger nextRequestId = new AtomicInteger(); - private final Map sentRequestMap = new LinkedHashMap<>(); - private final Map> receivedRequestMap = new LinkedHashMap<>(); - - /** - * Information about requests that have been sent and for which no response has been received yet. - */ - private static class PendingRequestInfo { - PendingRequestInfo(RequestMessage requestMessage2, CompletableFuture future2) { - this.requestMessage = requestMessage2; - this.future = future2; - } - RequestMessage requestMessage; - CompletableFuture future; - } - - /** - * @param out - a consumer that transmits messages to the remote service - * @param localEndpoint - the local service implementation - * @param exceptionHandler - an exception handler that should never return null. - */ - public RemoteEndpoint(MessageConsumer out, Endpoint localEndpoint, Function exceptionHandler) { - if (out == null) - throw new NullPointerException("out"); - if (localEndpoint == null) - throw new NullPointerException("localEndpoint"); - if (exceptionHandler == null) - throw new NullPointerException("exceptionHandler"); - this.out = out; - this.localEndpoint = localEndpoint; - this.exceptionHandler = exceptionHandler; - } - - /** - * @param out - a consumer that transmits messages to the remote service - * @param localEndpoint - the local service implementation - */ - public RemoteEndpoint(MessageConsumer out, Endpoint localEndpoint) { - this(out, localEndpoint, DEFAULT_EXCEPTION_HANDLER); - } - - /** - * Send a notification to the remote endpoint. - */ - @Override - public void notify(String method, Object parameter) { - NotificationMessage notificationMessage = createNotificationMessage(method, parameter); - try { - out.consume(notificationMessage); - } catch (Exception exception) { - Level logLevel = JsonRpcException.indicatesStreamClosed(exception) ? Level.INFO : Level.WARNING; - LOG.log(logLevel, "Failed to send notification message.", exception); - } - } - - protected NotificationMessage createNotificationMessage(String method, Object parameter) { - NotificationMessage notificationMessage = new NotificationMessage(); - notificationMessage.setJsonrpc(MessageConstants.JSONRPC_VERSION); - notificationMessage.setMethod(method); - notificationMessage.setParams(parameter); - return notificationMessage; - } - - /** - * Send a request to the remote endpoint. - */ - @Override - public CompletableFuture request(String method, Object parameter) { - final RequestMessage requestMessage = createRequestMessage(method, parameter); - final CompletableFuture result = new CompletableFuture() { - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - sendCancelNotification(requestMessage.getRawId()); - return super.cancel(mayInterruptIfRunning); - } - }; - synchronized(sentRequestMap) { - // Store request information so it can be handled when the response is received - sentRequestMap.put(requestMessage.getId(), new PendingRequestInfo(requestMessage, result)); - } - - try { - // Send the request to the remote service - out.consume(requestMessage); - } catch (Exception exception) { - // The message could not be sent, e.g. because the communication channel was closed - result.completeExceptionally(exception); - } - return result; - } - - protected RequestMessage createRequestMessage(String method, Object parameter) { - RequestMessage requestMessage = new RequestMessage(); - requestMessage.setId(String.valueOf(nextRequestId.incrementAndGet())); - requestMessage.setMethod(method); - requestMessage.setParams(parameter); - return requestMessage; - } - - protected void sendCancelNotification(Either id) { - CancelParams cancelParams = new CancelParams(); - cancelParams.setRawId(id); - notify(MessageJsonHandler.CANCEL_METHOD.getMethodName(), cancelParams); - } - - @Override - public void consume(Message message) { - if (message instanceof NotificationMessage) { - NotificationMessage notificationMessage = (NotificationMessage) message; - handleNotification(notificationMessage); - } else if (message instanceof RequestMessage) { - RequestMessage requestMessage = (RequestMessage) message; - handleRequest(requestMessage); - } else if (message instanceof ResponseMessage) { - ResponseMessage responseMessage = (ResponseMessage) message; - handleResponse(responseMessage); - } else { - LOG.log(Level.WARNING, "Unkown message type.", message); - } - } - - protected void handleResponse(ResponseMessage responseMessage) { - PendingRequestInfo requestInfo; - synchronized (sentRequestMap) { - requestInfo = sentRequestMap.remove(responseMessage.getId()); - } - if (requestInfo == null) { - // We have no pending request information that matches the id given in the response - LOG.log(Level.WARNING, "Unmatched response message: " + responseMessage); - } else if (responseMessage.getError() != null) { - // The remote service has replied with an error - requestInfo.future.completeExceptionally(new ResponseErrorException(responseMessage.getError())); - } else { - // The remote service has replied with a result object - requestInfo.future.complete(responseMessage.getResult()); - } - } - - protected void handleNotification(NotificationMessage notificationMessage) { - if (!handleCancellation(notificationMessage)) { - // Forward the notification to the local endpoint - try { - localEndpoint.notify(notificationMessage.getMethod(), notificationMessage.getParams()); - } catch (Exception exception) { - LOG.log(Level.WARNING, "Notification threw an exception: " + notificationMessage, exception); - } - } - } - - /** - * Cancellation is handled inside this class and not forwarded to the local endpoint. - * - * @return {@code true} if the given message is a cancellation notification, - * {@code false} if it can be handled by the local endpoint - */ - protected boolean handleCancellation(NotificationMessage notificationMessage) { - if (MessageJsonHandler.CANCEL_METHOD.getMethodName().equals(notificationMessage.getMethod())) { - Object cancelParams = notificationMessage.getParams(); - if (cancelParams != null) { - if (cancelParams instanceof CancelParams) { - synchronized (receivedRequestMap) { - String id = ((CancelParams) cancelParams).getId(); - CompletableFuture future = receivedRequestMap.get(id); - if (future != null) - future.cancel(true); - else - LOG.warning("Unmatched cancel notification for request id " + id); - } - return true; - } else { - LOG.warning("Cancellation support is disabled, since the '" + MessageJsonHandler.CANCEL_METHOD.getMethodName() + "' method has been registered explicitly."); - } - } else { - LOG.warning("Missing 'params' attribute of cancel notification."); - } - } - return false; - } - - protected void handleRequest(RequestMessage requestMessage) { - CompletableFuture future; - try { - // Forward the request to the local endpoint - future = localEndpoint.request(requestMessage.getMethod(), requestMessage.getParams()); - } catch (Throwable throwable) { - // The local endpoint has failed handling the request - reply with an error response - ResponseError errorObject = exceptionHandler.apply(throwable); - if (errorObject == null) { - errorObject = fallbackResponseError("Internal error. Exception handler provided no error object", throwable); - } - out.consume(createErrorResponseMessage(requestMessage, errorObject)); - if (throwable instanceof Error) - throw (Error) throwable; - else - return; - } - - final String messageId = requestMessage.getId(); - synchronized (receivedRequestMap) { - receivedRequestMap.put(messageId, future); - } - future.thenAccept((result) -> { - // Reply with the result object that was computed by the local endpoint - out.consume(createResultResponseMessage(requestMessage, result)); - }).exceptionally((Throwable t) -> { - // The local endpoint has failed computing a result - reply with an error response - ResponseMessage responseMessage; - if (isCancellation(t)) { - String message = "The request (id: " + messageId + ", method: '" + requestMessage.getMethod() + "') has been cancelled"; - ResponseError errorObject = new ResponseError(ResponseErrorCode.RequestCancelled, message, null); - responseMessage = createErrorResponseMessage(requestMessage, errorObject); - } else { - ResponseError errorObject = exceptionHandler.apply(t); - if (errorObject == null) { - errorObject = fallbackResponseError("Internal error. Exception handler provided no error object", t); - } - responseMessage = createErrorResponseMessage(requestMessage, errorObject); - } - out.consume(responseMessage); - return null; - }).thenApply((obj) -> { - synchronized (receivedRequestMap) { - receivedRequestMap.remove(messageId); - } - return null; - }); - } - - @Override - public void handle(Message message, List issues) { - if (issues.isEmpty()) { - throw new IllegalArgumentException("The list of issues must not be empty."); - } - - if (message instanceof RequestMessage) { - RequestMessage requestMessage = (RequestMessage) message; - handleRequestIssues(requestMessage, issues); - } else if (message instanceof ResponseMessage) { - ResponseMessage responseMessage = (ResponseMessage) message; - handleResponseIssues(responseMessage, issues); - } else { - logIssues(message, issues); - } - } - - protected void logIssues(Message message, List issues) { - for (MessageIssue issue : issues) { - String logMessage = "Issue found in " + message.getClass().getSimpleName() + ": " + issue.getText(); - LOG.log(Level.WARNING, logMessage, issue.getCause()); - } - } - - protected void handleRequestIssues(RequestMessage requestMessage, List issues) { - ResponseError errorObject = new ResponseError(); - if (issues.size() == 1) { - MessageIssue issue = issues.get(0); - errorObject.setMessage(issue.getText()); - errorObject.setCode(issue.getIssueCode()); - errorObject.setData(issue.getCause()); - } else { - if (requestMessage.getMethod() != null) - errorObject.setMessage("Multiple issues were found in '" + requestMessage.getMethod() + "' request."); - else - errorObject.setMessage("Multiple issues were found in request."); - errorObject.setCode(ResponseErrorCode.InvalidRequest); - errorObject.setData(issues); - } - out.consume(createErrorResponseMessage(requestMessage, errorObject)); - } - - protected void handleResponseIssues(ResponseMessage responseMessage, List issues) { - PendingRequestInfo requestInfo; - synchronized (sentRequestMap) { - requestInfo = sentRequestMap.remove(responseMessage.getId()); - } - if (requestInfo == null) { - // We have no pending request information that matches the id given in the response - LOG.log(Level.WARNING, "Unmatched response message: " + responseMessage); - logIssues(responseMessage, issues); - } else { - requestInfo.future.completeExceptionally(new MessageIssueException(responseMessage, issues)); - } - } - - protected ResponseMessage createResponseMessage(RequestMessage requestMessage) { - ResponseMessage responseMessage = new ResponseMessage(); - responseMessage.setRawId(requestMessage.getRawId()); - responseMessage.setJsonrpc(MessageConstants.JSONRPC_VERSION); - return responseMessage; - } - - protected ResponseMessage createResultResponseMessage(RequestMessage requestMessage, Object result) { - ResponseMessage responseMessage = createResponseMessage(requestMessage); - responseMessage.setResult(result); - return responseMessage; - } - - protected ResponseMessage createErrorResponseMessage(RequestMessage requestMessage, ResponseError errorObject) { - ResponseMessage responseMessage = createResponseMessage(requestMessage); - responseMessage.setError(errorObject); - return responseMessage; - } - - protected boolean isCancellation(Throwable t) { - if (t instanceof CompletionException) { - return isCancellation(t.getCause()); - } - return (t instanceof CancellationException); - } - - @Override - public String resolveMethod(String requestId) { - synchronized (sentRequestMap) { - PendingRequestInfo requestInfo = sentRequestMap.get(requestId); - if (requestInfo != null) { - return requestInfo.requestMessage.getMethod(); - } - } - return null; - } - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/ResponseErrorException.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/ResponseErrorException.java deleted file mode 100644 index d700591f2..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/ResponseErrorException.java +++ /dev/null @@ -1,36 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc; - -import org.eclipse.lsp4j.jsonrpc.messages.ResponseError; - -/** - * An exception thrown in order to send a response with an attached {@code error} object. - */ -public class ResponseErrorException extends RuntimeException { - - private static final long serialVersionUID = -5970739895395246885L; - private ResponseError responseError; - - public ResponseErrorException(ResponseError responseError) { - this.responseError = responseError; - } - - @Override - public String getMessage() { - return responseError.getMessage(); - } - - public ResponseError getResponseError() { - return responseError; - } -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/StandardLauncher.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/StandardLauncher.java deleted file mode 100644 index 0dd6b1492..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/StandardLauncher.java +++ /dev/null @@ -1,55 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2018 Red Hat Inc - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Future; - -import org.eclipse.lsp4j.jsonrpc.json.ConcurrentMessageProcessor; -import org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer; - -public class StandardLauncher implements Launcher { - private final ExecutorService execService; - private final T remoteProxy; - private final RemoteEndpoint remoteEndpoint; - private final ConcurrentMessageProcessor msgProcessor; - - public StandardLauncher(StreamMessageProducer reader, MessageConsumer messageConsumer, - ExecutorService execService, T remoteProxy, RemoteEndpoint remoteEndpoint) { - this(execService, remoteProxy, remoteEndpoint, - new ConcurrentMessageProcessor(reader, messageConsumer)); - } - - public StandardLauncher( - ExecutorService execService2, T remoteProxy2, RemoteEndpoint remoteEndpoint2, - ConcurrentMessageProcessor msgProcessor) { - this.execService = execService2; - this.remoteProxy = remoteProxy2; - this.remoteEndpoint = remoteEndpoint2; - this.msgProcessor = msgProcessor; - } - - @Override - public Future startListening() { - return msgProcessor.beginProcessing(execService); - } - - @Override - public T getRemoteProxy() { - return remoteProxy; - } - - @Override - public RemoteEndpoint getRemoteEndpoint() { - return remoteEndpoint; - } -} \ No newline at end of file diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/TracingMessageConsumer.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/TracingMessageConsumer.java deleted file mode 100644 index 5730e11b1..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/TracingMessageConsumer.java +++ /dev/null @@ -1,219 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016-2019 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc; - -import org.eclipse.lsp4j.jsonrpc.json.MessageJsonHandler; -import org.eclipse.lsp4j.jsonrpc.json.StreamMessageConsumer; -import org.eclipse.lsp4j.jsonrpc.messages.Message; -import org.eclipse.lsp4j.jsonrpc.messages.NotificationMessage; -import org.eclipse.lsp4j.jsonrpc.messages.RequestMessage; -import org.eclipse.lsp4j.jsonrpc.messages.ResponseMessage; - -import java.io.PrintWriter; -import java.time.Clock; -import java.time.Instant; -import java.time.format.DateTimeFormatter; -import java.util.Locale; -import java.util.Map; -import java.util.Objects; -import java.util.logging.Logger; - -import static java.util.logging.Level.WARNING; - -/** - * A {@link MessageConsumer} that outputs logs in a format that can be parsed by the LSP Inspector. - * https://microsoft.github.io/language-server-protocol/inspector/ - */ -public class TracingMessageConsumer implements MessageConsumer { - private static final Logger LOG = Logger.getLogger(TracingMessageConsumer.class.getName()); - - private final MessageConsumer messageConsumer; - private final Map sentRequests; - private final Map receivedRequests; - private final PrintWriter printWriter; - private final Clock clock; - private final DateTimeFormatter dateTimeFormatter; - - /** - * @param messageConsumer The {@link MessageConsumer} to wrap. - * @param sentRequests A map that keeps track of pending sent request data. - * @param receivedRequests A map that keeps track of pending received request data. - * @param printWriter Where to write the log to. - * @param clock The clock that is used to calculate timestamps and durations. - */ - public TracingMessageConsumer( - MessageConsumer messageConsumer, - Map sentRequests, - Map receivedRequests, - PrintWriter printWriter, - Clock clock) { - this(messageConsumer, sentRequests, receivedRequests, printWriter, clock, null); - } - - /** - * @param messageConsumer The {@link MessageConsumer} to wrap. - * @param sentRequests A map that keeps track of pending sent request data. - * @param receivedRequests A map that keeps track of pending received request data. - * @param printWriter Where to write the log to. - * @param clock The clock that is used to calculate timestamps and durations. - * @param locale THe Locale to format the timestamps and durations, or null to use default locale. - */ - public TracingMessageConsumer( - MessageConsumer messageConsumer, - Map sentRequests, - Map receivedRequests, - PrintWriter printWriter, - Clock clock, - Locale locale) { - this.messageConsumer = Objects.requireNonNull(messageConsumer); - this.sentRequests = Objects.requireNonNull(sentRequests); - this.receivedRequests = Objects.requireNonNull(receivedRequests); - this.printWriter = Objects.requireNonNull(printWriter); - this.clock = Objects.requireNonNull(clock); - if (locale == null) { - this.dateTimeFormatter = DateTimeFormatter.ofPattern("KK:mm:ss a").withZone(clock.getZone()); - } else { - this.dateTimeFormatter = DateTimeFormatter.ofPattern("KK:mm:ss a", locale).withZone(clock.getZone()); - } - } - - /** - * Constructs a log string for a given {@link Message}. The type of the {@link MessageConsumer} - * determines if we're sending or receiving a message. The type of the @{link Message} determines - * if it is a request, response, or notification. - */ - @Override - public void consume(Message message) throws MessageIssueException, JsonRpcException { - final Instant now = clock.instant(); - final String date = dateTimeFormatter.format(now); - final String logString; - - if (messageConsumer instanceof StreamMessageConsumer) { - logString = consumeMessageSending(message, now, date); - } else if (messageConsumer instanceof RemoteEndpoint) { - logString = consumeMessageReceiving(message, now, date); - } else { - LOG.log(WARNING, String.format("Unknown MessageConsumer type: %s", messageConsumer)); - logString = null; - } - - if (logString != null) { - printWriter.print(logString); - printWriter.flush(); - } - - messageConsumer.consume(message); - } - - private String consumeMessageSending(Message message, Instant now, String date) { - if (message instanceof RequestMessage) { - RequestMessage requestMessage = (RequestMessage) message; - String id = requestMessage.getId(); - String method = requestMessage.getMethod(); - RequestMetadata requestMetadata = new RequestMetadata(method, now); - sentRequests.put(id, requestMetadata); - Object params = requestMessage.getParams(); - String paramsJson = MessageJsonHandler.toString(params); - String format = "[Trace - %s] Sending request '%s - (%s)'\nParams: %s\n\n\n"; - return String.format(format, date, method, id, paramsJson); - } else if (message instanceof ResponseMessage) { - ResponseMessage responseMessage = (ResponseMessage) message; - String id = responseMessage.getId(); - RequestMetadata requestMetadata = receivedRequests.remove(id); - if (requestMetadata == null) { - LOG.log(WARNING, String.format("Unmatched response message: %s", message)); - return null; - } - String method = requestMetadata.method; - long latencyMillis = now.toEpochMilli() - requestMetadata.start.toEpochMilli(); - Object result = responseMessage.getResult(); - String resultJson = MessageJsonHandler.toString(result); - String format = - "[Trace - %s] Sending response '%s - (%s)'. Processing request took %sms\nResult: %s\n\n\n"; - return String.format(format, date, method, id, latencyMillis, resultJson); - } else if (message instanceof NotificationMessage) { - NotificationMessage notificationMessage = (NotificationMessage) message; - String method = notificationMessage.getMethod(); - Object params = notificationMessage.getParams(); - String paramsJson = MessageJsonHandler.toString(params); - String format = "[Trace - %s] Sending notification '%s'\nParams: %s\n\n\n"; - return String.format(format, date, method, paramsJson); - } else { - LOG.log(WARNING, String.format("Unknown message type: %s", message)); - return null; - } - } - - private String consumeMessageReceiving(Message message, Instant now, String date) { - if (message instanceof RequestMessage) { - RequestMessage requestMessage = (RequestMessage) message; - String method = requestMessage.getMethod(); - String id = requestMessage.getId(); - RequestMetadata requestMetadata = new RequestMetadata(method, now); - receivedRequests.put(id, requestMetadata); - Object params = requestMessage.getParams(); - String paramsJson = MessageJsonHandler.toString(params); - String format = "[Trace - %s] Received request '%s - (%s)'\nParams: %s\n\n\n"; - return String.format(format, date, method, id, paramsJson); - } else if (message instanceof ResponseMessage) { - ResponseMessage responseMessage = (ResponseMessage) message; - String id = responseMessage.getId(); - RequestMetadata requestMetadata = sentRequests.remove(id); - if (requestMetadata == null) { - LOG.log(WARNING, String.format("Unmatched response message: %s", message)); - return null; - } - String method = requestMetadata.method; - long latencyMillis = now.toEpochMilli() - requestMetadata.start.toEpochMilli(); - Object result = responseMessage.getResult(); - String resultJson = MessageJsonHandler.toString(result); - Object error = responseMessage.getError(); - String errorJson = MessageJsonHandler.toString(error); - String format = "[Trace - %s] Received response '%s - (%s)' in %sms\nResult: %s\nError: %s\n\n\n"; - return String.format(format, date, method, id, latencyMillis, resultJson, errorJson); - } else if (message instanceof NotificationMessage) { - NotificationMessage notificationMessage = (NotificationMessage) message; - String method = notificationMessage.getMethod(); - Object params = notificationMessage.getParams(); - String paramsJson = MessageJsonHandler.toString(params); - String format = "[Trace - %s] Received notification '%s'\nParams: %s\n\n\n"; - return String.format(format, date, method, paramsJson); - } else { - LOG.log(WARNING, String.format("Unknown message type: %s", message)); - return null; - } - } - - /** Data class for holding pending request metadata. */ - public static class RequestMetadata { - final String method; - final Instant start; - - public RequestMetadata(String method, Instant start) { - this.method = method; - this.start = start; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - RequestMetadata that = (RequestMetadata) o; - return Objects.equals(method, that.method) && Objects.equals(start, that.start); - } - - @Override - public int hashCode() { - return Objects.hash(method, start); - } - } -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/ConcurrentMessageProcessor.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/ConcurrentMessageProcessor.java deleted file mode 100644 index 1eedf2e8d..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/ConcurrentMessageProcessor.java +++ /dev/null @@ -1,131 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.json; - -import java.io.Closeable; -import java.io.IOException; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.eclipse.lsp4j.jsonrpc.MessageConsumer; -import org.eclipse.lsp4j.jsonrpc.MessageProducer; - -/** - * This class connects a message producer with a message consumer by listening for new messages in a dedicated thread. - */ -public class ConcurrentMessageProcessor implements Runnable { - - /** - * Start a thread that listens for messages in the message producer and forwards them to the message consumer. - * - * @param messageProducer - produces messages, e.g. by reading from an input channel - * @param messageConsumer - processes messages and potentially forwards them to other consumers - * @param executorService - the thread is started using this service - * @return a future that is resolved when the started thread is terminated, e.g. by closing a stream - * @deprecated Please use the non-static ConcurrentMessageProcessor.beginProcessing() instead. - */ - @Deprecated - public static Future startProcessing(MessageProducer messageProducer, MessageConsumer messageConsumer, - ExecutorService executorService) { - ConcurrentMessageProcessor reader = new ConcurrentMessageProcessor(messageProducer, messageConsumer); - final Future result = executorService.submit(reader); - return wrapFuture(result, messageProducer); - } - - public static Future wrapFuture(Future result, MessageProducer messageProducer) { - return new Future() { - - @Override - public Void get() throws InterruptedException, ExecutionException { - return (Void) result.get(); - } - - @Override - public Void get(long timeout, TimeUnit unit) - throws InterruptedException, ExecutionException, TimeoutException { - return (Void) result.get(timeout, unit); - } - - @Override - public boolean isDone() { - return result.isDone(); - } - - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - if (mayInterruptIfRunning && messageProducer instanceof Closeable) { - try { - ((Closeable) messageProducer).close(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - return result.cancel(mayInterruptIfRunning); - } - - @Override - public boolean isCancelled() { - return result.isCancelled(); - } - }; - } - - private static final Logger LOG = Logger.getLogger(ConcurrentMessageProcessor.class.getName()); - - private boolean isRunning; - - private final MessageProducer messageProducer; - private final MessageConsumer messageConsumer; - - public ConcurrentMessageProcessor(MessageProducer messageProducer, MessageConsumer messageConsumer) { - this.messageProducer = messageProducer; - this.messageConsumer = messageConsumer; - } - - /** - * Start a thread that listens for messages in the message producer and forwards them to the message consumer. - * - * @param executorService - the thread is started using this service - * @return a future that is resolved when the started thread is terminated, e.g. by closing a stream - */ - public Future beginProcessing(ExecutorService executorService) { - final Future result = executorService.submit(this); - return wrapFuture(result, messageProducer); - } - - public void run() { - processingStarted(); - try { - messageProducer.listen(messageConsumer); - } catch (Exception e) { - LOG.log(Level.SEVERE, e.getMessage(), e); - } finally { - processingEnded(); - } - } - - protected void processingStarted() { - if (isRunning) { - throw new IllegalStateException("The message processor is already running."); - } - isRunning = true; - } - - protected void processingEnded() { - isRunning = false; - } -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/JsonRpcMethod.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/JsonRpcMethod.java deleted file mode 100644 index b2dcf13d8..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/JsonRpcMethod.java +++ /dev/null @@ -1,88 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.json; - -import java.lang.reflect.Type; - -import com.google.gson.TypeAdapterFactory; - -/** - * A description of a JSON-RPC method. - */ -public class JsonRpcMethod { - - private final String methodName; - private final Type[] parameterTypes; - private final Type returnType; - private final TypeAdapterFactory returnTypeAdapterFactory; - private final boolean isNotification; - - private JsonRpcMethod(String methodName, Type[] parameterTypes, Type returnType, TypeAdapterFactory returnTypeAdapterFactory, - boolean isNotification) { - if (methodName == null) - throw new NullPointerException("methodName"); - this.methodName = methodName; - this.parameterTypes = parameterTypes; - this.returnType = returnType; - this.returnTypeAdapterFactory = returnTypeAdapterFactory; - this.isNotification = isNotification; - } - - public String getMethodName() { - return methodName; - } - - public Type[] getParameterTypes() { - return parameterTypes; - } - - public Type getReturnType() { - return returnType; - } - - public TypeAdapterFactory getReturnTypeAdapterFactory() { - return returnTypeAdapterFactory; - } - - public boolean isNotification() { - return isNotification; - } - - public static JsonRpcMethod notification(String name, Type... parameterTypes) { - return new JsonRpcMethod(name, parameterTypes, Void.class, null, true); - } - - public static JsonRpcMethod request(String name, Type returnType, Type... parameterTypes) { - return new JsonRpcMethod(name, parameterTypes, returnType, null, false); - } - - public static JsonRpcMethod request(String name, Type returnType, TypeAdapterFactory returnTypeAdapterFactory, Type... parameterTypes) { - return new JsonRpcMethod(name, parameterTypes, returnType, returnTypeAdapterFactory, false); - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - if (isNotification) - builder.append("JsonRpcMethod (notification) {\n"); - else - builder.append("JsonRpcMethod (request) {\n"); - builder.append("\tmethodName: ").append(methodName).append('\n'); - if (parameterTypes != null) - builder.append("\tparameterTypes: ").append(parameterTypes).append('\n'); - if (returnType != null) - builder.append("\treturnType: ").append(returnType).append('\n'); - builder.append("}"); - return builder.toString(); - } - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/JsonRpcMethodProvider.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/JsonRpcMethodProvider.java deleted file mode 100644 index a7312003e..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/JsonRpcMethodProvider.java +++ /dev/null @@ -1,26 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.json; - -import java.util.Map; - -import org.eclipse.lsp4j.jsonrpc.Endpoint; - -/** - * Provides {@link JsonRpcMethod}. Can be implemented by {@link Endpoint}s to - * provide information about the supported methods. - */ -public interface JsonRpcMethodProvider { - - Map supportedMethods(); - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/MessageConstants.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/MessageConstants.java deleted file mode 100644 index e6676fa1a..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/MessageConstants.java +++ /dev/null @@ -1,22 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.json; - -public interface MessageConstants { - - public static String JSONRPC_VERSION = "2.0"; - public static String CONTENT_LENGTH_HEADER = "Content-Length"; - public static String CONTENT_TYPE_HEADER = "Content-Type"; - public static String JSON_MIME_TYPE = "application/json"; - public static String CRLF = "\r\n"; - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/MessageJsonHandler.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/MessageJsonHandler.java deleted file mode 100644 index eb35b3a27..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/MessageJsonHandler.java +++ /dev/null @@ -1,168 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.json; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.InstanceCreator; -import com.google.gson.JsonIOException; -import com.google.gson.JsonParseException; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonToken; -import com.google.gson.stream.MalformedJsonException; -import com.itsaky.androidide.tooling.api.model.IAndroidProject; -import com.itsaky.androidide.tooling.api.model.internal.DefaultAndroidModule; - -import org.eclipse.lsp4j.jsonrpc.MessageIssueException; -import org.eclipse.lsp4j.jsonrpc.json.adapters.CollectionTypeAdapter; -import org.eclipse.lsp4j.jsonrpc.json.adapters.EitherTypeAdapter; -import org.eclipse.lsp4j.jsonrpc.json.adapters.EnumTypeAdapter; -import org.eclipse.lsp4j.jsonrpc.json.adapters.MessageTypeAdapter; -import org.eclipse.lsp4j.jsonrpc.json.adapters.ThrowableTypeAdapter; -import org.eclipse.lsp4j.jsonrpc.json.adapters.TupleTypeAdapters; -import org.eclipse.lsp4j.jsonrpc.messages.CancelParams; -import org.eclipse.lsp4j.jsonrpc.messages.Message; -import org.eclipse.lsp4j.jsonrpc.messages.MessageIssue; -import org.eclipse.lsp4j.jsonrpc.messages.ResponseErrorCode; - -import java.io.IOException; -import java.io.Reader; -import java.io.StringReader; -import java.io.StringWriter; -import java.io.Writer; -import java.util.Collections; -import java.util.Map; -import java.util.function.Consumer; - -/** A wrapper around Gson that includes configuration required for JSON-RPC messages. */ -public class MessageJsonHandler { - - public static final JsonRpcMethod CANCEL_METHOD = - JsonRpcMethod.notification("$/cancelRequest", CancelParams.class); - private static MessageJsonHandler toStringInstance; - private final Gson gson; - private final Map supportedMethods; - private MethodProvider methodProvider; - - /** - * @param supportedMethods - a map used to resolve RPC methods in {@link - * #getJsonRpcMethod(String)} - */ - public MessageJsonHandler(Map supportedMethods) { - this.supportedMethods = supportedMethods; - this.gson = getDefaultGsonBuilder().create(); - } - - /** Create a {@link GsonBuilder} with default settings for parsing JSON-RPC messages. */ - public GsonBuilder getDefaultGsonBuilder() { - return new GsonBuilder() - .registerTypeAdapterFactory(new CollectionTypeAdapter.Factory()) - .registerTypeAdapterFactory(new ThrowableTypeAdapter.Factory()) - .registerTypeAdapterFactory(new EitherTypeAdapter.Factory()) - .registerTypeAdapterFactory(new TupleTypeAdapters.TwoTypeAdapterFactory()) - .registerTypeAdapterFactory(new EnumTypeAdapter.Factory()) - .registerTypeAdapterFactory(new MessageTypeAdapter.Factory(this)); - } - - /** - * @param supportedMethods - a map used to resolve RPC methods in {@link - * #getJsonRpcMethod(String)} - * @param configureGson - a function that contributes to the GsonBuilder created by {@link - * #getDefaultGsonBuilder()} - */ - public MessageJsonHandler( - Map supportedMethods, Consumer configureGson) { - this.supportedMethods = supportedMethods; - GsonBuilder gsonBuilder = getDefaultGsonBuilder(); - configureGson.accept(gsonBuilder); - this.gson = gsonBuilder.create(); - } - - /** - * Perform JSON serialization of the given object using the default configuration of JSON-RPC - * messages enhanced with the pretty printing option. - */ - public static String toString(Object object) { - if (toStringInstance == null) { - toStringInstance = - new MessageJsonHandler( - Collections.emptyMap(), - gsonBuilder -> { - gsonBuilder.setPrettyPrinting(); - }); - } - return toStringInstance.gson.toJson(object); - } - - public Gson getGson() { - return gson; - } - - /** Resolve an RPC method by name. */ - public JsonRpcMethod getJsonRpcMethod(String name) { - JsonRpcMethod result = supportedMethods.get(name); - if (result != null) return result; - else if (CANCEL_METHOD.getMethodName().equals(name)) return CANCEL_METHOD; - return null; - } - - public MethodProvider getMethodProvider() { - return methodProvider; - } - - public void setMethodProvider(MethodProvider methodProvider) { - this.methodProvider = methodProvider; - } - - public Message parseMessage(CharSequence input) throws JsonParseException { - StringReader reader = new StringReader(input.toString()); - return parseMessage(reader); - } - - public Message parseMessage(Reader input) throws JsonParseException { - JsonReader jsonReader = new JsonReader(input); - Message message = gson.fromJson(jsonReader, Message.class); - - if (message != null) { - // Check whether the input has been fully consumed - try { - if (jsonReader.peek() != JsonToken.END_DOCUMENT) { - MessageIssue issue = - new MessageIssue( - "JSON document was not fully consumed.", - ResponseErrorCode.ParseError.getValue()); - throw new MessageIssueException(message, issue); - } - } catch (MalformedJsonException e) { - MessageIssue issue = - new MessageIssue( - "Message could not be parsed.", - ResponseErrorCode.ParseError.getValue(), - e); - throw new MessageIssueException(message, issue); - } catch (IOException e) { - throw new JsonIOException(e); - } - } - return message; - } - - public String serialize(Message message) { - StringWriter writer = new StringWriter(); - serialize(message, writer); - return writer.toString(); - } - - public void serialize(Message message, Writer output) throws JsonIOException { - gson.toJson(message, Message.class, output); - } -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/MethodProvider.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/MethodProvider.java deleted file mode 100644 index 3ece1f93c..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/MethodProvider.java +++ /dev/null @@ -1,23 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.json; - -public interface MethodProvider { - - /** - * Returns the method name for a given request id, or null if such request id is unknown. - * - * @return method name or {@code null} - */ - String resolveMethod(String requestId); - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/ResponseJsonAdapter.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/ResponseJsonAdapter.java deleted file mode 100644 index 3fe62d0c4..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/ResponseJsonAdapter.java +++ /dev/null @@ -1,30 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2018 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.json; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import com.google.gson.TypeAdapterFactory; - -/** - * An annotation that indicates the Gson {@link TypeAdapterFactory} to use with a request response. - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD}) -public @interface ResponseJsonAdapter { - - Class value(); - -} \ No newline at end of file diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/StreamMessageConsumer.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/StreamMessageConsumer.java deleted file mode 100644 index 313c47233..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/StreamMessageConsumer.java +++ /dev/null @@ -1,98 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.json; - -import java.io.IOException; -import java.io.OutputStream; -import java.nio.charset.StandardCharsets; - -import org.eclipse.lsp4j.jsonrpc.JsonRpcException; -import org.eclipse.lsp4j.jsonrpc.MessageConsumer; -import org.eclipse.lsp4j.jsonrpc.messages.Message; - -/** - * A message consumer that serializes messages to JSON and sends them to an output stream. - */ -public class StreamMessageConsumer implements MessageConsumer, MessageConstants { - - private final String encoding; - private final MessageJsonHandler jsonHandler; - - private final Object outputLock = new Object(); - - private OutputStream output; - - public StreamMessageConsumer(MessageJsonHandler jsonHandler) { - this(null, StandardCharsets.UTF_8.name(), jsonHandler); - } - - public StreamMessageConsumer(OutputStream output, MessageJsonHandler jsonHandler) { - this(output, StandardCharsets.UTF_8.name(), jsonHandler); - } - - public StreamMessageConsumer(OutputStream output, String encoding, MessageJsonHandler jsonHandler) { - this.output = output; - this.encoding = encoding; - this.jsonHandler = jsonHandler; - } - - public OutputStream getOutput() { - return output; - } - - public void setOutput(OutputStream output) { - this.output = output; - } - - @Override - public void consume(Message message) { - try { - String content = jsonHandler.serialize(message); - byte[] contentBytes = content.getBytes(encoding); - int contentLength = contentBytes.length; - - String header = getHeader(contentLength); - byte[] headerBytes = header.getBytes(StandardCharsets.US_ASCII); - - synchronized (outputLock) { - output.write(headerBytes); - output.write(contentBytes); - output.flush(); - } - } catch (IOException exception) { - throw new JsonRpcException(exception); - } - } - - /** - * Construct a header to be prepended to the actual content. This implementation writes - * {@code Content-Length} and {@code Content-Type} attributes according to the LSP specification. - */ - protected String getHeader(int contentLength) { - StringBuilder headerBuilder = new StringBuilder(); - appendHeader(headerBuilder, CONTENT_LENGTH_HEADER, contentLength).append(CRLF); - if (!StandardCharsets.UTF_8.name().equals(encoding)) { - appendHeader(headerBuilder, CONTENT_TYPE_HEADER, JSON_MIME_TYPE); - headerBuilder.append("; charset=").append(encoding).append(CRLF); - } - headerBuilder.append(CRLF); - return headerBuilder.toString(); - } - - /** - * Append a header attribute to the given builder. - */ - protected StringBuilder appendHeader(StringBuilder builder, String name, Object value) { - return builder.append(name).append(": ").append(value); - } - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/StreamMessageProducer.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/StreamMessageProducer.java deleted file mode 100644 index 835a903e3..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/StreamMessageProducer.java +++ /dev/null @@ -1,216 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.json; - -import java.io.Closeable; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.eclipse.lsp4j.jsonrpc.JsonRpcException; -import org.eclipse.lsp4j.jsonrpc.MessageConsumer; -import org.eclipse.lsp4j.jsonrpc.MessageIssueException; -import org.eclipse.lsp4j.jsonrpc.MessageIssueHandler; -import org.eclipse.lsp4j.jsonrpc.MessageProducer; -import org.eclipse.lsp4j.jsonrpc.messages.Message; - -/** - * A message producer that reads from an input stream and parses messages from JSON. - */ -public class StreamMessageProducer implements MessageProducer, Closeable, MessageConstants { - - private static final Logger LOG = Logger.getLogger(StreamMessageProducer.class.getName()); - - private final MessageJsonHandler jsonHandler; - private final MessageIssueHandler issueHandler; - - private InputStream input; - - private MessageConsumer callback; - private boolean keepRunning; - - public StreamMessageProducer(InputStream input, MessageJsonHandler jsonHandler) { - this(input, jsonHandler, null); - } - - public StreamMessageProducer(InputStream input, MessageJsonHandler jsonHandler, MessageIssueHandler issueHandler) { - this.input = input; - this.jsonHandler = jsonHandler; - this.issueHandler = issueHandler; - } - - public InputStream getInput() { - return input; - } - - public void setInput(InputStream input) { - this.input = input; - } - - protected static class Headers { - public int contentLength = -1; - public String charset = StandardCharsets.UTF_8.name(); - } - - @Override - public void listen(MessageConsumer callback) { - if (keepRunning) { - throw new IllegalStateException("This StreamMessageProducer is already running."); - } - this.keepRunning = true; - this.callback = callback; - try { - StringBuilder headerBuilder = null; - StringBuilder debugBuilder = null; - boolean newLine = false; - Headers headers = new Headers(); - while (keepRunning) { - int c = input.read(); - if (c == -1) { - // End of input stream has been reached - keepRunning = false; - } else { - if (debugBuilder == null) - debugBuilder = new StringBuilder(); - debugBuilder.append((char) c); - if (c == '\n') { - if (newLine) { - // Two consecutive newlines have been read, which signals the start of the message content - if (headers.contentLength < 0) { - fireError(new IllegalStateException("Missing header " + CONTENT_LENGTH_HEADER - + " in input \"" + debugBuilder + "\"")); - } else { - boolean result = handleMessage(input, headers); - if (!result) - keepRunning = false; - newLine = false; - } - headers = new Headers(); - debugBuilder = null; - } else if (headerBuilder != null) { - // A single newline ends a header line - parseHeader(headerBuilder.toString(), headers); - headerBuilder = null; - } - newLine = true; - } else if (c != '\r') { - // Add the input to the current header line - if (headerBuilder == null) - headerBuilder = new StringBuilder(); - headerBuilder.append((char) c); - newLine = false; - } - } - } // while (keepRunning) - } catch (IOException exception) { - if (JsonRpcException.indicatesStreamClosed(exception)) { - // Only log the error if we had intended to keep running - if (keepRunning) - fireStreamClosed(exception); - } else - throw new JsonRpcException(exception); - } finally { - this.callback = null; - this.keepRunning = false; - } - } - - /** - * Log an error. - */ - protected void fireError(Throwable error) { - String message = error.getMessage() != null ? error.getMessage() : "An error occurred while processing an incoming message."; - LOG.log(Level.SEVERE, message, error); - } - - /** - * Report that the stream was closed through an exception. - */ - protected void fireStreamClosed(Exception cause) { - String message = cause.getMessage() != null ? cause.getMessage() : "The input stream was closed."; - LOG.log(Level.INFO, message, cause); - } - - /** - * Parse a header attribute and set the corresponding data in the {@link Headers} fields. - */ - protected void parseHeader(String line, Headers headers) { - int sepIndex = line.indexOf(':'); - if (sepIndex >= 0) { - String key = line.substring(0, sepIndex).trim(); - switch (key) { - case CONTENT_LENGTH_HEADER: - try { - headers.contentLength = Integer.parseInt(line.substring(sepIndex + 1).trim()); - } catch (NumberFormatException e) { - fireError(e); - } - break; - case CONTENT_TYPE_HEADER: { - int charsetIndex = line.indexOf("charset="); - if (charsetIndex >= 0) - headers.charset = line.substring(charsetIndex + 8).trim(); - break; - } - } - } - } - - /** - * Read the JSON content part of a message, parse it, and notify the callback. - * - * @return {@code true} if we should continue reading from the input stream, {@code false} if we should stop - */ - protected boolean handleMessage(InputStream input, Headers headers) throws IOException { - if (callback == null) - callback = message -> LOG.log(Level.INFO, "Received message: " + message); - - try { - int contentLength = headers.contentLength; - byte[] buffer = new byte[contentLength]; - int bytesRead = 0; - - while (bytesRead < contentLength) { - int readResult = input.read(buffer, bytesRead, contentLength - bytesRead); - if (readResult == -1) - return false; - bytesRead += readResult; - } - - String content = new String(buffer, headers.charset); - try { - Message message = jsonHandler.parseMessage(content); - callback.consume(message); - } catch (MessageIssueException exception) { - // An issue was found while parsing or validating the message - if (issueHandler != null) - issueHandler.handle(exception.getRpcMessage(), exception.getIssues()); - else - fireError(exception); - } - } catch (Exception exception) { - // UnsupportedEncodingException can be thrown by String constructor - // JsonParseException can be thrown by jsonHandler - // We also catch arbitrary exceptions that are thrown by message consumers in order to keep this thread alive - fireError(exception); - } - return true; - } - - @Override - public void close() { - keepRunning = false; - } - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/adapters/CollectionTypeAdapter.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/adapters/CollectionTypeAdapter.java deleted file mode 100644 index 96d34f80a..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/adapters/CollectionTypeAdapter.java +++ /dev/null @@ -1,146 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016-2017 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.json.adapters; - -import java.io.IOException; -import java.lang.reflect.Constructor; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.util.ArrayList; -import java.util.Collection; -import java.util.LinkedHashSet; -import java.util.LinkedList; -import java.util.Queue; -import java.util.Set; -import java.util.SortedSet; -import java.util.TreeSet; -import java.util.function.Supplier; - -import com.google.gson.Gson; -import com.google.gson.JsonParseException; -import com.google.gson.TypeAdapter; -import com.google.gson.TypeAdapterFactory; -import com.google.gson.reflect.TypeToken; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonToken; -import com.google.gson.stream.JsonWriter; - -/** - * A specialized type adapter for collections that can handle single values. - */ -public class CollectionTypeAdapter extends TypeAdapter> { - - public static class Factory implements TypeAdapterFactory { - - @Override - @SuppressWarnings({ "unchecked" }) - public TypeAdapter create(Gson gson, TypeToken typeToken) { - if (!Collection.class.isAssignableFrom(typeToken.getRawType())) - return null; - - Type[] elementTypes = TypeUtils.getElementTypes(typeToken, Collection.class); - if (elementTypes.length != 1) - return null; - Type elementType = elementTypes[0]; - TypeAdapter elementTypeAdapter; - if (elementType == Object.class) - elementTypeAdapter = new JsonElementTypeAdapter(gson); - else - elementTypeAdapter = gson.getAdapter(TypeToken.get(elementType)); - Supplier> constructor = getConstructor((Class>) typeToken.getRawType()); - return (TypeAdapter) create(gson, elementType, elementTypeAdapter, constructor); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - protected TypeAdapter create(Gson gson, Type elementType, TypeAdapter elementTypeAdapter, Supplier> constructor) { - return new CollectionTypeAdapter(gson, elementType, elementTypeAdapter, constructor); - } - - protected Supplier> getConstructor(Class> rawType) { - try { - Constructor> constructor = rawType.getDeclaredConstructor(); - return () -> { - try { - return constructor.newInstance(); - } catch (Exception e) { - throw new JsonParseException(e); - } - }; - } catch (Exception e) { - if (SortedSet.class.isAssignableFrom(rawType)) - return () -> new TreeSet(); - else if (Set.class.isAssignableFrom(rawType)) - return () -> new LinkedHashSet(); - else if (Queue.class.isAssignableFrom(rawType)) - return () -> new LinkedList(); - else - return () -> new ArrayList(); - } - } - - } - - private final Gson gson; - private final Type elementType; - private final TypeAdapter elementTypeAdapter; - private final Supplier> constructor; - - public CollectionTypeAdapter(Gson gson, Type elementType, TypeAdapter elementTypeAdapter, Supplier> constructor) { - this.gson = gson; - this.elementType = elementType; - this.elementTypeAdapter = elementTypeAdapter; - this.constructor = constructor; - } - - @Override - public Collection read(JsonReader in) throws IOException { - JsonToken peek = in.peek(); - if (peek == JsonToken.NULL) { - in.nextNull(); - return null; - } else if (peek == JsonToken.BEGIN_ARRAY) { - Collection collection = constructor.get(); - in.beginArray(); - while (in.hasNext()) { - E instance = elementTypeAdapter.read(in); - collection.add(instance); - } - in.endArray(); - return collection; - } else { - Collection collection = constructor.get(); - E instance = elementTypeAdapter.read(in); - collection.add(instance); - return collection; - } - } - - @Override - public void write(JsonWriter out, Collection collection) throws IOException { - if (collection == null) { - out.nullValue(); - return; - } - out.beginArray(); - for (E element : collection) { - if (element != null && elementType != element.getClass() - && (elementType instanceof TypeVariable || elementType instanceof Class)) { - @SuppressWarnings("unchecked") - TypeAdapter runtimeTypeAdapter = (TypeAdapter) gson.getAdapter(TypeToken.get(element.getClass())); - runtimeTypeAdapter.write(out, element); - } else { - elementTypeAdapter.write(out, element); - } - } - out.endArray(); - } -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/adapters/CollectionTypeAdapterFactory.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/adapters/CollectionTypeAdapterFactory.java deleted file mode 100644 index 7a153e285..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/adapters/CollectionTypeAdapterFactory.java +++ /dev/null @@ -1,40 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.json.adapters; - -import java.lang.reflect.Type; -import java.util.Collection; -import java.util.function.Supplier; - -import com.google.gson.Gson; -import com.google.gson.TypeAdapter; - -/** - * @deprecated Use {@link CollectionTypeAdapter.Factory} instead. - */ -@Deprecated -public class CollectionTypeAdapterFactory extends CollectionTypeAdapter.Factory { - - /** - * @deprecated Use {@link CollectionTypeAdapter} instead. - */ - @Deprecated - protected static class Adapter extends CollectionTypeAdapter { - - public Adapter(Gson gson, Type elementType, TypeAdapter elementTypeAdapter, - Supplier> constructor) { - super(gson, elementType, elementTypeAdapter, constructor); - } - - } - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/adapters/EitherTypeAdapter.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/adapters/EitherTypeAdapter.java deleted file mode 100644 index 707c50613..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/adapters/EitherTypeAdapter.java +++ /dev/null @@ -1,286 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016-2018 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.json.adapters; - -import java.io.IOException; -import java.lang.reflect.Type; -import java.util.Collection; -import java.util.HashSet; -import java.util.function.Predicate; - -import org.eclipse.lsp4j.jsonrpc.messages.Either; -import org.eclipse.lsp4j.jsonrpc.messages.Either3; -import org.eclipse.lsp4j.jsonrpc.messages.Tuple; - -import com.google.gson.Gson; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParseException; -import com.google.gson.JsonParser; -import com.google.gson.TypeAdapter; -import com.google.gson.TypeAdapterFactory; -import com.google.gson.reflect.TypeToken; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonToken; -import com.google.gson.stream.JsonWriter; - -/** - * Type adapter for {@link Either} and {@link Either3}. - */ -public class EitherTypeAdapter extends TypeAdapter> { - - public static class Factory implements TypeAdapterFactory { - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Override - public TypeAdapter create(Gson gson, TypeToken typeToken) { - if (!TypeUtils.isEither(typeToken.getType())) { - return null; - } - return new EitherTypeAdapter(gson, typeToken); - } - - } - - /** - * A predicate that is usedful for checking alternatives in case both the left and the right type - * are JSON object types. - */ - public static class PropertyChecker implements Predicate { - - private final String propertyName; - private final String expectedValue; - private final Class expectedType; - - public PropertyChecker(String propertyName) { - this.propertyName = propertyName; - this.expectedValue = null; - this.expectedType = null; - } - - public PropertyChecker(String propertyName, String expectedValue) { - this.propertyName = propertyName; - this.expectedValue = expectedValue; - this.expectedType = null; - } - - public PropertyChecker(String propertyName, Class expectedType) { - this.propertyName = propertyName; - this.expectedType = expectedType; - this.expectedValue = null; - } - - @Override - public boolean test(JsonElement element) { - if (element.isJsonObject()) { - JsonObject object = element.getAsJsonObject(); - JsonElement value = object.get(propertyName); - if (expectedValue != null) - return value != null && value.isJsonPrimitive() && expectedValue.equals(value.getAsString()); - else if (expectedType != null) - return expectedType.isInstance(value); - else - return value != null; - } - return false; - } - - } - - /** - * A predicate for the case that a type alternative is a list. - */ - public static class ListChecker implements Predicate { - - private final Predicate elementChecker; - private final boolean resultIfEmpty; - - public ListChecker(Predicate elementChecker) { - this(elementChecker, false); - } - - public ListChecker(Predicate elementChecker, boolean resultIfEmpty) { - this.elementChecker = elementChecker; - this.resultIfEmpty = resultIfEmpty; - } - - @Override - public boolean test(JsonElement t) { - if (elementChecker.test(t)) - return true; - if (t.isJsonArray()) { - JsonArray array = t.getAsJsonArray(); - if (array.size() == 0) - return resultIfEmpty; - for (JsonElement e : array) { - if (elementChecker.test(e)) - return true; - } - } - return false; - } - - } - - protected final TypeToken> typeToken; - protected final EitherTypeArgument left; - protected final EitherTypeArgument right; - protected final Predicate leftChecker; - protected final Predicate rightChecker; - - public EitherTypeAdapter(Gson gson, TypeToken> typeToken) { - this(gson, typeToken, null, null); - } - - public EitherTypeAdapter(Gson gson, TypeToken> typeToken, Predicate leftChecker, Predicate rightChecker) { - this.typeToken = typeToken; - Type[] elementTypes = TypeUtils.getElementTypes(typeToken, Either.class); - this.left = new EitherTypeArgument(gson, elementTypes[0]); - this.right = new EitherTypeArgument(gson, elementTypes[1]); - this.leftChecker = leftChecker; - this.rightChecker = rightChecker; - } - - @Override - public void write(JsonWriter out, Either value) throws IOException { - if (value == null) { - out.nullValue(); - } else if (value.isLeft()) { - left.write(out, value.getLeft()); - } else { - right.write(out, value.getRight()); - } - } - - @Override - public Either read(JsonReader in) throws IOException { - JsonToken next = in.peek(); - if (next == JsonToken.NULL) { - in.nextNull(); - return null; - } - return create(next, in); - } - - protected Either create(JsonToken nextToken, JsonReader in) throws IOException { - boolean matchesLeft = left.isAssignable(nextToken); - boolean matchesRight = right.isAssignable(nextToken); - if (matchesLeft && matchesRight) { - if (leftChecker != null || rightChecker != null) { - JsonElement element = JsonParser.parseReader(in); - if (leftChecker != null && leftChecker.test(element)) - // Parse the left alternative from the JSON element tree - return createLeft(left.read(element)); - if (rightChecker != null && rightChecker.test(element)) - // Parse the right alternative from the JSON element tree - return createRight(right.read(element)); - } - throw new JsonParseException("Ambiguous Either type: token " + nextToken + " matches both alternatives."); - } else if (matchesLeft) { - // Parse the left alternative from the JSON stream - return createLeft(left.read(in)); - } else if (matchesRight) { - // Parse the right alternative from the JSON stream - return createRight(right.read(in)); - } else if (leftChecker != null || rightChecker != null) { - // If result is not the list but directly the only item in the list - JsonElement element = JsonParser.parseReader(in); - if (leftChecker != null && leftChecker.test(element)) - // Parse the left alternative from the JSON element tree - return createLeft(left.read(element)); - if (rightChecker != null && rightChecker.test(element)) - // Parse the right alternative from the JSON element tree - return createRight(right.read(element)); - } - throw new JsonParseException("Unexpected token " + nextToken + ": expected " + left + " | " + right + " tokens."); - } - - @SuppressWarnings("unchecked") - protected Either createLeft(L obj) throws IOException { - if (Either3.class.isAssignableFrom(typeToken.getRawType())) - return (Either) Either3.forLeft3(obj); - return Either.forLeft(obj); - } - - @SuppressWarnings("unchecked") - protected Either createRight(R obj) throws IOException { - if (Either3.class.isAssignableFrom(typeToken.getRawType())) - return (Either) Either3.forRight3((Either) obj); - return Either.forRight(obj); - } - - protected static class EitherTypeArgument { - - protected final TypeToken typeToken; - protected final TypeAdapter adapter; - protected final Collection expectedTokens; - - @SuppressWarnings("unchecked") - public EitherTypeArgument(Gson gson, Type type) { - this.typeToken = (TypeToken) TypeToken.get(type); - this.adapter = (type == Object.class) ? (TypeAdapter) new JsonElementTypeAdapter(gson) : gson.getAdapter(this.typeToken); - this.expectedTokens = new HashSet<>(); - for (Type expectedType : TypeUtils.getExpectedTypes(type)) { - Class rawType = TypeToken.get(expectedType).getRawType(); - JsonToken expectedToken = getExpectedToken(rawType); - expectedTokens.add(expectedToken); - } - } - - protected JsonToken getExpectedToken(Class rawType) { - if (rawType.isArray() || Collection.class.isAssignableFrom(rawType) || Tuple.class.isAssignableFrom(rawType)) { - return JsonToken.BEGIN_ARRAY; - } - if (Boolean.class.isAssignableFrom(rawType)) { - return JsonToken.BOOLEAN; - } - if (Number.class.isAssignableFrom(rawType) || Enum.class.isAssignableFrom(rawType)) { - return JsonToken.NUMBER; - } - if (Character.class.isAssignableFrom(rawType) || String.class.isAssignableFrom(rawType)) { - return JsonToken.STRING; - } - return JsonToken.BEGIN_OBJECT; - } - - public boolean isAssignable(JsonToken jsonToken) { - return this.expectedTokens.contains(jsonToken); - } - - public void write(JsonWriter out, T value) throws IOException { - this.adapter.write(out, value); - } - - public T read(JsonReader in) throws IOException { - return this.adapter.read(in); - } - - public T read(JsonElement element) throws IOException { - return this.adapter.fromJsonTree(element); - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - for (JsonToken expectedToken : expectedTokens) { - if (builder.length() != 0) { - builder.append(" | "); - } - builder.append(expectedToken); - } - return builder.toString(); - } - - } - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/adapters/EitherTypeAdapterFactory.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/adapters/EitherTypeAdapterFactory.java deleted file mode 100644 index 5abbe8320..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/adapters/EitherTypeAdapterFactory.java +++ /dev/null @@ -1,37 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.json.adapters; - -import org.eclipse.lsp4j.jsonrpc.messages.Either; - -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; - -/** - * @deprecated Use {@link EitherTypeAdapter.Factory} instead. - */ -@Deprecated -public class EitherTypeAdapterFactory extends EitherTypeAdapter.Factory { - - /** - * @deprecated Use {@link EitherTypeAdapter} instead. - */ - @Deprecated - protected static class Adapter extends EitherTypeAdapter { - - public Adapter(Gson gson, TypeToken> typeToken) { - super(gson, typeToken); - } - - } - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/adapters/EnumTypeAdapter.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/adapters/EnumTypeAdapter.java deleted file mode 100644 index c24ded2f8..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/adapters/EnumTypeAdapter.java +++ /dev/null @@ -1,105 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016-2017 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.json.adapters; - -import java.io.IOException; -import java.lang.reflect.Field; -import java.util.HashMap; -import java.util.Map; - -import com.google.gson.Gson; -import com.google.gson.TypeAdapter; -import com.google.gson.TypeAdapterFactory; -import com.google.gson.reflect.TypeToken; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonToken; -import com.google.gson.stream.JsonWriter; - -/** - * A custom type adapter for enums that uses integer values. - */ -public class EnumTypeAdapter> extends TypeAdapter { - - public static class Factory implements TypeAdapterFactory { - - @Override - @SuppressWarnings({ "unchecked", "rawtypes" }) - public TypeAdapter create(Gson gson, TypeToken typeToken) { - Class rawType = typeToken.getRawType(); - if (!Enum.class.isAssignableFrom(rawType) || rawType == Enum.class) - return null; - if (!rawType.isEnum()) - rawType = rawType.getSuperclass(); - try { - return new EnumTypeAdapter(rawType); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - } - - } - - private static String VALUE_FIELD_NAME = "value"; - - private final Map nameToConstant = new HashMap<>(); - private final Map valueToConstant = new HashMap<>(); - private final Map constantToValue = new HashMap<>(); - - EnumTypeAdapter(Class classOfT) throws IllegalAccessException { - try { - Field valueField = classOfT.getDeclaredField(VALUE_FIELD_NAME); - if (valueField.getType() != int.class && valueField.getType() != Integer.class) - throw new IllegalArgumentException("The field 'value' must contain an integer value."); - valueField.setAccessible(true); - for (T constant : classOfT.getEnumConstants()) { - nameToConstant.put(constant.name(), constant); - Integer constValue = (Integer) valueField.get(constant); - valueToConstant.put(constValue, constant); - constantToValue.put(constant, constValue); - } - } catch (NoSuchFieldException e) { - for (T constant : classOfT.getEnumConstants()) { - nameToConstant.put(constant.name(), constant); - int constValue = constant.ordinal(); - valueToConstant.put(constValue, constant); - constantToValue.put(constant, constValue); - } - } - } - - @Override - public T read(JsonReader in) throws IOException { - JsonToken peek = in.peek(); - if (peek == JsonToken.NULL) { - in.nextNull(); - return null; - } else if (peek == JsonToken.NUMBER) { - return valueToConstant.get(in.nextInt()); - } else { - String string = in.nextString(); - try { - return valueToConstant.get(Integer.parseInt(string)); - } catch (NumberFormatException e) { - return nameToConstant.get(string); - } - } - } - - @Override - public void write(JsonWriter out, T value) throws IOException { - if (value != null) - out.value(constantToValue.get(value)); - else - out.value((String) null); - } - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/adapters/EnumTypeAdapterFactory.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/adapters/EnumTypeAdapterFactory.java deleted file mode 100644 index ee23ddeb2..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/adapters/EnumTypeAdapterFactory.java +++ /dev/null @@ -1,20 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.json.adapters; - -/** - * @deprecated Use {@link EnumTypeAdapter.Factory} instead. - */ -@Deprecated -public class EnumTypeAdapterFactory extends EnumTypeAdapter.Factory { - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/adapters/JsonElementTypeAdapter.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/adapters/JsonElementTypeAdapter.java deleted file mode 100644 index 0e19daa9a..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/adapters/JsonElementTypeAdapter.java +++ /dev/null @@ -1,68 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2018 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.json.adapters; - -import java.io.IOException; - -import com.google.gson.Gson; -import com.google.gson.JsonElement; -import com.google.gson.TypeAdapter; -import com.google.gson.TypeAdapterFactory; -import com.google.gson.reflect.TypeToken; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonWriter; - -/** - * A type adapter that reads every input into a tree of {@link JsonElement}s. - */ -public class JsonElementTypeAdapter extends TypeAdapter { - - /** - * This factory should not be registered with a GsonBuilder because it always matches. - * Use it as argument to a {@link com.google.gson.annotations.JsonAdapter} annotation like this: - * {@code @JsonAdapter(JsonElementTypeAdapter.Factory.class)} - */ - public static class Factory implements TypeAdapterFactory { - - @SuppressWarnings("unchecked") - @Override - public TypeAdapter create(Gson gson, TypeToken type) { - return (TypeAdapter) new JsonElementTypeAdapter(gson); - } - - } - - private final Gson gson; - private final TypeAdapter adapter; - - public JsonElementTypeAdapter(Gson gson) { - this.gson = gson; - this.adapter = gson.getAdapter(JsonElement.class); - } - - @Override - public JsonElement read(JsonReader in) throws IOException { - return adapter.read(in); - } - - @Override - public void write(JsonWriter out, Object value) throws IOException { - if (value == null) { - out.nullValue(); - } else if (value instanceof JsonElement) { - adapter.write(out, (JsonElement) value); - } else { - gson.toJson(value, value.getClass(), out);; - } - } - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/adapters/MessageTypeAdapter.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/adapters/MessageTypeAdapter.java deleted file mode 100644 index 19986abc0..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/adapters/MessageTypeAdapter.java +++ /dev/null @@ -1,465 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016-2018 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.json.adapters; - -import com.google.gson.Gson; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonIOException; -import com.google.gson.JsonNull; -import com.google.gson.JsonParseException; -import com.google.gson.JsonParser; -import com.google.gson.JsonSyntaxException; -import com.google.gson.TypeAdapter; -import com.google.gson.TypeAdapterFactory; -import com.google.gson.reflect.TypeToken; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonToken; -import com.google.gson.stream.JsonWriter; -import com.google.gson.stream.MalformedJsonException; - -import org.eclipse.lsp4j.jsonrpc.MessageIssueException; -import org.eclipse.lsp4j.jsonrpc.json.JsonRpcMethod; -import org.eclipse.lsp4j.jsonrpc.json.MessageConstants; -import org.eclipse.lsp4j.jsonrpc.json.MessageJsonHandler; -import org.eclipse.lsp4j.jsonrpc.json.MethodProvider; -import org.eclipse.lsp4j.jsonrpc.messages.Either; -import org.eclipse.lsp4j.jsonrpc.messages.Message; -import org.eclipse.lsp4j.jsonrpc.messages.MessageIssue; -import org.eclipse.lsp4j.jsonrpc.messages.NotificationMessage; -import org.eclipse.lsp4j.jsonrpc.messages.RequestMessage; -import org.eclipse.lsp4j.jsonrpc.messages.ResponseError; -import org.eclipse.lsp4j.jsonrpc.messages.ResponseErrorCode; -import org.eclipse.lsp4j.jsonrpc.messages.ResponseMessage; - -import java.io.EOFException; -import java.io.IOException; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -/** - * The type adapter for messages dispatches between the different message types: {@link - * RequestMessage}, {@link ResponseMessage}, and {@link NotificationMessage}. - */ -public class MessageTypeAdapter extends TypeAdapter { - - private static final com.itsaky.androidide.utils.ILogger LOG = - com.itsaky.androidide.utils.ILogger.newInstance(""); - private static Type[] EMPTY_TYPE_ARRAY = {}; - private final MessageJsonHandler handler; - private final Gson gson; - - public MessageTypeAdapter(MessageJsonHandler handler, Gson gson) { - this.handler = handler; - this.gson = gson; - } - - @Override - public void write(JsonWriter out, Message message) throws IOException { - out.beginObject(); - out.name("jsonrpc"); - out.value( - message.getJsonrpc() == null - ? MessageConstants.JSONRPC_VERSION - : message.getJsonrpc()); - - if (message instanceof RequestMessage) { - RequestMessage requestMessage = (RequestMessage) message; - out.name("id"); - writeId(out, requestMessage.getRawId()); - out.name("method"); - out.value(requestMessage.getMethod()); - out.name("params"); - Object params = requestMessage.getParams(); - if (params == null) writeNullValue(out); - else gson.toJson(params, params.getClass(), out); - } else if (message instanceof ResponseMessage) { - ResponseMessage responseMessage = (ResponseMessage) message; - out.name("id"); - writeId(out, responseMessage.getRawId()); - if (responseMessage.getError() != null) { - out.name("error"); - gson.toJson(responseMessage.getError(), ResponseError.class, out); - } else { - out.name("result"); - Object result = responseMessage.getResult(); - if (result == null) { - writeNullValue(out); - } else { - gson.toJson(result, result.getClass(), out); - } - } - } else if (message instanceof NotificationMessage) { - NotificationMessage notificationMessage = (NotificationMessage) message; - out.name("method"); - out.value(notificationMessage.getMethod()); - out.name("params"); - Object params = notificationMessage.getParams(); - if (params == null) writeNullValue(out); - else gson.toJson(params, params.getClass(), out); - } - - out.endObject(); - } - - @Override - public Message read(JsonReader in) throws IOException, JsonIOException, JsonSyntaxException { - if (in.peek() == JsonToken.NULL) { - in.nextNull(); - return null; - } - - in.beginObject(); - String jsonrpc = null, method = null; - Either id = null; - Object rawParams = null; - Object rawResult = null; - ResponseError responseError = null; - try { - - while (in.hasNext()) { - String name = in.nextName(); - switch (name) { - case "jsonrpc": - { - jsonrpc = in.nextString(); - break; - } - case "id": - { - if (in.peek() == JsonToken.NUMBER) id = Either.forRight(in.nextInt()); - else id = Either.forLeft(in.nextString()); - break; - } - case "method": - { - method = in.nextString(); - break; - } - case "params": - { - rawParams = parseParams(in, method); - break; - } - case "result": - { - rawResult = parseResult(in, id != null ? id.get().toString() : null); - break; - } - case "error": - { - responseError = gson.fromJson(in, ResponseError.class); - break; - } - default: - in.skipValue(); - } - } - Object params = parseParams(rawParams, method); - Object result = parseResult(rawResult, id != null ? id.get().toString() : null); - - in.endObject(); - return createMessage(jsonrpc, id, method, params, result, responseError); - - } catch (JsonSyntaxException | MalformedJsonException | EOFException exception) { - if (id != null || method != null) { - // Create a message and bundle it to an exception with an issue that wraps the - // original exception - Message message = - createMessage(jsonrpc, id, method, rawParams, rawResult, responseError); - MessageIssue issue = - new MessageIssue( - "Message could not be parsed.", - ResponseErrorCode.ParseError.getValue(), - exception); - throw new MessageIssueException(message, issue); - } else { - throw exception; - } - } - } - - protected void writeId(JsonWriter out, Either id) throws IOException { - if (id == null) writeNullValue(out); - else if (id.isLeft()) out.value(id.getLeft()); - else if (id.isRight()) out.value(id.getRight()); - } - - /** - * Use this method to write a {@code null} value even if the JSON writer is set to not serialize - * {@code null}. - */ - protected void writeNullValue(JsonWriter out) throws IOException { - boolean previousSerializeNulls = out.getSerializeNulls(); - out.setSerializeNulls(true); - out.nullValue(); - out.setSerializeNulls(previousSerializeNulls); - } - - /** - * Convert the json input into the result object corresponding to the call made by id. - * - *

If the id is not known until after parsing, call {@link #parseResult(Object, String)} on - * the return value of this call for a second chance conversion. - * - * @param in json input to read from - * @param id id of request message this is in response to - * @return correctly typed object if the correct expected type can be determined, or a - * JsonElement representing the result - */ - protected Object parseResult(JsonReader in, String id) - throws JsonIOException, JsonSyntaxException { - Type type = null; - MethodProvider methodProvider = handler.getMethodProvider(); - if (methodProvider != null && id != null) { - String resolvedMethod = methodProvider.resolveMethod(id); - if (resolvedMethod != null) { - JsonRpcMethod jsonRpcMethod = handler.getJsonRpcMethod(resolvedMethod); - if (jsonRpcMethod != null) { - type = jsonRpcMethod.getReturnType(); - if (jsonRpcMethod.getReturnTypeAdapterFactory() != null) { - TypeAdapter typeAdapter = - jsonRpcMethod - .getReturnTypeAdapterFactory() - .create(gson, TypeToken.get(type)); - try { - if (typeAdapter != null) return typeAdapter.read(in); - } catch (IOException exception) { - throw new JsonIOException(exception); - } - } - } - } - } - return fromJson(in, type); - } - - /** - * Convert the JsonElement into the result object corresponding to the call made by id. If the - * result is already converted, does nothing. - * - * @param result json element to read from - * @param id id of request message this is in response to - * @return correctly typed object if the correct expected type can be determined, or result - * unmodified if no conversion can be done. - */ - protected Object parseResult(Object result, String id) throws JsonSyntaxException { - if (result instanceof JsonElement) { - // Type of result could not be resolved - try again with the parsed JSON tree - Type type = null; - MethodProvider methodProvider = handler.getMethodProvider(); - if (methodProvider != null) { - String resolvedMethod = methodProvider.resolveMethod(id); - if (resolvedMethod != null) { - JsonRpcMethod jsonRpcMethod = handler.getJsonRpcMethod(resolvedMethod); - if (jsonRpcMethod != null) { - type = jsonRpcMethod.getReturnType(); - if (jsonRpcMethod.getReturnTypeAdapterFactory() != null) { - TypeAdapter typeAdapter = - jsonRpcMethod - .getReturnTypeAdapterFactory() - .create(gson, TypeToken.get(type)); - if (typeAdapter != null) - return typeAdapter.fromJsonTree((JsonElement) result); - } - } - } - } - return fromJson((JsonElement) result, type); - } - return result; - } - - /** - * Convert the json input into the parameters object corresponding to the call made by method. - * - *

If the method is not known until after parsing, call {@link #parseParams(Object, String)} - * on the return value of this call for a second chance conversion. - * - * @param in json input to read from - * @param method method name of request - * @return correctly typed object if the correct expected type can be determined, or a - * JsonElement representing the parameters - */ - protected Object parseParams(JsonReader in, String method) throws IOException, JsonIOException { - JsonToken next = in.peek(); - if (next == JsonToken.NULL) { - in.nextNull(); - return null; - } - Type[] parameterTypes = getParameterTypes(method); - if (parameterTypes.length == 1) { - return fromJson(in, parameterTypes[0]); - } - if (parameterTypes.length > 1 && next == JsonToken.BEGIN_ARRAY) { - List parameters = new ArrayList(parameterTypes.length); - int index = 0; - in.beginArray(); - while (in.hasNext()) { - Type parameterType = index < parameterTypes.length ? parameterTypes[index] : null; - Object parameter = fromJson(in, parameterType); - parameters.add(parameter); - index++; - } - in.endArray(); - while (index < parameterTypes.length) { - parameters.add(null); - index++; - } - return parameters; - } - JsonElement rawParams = JsonParser.parseReader(in); - if (method != null - && parameterTypes.length == 0 - && (rawParams.isJsonArray() && rawParams.getAsJsonArray().size() == 0 - || rawParams.isJsonObject() && rawParams.getAsJsonObject().size() == 0)) { - return null; - } - return rawParams; - } - - /** - * Convert the JsonElement into the parameters object corresponding to the call made by method. - * If the result is already converted, does nothing. - * - * @param params json element to read from - * @param method method name of request - * @return correctly typed object if the correct expected type can be determined, or params - * unmodified if no conversion can be done. - */ - protected Object parseParams(Object params, String method) { - if (isNull(params)) { - return null; - } - if (!(params instanceof JsonElement)) { - return params; - } - JsonElement rawParams = (JsonElement) params; - Type[] parameterTypes = getParameterTypes(method); - if (parameterTypes.length == 1) { - return fromJson(rawParams, parameterTypes[0]); - } - if (parameterTypes.length > 1 && rawParams instanceof JsonArray) { - JsonArray array = (JsonArray) rawParams; - List parameters = - new ArrayList(Math.max(array.size(), parameterTypes.length)); - int index = 0; - Iterator iterator = array.iterator(); - while (iterator.hasNext()) { - Type parameterType = index < parameterTypes.length ? parameterTypes[index] : null; - Object parameter = fromJson(iterator.next(), parameterType); - parameters.add(parameter); - index++; - } - while (index < parameterTypes.length) { - parameters.add(null); - index++; - } - return parameters; - } - if (method != null - && parameterTypes.length == 0 - && (rawParams.isJsonArray() && rawParams.getAsJsonArray().size() == 0 - || rawParams.isJsonObject() && rawParams.getAsJsonObject().size() == 0)) { - return null; - } - return rawParams; - } - - protected Object fromJson(JsonReader in, Type type) throws JsonIOException { - if (isNullOrVoidType(type)) { - return JsonParser.parseReader(in); - } - return gson.fromJson(in, type); - } - - protected Object fromJson(JsonElement element, Type type) { - if (isNull(element)) { - return null; - } - if (isNullOrVoidType(type)) { - return element; - } - Object value = gson.fromJson(element, type); - if (isNull(value)) { - return null; - } - return value; - } - - protected boolean isNull(Object value) { - return value == null || value instanceof JsonNull; - } - - protected boolean isNullOrVoidType(Type type) { - return type == null || Void.class == type; - } - - protected Type[] getParameterTypes(String method) { - if (method != null) { - JsonRpcMethod jsonRpcMethod = handler.getJsonRpcMethod(method); - if (jsonRpcMethod != null) return jsonRpcMethod.getParameterTypes(); - } - return EMPTY_TYPE_ARRAY; - } - - protected Message createMessage( - String jsonrpc, - Either id, - String method, - Object params, - Object responseResult, - ResponseError responseError) - throws JsonParseException { - if (id != null && method != null) { - RequestMessage message = new RequestMessage(); - message.setJsonrpc(jsonrpc); - message.setRawId(id); - message.setMethod(method); - message.setParams(params); - return message; - } else if (id != null) { - ResponseMessage message = new ResponseMessage(); - message.setJsonrpc(jsonrpc); - message.setRawId(id); - if (responseError != null) message.setError(responseError); - else message.setResult(responseResult); - return message; - } else if (method != null) { - NotificationMessage message = new NotificationMessage(); - message.setJsonrpc(jsonrpc); - message.setMethod(method); - message.setParams(params); - return message; - } else { - throw new JsonParseException("Unable to identify the input message."); - } - } - - public static class Factory implements TypeAdapterFactory { - - private final MessageJsonHandler handler; - - public Factory(MessageJsonHandler handler) { - this.handler = handler; - } - - @Override - @SuppressWarnings("unchecked") - public TypeAdapter create(Gson gson, TypeToken typeToken) { - if (!Message.class.isAssignableFrom(typeToken.getRawType())) return null; - return (TypeAdapter) new MessageTypeAdapter(handler, gson); - } - } -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/adapters/MessageTypeAdapterFactory.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/adapters/MessageTypeAdapterFactory.java deleted file mode 100644 index 8afa239e4..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/adapters/MessageTypeAdapterFactory.java +++ /dev/null @@ -1,26 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.json.adapters; - -import org.eclipse.lsp4j.jsonrpc.json.MessageJsonHandler; - -/** - * @deprecated Use {@link MessageTypeAdapter.Factory} instead. - */ -@Deprecated -public class MessageTypeAdapterFactory extends MessageTypeAdapter.Factory { - - public MessageTypeAdapterFactory(MessageJsonHandler handler) { - super(handler); - } - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/adapters/ThrowableTypeAdapter.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/adapters/ThrowableTypeAdapter.java deleted file mode 100644 index caaaf94eb..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/adapters/ThrowableTypeAdapter.java +++ /dev/null @@ -1,136 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2018 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.json.adapters; - -import java.io.IOException; -import java.lang.reflect.Constructor; - -import com.google.gson.Gson; -import com.google.gson.JsonParseException; -import com.google.gson.TypeAdapter; -import com.google.gson.TypeAdapterFactory; -import com.google.gson.reflect.TypeToken; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonToken; -import com.google.gson.stream.JsonWriter; - -/** - * A type adapter for {@link Throwable}. This is used to report issues to the sender of a request. - */ -public class ThrowableTypeAdapter extends TypeAdapter { - - public static class Factory implements TypeAdapterFactory { - - @SuppressWarnings({ "unchecked" }) - @Override - public TypeAdapter create(Gson gson, TypeToken typeToken) { - if (!Throwable.class.isAssignableFrom(typeToken.getRawType())) - return null; - - return (TypeAdapter) new ThrowableTypeAdapter((TypeToken) typeToken); - } - - } - - private final TypeToken typeToken; - - public ThrowableTypeAdapter(TypeToken typeToken) { - this.typeToken = typeToken; - } - - @SuppressWarnings("unchecked") - @Override - public Throwable read(JsonReader in) throws IOException { - if (in.peek() == JsonToken.NULL) { - in.nextNull(); - return null; - } - - in.beginObject(); - String message = null; - Throwable cause = null; - while (in.hasNext()) { - String name = in.nextName(); - switch (name) { - case "message": { - message = in.nextString(); - break; - } - case "cause": { - cause = read(in); - break; - } - default: - in.skipValue(); - } - } - in.endObject(); - - try { - Constructor constructor; - if (message == null && cause == null) { - constructor = (Constructor) typeToken.getRawType().getDeclaredConstructor(); - return constructor.newInstance(); - } else if (message == null) { - constructor = (Constructor) typeToken.getRawType().getDeclaredConstructor(Throwable.class); - return constructor.newInstance(cause); - } else if (cause == null) { - constructor = (Constructor) typeToken.getRawType().getDeclaredConstructor(String.class); - return constructor.newInstance(message); - } else { - constructor = (Constructor) typeToken.getRawType().getDeclaredConstructor(String.class, Throwable.class); - return constructor.newInstance(message, cause); - } - } catch (NoSuchMethodException e) { - if (message == null && cause == null) - return new RuntimeException(); - else if (message == null) - return new RuntimeException(cause); - else if (cause == null) - return new RuntimeException(message); - else - return new RuntimeException(message, cause); - } catch (Exception e) { - throw new JsonParseException(e); - } - } - - @Override - public void write(JsonWriter out, Throwable throwable) throws IOException { - if (throwable == null) { - out.nullValue(); - } else if (throwable.getMessage() == null && throwable.getCause() != null) { - write(out, throwable.getCause()); - } else { - out.beginObject(); - if (throwable.getMessage() != null) { - out.name("message"); - out.value(throwable.getMessage()); - } - if (shouldWriteCause(throwable)) { - out.name("cause"); - write(out, throwable.getCause()); - } - out.endObject(); - } - } - - private boolean shouldWriteCause(Throwable throwable) { - Throwable cause = throwable.getCause(); - if (cause == null || cause.getMessage() == null || cause == throwable) - return false; - if (throwable.getMessage() != null && throwable.getMessage().contains(cause.getMessage())) - return false; - return true; - } - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/adapters/TupleTypeAdapters.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/adapters/TupleTypeAdapters.java deleted file mode 100644 index 2214f03de..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/adapters/TupleTypeAdapters.java +++ /dev/null @@ -1,74 +0,0 @@ -package org.eclipse.lsp4j.jsonrpc.json.adapters; - -import java.io.IOException; -import java.lang.reflect.Type; - -import org.eclipse.lsp4j.jsonrpc.messages.Tuple.Two; - -import com.google.gson.Gson; -import com.google.gson.TypeAdapter; -import com.google.gson.TypeAdapterFactory; -import com.google.gson.reflect.TypeToken; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonToken; -import com.google.gson.stream.JsonWriter; - -public final class TupleTypeAdapters { - - private TupleTypeAdapters() {} - - public static class TwoTypeAdapter extends TypeAdapter> { - - protected final TypeAdapter first; - protected final TypeAdapter second; - - @SuppressWarnings("unchecked") - public TwoTypeAdapter(Gson gson, TypeToken> typeToken) { - Type[] elementTypes = TypeUtils.getElementTypes(typeToken, Two.class); - this.first = gson.getAdapter((TypeToken) TypeToken.get(elementTypes[0])); - this.second = gson.getAdapter((TypeToken) TypeToken.get(elementTypes[1])); - } - - @Override - public void write(final JsonWriter out, final Two value) throws IOException { - if (value == null) { - out.nullValue(); - } else { - out.beginArray(); - first.write(out, value.getFirst()); - second.write(out, value.getSecond()); - out.endArray(); - } - } - - @Override - public Two read(final JsonReader in) throws IOException { - JsonToken next = in.peek(); - if (next == JsonToken.NULL) { - in.nextNull(); - return null; - } - in.beginArray(); - F f = first.read(in); - S s = second.read(in); - Two result = new Two(f, s); - in.endArray(); - return result; - } - - } - - public static class TwoTypeAdapterFactory implements TypeAdapterFactory { - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Override - public TypeAdapter create(Gson gson, TypeToken typeToken) { - if (!TypeUtils.isTwoTuple(typeToken.getType())) { - return null; - } - return new TwoTypeAdapter(gson, typeToken); - } - - } - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/adapters/TypeUtils.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/adapters/TypeUtils.java deleted file mode 100644 index 11e453088..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/adapters/TypeUtils.java +++ /dev/null @@ -1,242 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2017 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.json.adapters; - -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.lang.reflect.WildcardType; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import org.eclipse.lsp4j.jsonrpc.messages.Either; -import org.eclipse.lsp4j.jsonrpc.messages.Tuple; - -import com.google.gson.reflect.TypeToken; - -/** - * Utilities for handling types in the JSON parser / serializer. - */ -public final class TypeUtils { - - private TypeUtils() {} - - /** - * Determine the actual type arguments of the given type token with regard to the given target type. - */ - public static Type[] getElementTypes(TypeToken typeToken, Class targetType) { - return getElementTypes(typeToken.getType(), typeToken.getRawType(), targetType); - } - - private static Type[] getElementTypes(Type type, Class rawType, Class targetType) { - if (targetType.equals(rawType) && type instanceof ParameterizedType) { - Type mappedType; - if (type instanceof ParameterizedTypeImpl) - mappedType = type; - else - // Transform wildcards in the actual type arguments - mappedType = getMappedType(type, Collections.emptyMap()); - return ((ParameterizedType) mappedType).getActualTypeArguments(); - } - // Map the parameters of the raw type to the actual type arguments - Map varMapping = createVariableMapping(type, rawType); - if (targetType.isInterface()) { - // Look for superinterfaces that extend the target interface - Class[] interfaces = rawType.getInterfaces(); - for (int i = 0; i < interfaces.length; i++) { - if (Collection.class.isAssignableFrom(interfaces[i])) { - Type genericInterface = rawType.getGenericInterfaces()[i]; - Type mappedInterface = getMappedType(genericInterface, varMapping); - return getElementTypes(mappedInterface, interfaces[i], targetType); - } - } - } - if (!rawType.isInterface()) { - // Visit the superclass if it extends the target class / implements the target interface - Class rawSupertype = rawType.getSuperclass(); - if (targetType.isAssignableFrom(rawSupertype)) { - Type genericSuperclass = rawType.getGenericSuperclass(); - Type mappedSuperclass = getMappedType(genericSuperclass, varMapping); - return getElementTypes(mappedSuperclass, rawSupertype, targetType); - } - } - // No luck, return an array of Object types - Type[] result = new Type[targetType.getTypeParameters().length]; - Arrays.fill(result, Object.class); - return result; - } - - private static Map createVariableMapping(Type type, Class rawType) { - if (type instanceof ParameterizedType) { - TypeVariable>[] vars = rawType.getTypeParameters(); - Type[] args = ((ParameterizedType) type).getActualTypeArguments(); - Map newVarMapping = new HashMap<>(capacity(vars.length)); - for (int i = 0; i < vars.length; i++) { - Type actualType = Object.class; - if (i < args.length) { - actualType = args[i]; - if (actualType instanceof WildcardType) - actualType = ((WildcardType) actualType).getUpperBounds()[0]; - } - newVarMapping.put(vars[i].getName(), actualType); - } - return newVarMapping; - } - return Collections.emptyMap(); - } - - private static int capacity(int expectedSize) { - if (expectedSize < 3) - return expectedSize + 1; - else - return expectedSize + expectedSize / 3; - } - - private static Type getMappedType(Type type, Map varMapping) { - if (type instanceof TypeVariable) { - String name = ((TypeVariable) type).getName(); - if (varMapping.containsKey(name)) - return varMapping.get(name); - } - if (type instanceof WildcardType) { - return getMappedType(((WildcardType) type).getUpperBounds()[0], varMapping); - } - if (type instanceof ParameterizedType) { - ParameterizedType pt = (ParameterizedType) type; - Type[] origArgs = pt.getActualTypeArguments(); - Type[] mappedArgs = new Type[origArgs.length]; - for (int i = 0; i < origArgs.length; i++) { - mappedArgs[i] = getMappedType(origArgs[i], varMapping); - } - return new ParameterizedTypeImpl(pt, mappedArgs); - } - return type; - } - - private static class ParameterizedTypeImpl implements ParameterizedType { - - private final Type ownerType; - private final Type rawType; - private final Type[] actualTypeArguments; - - ParameterizedTypeImpl(ParameterizedType original, Type[] typeArguments) { - this(original.getOwnerType(), original.getRawType(), typeArguments); - } - - ParameterizedTypeImpl(Type ownerType, Type rawType, Type[] typeArguments) { - this.ownerType = ownerType; - this.rawType = rawType; - this.actualTypeArguments = typeArguments; - } - - @Override - public Type getOwnerType() { - return ownerType; - } - - @Override - public Type getRawType() { - return rawType; - } - - @Override - public Type[] getActualTypeArguments() { - return actualTypeArguments; - } - - @Override - public String toString() { - StringBuilder result = new StringBuilder(); - if (ownerType != null) { - result.append(toString(ownerType)); - result.append('$'); - } - result.append(toString(rawType)); - result.append('<'); - for (int i = 0; i < actualTypeArguments.length; i++) { - if (i > 0) - result.append(", "); - result.append(toString(actualTypeArguments[i])); - } - result.append('>'); - return result.toString(); - } - - private String toString(Type type) { - if (type instanceof Class) - return ((Class) type).getName(); - else - return String.valueOf(type); - } - - } - - /** - * Return all possible types that can be expected when an element of the given type is parsed. - * If the type satisfies {@link #isEither(Type)}, a list of the corresponding type arguments is returned, - * otherwise a list containg the type itself is returned. Type parameters are not resolved - * by this method (use {@link #getElementTypes(TypeToken, Class)} to get resolved parameters). - */ - public static Collection getExpectedTypes(Type type) { - Collection result = new ArrayList<>(); - collectExpectedTypes(type, result); - return result; - } - - private static void collectExpectedTypes(Type type, Collection types) { - if (isEither(type)) { - if (type instanceof ParameterizedType) { - for (Type typeArgument : ((ParameterizedType) type).getActualTypeArguments()) { - collectExpectedTypes(typeArgument, types); - } - } - if (type instanceof Class) { - for (Type typeParameter : ((Class) type).getTypeParameters()) { - collectExpectedTypes(typeParameter, types); - } - } - } else { - types.add(type); - } - } - - /** - * Test whether the given type is Either. - */ - public static boolean isEither(Type type) { - if (type instanceof ParameterizedType) { - return isEither(((ParameterizedType) type).getRawType()); - } - if (type instanceof Class) { - return Either.class.isAssignableFrom((Class) type); - } - return false; - } - - /** - * Test whether the given type is a two-tuple (pair). - */ - public static boolean isTwoTuple(Type type) { - if (type instanceof ParameterizedType) { - return isTwoTuple(((ParameterizedType) type).getRawType()); - } - if (type instanceof Class) { - return Tuple.Two.class.isAssignableFrom((Class) type); - } - return false; - } - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/messages/CancelParams.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/messages/CancelParams.java deleted file mode 100644 index 2c6a35ff6..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/messages/CancelParams.java +++ /dev/null @@ -1,86 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.messages; - -import org.eclipse.lsp4j.jsonrpc.json.MessageJsonHandler; -import org.eclipse.lsp4j.jsonrpc.validation.NonNull; - -/** - * To cancel a request a notification message with the following properties is sent. - */ -public class CancelParams { - - /** - * The request id to cancel. - */ - @NonNull - private Either id; - - @NonNull - public String getId() { - if (id == null) - return null; - if (id.isLeft()) - return id.getLeft(); - if (id.isRight()) - return id.getRight().toString(); - return null; - } - - @NonNull - public Either getRawId() { - return id; - } - - public void setId(@NonNull String id) { - this.id = Either.forLeft(id); - } - - public void setId(@NonNull int id) { - this.id = Either.forRight(id); - } - - public void setRawId(@NonNull Either id) { - this.id = id; - } - - @Override - public String toString() { - return MessageJsonHandler.toString(this); - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - CancelParams other = (CancelParams) obj; - if (this.id == null) { - if (other.id != null) - return false; - } else if (!this.id.equals(other.id)) - return false; - return true; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((this.id == null) ? 0 : this.id.hashCode()); - return result; - } - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/messages/Either.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/messages/Either.java deleted file mode 100644 index 0b5f48447..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/messages/Either.java +++ /dev/null @@ -1,223 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.messages; - -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Collection; -import java.util.function.Function; - -import org.eclipse.lsp4j.jsonrpc.validation.NonNull; - -/** - * An either type maps union types in protocol specifications. - */ -public class Either { - - public static Either forLeft(@NonNull L left) { - return new Either<>(left, null); - } - - public static Either forRight(@NonNull R right) { - return new Either<>(null, right); - } - - private final L left; - private final R right; - - protected Either(L left, R right) { - super(); - this.left = left; - this.right = right; - } - - public L getLeft() { - return left; - } - - public R getRight() { - return right; - } - - public Object get() { - if (left != null) - return left; - if (right != null) - return right; - return null; - } - - public boolean isLeft() { - return left != null; - } - - public boolean isRight() { - return right != null; - } - - public T map( - @NonNull Function mapLeft, - @NonNull Function mapRight) { - if (isLeft()) { - return mapLeft.apply(getLeft()); - } - if (isRight()) { - return mapRight.apply(getRight()); - } - return null; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof Either) { - Either other = (Either) obj; - return (this.left == other.left && this.right == other.right) - || (this.left != null && other.left != null && this.left.equals(other.left)) - || (this.right != null && other.right != null && this.right.equals(other.right)); - } - return false; - } - - @Override - public int hashCode() { - if (this.left != null) - return this.left.hashCode(); - if (this.right != null) - return this.right.hashCode(); - return 0; - } - - public String toString() { - StringBuilder builder = new StringBuilder("Either [").append(System.lineSeparator()); - builder.append(" left = ").append(left).append(System.lineSeparator()); - builder.append(" right = ").append(right).append(System.lineSeparator()); - return builder.append("]").toString(); - } - - /** - * Return a left disjoint type if the given type is either. - * - * @deprecated Use {@link org.eclipse.lsp4j.jsonrpc.json.adapters.TypeUtils#getElementTypes(Type, Class, Class)} instead - */ - @Deprecated - public static Type getLeftDisjointType(Type type) { - if (isEither(type)) { - if (type instanceof ParameterizedType) { - final ParameterizedType parameterizedType = (ParameterizedType) type; - return parameterizedType.getActualTypeArguments()[0]; - } - if (type instanceof Class) { - final Class cls = (Class) type; - return cls.getTypeParameters()[0]; - } - } - return null; - } - - /** - * Return a right disjoint type if the given type is either. - * - * @deprecated Use {@link org.eclipse.lsp4j.jsonrpc.json.adapters.TypeUtils#getElementTypes(Type, Class, Class)} instead - */ - @Deprecated - public static Type getRightDisjointType(Type type) { - if (isEither(type)) { - if (type instanceof ParameterizedType) { - final ParameterizedType parameterizedType = (ParameterizedType) type; - return parameterizedType.getActualTypeArguments()[1]; - } - if (type instanceof Class) { - final Class cls = (Class) type; - return cls.getTypeParameters()[1]; - } - } - return null; - } - - /** - * Return all disjoint types. - * - * @deprecated Use {@link org.eclipse.lsp4j.jsonrpc.json.adapters.TypeUtils#getExpectedTypes(Type)} instead - */ - @Deprecated - public static Collection getAllDisjoinTypes(Type type) { - return collectDisjoinTypes(type, new ArrayList<>()); - } - - @Deprecated - protected static Collection collectDisjoinTypes(Type type, Collection types) { - if (isEither(type)) { - if (type instanceof ParameterizedType) { - return collectDisjoinTypes((ParameterizedType) type, types); - } - if (type instanceof Class) { - return collectDisjoinTypes((Class) type, types); - } - } - types.add(type); - return types; - } - - @Deprecated - protected static Collection collectDisjoinTypes(ParameterizedType type, Collection types) { - for (Type typeArgument : type.getActualTypeArguments()) { - collectDisjoinTypes(typeArgument, types); - } - return types; - } - - @Deprecated - protected static Collection collectDisjoinTypes(Class type, Collection types) { - for (Type typeParameter : type.getTypeParameters()) { - collectDisjoinTypes(typeParameter, types); - } - return types; - } - - /** - * Test whether the given type is Either. - * - * @deprecated Use {@link org.eclipse.lsp4j.jsonrpc.json.adapters.TypeUtils#isEither(Type)} instead - */ - @Deprecated - public static boolean isEither(Type type) { - if (type instanceof ParameterizedType) { - return isEither((ParameterizedType) type); - } - if (type instanceof Class) { - return isEither((Class) type); - } - return false; - } - - /** - * Test whether the given type is Either. - * - * @deprecated Use {@link org.eclipse.lsp4j.jsonrpc.json.adapters.TypeUtils#isEither(Type)} instead - */ - @Deprecated - public static boolean isEither(ParameterizedType type) { - return isEither(type.getRawType()); - } - - /** - * Test whether the given class is Either. - * - * @deprecated Use {@link org.eclipse.lsp4j.jsonrpc.json.adapters.TypeUtils#isEither(Type)} instead - */ - @Deprecated - public static boolean isEither(Class cls) { - return Either.class.isAssignableFrom(cls); - } - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/messages/Either3.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/messages/Either3.java deleted file mode 100644 index 81f385ec2..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/messages/Either3.java +++ /dev/null @@ -1,111 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2017 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.messages; - -import java.util.function.Function; - -import org.eclipse.lsp4j.jsonrpc.validation.NonNull; - -/** - * Union type for three types. - */ -public class Either3 extends Either> { - - public static Either3 forFirst(@NonNull T1 first) { - return new Either3(first, null); - } - - public static Either3 forSecond(@NonNull T2 second) { - return new Either3(null, new Either(second, null)); - } - - public static Either3 forThird(@NonNull T3 third) { - return new Either3(null, new Either(null, third)); - } - - public static Either3 forLeft3(@NonNull T1 first) { - return new Either3(first, null); - } - - public static Either3 forRight3(@NonNull Either right) { - return new Either3(null, right); - } - - protected Either3(T1 left, Either right) { - super(left, right); - } - - public T1 getFirst() { - return getLeft(); - } - - public T2 getSecond() { - Either right = getRight(); - if (right == null) - return null; - else - return right.getLeft(); - } - - public T3 getThird() { - Either right = getRight(); - if (right == null) - return null; - else - return right.getRight(); - } - - @Override - public Object get() { - if (isRight()) - return getRight().get(); - return super.get(); - } - - public boolean isFirst() { - return isLeft(); - } - - public boolean isSecond() { - return isRight() && getRight().isLeft(); - } - - public boolean isThird() { - return isRight() && getRight().isRight(); - } - - public T map( - @NonNull Function mapFirst, - @NonNull Function mapSecond, - @NonNull Function mapThird) { - if (isFirst()) { - return mapFirst.apply(getFirst()); - } - if (isSecond()) { - return mapSecond.apply(getSecond()); - } - if (isThird()) { - return mapThird.apply(getThird()); - } - return null; - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder("Either3 [").append(System.lineSeparator()); - builder.append(" first = ").append(getFirst()).append(System.lineSeparator()); - builder.append(" second = ").append(getSecond()).append(System.lineSeparator()); - builder.append(" third = ").append(getThird()).append(System.lineSeparator()); - return builder.append("]").toString(); - } - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/messages/IdentifiableMessage.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/messages/IdentifiableMessage.java deleted file mode 100644 index 61faf65a4..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/messages/IdentifiableMessage.java +++ /dev/null @@ -1,81 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2018 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.messages; - -import org.eclipse.lsp4j.jsonrpc.validation.NonNull; - -/** - * A message with an {@code id} property. - */ -public abstract class IdentifiableMessage extends Message { - - /** - * The message identifier. - */ - @NonNull - private Either id; - - public String getId() { - if (id == null) - return null; - if (id.isLeft()) - return id.getLeft(); - if (id.isRight()) - return id.getRight().toString(); - return null; - } - - @NonNull - public Either getRawId() { - return id; - } - - public void setId(String id) { - this.id = Either.forLeft(id); - } - - public void setId(int id) { - this.id = Either.forRight(id); - } - - public void setRawId(@NonNull Either id) { - this.id = id; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - if (!super.equals(obj)) - return false; - IdentifiableMessage other = (IdentifiableMessage) obj; - if (this.id == null) { - if (other.id != null) - return false; - } else if (!this.id.equals(other.id)) - return false; - return true; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + ((this.id == null) ? 0 : this.id.hashCode()); - return result; - } - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/messages/Message.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/messages/Message.java deleted file mode 100644 index 5d4be746c..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/messages/Message.java +++ /dev/null @@ -1,66 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.messages; - -import org.eclipse.lsp4j.jsonrpc.json.MessageConstants; -import org.eclipse.lsp4j.jsonrpc.json.MessageJsonHandler; -import org.eclipse.lsp4j.jsonrpc.validation.NonNull; - -/** - * A general message as defined by JSON-RPC. The language server protocol always - * uses "2.0" as the jsonrpc version. - */ -public abstract class Message { - - @NonNull - private String jsonrpc = MessageConstants.JSONRPC_VERSION; - - @NonNull - public String getJsonrpc() { - return this.jsonrpc; - } - - public void setJsonrpc(@NonNull String jsonrpc) { - this.jsonrpc = jsonrpc; - } - - @Override - public String toString() { - return MessageJsonHandler.toString(this); - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Message other = (Message) obj; - if (this.jsonrpc == null) { - if (other.jsonrpc != null) - return false; - } else if (!this.jsonrpc.equals(other.jsonrpc)) - return false; - return true; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((this.jsonrpc == null) ? 0 : this.jsonrpc.hashCode()); - return result; - } - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/messages/MessageIssue.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/messages/MessageIssue.java deleted file mode 100644 index 122025532..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/messages/MessageIssue.java +++ /dev/null @@ -1,60 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2018 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.messages; - -import org.eclipse.lsp4j.jsonrpc.validation.NonNull; - -/** - * Describes an issue found while parsing or validating a message. - */ -public class MessageIssue { - - @NonNull - private String text; - - private int code; - - private Exception cause; - - public MessageIssue(@NonNull String text) { - this(text, 0, null); - } - - public MessageIssue(@NonNull String text, int code) { - this(text, code, null); - } - - public MessageIssue(@NonNull String text, int code, Exception cause) { - this.text = text; - this.code = code; - this.cause = cause; - } - - @NonNull - public String getText() { - return text; - } - - public int getIssueCode() { - return code; - } - - public Exception getCause() { - return cause; - } - - @Override - public String toString() { - return getText(); - } - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/messages/NotificationMessage.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/messages/NotificationMessage.java deleted file mode 100644 index b10f9d465..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/messages/NotificationMessage.java +++ /dev/null @@ -1,83 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.messages; - -import org.eclipse.lsp4j.jsonrpc.validation.NonNull; - -/** - * A notification message. A processed notification message must not send a - * response back. They work like events. - */ -public class NotificationMessage extends Message { - - /** - * The method to be invoked. - */ - @NonNull - private String method; - - @NonNull - public String getMethod() { - return this.method; - } - - public void setMethod(@NonNull String method) { - this.method = method; - } - - /** - * The method's params. - */ - private Object params; - - public Object getParams() { - return this.params; - } - - public void setParams(Object params) { - this.params = params; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - if (!super.equals(obj)) - return false; - NotificationMessage other = (NotificationMessage) obj; - if (this.method == null) { - if (other.method != null) - return false; - } else if (!this.method.equals(other.method)) - return false; - if (this.params == null) { - if (other.params != null) - return false; - } else if (!this.params.equals(other.params)) - return false; - return true; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + ((this.method == null) ? 0 : this.method.hashCode()); - result = prime * result + ((this.params == null) ? 0 : this.params.hashCode()); - return result; - } - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/messages/RequestMessage.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/messages/RequestMessage.java deleted file mode 100644 index 42d76c26e..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/messages/RequestMessage.java +++ /dev/null @@ -1,84 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.messages; - -import org.eclipse.lsp4j.jsonrpc.validation.NonNull; - -/** - * A request message to describe a request between the client and the server. - * Every processed request must send a response back to the sender of the - * request. - */ -public class RequestMessage extends IdentifiableMessage { - - /** - * The method to be invoked. - */ - @NonNull - private String method; - - @NonNull - public String getMethod() { - return this.method; - } - - public void setMethod(@NonNull String method) { - this.method = method; - } - - /** - * The method's parameters. The object type depends on the chosen method. - */ - private Object params; - - public Object getParams() { - return this.params; - } - - public void setParams(Object params) { - this.params = params; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - if (!super.equals(obj)) - return false; - RequestMessage other = (RequestMessage) obj; - if (this.method == null) { - if (other.method != null) - return false; - } else if (!this.method.equals(other.method)) - return false; - if (this.params == null) { - if (other.params != null) - return false; - } else if (!this.params.equals(other.params)) - return false; - return true; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + ((this.method == null) ? 0 : this.method.hashCode()); - result = prime * result + ((this.params == null) ? 0 : this.params.hashCode()); - return result; - } - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/messages/ResponseError.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/messages/ResponseError.java deleted file mode 100644 index 64b8888d5..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/messages/ResponseError.java +++ /dev/null @@ -1,123 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.messages; - -import org.eclipse.lsp4j.jsonrpc.json.MessageJsonHandler; -import org.eclipse.lsp4j.jsonrpc.json.adapters.JsonElementTypeAdapter; -import org.eclipse.lsp4j.jsonrpc.validation.NonNull; - -import com.google.gson.annotations.JsonAdapter; - -public class ResponseError { - - /** - * A number indicating the error type that occurred. - */ - @NonNull - private int code; - - @NonNull - public int getCode() { - return this.code; - } - - public void setCode(@NonNull int code) { - this.code = code; - } - - public void setCode(ResponseErrorCode code) { - this.setCode(code.getValue()); - } - - /** - * A string providing a short description of the error. - */ - @NonNull - private String message; - - @NonNull - public String getMessage() { - return this.message; - } - - public void setMessage(@NonNull String message) { - this.message = message; - } - - /** - * A Primitive or Structured value that contains additional information - * about the error. Can be omitted. - */ - @JsonAdapter(JsonElementTypeAdapter.Factory.class) - private Object data; - - public Object getData() { - return this.data; - } - - public void setData(Object data) { - this.data = data; - } - - public ResponseError() { - } - - public ResponseError(ResponseErrorCode code, String message, Object data) { - this(code.getValue(), message, data); - } - - public ResponseError(int code, String message, Object data) { - this.code = code; - this.message = message; - this.data = data; - } - - @Override - public String toString() { - return MessageJsonHandler.toString(this); - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - ResponseError other = (ResponseError) obj; - if (other.code != this.code) - return false; - if (this.message == null) { - if (other.message != null) - return false; - } else if (!this.message.equals(other.message)) - return false; - if (this.data == null) { - if (other.data != null) - return false; - } else if (!this.data.equals(other.data)) - return false; - return true; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + this.code; - result = prime * result + ((this.message == null) ? 0 : this.message.hashCode()); - result = prime * result + ((this.data == null) ? 0 : this.data.hashCode()); - return result; - } - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/messages/ResponseErrorCode.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/messages/ResponseErrorCode.java deleted file mode 100644 index 14761c8cf..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/messages/ResponseErrorCode.java +++ /dev/null @@ -1,129 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.messages; - -/** - * A number indicating the error type that occurred. - */ -public enum ResponseErrorCode { - - ParseError(-32700), - - InvalidRequest(-32600), - - MethodNotFound(-32601), - - InvalidParams(-32602), - - InternalError(-32603), - - /** - * This is the start range of JSON RPC reserved error codes. - * It doesn't denote a real error code. No LSP error codes should - * be defined between the start and end range. For backwards - * compatibility the {@link #serverNotInitialized} and the - * {@link #UnknownErrorCode} are left in the range. - *

- * Since 3.16.0 - */ - jsonrpcReservedErrorRangeStart(-32099), - - /** @deprecated use {@link #jsonrpcReservedErrorRangeStart} */ - @Deprecated - serverErrorStart(-32099), - - /** - * Error code indicating that a server received a notification or - * request before the server has received the {@code initialize} request. - *

- * Should be {@code ServerNotInitialized} - */ - serverNotInitialized(-32002), - - UnknownErrorCode(-32001), - - /** - * This is the end range of JSON RPC reserved error codes. - * It doesn't denote a real error code. - *

- * Since 3.16.0 - */ - jsonrpcReservedErrorRangeEnd(-32000), - - /** @deprecated use {@link #jsonrpcReservedErrorRangeEnd} */ - @Deprecated - serverErrorEnd(-32000), - - /** - * This is the start range of LSP reserved error codes. - * It doesn't denote a real error code. - *

- * Since 3.16.0 - */ - lspReservedErrorRangeStart(-32899), - - /** - * A request failed but it was syntactically correct, e.g the - * method name was known and the parameters were valid. The error - * message should contain human readable information about why - * the request failed. - *

- * Since 3.17.0 - */ - RequestFailed(-32803), - - /** - * The server cancelled the request. This error code should - * only be used for requests that explicitly support being - * server cancellable. - *

- * Since 3.17.0 - */ - ServerCancelled(-32802), - - /** - * The server detected that the content of a document got - * modified outside normal conditions. A server should - * NOT send this error code if it detects a content change - * in it unprocessed messages. The result even computed - * on an older state might still be useful for the client. - *

- * If a client decides that a result is not of any use anymore - * the client should cancel the request. - */ - ContentModified(-32801), - - /** - * The client has canceled a request and a server as detected - * the cancel. - */ - RequestCancelled(-32800), - - /** - * This is the end range of LSP reserved error codes. - * It doesn't denote a real error code. - *

- * Since 3.16.0 - */ - lspReservedErrorRangeEnd(-32800); - - private final int value; - - ResponseErrorCode(int value) { - this.value = value; - } - - public int getValue() { - return value; - } - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/messages/ResponseMessage.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/messages/ResponseMessage.java deleted file mode 100644 index baf33e3b9..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/messages/ResponseMessage.java +++ /dev/null @@ -1,83 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.messages; - -/** - * Response message sent as a result of a request. If a request doesn't provide - * a result value the receiver of a request still needs to return a response - * message to conform to the JSON RPC specification. The result property of the - * ResponseMessage should be set to null in this case to signal a successful - * request. A response message is linked to a request via their {@code id} properties. - */ -public class ResponseMessage extends IdentifiableMessage { - - /** - * The result of a request. This can be omitted in the case of an error. - * The object type depends on the method of the corresponding request. - */ - private Object result; - - public Object getResult() { - return this.result; - } - - public void setResult(Object result) { - this.result = result; - } - - /** - * The error object in case a request fails. - */ - private ResponseError error; - - public ResponseError getError() { - return this.error; - } - - public void setError(ResponseError error) { - this.error = error; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - if (!super.equals(obj)) - return false; - ResponseMessage other = (ResponseMessage) obj; - if (this.result == null) { - if (other.result != null) - return false; - } else if (!this.result.equals(other.result)) - return false; - if (this.error == null) { - if (other.error != null) - return false; - } else if (!this.error.equals(other.error)) - return false; - return true; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + ((this.result == null) ? 0 : this.result.hashCode()); - result = prime * result + ((this.error == null) ? 0 : this.error.hashCode()); - return result; - } - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/messages/Tuple.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/messages/Tuple.java deleted file mode 100644 index 03618ceb0..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/messages/Tuple.java +++ /dev/null @@ -1,81 +0,0 @@ -package org.eclipse.lsp4j.jsonrpc.messages; - -import java.io.IOException; - -import org.eclipse.lsp4j.jsonrpc.validation.NonNull; - -import com.google.gson.TypeAdapter; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonWriter; - -/** - * Representation of tuple types. - */ -@SuppressWarnings("all") -public interface Tuple { - - public static Two two(F first, S second) { - return new Two(first, second); - } - - /** - * A two-tuple, i.e. a pair. - */ - public static class Two implements Tuple { - - private final F first; - private final S second; - - public Two(F first, S second) { - this.first = first; - this.second = second; - } - - public F getFirst() { - return this.first; - } - - public S getSecond() { - return this.second; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Tuple.Two other = (Tuple.Two) obj; - if (this.first == null) { - if (other.first != null) - return false; - } else if (!this.first.equals(other.first)) - return false; - if (this.second == null) { - if (other.second != null) - return false; - } else if (!this.second.equals(other.second)) - return false; - return true; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((this.first == null) ? 0 : this.first.hashCode()); - return prime * result + ((this.second == null) ? 0 : this.second.hashCode()); - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder("Tuples.Two [").append(System.lineSeparator()); - builder.append(" first = ").append(first).append(System.lineSeparator()); - builder.append(" second = ").append(second).append(System.lineSeparator()); - return builder.append("]").toString(); - } - } - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/services/AnnotationUtil.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/services/AnnotationUtil.java deleted file mode 100644 index 48f6fc2f3..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/services/AnnotationUtil.java +++ /dev/null @@ -1,131 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.services; - -import java.lang.reflect.Method; -import java.lang.reflect.Type; -import java.util.Arrays; -import java.util.Set; -import java.util.function.Consumer; - -public final class AnnotationUtil { - private AnnotationUtil() {} - - public static void findDelegateSegments(Class clazz, Set> visited, Consumer acceptor) { - if (clazz == null || !visited.add(clazz)) - return; - findDelegateSegments(clazz.getSuperclass(), visited, acceptor); - for (Class interf : clazz.getInterfaces()) { - findDelegateSegments(interf, visited, acceptor); - } - for (Method method : clazz.getDeclaredMethods()) { - if (isDelegateMethod(method)) { - acceptor.accept(method); - } - } - } - - public static boolean isDelegateMethod(Method method) { - if (!method.isSynthetic()) { - JsonDelegate jsonDelegate = method.getAnnotation(JsonDelegate.class); - if (jsonDelegate != null) { - if (!(method.getParameterCount() == 0 && method.getReturnType().isInterface())) { - throw new IllegalStateException( - "The method " + method.toString() + " is not a proper @JsonDelegate method."); - } - return true; - } - } - return false; - } - - - /** - * Depth first search for annotated methods in hierarchy. - */ - public static void findRpcMethods(Class clazz, Set> visited, Consumer acceptor) { - if (clazz == null || !visited.add(clazz)) - return; - findRpcMethods(clazz.getSuperclass(), visited, acceptor); - for (Class interf : clazz.getInterfaces()) { - findRpcMethods(interf, visited, acceptor); - } - String segment = getSegment(clazz); - for (Method method : clazz.getDeclaredMethods()) { - MethodInfo methodInfo = createMethodInfo(method, segment); - if (methodInfo != null) { - acceptor.accept(methodInfo); - } - } - } - - protected static String getSegment(Class clazz) { - JsonSegment jsonSegment = clazz.getAnnotation(JsonSegment.class); - return jsonSegment == null ? "" : jsonSegment.value() + "/"; - } - - protected static MethodInfo createMethodInfo(Method method, String segment) { - if (!method.isSynthetic()) { - JsonRequest jsonRequest = method.getAnnotation(JsonRequest.class); - if (jsonRequest != null) { - return createRequestInfo(method, segment, jsonRequest); - } - JsonNotification jsonNotification = method.getAnnotation(JsonNotification.class); - if (jsonNotification != null) { - return createNotificationInfo(method, segment, jsonNotification); - } - } - return null; - } - - protected static MethodInfo createNotificationInfo(Method method, String segment, JsonNotification jsonNotification) { - MethodInfo methodInfo = createMethodInfo(method, jsonNotification.useSegment(), segment, jsonNotification.value()); - methodInfo.isNotification = true; - return methodInfo; - } - - protected static MethodInfo createRequestInfo(Method method, String segment, JsonRequest jsonRequest) { - return createMethodInfo(method, jsonRequest.useSegment(), segment, jsonRequest.value()); - } - - protected static MethodInfo createMethodInfo(Method method, boolean useSegment, String segment, String value) { - method.setAccessible(true); - - MethodInfo methodInfo = new MethodInfo(); - methodInfo.method = method; - methodInfo.parameterTypes = getParameterTypes(method); - methodInfo.name = getMethodName(method, useSegment, segment, value); - return methodInfo; - } - - protected static String getMethodName(Method method, boolean useSegment, String segment, String value) { - String name = value != null && value.length() > 0 ? value : method.getName(); - return useSegment ? segment + name : name; - } - - protected static Type[] getParameterTypes(Method method) { - return Arrays.stream(method.getParameters()).map(t -> t.getParameterizedType()).toArray(Type[]::new); - } - - static class MethodInfo { - private static Type[] EMPTY_TYPE_ARRAY = {}; - public String name; - public Method method; - public Type[] parameterTypes = EMPTY_TYPE_ARRAY; - public boolean isNotification = false; - } - - static class DelegateInfo { - public Method method; - public Object delegate; - } -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/services/EndpointProxy.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/services/EndpointProxy.java deleted file mode 100644 index bb1609c78..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/services/EndpointProxy.java +++ /dev/null @@ -1,130 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.services; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.LinkedHashMap; - -import org.eclipse.lsp4j.jsonrpc.Endpoint; -import org.eclipse.lsp4j.jsonrpc.services.AnnotationUtil.DelegateInfo; -import org.eclipse.lsp4j.jsonrpc.services.AnnotationUtil.MethodInfo; - -/** - * A Proxy that wraps an {@link Endpoint} in one or more service interfaces, i.e. interfaces - * containing {@link JsonNotification} and {@link JsonRequest} methods. - */ -public class EndpointProxy implements InvocationHandler { - - private final Method object_equals; - private final Method object_hashCode; - private final Method object_toString; - - private final Endpoint delegate; - private final LinkedHashMap methodInfos; - private final LinkedHashMap delegatedSegments; - - public EndpointProxy(Endpoint delegate, Class interface_) { - this(delegate, Collections.singletonList(interface_)); - } - - public EndpointProxy(Endpoint delegate, Collection> interfaces) { - if (delegate == null) - throw new NullPointerException("delegate"); - if (interfaces == null) - throw new NullPointerException("interfaces"); - if (interfaces.isEmpty()) - throw new IllegalArgumentException("interfaces must not be empty."); - - this.delegate = delegate; - try { - object_equals = Object.class.getDeclaredMethod("equals", Object.class); - object_hashCode = Object.class.getDeclaredMethod("hashCode"); - object_toString = Object.class.getDeclaredMethod("toString"); - } catch (NoSuchMethodException | SecurityException exception) { - throw new RuntimeException(exception); - } - methodInfos = new LinkedHashMap<>(); - delegatedSegments = new LinkedHashMap<>(); - for (Class interf : interfaces) { - AnnotationUtil.findRpcMethods(interf, new HashSet>(), (methodInfo) -> { - if (methodInfos.put(methodInfo.method.getName(), methodInfo) != null) { - throw new IllegalStateException("Duplicate RPC method " + methodInfo.method); - } - }); - AnnotationUtil.findDelegateSegments(interf, new HashSet>(), (method) -> { - Object delegateProxy = ServiceEndpoints.toServiceObject(delegate, method.getReturnType()); - DelegateInfo info = new DelegateInfo(); - info.delegate = delegateProxy; - info.method = method; - if (delegatedSegments.put(method.getName(), info) != null) { - throw new IllegalStateException("Duplicate RPC method " + method); - } - }); - } - } - - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - args = args == null ? new Object[0] : args; - MethodInfo methodInfo = this.methodInfos.get(method.getName()); - if (methodInfo != null) { - Object params = getParams(args, methodInfo); - if (methodInfo.isNotification) { - delegate.notify(methodInfo.name, params); - return null; - } - return delegate.request(methodInfo.name, params); - } - DelegateInfo delegateInfo = this.delegatedSegments.get(method.getName()); - if (delegateInfo != null) { - return delegateInfo.delegate; - } - if (object_equals.equals(method) && args.length == 1) { - if(args[0] != null ) { - try { - return this.equals(Proxy.getInvocationHandler(args[0])); - } catch (IllegalArgumentException exception) { - } - } - return this.equals(args[0]); - } - if (object_hashCode.equals(method)) { - return this.hashCode(); - } - if (object_toString.equals(method)) { - return this.toString(); - } - return method.invoke(delegate, args); - } - - protected Object getParams(Object[] args, MethodInfo methodInfo) { - if (args.length == 0) { - return null; - } - if (args.length == 1) { - return args[0]; - } - return Arrays.asList(args); - } - - @Override - public String toString() { - return getClass().getSimpleName() + " for " + delegate.toString(); - } - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/services/GenericEndpoint.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/services/GenericEndpoint.java deleted file mode 100644 index 918c0d8dd..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/services/GenericEndpoint.java +++ /dev/null @@ -1,180 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.services; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.function.Function; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.stream.Stream; - -import org.eclipse.lsp4j.jsonrpc.Endpoint; -import org.eclipse.lsp4j.jsonrpc.ResponseErrorException; -import org.eclipse.lsp4j.jsonrpc.messages.ResponseError; -import org.eclipse.lsp4j.jsonrpc.messages.ResponseErrorCode; - -/** - * An endpoint that reflectively delegates to {@link JsonNotification} and - * {@link JsonRequest} methods of one or more given delegate objects. - */ -public class GenericEndpoint implements Endpoint { - - private static final Logger LOG = Logger.getLogger(GenericEndpoint.class.getName()); - private static final Object[] NO_ARGUMENTS = {}; - - private final LinkedHashMap>> methodHandlers = new LinkedHashMap<>(); - private final List delegates; - - public GenericEndpoint(Object delegate) { - this.delegates = Collections.singletonList(delegate); - recursiveFindRpcMethods(delegate, new HashSet<>(), new HashSet<>()); - } - - public GenericEndpoint(Collection delegates) { - this.delegates = new ArrayList<>(delegates); - for (Object delegate : this.delegates) { - recursiveFindRpcMethods(delegate, new HashSet<>(), new HashSet<>()); - } - } - - protected void recursiveFindRpcMethods(Object current, Set> visited, Set> visitedForDelegate) { - AnnotationUtil.findRpcMethods(current.getClass(), visited, (methodInfo) -> { - @SuppressWarnings("unchecked") - Function> handler = (arg) -> { - try { - Method method = methodInfo.method; - Object[] arguments = this.getArguments(method, arg); - return (CompletableFuture) method.invoke(current, arguments); - } catch (InvocationTargetException | IllegalAccessException e) { - throw new RuntimeException(e); - } - }; - if (methodHandlers.put(methodInfo.name, handler) != null) { - throw new IllegalStateException("Multiple methods for name " + methodInfo.name); - } - }); - AnnotationUtil.findDelegateSegments(current.getClass(), visitedForDelegate, (method) -> { - try { - Object delegate = method.invoke(current); - if (delegate != null) { - recursiveFindRpcMethods(delegate, visited, visitedForDelegate); - } else { - LOG.log(Level.SEVERE, "A delegate object is null, jsonrpc methods of '" + method + "' are ignored"); - } - } catch (InvocationTargetException | IllegalAccessException e) { - throw new RuntimeException(e); - } - }); - } - - protected Object[] getArguments(Method method, Object arg) { - int parameterCount = method.getParameterCount(); - if (parameterCount == 0) { - if (arg != null) { - LOG.warning("Unexpected params '" + arg + "' for '" + method + "' is ignored"); - } - return NO_ARGUMENTS; - } - if (arg instanceof List) { - List arguments = (List) arg; - int argumentCount = arguments.size(); - if (argumentCount == parameterCount) { - return arguments.toArray(); - } - if (argumentCount > parameterCount) { - Stream unexpectedArguments = arguments.stream().skip(parameterCount); - String unexpectedParams = unexpectedArguments.map(a -> "'" + a + "'").reduce((a, a2) -> a + ", " + a2).get(); - LOG.warning("Unexpected params " + unexpectedParams + " for '" + method + "' is ignored"); - return arguments.subList(0, parameterCount).toArray(); - } - return arguments.toArray(new Object[parameterCount]); - } - Object[] arguments = new Object[parameterCount]; - arguments[0] = arg; - return arguments; - } - - @Override - public CompletableFuture request(String method, Object parameter) { - // Check the registered method handlers - Function> handler = methodHandlers.get(method); - if (handler != null) { - return handler.apply(parameter); - } - - // Ask the delegate objects whether they can handle the request generically - List> futures = new ArrayList<>(delegates.size()); - for (Object delegate : delegates) { - if (delegate instanceof Endpoint) { - futures.add(((Endpoint) delegate).request(method, parameter)); - } - } - if (!futures.isEmpty()) { - return CompletableFuture.anyOf(futures.toArray(new CompletableFuture[futures.size()])); - } - - // Create a log message about the unsupported method - String message = "Unsupported request method: " + method; - if (isOptionalMethod(method)) { - LOG.log(Level.INFO, message); - return CompletableFuture.completedFuture(null); - } - LOG.log(Level.WARNING, message); - CompletableFuture exceptionalResult = new CompletableFuture(); - ResponseError error = new ResponseError(ResponseErrorCode.MethodNotFound, message, null); - exceptionalResult.completeExceptionally(new ResponseErrorException(error)); - return exceptionalResult; - } - - @Override - public void notify(String method, Object parameter) { - // Check the registered method handlers - Function> handler = methodHandlers.get(method); - if (handler != null) { - handler.apply(parameter); - return; - } - - // Ask the delegate objects whether they can handle the notification generically - int notifiedDelegates = 0; - for (Object delegate : delegates) { - if (delegate instanceof Endpoint) { - ((Endpoint) delegate).notify(method, parameter); - notifiedDelegates++; - } - } - - if (notifiedDelegates == 0) { - // Create a log message about the unsupported method - String message = "Unsupported notification method: " + method; - if (isOptionalMethod(method)) { - LOG.log(Level.INFO, message); - } else { - LOG.log(Level.WARNING, message); - } - } - } - - protected boolean isOptionalMethod(String method) { - return method != null && method.startsWith("$/"); - } - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/services/JsonDelegate.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/services/JsonDelegate.java deleted file mode 100644 index 5a6b2249e..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/services/JsonDelegate.java +++ /dev/null @@ -1,28 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.services; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * A method annotated with {@link JsonDelegate} is treated as a delegate method. - * As a result jsonrpc methods of the delegate will be considered, too. - * If an annotated method returns `null` - * then jsonrpc methods of the delegate are not considered. - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.METHOD) -public @interface JsonDelegate { -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/services/JsonNotification.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/services/JsonNotification.java deleted file mode 100644 index 75ad20bd2..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/services/JsonNotification.java +++ /dev/null @@ -1,52 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016, 2020 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.services; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Annotation to mark a notification method on an interface or class. - *

- * A notification method must be of type void and have zero or one - * argument. - *

- * According to jsonrpc an argument must be an 'object' (a java bean, not e,g. - * String). - *

- * The name of the jsonrpc notification will be the optional segment, followed - * by the name of the Java method that is annotated with JsonNotification. The - * name of the jsonrpc notification can be customized by using the - * {@link #value()} field of this annotation. To specify the whole name, - * including the segment, in the value, set {@link #useSegment()} to false. - * - * @see JsonSegment - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.METHOD) -public @interface JsonNotification { - /** - * The name of the the jsonrpc request method. If empty, uses the name of the - * annotated method. - */ - String value() default ""; - - /** - * When using segments, useSegment will be true to prepend the segment name to - * the name of the request. - * - * @see JsonSegment - */ - boolean useSegment() default true; -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/services/JsonRequest.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/services/JsonRequest.java deleted file mode 100644 index 4e9b801b3..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/services/JsonRequest.java +++ /dev/null @@ -1,53 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016, 2020 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.services; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.util.concurrent.CompletableFuture; - -/** - * Annotation to mark a request method on an interface or class. - *

- * A request method must have the return type {@link CompletableFuture} with an - * object parameter type or Void and have zero or one argument. - *

- * According to jsonrpc an argument must be an 'object' (a java bean, not e,g. - * String). - *

- * The name of the jsonrpc request will be the optional segment, followed by the - * name of the Java method that is annotated with JsonRequest. The name of the - * jsonrpc request can be customized by using the {@link #value()} field of this - * annotation. To specify the whole name, including the segment, in the value, - * set {@link #useSegment()} to false. - * - * @see JsonSegment - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ ElementType.METHOD, ElementType.TYPE }) -public @interface JsonRequest { - /** - * The name of the the jsonrpc request method. If empty, uses the name of the - * annotated method. - */ - String value() default ""; - - /** - * When using segments, useSegment will be true to prepend the segment name to - * the name of the request. - * - * @see JsonSegment - */ - boolean useSegment() default true; -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/services/JsonSegment.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/services/JsonSegment.java deleted file mode 100644 index 2b731979c..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/services/JsonSegment.java +++ /dev/null @@ -1,26 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.services; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Use on a class or interface to prefix all declared {@link JsonRequest} and {@link JsonNotification} methods. - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -public @interface JsonSegment { - String value() default ""; -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/services/ServiceEndpoints.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/services/ServiceEndpoints.java deleted file mode 100644 index c8ad3f011..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/services/ServiceEndpoints.java +++ /dev/null @@ -1,128 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.services; - -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Proxy; -import java.lang.reflect.Type; -import java.util.Collection; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Set; - -import org.eclipse.lsp4j.jsonrpc.Endpoint; -import org.eclipse.lsp4j.jsonrpc.json.JsonRpcMethod; -import org.eclipse.lsp4j.jsonrpc.json.ResponseJsonAdapter; - -import com.google.gson.TypeAdapterFactory; - -public final class ServiceEndpoints { - private ServiceEndpoints() {} - - /** - * Wraps a given {@link Endpoint} in the given service interface. - * - * @return the wrapped service object - */ - @SuppressWarnings("unchecked") - public static T toServiceObject(Endpoint endpoint, Class interface_) { - Class[] interfArray = new Class[]{interface_, Endpoint.class}; - EndpointProxy invocationHandler = new EndpointProxy(endpoint, interface_); - return (T) Proxy.newProxyInstance(interface_.getClassLoader(), interfArray, invocationHandler); - } - - /** - * Wraps a given {@link Endpoint} in the given service interfaces. - * - * @return the wrapped service object - */ - public static Object toServiceObject(Endpoint endpoint, Collection> interfaces, ClassLoader classLoader) { - Class[] interfArray = new Class[interfaces.size() + 1]; - interfaces.toArray(interfArray); - interfArray[interfArray.length - 1] = Endpoint.class; - EndpointProxy invocationHandler = new EndpointProxy(endpoint, interfaces); - return Proxy.newProxyInstance(classLoader, interfArray, invocationHandler); - } - - /** - * Wraps a given object with service annotations behind an {@link Endpoint} interface. - * - * @return the wrapped service endpoint - */ - public static Endpoint toEndpoint(Object serviceObject) { - return new GenericEndpoint(serviceObject); - } - - /** - * Wraps a collection of objects with service annotations behind an {@link Endpoint} interface. - * - * @return the wrapped service endpoint - */ - public static Endpoint toEndpoint(Collection serviceObjects) { - return new GenericEndpoint(serviceObjects); - } - - /** - * Finds all Json RPC methods on a given class. - * - * @return the supported JsonRpcMethods - */ - public static Map getSupportedMethods(Class type) { - Set> visitedTypes = new HashSet<>(); - return getSupportedMethods(type, visitedTypes); - } - - /** - * Finds all Json RPC methods on a given type - */ - private static Map getSupportedMethods(Class type, Set> visitedTypes) { - Map result = new LinkedHashMap(); - AnnotationUtil.findRpcMethods(type, visitedTypes, (methodInfo) -> { - JsonRpcMethod meth; - if (methodInfo.isNotification) { - meth = JsonRpcMethod.notification(methodInfo.name, methodInfo.parameterTypes); - } else { - Type genericReturnType = methodInfo.method.getGenericReturnType(); - if (genericReturnType instanceof ParameterizedType) { - Type returnType = ((ParameterizedType) genericReturnType).getActualTypeArguments()[0]; - TypeAdapterFactory responseTypeAdapter = null; - ResponseJsonAdapter responseTypeAdapterAnnotation = methodInfo.method.getAnnotation(ResponseJsonAdapter.class); - if (responseTypeAdapterAnnotation != null) { - try { - responseTypeAdapter = responseTypeAdapterAnnotation.value().newInstance(); - } catch (InstantiationException | IllegalAccessException e) { - throw new RuntimeException(e); - } - } - meth = JsonRpcMethod.request(methodInfo.name, returnType, responseTypeAdapter, methodInfo.parameterTypes); - } else { - throw new IllegalStateException("Expecting return type of CompletableFuture but was : " + genericReturnType); - } - } - if (result.put(methodInfo.name, meth) != null) { - throw new IllegalStateException("Duplicate RPC method "+methodInfo.name+"."); - }; - }); - - AnnotationUtil.findDelegateSegments(type, new HashSet<>(), (method)-> { - Map supportedDelegateMethods = getSupportedMethods(method.getReturnType(), visitedTypes); - for (JsonRpcMethod meth : supportedDelegateMethods.values()) { - if (result.put(meth.getMethodName(), meth) != null) { - throw new IllegalStateException("Duplicate RPC method "+meth.getMethodName()+"."); - }; - } - }); - return result; - } - -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/validation/NonNull.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/validation/NonNull.java deleted file mode 100644 index 9771e754d..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/validation/NonNull.java +++ /dev/null @@ -1,31 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.validation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Indicates that the annotated field or parameter must not be set to {@code null}. If validation - * is active, an exception is thrown when a message is received where a {@code NonNull} field - * has a {@code null} or {@code undefined} value. - * - * In order to achieve consistent behavior, for every field with this annotation the corresponding - * getter method as well as the parameter of the corresponding setter method are also expected to - * be annotated. - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE_PARAMETER}) -public @interface NonNull { -} diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/validation/ReflectiveMessageValidator.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/validation/ReflectiveMessageValidator.java deleted file mode 100644 index 965c81135..000000000 --- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/validation/ReflectiveMessageValidator.java +++ /dev/null @@ -1,185 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2016 TypeFox and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - ******************************************************************************/ -package org.eclipse.lsp4j.jsonrpc.validation; - -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Deque; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.ListIterator; -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.eclipse.lsp4j.jsonrpc.JsonRpcException; -import org.eclipse.lsp4j.jsonrpc.MessageConsumer; -import org.eclipse.lsp4j.jsonrpc.MessageIssueException; -import org.eclipse.lsp4j.jsonrpc.messages.Either; -import org.eclipse.lsp4j.jsonrpc.messages.Message; -import org.eclipse.lsp4j.jsonrpc.messages.MessageIssue; -import org.eclipse.lsp4j.jsonrpc.messages.ResponseErrorCode; - -import com.google.gson.JsonElement; - -/** - * Validates messages and forwards them to other message consumers. In case an issue is found, - * a {@link MessageIssueException} is thrown. - */ -public class ReflectiveMessageValidator implements MessageConsumer { - - private static final Logger LOG = Logger.getLogger(ReflectiveMessageValidator.class.getName()); - - private final MessageConsumer delegate; - - /** - * When created with this constructor, the validator acts as a message sink. - */ - public ReflectiveMessageValidator() { - this.delegate = null; - } - - /** - * Forward messages to the given consumer unless an issue is found. - */ - public ReflectiveMessageValidator(MessageConsumer delegate) { - this.delegate = delegate; - } - - @Override - public void consume(Message message) throws MessageIssueException, JsonRpcException { - List issues = validate(message); - if (!issues.isEmpty()) { - // Sort the messages in order to get a stable order (otherwise it depends on the JVM's reflection implementation) - Collections.sort(issues, (issue1, issue2) -> issue1.getText().compareTo(issue2.getText())); - throw new MessageIssueException(message, issues); - } else if (delegate != null) { - delegate.consume(message); - } - } - - /** - * Check whether the given object is valid. If it is not valid, its issues are not reported. - */ - public boolean isValid(Object object) { - List issues = validate(object); - return issues.isEmpty(); - } - - protected List validate(Object object) { - List result = new ArrayList<>(); - try { - validate(object, result, new LinkedList<>(), new LinkedList<>()); - } catch (Exception e) { - LOG.log(Level.SEVERE, "Error during message validation: " + e.getMessage(), e); - result.add(new MessageIssue("Message validation failed, please check the logs of the remote endpoint.", - ResponseErrorCode.InvalidParams.getValue())); - } - return result; - } - - /** - * Validate all fields of the given object. - */ - protected void validate(Object object, List issues, Deque objectStack, Deque accessorStack) throws Exception { - if (object == null - || object instanceof Enum - || object instanceof String - || object instanceof Number - || object instanceof Boolean - || object instanceof JsonElement - || object instanceof Throwable) { - return; - } - if (objectStack.contains(object)) { - issues.add(new MessageIssue("An element of the message has a direct or indirect reference to itself." - + " Path: " + createPathString(accessorStack), - ResponseErrorCode.InvalidParams.getValue())); - return; - } - objectStack.push(object); - if (object instanceof List) { - ListIterator iter = ((List) object).listIterator(); - while (iter.hasNext()) { - accessorStack.push(iter.nextIndex()); - Object element = iter.next(); - if (element == null) { - issues.add(new MessageIssue("Lists must not contain null references." - + " Path: " + createPathString(accessorStack), - ResponseErrorCode.InvalidParams.getValue())); - } - validate(element, issues, objectStack, accessorStack); - accessorStack.pop(); - } - } else if (object instanceof Either) { - Either either = (Either) object; - if (either.isLeft()) { - validate(either.getLeft(), issues, objectStack, accessorStack); - } else if (either.isRight()) { - validate(either.getRight(), issues, objectStack, accessorStack); - } else { - issues.add(new MessageIssue("An Either instance must not be empty." - + " Path: " + createPathString(accessorStack), - ResponseErrorCode.InvalidParams.getValue())); - } - } else { - for (Method method : object.getClass().getMethods()) { - if (isGetter(method)) { - accessorStack.push(method); - Object value = method.invoke(object); - if (value == null && method.getAnnotation(NonNull.class) != null) { - issues.add(new MessageIssue("The accessor '" + method.getDeclaringClass().getSimpleName() - + "." + method.getName() + "()' must return a non-null value." - + " Path: " + createPathString(accessorStack), - ResponseErrorCode.InvalidParams.getValue())); - } - validate(value, issues, objectStack, accessorStack); - accessorStack.pop(); - } - } - } - objectStack.pop(); - } - - protected String createPathString(Deque accessorStack) { - StringBuilder result = new StringBuilder("$"); - Iterator resultIter = accessorStack.descendingIterator(); - while(resultIter.hasNext()) { - Object accessor = resultIter.next(); - if (accessor instanceof Method) - result.append('.').append(getPropertyName((Method) accessor)); - else if (accessor instanceof Integer) - result.append('[').append(accessor).append(']'); - else - result.append(accessor); - } - return result.toString(); - } - - protected boolean isGetter(Method method) { - return method.getParameterCount() == 0 && method.getName().startsWith("get") - && method.getDeclaringClass() != Object.class - && Modifier.isPublic(method.getModifiers()) - && !Modifier.isStatic(method.getModifiers()); - } - - protected String getPropertyName(Method method) { - String methodName = method.getName(); - if (methodName.startsWith("get") && methodName.length() > 3) - return methodName.substring(3, 4).toLowerCase() + methodName.substring(4); - else - return methodName; - } - -} diff --git a/build-tools/tooling-api/build.gradle b/build-tools/tooling-api/build.gradle index 448474e8f..54f3c9291 100644 --- a/build-tools/tooling-api/build.gradle +++ b/build-tools/tooling-api/build.gradle @@ -30,12 +30,12 @@ dependencies { implementation project (path: ':build-tools:tooling-api-model') implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" + api 'org.eclipse.lsp4j:org.eclipse.lsp4j.jsonrpc:0.12.0' testImplementation tests.junit testImplementation tests.google_truth api google.gson - api project (':build-tools:jsonrpc') } repositories { diff --git a/settings.gradle b/settings.gradle index cb25ec9e0..3e1e3244c 100755 --- a/settings.gradle +++ b/settings.gradle @@ -23,4 +23,3 @@ include ':build-tools:logger' include ':build-tools:tooling-api' include ':build-tools:tooling-api-impl' include ':build-tools:tooling-api-model' -include ':build-tools:jsonrpc'