2010-12-08 2 views
1

У меня есть строка, содержащая исходный код класса. Теперь у меня есть еще одна строка, содержащая полное имя метода в этом классе. Имя способа является, например,Восстановить исходный код метода из файла исходного кода класса

public void (java.lang.String test) 

Теперь я хочу вернуть исходный код этого метода из строки с исходным кодом класса. Как я могу это сделать? С String#indexOf(methodName) я могу найти начало исходного кода метода, но как найти конец?

==== ==== РЕДАКТИРОВАТЬ

Я использовал подсчет фигурные скобки приближаются:

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

Это работает более или менее хорошо, однако, если метод определен без тела, он не работает. Любые подсказки, как это решить?

+0

Предполагается, что это полностью зависит от языка кода, который вы разбираете.Это похоже на Java, и в этом случае вы будете считать фигурные фигурные скобки. – lesscode 2010-12-08 12:27:04

+0

Это java. Итак, вы предлагаете считать открытые кудри, и если это 0, метод закончен? – 2010-12-08 12:28:25

+0

это использование ikvm? – IanNorton 2010-12-08 12:29:31

ответ

1

Подсчет фигурных скобок и остановка при уменьшении числа до 0 - это действительно путь. Конечно, вам нужно учитывать фигурные скобки, которые появляются как литералы, и поэтому их не следует учитывать, например. фигурные скобки в комментариях и строках.

В целом это своего рода неблагодарное стремление, сопоставимое по сложности, построение парсера командной строки, если вы хотите, чтобы он работал действительно надежно. Если вы знаете, что можете уйти от него, вы можете сократить некоторые углы и просто подсчитать все фигурные скобки, хотя я не рекомендую это делать.

Update:

Вот некоторые примеры кода, чтобы сделать подсчет скобка. Как я уже сказал, это неблагодарная работа, и есть тонны деталей, которые вам нужно получить правильно (по сути, вы пишете мини-лексер). Он находится на C#, так как он наиболее близок к Java. Я могу с уверенностью писать код.

Код ниже не является полным и, вероятно, не на 100% правильным (например: verbatim strings на 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 
1

Посмотрите: - Parser for C#

Он рекомендует использовать NRefactory разобрать и tokenise исходного кода, вы должны быть в состоянии использовать, чтобы перемещаться источником класса и выбрать методы.

1

Вам придется, вероятно, знать последовательность методов, перечисленных в файле кода. Таким образом, вы можете искать область закрытия метода }, которая может находиться прямо над началом следующего метода.

Таким образом, вы код может выглядеть следующим образом:

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

Ищут .LastIndexOf(yourMethodTerminator /*probably a} */,...) между строкой nStartOfMethod и nStartOfNextMethod

В этом случае, если вы не знаете последовательность методов, вам может закончиться пропуском метода между ними, чтобы найти конечную фигуру.

Смежные вопросы