Pour les outils d'analyse statique, j'utilise souvent CPD, PMD , FindBugs et Checkstyle .
CPD est l'outil PMD "Copy / Paste Detector". J'utilisais PMD pendant un petit moment avant de remarquer le lien «Finding Duplicated Code» sur la page Web PMD .
Je tiens à souligner que ces outils peuvent parfois être étendus au-delà de leur ensemble de règles «prêt à l'emploi». Et pas seulement parce qu'ils sont open source afin que vous puissiez les réécrire. Certains de ces outils sont livrés avec des applications ou "hooks" qui leur permettent d'être étendus. Par exemple, PMD est fourni avec l' outil "designer" qui vous permet de créer de nouvelles règles. En outre, Checkstyle a la vérification DescendantToken qui a des propriétés qui permettent une personnalisation substantielle.
J'intègre ces outils avec une version basée sur Ant . Vous pouvez suivre le lien pour voir ma configuration commentée.
En plus de la simple intégration dans la construction, je trouve utile de configurer les outils pour qu'ils soient quelque peu «intégrés» de plusieurs autres manières. À savoir, la génération de rapports et l'uniformité de la suppression des avertissements. Je voudrais ajouter ces aspects à cette discussion (qui devrait probablement avoir la balise "static-analysis" aussi): comment les gens configurent-ils ces outils pour créer une solution "unifiée"? (J'ai posé cette question séparément ici )
Tout d'abord, pour les rapports d'avertissement, je transforme la sortie afin que chaque avertissement ait le format simple:
/absolute-path/filename:line-number:column-number: warning(tool-name): message
Ceci est souvent appelé le «format Emacs», mais même si vous n'utilisez pas Emacs, c'est un format raisonnable pour homogénéiser les rapports. Par exemple:
/project/src/com/example/Foo.java:425:9: warning(Checkstyle):Missing a Javadoc comment.
Mes transformations de format d'avertissement sont effectuées par mon script Ant avec des chaînes de filtres Ant .
La deuxième "intégration" que je fais est pour la suppression des avertissements. Par défaut, chaque outil prend en charge les commentaires ou une annotation (ou les deux) que vous pouvez placer dans votre code pour faire taire un avertissement que vous souhaitez ignorer. Mais ces diverses demandes de suppression d'avertissement n'ont pas un aspect cohérent qui semble quelque peu idiot. Lorsque vous supprimez un avertissement, vous supprimez un avertissement, alors pourquoi ne pas toujours écrire " SuppressWarning
?"
Par exemple, la configuration par défaut de PMD supprime la génération d'avertissements sur les lignes de code avec la chaîne " NOPMD
" dans un commentaire. De plus, PMD prend en charge l' @SuppressWarnings
annotation Java . Je configure PMD pour utiliser des commentaires contenant " SuppressWarning(PMD.
" au lieu de NOPMD
pour que les suppressions PMD se ressemblent. Je remplis la règle particulière violée lors de l'utilisation de la suppression du style de commentaire:
// SuppressWarnings(PMD.PreserveStackTrace) justification: (false positive) exceptions are chained
Seule la SuppressWarnings(PMD.
partie " " est significative pour un commentaire, mais elle est cohérente avec la prise en charge par PMD de l' @SuppressWarning
annotation qui reconnaît les violations de règle individuelles par leur nom:
@SuppressWarnings("PMD.CompareObjectsWithEquals") // justification: identity comparision intended
De même, Checkstyle supprime la génération d'avertissements entre les paires de commentaires (aucune prise en charge d'annotation n'est fournie). Par défaut, les commentaires pour activer et désactiver Checkstyle contiennent les chaînes CHECKSTYLE:OFF
et CHECKSTYLE:ON
, respectivement. Changer cette configuration (avec "SuppressionCommentFilter" de Checkstyle) pour utiliser les chaînes " BEGIN SuppressWarnings(CheckStyle.
" et " END SuppressWarnings(CheckStyle.
" fait que les contrôles ressemblent davantage à PMD:
// BEGIN SuppressWarnings(Checkstyle.HiddenField) justification: "Effective Java," 2nd ed., Bloch, Item 2
// END SuppressWarnings(Checkstyle.HiddenField)
Avec les commentaires Checkstyle, la violation de vérification particulière ( HiddenField
) est significative car chaque vérification a sa propre BEGIN/END
paire de commentaires " ".
FindBugs prend également en charge la suppression de la génération d'avertissement avec une @SuppressWarnings
annotation, de sorte qu'aucune configuration supplémentaire n'est nécessaire pour atteindre un certain niveau d'uniformité avec d'autres outils. Malheureusement, Findbugs doit prendre en charge une @SuppressWarnings
annotation personnalisée car l' @SuppressWarnings
annotation Java intégrée a une SOURCE
politique de rétention qui n'est pas assez forte pour conserver l'annotation dans le fichier de classe là où FindBugs en a besoin. Je qualifie entièrement les suppressions d'avertissements FindBugs pour éviter les conflits avec l' @SuppressWarnings
annotation de Java :
@edu.umd.cs.findbugs.annotations.SuppressWarnings("UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR")
Ces techniques rendent les choses raisonnablement cohérentes entre les outils. Notez que le fait que chaque suppression d'avertissement contienne la chaîne " SuppressWarnings
" facilite l'exécution d'une recherche simple pour trouver toutes les instances de tous les outils sur une base de code entière.