Per gli strumenti di analisi statica utilizzo spesso CPD, PMD , FindBugs e Checkstyle .
CPD è lo strumento PMD "Copy / Paste Detector". Stavo usando PMD per un po 'prima di notare il link "Finding Duplicated Code" sulla pagina web di PMD .
Vorrei sottolineare che questi strumenti a volte possono essere estesi oltre il loro insieme di regole "fuori dagli schemi". E non solo perché sono open source in modo da poterli riscrivere. Alcuni di questi strumenti vengono forniti con applicazioni o "ganci" che consentono di estenderli. Ad esempio, PMD viene fornito con lo strumento "designer" che consente di creare nuove regole. Inoltre, Checkstyle ha il controllo DescendantToken che ha proprietà che consentono una personalizzazione sostanziale.
Integro questi strumenti con una build basata su Ant . Puoi seguire il link per vedere la mia configurazione commentata.
Oltre alla semplice integrazione nella build, trovo utile configurare gli strumenti in modo che siano in qualche modo "integrati" in un paio di altri modi. Vale a dire, uniformità della generazione di report e della soppressione degli avvisi. Vorrei aggiungere questi aspetti a questa discussione (che probabilmente dovrebbe avere anche il tag "static-analysis"): come stanno configurando questi strumenti le persone per creare una soluzione "unificata"? (Ho posto questa domanda separatamente qui )
Innanzitutto, per i report di avviso, trasformo l'output in modo che ogni avviso abbia il formato semplice:
/absolute-path/filename:line-number:column-number: warning(tool-name): message
Questo è spesso chiamato "formato Emacs", ma anche se non stai usando Emacs, è un formato ragionevole per omogeneizzare i rapporti. Per esempio:
/project/src/com/example/Foo.java:425:9: warning(Checkstyle):Missing a Javadoc comment.
Le mie trasformazioni del formato di avviso vengono eseguite dal mio script Ant con le catene di filtri Ant .
La seconda "integrazione" che faccio è per la soppressione degli avvisi. Per impostazione predefinita, ogni strumento supporta commenti o un'annotazione (o entrambi) che è possibile inserire nel codice per silenziare un avviso che si desidera ignorare. Ma queste varie richieste di soppressione degli avvisi non hanno un aspetto coerente che sembra alquanto sciocco. Quando sopprimi un avviso, stai sopprimendo un avviso, quindi perché non scrivere sempre " SuppressWarning
?"
Ad esempio, la configurazione predefinita di PMD sopprime la generazione di avvisi sulle righe di codice con la stringa " NOPMD
" in un commento. Inoltre, PMD supporta l' @SuppressWarnings
annotazione di Java . Configuro PMD per utilizzare commenti contenenti " SuppressWarning(PMD.
" invece di in NOPMD
modo che le soppressioni PMD si assomiglino. Inserisco la regola particolare che viene violata quando si utilizza la soppressione dello stile di commento:
// SuppressWarnings(PMD.PreserveStackTrace) justification: (false positive) exceptions are chained
Solo la parte " SuppressWarnings(PMD.
" è significativa per un commento, ma è coerente con il supporto di PMD per l' @SuppressWarning
annotazione che riconosce le singole violazioni delle regole per nome:
@SuppressWarnings("PMD.CompareObjectsWithEquals") // justification: identity comparision intended
Allo stesso modo, Checkstyle sopprime la generazione di avvisi tra coppie di commenti (non viene fornito alcun supporto per le annotazioni). Per impostazione predefinita, i commenti per disattivare e attivare Checkstyle contengono le stringhe CHECKSTYLE:OFF
e CHECKSTYLE:ON
, rispettivamente. La modifica di questa configurazione (con "SuppressionCommentFilter" di Checkstyle) per utilizzare le stringhe " BEGIN SuppressWarnings(CheckStyle.
" e " END SuppressWarnings(CheckStyle.
" rende i controlli più simili a PMD:
// BEGIN SuppressWarnings(Checkstyle.HiddenField) justification: "Effective Java," 2nd ed., Bloch, Item 2
// END SuppressWarnings(Checkstyle.HiddenField)
Con i commenti stile di controllo, la particolare violazione del controllo ( HiddenField
) è significativa perché ogni controllo ha la sua " BEGIN/END
" coppia di commenti.
FindBugs supporta anche la soppressione della generazione di avvisi con @SuppressWarnings
un'annotazione, quindi non sono necessarie ulteriori configurazioni per ottenere un certo livello di uniformità con altri strumenti. Sfortunatamente, Findbugs deve supportare @SuppressWarnings
un'annotazione personalizzata perché l' @SuppressWarnings
annotazione Java incorporata ha una SOURCE
politica di conservazione che non è abbastanza forte da mantenere l'annotazione nel file di classe in cui FindBugs ne ha bisogno. Qualifico pienamente la soppressione degli avvisi di FindBugs per evitare conflitti con l' @SuppressWarnings
annotazione di Java :
@edu.umd.cs.findbugs.annotations.SuppressWarnings("UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR")
Queste tecniche fanno sembrare le cose ragionevolmente coerenti tra gli strumenti. Notare che il fatto che ogni soppressione di avviso contenga la stringa " SuppressWarnings
" semplifica l'esecuzione di una semplice ricerca per trovare tutte le istanze per tutti gli strumenti su un'intera base di codice.