Comptage de lignes de code en Java

Cette semaine, c'est Julien qui vous propose un #KataOfTheWeek : Comptage de lignes

Briefing du Kata : Soit un morceau de code source en Java. l'idée est de compter les lignes de code. Ne sont pas considérées comme lignes de code :

  • les lignes blanches
  • les lignes qui commencent par // (il peut y avoir des blancs devant)
  • les lignes qui commencent par /*.

Autres points à prendre en compte :

  • il est possible d'avoir des commentaires multilignes, donc qui commencent par /* et finissent plus loin par */.
  • pour simplifier on considère qu'il ne peut y avoir au maximum qu'un commentaire par ligne (et pas plusieurs commentaires sur une ligne) et qu'une ligne de code ne contient pas de commentaires, et vice-versa, et qu'une string ne contient pas de syntaxe de commentaire.
  • on considère que le code compile. ;-)

Ci-dessous un exemple de code :

// This file contains 3 lines of code
public interface Dave {

    /**
     * count the number of lines in a file
     */
    int countLines(File inFile);

    // I'm a useless line !
}

Un autre exemple de code :

/*****
 * This is a test program with 5 lines of code
 *  \/* no nesting allowed!
 //*****/
public class Hello {

   public static final void main(String [] args) {
      // Say hello
      System.out.println("Hello");
      /* another case to handle */
   }
}

Saurez-vous résoudre le problème ?

Bon courage !


Et voici une solution proposée par l'auteur :

On a là un classique problème de compilation, même si on le simplifie pour éviter que ce soit le bazar. Comme tout problème de compilation le mieux est de passer par une machine à état.

Un point très important est qu'il faut considérer que les lignes contiennent toutes des espaces avant et après.

Comme on peut le voir la solution n'est pas des plus sympathiques et est un joli cas de TDD. Pour les masochistes vous pouvez tenter le Kata complet (ci-dessus), il est super à découvrir !

private boolean isSingleLineComment(String line) {
   return line.startsWith("//");
}

private boolean isMultiLineCommandStart(String line) {
   return line.startsWith("/*");
}

private boolean isMultiLineCommandEnd(String line) {
   return line.endsWIth("*/");
}

// Le bufferedreader contient la méthode readLine(), très sympa.
public int countLines(BufferedReader br) {
   int res = 0;
   String line = br.readLine();

   // C'est notre marqueur d'état.
   bool isInComment = false;

   while (line != null) {

      // très important de virer les espaces !
      line = line.trim();

      // piège : on est dans un commentaire sur une ligne qui commence par //
      if (!isSingleLineComment(line) && !isInComment) {
         isInComment = isMultiLineCommandStart(line);
         // Là ça devient sioux : on ne compte la ligne que si on n'est pas dans un commentaire... et si la ligne n'est pas vide
         if (!isInComment && !line.isEmpty()) {
            res++;
         } 
      }
      // surtout pas de else ici, on peut avoir un commentaire qui se termine sur la même ligne que là où il a commencé.
      if (isInComment) {
         isInComment = !isMultiLineCommandEnd(line);
      }

      line = br.readLine();
   }

   return res;
}

Votre équipe TakiVeille

TakiVeille

TakiVeille