Domanda

Ciao,

Sfondo:

Sto usando Checkstyle 4.4.2 con un modulo di controllo RegExp per rilevare quando il nome del file nelle intestazioni di origine java out non corrisponde al nome del file della classe o dell'interfaccia in cui risiedono. Ciò può accadere quando uno sviluppatore copia un'intestazione da una classe all'altra e non modifica il "File: " tag.

L'uso delle espressioni regolari nel controllo RexExp ha subito molte incarnazioni e (anche se a questo punto è probabilmente eccessivo) è simile al seguente:

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

La forma base dei file che sto controllando (anche se notevolmente semplificata) è simile a questa

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

Il problema:

Quando non viene trovata alcuna corrispondenza , (ovvero quando un'intestazione contenente " File: Bar.java " viene copiata nel file Bat.java), ricevo StackOverflowError su file molto lunghi (il mio caso di prova è @ 1300 righe).

Ho sperimentato diversi tester visivi di espressioni regolari e posso vederlo nel caso non corrispondente quando il motore regex passa la riga contenente la classe o il nome dell'interfaccia ricomincia a cercare nella riga successiva e esegue alcuni backtracking che probabilmente causano StackOverflowError

La domanda:

Come prevenire StackOverflowError modificando l'espressione regolare

Esiste un modo per modificare la mia espressione regolare in modo tale che nel caso non corrispondente (cioè quando viene copiata un'intestazione contenente " File: Bar.java " nel file Bat.java) che la corrispondenza si fermerebbe una volta che esamina la riga contenente l'interfaccia o il nome della classe e vede che " \ 1 " non corrisponde al primo gruppo.

In alternativa, se ciò può essere fatto, è possibile ridurre al minimo la ricerca e la corrispondenza che avvengono dopo aver esaminato la riga contenente l'interfaccia o la classe minimizzando così l'elaborazione e (si spera) l'errore StackOverflow?

È stato utile?

Soluzione

Prova

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

in modalità dot-match-all. Motivazione:

[\ w \ s] (il | non appartiene lì) corrisponde a qualsiasi cosa, comprese le interruzioni di riga. Ciò si traduce in molti backtracking nelle righe che la parte precedente della regex aveva abbinato.

Se lasci che il punto goloso divori tutto fino alla fine del file (veloce) e poi fai un passo indietro fino a trovare una linea che inizia con parole o spazi / tabulazioni (ma senza nuove righe) e quindi class o interfaccia e \ 1, quindi ciò non richiede tanto spazio nello stack.

Una soluzione diversa, e probabilmente anche migliore, sarebbe quella di dividere il problema in parti.

Per prima cosa, corrisponde al file : (\ w +) \. java . Quindi esegui una seconda ricerca con ^ [\ w \ t] + (?: class | interface) più la corrispondenza \ 1 dalla prima ricerca nello stesso file.

Altri suggerimenti

Seguito:

Ho inserito il suggerimento di Tim Pietzcher sopra e la sua soluzione golosa è fallita più velocemente e senza StackOverflowError quando non è stata trovata alcuna corrispondenza. Tuttavia, nel caso positivo, StackOverflowError si è comunque verificato.

Ho dato un'occhiata al codice sorgente RegexpCheck.java . Il modello delle classi è costruito in modalità multilinea in modo tale che le espressioni ^ e $ corrispondano subito dopo o appena prima, rispettivamente, un terminatore di riga o la fine della sequenza di input. Quindi legge l'intero file di classe in una stringa ed esegue una ricerca ricorsiva per il modello (vedere findMatch ()). Questo è senza dubbio la fonte di StackOverflowException.

Alla fine non l'ho fatto funzionare (e ho rinunciato) Da quando Maven 2 ha rilasciato il maven-checkstyle-plugin-2.4 / Checkstyle 5.0 circa 6 settimane fa abbiamo deciso di aggiornare i nostri strumenti. Questo potrebbe non risolvere il problema StackOverflowError, ma mi darà qualcos'altro su cui lavorare fino a quando qualcuno deciderà che dobbiamo perseguire nuovamente questo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top