更新:在得到一个意想不到的好答案后,我在这个问题的底部添加了一些上下文,准确地说明了我将如何使用这些字符串函数调用
我需要翻译字符串,例如my.package.ClassName#functionName(1, "a string value", true)
转换为对该函数的反射调用。获取包、类和函数名不是问题。我已经开始使用自己的解决方案来解析参数列表,确定每个参数的类型并返回一个适当的对象。
(我将类型的范围限制为八个原语加上字符串。null
将被认为是一个字符串,逗号和双引号必须用一些简单的标记严格转义,例如__DBL_QT__
,以避免在逗号上进行不转义和分割的复杂性。
我不是在问如何通过字符串解析做到这一点,因为我知道如何。只是需要做很多工作,我希望已经有解决方案了。不幸的是,它是如此通用的术语,我找不到任何地方。
我理解要求外部现有库是离题的。我只是希望在它关闭之前得到一些反馈,甚至是一个更好的搜索条件的建议。或者,可能会提出一种完全不同的方法……
谢谢。
背景:
每个函数调用都在函数的JavaDoc块中找到,并且表示一段示例代码——它的源代码或它的System.out
输出——将显示在该位置。
参数用于自定义其显示,如
- 缩进,
- 删除不相关的部分(如许可块),和
- 用于javadoc -链接最重要的函数。此自定义主要用于源代码表示,但也可以应用于其输出。
(第一个参数始终是Appendable
,它将执行实际输出。)
用户需要能够调用任何函数,在许多情况下,该函数将是位于JavaDoc-ed函数本身下面的私有静态函数。
我编写的应用程序将读取源代码文件(包含JavaDoc块的文件,其中存在这些字符串函数调用),并创建*.java文件的副本,该文件随后将由javadoc
处理。
因此,对于每一段示例代码,可能会有两个,甚至更多的字符串函数调用。可能还有更多,因为我可能想要在不同的上下文中显示同一个示例的不同片段——可能是在整个类JavaDoc块中显示整个示例,并在该类的相关函数中显示它的片段。
我已经编写了解析源代码的过程(源代码包含JavaDoc块,它与读取示例代码的过程是分开的),并使用insert example-code here
和insert example-code-output here
标记盲目地重新输出其源代码。
我现在在InsertExampleCode
对象中有这个字符串函数调用,在字符串字段中。现在我需要按照问题开头的描述来做。找出他们想要调用的函数,然后这样做。
将#
更改为点(.
),围绕它编写一个类定义,以便您有一个有效的Java源文件,在类路径中包含tools.jar
并调用com.sun.tools.javac.Main
。
创建您自己的ClassLoader
实例来加载编译后的类,并运行它(使它实现一个有用的接口,例如java.util.concurrent.Callable
,以便您可以轻松获得调用的结果)
我为此创建的名为com.github.aliteralmind.codelet.simplesig.SimpleMethodSignature
的类是一个重要的Codelet,用于翻译每个标记的"customizer"部分,这是一个自定义标记输出的函数。
(安装说明。类路径中必须包含的jar文件只有codelet和xbnjava。)
示例字符串签名,在标签中:
{@.codelet.and.out com.github.aliteralmind.codelet.examples.adder.AdderDemo%eliminateCommentBlocksAndPackageDecl()}
定制器部分是百分号(%
)之后的所有内容。此自定义器仅包含函数名和空参数。这意味着该函数必须存在于少数严格指定的类集中。
{@.codelet.and.out com.github.aliteralmind.codelet.examples.adder.AdderDemo%lineRange(1, false, "Adder adder", 2, false, "println(adder.getSum())", "^ ")}
这也指定了参数,按照设计,这些参数是"简单的"——要么是非空字符串,要么是基本类型。
{@.codelet.and.out com.github.aliteralmind.codelet.examples.adder.AdderDemo%com.github.aliteralmind.codelet.examples.LineRangeWithLinksCompact#adderDemo_lineSnippetWithLinks()}
指定函数所在的显式包和类。
由于这些标签的性质以及字符串签名的实现方式,我决定坚持使用直接字符串解析而不是动态编译。
使用SimpleMethodSignature
的两个例子:
在第一个例子中,完整的签名(包、类和函数名,包括它的所有参数)都在字符串中指定。
import com.github.aliteralmind.codelet.simplesig.SimpleMethodSignature;
import com.github.xbn.lang.reflect.InvokeMethodWithRtx;
import java.lang.reflect.Method;
public class SimpleMethodSigNoDefaults {
public static final void main(String[] ignored) {
String strSig = "com.github.aliteralmind.codelet.examples.simplesig." +
"SimpleMethodSigNoDefaults#getStringForBoolInt(false, 3)";
SimpleMethodSignature simpleSig = null;
try {
simpleSig = SimpleMethodSignature.newFromStringAndDefaults(
String.class, strSig, null, null,
null); //debug (on=System.out, off=null)
} catch(ClassNotFoundException cnfx) {
throw new RuntimeException(cnfx);
}
Method m = null;
try {
m = simpleSig.getMethod();
} catch(NoSuchMethodException nsmx) {
throw new RuntimeException(nsmx);
}
m.setAccessible(true);
Object returnValue = new InvokeMethodWithRtx(m).sstatic().
parameters(simpleSig.getParamValueObjectList().toArray()).invokeGetReturnValue();
System.out.println(returnValue);
}
public static final String getStringForBoolInt(Boolean b, Integer i) {
return "b=" + b + ", i=" + i;
}
}
输出:b=false, i=3
第二个示例演示了未指定(包和)类名的字符串签名。直接提供势类,其中必须存在函数。
import com.github.aliteralmind.codelet.simplesig.SimpleMethodSignature;
import com.github.xbn.lang.reflect.InvokeMethodWithRtx;
import java.lang.reflect.Method;
public class SimpleMethodSigWithClassDefaults {
public static final void main(String[] ignored) {
String strSig = "getStringForBoolInt(false, 3)";
SimpleMethodSignature simpleSig = null;
try {
simpleSig = SimpleMethodSignature.newFromStringAndDefaults(
String.class, strSig, null,
new Class[]{Object.class, SimpleMethodSigWithClassDefaults.class, SimpleMethodSignature.class},
null); //debug (on=System.out, off=null)
} catch(ClassNotFoundException cnfx) {
throw new RuntimeException(cnfx);
}
Method m = null;
try {
m = simpleSig.getMethod();
} catch(NoSuchMethodException nsmx) {
throw new RuntimeException(nsmx);
}
m.setAccessible(true);
Object returnValue = new InvokeMethodWithRtx(m).sstatic().
parameters(simpleSig.getParamValueObjectList().toArray()).invokeGetReturnValue();
System.out.println(returnValue);
}
public static final String getStringForBoolInt(Boolean b, Integer i) {
return "b=" + b + ", i=" + i;
}
}
输出:b=false, i=3