diff --git a/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/client/DefaultLanguageClient.kt b/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/client/DefaultLanguageClient.kt index cea7cff36..92f22f225 100644 --- a/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/client/DefaultLanguageClient.kt +++ b/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/client/DefaultLanguageClient.kt @@ -69,7 +69,7 @@ open class DefaultLanguageClient(protected val context: ClientContext) : } override fun registerCapability(params: RegistrationParams): CompletableFuture { - //Not prepared to support this feature + // Not prepared to support this feature return CompletableFuture.completedFuture(null) } @@ -83,8 +83,6 @@ open class DefaultLanguageClient(protected val context: ClientContext) : } override fun publishDiagnostics(publishDiagnosticsParams: PublishDiagnosticsParams) { - // FIXME: support it. - val diagnosticsContainer = context.project.diagnosticsContainer val uri = URI(publishDiagnosticsParams.uri).toFileUri() @@ -96,7 +94,6 @@ open class DefaultLanguageClient(protected val context: ClientContext) : val editor = context.getEditor(uri) editor?.onDiagnosticsUpdate() - } override fun refreshDiagnostics(): CompletableFuture { diff --git a/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/client/connection/CustomConnectProvider.kt b/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/client/connection/CustomConnectProvider.kt index 77d2ac495..b1115f116 100644 --- a/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/client/connection/CustomConnectProvider.kt +++ b/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/client/connection/CustomConnectProvider.kt @@ -62,7 +62,7 @@ class CustomConnectProvider(private val streamProvider: StreamProvider) : Stream /** * Provider of language server connection */ - interface StreamProvider { + fun interface StreamProvider { @WorkerThread fun getStreams(): Pair } diff --git a/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/client/languageserver/requestmanager/DefaultRequestManager.kt b/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/client/languageserver/requestmanager/DefaultRequestManager.kt index 45c77ad2e..60bfaccee 100644 --- a/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/client/languageserver/requestmanager/DefaultRequestManager.kt +++ b/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/client/languageserver/requestmanager/DefaultRequestManager.kt @@ -49,6 +49,8 @@ import org.eclipse.lsp4j.DidCloseTextDocumentParams import org.eclipse.lsp4j.DidOpenTextDocumentParams import org.eclipse.lsp4j.DidSaveTextDocumentParams import org.eclipse.lsp4j.DocumentColorParams +import org.eclipse.lsp4j.DocumentDiagnosticParams +import org.eclipse.lsp4j.DocumentDiagnosticReport import org.eclipse.lsp4j.DocumentFormattingParams import org.eclipse.lsp4j.DocumentHighlight import org.eclipse.lsp4j.DocumentHighlightParams @@ -491,6 +493,19 @@ class DefaultRequestManager( } else null } + override fun diagnostic(params: DocumentDiagnosticParams?): CompletableFuture? { + return if (checkStatus()) { + try { + if (serverCapabilities.diagnosticProvider != null) textDocumentService.diagnostic( + params + ) else null + } catch (e: Exception) { + crashed(e) + null + } + } else null + } + override fun definition(params: TextDocumentPositionParams): CompletableFuture, List>>? { return definition(DefinitionParams(params.textDocument, params.position)) } diff --git a/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/editor/LspEditor.kt b/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/editor/LspEditor.kt index 491d0de1d..61e15c3d8 100644 --- a/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/editor/LspEditor.kt +++ b/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/editor/LspEditor.kt @@ -26,11 +26,13 @@ package io.github.rosemoe.sora.lsp.editor import androidx.annotation.WorkerThread import io.github.rosemoe.sora.event.ContentChangeEvent +import io.github.rosemoe.sora.event.SelectionChangeEvent import io.github.rosemoe.sora.lang.Language import io.github.rosemoe.sora.lsp.client.languageserver.requestmanager.RequestManager import io.github.rosemoe.sora.lsp.client.languageserver.serverdefinition.LanguageServerDefinition import io.github.rosemoe.sora.lsp.client.languageserver.wrapper.LanguageServerWrapper import io.github.rosemoe.sora.lsp.editor.event.LspEditorContentChangeEventReceiver +import io.github.rosemoe.sora.lsp.editor.event.LspEditorSelectionChangeEventReceiver import io.github.rosemoe.sora.lsp.editor.signature.SignatureHelpWindow import io.github.rosemoe.sora.lsp.events.EventType import io.github.rosemoe.sora.lsp.events.diagnostics.publishDiagnostics @@ -44,6 +46,7 @@ import io.github.rosemoe.sora.lsp.utils.clearVersions import io.github.rosemoe.sora.widget.CodeEditor import io.github.rosemoe.sora.widget.subscribeEvent import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay import kotlinx.coroutines.future.future import kotlinx.coroutines.runBlocking import kotlinx.coroutines.withContext @@ -67,6 +70,8 @@ class LspEditor( private lateinit var editorContentChangeEventReceiver: LspEditorContentChangeEventReceiver + private lateinit var editorSelectionChangeEventReceiver: LspEditorSelectionChangeEventReceiver + private var currentLanguage: LspLanguage? = null private var isClose = false @@ -102,12 +107,25 @@ class LspEditor( editorContentChangeEventReceiver = LspEditorContentChangeEventReceiver(this) - val subscriptionReceipt = - currentEditor.subscribeEvent( - editorContentChangeEventReceiver + editorSelectionChangeEventReceiver = LspEditorSelectionChangeEventReceiver(this) + + val subscriptionReceipts = + mutableListOf( + currentEditor.subscribeEvent( + editorContentChangeEventReceiver + ), + currentEditor.subscribeEvent( + editorSelectionChangeEventReceiver + ) ) - unsubscribeFunction = Runnable { subscriptionReceipt.unsubscribe() } + unsubscribeFunction = + Runnable { + subscriptionReceipts.removeAll { + it.unsubscribe() + true + } + } } get() { return _currentEditor.get() @@ -207,7 +225,7 @@ class LspEditor( exception.printStackTrace(); } start = System.currentTimeMillis() - Thread.sleep((retryTime / 10).toLong()) + delay((retryTime / 10).toLong()) } if (!isConnected && start > maxRetryTime) { diff --git a/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/editor/LspLanguage.kt b/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/editor/LspLanguage.kt index 7afb124c6..251b799f9 100644 --- a/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/editor/LspLanguage.kt +++ b/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/editor/LspLanguage.kt @@ -96,7 +96,7 @@ class LspLanguage(var editor: LspEditor) : Language { }*/ val prefix = computePrefix(content, position) - Log.d("prefix", prefix); + val prefixLength = prefix.length val documentChangeEvent = diff --git a/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/editor/completion/LspCompletionItem.kt b/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/editor/completion/LspCompletionItem.kt index 7c1c79a09..f108288c3 100644 --- a/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/editor/completion/LspCompletionItem.kt +++ b/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/editor/completion/LspCompletionItem.kt @@ -24,6 +24,7 @@ package io.github.rosemoe.sora.lsp.editor.completion +import android.util.Log import io.github.rosemoe.sora.lang.completion.CompletionItemKind import io.github.rosemoe.sora.lang.completion.SimpleCompletionIconDrawer.draw import io.github.rosemoe.sora.lang.completion.snippet.parser.CodeSnippetParser diff --git a/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/editor/event/LspEditorContentChangeEventReceiver.kt b/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/editor/event/LspEditorContentChangeEventReceiver.kt index e752eabf3..de477b3ad 100644 --- a/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/editor/event/LspEditorContentChangeEventReceiver.kt +++ b/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/editor/event/LspEditorContentChangeEventReceiver.kt @@ -24,15 +24,23 @@ package io.github.rosemoe.sora.lsp.editor.event +import android.util.Log import io.github.rosemoe.sora.event.ContentChangeEvent import io.github.rosemoe.sora.event.EventReceiver +import io.github.rosemoe.sora.event.SelectionChangeEvent import io.github.rosemoe.sora.event.Unsubscribe import io.github.rosemoe.sora.lsp.editor.LspEditor import io.github.rosemoe.sora.lsp.events.EventType +import io.github.rosemoe.sora.lsp.events.diagnostics.publishDiagnostics +import io.github.rosemoe.sora.lsp.events.diagnostics.queryDocumentDiagnostics import io.github.rosemoe.sora.lsp.events.document.documentChange import io.github.rosemoe.sora.lsp.events.signature.signatureHelp import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import org.eclipse.lsp4j.DocumentDiagnosticReport +import org.eclipse.lsp4j.FullDocumentDiagnosticReport +import org.eclipse.lsp4j.UnchangedDocumentDiagnosticReport +import org.eclipse.lsp4j.jsonrpc.messages.Either class LspEditorContentChangeEventReceiver(private val editor: LspEditor) : @@ -49,9 +57,41 @@ class LspEditorContentChangeEventReceiver(private val editor: LspEditor) : } editor.eventManager.emitAsync(EventType.signatureHelp, event.changeStart) + + val diagnostics = + editor.eventManager.emitAsync(EventType.queryDocumentDiagnostics) + .getOrNull("diagnostics") ?: return@launch + + if (diagnostics.isRelatedUnchangedDocumentDiagnosticReport) { + // no-op + return@launch + } + + if (diagnostics.isRelatedFullDocumentDiagnosticReport) { + editor.eventManager.emit(EventType.publishDiagnostics) { + put("data", diagnostics.left.items) + } + } } } } +class LspEditorSelectionChangeEventReceiver(private val editor: LspEditor) : + EventReceiver { + override fun onReceive(event: SelectionChangeEvent, unsubscribe: Unsubscribe) { + + editor.coroutineScope.launch(Dispatchers.IO) { + + if (editor.hitReTrigger(event.editor.text[event.left.index].toString())) { + editor.showSignatureHelp(null) + return@launch + } + + editor.eventManager.emitAsync(EventType.signatureHelp, event.left) + } + + + } +} \ No newline at end of file diff --git a/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/events/EventEmitter.kt b/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/events/EventEmitter.kt index a5be7a587..eda42303f 100644 --- a/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/events/EventEmitter.kt +++ b/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/events/EventEmitter.kt @@ -161,7 +161,7 @@ class EventContext { } fun getOrNull(key: String): T? { - return data[key] as T? + return data[key] as? T? } fun put(key: String, value: Any) { diff --git a/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/events/diagnostics/PublishDiagnosticsEvent.kt b/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/events/diagnostics/PublishDiagnosticsEvent.kt index 53391b789..8abd42b3c 100644 --- a/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/events/diagnostics/PublishDiagnosticsEvent.kt +++ b/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/events/diagnostics/PublishDiagnosticsEvent.kt @@ -40,7 +40,7 @@ class PublishDiagnosticsEvent : EventListener { val lspEditor = context.get("lsp-editor") val originEditor = lspEditor.editor ?: return - val data = context.get>("data") + val data = context.getOrNull>("data") ?: return val diagnosticsContainer = originEditor.diagnostics ?: DiagnosticsContainer() @@ -51,7 +51,10 @@ class PublishDiagnosticsEvent : EventListener { data.transformToEditorDiagnostics(originEditor) ) - originEditor.diagnostics = diagnosticsContainer + // run on ui thread + originEditor.post { + originEditor.diagnostics = diagnosticsContainer + } } diff --git a/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/events/diagnostics/QueryDocumentDiagnosticsEvent.kt b/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/events/diagnostics/QueryDocumentDiagnosticsEvent.kt index db69233f1..5271e5bb3 100644 --- a/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/events/diagnostics/QueryDocumentDiagnosticsEvent.kt +++ b/editor-lsp/src/main/java/io/github/rosemoe/sora/lsp/events/diagnostics/QueryDocumentDiagnosticsEvent.kt @@ -48,22 +48,10 @@ class QueryDocumentDiagnosticsEvent : AsyncEventListener() { .diagnostic( editor.uri.createDocumentDiagnosticParams() ) - .thenApply { either: DocumentDiagnosticReport -> - if (either.isRelatedFullDocumentDiagnosticReport) - either.relatedFullDocumentDiagnosticReport - .relatedDocuments - else - either.relatedUnchangedDocumentDiagnosticReport - .relatedDocuments - } this.future = future.thenAccept { } - val result = future.await() - - if (result.isEmpty()) { - return - } + val result = future.await() ?: return context.put("diagnostics", result) }