StackOverflowError com Checkstyle 4,4 verificação RegExp
-
05-07-2019 - |
Pergunta
Olá,
Antecedentes:
Eu estou usando Checkstyle 4.4.2 com um módulo verificador RegExp para detectar quando o nome do arquivo em cabeçalhos de origem fora java não coincidir com o nome da classe ou interface em que residem arquivo. Isso pode acontecer quando um desenvolvedor de cópias de um cabeçalho de uma classe para outra e não modifica o "arquivo:". Tag
O uso de expressões regulares no verificador RexExp passou por muitas encarnações e (embora seja possivelmente um exagero neste momento) parece com isso:
File: (\w+)\.java\n(?:.*\n)*?(?:[\w|\s]*?(?: class | interface )\1)
A forma básica de arquivos que eu estou verificando (embora muito simplificada) se parece com isso
/*
*
* Copyright 2009
* ...
* File: Bar.java
* ...
*/
package foo
...
import ..
...
/**
* ...
*/
public class Bar
{...}
O Problema:
Quando nenhuma correspondência for encontrada , (ou seja, quando um cabeçalho contendo "File: Bar.java" é copiado para arquivo Bat.java) eu receber uma StackOverflowError em arquivos muito longos (meu caso de teste é @ 1300 linhas).
Eu experimentei com vários testadores de expressão regular visuais e pode ver que no caso de não-casamento quando o motor regex passa a linha que contém o nome da classe ou interface que começa a procurar novamente na próxima linha e faz algum retrocesso que provavelmente faz com que o StackOverflowError
A Pergunta:
Como evitar a StackOverflowError modificando a expressão regular
Existe alguma maneira de modificar a minha expressão regular tal que no caso de não-casamento (ou seja, quando um cabeçalho contendo "File: Bar.java" é copiado para arquivo Bat.java) que a correspondência iria parar uma vez que examina a linha que contém o nome da interface ou classe e vê que "\ 1" não coincide com o primeiro grupo.
Como alternativa, se isso pode ser feito, é é possível minimizar a pesquisa e correspondência que ocorre depois que examina a linha que contém o interface ou classe de processamento minimizando, assim, e (espero) o erro StackOverflow?
Solução
Tente
File: (\w+)\.java\n.*^[\w \t]+(?:class|interface) \1
no ponto-jogos-all modo. Justificativa:
[\w\s]
(a | não pertence lá) corresponde a qualquer coisa, incluindo as quebras de linha. Isso resulta em um monte de retrocesso de volta para as linhas que a parte anterior do regex tinha correspondido.
Se você deixar o ponto gananciosos devorar tudo até o final do arquivo (rápida) e, em seguida, recuar até encontrar uma linha que começa com palavras ou espaços / abas (mas sem novas linhas) e depois class
ou interface
e \ 1, em seguida, que não requer tanto espaço pilha.
Um diferente, e provavelmente melhor solução ainda seria dividir o problema em partes.
Primeiro coincidir com a parte File: (\w+)\.java
. Em seguida, faça uma segunda pesquisa com ^[\w \t]+(?:class|interface)
mais o jogo \1
da primeira pesquisa sobre o mesmo arquivo.
Outras dicas
Siga-se:
I ligado a sugestão de Tim Pietzcher acima e sua solução ganancioso, de fato, falhar mais rápido e sem StackOverflowError quando nenhuma correspondência foi encontrada. No entanto, no caso positivo, o StackOverflowError ainda ocorrido.
Eu levei um olhar para o código-fonte RegexpCheck.java . O padrão de classes é construído de modo tal que as várias linhas expressões ^ e $ jogo apenas depois ou imediatamente antes de, respectivamente, um terminal de linha ou o fim da sequência de entrada. Em seguida, ele lê o arquivo de classe inteira em uma corda e faz uma pesquisa recursiva para o padrão (veja findMatch ()). Essa é, sem dúvida, a fonte do StackOverflowException.
No final, eu não fazê-lo funcionar (e desistiu) Desde Maven 2 lançado do Maven-checkstyle plugin-2.4 / 5.0 Checkstyle cerca de 6 semanas atrás nós decidimos atualizar nossas ferramentas. Isto pode não resolver o problema StackOverflowError, mas vai me dar alguma coisa para o trabalho em até que alguém decide que precisamos perseguir isso novamente.