我这里有一个包含类源代码的String。现在我有另一个String,其中包含此类中方法的全名。方法名称是例如。
public void (java.lang.String test)
现在我想从带有类源代码的字符串中读取此方法的源代码。我怎样才能做到这一点?使用String#indexOf(methodName)
,我可以找到方法源代码的开头,但我如何找到结束?
==== EDIT ====
我使用了计数大括号的方法:
internal void retrieveSourceCode()
{
int startPosition = parentClass.getSourceCode().IndexOf(this.getName());
if (startPosition != -1)
{
String subCode = parentClass.getSourceCode().Substring(startPosition, parentClass.getSourceCode().Length - startPosition);
for (int i = 0; i < subCode.Length; i++)
{
String c = subCode.Substring(0, i);
int open = c.Split('{').Count() - 1;
int close = c.Split('}').Count() - 1;
if (open == close && open != 0)
{
sourceCode = c;
break;
}
}
}
Console.WriteLine("SourceCode for " + this.getName() + "\n" + sourceCode);
}
这或多或少都有效,但是,如果定义一个没有body的方法,它就会失败。任何提示如何解决?
答案 0 :(得分:1)
请查看: - Parser for C#
它建议使用NRefactory来解析和标记源代码,您应该能够使用它来导航类源并选择方法。
答案 1 :(得分:1)
计数括号并在计数减少到0时停止确实是要走的路。当然,您需要考虑以文字显示的大括号,因此不应计算,例如评论和字符串中的括号。
总的来说,这是一种吃力不讨好的努力,在复杂性方面可以说,如果你想让它真正可靠地工作,那就建立一个命令行解析器。如果你知道你可以逃脱它,你可以削减一些角落,只计算所有的牙套,虽然我不推荐它。
<强>更新强>
这是一些用于进行大括号计数的示例代码。正如我所说,这是一个吃力不讨好的工作,你需要做大量的细节(实质上,你正在写一个迷你词法分子)。它位于C#中,因为它是最接近Java的,我可以放心地编写代码。
下面的代码不完整,可能不是100%正确(例如:C#中的逐字字符串不允许@和开头引号之间的空格,但是我知道这是为了一个事实还是只是忘了它?)
// sourceCode is a string containing all the source file's text
var sourceCode = "...";
// startIndex is the index of the char AFTER the opening brace
// for the method we are interested in
var methodStartIndex = 42;
var openBraces = 1;
var insideLiteralString = false;
var insideVerbatimString = false;
var insideBlockComment = false;
var lastChar = ' '; // White space is ignored by the C# parser,
// so a space is a good "neutral" character
for (var i = methodStartIndex; openBraces > 0; ++i) {
var ch = sourceCode[i];
switch (ch) {
case '{':
if (!insideBlockComment && !insideLiteralString && !insideVerbatimString) {
++openBraces;
}
break;
case '}':
if (!insideBlockComment && !insideLiteralString && !insideVerbatimString) {
--openBraces;
}
break;
case '"':
if (insideBlockComment) {
continue;
}
if (insideLiteralString) {
// "Step out" of the string if this is the closing quote
insideLiteralString = lastChar != '\';
}
else if (insideVerbatimString) {
// If this quote is part of a two-quote pair, do NOT step out
// (it means the string contains a literal quote)
// This can throw, but only for source files with syntax errors
// I 'm ignoring this possibility here...
var nextCh = sourceCode[i + 1];
if (nextCh == '"') {
++i; // skip that next quote
}
else {
insideVerbatimString = false;
}
}
else {
if (lastChar == '@') {
insideVerbatimString = true;
}
else {
insideLiteralString = true;
}
}
break;
case '/':
if (insideLiteralString || insideVerbatimString) {
continue;
}
// TODO: parse this
// It can start a line comment, if followed by /
// It can start a block comment, if followed by *
// It can end a block comment, if preceded by *
// Line comments are intended to be handled by just incrementing i
// until you see a CR and/or LF, hence no insideLineComment flag.
break;
}
lastChar = ch;
}
// From the values of methodStartIndex and i we can now do sourceCode.Substring and get the method source
答案 2 :(得分:1)
您可能必须知道代码文件中列出的方法序列。这样,您可以查找关闭范围}
的方法,该方法可能位于下一个方法的开头。
所以您的代码可能如下所示:
nStartOfMethod = String.indexOf(methodName)
nStartOfNextMethod = String.indexOf(NextMethodName)
在.LastIndexOf(yourMethodTerminator /*probably a
和*/,...)
nStartOfMethod
} nStartOfNextMethod
在这种情况下,如果你知道方法序列,你可能最终会在其间跳过一个方法,以找到一个结束括号。