2010-12-08 19 views
1

J'ai ici une chaîne qui contient le code source d'une classe. Maintenant j'ai une autre chaîne qui contient le nom complet d'une méthode dans cette classe. Le nom de la méthode est par exempleRécupérer le code source de la méthode à partir du fichier de code source de la classe

public void (java.lang.String test) 

Maintenant, je veux récupérer le code source de cette méthode à partir de la chaîne avec le code source de la classe. Comment puis je faire ça? Avec String#indexOf(methodName) je peux trouver le début du code source de la méthode, mais comment puis-je trouver la fin?

==== ==== EDIT

je le compte approcher des accolades:

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

Cela fonctionne plus ou moins bien, mais, si une méthode est définie sans corps, il échoue. Des allusions comment résoudre cela?

+0

Supposons que cela dépend entièrement de la langue du code que vous analysez.Il ressemble à Java, auquel cas vous comptez des accolades. – lesscode

+0

C'est java. Alors suggérez-vous de compter les boucles ouvertes et si c'est 0, la méthode est terminée? –

+0

est-ce en utilisant ikvm? – IanNorton

Répondre

1

Compter les accolades et s'arrêter lorsque le compte diminue à 0 est en effet le chemin à parcourir. Bien sûr, vous devez prendre en compte les accolades qui apparaissent comme des littéraux et ne doivent donc pas être comptées, par ex. accolades dans les commentaires et les chaînes.

Dans l'ensemble, c'est une sorte de travail ingrat, comparable en termes de complexité, à la construction d'un analyseur de ligne de commande si vous voulez que cela fonctionne vraiment de manière fiable. Si vous savez que vous pouvez vous en sortir, vous pouvez couper quelques coins et simplement compter tous les accolades, même si je ne le recommande pas.

Mise à jour:

Voici quelques exemples de code pour effectuer le comptage des accolades. Comme je l'ai dit, c'est un travail ingrat et il y a des tonnes de détails à corriger (en substance, vous écrivez un mini-lexer). C'est en C#, comme c'est le plus proche de Java, je peux écrire du code en toute confiance.

Le code ci-dessous n'est pas complet et probablement pas 100% correct (par exemple: les chaînes verbatim en C# n'autorisent pas les espaces entre le @ et la citation d'ouverture, mais le savais-je?)

// 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 
+0

Un extrait de code et comment compter les accolades? – RoflcoptrException

1

Jetez un oeil à: - Parser for C#

Il recommande d'utiliser NRefactory pour analyser et code source tokenise, vous devriez pouvoir l'utiliser pour naviguer dans votre source de classe et choisir les méthodes.

1

Vous devrez probablement savoir la séquence des méthodes répertoriées dans le fichier de code. Pour cela, vous pouvez rechercher la méthode fermant la portée } qui peut être juste au-dessus du début de la méthode suivante.

donc votre code pourrait ressembler à:

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

Rechercher .LastIndexOf(yourMethodTerminator /*probably a} */,...) entre une chaîne de nStartOfMethod et nStartOfNextMethod

Dans ce cas, si vous ne savoir la séquence des méthodes, vous pourrait finir par sauter une méthode entre, pour trouver une accolade de fin.

+0

Malheureusement, les méthodes ne sont pas triées – RoflcoptrException