简体   繁体   English

从类源代码文件中检索方法源代码

[英]Retrieve method source code from class source code file

I have here a String that contains the source code of a class. 我这里有一个包含类源代码的字符串。 Now i have another String that contains the full name of a method in this class. 现在,我有另一个String,其中包含此类中的方法的全名。 The method name is eg 方法名称例如

public void (java.lang.String test)

Now I want to retieve the source code of this method from the string with the class' source code. 现在,我想从字符串中提取该方法的源代码,并添加类的源代码。 How can I do that? 我怎样才能做到这一点? With String#indexOf(methodName) i can find the start of the method source code, but how do i find the end? 使用String#indexOf(methodName)我可以找到方法源代码的开头,但是如何找到结尾?

====EDIT==== ==== ====编辑

I used the count curly-braces approach: 我使用了大括号计数方法:

 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);
        }

This works more or less fine, However, if a method is defined without body, it fails. 这或多或少可以正常工作,但是,如果定义的方法没有主体,则它将失败。 Any hints how to solve that? 任何提示如何解决?

Have a look at:- Parser for C# 看看: -C#解析器

It recommends using NRefactory to parse and tokenise source code, you should be able to use that to navigate your class source and pick out methods. 它建议使用NRefactory解析和标记化源代码,您应该能够使用它来导航类源代码并挑选方法。

Counting braces and stopping when the count decreases to 0 is indeed the way to go. 计数括号并在计数减少到0时停止计数确实是一种方法。 Of course, you need to take into account braces that appear as literals and should thus not be counted, eg braces in comments and strings. 当然,您需要考虑到出现在文字上的花括号,因此不应计算在内,例如注释和字符串中的花括号。

Overall this is kind of a thankless endeavour, comparable in complexity to say, building a command line parser if you want to get it working really reliably. 总的来说,这是一种不费吹灰之力,如果要使它真正可靠地运行,则要建立一个命令行解析器,其复杂程度可以说是相当的。 If you know you can get away with it you could cut some corners and just count all the braces, although I do not recommend it. 如果您知道您可以使用它,则可以开一些角,只算所有括号,尽管我不建议这样做。

Update: 更新:

Here's some sample code to do the brace counting. 这是一些用于进行大括号计数的示例代码。 As I said, this is a thankless job and there are tons of details you have to get right (in essence, you 're writing a mini-lexer). 就像我说的那样,这是一项不费力的工作,您必须弄清很多细节(实质上,您正在编写一个微型词法分析器)。 It's in C#, as this is the closest to Java I can write code in with confidence. 它在C#中,因为它是最接近Java的语言,我可以放心地编写代码。

The code below is not complete and probably not 100% correct (for example: verbatim strings in C# do not allow spaces between the @ and the opening quote, but did I know that for a fact or just forgot about it?) 下面的代码不完整,并且可能不是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

You will have to, probably, know the sequence of the methods listed in the code file. 您可能必须知道代码文件中列出的方法的顺序。 So that, you can look for the method closing scope } which may be right above start of next method. 因此,您可以寻找方法close scope } ,它可能在下一个方法的开始上方。

So you code might look like: 因此,您的代码可能看起来像:

nStartOfMethod = String.indexOf(methodName)
nStartOfNextMethod = String.indexOf(NextMethodName)

Look for .LastIndexOf(yourMethodTerminator /*probably a } */,...) between a string of nStartOfMethod and nStartOfNextMethod nStartOfMethodnStartOfNextMethod的字符串之间寻找.LastIndexOf(yourMethodTerminator /*probably a } */,...)

In this case, if you dont know the sequence of methods, you might end up skipping a method in between, to find an ending brace. 在这种情况下,如果您不知道方法的顺序,则可能最终会跳过两者之间的方法,以找到结尾括号。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM