Come disabilitare una particolare regola di stile di controllo per una particolare riga di codice?


183

Ho un checkstyle regola di convalida configurato nel mio progetto, che vieta di definire metodi di classe con più di 3 parametri di input. La regola funziona bene per le mie lezioni, ma a volte devo estendere le lezioni di terze parti, che non obbediscono a questa particolare regola.

Esiste la possibilità di indicare allo "stile di controllo" che un determinato metodo debba essere silenziosamente ignorato?

A proposito, ho finito con il mio wrapper di checkstyle: qulice.com (vedi Controllo rigoroso della qualità del codice Java )

Risposte:


291

Scopri l'uso di supressionCommentFilter su http://checkstyle.sourceforge.net/config_filters.html#SuppressionCommentFilter . Dovrai aggiungere il modulo a checkstyle.xml

<module name="SuppressionCommentFilter"/>

ed è configurabile. Quindi puoi aggiungere commenti al tuo codice per disattivare lo stile di controllo (a vari livelli) e quindi riaccenderlo attraverso l'uso dei commenti nel tuo codice. Per esempio

//CHECKSTYLE:OFF
public void someMethod(String arg1, String arg2, String arg3, String arg4) {
//CHECKSTYLE:ON

O ancora meglio, usa questa versione più ottimizzata:

<module name="SuppressionCommentFilter">
    <property name="offCommentFormat" value="CHECKSTYLE.OFF\: ([\w\|]+)"/>
    <property name="onCommentFormat" value="CHECKSTYLE.ON\: ([\w\|]+)"/>
    <property name="checkFormat" value="$1"/>
</module>

che consente di disattivare controlli specifici per specifiche righe di codice:

//CHECKSTYLE.OFF: IllegalCatch - Much more readable than catching 7 exceptions
catch (Exception e)
//CHECKSTYLE.ON: IllegalCatch

* Nota: dovrai anche aggiungere FileContentsHolder:

<module name="FileContentsHolder"/>

Guarda anche

<module name="SuppressionFilter">
    <property name="file" value="docs/suppressions.xml"/>
</module>

nella SuppressionFiltersezione in quella stessa pagina, che consente di disattivare i singoli controlli per le risorse con pattern corrispondenti.

Quindi, se hai nel tuo checkstyle.xml:

<module name="ParameterNumber">
   <property name="id" value="maxParameterNumber"/>
   <property name="max" value="3"/>
   <property name="tokens" value="METHOD_DEF"/>
</module>

Puoi disattivarlo nel tuo file xml di soppressione con:

<suppress id="maxParameterNumber" files="YourCode.java"/>

Un altro metodo, ora disponibile in Checkstyle 5.7, è quello di eliminare le violazioni tramite l' @SuppressWarningsannotazione java. Per fare ciò, dovrai aggiungere due nuovi moduli ( SuppressWarningsFiltere SuppressWarningsHolder) nel tuo file di configurazione:

<module name="Checker">
   ...
   <module name="SuppressWarningsFilter" />
   <module name="TreeWalker">
       ...
       <module name="SuppressWarningsHolder" />
   </module>
</module> 

Quindi, all'interno del tuo codice puoi effettuare le seguenti operazioni:

@SuppressWarnings("checkstyle:methodlength")
public void someLongMethod() throws Exception {

oppure, per soppressioni multiple:

@SuppressWarnings({"checkstyle:executablestatementcount", "checkstyle:methodlength"})
public void someLongMethod() throws Exception {

NB: il checkstyle:prefisso " " è facoltativo (ma consigliato). Secondo i documenti, il nome del parametro deve essere in minuscolo, ma la pratica indica che tutti i casi funzionano.


7
Ricorda di aggiungere FileContentsHolder su TreeWalter. Vedere stackoverflow.com/a/5764666/480483
djjeck

2
se lo usi //CHECKSTYLE.OFF: e poi dimentichi di riaccenderlo, rimarrà spuntato solo nel file contenente //CHECKSTYLE.OFF: o anche tutti i file successivamente elaborati?
Roland,

1
@Roland, rimane spento solo per la durata della lezione di prova.
Chris Knight,

1
"il nome del parametro deve essere in minuscolo." @SuppressWarnings("checkstyle:VariableDeclarationUsageDistance")ha funzionato altrettanto bene per me come l'equivalente minuscolo.
Anders Rabo Thorbeck,

2
Dal momento che checkstyle 8.1 il SuppressionCommentFilter dovrebbe essere sotto la TreeWalker, e il FileContentHoldernon è necessario (disponibile) più.
avandeursen,

70

Se si preferisce utilizzare le annotazioni per mettere a tacere selettivamente le regole, questo è ora possibile utilizzando l' @SuppressWarningsannotazione, a partire da Checkstyle 5.7 (e supportato dal Checkstyle Maven Plugin 2.12+).

Innanzitutto, nel tuo checkstyle.xml, aggiungi il SuppressWarningsHoldermodulo a TreeWalker:

<module name="TreeWalker">
    <!-- Make the @SuppressWarnings annotations available to Checkstyle -->
    <module name="SuppressWarningsHolder" />
</module>

Quindi, abilita SuppressWarningsFilterthere (come fratello / sorella TreeWalker):

<!-- Filter out Checkstyle warnings that have been suppressed with the @SuppressWarnings annotation -->
<module name="SuppressWarningsFilter" />

<module name="TreeWalker">
...

Ora puoi annotare, ad esempio, il metodo che desideri escludere da una determinata regola di Checkstyle:

@SuppressWarnings("checkstyle:methodlength")
@Override
public boolean equals(Object obj) {
    // very long auto-generated equals() method
}

Il checkstyle:prefisso nell'argomento a@SuppressWarnings è facoltativo, ma mi piace come promemoria da dove proviene questo avviso. Il nome della regola deve essere minuscolo.

Infine, se stai usando Eclipse, si lamenterà del fatto che l'argomento è sconosciuto:

@SuppressWarnings non supportato ("checkstyle: methodlength")

Puoi disabilitare questo avviso Eclipse nelle preferenze se ti piace:

Preferences:
  Java
  --> Compiler
  --> Errors/Warnings
  --> Annotations
  --> Unhandled token in '@SuppressWarnings': set to 'Ignore'

2
Nomino questa come risposta verificata, poiché penso che questa sia la soluzione che dovrebbe funzionare meglio nella maggior parte dei casi.
avandeursen,

33

Ciò che funziona bene è SuppressWithNearbyCommentFilter che utilizza i singoli commenti per sopprimere gli eventi di controllo.

Per esempio

// CHECKSTYLE IGNORE check FOR NEXT 1 LINES
public void onClick(View view) { ... }

Per configurare un filtro in modo che CHECKSTYLE IGNORE verifichi LE PROSSIME LINEE VAR evita di innescare eventuali audit per il controllo dato per la riga corrente e le righe var successive (per un totale di var + 1 righe):

<module name="SuppressWithNearbyCommentFilter">
    <property name="commentFormat" value="CHECKSTYLE IGNORE (\w+) FOR NEXT (\d+) LINES"/>
    <property name="checkFormat" value="$1"/>
    <property name="influenceFormat" value="$2"/>
</module>

http://checkstyle.sourceforge.net/config.html


Modificherei la regex per CHECKSTYLE IGNORE (\w+) FOR NEXT (\d+) LINES?rendere più leggibile il comando ignore. (Sarai in grado di utilizzare "CHECKSTYLE IGNORE check FOR NEXT 1 LINE" e "CHECKSTYLE IGNORE check FOR NEXT 3 LINES").
Matt3o12,

@ matt3o12 CHECKSTYLE IGNORE (\w+) FOR NEXT (\d+) LINEfunziona anche per me (corrisponde sia a lineche a lines).
Slava Semushin,

3

Ogni risposta che fa riferimento a SuppressWarningsFilter manca di un dettaglio importante. Puoi usare l'id tutto minuscolo se è definito come tale nel tuo checkstyle-config.xml. In caso contrario, è necessario utilizzare il nome del modulo originale.

Ad esempio, se nel mio checkstyle-config.xml ho:

<module name="NoWhitespaceBefore"/>

Non posso usare:

@SuppressWarnings({"nowhitespacebefore"})

Devo, tuttavia, usare:

@SuppressWarnings({"NoWhitespaceBefore"})

Affinché la prima sintassi funzioni, checkstyle-config.xml dovrebbe avere:

<module name="NoWhitespaceBefore">
  <property name="id" value="nowhitespacebefore"/>
</module>

Questo è ciò che ha funzionato per me, almeno nella versione CheckStyle 6.17.


1

Ho avuto difficoltà con le risposte sopra, potenzialmente perché ho impostato gli avvisi checkStyle come errori. Ciò che ha funzionato è stato SuppressionFilter: http://checkstyle.sourceforge.net/config_filters.html#SuppressionFilter

Lo svantaggio di ciò è che l'intervallo di righe è archiviato in un file suppresssions.xml separato, quindi uno sviluppatore sconosciuto potrebbe non stabilire immediatamente la connessione.


Grazie, è stata l'unica cosa che ha funzionato anche per me
jonathanrz

1
<module name="Checker">
    <module name="SuppressionCommentFilter"/>
    <module name="TreeWalker">
        <module name="FileContentsHolder"/>
    </module>
</module>

Per configurare un filtro per sopprimere gli eventi di controllo tra un commento contenente la riga BEGIN GENERATED CODE e un commento contenente la riga END GENERATED CODE:

<module name="SuppressionCommentFilter">
  <property name="offCommentFormat" value="BEGIN GENERATED CODE"/>
  <property name="onCommentFormat" value="END GENERATED CODE"/>
</module>

//BEGIN GENERATED CODE
@Override
public boolean equals(Object obj) { ... } // No violation events will be reported

@Override
public int hashCode() { ... } // No violation events will be reported
//END GENERATED CODE

Vedi altro


0

Puoi provare https://checkstyle.sourceforge.io/config_filters.html#SuppressionXpathFilter

Puoi configurarlo come:


<module name="SuppressionXpathFilter">
  <property name="file" value="config/suppressions-xpath.xml"/>
  <property name="optional" value="false"/>
</module>
        

Generare soppressioni Xpath usando l'interfaccia della riga di comando con l'opzione -g e specificare l'output utilizzando l'opzione -o.

https://checkstyle.sourceforge.io/cmdline.html#Command_line_usage

Ecco uno snippet di formiche che ti aiuterà a impostare la generazione automatica delle soppressioni Checkstyle:


<target name="checkstyleg">
    <move file="suppressions-xpath.xml"
      tofile="suppressions-xpath.xml.bak"
      preservelastmodified="true"
      force="true"
      failonerror="false"
      verbose="true"/>
    <fileset dir="${basedir}"
                    id="javasrcs">
    <include name="**/*.java" />
    </fileset>
    <pathconvert property="sources"
                            refid="javasrcs"
                            pathsep=" " />
    <loadfile property="cs.cp"
                        srcFile="../${cs.classpath.file}" />
    <java classname="${cs.main.class}"
                logError="true">
    <arg line="-c ../${cs.config} -p ${cs.properties} -o ${ant.project.name}-xpath.xml -g ${sources}" />
    <classpath>
        <pathelement path="${cs.cp}" />
        <pathelement path="${java.class.path}" />
    </classpath>
</java>
<condition property="file.is.empty" else="false">
     <length file="${ant.project.name}-xpath.xml" when="equal" length="0" />
   </condition>
   <if>
     <equals arg1="${file.is.empty}" arg2="false"/>
     <then>
     <move file="${ant.project.name}-xpath.xml"
      tofile="suppressions-xpath.xml"
      preservelastmodified="true"
      force="true"
      failonerror="true"
  verbose="true"/>
   </then>
</if>
    </target>

Suppressions-xpath.xml è specificato come origine soppressioni Xpath nella configurazione delle regole di Checkstyle. Nel frammento sopra, sto caricando il percorso di classe Checkstyle da un file cs.cp in una proprietà. Puoi scegliere di specificare direttamente il percorso di classe.

Oppure potresti usare Groovy in Maven (o Ant) per fare lo stesso:


import java.nio.file.Files
import java.nio.file.StandardCopyOption  
import java.nio.file.Paths

def backupSuppressions() {
  def supprFileName = 
      project.properties["checkstyle.suppressionsFile"]
  def suppr = Paths.get(supprFileName)
  def target = null
  if (Files.exists(suppr)) {
    def supprBak = Paths.get(supprFileName + ".bak")
    target = Files.move(suppr, supprBak,
        StandardCopyOption.REPLACE_EXISTING)
    println "Backed up " + supprFileName
  }
  return target
}

def renameSuppressions() {
  def supprFileName = 
      project.properties["checkstyle.suppressionsFile"]
  def suppr = Paths.get(project.name + "-xpath.xml")
  def target = null
  if (Files.exists(suppr)) {
    def supprNew = Paths.get(supprFileName)
    target = Files.move(suppr, supprNew)
    println "Renamed " + suppr + " to " + supprFileName
  }
  return target
}

def getClassPath(classLoader, sb) {
  classLoader.getURLs().each {url->
     sb.append("${url.getFile().toString()}:")
  }
  if (classLoader.parent) {
     getClassPath(classLoader.parent, sb)
  }
  return sb.toString()
}

backupSuppressions()

def cp = getClassPath(this.class.classLoader, 
    new StringBuilder())
def csMainClass = 
      project.properties["cs.main.class"]
def csRules = 
      project.properties["checkstyle.rules"]
def csProps = 
      project.properties["checkstyle.properties"]

String[] args = ["java", "-cp", cp,
    csMainClass,
    "-c", csRules,
"-p", csProps,
"-o", project.name + "-xpath.xml",
"-g", "src"]

ProcessBuilder pb = new ProcessBuilder(args)
pb = pb.inheritIO()
Process proc = pb.start()
proc.waitFor()

renameSuppressions()

L'unico inconveniente con l'uso delle soppressioni Xpath --- oltre ai controlli che non supporta --- è se si dispone di codice come il seguente:

package cstests;

@SuppressWarnings("PMD")
public interface TestMagicNumber {
  static byte[] getAsciiRotator() {
    byte[] rotation = new byte[95 * 2];
    for (byte i = ' '; i <= '~'; i++) {
      rotation[i - ' '] = i;
      rotation[i + 95 - ' '] = i;
    }
    return rotation;
  }
}

La soppressione Xpath generata in questo caso non viene ingerita da Checkstyle e il checker ha esito negativo con un'eccezione:

<suppress-xpath
       files="TestMagicNumber.java"
       checks="MagicNumberCheck"
       query="/INTERFACE_DEF[./IDENT[@text='TestMagicNumber']]/OBJBLOCK/METHOD_DEF[./IDENT[@text='getAsciiRotator']]/SLIST/LITERAL_FOR/SLIST/EXPR/ASSIGN[./IDENT[@text='i']]/INDEX_OP[./IDENT[@text='rotation']]/EXPR/MINUS[./CHAR_LITERAL[@text='' '']]/PLUS[./IDENT[@text='i']]/NUM_INT[@text='95']"/>

La generazione di soppressioni Xpath è consigliata quando sono state corrette tutte le altre violazioni e si desidera eliminare il resto. Non ti consentirà di selezionare istanze specifiche nel codice da eliminare. Puoi, tuttavia, scegliere e sopprimere le soppressioni dal file generato per fare proprio questo.

Per specificare una regola, un file o un messaggio di errore specifici, SuppressionXpathSingleFilter sarebbe più adatto.

https://checkstyle.sourceforge.io/config_filters.html#SuppressionXpathSingleFilter

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.