diff --git a/app/src/main/assets/data/common/tooling-api-all.jar b/app/src/main/assets/data/common/tooling-api-all.jar index 5cca62173..0b1235328 100644 Binary files a/app/src/main/assets/data/common/tooling-api-all.jar and b/app/src/main/assets/data/common/tooling-api-all.jar differ diff --git a/editor/src/main/java/com/itsaky/androidide/editor/ui/IDEEditor.java b/editor/src/main/java/com/itsaky/androidide/editor/ui/IDEEditor.java index 3a52dff25..45bd7d62c 100644 --- a/editor/src/main/java/com/itsaky/androidide/editor/ui/IDEEditor.java +++ b/editor/src/main/java/com/itsaky/androidide/editor/ui/IDEEditor.java @@ -27,13 +27,13 @@ import android.app.ProgressDialog; import android.content.Context; import android.graphics.Rect; import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; import android.util.AttributeSet; import android.view.inputmethod.EditorInfo; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.UiThread; - import com.blankj.utilcode.util.ThreadUtils; import com.itsaky.androidide.editor.adapters.CompletionListAdapter; import com.itsaky.androidide.editor.api.IEditor; @@ -61,12 +61,6 @@ import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE; import com.itsaky.androidide.utils.DocumentUtils; import com.itsaky.androidide.utils.FlashbarUtilsKt; import com.itsaky.androidide.utils.ILogger; - -import org.greenrobot.eventbus.EventBus; - -import java.io.File; -import java.util.concurrent.CompletableFuture; - import io.github.rosemoe.sora.event.ContentChangeEvent; import io.github.rosemoe.sora.event.SelectionChangeEvent; import io.github.rosemoe.sora.event.Unsubscribe; @@ -74,9 +68,14 @@ import io.github.rosemoe.sora.widget.CodeEditor; import io.github.rosemoe.sora.widget.IDEEditorSearcher; import io.github.rosemoe.sora.widget.component.EditorAutoCompletion; import io.github.rosemoe.sora.widget.component.EditorTextActionWindow; +import java.io.File; +import java.util.concurrent.CompletableFuture; +import org.greenrobot.eventbus.EventBus; public class IDEEditor extends CodeEditor implements IEditor, ILspEditor { + private static final long SELECTION_CHANGE_DELAY = 500; + private static final ILogger LOG = ILogger.newInstance("IDEEditor"); @Nullable private EditorActionsMenu actionsMenu; @@ -87,7 +86,24 @@ public class IDEEditor extends CodeEditor implements IEditor, ILspEditor { private ILanguageServer languageServer; private SignatureHelpWindow signatureHelpWindow; private DiagnosticWindow diagnosticWindow; - @Nullable ILanguageClient languageClient; + @Nullable + ILanguageClient languageClient; + + private final Handler selectionChangeHandler = new Handler(Looper.getMainLooper()); + + @Nullable + private Runnable selectionChangeRunner = () -> { + final var cursor = getCursor(); + if (languageClient == null || cursor == null || cursor.isSelected()) { + return; + } + + final var line = cursor.getLeftLine(); + final var column = cursor.getLeftColumn(); + + // diagnostics are expected to be sorted, so, we do a binary search + getDiagnosticWindow().showDiagnostic(languageClient.getDiagnosticAt(getFile(), line, column)); + }; public IDEEditor(Context context) { this(context, null); @@ -103,7 +119,7 @@ public class IDEEditor extends CodeEditor implements IEditor, ILspEditor { public IDEEditor(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); - + this.isModified = false; this.actionsMenu = new EditorActionsMenu(this); this.actionsMenu.init(); @@ -122,17 +138,14 @@ public class IDEEditor extends CodeEditor implements IEditor, ILspEditor { } private void handleSelectionChange(@NonNull SelectionChangeEvent event, Unsubscribe unsubscribe) { - if (event.isSelected() || languageClient == null) { - // do not show diagnostics when text is selected - // or if we cannot get diagnostics - return; + if (getDiagnosticWindow().isShowing()) { + getDiagnosticWindow().dismiss(); } - final var line = event.getLeft().line; - final var column = event.getLeft().column; - - // diagnostics are expected to be sorted, so, we do a binary search - getDiagnosticWindow().showDiagnostic(languageClient.getDiagnosticAt(getFile(), line, column)); + if (selectionChangeRunner != null) { + selectionChangeHandler.removeCallbacks(selectionChangeRunner); + selectionChangeHandler.postDelayed(selectionChangeRunner, SELECTION_CHANGE_DELAY); + } } private DiagnosticWindow getDiagnosticWindow() { @@ -165,7 +178,7 @@ public class IDEEditor extends CodeEditor implements IEditor, ILspEditor { dispatchDocumentOpenEvent(); } } - + @NonNull @Override public Bundle getExtraArguments() { @@ -174,7 +187,7 @@ public class IDEEditor extends CodeEditor implements IEditor, ILspEditor { args.putString(KEY_FILE, path); return args; } - + protected void dispatchDocumentOpenEvent() { if (getFile() == null) { return; @@ -220,12 +233,12 @@ public class IDEEditor extends CodeEditor implements IEditor, ILspEditor { }); } } - + @Override public int getTabWidth() { return getTabSize(); } - + /** * Shows the given signature help in the editor. * @@ -307,10 +320,10 @@ public class IDEEditor extends CodeEditor implements IEditor, ILspEditor { final var end = range.getEnd(); final var text = getText(); final var lineCount = text.getLineCount(); - + start.setLine(min(max(0, start.getLine()), lineCount - 1)); start.setColumn(min(max(0, start.getColumn()), text.getColumnCount(start.getLine()))); - + end.setLine(min(max(0, end.getLine()), lineCount - 1)); end.setColumn(min(max(0, end.getColumn()), text.getColumnCount(end.getLine()))); } @@ -365,7 +378,7 @@ public class IDEEditor extends CodeEditor implements IEditor, ILspEditor { /** * Checks if the given column is valid for this editor's text. * - * @param line The line of the column to check. + * @param line The line of the column to check. * @param column The column to check. * @return true if valid, false otherwise. */ @@ -388,7 +401,7 @@ public class IDEEditor extends CodeEditor implements IEditor, ILspEditor { * it'll be set to {@link ILanguageClient} set in the language server. * * @param server The server to set. Provide null to disable all the language server - * features. + * features. */ @Override public void setLanguageServer(ILanguageServer server) { @@ -425,7 +438,9 @@ public class IDEEditor extends CodeEditor implements IEditor, ILspEditor { return line; } - /** Set the selection of the editor's cursor to the last line of the it's content. */ + /** + * Set the selection of the editor's cursor to the last line of the it's content. + */ @Override public void goToEnd() { final var line = getText().getLineCount() - 1; @@ -543,8 +558,7 @@ public class IDEEditor extends CodeEditor implements IEditor, ILspEditor { return; } - @SuppressWarnings("deprecation") - final ProgressDialog pd = + @SuppressWarnings("deprecation") final ProgressDialog pd = ProgressDialog.show( getContext(), null, getContext().getString(string.msg_finding_references)); @@ -661,7 +675,9 @@ public class IDEEditor extends CodeEditor implements IEditor, ILspEditor { } } - /** Ensures that all the windows are dismissed. */ + /** + * Ensures that all the windows are dismissed. + */ @Override public void ensureWindowsDismissed() { if (getDiagnosticWindow().isShowing()) { @@ -671,7 +687,7 @@ public class IDEEditor extends CodeEditor implements IEditor, ILspEditor { if (getSignatureHelpWindow().isShowing()) { getSignatureHelpWindow().dismiss(); } - + if (actionsMenu != null && actionsMenu.isShowing()) { actionsMenu.dismiss(); } @@ -782,7 +798,9 @@ public class IDEEditor extends CodeEditor implements IEditor, ILspEditor { } } - /** Notify the language server that the file in this editor is about to be closed. */ + /** + * Notify the language server that the file in this editor is about to be closed. + */ public void notifyClose() { if (getFile() == null) { LOG.info("No language server is available for this file"); @@ -790,19 +808,25 @@ public class IDEEditor extends CodeEditor implements IEditor, ILspEditor { } dispatchDocumentCloseEvent(); - + if (actionsMenu != null) { actionsMenu.unsubscribeEvents(); } + + if (selectionChangeRunner != null) { + this.selectionChangeHandler.removeCallbacks(selectionChangeRunner); + this.selectionChangeRunner = null; + } + ensureWindowsDismissed(); } - + @Override public void release() { super.release(); this.actionsMenu = null; } - + protected void dispatchDocumentCloseEvent() { if (getFile() == null) { return;