From 28a48b9a0c6378d05da685d32f8dbc20f2403e1a Mon Sep 17 00:00:00 2001 From: Akash Yadav Date: Tue, 10 Aug 2021 10:29:00 +0530 Subject: [PATCH] v1.0.3-alpha - Implemented 'Go to Definition' - Partially implemented 'Find all references' (without UI) --- .../com/itsaky/androidide/EditorActivity.java | 134 ++++++++++++++++-- .../adapters/EditorPagerAdapter.java | 20 ++- .../adapters/SearchListAdapter.java | 7 + .../androidide/fragments/EditorFragment.java | 36 ++++- .../androidide/interfaces/JLSRequestor.java | 3 + .../java/server/JavaLanguageServer.java | 66 ++++++++- .../rosemoe/editor/widget/CodeEditor.java | 31 ++++ .../widget/EditorTextActionModeStarter.java | 16 ++- app/src/main/res/drawable/ic_search.xml | 10 ++ app/src/main/res/layout/activity_editor.xml | 48 ++++++- app/src/main/res/layout/layout_sheet.xml | 2 +- app/src/main/res/values/strings.xml | 3 + .../java/com/itsaky/lsp/LanguageClient.java | 4 + .../main/java/com/itsaky/lsp/Location.java | 6 + lsp/src/main/java/com/itsaky/lsp/Range.java | 4 + .../java/com/itsaky/lsp/ReferenceContext.java | 6 + 16 files changed, 373 insertions(+), 23 deletions(-) create mode 100644 app/src/main/java/com/itsaky/androidide/adapters/SearchListAdapter.java create mode 100644 app/src/main/res/drawable/ic_search.xml diff --git a/app/src/main/java/com/itsaky/androidide/EditorActivity.java b/app/src/main/java/com/itsaky/androidide/EditorActivity.java index 54ed2d5e7..a6e1c6246 100644 --- a/app/src/main/java/com/itsaky/androidide/EditorActivity.java +++ b/app/src/main/java/com/itsaky/androidide/EditorActivity.java @@ -6,9 +6,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.graphics.Color; -import android.graphics.PorterDuff; import android.graphics.Rect; -import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.os.Bundle; import android.text.SpannableStringBuilder; @@ -33,6 +31,7 @@ import com.blankj.utilcode.util.FileUtils; import com.blankj.utilcode.util.IntentUtils; import com.blankj.utilcode.util.KeyboardUtils; import com.blankj.utilcode.util.SizeUtils; +import com.blankj.utilcode.util.ThrowableUtils; import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.navigation.NavigationView; import com.google.android.material.tabs.TabLayout; @@ -43,6 +42,7 @@ import com.google.gson.JsonElement; import com.google.gson.JsonParser; import com.itsaky.androidide.adapters.DiagnosticsAdapter; import com.itsaky.androidide.adapters.EditorPagerAdapter; +import com.itsaky.androidide.adapters.SearchListAdapter; import com.itsaky.androidide.adapters.viewholders.FileTreeViewHolder; import com.itsaky.androidide.app.StudioActivity; import com.itsaky.androidide.databinding.ActivityEditorBinding; @@ -67,12 +67,14 @@ import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE; import com.itsaky.androidide.tasks.GradleTask; import com.itsaky.androidide.tasks.TaskExecutor; import com.itsaky.androidide.utils.Environment; +import com.itsaky.androidide.utils.Logger; import com.itsaky.androidide.utils.PreferenceManager; import com.itsaky.androidide.utils.ProjectWriter; import com.itsaky.androidide.utils.Symbols; import com.itsaky.androidide.utils.TypefaceUtils; import com.itsaky.androidide.utils.VersionedFileManager; import com.itsaky.androidide.views.MaterialBanner; +import com.itsaky.androidide.views.SymbolInputView; import com.itsaky.lsp.Diagnostic; import com.itsaky.lsp.DidChangeTextDocumentParams; import com.itsaky.lsp.DidChangeWatchedFilesParams; @@ -85,9 +87,12 @@ import com.itsaky.lsp.JavaColors; import com.itsaky.lsp.JavaReportProgressParams; import com.itsaky.lsp.JavaStartProgressParams; import com.itsaky.lsp.LanguageClient; +import com.itsaky.lsp.Location; import com.itsaky.lsp.Message; import com.itsaky.lsp.ParameterInformation; import com.itsaky.lsp.PublishDiagnosticsParams; +import com.itsaky.lsp.Range; +import com.itsaky.lsp.ReferenceParams; import com.itsaky.lsp.ShowMessageParams; import com.itsaky.lsp.SignatureHelp; import com.itsaky.lsp.SignatureInformation; @@ -108,7 +113,6 @@ import java.util.Stack; import java.util.regex.Pattern; import me.piruin.quickaction.ActionItem; import me.piruin.quickaction.QuickAction; -import com.itsaky.androidide.views.SymbolInputView; public class EditorActivity extends StudioActivity implements FileTreeFragment.FileActionListener, IDEService.BuildListener, @@ -129,6 +133,7 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F private CodeEditor buildView; private CodeEditor logView; private RecyclerView diagnosticList; + private RecyclerView searchResultList; private SymbolInputView symbolInput; private LogLanguageImpl mLogLanguageImpl; @@ -262,6 +267,10 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F if(getDiagnosticsList().getParent() != null && getDiagnosticsList().getParent() instanceof ViewGroup) { ((ViewGroup) getDiagnosticsList().getParent()).removeView(getDiagnosticsList()); } + + if(getSearchResultList().getParent() != null && getSearchResultList().getParent() instanceof ViewGroup) { + ((ViewGroup) getSearchResultList().getParent()).removeView(getSearchResultList()); + } mBinding.buildOutcontainer.addView(getBuildView(), new ViewGroup.LayoutParams(-1, -1)); mBinding.buildContainer.setVisibility(View.GONE); @@ -277,6 +286,11 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F mBinding.diagContainer.setVisibility(View.GONE); mBinding.diagToolbar.setNavigationOnClickListener(v -> hideDiagnostics()); mBinding.diagToolbar.setOnClickListener(v -> hideDiagnostics()); + + mBinding.searchResultsListContainer.addView(getSearchResultList(), new ViewGroup.LayoutParams(-1, -1)); + mBinding.searchResultsContainer.setVisibility(View.GONE); + mBinding.searchResultsToolbar.setNavigationOnClickListener(v -> hideSearchResults()); + mBinding.searchResultsToolbar.setOnClickListener(v -> hideSearchResults()); mBinding.viewOptionsCard.setVisibility(View.GONE); mBinding.transformScrim.setVisibility(View.GONE); @@ -284,6 +298,7 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F mBinding.transformScrim.setOnClickListener(v -> hideViewOptions()); mBinding.viewBuildOut.setOnClickListener(v -> showBuildResult()); mBinding.viewDiags.setOnClickListener(v -> showDiagnostics()); + mBinding.viewSearchResults.setOnClickListener(v -> showSearchResults()); mBinding.viewLogs.setOnClickListener(v -> showLogResult()); mBinding.viewFiles.setOnClickListener(v -> showFiles()); mBinding.viewDaemonStatus.setOnClickListener(v -> showDaemonStatus()); @@ -334,6 +349,8 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F hideViewOptions(); } else if(mBinding.diagContainer.getVisibility() == View.VISIBLE) { hideDiagnostics(); + } else if(mBinding.searchResultsContainer.getVisibility() == View.VISIBLE) { + hideSearchResults(); } else if(mFileOptionsFragment != null && mFileOptionsFragment.isShowing()) { mFileOptionsFragment.dismiss(); } else { @@ -661,6 +678,20 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F mBinding.diagContainer.setVisibility(View.GONE); mBinding.viewOptionsCard.setVisibility(View.VISIBLE); } + + private void showSearchResults() { + TransitionManager.beginDelayedTransition(mBinding.getRoot(), createContainerTransformFor(mBinding.viewSearchResults, mBinding.searchResultsContainer)); + mBinding.diagContainer.setVisibility(View.VISIBLE); + mBinding.viewOptionsCard.setVisibility(View.GONE); + hideToolbarAndTabs(); + } + + private void hideSearchResults() { + showToolbarAndTabs(); + TransitionManager.beginDelayedTransition(mBinding.getRoot(), createContainerTransformFor(mBinding.searchResultsContainer, mBinding.viewSearchResults)); + mBinding.diagContainer.setVisibility(View.GONE); + mBinding.viewOptionsCard.setVisibility(View.VISIBLE); + } private MaterialContainerTransform createContainerTransformFor(View start, View end) { return createContainerTransformFor(start, end, mBinding.realContainer); @@ -917,6 +948,72 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F server.signatureHelp(params, file); else addPendingMessage(createMessage(JavaLanguageServer.Method.DID_SAVE, gson.toJson(params))); } + + @Override + public void findDefinition(TextDocumentPositionParams params) { + final JavaLanguageServer server = getApp().getJavaLanguageServer(); + if(server == null) return; + server.findDefinition(params); + } + + @Override + public void gotoDefinition(List locations) { + if(locations == null || locations.size() <= 0) { + getApp().toast(R.string.msg_no_definition, Toaster.Type.ERROR); + return; + } + Location loc = locations.get(0); + final File file = new File(loc.uri); + final Range range = loc.range; + try { + if(mPagerAdapter == null) return; + if(mPagerAdapter.getCount() <= 0) { + openFile(file, range); + return; + } + EditorFragment frag = mPagerAdapter.getFrag(mBinding.tabs.getSelectedTabPosition()); + if(frag != null + && frag.getFile() != null + && frag.getEditor() != null + && frag.getFile().getAbsolutePath().equals(file.getAbsolutePath())) { + if(range.start.equals(range.end)) { + frag.getEditor().setSelection(range.start.line, range.start.character); + } else { + frag.getEditor().setSelectionRegion(range.start.line, range.start.character, range.end.line, range.end.character); + } + } else { + openFile(file, range); + EditorFragment opened = mPagerAdapter.findEditorByFile(file); + if(opened != null && opened.getEditor() != null) { + CodeEditor editor = opened.getEditor(); + editor.post(() -> { + if(range.start.equals(range.end)) { + editor.setSelection(range.start.line, range.start.character); + } else { + editor.setSelectionRegion(range.start.line, range.start.character, range.end.line, range.end.character); + } + }); + } + } + } catch (Throwable th) { + Logger.instance().e(ThrowableUtils.getFullStackTrace(th)); + } + } + + @Override + public void findReferences(ReferenceParams params) { + final JavaLanguageServer server = getApp().getJavaLanguageServer(); + if(server == null) return; + server.findReferences(params); + } + + @Override + public void references(List references) { + if(references == null || references.size() <= 0) { + getApp().toast(R.string.msg_no_references, Toaster.Type.INFO); + return; + } + } private void addPendingMessage(Message msg) { pendingMessages.push(msg); @@ -1105,6 +1202,17 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F return diagnosticList; } + private RecyclerView getSearchResultList() { + return searchResultList == null ? createSearchResultList() : searchResultList; + } + + private RecyclerView createSearchResultList() { + searchResultList = new RecyclerView(this); + searchResultList.setLayoutManager(new LinearLayoutManager(this)); + searchResultList.setAdapter(new SearchListAdapter()); + return searchResultList; + } + private List mapAsGroup(Map> diags) { List groups = new ArrayList<>(); if(diags == null || diags.size() <= 0) @@ -1129,12 +1237,22 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F @Override public void openFile(File file) { - int i = mPagerAdapter.openFile(file, this, this); - if(i >= 0 && !mBinding.tabs.getTabAt(i).isSelected()) - mBinding.tabs.getTabAt(i).select(); - mBinding.editorDrawerLayout.closeDrawer(GravityCompat.END); - invalidateOptionsMenu(); + openFile(file, null); } + + public EditorFragment openFile(File file, Range selection) { + if(selection == null) selection = Range.ofZero(); + int i = mPagerAdapter.openFile(file, selection, this, this); + if(i >= 0 && !mBinding.tabs.getTabAt(i).isSelected()) + mBinding.tabs.getTabAt(i).select(); + mBinding.editorDrawerLayout.closeDrawer(GravityCompat.END); + invalidateOptionsMenu(); + try { + return mPagerAdapter.getFrag(i); + } catch (Throwable th) { + return null; + } + } @Override public void onOpenSuccessful(File file, String text) { diff --git a/app/src/main/java/com/itsaky/androidide/adapters/EditorPagerAdapter.java b/app/src/main/java/com/itsaky/androidide/adapters/EditorPagerAdapter.java index 11a3fa74d..8b744edda 100644 --- a/app/src/main/java/com/itsaky/androidide/adapters/EditorPagerAdapter.java +++ b/app/src/main/java/com/itsaky/androidide/adapters/EditorPagerAdapter.java @@ -10,6 +10,7 @@ import java.io.File; import java.util.ArrayList; import java.util.List; import com.itsaky.androidide.interfaces.JLSRequestor; +import com.itsaky.lsp.Range; public class EditorPagerAdapter extends FragmentStatePagerAdapter { @@ -36,21 +37,28 @@ public class EditorPagerAdapter extends FragmentStatePagerAdapter mFragments.addAll(fragments); } - public EditorFragment findEditorByFile(File file) { + public int findIndexOfEditorByFile(File file) { for(int i=0;i { binding.editor.setText(result); postRead(); + binding.editor.post(() -> { + if(range.start.equals(range.end)) { + getEditor().setSelection(range.start.line, range.start.character); + } else { + getEditor().setSelectionRegion(range.start.line, range.start.character, range.end.line, range.end.character); + } + }); }); } + + private Range fromArgs(Bundle args) { + if(!(args.containsKey(KEY_LINE_START) + && args.containsKey(KEY_COLUMN_START) + && args.containsKey(KEY_LINE_END) + && args.containsKey(KEY_COLUMN_END))) + return Range.ofZero(); + + return new Range( + new Position( + args.getInt(KEY_LINE_START), + args.getInt(KEY_COLUMN_START)), + new Position( + args.getInt(KEY_LINE_END), + args.getInt(KEY_COLUMN_END) + )); + } public void setDiagnostics(List diags) { if(binding.editor != null && diags != null) { diff --git a/app/src/main/java/com/itsaky/androidide/interfaces/JLSRequestor.java b/app/src/main/java/com/itsaky/androidide/interfaces/JLSRequestor.java index d1412facc..da8061c37 100644 --- a/app/src/main/java/com/itsaky/androidide/interfaces/JLSRequestor.java +++ b/app/src/main/java/com/itsaky/androidide/interfaces/JLSRequestor.java @@ -7,6 +7,7 @@ import com.itsaky.lsp.DidOpenTextDocumentParams; import com.itsaky.lsp.DidSaveTextDocumentParams; import com.itsaky.lsp.TextDocumentPositionParams; import java.io.File; +import com.itsaky.lsp.ReferenceParams; public interface JLSRequestor { @@ -19,4 +20,6 @@ public interface JLSRequestor { void didChangeWatchedFiles(DidChangeWatchedFilesParams params); void signatureHelp(TextDocumentPositionParams params, File file); + void findDefinition(TextDocumentPositionParams params); + void findReferences(ReferenceParams params); } diff --git a/app/src/main/java/com/itsaky/androidide/language/java/server/JavaLanguageServer.java b/app/src/main/java/com/itsaky/androidide/language/java/server/JavaLanguageServer.java index f2f23d5db..3ec782823 100644 --- a/app/src/main/java/com/itsaky/androidide/language/java/server/JavaLanguageServer.java +++ b/app/src/main/java/com/itsaky/androidide/language/java/server/JavaLanguageServer.java @@ -12,6 +12,7 @@ import com.itsaky.androidide.app.StudioApp; import com.itsaky.androidide.models.AndroidProject; import com.itsaky.androidide.shell.ShellServer; import com.itsaky.androidide.utils.Environment; +import com.itsaky.androidide.utils.FileUtil; import com.itsaky.androidide.utils.Logger; import com.itsaky.lsp.CancelParams; import com.itsaky.lsp.CodeActionParams; @@ -37,6 +38,7 @@ import com.itsaky.lsp.TextEdit; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; @@ -46,6 +48,9 @@ import java.util.List; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentHashMap; +import com.itsaky.lsp.Location; +import com.google.gson.reflect.TypeToken; +import com.itsaky.lsp.ReferenceParams; public class JavaLanguageServer implements ShellServer.Callback { @@ -60,6 +65,8 @@ public class JavaLanguageServer implements ShellServer.Callback { private final ConcurrentHashMap completionRequests = new ConcurrentHashMap<>(); private final ConcurrentHashMap formattingRequests = new ConcurrentHashMap<>(); + private final ConcurrentHashMap definitionRequests = new ConcurrentHashMap<>(); + private final ConcurrentHashMap referencesRequests = new ConcurrentHashMap<>(); private final ConcurrentHashMap signatureRequests = new ConcurrentHashMap<>(); private final BlockingQueue completionResponseQueue = new ArrayBlockingQueue<>(20); @@ -226,6 +233,16 @@ public class JavaLanguageServer implements ShellServer.Callback { signatureRequests.put(id, file); } + public void findDefinition(TextDocumentPositionParams params) { + int id = write(Method.DEFINITION, gson.toJson(params)); + definitionRequests.put(id, id); + } + + public void findReferences(ReferenceParams params) { + int id = write(Method.REFERENCES, gson.toJson(params)); + referencesRequests.put(id, id); + } + public void cancelRequest(int requestId) { CancelParams p = new CancelParams(); p.id = requestId; @@ -266,12 +283,41 @@ public class JavaLanguageServer implements ShellServer.Callback { @Override public void output(CharSequence charSequence) { + writeOut(charSequence.toString()); + } + + private BufferedOutputStream os; + private BufferedOutputStream os1; + + private void writeOut(String data) { + try { + if(os == null) { + os = new BufferedOutputStream(new FileOutputStream(new File(FileUtil.getExternalStorageDir(), "ide_xlog/out.txt"), true)); + } + os.write(data.getBytes()); + os.flush(); + } catch (Throwable th) { + logger.e(ThrowableUtils.getFullStackTrace(th)); + } + } + + private void writeOut2(String data) { + try { + if(os1 == null) { + os1 = new BufferedOutputStream(new FileOutputStream(new File(FileUtil.getExternalStorageDir(), "ide_xlog/verbose.txt"), true)); + } + os1.write(data.getBytes()); + os1.flush(); + } catch (Throwable th) { + logger.e(ThrowableUtils.getFullStackTrace(th)); + } } /** * This method is called on UI Thread, do not perform time consuming or networking tasks */ private void onServerOut(String line) { + writeOut2(line + "\n"); if(line.contains(CONTENT_LENGTH)) line = line.substring(0, line.lastIndexOf(CONTENT_LENGTH)); if(this.client == null) return; try { @@ -294,11 +340,10 @@ public class JavaLanguageServer implements ShellServer.Callback { client.javaProgressEnd(); } else if(method.equals(Method.JAVA_COLORS)) { JavaColors colors = gson.fromJson(obj.get(Key.PARAMS).toString(), JavaColors.class); - logger.v(colors.toString()); client.javaColors(colors); } } else if(obj.has(Key.ID)) { - int id = obj.get(Key.ID).getAsInt(); + final int id = obj.get(Key.ID).getAsInt(); if(completionRequests.containsKey(id)) { final CompletionList list = gson.fromJson(obj.get(Key.RESULT).getAsJsonObject(), CompletionList.class); completionResponseQueue.put(list); @@ -311,6 +356,22 @@ public class JavaLanguageServer implements ShellServer.Callback { } catch ( Throwable th) { client.signatureHelp(null, null); } + } else if(definitionRequests.containsKey(id)) { + try { + final List locations = gson.fromJson(obj.get(Key.RESULT).getAsJsonArray(), new TypeToken>(){}.getType()); + if(locations != null && locations.size() > 0) + client.gotoDefinition(locations); + } catch (Throwable th) { + client.gotoDefinition(null); + } + } else if(referencesRequests.containsKey(id)) { + try { + final List locations = gson.fromJson(obj.get(Key.RESULT).getAsJsonArray(), new TypeToken>(){}.getType()); + if(locations != null && locations.size() > 0) + client.references(locations); + } catch (Throwable th) { + client.references(null); + } } } } catch (Throwable th) { @@ -339,6 +400,7 @@ public class JavaLanguageServer implements ShellServer.Callback { public static final String HOVER = "textDocument/hover"; public static final String SIGNATURE_HELP = "textDocument/signatureHelp"; public static final String DEFINITION = "textDocument/definition"; + public static final String REFERENCES = "textDocument/references"; public static final String PREPARE_RENAME = "textDocument/prepareRename"; public static final String RENAME = "textDocument/rename"; diff --git a/app/src/main/java/io/github/rosemoe/editor/widget/CodeEditor.java b/app/src/main/java/io/github/rosemoe/editor/widget/CodeEditor.java index 9a027b9af..57ca79dd3 100644 --- a/app/src/main/java/io/github/rosemoe/editor/widget/CodeEditor.java +++ b/app/src/main/java/io/github/rosemoe/editor/widget/CodeEditor.java @@ -96,6 +96,12 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; +import com.itsaky.androidide.utils.Logger; +import com.blankj.utilcode.util.ThrowableUtils; +import com.itsaky.lsp.TextDocumentPositionParams; +import com.itsaky.lsp.TextDocumentIdentifier; +import com.itsaky.lsp.ReferenceParams; +import com.itsaky.lsp.ReferenceContext; /** * CodeEditor is a editor that can highlight text regions by doing basic syntax analyzing @@ -4414,6 +4420,31 @@ public class CodeEditor extends View implements ContentListener, TextAnalyzer.Ca public void uncommentSelected() { } + + public void findDefinition() { + if(jlsRequestor == null || getFile() == null) return; + try { + TextDocumentPositionParams params = new TextDocumentPositionParams(); + params.position = new Position(getCursor().getLeftLine(), getCursor().getLeftColumn()); + params.textDocument = new TextDocumentIdentifier(getFile().toURI()); + jlsRequestor.findDefinition(params); + } catch (Throwable th) { + Logger.instance("CodeEditor").e(ThrowableUtils.getFullStackTrace(th)); + } + } + + public void findReferences() { + if(jlsRequestor == null || getFile() == null) return; + try { + ReferenceParams params = new ReferenceParams(); + params.context = new ReferenceContext(true); + params.position = new Position(getCursor().getLeftLine(), getCursor().getLeftColumn()); + params.textDocument = new TextDocumentIdentifier(getFile().toURI()); + jlsRequestor.findReferences(params); + } catch (Throwable th) { + Logger.instance("CodeEditor").e(ThrowableUtils.getFullStackTrace(th)); + } + } @Override public void afterInsert(Content content, int startLine, int startColumn, int endLine, int endColumn, CharSequence insertedContent) { diff --git a/app/src/main/java/io/github/rosemoe/editor/widget/EditorTextActionModeStarter.java b/app/src/main/java/io/github/rosemoe/editor/widget/EditorTextActionModeStarter.java index 1cf4406ec..cf32a93ee 100644 --- a/app/src/main/java/io/github/rosemoe/editor/widget/EditorTextActionModeStarter.java +++ b/app/src/main/java/io/github/rosemoe/editor/widget/EditorTextActionModeStarter.java @@ -68,7 +68,8 @@ class EditorTextActionModeStarter implements CodeEditor.EditorTextActionPresente menu.add(0, 3, 0, mEditor.getContext().getString(android.R.string.paste)) .setShowAsActionFlags(2) .setIcon(array.getDrawable(3)); - + menu.add(0, 4, 0, "Go to Definition"); + menu.add(0, 5, 0, "Find all references"); array.recycle(); return true; } @@ -86,16 +87,22 @@ class EditorTextActionModeStarter implements CodeEditor.EditorTextActionPresente break; case 1: mEditor.cutText(); - onExit(); break; case 2: mEditor.copyText(); - onExit(); break; case 3: mEditor.pasteText(); - onExit(); + break; + case 4: + mEditor.findDefinition(); + break; + case 5: + mEditor.findReferences(); + break; } + if(menuItem.getItemId() != 0) + onExit(); return false; } @@ -126,6 +133,7 @@ class EditorTextActionModeStarter implements CodeEditor.EditorTextActionPresente int column = IntPair.getSecond(packed); mEditor.setSelection(line, column); mEditor.hideAutoCompleteWindow(); + mEditor.hideDiagnosticWindow(); } @Override diff --git a/app/src/main/res/drawable/ic_search.xml b/app/src/main/res/drawable/ic_search.xml new file mode 100644 index 000000000..090645da3 --- /dev/null +++ b/app/src/main/res/drawable/ic_search.xml @@ -0,0 +1,10 @@ + + + + diff --git a/app/src/main/res/layout/activity_editor.xml b/app/src/main/res/layout/activity_editor.xml index b5fbf1321..2707243d5 100644 --- a/app/src/main/res/layout/activity_editor.xml +++ b/app/src/main/res/layout/activity_editor.xml @@ -145,6 +145,23 @@ app:iconTint="@color/primaryIconColor" app:cornerRadius="0dp" app:icon="@drawable/ic_diagnostics" + app:backgroundTint="@color/primaryColor" + app:rippleColor="@color/rippleHighlightColor_light"/> + + @@ -292,6 +309,36 @@ + + + + + + + + - diff --git a/app/src/main/res/layout/layout_sheet.xml b/app/src/main/res/layout/layout_sheet.xml index 3af4515b0..6bf298896 100644 --- a/app/src/main/res/layout/layout_sheet.xml +++ b/app/src/main/res/layout/layout_sheet.xml @@ -18,7 +18,7 @@ android:ellipsize="end" android:textColor="@color/primaryTextColor" android:elevation="0dp" - android:background="@android:color/transparent" + android:background="@color/primaryDarkColor" app:rippleColor="@color/rippleHighlightColor" app:icon="@drawable/ic_chevron_down" app:iconPadding="8dp" diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f632f3746..42b943b34 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,4 +1,7 @@ + Search results + Definition not found + No references found AndroidIDE uses a modified build of the JDK which is licensed under the GNU General Public License v2.0. The source code and the license of the JDK can be found in the JDK itself or at : Developers \u2022 Akash Yadav\n\u2022 Marvin Stelter diff --git a/lsp/src/main/java/com/itsaky/lsp/LanguageClient.java b/lsp/src/main/java/com/itsaky/lsp/LanguageClient.java index a6d7ef853..a3263081f 100644 --- a/lsp/src/main/java/com/itsaky/lsp/LanguageClient.java +++ b/lsp/src/main/java/com/itsaky/lsp/LanguageClient.java @@ -2,6 +2,7 @@ package com.itsaky.lsp; import com.google.gson.JsonElement; import java.io.File; +import java.util.List; public interface LanguageClient { void javaProgressStart(JavaStartProgressParams params); @@ -9,6 +10,9 @@ public interface LanguageClient { void javaProgressEnd(); void publishDiagnostics(PublishDiagnosticsParams params); + + void gotoDefinition(List locations); + void references(List references); void signatureHelp(SignatureHelp signature, File file); void javaColors(JavaColors colors); diff --git a/lsp/src/main/java/com/itsaky/lsp/Location.java b/lsp/src/main/java/com/itsaky/lsp/Location.java index 690930b87..03c060144 100644 --- a/lsp/src/main/java/com/itsaky/lsp/Location.java +++ b/lsp/src/main/java/com/itsaky/lsp/Location.java @@ -2,6 +2,7 @@ package com.itsaky.lsp; import com.google.gson.annotations.SerializedName; import java.net.URI; +import com.google.gson.GsonBuilder; public class Location { @SerializedName("uri") @@ -17,5 +18,10 @@ public class Location { this.range = range; } + @Override + public String toString() { + return new GsonBuilder().setPrettyPrinting().create().toJson(this); + } + public static final Location NONE = new Location(null, Range.NONE); } diff --git a/lsp/src/main/java/com/itsaky/lsp/Range.java b/lsp/src/main/java/com/itsaky/lsp/Range.java index 8143b3f2f..e4e259868 100644 --- a/lsp/src/main/java/com/itsaky/lsp/Range.java +++ b/lsp/src/main/java/com/itsaky/lsp/Range.java @@ -31,6 +31,10 @@ public class Range { } return false; } + + public static Range ofZero() { + return new Range(new Position(0, 0), new Position(0, 0)); + } public static final Range NONE = new Range(Position.NONE, Position.NONE); } diff --git a/lsp/src/main/java/com/itsaky/lsp/ReferenceContext.java b/lsp/src/main/java/com/itsaky/lsp/ReferenceContext.java index 68848897f..06dad5742 100644 --- a/lsp/src/main/java/com/itsaky/lsp/ReferenceContext.java +++ b/lsp/src/main/java/com/itsaky/lsp/ReferenceContext.java @@ -6,4 +6,10 @@ public class ReferenceContext { @SerializedName("includeDeclaration") public boolean includeDeclaration; + + public ReferenceContext(){} + + public ReferenceContext(boolean includeDeclaration) { + this.includeDeclaration = includeDeclaration; + } }