2009-11-25 7 views
0

Bonjour,StackOverflowError avec Checkstyle 4.4 RegExp chèque

Contexte:

J'utilise Checkstyle 4.4.2 avec un module de vérification de RegExp pour détecter lorsque le nom de fichier dans les en-têtes source sur java faire ne correspond pas au nom de fichier de la classe ou de l'interface dans laquelle ils résident. Cela peut se produire lorsqu'un développeur copie un en-tête d'une classe à une autre et ne modifie pas la balise "File:".

L'utilisation régulière d'expression dans le vérificateur RexExp a été par beaucoup d'incarnations et (si elle est peut-être exagéré à ce stade) ressemble à ceci:

File: (\w+)\.java\n(?:.*\n)*?(?:[\w|\s]*?(?: class | interface)\1) 

La forme de base des fichiers Je vérifie (bien que beaucoup simplifiée) se présente comme suit

/* 
* 
* Copyright 2009 
* ... 
* File: Bar.java 
* ... 
*/ 
package foo 
... 
import .. 
... 
/** 
* ... 
*/ 
public class Bar 
{...} 

Le problème:

Lorsque aucune correspondance trouvée, (c.-à-d. quand un en-tête contenant "File: Bar.java" est copié dans le fichier Bat.java), je reçois un StackOverflowError sur des fichiers très longs (mon test est @ 1300 lignes).

Je l'ai expérimenté avec plusieurs testeurs d'expression réguliers visuels et peut voir que dans le cas non-appariement lorsque le moteur regex passe la ligne contenant le nom de la classe ou de l'interface, il commence la recherche à nouveau sur la ligne suivante et fait certains retours en arrière qui provoque probablement le StackOverflowError

la question:

Comment éviter la StackOverflowError en modifiant l'expression régulière

Existe-t-il un moyen de modifier mon expression régulière de telle sorte que, dans le cas , le cas non correspondant (c.-à-d. quand un en-tête contenant "File: Bar.java" est copié dans le fichier Bat.java) que la correspondance s'arrête une fois qu'elle examine la ligne contenant l'interface ou le nom de classe et voit que "\ 1" ne correspond pas au premier groupe. Est-il possible de minimiser la recherche et l'appariement après avoir examiné la ligne contenant l'interface ou la classe, minimisant ainsi le traitement et (espérons-le) l'erreur StackOverflow?

+0

Avez-vous dépassé la pile de google et obtenu ce site? –

+0

Non, j'ai lu Coding Horror depuis le début, donc je le savais; juste n'ai pas eu une bonne question jusqu'à maintenant. – jtsampson

Répondre

0

Essayez

File: (\w+)\.java\n.*^[\w \t]+(?:class|interface) \1 

en-point-matchs tous les modes. Justification:

[\w\s] (le | n'appartient pas à cet emplacement) correspond à n'importe quoi, y compris les sauts de ligne. Il en résulte beaucoup de retour en arrière dans les lignes que la partie précédente de l'expression rationnelle avait égalées.

Si vous laissez les gourmands point engloutissent tout jusqu'à la fin du fichier (rapide), puis revenir en arrière jusqu'à ce que vous trouviez une ligne qui commence par des mots ou des espaces/onglets (mais pas de retour à la ligne), puis class ou interface et \ 1, alors cela ne nécessite pas autant d'espace de pile.

Une solution différente, et probablement encore meilleure, serait de diviser le problème en parties.

Première correspondance avec la pièce File: (\w+)\.java. Ensuite, faites une seconde recherche avec ^[\w \t]+(?:class|interface) plus le \1 correspondant à la première recherche sur le même fichier.

+0

Tim, Désolé pour la réponse tardive (vacances et tous). Je vais essayer ça plus tard cette semaine et revenir vers vous. – jtsampson

+0

Tim, Bien que votre réponse n'était pas la solution pour moi, c'était la meilleure réponse WRT la regex. Ne sachant pas encore comment utiliser StackOverflow, j'ai posté ma propre réponse comme réponse (que j'aurais dû écrire ici). - Cela étant dit, je vous accepte comme le plus utile. – jtsampson

0

Suivi:

J'ai branché la suggestion de Tim Pietzcher ci-dessus et sa solution gourmande ne fait manquai plus rapidement et sans StackOverflowError quand aucune correspondance n'a été trouvée. Cependant, dans le cas positif, StackOverflowError s'est toujours produit.

J'ai regardé le code source RegexpCheck.java. Le modèle de classes est construit en mode multiligne de sorte que les expressions^et $ correspondent juste après ou juste avant, respectivement, un terminateur de ligne ou la fin de la séquence d'entrée. Ensuite, il lit le fichier de classe entier dans une chaîne et effectue une recherche récursive pour le modèle (voir findMatch()). C'est sans doute la source de l'exception StackOverflowException. En fin de compte, je ne l'ai pas fait fonctionner (et j'ai abandonné) Depuis que Maven 2 a sorti le maven-checkstyle-plugin-2.4/Checkstyle 5.0 il y a environ 6 semaines, nous avons décidé de mettre à jour nos outils. Cela ne résout peut-être pas le problème StackOverflowError, mais cela me donnera quelque chose d'autre à travailler jusqu'à ce que quelqu'un décide que nous devons poursuivre cela.