GReQL Regeln: Unterschied zwischen den Versionen

Aus JACK Wiki
Zur Navigation springen Zur Suche springen
Zeile 26: Zeile 26:
           with
           with
             x.name=capitalizeFirst(x.name) and
             x.name=capitalizeFirst(x.name) and
             isEmpty(from m : V{Modifier} with x <--&{FieldDeclaration} --> m and m.name="final" report m end)
             isEmpty(from m : V{Modifier} with x <nowiki>&amp;lt;--&amp;amp;{FieldDeclaration} --&amp;gt;</nowiki> m and m.name="final" report m end)
           report 0 end
           report 0 end
   </query>
   </query>

Version vom 9. Juli 2018, 11:02 Uhr

Beispiele für statische Prüfregeln für Java-Code

Codestil

<rule type="absence" points="0">
  <query>from x : V{MethodDeclaration}
         with
            x.name=capitalizeFirst(x.name) and
            x.constructor="false"
         report 0 end
  </query>
  <feedback prefix="Hinweis (ohne Punktabzug)">Du verwendest Methodennamen, die mit einem Großbuchstaben beginnen. Das ist möglich, aber es entspricht nicht dem üblichen Programmierstil für Java.</feedback>
</rule>

Diese Regel sucht nach groß geschriebenen Methodennamen.

<rule type="absence" points="0">
  <query>from x : V{TypeDeclaration}
         with
            not (x.name=capitalizeFirst(x.name))
         report 0 end
  </query>
  <feedback prefix="Hinweis (ohne Punktabzug)">Du verwendest Klassennamen, die nicht mit einem Großbuchstaben beginnen. Das ist möglich, aber es entspricht nicht dem üblichen Programmierstil für Java.</feedback>
</rule>

Diese Regel sucht nach klein geschriebenen Klassennamen.

<rule type="absence" points="0">
  <query>from x : V{VariableDeclarationFragment}
         with
            x.name=capitalizeFirst(x.name) and
            isEmpty(from m : V{Modifier} with x &lt;--&amp;{FieldDeclaration} --&gt; m and m.name="final" report m end)
         report 0 end
  </query>
<feedback prefix="Hinweis (ohne Punktabzug)">Du verwendest Variablennamen, die mit einem Großbuchstaben beginnen. Das ist möglich, aber es entspricht nicht dem üblichen Programmierstil für Java.</feedback>
</rule>

Diese Regel sucht nach groß geschriebenen Variablennamen, wobei als "final" deklarierte Klassenvariablen ausgelassen werden.

Einfache Inhalte

<rule type="presence" points="2">
  <query>from m : V{MethodDeclaration}, s : V{StringLiteral}
         with
            m.name="m" and
            m -->{Child}* s and
            s.content = "\"Zeichenkette\""
         report 0 end
  </query>
  <feedback>Deine Lösung verwendet nicht den String "Zeichenkette".</feedback>
</rule>

Diese Regel sucht in der Methode m nach einem String-Literal mit einem vorgegebenen Inhalt.

<rule type="absence" points="2">
  <query>from m : V{MethodDeclaration}, s : V{StringLiteral}
         with
            m.name="m" and
            m -->{Child}* s and
            stringLength(s.content) > 4
         report s.line as "line" end
  </query>
  <feedback>Du verwendest in Zeile {line} ein festes String-Literal. Ist deine Lösung allgemeingültig?</feedback>
</rule>

Diese Regel sucht in der Methode m nach einem String-Literal der Länge 4 oder länger (inklusive Anführungszeichen) und meldet es mit Angabe der Zeilennummer als Fehler.

<rule type="absence" points="0">
  <query>from p : V{PackageDeclaration}
         report 0 end
  </query>
  <feedback prefix="Paketdefinition">Deine Lösung beinhaltet eine package-Angabe. Bitte entferne diese.</feedback>
</rule>

Diese Regel sucht nach Paketdefinitionen und meldet diese als Fehler.

<rule type="absence" points="1">
   <query>from u : V{CompilationUnit}, x : V{MethodInvocation}, y : V{SimpleName}
          with
             u -->* x -->{ElementExpression} y and
             x.name="exit" and
             y.name="System"
          report u.name as "name", x.line as "line" end
  </query>
  <feedback>Der Aufruf von "System.exit()" in der Datei {name} in Zeile {line} ist nicht gestattet.</feedback>
</rule>

Diese Regel sucht nach Aufrufen von System.exit() und melde diese unter Angabe von Klasse und Zeilennummer als Fehler.

Kontrollstrukturen

<rule type="absence" points="4">
  <query>from m : V{MethodDeclaration}
         with
            m.name="m" and
            isEmpty(m -->{Child}*&{WhileStatement}) and
            isEmpty(m -->{Child}*&{DoStatement}) and
            isEmpty(m -->{Child}*&{ForStatement}) and
            isEmpty(m -->{Child}*&{EnhancedForStatement})
         report 0 end
  </query>
  <feedback>In der Methode "m()" wird kein Schleifenkonstrukt verwendet.</feedback>
</rule>

Diese Regel überprüft, ob Methode m ein beliebiges Schleifenkonstrukt enthält.

<rule type="absence" points="2">
  <query>from u : V{CompilationUnit}, x : V{IfStatement}
         with
            ( not isEmpty(u -->* x -->{IfStatementThenStatement}&{EmptyStatement}) or
              (not isEmpty(u -->* x -->{IfStatementThenStatement}&{Block}) and isEmpty(u -->* x -->{IfStatementThenStatement}&{Block} -->{Child}))
            ) and
            ( not isEmpty(u -->* x -->{IfStatementElseStatement}&{EmptyStatement}) or
              (not isEmpty(u -->* x -->{IfStatementElseStatement}&{Block}) and isEmpty(u -->* x -->{IfStatementElseStatement}&{Block} -->{Child}))
            )
         report u.name as "name", x.line as "line" end
  </query>
  <feedback>In der Datei {name} enthält das if-Statement in Zeile {line} in beiden Zweigen keinen Code und ist dadurch sinnlos.</feedback>
</rule>

Diese Regel sucht nach einer if-Anweisung, die nur leere Zweige enthält und meldet eine solche Anweisung als Fehler.

<rule type="absence" points="2">
  <query>from u : V{CompilationUnit}, x : V{IfStatement}
         with
            not isEmpty(u -->* x -->{IfStatementThenStatement}&{EmptyStatement}) and
            isEmpty(x -->{IfStatementElseStatement}&{Statement})
         report u.name as "name", x.line as "line" end
  </query>
  <feedback>In der Datei {name} endet das if-Statement in Zeile {line} hinter der Bedingung sofort mit einem Semikolon. Die Bedingung ist dadurch wirkungslos und die folgende Anweisung wird immer ausgeführt.</feedback>
</rule>

Diese Regel sucht nach einer if-Anweisung, die keine Zweige enthält und meldet eine solche Anweisung als Fehler.

<rule type="absence" points="2">
  <query>from u : V{CompilationUnit}, x : V{WhileStatement}
         with
            not isEmpty(u -->* x -->{WhileStatementBody}&{EmptyStatement}) or
            (not isEmpty(u -->* x -->{WhileStatementBody}&{Block}) and
            isEmpty(u -->* x -->{WhileStatementBody}&{Block} -->{Child}))
         report u.name as "name", x.line as "line" end
  </query>
  <feedback>In der Datei {name} besteht die while-Schleife in Zeile {line} nur aus einer Abbruchbedingung und ist dadurch sinnlos.</feedback>
</rule>

Diese Regel sucht nach einer while-Schleife, die nur aus einer Abbruchbedingung besteht und meldet eine solche Schleife als Fehler.

<rule type="presence" points="1">
   <query>from m : V{MethodDeclaration}, n : V{MethodDeclaration}
          with
             m (-->{Child}*&{MethodInvocation} -->{Access}&{MethodDeclaration})* n and
             n -->{Child}*&{MethodInvocation} -->{Access} m and
             m.name="m"
          report 0 end
  </query>
  <feedback prefix="Rekursionscheck"> Die Methode "m()" enthält nicht die geforderte Rekursion.</feedback>
</rule>

Diese Regel überprüft, ob Methode m rekursiv arbeitet. Dabei ist es egal, ob sich die Methode direkt selber aufruft, oder über einen oder mehrere Zwischenschritte aufgerufen wird.

<rule type="presence" points="5">
   <query>from m : V{MethodDeclaration}
          with
             m (-->{Child}*&{MethodInvocation} -->{Access}&{MethodDeclaration}) m and
             m.name="m"
          report 0 end
  </query>
  <feedback prefix="Rekursionscheck">Die Methode "m()" enthält nicht die geforderte Rekursion.</feedback>
</rule>

Diese Regel überprüft, ob Methode m rekursiv arbeitet und sich insbesondere ohne Zwischenschritte über andere Methoden selber wieder aufruft.

Methoden

<rule type="presence" points="4">
  <query>from t : V{TypeDeclaration}, m : V{MethodDeclaration}
         with
            t.name="A" and
            t -->{TypeDeclarationBodyDeclarations2} m and
            hasSignature(m, "public static String method(int)")
         report 0 end
  </query>
  <feedback prefix="Signaturcheck">Die Methode "public static String method(int param)" in der Klasse "A" fehlt. Hast du die vorgegebene Methodensignatur veraendert?</feedback>
</rule>

Diese Regel überprüft, ob Klasse A eine Methode mit einer bestimmten Signatur enthält, wobei der Name des Methodenparameters unerheblich ist.

<rule type="presence" points="4">
  <query>from t : V{TypeDeclaration}, m : V{MethodDeclaration}
         with
            t.name="A" and
            t -->{TypeDeclarationBodyDeclarations2} m and
            hasSignature(m, "int method()") and
            isEmpty(m -->{Child}&{Modifier})
         report 0 end
  </query>
  <query>from t : V{TypeDeclaration}, m : V{MethodDeclaration}, mo : V{Modifier}
         with
            t.name="A" and
            t -->{TypeDeclarationBodyDeclarations2} m and
            hasSignature(m, "int method()") and
            m --> mo and not (mo.name="private")
        report 0 end
  </query>
  <feedback prefix="Signaturcheck">Die Methode "int method()" in der Klasse "A" fehlt oder ist mit dem Modifier "private" versehen. Hast du die vorgegebene Methodensignatur veraendert?</feedback>
</rule>

Diese Regel überprüft, ob Klasse A eine Methode mit einer bestimmten Signatur enthält, die nicht mit dem Modifier private versehen ist.

<rule type="presence" points="1">
   <query>from t : V{TypeDeclaration}, m : V{MethodDeclaration}, pt : V{ParameterizedType}, ptt : V{SimpleType}, pta : V{SimpleType}
          with
             t.name="A" and
             t -->{TypeDeclarationBodyDeclarations2} m and
             m.name="m" and
             m -->{MethodDeclarationReturnType} pt and
             pt -->{ParameterizedTypeType} ptt and
             ptt.name="B" and
             pt -->{ParameterizedTypeTypeArguments1} pta and
             pta.name="C"
          report 0 end
  </query>
  <feedback prefix="Signatur">Der Methode "public B<C> m()" in der Klasse "A" fehlt. Hast du die vorgegebene Methodensignatur veraendert?</feedback>
</rule>

Diese Regel überprüft, ob Klasse A eine Methode m mit parametrisierten Rückgabetyp B<C> enthält.

Vererbungshierarchie

<rule type="presence" points="5">
  <query>from t : V{TypeDeclaration}, st : V{SimpleType}
         with
            t.name="A" and
            st.name="B" and
            t -->{TypeDeclarationSuperclassType2} st
         report 0 end
  </query>
  <feedback prefix="Typhierarchie">A ist nicht als Unterklasse von B modelliert.</feedback>
</rule>

Diese Regel überprüft, ob Klasse A direkte Unterklasse von Klasse B ist.

<rule type="presence" points="1">
   <query>from t : V{TypeDeclaration}, st : V{SimpleType}
          with
             t.name="A" and
             t -->{TypeDeclarationSuperInterfaceTypes2} st and
             st.name="B"
          report 0 end
  </query>
  <feedback prefix="Typhierarchie">A implementiert nicht das Interface B.</feedback>
</rule>

Diese Regel überprüft, ob Klasse A das Interface B implementiert.

<rule type="presence" points="1">
  <query>from t : V{TypeDeclaration}, pt : V{ParameterizedType}, ptt : V{SimpleType}, pta : V{SimpleType}
         with
            t.name="A" and
            t -->{TypeDeclarationSuperInterfaceTypes1} pt and
            pt -->{ParameterizedTypeType} ptt and
            ptt.name="B" and
            pt -->{ParameterizedTypeTypeArguments1} pta and
            pta.name="C"
         report 0 end
  </query>
  <feedback prefix="Typhierarchie">A implementiert nicht das Interface B<C>.</feedback>
</rule>

Diese Regel überprüft, ob Klasse A das Interface B<C> implementiert.

<rule type="presence" points="3">
  <query>from u : V{TypeDeclaration}, s : V{SimpleType}
         with
            ((u -->{TypeDeclarationSuperclassType2} s and s.name="Thread") or
            (u -->{TypeDeclarationSuperInterfaceTypes2} s and s.name="Runnable")) and
            u.name="A"
         report 0 end
  </query>
  <feedback>In der Klasse "A" sollte entweder das Interface "Runnable" implementieren oder von "Thread" erben.</feedback>
</rule>

Diese Regel überprüft, ob Klasse A das Interface Runnable implementiert oder von Thread erbt.

Aufrufbeziehungen

<rule type="presence" points="5">
  <query>from u : V{TypeDeclaration}, x : V{MethodInvocation}, y : V{SimpleName}
         with
            u -->* x -->{ElementExpression} y and
            u.name="A" and
            x.name="m" and
            y.name="B"
         report 0 end
  </query>
  <feedback>In der Klasse "A" sollte "B.m()" aufgerufen werden.</feedback>
</rule>

Diese Regel überprüft, ob Klasse A eine Methode B.m aufruft.

<rule type="presence" points="5">
  <query>from u : V{TypeDeclaration}, x : V{MethodInvocation}, y : V{SimpleName}, z : V{VariableDeclarationStatement}, f : V{VariableDeclarationFragment}, t : V{SimpleType}
         with
            u -->* x -->{ElementExpression} y and
            u -->* z -->{VariableDeclarationStatementType} t and
            u -->* z -->{VariableDeclarationStatementFragments} f and
            u.name="A" and
            x.name="m" and
            y.name=f.name and
            t.name="B"
         report 0 end
  </query>
  <feedback>In der Klasse "A" sollte "m()" auf einem Objekt vom Typ "B" aufgerufen werden.</feedback>
</rule>

Diese Regel überprüft, ob Klasse A Methode m auf einem Objekt vom Typ B aufruft.

<rule type="presence" points="4">
  <query>from u : V{TypeDeclaration}, m : V{MethodDeclaration}, x : V{ClassInstanceCreation}, t : V{SimpleType}
         with
            u -->{Child}* m -->* x -->{ClassInstanceCreationType} t and
            u.name="A" and
            m.name="m" and
            t.name="B"
         report 0 end
  </query>
  <feedback>In der Klasse "A" muss in Methode m() mindestens eine Instanz von "B" erzeugt werden.</feedback>
</rule>

Diese Regel überprüft, ob Klasse A in Methode m eine Instanz von Klasse B erstellt.