From 7ae6022a48acb7a578b38c5a7d2826bb76e305cd Mon Sep 17 00:00:00 2001
From: SeeBasTStick <sebastian.stock@hhu.de>
Date: Sun, 14 Jun 2020 17:13:48 +0200
Subject: [PATCH] basic setup to get a hardcoded response

---
 .gitignore                                    |  1 +
 build.gradle.kts                              |  3 +
 gradle/wrapper/gradle-wrapper.properties      |  5 ++
 src/main/kotlin/b/language/server/App.kt      | 33 +++++++
 .../b/language/server/BDocumentService.kt     | 67 ++++++++++++++
 .../b/language/server/BWorkspaceService.kt    | 23 +++++
 src/main/kotlin/b/language/server/Server.kt   | 90 +++++++++++++++++++
 src/test/kotlin/b/language/server/AppTest.kt  | 14 +++
 8 files changed, 236 insertions(+)
 create mode 100644 gradle/wrapper/gradle-wrapper.properties
 create mode 100644 src/main/kotlin/b/language/server/App.kt
 create mode 100644 src/main/kotlin/b/language/server/BDocumentService.kt
 create mode 100644 src/main/kotlin/b/language/server/BWorkspaceService.kt
 create mode 100644 src/main/kotlin/b/language/server/Server.kt
 create mode 100644 src/test/kotlin/b/language/server/AppTest.kt

diff --git a/.gitignore b/.gitignore
index 47af25b..9460fd2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -27,3 +27,4 @@ hs_err_pid*
 
 # Ignore Gradle build output directory
 build
+/.idea/
diff --git a/build.gradle.kts b/build.gradle.kts
index ae11418..03f0b4e 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -10,6 +10,7 @@ plugins {
     idea
     // Apply the application plugin to add support for building a CLI application.
     application
+    id("com.github.johnrengelman.shadow") version "5.2.0"
 }
 
 repositories {
@@ -25,6 +26,8 @@ dependencies {
     // Use the Kotlin JDK 8 standard library.
     implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
 
+    implementation("org.eclipse.lsp4j", "org.eclipse.lsp4j",  "0.9.0")
+
     // Use the Kotlin test library.
     testImplementation("org.jetbrains.kotlin:kotlin-test")
 
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..622ab64
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/src/main/kotlin/b/language/server/App.kt b/src/main/kotlin/b/language/server/App.kt
new file mode 100644
index 0000000..b88299a
--- /dev/null
+++ b/src/main/kotlin/b/language/server/App.kt
@@ -0,0 +1,33 @@
+/*
+ * This Kotlin source file was generated by the Gradle 'init' task.
+ */
+package b.language.server
+
+import org.eclipse.lsp4j.jsonrpc.Launcher
+import org.eclipse.lsp4j.launch.LSPLauncher
+import org.eclipse.lsp4j.services.LanguageClient
+import java.io.InputStream
+import java.io.OutputStream
+import java.util.concurrent.Future
+
+
+class App {
+    val greeting: String
+        get() {
+            return "Hello world."
+        }
+}
+
+fun main(args: Array<String>) {
+    startServer(System.`in`, System.out);
+
+}
+
+fun startServer(inputStream: InputStream, outputStream: OutputStream){
+    val server : Server = Server()
+    val launcher : Launcher<LanguageClient> = LSPLauncher.createServerLauncher(server, inputStream, outputStream)
+    val startListing : Future<*> = launcher.startListening()
+    server.setRemoteProxy(launcher.remoteProxy)
+    startListing.get()
+
+}
diff --git a/src/main/kotlin/b/language/server/BDocumentService.kt b/src/main/kotlin/b/language/server/BDocumentService.kt
new file mode 100644
index 0000000..a0dbf76
--- /dev/null
+++ b/src/main/kotlin/b/language/server/BDocumentService.kt
@@ -0,0 +1,67 @@
+package b.language.server
+
+import org.eclipse.lsp4j.*
+import org.eclipse.lsp4j.jsonrpc.messages.Either
+import org.eclipse.lsp4j.services.TextDocumentService
+import java.util.concurrent.CompletableFuture
+import java.util.concurrent.ConcurrentHashMap
+
+class BDocumentService(private val server: Server) : TextDocumentService {
+
+    private val documents = ConcurrentHashMap<String, String>()
+
+    /**
+     * The document open notification is sent from the client to the server to
+     * signal newly opened text documents. The document's truth is now managed
+     * by the client and the server must not try to read the document's truth
+     * using the document's uri.
+     *
+     * Registration Options: TextDocumentRegistrationOptions
+     */
+    override fun didOpen(params: DidOpenTextDocumentParams?) {
+        documents[params?.textDocument!!.uri] = params.textDocument!!.text
+    }
+
+    /**
+     * The document save notification is sent from the client to the server when
+     * the document for saved in the client.
+     *
+     * Registration Options: TextDocumentSaveRegistrationOptions
+     */
+    override fun didSave(params: DidSaveTextDocumentParams?) {
+        println("Save")
+        TODO("Not yet implemented")
+    }
+
+    /**
+     * The document close notification is sent from the client to the server
+     * when the document got closed in the client. The document's truth now
+     * exists where the document's uri points to (e.g. if the document's uri is
+     * a file uri the truth now exists on disk).
+     *
+     * Registration Options: TextDocumentRegistrationOptions
+     */
+    override fun didClose(params: DidCloseTextDocumentParams?) {
+        TODO("Not yet implemented")
+    }
+
+    /**
+     * The document change notification is sent from the client to the server to
+     * signal changes to a text document.
+     *
+     * Registration Options: TextDocumentChangeRegistrationOptions
+     */
+    override fun didChange(params: DidChangeTextDocumentParams?) {
+
+        CompletableFuture.runAsync {
+             val diagnostics : ArrayList<Diagnostic> =
+                     arrayListOf(Diagnostic(Range(Position(1,1), Position(1,1)), "Test",  DiagnosticSeverity.Error, "Test"))
+            server.languageClient.publishDiagnostics(PublishDiagnosticsParams(params?.textDocument?.uri, diagnostics))
+        }
+    }
+
+
+
+
+
+}
\ No newline at end of file
diff --git a/src/main/kotlin/b/language/server/BWorkspaceService.kt b/src/main/kotlin/b/language/server/BWorkspaceService.kt
new file mode 100644
index 0000000..2ae8540
--- /dev/null
+++ b/src/main/kotlin/b/language/server/BWorkspaceService.kt
@@ -0,0 +1,23 @@
+package b.language.server
+
+import org.eclipse.lsp4j.DidChangeConfigurationParams
+import org.eclipse.lsp4j.DidChangeWatchedFilesParams
+import org.eclipse.lsp4j.services.WorkspaceService
+
+class BWorkspaceService : WorkspaceService {
+    /**
+     * The watched files notification is sent from the client to the server when
+     * the client detects changes to file watched by the language client.
+     */
+    override fun didChangeWatchedFiles(params: DidChangeWatchedFilesParams?) {
+        TODO("Not yet implemented")
+    }
+
+    /**
+     * A notification sent from the client to the server to signal the change of
+     * configuration settings.
+     */
+    override fun didChangeConfiguration(params: DidChangeConfigurationParams?) {
+        TODO("Not yet implemented")
+    }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/b/language/server/Server.kt b/src/main/kotlin/b/language/server/Server.kt
new file mode 100644
index 0000000..3e5e5b1
--- /dev/null
+++ b/src/main/kotlin/b/language/server/Server.kt
@@ -0,0 +1,90 @@
+package b.language.server
+
+import org.eclipse.lsp4j.*
+import org.eclipse.lsp4j.services.LanguageClient
+import org.eclipse.lsp4j.services.LanguageServer
+import org.eclipse.lsp4j.services.TextDocumentService
+import org.eclipse.lsp4j.services.WorkspaceService
+import java.util.concurrent.CompletableFuture
+import kotlin.system.exitProcess
+
+
+class Server : LanguageServer {
+
+    private val textDocumentService : TextDocumentService
+    private val bWorkspaceService : WorkspaceService
+    lateinit var languageClient : LanguageClient
+
+
+
+    init {
+        textDocumentService = BDocumentService(this)
+        bWorkspaceService = BWorkspaceService()
+    }
+
+
+    /**
+     * The initialize request is sent as the first request from the client to
+     * the server.
+     *
+     * If the server receives request or notification before the initialize request it should act as follows:
+     * - for a request the respond should be errored with code: -32001. The message can be picked by the server.
+     * - notifications should be dropped, except for the exit notification. This will allow the exit a server without an initialize request.
+     *
+     * Until the server has responded to the initialize request with an InitializeResult
+     * the client must not sent any additional requests or notifications to the server.
+     *
+     * During the initialize request the server is allowed to sent the notifications window/showMessage,
+     * window/logMessage and telemetry/event as well as the window/showMessageRequest request to the client.
+     */
+    override fun initialize(params: InitializeParams?): CompletableFuture<InitializeResult> {
+        val res = InitializeResult(ServerCapabilities())
+        res.capabilities.setCodeActionProvider(true)
+        res.capabilities.completionProvider = CompletionOptions()
+        res.capabilities.definitionProvider = false
+        res.capabilities.hoverProvider = false
+        res.capabilities.referencesProvider = false
+        res.capabilities.setTextDocumentSync(TextDocumentSyncKind.Full)
+        res.capabilities.documentSymbolProvider = false
+
+        return CompletableFuture.supplyAsync { res }
+    }
+
+
+    /**
+     * The shutdown request is sent from the client to the server. It asks the
+     * server to shutdown, but to not exit (otherwise the response might not be
+     * delivered correctly to the client). There is a separate exit notification
+     * that asks the server to exit.
+     */
+    override fun shutdown(): CompletableFuture<Any> {
+        return CompletableFuture.supplyAsync{true}
+    }
+
+    /**
+     * Provides access to the textDocument services.
+     */
+    override fun getTextDocumentService(): TextDocumentService {
+        return textDocumentService
+    }
+
+    /**
+     * A notification to ask the server to exit its process.
+     */
+    override fun exit() {
+        exitProcess(0);
+    }
+
+
+
+    /**
+     * Provides access to the workspace services.
+     */
+    override fun getWorkspaceService(): WorkspaceService {
+        return bWorkspaceService
+    }
+
+    fun setRemoteProxy(remoteProxy: LanguageClient) {
+        this.languageClient = remoteProxy
+    }
+}
\ No newline at end of file
diff --git a/src/test/kotlin/b/language/server/AppTest.kt b/src/test/kotlin/b/language/server/AppTest.kt
new file mode 100644
index 0000000..898b91c
--- /dev/null
+++ b/src/test/kotlin/b/language/server/AppTest.kt
@@ -0,0 +1,14 @@
+/*
+ * This Kotlin source file was generated by the Gradle 'init' task.
+ */
+package b.language.server
+
+import kotlin.test.Test
+import kotlin.test.assertNotNull
+
+class AppTest {
+    @Test fun testAppHasAGreeting() {
+        val classUnderTest = App()
+        assertNotNull(classUnderTest.greeting, "app should have a greeting")
+    }
+}
-- 
GitLab