mirror of
https://gitee.com/zhangsken/AndroidIDE.git
synced 2026-10-16 07:49:44 +08:00
New feature: Expand selection
Expand the current selection in editor using the 'Expand selection' option
This commit is contained in:
Generated
+1
@@ -3,6 +3,7 @@
|
||||
<component name="DesignSurface">
|
||||
<option name="filePathToZoomLevelMap">
|
||||
<map>
|
||||
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/drawable-hdpi/ic_expand_selection.xml" value="0.20833333333333334" />
|
||||
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/drawable/bg_design_container_background.xml" value="0.1" />
|
||||
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/drawable/bg_ui_view_pressed.xml" value="0.1" />
|
||||
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/drawable/ic_github.xml" value="0.21837606837606838" />
|
||||
|
||||
Binary file not shown.
@@ -81,6 +81,7 @@ import com.itsaky.lsp.models.DocumentChangeEvent;
|
||||
import com.itsaky.lsp.models.DocumentCloseEvent;
|
||||
import com.itsaky.lsp.models.DocumentOpenEvent;
|
||||
import com.itsaky.lsp.models.DocumentSaveEvent;
|
||||
import com.itsaky.lsp.models.ExpandSelectionParams;
|
||||
import com.itsaky.lsp.models.Position;
|
||||
import com.itsaky.lsp.models.Range;
|
||||
import com.itsaky.lsp.models.ReferenceParams;
|
||||
@@ -3528,6 +3529,17 @@ public class CodeEditor extends View implements ContentListener, TextAnalyzer.Ca
|
||||
setSelectionRegion (0, 0, getLineCount () - 1, getText ().getColumnCount (getLineCount () - 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set selection to the given range.
|
||||
* @param range The range to select.
|
||||
*/
|
||||
public void setSelection (Range range) {
|
||||
setSelectionRegion (range.getStart ().getLine (),
|
||||
range.getStart ().getColumn (),
|
||||
range.getEnd ().getLine (),
|
||||
range.getEnd ().getColumn ());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set selection region with a call to {@link CodeEditor#ensureSelectionVisible()}
|
||||
*
|
||||
@@ -4634,6 +4646,36 @@ public class CodeEditor extends View implements ContentListener, TextAnalyzer.Ca
|
||||
)));
|
||||
}
|
||||
|
||||
public void expandSelection () {
|
||||
if (mLanguageServer == null || getFile () == null) {
|
||||
LOG.error ("Cannot expand selection. Language server or file is null");
|
||||
return;
|
||||
}
|
||||
|
||||
final var pd = ProgressDialog.show (getContext (), null, getContext ().getString (R.string.please_wait), true, false);
|
||||
final CompletableFuture<Range> future = CompletableFuture.supplyAsync (() ->
|
||||
mLanguageServer.getSelectionProvider ()
|
||||
.expandSelection (
|
||||
new ExpandSelectionParams (
|
||||
getFile ().toPath (),
|
||||
getCursorRange ()
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
future.whenComplete (((range, throwable) -> {
|
||||
|
||||
pd.dismiss ();
|
||||
|
||||
if (throwable != null) {
|
||||
LOG.error ("Error computing expanded selection range", throwable);
|
||||
return;
|
||||
}
|
||||
|
||||
setSelection (range);
|
||||
}));
|
||||
}
|
||||
|
||||
public Position getCursorAsLSPPosition () {
|
||||
return new Position (getCursor ().getLeftLine (), getCursor ().getLeftColumn ());
|
||||
}
|
||||
|
||||
+16
-84
@@ -36,6 +36,7 @@ import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.blankj.utilcode.util.SizeUtils;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.itsaky.androidide.R;
|
||||
import com.itsaky.androidide.app.StudioApp;
|
||||
import com.itsaky.androidide.utils.DialogUtils;
|
||||
import com.itsaky.lsp.models.CodeActionItem;
|
||||
@@ -84,23 +85,27 @@ class EditorTextActionModeStarter implements CodeEditor.EditorTextActionPresente
|
||||
android.R.attr.actionModePasteDrawable,
|
||||
});
|
||||
|
||||
menu.add (0, 8, 0, R.string.action_expand_selection)
|
||||
.setShowAsActionFlags (1)
|
||||
.setIcon (createDrawable (R.drawable.ic_expand_selection));
|
||||
|
||||
menu.add(0, 0, 0, mEditor.getContext().getString(android.R.string.selectAll))
|
||||
.setShowAsActionFlags(2)
|
||||
.setShowAsActionFlags(1)
|
||||
.setIcon(array.getDrawable(0));
|
||||
|
||||
if (mEditor.isEditable()) {
|
||||
menu.add(0, 1, 0, mEditor.getContext().getString(android.R.string.cut))
|
||||
.setShowAsActionFlags(2)
|
||||
.setShowAsActionFlags(1)
|
||||
.setIcon(array.getDrawable(1));
|
||||
}
|
||||
|
||||
menu.add(0, 2, 0, mEditor.getContext().getString(android.R.string.copy))
|
||||
.setShowAsActionFlags(2)
|
||||
.setShowAsActionFlags(1)
|
||||
.setIcon(array.getDrawable(2));
|
||||
|
||||
if (mEditor.isEditable()) {
|
||||
menu.add(0, 3, 0, mEditor.getContext().getString(android.R.string.paste))
|
||||
.setShowAsActionFlags(2)
|
||||
.setShowAsActionFlags(1)
|
||||
.setIcon(array.getDrawable(3));
|
||||
}
|
||||
|
||||
@@ -191,18 +196,16 @@ class EditorTextActionModeStarter implements CodeEditor.EditorTextActionPresente
|
||||
mEditor.uncommentLine();
|
||||
break;
|
||||
case 8 :
|
||||
if (fixes == null || fixes.isEmpty()) {
|
||||
StudioApp.getInstance().toast(com.itsaky.androidide.R.string.msg_no_code_actions, Toaster.Type.INFO);
|
||||
break;
|
||||
}
|
||||
showFixes();
|
||||
mEditor.expandSelection ();
|
||||
break;
|
||||
}
|
||||
|
||||
if (menuItem.getItemId() != 0) {
|
||||
onExit();
|
||||
|
||||
final var id = menuItem.getItemId ();
|
||||
if (id == 0 || id == 8) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
return onExit ();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -211,77 +214,6 @@ class EditorTextActionModeStarter implements CodeEditor.EditorTextActionPresente
|
||||
mActionMode = null;
|
||||
mEditor.setSelection(mEditor.getCursor().getLeftLine(), mEditor.getCursor().getLeftColumn());
|
||||
}
|
||||
|
||||
void showFixes() {
|
||||
final MaterialAlertDialogBuilder builder = DialogUtils.newMaterialDialogBuilder (mEditor.getContext ());
|
||||
builder.setTitle(com.itsaky.androidide.R.string.msg_code_actions);
|
||||
builder.setView(createFixesListView());
|
||||
builder.show();
|
||||
}
|
||||
|
||||
ListView createFixesListView() {
|
||||
final ListView list = new ListView(mEditor.getContext());
|
||||
final QuickFixAdapter adapter = new QuickFixAdapter(fixes);
|
||||
list.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
list.setAdapter(adapter);
|
||||
list.setOnItemClickListener((a, b, c, d) -> performCodeAction(adapter.getItem(c)));
|
||||
return list;
|
||||
}
|
||||
|
||||
class QuickFixAdapter extends BaseAdapter {
|
||||
|
||||
private final List<CodeActionItem> actions;
|
||||
private final int dp16 = SizeUtils.dp2px(16);
|
||||
private final int dp4 = SizeUtils.dp2px(4);
|
||||
private final int dp48 = SizeUtils.dp2px(48);
|
||||
|
||||
public QuickFixAdapter(List<CodeActionItem> actions) {
|
||||
this.actions = actions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return actions.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodeActionItem getItem(int position) {
|
||||
return actions.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
if (convertView == null) {
|
||||
convertView = createItemTextView(position, parent);
|
||||
}
|
||||
return convertView;
|
||||
}
|
||||
|
||||
private View createItemTextView(int position, ViewGroup parent) {
|
||||
final var action = getItem(position);
|
||||
final TextView text = new TextView(parent.getContext());
|
||||
final String title = action.getTitle();
|
||||
|
||||
text.setText(title);
|
||||
text.setPaddingRelative(dp16, dp4, dp16, dp4);
|
||||
text.setMinHeight(dp48);
|
||||
text.setGravity(Gravity.CENTER_VERTICAL);
|
||||
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
void performCodeAction(CodeActionItem action) {
|
||||
if (mEditor.getLanguageClient() != null) {
|
||||
mEditor.getLanguageClient().performCodeAction(mEditor, action);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<!-- drawable/arrow_expand_all.xml -->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:height="24dp"
|
||||
android:width="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path android:fillColor="#ffffff" android:pathData="M9.5,13.09L10.91,14.5L6.41,19H10V21H3V14H5V17.59L9.5,13.09M10.91,9.5L9.5,10.91L5,6.41V10H3V3H10V5H6.41L10.91,9.5M14.5,13.09L19,17.59V14H21V21H14V19H17.59L13.09,14.5L14.5,13.09M13.09,9.5L17.59,5H14V3H21V10H19V6.41L14.5,10.91L13.09,9.5Z" />
|
||||
</vector>
|
||||
@@ -156,7 +156,7 @@
|
||||
<string name="template_navigation_drawer">Navigation drawer project</string>
|
||||
<string name="template_kotlin_basic">Kotlin Basic Project</string>
|
||||
<string name="template_description_kotlin_basic">Kotlin project with Appcompat Toolbar and a Floating Action Button</string>
|
||||
|
||||
|
||||
<!-- Files -->
|
||||
<string name="save">Save</string>
|
||||
<string name="show_files">Files</string>
|
||||
@@ -354,5 +354,6 @@
|
||||
<string name="msg_compiler_module_install">Compiler module is being installed, please wait…</string>
|
||||
<string name="msg_compiler_module_install_failed">Compiler module installation failed. The error was:\n%s</string>
|
||||
<string name="msg_compiler_module_installed">Compiler module installed successfully!</string>
|
||||
|
||||
<string name="action_expand_selection">Expand selection</string>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -131,6 +131,14 @@ public interface ILanguageServer {
|
||||
@NonNull
|
||||
IDefinitionProvider getDefinitionProvider();
|
||||
|
||||
/**
|
||||
* Get the selection provider associated with this language server.
|
||||
*
|
||||
* @return The selection provider instance.
|
||||
*/
|
||||
@NonNull
|
||||
ISelectionProvider getSelectionProvider ();
|
||||
|
||||
/**
|
||||
* Get the signature help provider associated with this language server.
|
||||
* @return The signature help provider.
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* This file is part of AndroidIDE.
|
||||
*
|
||||
* AndroidIDE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AndroidIDE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.lsp.api;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.itsaky.lsp.models.ExpandSelectionParams;
|
||||
import com.itsaky.lsp.models.Range;
|
||||
|
||||
/**
|
||||
* A selection provider provides features such as
|
||||
* expanding the current selection.
|
||||
*
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
public interface ISelectionProvider {
|
||||
|
||||
/**
|
||||
* Request sent by client for expanding the current selection.
|
||||
* <p>
|
||||
* Example: If a statement in a method body is selected,
|
||||
* the provider returns the range of the method body as the expanded selection.
|
||||
* </p>
|
||||
*
|
||||
* @param params The params for expanding the selection.
|
||||
* @return The expanded selection range. Or same range as params if cannot be expanded.
|
||||
*/
|
||||
Range expandSelection (@NonNull ExpandSelectionParams params);
|
||||
}
|
||||
@@ -41,6 +41,14 @@ public interface IServerSettings {
|
||||
*/
|
||||
boolean codeActionsEnabled ();
|
||||
|
||||
/**
|
||||
* Called by language server to check if
|
||||
* smart selections are enabled or not.
|
||||
*
|
||||
* @return {@code true} if enabled, {@code false} otherwise.
|
||||
*/
|
||||
boolean smartSelectionsEnabled ();
|
||||
|
||||
/**
|
||||
* Called by the language server to check if the signature
|
||||
* help is enabled.
|
||||
|
||||
@@ -142,7 +142,44 @@ open class Range(var start: Position, var end: Position) : Comparable<Range> {
|
||||
return start.line <= line && end.line >= line
|
||||
}
|
||||
|
||||
fun containsColumn (column: Int): Boolean {
|
||||
return start.column <= column && end.column >= column
|
||||
}
|
||||
|
||||
fun containsRange (other: Range) : Boolean {
|
||||
if (!containsLine(other.start.line) || !containsLine(other.end.line)) {
|
||||
return false
|
||||
}
|
||||
|
||||
return containsColumn(other.start.column) && containsColumn(other.end.column);
|
||||
}
|
||||
|
||||
fun isSmallerThan (other: Range) : Boolean {
|
||||
return other.isBiggerThan(this)
|
||||
}
|
||||
|
||||
fun isBiggerThan (other: Range) : Boolean {
|
||||
|
||||
if (equals(other)) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (start.line < other.start.line && end.line > other.end.line) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (start.line == other.start.line && end.line == other.end.line) {
|
||||
if (start.column <= other.start.column && end.column >= other.end.column) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "Range(start=$start, end=$end)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class ExpandSelectionParams (var file: Path, var selection: Range)
|
||||
@@ -27,6 +27,7 @@ import com.itsaky.lsp.api.IServerSettings
|
||||
class DefaultServerSettings : IServerSettings {
|
||||
override fun completionsEnabled(): Boolean = true
|
||||
override fun codeActionsEnabled(): Boolean = true
|
||||
override fun smartSelectionsEnabled(): Boolean = true
|
||||
override fun signatureHelpEnabled(): Boolean = true
|
||||
override fun referencesEnabled(): Boolean = true
|
||||
override fun definitionsEnabled(): Boolean = true
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* This file is part of AndroidIDE.
|
||||
*
|
||||
* AndroidIDE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AndroidIDE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.lsp.util
|
||||
|
||||
import com.itsaky.lsp.api.ISelectionProvider
|
||||
import com.itsaky.lsp.models.ExpandSelectionParams
|
||||
import com.itsaky.lsp.models.Range
|
||||
|
||||
/**
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
class NoSelectionProvider : ISelectionProvider {
|
||||
override fun expandSelection(params: ExpandSelectionParams): Range = params.selection;
|
||||
}
|
||||
@@ -29,6 +29,7 @@ import com.itsaky.lsp.api.IDocumentHandler;
|
||||
import com.itsaky.lsp.api.ILanguageClient;
|
||||
import com.itsaky.lsp.api.ILanguageServer;
|
||||
import com.itsaky.lsp.api.IReferenceProvider;
|
||||
import com.itsaky.lsp.api.ISelectionProvider;
|
||||
import com.itsaky.lsp.api.IServerSettings;
|
||||
import com.itsaky.lsp.api.ISignatureHelpProvider;
|
||||
import com.itsaky.lsp.java.compiler.JavaCompilerService;
|
||||
@@ -37,6 +38,7 @@ import com.itsaky.lsp.java.providers.CodeActionProvider;
|
||||
import com.itsaky.lsp.java.providers.CompletionProvider;
|
||||
import com.itsaky.lsp.java.providers.DefinitionProvider;
|
||||
import com.itsaky.lsp.java.providers.JavaCodeAnalyzer;
|
||||
import com.itsaky.lsp.java.providers.JavaSelectionProvider;
|
||||
import com.itsaky.lsp.java.providers.ReferenceProvider;
|
||||
import com.itsaky.lsp.java.providers.SignatureProvider;
|
||||
import com.itsaky.lsp.models.DocumentChangeEvent;
|
||||
@@ -51,6 +53,7 @@ import com.itsaky.lsp.util.NoCodeAnalyzer;
|
||||
import com.itsaky.lsp.util.NoCompletionsProvider;
|
||||
import com.itsaky.lsp.util.NoDefinitionProvider;
|
||||
import com.itsaky.lsp.util.NoReferenceProvider;
|
||||
import com.itsaky.lsp.util.NoSelectionProvider;
|
||||
import com.itsaky.lsp.util.NoSignatureHelpProvider;
|
||||
|
||||
import java.util.Collections;
|
||||
@@ -208,6 +211,16 @@ public class JavaLanguageServer implements ILanguageServer, IDocumentHandler {
|
||||
return new DefinitionProvider (getCompiler ());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ISelectionProvider getSelectionProvider () {
|
||||
if (!settings.smartSelectionsEnabled ()) {
|
||||
return new NoSelectionProvider ();
|
||||
}
|
||||
|
||||
return new JavaSelectionProvider (getCompiler ());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ISignatureHelpProvider getSignatureHelpProvider () {
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* This file is part of AndroidIDE.
|
||||
*
|
||||
* AndroidIDE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AndroidIDE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.lsp.java.providers;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.itsaky.androidide.utils.Logger;
|
||||
import com.itsaky.lsp.api.ISelectionProvider;
|
||||
import com.itsaky.lsp.java.compiler.CompilerProvider;
|
||||
import com.itsaky.lsp.java.visitors.FindBiggerRange;
|
||||
import com.itsaky.lsp.models.ExpandSelectionParams;
|
||||
import com.itsaky.lsp.models.Position;
|
||||
import com.itsaky.lsp.models.Range;
|
||||
import com.sun.source.tree.CompilationUnitTree;
|
||||
import com.sun.source.tree.LineMap;
|
||||
import com.sun.source.tree.Tree;
|
||||
import com.sun.source.util.SourcePositions;
|
||||
import com.sun.source.util.TreePath;
|
||||
import com.sun.source.util.Trees;
|
||||
|
||||
/**
|
||||
* Selection provider implementation for Java.
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
public class JavaSelectionProvider implements ISelectionProvider {
|
||||
|
||||
private final CompilerProvider compiler;
|
||||
|
||||
private static final Logger LOG = Logger.instance ("JavaSelectionProvider");
|
||||
|
||||
public JavaSelectionProvider (CompilerProvider compiler) {
|
||||
this.compiler = compiler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Range expandSelection (@NonNull ExpandSelectionParams params) {
|
||||
return compiler.compile (params.getFile ()).getWithTask (task -> {
|
||||
final CompilationUnitTree root = task.root (params.getFile ());
|
||||
final FindBiggerRange rangeFinder = new FindBiggerRange (task.task, root);
|
||||
final Range range = rangeFinder.scan (root, params.getSelection ());
|
||||
|
||||
if (range != null) {
|
||||
LOG.debug ("Expanding selection to range", range);
|
||||
return range;
|
||||
}
|
||||
|
||||
LOG.debug ("Unable to expand selection");
|
||||
return params.getSelection ();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* This file is part of AndroidIDE.
|
||||
*
|
||||
* AndroidIDE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AndroidIDE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.lsp.java.visitors;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.itsaky.androidide.utils.Logger;
|
||||
import com.itsaky.lsp.models.Position;
|
||||
import com.itsaky.lsp.models.Range;
|
||||
import com.sun.source.tree.BlockTree;
|
||||
import com.sun.source.tree.CatchTree;
|
||||
import com.sun.source.tree.ClassTree;
|
||||
import com.sun.source.tree.CompilationUnitTree;
|
||||
import com.sun.source.tree.LineMap;
|
||||
import com.sun.source.tree.MethodTree;
|
||||
import com.sun.source.tree.SynchronizedTree;
|
||||
import com.sun.source.tree.Tree;
|
||||
import com.sun.source.tree.TryTree;
|
||||
import com.sun.source.util.JavacTask;
|
||||
import com.sun.source.util.SourcePositions;
|
||||
import com.sun.source.util.TreeScanner;
|
||||
import com.sun.source.util.Trees;
|
||||
|
||||
/**
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
public class FindBiggerRange extends TreeScanner<Range, Range> {
|
||||
|
||||
private final SourcePositions positions;
|
||||
private final CompilationUnitTree root;
|
||||
private final LineMap lineMap;
|
||||
|
||||
public FindBiggerRange (JavacTask task, @NonNull CompilationUnitTree root) {
|
||||
this.positions = Trees.instance (task).getSourcePositions ();
|
||||
this.root = root;
|
||||
this.lineMap = root.getLineMap ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Range scan (Tree tree, Range range) {
|
||||
final Range smallerThanThis = super.scan (tree, range);
|
||||
if (smallerThanThis != null) {
|
||||
return smallerThanThis;
|
||||
}
|
||||
|
||||
final Range treeRange = getRange (tree);
|
||||
if (treeRange != null && range.isSmallerThan (treeRange)) {
|
||||
Logger.instance ("FindBiggerRange").debug ("Selecting tree", tree, tree.getClass (), tree.getKind ());
|
||||
return treeRange;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Range visitTry (TryTree node, Range range) {
|
||||
|
||||
// If this try's body or finally block is selected, then select the entire try
|
||||
final Range methodRange = getRange (node);
|
||||
final Range blockRange = getRange (node.getBlock ());
|
||||
final Range finallyRange = getRange (node.getFinallyBlock ());
|
||||
if ((range.equals (blockRange) || range.equals (finallyRange)) && methodRange != null) {
|
||||
return methodRange;
|
||||
}
|
||||
|
||||
return super.visitTry (node, range);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Range visitMethod (MethodTree node, Range range) {
|
||||
|
||||
// If this methods body is selected, then select the entire method
|
||||
final Range methodRange = getRange (node);
|
||||
final Range blockRange = getRange (node.getBody ());
|
||||
if (range.equals (blockRange) && methodRange != null) {
|
||||
return methodRange;
|
||||
}
|
||||
|
||||
return super.visitMethod (node, range);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Range reduce (Range r1, Range r2) {
|
||||
return r1 == null ? r2 : r1;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Range getRange (Tree leaf) {
|
||||
final Range range = new Range ();
|
||||
final Position start = new Position (0,0);
|
||||
final Position end = new Position (0,0);
|
||||
|
||||
final long startPos = positions.getStartPosition (root, leaf);
|
||||
final long endPos = positions.getEndPosition (root, leaf);
|
||||
|
||||
if (startPos == -1 || endPos == -1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
start.setLine ((int) lineMap.getLineNumber (startPos) - 1);
|
||||
start.setColumn ((int) lineMap.getColumnNumber (startPos) - 1);
|
||||
|
||||
end.setLine ((int) lineMap.getLineNumber (endPos) - 1);
|
||||
end.setColumn ((int) lineMap.getColumnNumber (endPos) - 1);
|
||||
|
||||
range.setStart (start);
|
||||
range.setEnd (end);
|
||||
|
||||
return range;
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import com.sun.source.util.*;
|
||||
import javax.lang.model.element.Name;
|
||||
|
||||
public class FindNameAt extends TreePathScanner<TreePath, Long> {
|
||||
|
||||
private final JavacTask task;
|
||||
private CompilationUnitTree root;
|
||||
private ClassTree surroundingClass;
|
||||
|
||||
Reference in New Issue
Block a user