2011-05-26 10 views
12

Uso checkstyle para verificar si mi código java respeta las directrices de nuestro proyecto.Permitir instrucción if simple sin más no tener llaves en el código

Sin embargo, tenemos una guía que no puedo averiguar cómo verificar con esta herramienta. Queremos permitir simple si (entender si sin otra cosa y no otra estructura condicional en ella) no tener apoyo, como en este ejemplo:

// valid 
if(condition) callFunction(); 

// invalid 
if(condition) for(int i = 0; i < someValue; i++) callFunction(i); 

// valid 
if(condition) { 
    for(int i = 0; i < someValue; i++) { 
     callFunction(i); 
    } 
} 

// invalid 
if(condition) callFunction(); 
else callOtherFunction(); 

Esta convención se puede discutir, pero esta es la que elegimos . Permite una sintaxis reducida para casos muy triviales, pero asegura que tengamos una buena sangría y delimitación de bloques para estructuras más complejas.

Cualquier ayuda con eso sería muy apreciada.

También estoy listo para hacer algún código para realizar esta comprobación si no hay nada disponible, pero realmente no sé por dónde empezar. En el último ressort, también se apreciarán algunos consejos al respecto.

+12

Mi sugerencia seria es cambiar sus directrices. Pasa el tiempo buscando una solución para que sus pautas de estilo * sean inferiores *.Inline if declaraciones como esta (que no usan bloques) conducen a errores. Realmente, muy desagradables errores. –

+1

@Mark No conozco el uso de Ifs en línea para llamadas a funciones simples, pero creo que es razonable usarlas para verificar algunas condiciones y lanzar una excepción si no se cumplen las condiciones. –

+6

Esta pregunta no se trata de si las pautas son razonables. Esta pregunta se trata de cómo modificar el estilo de comprobación para respaldar estas pautas. Creo que deberíamos evitar discutir las directrices en esta pregunta. –

Respuesta

5

Al final, implementé un cheque personalizado para checkstyle. Aquí está el código fuente si alguien está interesado en él:

import com.puppycrawl.tools.checkstyle.api.Check; 
import com.puppycrawl.tools.checkstyle.api.DetailAST; 
import com.puppycrawl.tools.checkstyle.api.TokenTypes; 

public class IfBracesCheck extends Check { 

    @Override 
    public int[] getDefaultTokens() { 
     return new int[] { 
      TokenTypes.LITERAL_ELSE, 
      TokenTypes.LITERAL_IF, 
     }; 
    } 

    @Override 
    public void visitToken(DetailAST aAST) { 
     final DetailAST slistAST = aAST.findFirstToken(TokenTypes.SLIST); 

     if(aAST.getType() == TokenTypes.LITERAL_ELSE) { 
      // If we have an else, it must have braces, except it is an "else if" (then the if must have braces). 
      DetailAST ifToken = aAST.findFirstToken(TokenTypes.LITERAL_IF); 

      if(ifToken == null) { 
       // This is an simple else, it must have brace. 
       if(slistAST == null) { 
        log(aAST.getLineNo(), "ifBracesElse", aAST.getText()); 
       } 
      } else { 
       // This is an "else if", the if must have braces. 
       if(ifToken.findFirstToken(TokenTypes.SLIST) == null) { 
        log(aAST.getLineNo(), "ifBracesConditional", ifToken.getText(), aAST.getText() + " " + ifToken.getText()); 
       } 
      } 
     } else if(aAST.getType() == TokenTypes.LITERAL_IF) { 
      // If the if uses braces, nothing as to be checked. 
      if (slistAST != null) { 
       return; 
      } 

      // We have an if, we need to check if it has no conditionnal structure as direct child. 
      final int[] conditionals = { 
       TokenTypes.LITERAL_DO, 
       TokenTypes.LITERAL_ELSE, 
       TokenTypes.LITERAL_FOR, 
       TokenTypes.LITERAL_IF, 
       TokenTypes.LITERAL_WHILE, 
       TokenTypes.LITERAL_SWITCH, 
      }; 

      for(int conditional : conditionals) { 
       DetailAST conditionalAST = aAST.findFirstToken(conditional); 

       if (conditionalAST != null) { 
        log(aAST.getLineNo(), "ifBracesConditional", aAST.getText(), conditionalAST.getText()); 

        // Let's trigger this only once. 
        return; 
       } 
      } 
     } 
    } 
} 
0

Aunque estoy de acuerdo con los comentarios de que esta es una mala idea, es posible que no pueda cambiar las pautas. Así que es posible que desee probar esto:

  1. En el módulo Checkstyle Bloques ->necesitar aparatos ortopédicos, deshabilite la si palabra clave
  2. crear una nueva instancia del módulo Regexp ->RegexpSingleLineJava y tratar de encontrar una expresión regular que corresponda a los casos no válidos, pero no los válidos sus

(Módulo na mes son de Eclipse Checkstyle Plugin 5.3.0)

+0

Pensé en algo así, pero Regex no es lo suficientemente potente como para manejar esa regla, incluso es probable que sea parte de la solución. – deadalnix

+0

Regexp es bastante potente;) Según sus ejemplos, el segundo ejemplo ya no es válido, siempre que se requiera que el enunciado for tenga llaves. El cuarto ejemplo sigue siendo válido, pero tengo una expresión regular que funciona, pero no en checkstyle. Quizás puedas resolverlo: (? S) if. *;. * Else – Stephan

+0

No, esto no funciona: asegúrate de que no exista estructura condicionada dentro del if si es casi imposible usar regex, y la variedad de casos requiere algo de lógica. Su propuesta coincidirá con una gran variedad de casos, incluido el uso legal de if. De todos modos, supongo que con algo de expresiones regulares y un poco de lógica, algo se puede gestionar aquí. – deadalnix

1

Sólo quiero añadir que ahora propiedad soportes Checkstyle 'allowSingleLineIf' que cubre algunos casos.

<module name="NeedBraces"> 
     <property name="allowSingleLineIf" value="true"/> 
    </module> 
0

CheckStyle 6,14 NeedBracesCheck apoyo rool allowSingleLineStatement opción

allowSingleLineStatement que permite declaraciones de una sola línea sin tirantes, por ejemplo .:

si (obj.isValid()) return true;

while (obj.isValid()) return true;

hacer esto.notificar(); while (o! = null);

for (int i = 0;;) this.notify();

documentation

Cuestiones relacionadas