¿Cómo deshabilitar una regla de estilo de verificación particular para una línea de código particular?


185

Tengo una regla de validación de estilo de verificación configurada en mi proyecto, que prohíbe definir métodos de clase con más de 3 parámetros de entrada. La regla funciona bien para mis clases, pero a veces tengo que extender las clases de terceros, que no obedecen esta regla en particular.

¿Existe la posibilidad de indicarle al "estilo de verificación" que cierto método debe ser ignorado en silencio?

Por cierto, terminé con mi propio contenedor de checkstyle: qulice.com (ver Control estricto de la calidad del código Java )

Respuestas:


292

Consulte el uso de supressionCommentFilter en http://checkstyle.sourceforge.net/config_filters.html#SuppressionCommentFilter . Deberá agregar el módulo a su checkstyle.xml

<module name="SuppressionCommentFilter"/>

Y es configurable. Por lo tanto, puede agregar comentarios a su código para desactivar el estilo de verificación (en varios niveles) y luego volver a activarlo mediante el uso de comentarios en su código. P.ej

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

O incluso mejor, use esta versión más ajustada:

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

que le permite desactivar comprobaciones específicas para líneas de código específicas:

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

* Nota: también deberá agregar FileContentsHolder:

<module name="FileContentsHolder"/>

Ver también

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

debajo de la SuppressionFiltersección en esa misma página, que le permite desactivar las comprobaciones individuales para recursos de patrones coincidentes.

Entonces, si tiene en su checkstyle.xml:

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

Puede desactivarlo en su archivo xml de supresión con:

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

Otro método, ahora disponible en Checkstyle 5.7 es suprimir violaciones a través de la @SuppressWarningsanotación java. Para hacer esto, necesitará agregar dos nuevos módulos ( SuppressWarningsFiltery SuppressWarningsHolder) en su archivo de configuración:

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

Luego, dentro de su código puede hacer lo siguiente:

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

o, para múltiples supresiones:

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

NB: El checkstyle:prefijo " " es opcional (pero recomendado). Según los documentos, el nombre del parámetro debe estar en minúsculas, pero la práctica indica que cualquier caso funciona.


77
Recuerde agregar FileContentsHolder en el TreeWalter. Ver stackoverflow.com/a/5764666/480483
djjeck el

2
si usa //CHECKSTYLE.OFF: y luego olvida volver a encenderlo, ¿permanecerá marcado solo en el archivo que contiene //CHECKSTYLE.OFF: o también en todos los archivos procesados ​​posteriormente?
Roland

1
@Roland, permanece apagado solo por la duración de esa clase de prueba.
Chris Knight

1
"el nombre del parámetro debe estar en minúsculas". @SuppressWarnings("checkstyle:VariableDeclarationUsageDistance")funcionó tan bien para mí como el equivalente en minúsculas.
Anders Rabo Thorbeck

2
Desde Checkstyle 8.1 del SuppressionCommentFilter debe estar bajo el TreeWalkery el FileContentHolderno es necesario (disponible) nunca más.
avandeursen

71

Si prefiere usar anotaciones para silenciar selectivamente las reglas, ahora es posible usar la @SuppressWarningsanotación, comenzando con Checkstyle 5.7 (y compatible con Checkstyle Maven Plugin 2.12+).

Primero, en su checkstyle.xml, agregue el SuppressWarningsHoldermódulo a TreeWalker:

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

A continuación, habilite SuppressWarningsFilterthere (como un hermano para TreeWalker):

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

<module name="TreeWalker">
...

Ahora puede anotar, por ejemplo, el método que desea excluir de una determinada regla de Checkstyle:

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

El checkstyle:prefijo en el argumento @SuppressWarningses opcional, pero me gusta como recordatorio de dónde vino esta advertencia. El nombre de la regla debe estar en minúscula.

Por último, si está utilizando Eclipse, se quejará de que el argumento es desconocido para él:

@SuppressWarnings no admitido ("checkstyle: methodlength")

Puede deshabilitar esta advertencia de Eclipse en las preferencias si lo desea:

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

2
Nomino esto como la respuesta marcada, ya que creo que esta es la solución que debería funcionar mejor en la mayoría de los casos.
avandeursen

34

Lo que también funciona bien es SuppressWithNearbyCommentFilter, que utiliza comentarios individuales para suprimir eventos de auditoría.

Por ejemplo

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

Para configurar un filtro para que CHECKSTYLE IGNORE verifique para las SIGUIENTES líneas var evite activar cualquier auditoría para la verificación dada para la línea actual y las siguientes líneas var (para un total de líneas var + 1):

<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


Cambiaría la expresión regular a la CHECKSTYLE IGNORE (\w+) FOR NEXT (\d+) LINES?que hará que el comando ignorar sea más legible. (Podrá utilizar "CHECKSTYLE IGNORE check para NEXT 1 LINE" y "CHECKSTYLE IGNORE check para NEXT 3 LINES").
Matt3o12

@ matt3o12 CHECKSTYLE IGNORE (\w+) FOR NEXT (\d+) LINEtambién funciona para mí (coincide con ambos liney lines).
Slava Semushin

4

A cada respuesta que se refiere a SuppressWarningsFilter le falta un detalle importante. Solo puede usar la identificación en minúsculas si está definida como tal en su checkstyle-config.xml. Si no, debe usar el nombre del módulo original.

Por ejemplo, si en mi checkstyle-config.xml tengo:

<module name="NoWhitespaceBefore"/>

No puedo usar:

@SuppressWarnings({"nowhitespacebefore"})

Sin embargo, debo usar:

@SuppressWarnings({"NoWhitespaceBefore"})

Para que la primera sintaxis funcione, el checkstyle-config.xml debería tener:

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

Esto es lo que funcionó para mí, al menos en la versión CheckStyle 6.17.


1

Tuve dificultades con las respuestas anteriores, posiblemente porque configuré las advertencias checkStyle como errores. Lo que funcionó fue SuppressionFilter: http://checkstyle.sourceforge.net/config_filters.html#SuppressionFilter

El inconveniente de esto es que el rango de línea se almacena en un archivo suppresssions.xml separado, por lo que un desarrollador desconocido puede no hacer la conexión de inmediato.


Gracias, fue lo único que funcionó para mí también
jonathanrz

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

Para configurar un filtro para suprimir los eventos de auditoría entre un comentario que contiene la línea CÓDIGO INICIADO GENERADO y un comentario que contiene la línea CÓDIGO FINALIZADO:

<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

Ver más


0

Puede probar https://checkstyle.sourceforge.io/config_filters.html#SuppressionXpathFilter

Puedes configurarlo como:


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

Genere supresiones Xpath usando la CLI con la opción -g y especifique la salida usando el interruptor -o.

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

Aquí hay un fragmento de hormiga que lo ayudará a configurar su generación automática de supresiones 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 se especifica como la fuente de supresiones Xpath en la configuración de las reglas de Checkstyle. En el fragmento anterior, estoy cargando la ruta de clase Checkstyle desde un archivo cs.cp en una propiedad. Puede elegir especificar el classpath directamente.

O puede usar groovy dentro de Maven (o Ant) para hacer lo mismo:


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()

El único inconveniente con el uso de supresiones Xpath --- además de las comprobaciones que no admite --- es si tiene un código como el siguiente:

package cstests;

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;
  }
}

Checkstyle no ingiere la supresión de Xpath generada en este caso y el corrector falla con una excepción:

<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']"/>

Se recomienda generar supresiones Xpath cuando haya solucionado todas las demás violaciones y desee suprimir el resto. No le permitirá seleccionar instancias específicas en el código para suprimir. Sin embargo, puede elegir y eliminar supresiones del archivo generado para hacer precisamente eso.

SuppressionXpathSingleFilter es más adecuado para identificar y suprimir una regla específica, archivo o mensaje de error. Puede configurar múltiples filtros identificando cada uno por el atributo id.

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

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.