Pregunta

Hola ,

Background:

Estoy usando Checkstyle 4.4.2 con un módulo de control RegExp para detectar cuándo el nombre del archivo en los encabezados de origen de Java no coincide con el nombre del archivo de la clase o interfaz en la que residen. Esto puede suceder cuando un desarrollador copia un encabezado de una clase a otra y no modifica el " Archivo: " etiqueta.

El uso de expresiones regulares en el verificador de RexExp ha pasado por muchas encarnaciones y (aunque posiblemente sea una exageración en este punto) tiene este aspecto:

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

La forma básica de los archivos que estoy verificando (aunque muy simplificada) tiene este aspecto

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

El problema:

Cuando no se encuentra ninguna coincidencia , (es decir, cuando un encabezado que contiene " Archivo: Bar.java " se copia en el archivo Bat.java) Recibo un StackOverflowError en archivos muy largos (mi caso de prueba es @ 1300 líneas).

He experimentado con varios comprobadores visuales de expresiones regulares y puedo ver que en el caso no coincidente cuando el motor de expresiones regulares pasa la línea que contiene la clase o el nombre de la interfaz comienza a buscar de nuevo en la siguiente línea y realiza un seguimiento que probablemente provoca que StackOverflowError

La pregunta:

Cómo evitar que StackOverflowError modifique la expresión regular

¿Hay alguna forma de modificar mi expresión regular de modo que en el caso no coincidente (es decir, cuando se copie un encabezado que contenga la palabra " Archivo: Bar.java " en el archivo Bat.java) que la coincidencia se detendría una vez que examine la línea que contiene la interfaz o el nombre de la clase y vea que " \ 1 " no coincide con el primer grupo.

Alternativamente, si se puede hacer, ¿es posible minimizar la búsqueda y la coincidencia que tiene lugar después de examinar la línea que contiene la interfaz o clase, minimizando así el procesamiento y (con suerte) el error de StackOverflow?

¿Fue útil?

Solución

Probar

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

en el modo punto-coincidencias-todos. Justificación:

[\ w \ s] (el | no pertenece) coincide con cualquier cosa, incluidos los saltos de línea. Esto resulta en una gran cantidad de retroceso en las líneas que la parte anterior de la expresión regular había coincidido.

Si deja que el codicioso punto engulle todo hasta el final del archivo (rápido) y luego retroceda hasta que encuentre una línea que comience con palabras o espacios / tabulaciones (pero no con nuevas líneas) y luego class o interface y \ 1, entonces eso no requiere tanto espacio de pila.

Una solución diferente, y probablemente incluso mejor sería dividir el problema en partes.

Primero haga coincidir el archivo : (\ w +) \. java . Luego haga una segunda búsqueda con ^ [\ w \ t] + (?: Class | interface) más la coincidencia de \ 1 de la primera búsqueda en el mismo archivo.

Otros consejos

Seguimiento:

He incluido la sugerencia de Tim Pietzcher arriba y su solución codiciosa realmente falló más rápido y sin un StackOverflowError cuando no se encontró una coincidencia. Sin embargo, en el caso positivo, el StackOverflowError todavía ocurrió.

Eché un vistazo al código fuente RegexpCheck.java . El patrón de clases se construye en modo multilínea, de modo que las expresiones ^ y $ coincidan justo después o justo antes, respectivamente, de un terminador de línea o del final de la secuencia de entrada. Luego lee todo el archivo de la clase en una cadena y realiza una búsqueda recursiva del patrón (vea findMatch ()). Esa es, sin duda, la fuente de la excepción StackOverflowException.

Al final no logré que funcionara (y me rendí). Desde que Maven 2 lanzó Maven-checkstyle-plugin-2.4 / Checkstyle 5.0 hace unas 6 semanas, decidimos actualizar nuestras herramientas. Es posible que esto no resuelva el problema StackOverflowError, pero me dará algo más en lo que trabajar hasta que alguien decida que debemos continuar con esto.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top