Skip to content

Commit

Permalink
docs: add missing javadocs
Browse files Browse the repository at this point in the history
  • Loading branch information
sillydan1 committed Feb 18, 2024
1 parent eb5c0f2 commit 5db98d6
Show file tree
Hide file tree
Showing 9 changed files with 158 additions and 2 deletions.
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ subprojects {
}

javadoc {
exclude 'dk/gtz/graphedit/proto/**'
if (JavaVersion.current().isJava9Compatible()) {
options.addBooleanOption('html5', true)
}
Expand Down
75 changes: 73 additions & 2 deletions core/src/main/java/dk/gtz/graphedit/spi/GrpcLanguageServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,24 +54,78 @@
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.MapChangeListener;

/**
* Language server base class for wiring a gRPC based language server with graphedit.
*
* Extend this clas and override the appropriate subprocess invocation parts to seamlessly integrate your MLSP implementation.
*/
public abstract class GrpcLanguageServer implements ILanguageServer {
private final Logger logger = LoggerFactory.getLogger(GrpcLanguageServer.class);

/**
* Lazy loaded gRPC language server stub interface instance.
* Use this to interact with the connected language server.
*/
protected final Lazy<LanguageServerStub> stub;

/**
* Lazy loaded server info struct.
*/
protected final Lazy<ServerInfo> serverInfo;

/**
* Utility instance of the gRPC Empty value.
*/
protected final Empty empty;

/**
* Reference to the current editor buffercontainer
*/
protected IBufferContainer bufferContainer;

/**
* Host string, pointing to the connected language server
*/
protected final String host;

/**
* Host port, pointing to the connected language server
*/
protected final int port;

/**
* The thread in which the language server process is running
*/
protected final Thread programThread;

/**
* Maximum amount of attempts to connect to the language server
*/
protected int maxConnectionAttempts = 60;

/**
* Time (in milliseconds) to wait between failed connection attempts
*/
protected int connectionAttemptWaitMilliseconds = 1000;
private final Converter converter;

public GrpcLanguageServer(String command, List<String> arguments) {
/**
* Constructs a new GrpcLanguageServer instance
* @param command The subprocess command to execute at startup
* @param arguments The arguments to provide to the subprocess command
*/
protected GrpcLanguageServer(String command, List<String> arguments) {
this("0.0.0.0", new Random().nextInt(5000, 6000), command, arguments);
}

public GrpcLanguageServer(String host, int port, String command, List<String> arguments) {
/**
* Constructs a new GrpcLanguageServer instance
* @param host The gRPC host to connect to
* @param port The gRPC port to connect to
* @param command The subprocess command to execute at startup
* @param arguments The arguments to provide to the subprocess command
*/
protected GrpcLanguageServer(String host, int port, String command, List<String> arguments) {
this.host = host;
this.port = port;
this.converter = new Converter();
Expand All @@ -82,13 +136,21 @@ public GrpcLanguageServer(String host, int port, String command, List<String> ar
this.serverInfo = new Lazy<>(this::getServerInfo);
}

/**
* Connect to the language server.
* @return A new language server stub instance
*/
protected LanguageServerStub connect() {
if(!programThread.isAlive())
programThread.start();
var channel = ManagedChannelBuilder.forAddress(host, port).usePlaintext().build();
return LanguageServerGrpc.newStub(channel);
}

/**
* Get the information about the language server.
* @return A class of language server information
*/
protected ServerInfo getServerInfo() {
try {
var so = new SingleResponseStreamObserver<ServerInfo>();
Expand All @@ -100,6 +162,11 @@ protected ServerInfo getServerInfo() {
}
}

/**
* Check if the language server reports that it is capable of some feature.
* @param capability The feature capability
* @return {@code true} if the server reports that it is capable of the provided feature, otherwise {@code false}
*/
protected boolean isServerCapable(Capability capability) {
return serverInfo.get().getCapabilitiesList().contains(capability);
}
Expand All @@ -119,6 +186,10 @@ public String getServerVersion() {
return serverInfo.get().getSemanticVersion();
}

/**
* Tell the connected language server to handle the provided diff
* @param diff The diff for the connected server to handle
*/
protected void handleDiff(Diff diff) {
if(!isServerCapable(Capability.CAPABILITY_DIFFS))
return;
Expand Down
4 changes: 4 additions & 0 deletions core/src/main/java/dk/gtz/graphedit/spi/IExporter.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,9 @@ public interface IExporter {
*/
String getName();

/**
* Returns the file extension that exported files will have.
* @return A file extension e.g. ".json"
*/
String getFileExtension();
}
20 changes: 20 additions & 0 deletions core/src/main/java/dk/gtz/graphedit/spi/ResponseContainer.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,43 @@

import java.util.Optional;

/**
* A container utility class that can hold either: nothing, valid value or an error.
* @param <T> The type of the contained value
*/
public class ResponseContainer<T> {
private Optional<T> result;
private Optional<Throwable> error;

/**
* Constructs a new container instance
*/
public ResponseContainer() {
result = Optional.empty();
error = Optional.empty();
}

/**
* Set the result value
* @param e the result value
*/
public void set(T e) {
result = Optional.of(e);
}

/**
* Set the container to have an error.
* @param e the error to hold
*/
public void setError(Throwable e) {
error = Optional.of(e);
}

/**
* Get the contained value.
* @return An instance of T
* @throws RuntimeException if an error had occurred or if the value is not present
*/
public T get() {
if(error.isPresent())
throw new RuntimeException(error.get());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,31 @@

import io.grpc.stub.StreamObserver;

/**
* Utility class for capturing a single gRPC response and returning it.
*
* Example Usage:
* <pre>
* {@code
* try {
* var so = new SingleResponseStreamObserver<GRPCObject>();
* stub.get().getValue(empty, so);
* so.await();
* return so.get();
* } catch(InterruptedException e) {
* // handle e
* }
* }
* </pre>
* @param <T> The type of return value
*/
public class SingleResponseStreamObserver<T> implements StreamObserver<T> {
private final ResponseContainer<T> container;
private final CountDownLatch latch;

/**
* Constructs a new SingleResponseStreamObserver instance
*/
public SingleResponseStreamObserver() {
container = new ResponseContainer<>();
latch = new CountDownLatch(1);
Expand All @@ -29,10 +50,19 @@ public void onCompleted() {
latch.countDown();
}

/**
* Get the returned value.
* @return An instance of T
* @throws RuntimeException if an error had occurred or if the value is not present
*/
public T get() {
return container.get();
}

/**
* Wait for the request to complete.
* @throws InterruptedException if the current thread is interrupted while waiting
*/
public void await() throws InterruptedException {
latch.await();
}
Expand Down
2 changes: 2 additions & 0 deletions core/src/main/java/dk/gtz/graphedit/util/EditorActions.java
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,7 @@ public static Optional<File> openFile(String description, List<String> filterTyp

/**
* Prompt the user to pick a file
* @param filter filter the types of files that can be picked
* @return Possibly a file reference. Will be empty if the user cancelled the action
*/
public static Optional<File> openFile(ExtensionFilter filter) {
Expand Down Expand Up @@ -576,6 +577,7 @@ public static List<File> openFiles(String description, List<String> filterTypes)

/**
* Prompt the user to pick one or more files
* @param filter filter the types of files that can be picked
* @return Possibly a list of file references. Will be empty if the user cancelled the action or selected no files
*/
public static List<File> openFiles(ExtensionFilter filter) {
Expand Down
7 changes: 7 additions & 0 deletions core/src/main/java/dk/gtz/graphedit/util/PlatformUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,13 @@ public static String removeFileExtension(String fname) {
return fname;
}

/**
* Launch a new subprocess and wait for it to complete whilst logging the stout to TRACE-level and stderr to ERROR-level logging.
*
* Note that this will block the current thread of execution until the command is completed.
* @param command The command to launch the subprocess with
* @param arguments The command-line arguments to provide the subprocess with
*/
public static void launchProgram(String command, List<String> arguments) {
Process p = null;
try {
Expand Down
16 changes: 16 additions & 0 deletions core/src/main/java/dk/gtz/graphedit/util/RetryUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,21 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Utility functions for retrying actions multiple times.
*/
public final class RetryUtils {
private static final Logger logger = LoggerFactory.getLogger(RetryUtils.class);

/**
* Try an action until it returns a value or until a set amount of attempts failed.
* @param <T> The return type that the function should return.
* @param maxAttempts Maximum amount of times to try
* @param sleepMillis Amount of time to wait between failed attempts
* @param f The supplier function to try
* @return The return value of the supplier function f
* @throws RuntimeException if too many attempts happenned
*/
public static <T> T tryTimes(int maxAttempts, int sleepMillis, Supplier<T> f) {
for(var attempts = 0; attempts < maxAttempts; attempts++) {
try {
Expand All @@ -20,6 +32,10 @@ public static <T> T tryTimes(int maxAttempts, int sleepMillis, Supplier<T> f) {
throw new RuntimeException("too many attempts");
}

/**
* Sleep for a set amount of milliseconds. If interrupted, simply return.
* @param milliseconds The length of time to wait in milliseconds
*/
public static void sleep(int milliseconds) {
try {
Thread.sleep(milliseconds);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ private ViewModelDiff(String syntaxStyle) {
edgeAdditions = new ArrayList<>();
}

/**
* Create a new empty diff
* @param syntaxStyle The syntax style of the new diff
* @return A new empty diff
*/
public static ViewModelDiff empty(String syntaxStyle) {
return new ViewModelDiff(syntaxStyle);
}
Expand Down

0 comments on commit 5db98d6

Please sign in to comment.