diff --git a/LanguageServer/pom.xml b/LanguageServer/pom.xml new file mode 100644 index 0000000..e2d813f --- /dev/null +++ b/LanguageServer/pom.xml @@ -0,0 +1,32 @@ + + + 4.0.0 + + org.nittalab + LanguageServer + 0.1 + + + 21 + 21 + UTF-8 + + + + + org.eclipse.lsp4j + org.eclipse.lsp4j + 0.24.0 + + + + org.junit.jupiter + junit-jupiter-api + 5.13.0-M2 + test + + + + \ No newline at end of file diff --git a/LanguageServer/src/main/java/org/nittalab/dtram/languageserver/DTRAMLanguageServer.java b/LanguageServer/src/main/java/org/nittalab/dtram/languageserver/DTRAMLanguageServer.java new file mode 100644 index 0000000..6f68598 --- /dev/null +++ b/LanguageServer/src/main/java/org/nittalab/dtram/languageserver/DTRAMLanguageServer.java @@ -0,0 +1,63 @@ +package org.nittalab.dtram.languageserver; + +import org.eclipse.lsp4j.*; +import org.eclipse.lsp4j.services.*; + +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.logging.Logger; + +public class DTRAMLanguageServer implements LanguageServer, LanguageClientAware { + private static final Logger logger = Logger.getLogger(DTRAMLanguageServer.class.getName()); + + private final WorkspaceService workspaceService; + private final TextDocumentService textDocumentService; + + public DTRAMLanguageServer() { + this.workspaceService = new DTRAMWorkspaceService(); + this.textDocumentService = new DTRAMTextDocumentService(); + } + + @Override + public void connect(LanguageClient client) { + } + + @Override + public CompletableFuture initialize(InitializeParams params) { + ClientInfo clientInfo = params.getClientInfo(); + logger.info("Connected to: " + clientInfo.getName() + " " + clientInfo.getVersion()); + + ServerCapabilities capabilities = new ServerCapabilities(); + + /* エディタに補完機能が利用できることを伝える **/ + CompletionOptions completionOptions = new CompletionOptions(); + completionOptions.setTriggerCharacters(List.of(".", " ")); // 入力補完を開始する文字 + + capabilities.setTextDocumentSync(TextDocumentSyncKind.Full); // ファイルの同期方法を指定(毎回ドキュメント全体を送信してもらう) + capabilities.setPositionEncoding(PositionEncodingKind.UTF16); // 文字列符号化方式を指定 + capabilities.setCompletionProvider(completionOptions); + + InitializeResult result = new InitializeResult(capabilities); + return CompletableFuture.completedFuture(result); + } + + @Override + public CompletableFuture shutdown() { + return CompletableFuture.supplyAsync(Object::new); + } + + @Override + public void exit() { + System.exit(0); + } + + @Override + public WorkspaceService getWorkspaceService() { + return workspaceService; + } + + @Override + public TextDocumentService getTextDocumentService() { + return textDocumentService; + } +} diff --git a/LanguageServer/src/main/java/org/nittalab/dtram/languageserver/DTRAMTextDocumentService.java b/LanguageServer/src/main/java/org/nittalab/dtram/languageserver/DTRAMTextDocumentService.java new file mode 100644 index 0000000..2c43b1c --- /dev/null +++ b/LanguageServer/src/main/java/org/nittalab/dtram/languageserver/DTRAMTextDocumentService.java @@ -0,0 +1,42 @@ +package org.nittalab.dtram.languageserver; + +import org.eclipse.lsp4j.*; +import org.eclipse.lsp4j.jsonrpc.CompletableFutures; +import org.eclipse.lsp4j.jsonrpc.messages.Either; +import org.eclipse.lsp4j.services.TextDocumentService; +import org.nittalab.dtram.languageserver.completion.*; + +import java.util.List; +import java.util.concurrent.CompletableFuture; + +public class DTRAMTextDocumentService implements TextDocumentService { + @Override + public void didOpen(DidOpenTextDocumentParams params) { + } + + @Override + public void didChange(DidChangeTextDocumentParams params) { + } + + @Override + public void didClose(DidCloseTextDocumentParams params) { + } + + @Override + public void didSave(DidSaveTextDocumentParams params) { + } + + @Override + public CompletableFuture, CompletionList>> completion(CompletionParams params) { + System.out.println(params.getPosition().getLine() + " " + params.getPosition().getCharacter()); + return CompletableFutures.computeAsync(checker -> { + CompletionItem append = new AppendCompletionItem(); + CompletionItem delete = new DeleteCompletionItem(); + CompletionItem channel = new ChannelCompletionItem(); + CompletionItem in = new InputCompletionItem(); + CompletionItem ref = new ReferenceCompletionItem(); + CompletionItem out = new OutputCompletionItem(); + return Either.forLeft(List.of(append, delete, channel, in, ref, out)); + }); + } +} diff --git a/LanguageServer/src/main/java/org/nittalab/dtram/languageserver/DTRAMWorkspaceService.java b/LanguageServer/src/main/java/org/nittalab/dtram/languageserver/DTRAMWorkspaceService.java new file mode 100644 index 0000000..81ec08b --- /dev/null +++ b/LanguageServer/src/main/java/org/nittalab/dtram/languageserver/DTRAMWorkspaceService.java @@ -0,0 +1,15 @@ +package org.nittalab.dtram.languageserver; + +import org.eclipse.lsp4j.DidChangeConfigurationParams; +import org.eclipse.lsp4j.DidChangeWatchedFilesParams; +import org.eclipse.lsp4j.services.WorkspaceService; + +public class DTRAMWorkspaceService implements WorkspaceService { + @Override + public void didChangeConfiguration(DidChangeConfigurationParams params) { + } + + @Override + public void didChangeWatchedFiles(DidChangeWatchedFilesParams params) { + } +} diff --git a/LanguageServer/src/main/java/org/nittalab/dtram/languageserver/completion/AppendCompletionItem.java b/LanguageServer/src/main/java/org/nittalab/dtram/languageserver/completion/AppendCompletionItem.java new file mode 100644 index 0000000..33dfb2e --- /dev/null +++ b/LanguageServer/src/main/java/org/nittalab/dtram/languageserver/completion/AppendCompletionItem.java @@ -0,0 +1,14 @@ +package org.nittalab.dtram.languageserver.completion; + +import org.eclipse.lsp4j.CompletionItem; +import org.eclipse.lsp4j.CompletionItemKind; + +public final class AppendCompletionItem extends CompletionItem { + + public AppendCompletionItem() { + super(); + setLabel("append"); + setDetail("Append the specified element to the collection"); + setKind(CompletionItemKind.Snippet); + } +} diff --git a/LanguageServer/src/main/java/org/nittalab/dtram/languageserver/completion/ChannelCompletionItem.java b/LanguageServer/src/main/java/org/nittalab/dtram/languageserver/completion/ChannelCompletionItem.java new file mode 100644 index 0000000..93e14bd --- /dev/null +++ b/LanguageServer/src/main/java/org/nittalab/dtram/languageserver/completion/ChannelCompletionItem.java @@ -0,0 +1,14 @@ +package org.nittalab.dtram.languageserver.completion; + +import org.eclipse.lsp4j.CompletionItem; +import org.eclipse.lsp4j.CompletionItemKind; + +public final class ChannelCompletionItem extends CompletionItem { + + public ChannelCompletionItem() { + super(); + setLabel("channel"); + setDetail("Inserts the specified element as the last element of the collection"); + setKind(CompletionItemKind.Snippet); + } +} diff --git a/LanguageServer/src/main/java/org/nittalab/dtram/languageserver/completion/DeleteCompletionItem.java b/LanguageServer/src/main/java/org/nittalab/dtram/languageserver/completion/DeleteCompletionItem.java new file mode 100644 index 0000000..1db6eb3 --- /dev/null +++ b/LanguageServer/src/main/java/org/nittalab/dtram/languageserver/completion/DeleteCompletionItem.java @@ -0,0 +1,14 @@ +package org.nittalab.dtram.languageserver.completion; + +import org.eclipse.lsp4j.CompletionItem; +import org.eclipse.lsp4j.CompletionItemKind; + +public final class DeleteCompletionItem extends CompletionItem { + + public DeleteCompletionItem() { + super(); + setLabel("delete"); + setDetail("Deletes the element of the collection with specified id"); + setKind(CompletionItemKind.Snippet); + } +} diff --git a/LanguageServer/src/main/java/org/nittalab/dtram/languageserver/completion/InputCompletionItem.java b/LanguageServer/src/main/java/org/nittalab/dtram/languageserver/completion/InputCompletionItem.java new file mode 100644 index 0000000..1c5ee9e --- /dev/null +++ b/LanguageServer/src/main/java/org/nittalab/dtram/languageserver/completion/InputCompletionItem.java @@ -0,0 +1,14 @@ +package org.nittalab.dtram.languageserver.completion; + +import org.eclipse.lsp4j.CompletionItem; +import org.eclipse.lsp4j.CompletionItemKind; + +public final class InputCompletionItem extends CompletionItem { + + public InputCompletionItem() { + super(); + setLabel("in"); + setDetail("Defines an input transition function"); + setKind(CompletionItemKind.Snippet); + } +} diff --git a/LanguageServer/src/main/java/org/nittalab/dtram/languageserver/completion/OutputCompletionItem.java b/LanguageServer/src/main/java/org/nittalab/dtram/languageserver/completion/OutputCompletionItem.java new file mode 100644 index 0000000..9de3a35 --- /dev/null +++ b/LanguageServer/src/main/java/org/nittalab/dtram/languageserver/completion/OutputCompletionItem.java @@ -0,0 +1,14 @@ +package org.nittalab.dtram.languageserver.completion; + +import org.eclipse.lsp4j.CompletionItem; +import org.eclipse.lsp4j.CompletionItemKind; + +public final class OutputCompletionItem extends CompletionItem { + + public OutputCompletionItem() { + super(); + setLabel("out"); + setDetail("Defines an output transition function"); + setKind(CompletionItemKind.Snippet); + } +} diff --git a/LanguageServer/src/main/java/org/nittalab/dtram/languageserver/completion/ReferenceCompletionItem.java b/LanguageServer/src/main/java/org/nittalab/dtram/languageserver/completion/ReferenceCompletionItem.java new file mode 100644 index 0000000..40bef22 --- /dev/null +++ b/LanguageServer/src/main/java/org/nittalab/dtram/languageserver/completion/ReferenceCompletionItem.java @@ -0,0 +1,14 @@ +package org.nittalab.dtram.languageserver.completion; + +import org.eclipse.lsp4j.CompletionItem; +import org.eclipse.lsp4j.CompletionItemKind; + +public final class ReferenceCompletionItem extends CompletionItem { + + public ReferenceCompletionItem() { + super(); + setLabel("ref"); + setDetail("Defines an reference transition function"); + setKind(CompletionItemKind.Snippet); + } +} diff --git a/LanguageServer/src/main/java/org/nittalab/dtram/languageserver/main/Main.java b/LanguageServer/src/main/java/org/nittalab/dtram/languageserver/main/Main.java new file mode 100644 index 0000000..7777d1e --- /dev/null +++ b/LanguageServer/src/main/java/org/nittalab/dtram/languageserver/main/Main.java @@ -0,0 +1,58 @@ +package org.nittalab.dtram.languageserver.main; + +import org.eclipse.lsp4j.launch.LSPLauncher; +import org.nittalab.dtram.languageserver.DTRAMLanguageServer; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.ServerSocket; +import java.util.concurrent.ExecutionException; + +/** + * The entry point of the server. + * + * @author Shohei Yamagiwa + * @since 0.1 + */ +public class Main { + /** + * The port number of the connection between the server and client. + */ + private static final int PORT = 8080; + + /** + * The entry point of the server. + * + * @param args This is just a boilerplate so won't be used in the server + * @author Shohei Yamagiwa + * @since 0.1 + */ + public static void main(String[] args) { + try (var serverSocket = new ServerSocket(PORT)) { + var socket = serverSocket.accept(); + startServer(socket.getInputStream(), socket.getOutputStream()); + } catch (ExecutionException | InterruptedException | IOException e) { + throw new RuntimeException(e); + } + } + + /** + * Starts the language server with given streams. + * + * @param in {@link InputStream} to listen for incoming messages + * @param out {@link OutputStream} to send outgoing messages + * @throws ExecutionException Thrown when the connection couldn't be established + * @throws InterruptedException Thrown when the connection is interrupted + * @author Shohei Yamagiwa + * @since 0.1 + */ + private static void startServer(InputStream in, OutputStream out) throws ExecutionException, InterruptedException { + var server = new DTRAMLanguageServer(); + var launcher = LSPLauncher.createServerLauncher(server, in, out); + var client = launcher.getRemoteProxy(); + + server.connect(client); + launcher.startListening(); + } +}