mirror of
https://gitee.com/zhangsken/AndroidIDE.git
synced 2026-10-16 07:49:44 +08:00
Added action to override multiple methods at once
This commit is contained in:
Generated
+2
@@ -4,6 +4,8 @@
|
||||
<option name="SPACE_BEFORE_OPENING_ANGLE_BRACKET_IN_TYPE_PARAMETER" value="true" />
|
||||
</JavaCodeStyleSettings>
|
||||
<JetCodeStyleSettings>
|
||||
<option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="2147483647" />
|
||||
<option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="2147483647" />
|
||||
<option name="ALLOW_TRAILING_COMMA" value="true" />
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
</JetCodeStyleSettings>
|
||||
|
||||
@@ -139,7 +139,7 @@ public class CursorCodeActionProvider {
|
||||
if (classTree == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
|
||||
final TreePath classPath = trees.getPath(task.root(), classTree);
|
||||
final Elements elements = task.task.getElements();
|
||||
final TypeElement classElement = (TypeElement) trees.getElement(classPath);
|
||||
|
||||
+8
-1
@@ -152,6 +152,13 @@ class GenerateSettersAndGettersAction : BaseCodeAction() {
|
||||
->
|
||||
if (error != null) {
|
||||
log.error("Unable to generate setters and getters", error)
|
||||
ThreadUtils.runOnUiThread {
|
||||
BaseApplication.getBaseInstance()
|
||||
.toast(
|
||||
data[Context::class.java]!!.getString(
|
||||
R.string.msg_cannot_generate_setters_getters),
|
||||
Toaster.Type.ERROR)
|
||||
}
|
||||
return@whenComplete
|
||||
}
|
||||
}
|
||||
@@ -201,7 +208,7 @@ class GenerateSettersAndGettersAction : BaseCodeAction() {
|
||||
|
||||
log.debug("Creating setters/getters for fields", fields.map { it.name })
|
||||
|
||||
generateForFields(data, task, type, fields.map { TreePath(typeFinder.storedPath, it) })
|
||||
generateForFields(data, task, type, fields.map { TreePath(typeFinder.path, it) })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ class JavaCodeActionsMenu : CodeActionsMenu() {
|
||||
addAction(SuppressUncheckedWarningAction())
|
||||
addAction(AddThrowsAction())
|
||||
addAction(GenerateSettersAndGettersAction())
|
||||
addAction(OverrideSuperclassMethodsAction())
|
||||
addAction(GenerateConstructorAction())
|
||||
}
|
||||
}
|
||||
|
||||
+277
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
* 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.actions
|
||||
|
||||
import android.content.Context
|
||||
import com.blankj.utilcode.util.ThreadUtils
|
||||
import com.itsaky.androidide.actions.ActionData
|
||||
import com.itsaky.androidide.app.BaseApplication
|
||||
import com.itsaky.androidide.utils.Logger
|
||||
import com.itsaky.lsp.java.JavaLanguageServer
|
||||
import com.itsaky.lsp.java.R
|
||||
import com.itsaky.lsp.java.rewrite.AddImport
|
||||
import com.itsaky.lsp.java.utils.EditHelper
|
||||
import com.itsaky.lsp.java.utils.FindHelper
|
||||
import com.itsaky.lsp.java.utils.JavaPoetUtils
|
||||
import com.itsaky.lsp.java.utils.MethodPtr
|
||||
import com.itsaky.lsp.java.visitors.FindTypeDeclarationAt
|
||||
import com.itsaky.lsp.models.Position
|
||||
import com.itsaky.lsp.models.Range
|
||||
import com.itsaky.toaster.Toaster
|
||||
import com.sun.source.util.Trees
|
||||
import io.github.rosemoe.sora.widget.CodeEditor
|
||||
import java.util.*
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import javax.lang.model.element.ElementKind
|
||||
import javax.lang.model.element.ExecutableElement
|
||||
import javax.lang.model.element.Modifier
|
||||
import javax.lang.model.element.TypeElement
|
||||
import javax.lang.model.type.DeclaredType
|
||||
|
||||
/**
|
||||
* Allows the user to override multiple methods from superclass at once.
|
||||
*
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
class OverrideSuperclassMethodsAction : BaseCodeAction() {
|
||||
override val titleTextRes: Int = R.string.action_override_superclass_methods
|
||||
override val id: String = "lsp_java_overrideSuperclassMethods"
|
||||
override var label: String = "Override superclass methods"
|
||||
private val log = Logger.newInstance(javaClass.simpleName)
|
||||
private var position: Long = -1
|
||||
|
||||
override fun prepare(data: ActionData) {
|
||||
super.prepare(data)
|
||||
|
||||
if (!visible || !hasRequiredData(data, Range::class.java, CodeEditor::class.java)) {
|
||||
markInvisible()
|
||||
return
|
||||
}
|
||||
|
||||
visible = true
|
||||
enabled = true
|
||||
}
|
||||
|
||||
override fun execAction(data: ActionData): Any {
|
||||
val range = data[Range::class.java]!!
|
||||
val server = data[JavaLanguageServer::class.java]!!
|
||||
val file = requirePath(data)
|
||||
|
||||
return server.compiler.compile(file).get { task ->
|
||||
// 1-based line and column index
|
||||
val startLine = range.start.line + 1
|
||||
val startColumn = range.start.column + 1
|
||||
val endLine = range.end.line + 1
|
||||
val endColumn = range.end.column + 1
|
||||
val lines = task.root().lineMap
|
||||
val start = lines.getPosition(startLine.toLong(), startColumn.toLong())
|
||||
val end = lines.getPosition(endLine.toLong(), endColumn.toLong())
|
||||
|
||||
if (start == (-1).toLong() || end == (-1).toLong()) {
|
||||
return@get false
|
||||
}
|
||||
|
||||
this.position = start
|
||||
val typeFinder = FindTypeDeclarationAt(task.task)
|
||||
var type = typeFinder.scan(task.root(file), start)
|
||||
if (type == null) {
|
||||
type = typeFinder.scan(task.root(file), end)
|
||||
position = end
|
||||
}
|
||||
|
||||
if (type == null) {
|
||||
return@get false
|
||||
}
|
||||
|
||||
val overridable = mutableListOf<MethodPtr>()
|
||||
val trees = Trees.instance(task.task)
|
||||
val elements = task.task.elements
|
||||
val classPath = typeFinder.path
|
||||
val element = trees.getElement(classPath) as TypeElement
|
||||
|
||||
for (member in elements.getAllMembers(element)) {
|
||||
if (member.modifiers.contains(Modifier.FINAL) ||
|
||||
member.kind != ElementKind.METHOD) {
|
||||
continue
|
||||
}
|
||||
|
||||
val method = member as ExecutableElement
|
||||
val methodSource = member.getEnclosingElement() as TypeElement
|
||||
if (methodSource.qualifiedName.contentEquals("java.lang.Object") ||
|
||||
methodSource == element) {
|
||||
continue
|
||||
}
|
||||
|
||||
val pointer = MethodPtr(task.task, method)
|
||||
overridable.add(pointer)
|
||||
}
|
||||
|
||||
return@get overridable
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun postExec(data: ActionData, result: Any) {
|
||||
if (result !is List<*> || result.isEmpty() || position < 0) {
|
||||
log.warn("Unable to find any overridable method")
|
||||
BaseApplication.getBaseInstance()
|
||||
.toast(
|
||||
data[Context::class.java]!!.getString(R.string.msg_no_overridable_methods),
|
||||
Toaster.Type.ERROR)
|
||||
return
|
||||
}
|
||||
|
||||
val methods = (result as List<MethodPtr>).sortedBy { it.methodName }
|
||||
val checkedMethods = mutableListOf<MethodPtr>()
|
||||
val names = mapMethodPointers(methods)
|
||||
val builder = newDialogBuilder(data)
|
||||
builder.setTitle(data[Context::class.java]!!.getString(R.string.msg_select_methods))
|
||||
builder.setMultiChoiceItems(names, BooleanArray(names.size)) { _, which, isChecked ->
|
||||
checkedMethods.apply {
|
||||
if (isChecked) {
|
||||
add(methods[which])
|
||||
} else {
|
||||
remove(methods[which])
|
||||
}
|
||||
}
|
||||
}
|
||||
builder.setPositiveButton(android.R.string.ok) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
|
||||
if (checkedMethods.isEmpty()) {
|
||||
BaseApplication.getBaseInstance()
|
||||
.toast(
|
||||
data[Context::class.java]!!.getString(R.string.msg_no_methods_selected),
|
||||
Toaster.Type.ERROR)
|
||||
return@setPositiveButton
|
||||
}
|
||||
|
||||
CompletableFuture.runAsync { overrideMethods(data, checkedMethods) }.whenComplete {
|
||||
_,
|
||||
error,
|
||||
->
|
||||
if (error != null) {
|
||||
log.error("An error occurred overriding methods")
|
||||
|
||||
ThreadUtils.runOnUiThread {
|
||||
BaseApplication.getBaseInstance()
|
||||
.toast(
|
||||
data[Context::class.java]!!.getString(
|
||||
R.string.msg_cannot_override_methods),
|
||||
Toaster.Type.ERROR)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
builder.setNegativeButton(android.R.string.cancel, null)
|
||||
builder.show()
|
||||
}
|
||||
|
||||
private fun overrideMethods(data: ActionData, checkedMethods: MutableList<MethodPtr>) {
|
||||
val server = data[JavaLanguageServer::class.java]!!
|
||||
val file = requirePath(data)
|
||||
|
||||
server.compiler.compile(file).run { task ->
|
||||
val types = task.task.types
|
||||
val trees = Trees.instance(task.task)
|
||||
val sb = StringBuilder()
|
||||
val imports = mutableSetOf<String>()
|
||||
|
||||
val typeFinder = FindTypeDeclarationAt(task.task)
|
||||
val classTree = typeFinder.scan(task.root(), position)
|
||||
val thisClass = trees.getElement(typeFinder.path) as TypeElement
|
||||
val indent = EditHelper.indent(task.task, task.root(), classTree) + 4
|
||||
|
||||
for (pointer in checkedMethods) {
|
||||
val superMethod =
|
||||
FindHelper.findMethod(
|
||||
task, pointer.className, pointer.methodName, pointer.erasedParameterTypes)
|
||||
|
||||
val thisDeclaredType = thisClass.asType() as DeclaredType
|
||||
val spec = JavaPoetUtils.buildMethod(superMethod, types, thisDeclaredType).build()
|
||||
|
||||
sb.append("\n")
|
||||
sb.append(JavaPoetUtils.print(spec, imports, false))
|
||||
sb.replace(Regex(Regex.escape("\n")), "\n${EditHelper.repeatSpaces(indent)}")
|
||||
sb.append("\n")
|
||||
}
|
||||
|
||||
ThreadUtils.runOnUiThread {
|
||||
performEdits(
|
||||
data,
|
||||
sb,
|
||||
imports,
|
||||
EditHelper.insertAtEndOfClass(task.task, task.root(file), classTree))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun performEdits(
|
||||
data: ActionData,
|
||||
sb: StringBuilder,
|
||||
imports: MutableSet<String>,
|
||||
position: Position
|
||||
) {
|
||||
val server = data[JavaLanguageServer::class.java]!!
|
||||
val editor = data[CodeEditor::class.java]!!
|
||||
val file = requirePath(data)
|
||||
val text = editor.text
|
||||
|
||||
text.beginBatchEdit()
|
||||
|
||||
text.insert(position.line, position.column, sb)
|
||||
|
||||
for (name in imports) {
|
||||
val rewrite = AddImport(file, name)
|
||||
val edits = rewrite.rewrite(server.compiler)[file]
|
||||
if (edits == null || edits.isEmpty()) {
|
||||
continue
|
||||
}
|
||||
|
||||
for (edit in edits) {
|
||||
if (edit.range.start == edit.range.end) {
|
||||
text.insert(edit.range.start.line, edit.range.start.column, edit.newText)
|
||||
} else {
|
||||
text.replace(
|
||||
edit.range.start.line,
|
||||
edit.range.start.column,
|
||||
edit.range.end.line,
|
||||
edit.range.end.column,
|
||||
edit.newText)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
text.endBatchEdit()
|
||||
editor.formatCodeAsync()
|
||||
}
|
||||
|
||||
private fun mapMethodPointers(methods: List<MethodPtr>): Array<CharSequence> {
|
||||
return methods
|
||||
.map { Arrays.toString(it.simplifiedErasedParameterTypes) }
|
||||
.map {
|
||||
val arr = it.toCharArray()
|
||||
arr[0] = '('
|
||||
arr[arr.size - 1] = ')'
|
||||
|
||||
String(arr)
|
||||
}
|
||||
.mapIndexed { index, params -> "${methods[index].methodName}$params" }
|
||||
.toTypedArray()
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ package com.itsaky.lsp.java.providers;
|
||||
|
||||
import static com.itsaky.lsp.java.utils.EditHelper.addImportIfNeeded;
|
||||
import static com.itsaky.lsp.java.utils.EditHelper.repeatSpaces;
|
||||
import static com.itsaky.lsp.java.utils.JavaPoetUtils.buildMethod;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
@@ -46,7 +47,6 @@ import com.itsaky.lsp.models.CompletionItemKind;
|
||||
import com.itsaky.lsp.models.CompletionParams;
|
||||
import com.itsaky.lsp.models.CompletionResult;
|
||||
import com.itsaky.lsp.models.InsertTextFormat;
|
||||
import com.squareup.javapoet.AnnotationSpec;
|
||||
import com.squareup.javapoet.MethodSpec;
|
||||
import com.sun.source.tree.ClassTree;
|
||||
import com.sun.source.tree.CompilationUnitTree;
|
||||
@@ -76,7 +76,6 @@ import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.ElementKind;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
@@ -86,8 +85,6 @@ import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.element.VariableElement;
|
||||
import javax.lang.model.type.ArrayType;
|
||||
import javax.lang.model.type.DeclaredType;
|
||||
import javax.lang.model.type.NoType;
|
||||
import javax.lang.model.type.TypeKind;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.type.TypeVariable;
|
||||
import javax.lang.model.util.Types;
|
||||
@@ -886,32 +883,7 @@ public class CompletionProvider extends AbstractServiceProvider implements IComp
|
||||
|
||||
// Print the method details and the annotations
|
||||
final int indent = EditHelper.indent(FileStore.contents(completingFile), (int) this.cursor);
|
||||
final MethodSpec.Builder builder = MethodSpec.overriding(method, type, types);
|
||||
final List<? extends AnnotationMirror> mirrors = method.getAnnotationMirrors();
|
||||
if (mirrors != null && !mirrors.isEmpty()) {
|
||||
for (final AnnotationMirror mirror : mirrors) {
|
||||
if (mirror.getAnnotationType().getKind() != TypeKind.NULL) {
|
||||
builder.addAnnotation(AnnotationSpec.get(mirror));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean addComment = true;
|
||||
// Add super call if the method is not abstract
|
||||
if (!method.getModifiers().contains(Modifier.ABSTRACT)) {
|
||||
if (method.getReturnType() instanceof NoType) {
|
||||
builder.addStatement(createSuperCall(builder));
|
||||
} else {
|
||||
addComment = false;
|
||||
builder.addComment("TODO: Implement this method");
|
||||
builder.addStatement("return " + createSuperCall(builder));
|
||||
}
|
||||
}
|
||||
|
||||
if (addComment) {
|
||||
builder.addComment("TODO: Implement this method");
|
||||
}
|
||||
|
||||
final MethodSpec.Builder builder = buildMethod(method, types, type);
|
||||
final Set<String> imports = new HashSet<>();
|
||||
final MethodSpec methodSpec = builder.build();
|
||||
String insertText = JavaPoetUtils.print(methodSpec, imports, false);
|
||||
@@ -946,28 +918,6 @@ public class CompletionProvider extends AbstractServiceProvider implements IComp
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a superclass method invocation statement.
|
||||
*
|
||||
* @param builder The method builder.
|
||||
* @return The super invocation statement string without ending ';'.
|
||||
*/
|
||||
@NonNull
|
||||
private String createSuperCall(@NonNull MethodSpec.Builder builder) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("super.");
|
||||
sb.append(builder.name);
|
||||
sb.append("(");
|
||||
for (int i = 0; i < builder.parameters.size(); i++) {
|
||||
sb.append(builder.parameters.get(i).name);
|
||||
if (i != builder.parameters.size() - 1) {
|
||||
sb.append(", ");
|
||||
}
|
||||
}
|
||||
sb.append(")");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private CompletionData data(CompileTask task, Element element, int overloads) {
|
||||
CompletionData data = new CompletionData();
|
||||
|
||||
@@ -17,29 +17,88 @@
|
||||
|
||||
package com.itsaky.lsp.java.utils
|
||||
|
||||
import com.squareup.javapoet.AnnotationSpec
|
||||
import com.squareup.javapoet.ImportCollectingCodeWriter
|
||||
import com.squareup.javapoet.MethodSpec
|
||||
import javax.lang.model.element.ExecutableElement
|
||||
import javax.lang.model.element.Modifier
|
||||
import javax.lang.model.type.DeclaredType
|
||||
import javax.lang.model.type.NoType
|
||||
import javax.lang.model.type.TypeKind
|
||||
import javax.lang.model.util.Types
|
||||
|
||||
/**
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
/** @author Akash Yadav */
|
||||
class JavaPoetUtils {
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun print(method: MethodSpec, importsOut: MutableSet<String>, qualifiedNames: Boolean = true): String {
|
||||
fun print(
|
||||
method: MethodSpec,
|
||||
importsOut: MutableSet<String>,
|
||||
qualifiedNames: Boolean = true,
|
||||
): String {
|
||||
val sb = StringBuilder()
|
||||
val writer = ImportCollectingCodeWriter(sb)
|
||||
|
||||
writer.setPrintQualifiedNames(qualifiedNames)
|
||||
|
||||
writer.isPrintQualifiedNames = qualifiedNames
|
||||
writer.emit(method)
|
||||
importsOut.addAll(writer.importClasses)
|
||||
|
||||
|
||||
return sb.toString()
|
||||
}
|
||||
|
||||
|
||||
@JvmStatic
|
||||
fun print(build: MethodSpec, imports: MutableSet<String>): String {
|
||||
return print(build, imports, true)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun buildMethod(method: ExecutableElement, types: Types, type: DeclaredType): MethodSpec.Builder {
|
||||
val builder = MethodSpec.overriding(method, type, types)
|
||||
val mirrors = method.annotationMirrors
|
||||
if (mirrors != null && mirrors.isNotEmpty()) {
|
||||
for (mirror in mirrors) {
|
||||
if (mirror.annotationType.kind != TypeKind.NULL) {
|
||||
builder.addAnnotation(AnnotationSpec.get(mirror))
|
||||
}
|
||||
}
|
||||
}
|
||||
var addComment = true
|
||||
// Add super call if the method is not abstract
|
||||
if (!method.modifiers.contains(Modifier.ABSTRACT)) {
|
||||
if (method.returnType is NoType) {
|
||||
builder.addStatement(createSuperCall(builder))
|
||||
} else {
|
||||
addComment = false
|
||||
builder.addComment("TODO: Implement this method")
|
||||
builder.addStatement("return " + createSuperCall(builder))
|
||||
}
|
||||
}
|
||||
if (addComment) {
|
||||
builder.addComment("TODO: Implement this method")
|
||||
}
|
||||
return builder
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a superclass method invocation statement.
|
||||
*
|
||||
* @param builder The method builder.
|
||||
* @return The super invocation statement string without ending ';'.
|
||||
*/
|
||||
private fun createSuperCall(builder: MethodSpec.Builder): String {
|
||||
val sb = java.lang.StringBuilder()
|
||||
sb.append("super.")
|
||||
sb.append(builder.name)
|
||||
sb.append("(")
|
||||
for (i in builder.parameters.indices) {
|
||||
sb.append(builder.parameters[i].name)
|
||||
if (i != builder.parameters.size - 1) {
|
||||
sb.append(", ")
|
||||
}
|
||||
}
|
||||
sb.append(")")
|
||||
return sb.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,11 +19,18 @@ package com.itsaky.lsp.java.utils;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.squareup.javapoet.ImportCollectingCodeWriter;
|
||||
import com.squareup.javapoet.TypeName;
|
||||
import com.sun.source.util.JavacTask;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.element.VariableElement;
|
||||
import javax.lang.model.type.TypeKind;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.util.Types;
|
||||
|
||||
@@ -34,6 +41,7 @@ public class MethodPtr {
|
||||
|
||||
public String className, methodName;
|
||||
public String[] erasedParameterTypes;
|
||||
public String[] simplifiedErasedParameterTypes;
|
||||
|
||||
public MethodPtr(@NonNull JavacTask task, @NonNull ExecutableElement method) {
|
||||
final Types types = task.getTypes();
|
||||
@@ -41,11 +49,61 @@ public class MethodPtr {
|
||||
className = parent.getQualifiedName().toString();
|
||||
methodName = method.getSimpleName().toString();
|
||||
erasedParameterTypes = new String[method.getParameters().size()];
|
||||
simplifiedErasedParameterTypes = new String[erasedParameterTypes.length];
|
||||
|
||||
for (int i = 0; i < erasedParameterTypes.length; i++) {
|
||||
final VariableElement param = method.getParameters().get(i);
|
||||
final TypeMirror type = param.asType();
|
||||
final TypeMirror erased = types.erasure(type);
|
||||
erasedParameterTypes[i] = erased.toString();
|
||||
simplifiedErasedParameterTypes[i] = simplify(erased);
|
||||
}
|
||||
}
|
||||
|
||||
private String simplify(@NonNull TypeMirror type) {
|
||||
|
||||
if (type.getKind() == TypeKind.NULL) {
|
||||
return type.toString();
|
||||
}
|
||||
|
||||
final TypeName name = TypeName.get(type);
|
||||
try {
|
||||
return getSimpleName(name);
|
||||
} catch (IOException e) {
|
||||
return type.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof MethodPtr)) {
|
||||
return false;
|
||||
}
|
||||
MethodPtr methodPtr = (MethodPtr) o;
|
||||
return Objects.equals(className, methodPtr.className)
|
||||
&& Objects.equals(methodName, methodPtr.methodName)
|
||||
&& Arrays.equals(erasedParameterTypes, methodPtr.erasedParameterTypes)
|
||||
&& Arrays.equals(
|
||||
simplifiedErasedParameterTypes, methodPtr.simplifiedErasedParameterTypes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = Objects.hash(className, methodName);
|
||||
result = 31 * result + Arrays.hashCode(erasedParameterTypes);
|
||||
result = 31 * result + Arrays.hashCode(simplifiedErasedParameterTypes);
|
||||
return result;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private String getSimpleName(TypeName name) throws IOException {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
final ImportCollectingCodeWriter writer = new ImportCollectingCodeWriter(sb);
|
||||
writer.setPrintQualifiedNames(false);
|
||||
writer.emit(name);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ public class FindTypeDeclarationAt extends TreePathScanner<ClassTree, Long> {
|
||||
private final SourcePositions pos;
|
||||
private CompilationUnitTree root;
|
||||
|
||||
private TreePath stored;
|
||||
private TreePath path;
|
||||
|
||||
public FindTypeDeclarationAt(JavacTask task) {
|
||||
pos = Trees.instance(task).getSourcePositions();
|
||||
@@ -48,7 +48,7 @@ public class FindTypeDeclarationAt extends TreePathScanner<ClassTree, Long> {
|
||||
return smaller;
|
||||
}
|
||||
if (pos.getStartPosition(root, t) <= find && find < pos.getEndPosition(root, t)) {
|
||||
this.stored = getCurrentPath();
|
||||
this.path = getCurrentPath();
|
||||
return t;
|
||||
}
|
||||
return null;
|
||||
@@ -60,7 +60,7 @@ public class FindTypeDeclarationAt extends TreePathScanner<ClassTree, Long> {
|
||||
return b;
|
||||
}
|
||||
|
||||
public TreePath getStoredPath() {
|
||||
return stored;
|
||||
public TreePath getPath() {
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,4 +33,10 @@
|
||||
<string name="msg_select_fields">Select fields</string>
|
||||
<string name="msg_no_fields_selected">No fields selected</string>
|
||||
<string name="msg_no_fields_found">No fields found</string>
|
||||
<string name="action_override_superclass_methods">Override superclass methods</string>
|
||||
<string name="msg_no_methods_selected">No methods selected</string>
|
||||
<string name="msg_cannot_override_methods">Unable to override methods</string>
|
||||
<string name="msg_cannot_generate_setters_getters">Unable to generate setters and getters</string>
|
||||
<string name="msg_select_methods">Select methods to override</string>
|
||||
<string name="msg_no_overridable_methods">Unable to find any overridable method</string>
|
||||
</resources>
|
||||
Reference in New Issue
Block a user