我需要在 Spoon 中传递一个匿名类的实例作为函数参数。 就我而言,我有一个匿名比较器,我需要将其传递给一个函数,该函数将比较器<?>作为参数。
这是我的代码:
public boolean isToBeProcessed(CtType<?> candidate) {
if(candidate instanceof CtClass<?> && ((CtClass<?>)candidate).isAnonymous()==true){
CtClass<?> clas = (CtClass<?>)candidate;
List<CtMethod<?>> list = clas.filterChildren(
new AbstractFilter<CtMethod<?>>(CtMethod.class) {
@Override
public boolean matches(CtMethod<?> method) {
return method.getSimpleName().equals("compare");
}
}
).list();
return !(list==null || list.isEmpty());
}
return false;
}
@Override
public void process(CtType<?> element) {
// here I need to pass the anonymous Comparator class
testComparator( ??? );
}
public void testComparator(Comparator<?> comparator) {
......
}
我是 Spoon 的新手,感谢您对此的帮助。
谢谢。
我想我设法做到了你的要求。
目录/应用程序.java
import java.util.Comparator;
public class App {
public static void main(String[] args) {
foo1(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return 0;
}
});
foo2(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return 0;
}
});
}
}
src/main/java/MyProcessor.java
import spoon.Launcher;
import spoon.processing.AbstractProcessor;
import spoon.reflect.declaration.CtClass;
import spoon.reflect.declaration.CtMethod;
import spoon.reflect.declaration.CtType;
import spoon.reflect.visitor.filter.AbstractFilter;
import spoon.support.compiler.FileSystemFile;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.List;
public class MyProcessor extends AbstractProcessor<CtType<?>> {
@Override
public boolean isToBeProcessed(CtType<?> candidate) {
if (candidate instanceof CtClass<?> && ((CtClass<?>) candidate).isAnonymous() == true) {
CtClass<?> clas = (CtClass<?>) candidate;
List<CtMethod<?>> list = clas.filterChildren(
new AbstractFilter<CtMethod<?>>(CtMethod.class) {
@Override
public boolean matches(CtMethod<?> method) {
return method.getSimpleName().equals("compare");
}
}
).list();
return !(list == null || list.isEmpty());
}
return false;
}
@Override
public void process(CtType<?> element) {
String implementsString = element.getParent().toString()
.replace("()", "")
.replace("new", "implements");
String codeA =
"public class A {n" +
" public void m() {n" +
" Main.testComparator(new B());n" +
" }n" +
"}";
String codeB = "public class B " + implementsString;
String fileNameA = "dir2/A.java";
String fileNameB = "dir2/B.java";
try (FileWriter fileWriterA = new FileWriter(fileNameA);
FileWriter fileWriterB = new FileWriter(fileNameB)) {
fileWriterA.write(codeA);
fileWriterB.write(codeB);
} catch (IOException e) {
throw new RuntimeException(e);
}
Launcher launcher = new Launcher();
launcher.addInputResource("dir2");
Collection<CtType<?>> allTypes = launcher.buildModel().getAllTypes();
CtClass<?> ctClassA = (CtClass<?>) allTypes.stream().findFirst().get();
Object instance = ctClassA.newInstance();
Class<?> classA = instance.getClass();
try {
Method method = classA.getMethod("m");
method.invoke(instance);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
}
src/main/java/Main.java
import spoon.Launcher;
import java.util.Comparator;
public class Main {
public static void testComparator(Comparator<?> comparator) {
System.out.println("test Comparator");
}
public static void main(String[] args) {
Launcher launcher = new Launcher();
launcher.addInputResource("dir");
launcher.addProcessor(new MyProcessor());
launcher.run();
}
}
目录2/A.java
目录2/B.java
庞.xml
...
<dependency>
<groupId>fr.inria.gforge.spoon</groupId>
<artifactId>spoon-core</artifactId>
<version>8.2.0</version>
</dependency>
还必须将目录spooned-classes
添加到类路径中。我正在使用 sbt。这可以在此处指定为unmanagedClasspath in Runtime ++= Seq(file("spooned-classes")).classpath
。在 Maven 中,应该以类似的方式指定这一点。
输出:
[main] INFO spoon.Launcher - Running in NOCLASSPATH mode (doc: http://spoon.gforge.inria.fr/launcher.html).
[main] INFO spoon.Launcher - Running in NOCLASSPATH mode (doc: http://spoon.gforge.inria.fr/launcher.html).
test Comparator
[main] INFO spoon.Launcher - Running in NOCLASSPATH mode (doc: http://spoon.gforge.inria.fr/launcher.html).
test Comparator
因此,Main
年的testComparator
被执行了两次,对应于foo1
年和foo2
年的App
.