java - 如何以编程方式查找对方法的所有引用?
问题描述
因此,这不是使用 Eclipse IDE 查找方法引用的方法。
我需要通过代码(Java)找到它们。
背景: 我们有数百个项目,都基于一个共同的项目。多年来,通用项目有一些非常糟糕的代码已被替换。错误代码已被标记为已弃用。
现在,我想删除所有已弃用的代码。但是,我想创建一些代码来迁移我们拥有的所有其他项目。
方法: 现在,对于某些事情,我可以在项目代码中搜索一些关键字(即方法名称)并替换为其他内容。但是,有些方法名称会发生冲突,并且进行简单的搜索/替换将不起作用。
我的想法是,如果我有一个不推荐使用的方法: com.foo.bar.SomeClass.someMethod(String)
然后以某种方式找到使用 someMethod(String) 的每个地方,然后我可以用 newMethod(String) 替换那个
我看过一些:
基本上,我想创建一个迁移程序,使迁移到新的通用代码变得简单。我计划使用相同的迁移代码来帮助将项目从 JDK8 迁移到 OpenJDK11。
关于如何实现这一点的想法?
解决方案
做一些搜索,我有一些基本代码,但仍然没有 100%
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
public class ProjectMigration {
public static void main (String[] args) {
ProjectMigration migration = new ProjectMigration();
try {
migration.migrate();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
private List<DeprecatedClass> getDeprecatedMethods () {
List<DeprecatedClass> deprecatedClasses = new ArrayList<>();
deprecatedClasses.add(
new DeprecatedClass("com.e2open.selenium.api_common.abstractHelpers.SystemInformation",
"isInternetExplorer8", "boolean", ""));
deprecatedClasses.add(
new DeprecatedClass("com.e2open.selenium.api_common.AbstractPage", "radioButtonSelect",
"boolean", "java.lang.String", "java.lang.String"));
return deprecatedClasses;
}
public void migrate ()
throws ClassNotFoundException, InstantiationException, IllegalAccessException {
List<DeprecatedClass> deprecatedClasses = getDeprecatedMethods();
for (DeprecatedClass clazz : deprecatedClasses) {
System.out.println("CLASS: " + clazz.getClazz());
Class c = Class.forName(clazz.getClazz());
analyze(c.newInstance(), clazz);
System.out.println();
}
}
private void analyze (Object object, DeprecatedClass deprecatedClass) {
ClassVisitor cv = new ClassVisitor(Opcodes.ASM5) {
@Override
public MethodVisitor visitMethod (
int access, String name, String desc, String signature, String[] exceptions) {
if (isDeprecatedMethod(deprecatedClass, name, desc)) {
logMethod(name, desc);
return new MethodVisitor(Opcodes.ASM5) {
@Override
public void visitMethodInsn (
int opcode, String owner, String name, String desc, boolean arg4) {
if (owner.contains("e2open")) {
processMethod(owner, name, desc);
}
super.visitMethodInsn(opcode, owner, name, desc, arg4);
}
};
}
return null;
}
};
try {
ClassReader classReader = new ClassReader(object.getClass().getCanonicalName());
classReader.accept(cv, 0);
} catch (IOException e) {
System.err.println("Something went wrong !! " + e.getMessage());
}
}
protected void processMethod (String owner, String name, String desc) {
System.out.println(
"classUsed[" + owner.replace("/", ".") + "]; methodUsed[" + name + "]; methodParameters["
+ desc + "]");
}
protected void logMethod (String name, String desc) {
String returnType = getReturnType(desc);
String paramters = getParamters(desc);
System.out.println(String.format("METHOD: %s %s(%s)", returnType, name, paramters));
}
private String getParamters (String desc) {
String parms = desc.split("\\)")[0];
if (parms.equals("(")) {
return "";
}
parms = parms.substring(2, parms.length());
String[] parmameters = parms.split(";");
StringBuilder paramterString = new StringBuilder();
for (String p : parmameters) {
paramterString.append(p.replaceAll("/", ".")).append(", ");
}
return paramterString.toString().substring(0, paramterString.length() - 2);
}
private String getReturnType (String desc) {
String returnType = desc.split("\\)")[1];
if (returnType.equals("V")) {
return "void";
}
if (returnType.length() == 1) {
return returnType;
}
return returnType.substring(1, returnType.length() - 1).replace("/", ".");
}
private boolean isDeprecatedMethod (
DeprecatedClass deprecatedClass, String method, String parmeters) {
if ((method.equals(deprecatedClass.getMethod()))
&& (parmeters.equals(deprecatedClass.getParameters()))) {
return true;
}
return false;
}
private class DeprecatedClass {
private String clazz;
private String method;
private List<String> parameters;
private String returnType;
public DeprecatedClass() {}
/**
* No paramters and no return type
*
* @param clazzName The class to check. Example: com.e2open.selenium.api_common.AbstractPage
* @param methodName The method name to find references for. Example: clearAllInputFields
*/
public DeprecatedClass(String clazzName, String methodName) {
this.clazz = clazzName;
this.method = methodName;
}
/**
* Use if there is a return type and/or parameters
*
* @param clazzName The class to check. Example: com.e2open.selenium.api_common.AbstractPage
* @param methodName he method name to find references for. Example: findFieldByAttribute
* @param returnType The returned type. Example: org.openqa.selenium.By
* @param parameterValues List of paramters. Example: "java.lang.String", "java.lang.String",
* "java.lang.String"
*/
public DeprecatedClass(String clazzName, String methodName, String returnType,
String... parameterValues) {
this.clazz = clazzName;
this.method = methodName;
setReturnType(returnType);
if (parameterValues != null) {
for (String parm : parameterValues) {
if (StringUtils.isNoneBlank(parm)) {
addParameter(parm);
}
}
}
}
/**
* @return the clazz
*/
public String getClazz () {
return clazz;
}
/**
* @param clazz the clazz to set
*/
public void setClazz (String clazz) {
this.clazz = clazz;
}
/**
* @return the method
*/
public String getMethod () {
return method;
}
/**
* @param method the method to set
*/
public void setMethod (String method) {
this.method = method;
}
/**
* @param returnType the returnType to set
*/
public void setReturnType (String returnType) {
if (returnType != null) {
if ("boolean".equals(returnType)) {
this.returnType = "Z";
} else {
this.returnType = "L" + returnType.replaceAll("\\.", "/") + ";";
}
}
}
/**
* @return the parameters
*/
public String getParameters () {
StringBuilder parms = new StringBuilder();
if (this.parameters == null) {
parms.append("()");
} else {
parms.append("(").append(String.join("", this.parameters)).append(")");
}
if (this.returnType == null) {
parms.append("V");
} else {
parms.append(this.returnType);
}
return parms.toString();
}
/**
* @param parameters the parameters to set
*/
public void addParameter (String parameter) {
if (this.parameters == null) {
this.parameters = new ArrayList<>();
}
this.parameters.add("L" + parameter.replaceAll("\\.", "/") + ";");
}
}
}
我得到的结果是:
CLASS: com.e2open.selenium.api_common.abstractHelpers.SystemInformation
METHOD: Z isInternetExplorer8()
classUsed[com.e2open.selenium.api_common.abstractHelpers.SystemInformation]; methodUsed[getSystemData]; methodParameters[()Lcom/e2open/selenium/api_common/abstractHelpers/SystemInformation$SystemData;]
classUsed[com.e2open.selenium.api_common.browser.BrowserType]; methodUsed[equals]; methodParameters[(Ljava/lang/Object;)Z]
CLASS: com.e2open.selenium.api_common.AbstractPage
METHOD: Z radioButtonSelect(java.lang.String, Ljava.lang.String)
classUsed[com.e2open.selenium.api_common.JLog]; methodUsed[write]; methodParameters[(Ljava/lang/String;)V]
classUsed[com.e2open.selenium.api_common.AbstractPage]; methodUsed[radioButtonGet]; methodParameters[(Ljava/lang/String;Ljava/lang/String;)Lorg/openqa/selenium/WebElement;]
然而,结果并不正确。
如果我采用其中一种方法:com.e2open.selenium.api_common.abstractHelpers.SystemInformation.isInternetExplorer8()
并使用 Eclipse 查找 References,我得到 isInternetExplorer8 Eclipse References Image
对于其他方法进行搜索:com.e2open.selenium.api_common.AbstractPage.radioButtonSelect(String, String) radioButtonSelect Eclipse Reference Image
我不确定要改变什么或从这里去哪里。
推荐阅读
- javascript - 如何仅在特定事件发生后初始化 .each() 函数?
- oracle - 如何获取 SDO GEOMETRY 的 X 坐标
- c# - RabbitMQ 发布者通过主题交换确认 - BasicAcks 仅在第一次触发一次
- python - 熊猫到第二个 excel 选项卡
- java - GLFW 没有检测到一半的键
- python - pandas 数据框 KeyError oop
- python - 如何在这里改变路径的“成本”?
- java - Maven - Failsafe 插件没有并行运行黄瓜测试
- arrays - 用褶皱画一本书的封面 (Ada)
- sql-server - 分组后用分号分隔符连接行