Para ferramentas de análise estática, geralmente uso CPD, PMD , FindBugs e Checkstyle .
CPD é a ferramenta PMD "Copiar / Colar Detector". Eu estava usando o PMD por um tempo antes de notar o link "Finding Duplicated Code" na página do PMD .
Eu gostaria de salientar que essas ferramentas às vezes podem ser estendidas além de seu conjunto de regras "out-of-the-box". E não apenas porque eles são de código aberto para que você possa reescrevê-los. Algumas dessas ferramentas vêm com aplicativos ou "ganchos" que permitem que sejam estendidas. Por exemplo, o PMD vem com a ferramenta "designer" que permite criar novas regras. Além disso, Checkstyle tem a verificação DescendantToken que possui propriedades que permitem uma personalização substancial.
Eu integro essas ferramentas com uma construção baseada no Ant . Você pode seguir o link para ver minha configuração comentada.
Além da integração simples com a construção, acho útil configurar as ferramentas para serem um tanto "integradas" de algumas outras maneiras. Ou seja, geração de relatórios e uniformidade de supressão de avisos. Eu gostaria de adicionar esses aspectos a esta discussão (que provavelmente deveria ter a tag "análise estática" também): como as pessoas estão configurando essas ferramentas para criar uma solução "unificada"? (Eu fiz esta pergunta separadamente aqui )
Primeiro, para relatórios de aviso, eu transformo a saída para que cada aviso tenha o formato simples:
/absolute-path/filename:line-number:column-number: warning(tool-name): message
Isso geralmente é chamado de "formato Emacs", mas mesmo se você não estiver usando o Emacs, é um formato razoável para homogeneizar relatórios. Por exemplo:
/project/src/com/example/Foo.java:425:9: warning(Checkstyle):Missing a Javadoc comment.
Minhas transformações de formato de aviso são feitas por meu script Ant com filterchains Ant .
A segunda "integração" que faço é para supressão de avisos. Por padrão, cada ferramenta oferece suporte a comentários ou uma anotação (ou ambos) que você pode colocar em seu código para silenciar um aviso que deseja ignorar. Mas essas várias solicitações de supressão de aviso não têm uma aparência consistente, o que parece um tanto bobo. Ao suprimir um aviso, você está suprimindo um aviso, então por que não escrever sempre " SuppressWarning
?"
Por exemplo, a configuração padrão do PMD suprime a geração de avisos nas linhas de código com a string " NOPMD
" em um comentário. Além disso, o PMD oferece suporte à @SuppressWarnings
anotação Java . Eu configuro o PMD para usar comentários contendo " SuppressWarning(PMD.
" em vez de NOPMD
para que as supressões de PMD sejam semelhantes. Eu preencho a regra específica que é violada ao usar a supressão de estilo de comentário:
// SuppressWarnings(PMD.PreserveStackTrace) justification: (false positive) exceptions are chained
Apenas a SuppressWarnings(PMD.
parte " " é significativa para um comentário, mas é consistente com o suporte do PMD para a @SuppressWarning
anotação que reconhece violações de regra individuais por nome:
@SuppressWarnings("PMD.CompareObjectsWithEquals") // justification: identity comparision intended
Da mesma forma, Checkstyle suprime a geração de avisos entre pares de comentários (nenhum suporte de anotação é fornecido). Por padrão, os comentários para ativar e desativar Checkstyle contêm as strings CHECKSTYLE:OFF
e CHECKSTYLE:ON
, respectivamente. Alterar esta configuração (com "SuppressionCommentFilter" do Checkstyle) para usar as strings " BEGIN SuppressWarnings(CheckStyle.
" e " END SuppressWarnings(CheckStyle.
" torna os controles mais parecidos com PMD:
// BEGIN SuppressWarnings(Checkstyle.HiddenField) justification: "Effective Java," 2nd ed., Bloch, Item 2
// END SuppressWarnings(Checkstyle.HiddenField)
Com comentários de estilo de verificação, a violação de verificação específica ( HiddenField
) é significativa porque cada verificação tem seu próprio BEGIN/END
par de comentários " ".
FindBugs também suporta a supressão de geração de aviso com uma @SuppressWarnings
anotação, portanto, nenhuma configuração adicional é necessária para atingir algum nível de uniformidade com outras ferramentas. Infelizmente, Findbugs precisa suportar uma @SuppressWarnings
anotação customizada porque a @SuppressWarnings
anotação Java integrada tem uma SOURCE
política de retenção que não é forte o suficiente para reter a anotação no arquivo de classe onde FindBugs precisa dela. Eu qualifico totalmente as supressões de avisos do FindBugs para evitar conflito com a @SuppressWarnings
anotação do Java :
@edu.umd.cs.findbugs.annotations.SuppressWarnings("UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR")
Essas técnicas fazem as coisas parecerem razoavelmente consistentes entre as ferramentas. Observe que ter cada supressão de aviso contendo a string " SuppressWarnings
" facilita a execução de uma pesquisa simples para encontrar todas as instâncias de todas as ferramentas em uma base de código inteira.