GReQL Regeln: Unterschied zwischen den Versionen

Aus JACK Wiki
Zur Navigation springen Zur Suche springen
Keine Bearbeitungszusammenfassung
Keine Bearbeitungszusammenfassung
Zeile 1: Zeile 1:
== Beispiele für statische Prüfregeln für Java-Code ==
== Beispiele für statische Prüfregeln für Java-Code ==
=== Codestil ===
=== Codestil ===
<syntaxhighlight lang="xml" line='line'>
  <rule type="absence" points="0">
  <rule type="absence" points="0">
   <query>from x : V{MethodDeclaration}
   <query>from x : V{MethodDeclaration}
Zeile 10: Zeile 11:
   <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>
   <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>
  </rule>
</syntaxhighlight>
Diese Regel sucht nach groß geschriebenen Methodennamen.
Diese Regel sucht nach groß geschriebenen Methodennamen.


<syntaxhighlight lang="xml" line='line'>
  <rule type="absence" points="0">
  <rule type="absence" points="0">
   <query>from x : V{TypeDeclaration}
   <query>from x : V{TypeDeclaration}
Zeile 20: Zeile 23:
   <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>
   <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>
  </rule>
</syntaxhighlight>
Diese Regel sucht nach klein geschriebenen Klassennamen.
Diese Regel sucht nach klein geschriebenen Klassennamen.


<syntaxhighlight lang="xml" line='line'>
  <rule type="absence" points="0">
  <rule type="absence" points="0">
   <query>from x : V{VariableDeclarationFragment}
   <query>from x : V{VariableDeclarationFragment}
Zeile 31: Zeile 36:
  <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>
  <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>
  </rule>
</syntaxhighlight>
Diese Regel sucht nach groß geschriebenen Variablennamen, wobei als "final" deklarierte Klassenvariablen ausgelassen werden.
Diese Regel sucht nach groß geschriebenen Variablennamen, wobei als "final" deklarierte Klassenvariablen ausgelassen werden.


=== Einfache Inhalte ===
=== Einfache Inhalte ===
<syntaxhighlight lang="xml" line='line'>
  <rule type="presence" points="2">
  <rule type="presence" points="2">
   <query>from m : V{MethodDeclaration}, s : V{StringLiteral}
   <query>from m : V{MethodDeclaration}, s : V{StringLiteral}
Zeile 44: Zeile 51:
   <feedback>Deine Lösung verwendet nicht den String "Zeichenkette".</feedback>
   <feedback>Deine Lösung verwendet nicht den String "Zeichenkette".</feedback>
  </rule>
  </rule>
</syntaxhighlight>
Diese Regel sucht in der Methode <code>m</code> nach einem String-Literal mit einem vorgegebenen Inhalt.
Diese Regel sucht in der Methode <code>m</code> nach einem String-Literal mit einem vorgegebenen Inhalt.


<syntaxhighlight lang="xml" line='line'>
  <rule type="absence" points="2">
  <rule type="absence" points="2">
   <query>from m : V{MethodDeclaration}, s : V{StringLiteral}
   <query>from m : V{MethodDeclaration}, s : V{StringLiteral}
Zeile 56: Zeile 65:
   <feedback>Du verwendest in Zeile {line} ein festes String-Literal. Ist deine Lösung allgemeingültig?</feedback>
   <feedback>Du verwendest in Zeile {line} ein festes String-Literal. Ist deine Lösung allgemeingültig?</feedback>
  </rule>
  </rule>
</syntaxhighlight>
Diese Regel sucht in der Methode <code>m</code> nach einem String-Literal der Länge 4 oder länger (inklusive Anführungszeichen) und meldet es mit Angabe der Zeilennummer als Fehler.
Diese Regel sucht in der Methode <code>m</code> nach einem String-Literal der Länge 4 oder länger (inklusive Anführungszeichen) und meldet es mit Angabe der Zeilennummer als Fehler.


<syntaxhighlight lang="xml" line='line'>
  <rule type="absence" points="0">
  <rule type="absence" points="0">
   <query>from p : V{PackageDeclaration}
   <query>from p : V{PackageDeclaration}
Zeile 64: Zeile 75:
   <feedback prefix="Paketdefinition">Deine Lösung beinhaltet eine package-Angabe. Bitte entferne diese.</feedback>
   <feedback prefix="Paketdefinition">Deine Lösung beinhaltet eine package-Angabe. Bitte entferne diese.</feedback>
  </rule>
  </rule>
</syntaxhighlight>
Diese Regel sucht nach Paketdefinitionen und meldet diese als Fehler.
Diese Regel sucht nach Paketdefinitionen und meldet diese als Fehler.


<syntaxhighlight lang="xml" line='line'>
  <rule type="absence" points="1">
  <rule type="absence" points="1">
     <query>from u : V{CompilationUnit}, x : V{MethodInvocation}, y : V{SimpleName}
     <query>from u : V{CompilationUnit}, x : V{MethodInvocation}, y : V{SimpleName}
Zeile 76: Zeile 89:
   <feedback>Der Aufruf von "System.exit()" in der Datei {name} in Zeile {line} ist nicht gestattet.</feedback>
   <feedback>Der Aufruf von "System.exit()" in der Datei {name} in Zeile {line} ist nicht gestattet.</feedback>
  </rule>
  </rule>
</syntaxhighlight>
Diese Regel sucht nach Aufrufen von System.exit() und melde diese unter Angabe von Klasse und Zeilennummer als Fehler.
Diese Regel sucht nach Aufrufen von System.exit() und melde diese unter Angabe von Klasse und Zeilennummer als Fehler.


=== Kontrollstrukturen ===
=== Kontrollstrukturen ===
<syntaxhighlight lang="xml" line='line'>
  <rule type="absence" points="4">
  <rule type="absence" points="4">
   <query>from m : V{MethodDeclaration}
   <query>from m : V{MethodDeclaration}
Zeile 91: Zeile 106:
   <feedback>In der Methode "m()" wird kein Schleifenkonstrukt verwendet.</feedback>
   <feedback>In der Methode "m()" wird kein Schleifenkonstrukt verwendet.</feedback>
  </rule>
  </rule>
</syntaxhighlight>
Diese Regel überprüft, ob Methode <code>m</code> ein beliebiges Schleifenkonstrukt enthält.
Diese Regel überprüft, ob Methode <code>m</code> ein beliebiges Schleifenkonstrukt enthält.


<syntaxhighlight lang="xml" line='line'>
  <rule type="absence" points="2">
  <rule type="absence" points="2">
   <query>from u : V{CompilationUnit}, x : V{IfStatement}
   <query>from u : V{CompilationUnit}, x : V{IfStatement}
Zeile 106: Zeile 123:
   <feedback>In der Datei {name} enthält das if-Statement in Zeile {line} in beiden Zweigen keinen Code und ist dadurch sinnlos.</feedback>
   <feedback>In der Datei {name} enthält das if-Statement in Zeile {line} in beiden Zweigen keinen Code und ist dadurch sinnlos.</feedback>
  </rule>
  </rule>
</syntaxhighlight>
Diese Regel sucht nach einer if-Anweisung, die nur leere Zweige enthält und meldet eine solche Anweisung als Fehler.
Diese Regel sucht nach einer if-Anweisung, die nur leere Zweige enthält und meldet eine solche Anweisung als Fehler.


<syntaxhighlight lang="xml" line='line'>
  <rule type="absence" points="2">
  <rule type="absence" points="2">
   <query>from u : V{CompilationUnit}, x : V{IfStatement}
   <query>from u : V{CompilationUnit}, x : V{IfStatement}
Zeile 117: Zeile 136:
   <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>
   <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>
  </rule>
</syntaxhighlight>
Diese Regel sucht nach einer if-Anweisung, die keine Zweige enthält und meldet eine solche Anweisung als Fehler.
Diese Regel sucht nach einer if-Anweisung, die keine Zweige enthält und meldet eine solche Anweisung als Fehler.


<syntaxhighlight lang="xml" line='line'>
  <rule type="absence" points="2">
  <rule type="absence" points="2">
   <query>from u : V{CompilationUnit}, x : V{WhileStatement}
   <query>from u : V{CompilationUnit}, x : V{WhileStatement}
Zeile 129: Zeile 150:
   <feedback>In der Datei {name} besteht die while-Schleife in Zeile {line} nur aus einer Abbruchbedingung und ist dadurch sinnlos.</feedback>
   <feedback>In der Datei {name} besteht die while-Schleife in Zeile {line} nur aus einer Abbruchbedingung und ist dadurch sinnlos.</feedback>
  </rule>
  </rule>
</syntaxhighlight>
Diese Regel sucht nach einer while-Schleife, die nur aus einer Abbruchbedingung besteht und meldet eine solche Schleife als Fehler.
Diese Regel sucht nach einer while-Schleife, die nur aus einer Abbruchbedingung besteht und meldet eine solche Schleife als Fehler.


<syntaxhighlight lang="xml" line='line'>
  <rule type="presence" points="1">
  <rule type="presence" points="1">
     <query>from m : V{MethodDeclaration}, n : V{MethodDeclaration}
     <query>from m : V{MethodDeclaration}, n : V{MethodDeclaration}
Zeile 141: Zeile 164:
   <feedback prefix="Rekursionscheck"> Die Methode "m()" enthält nicht die geforderte Rekursion.</feedback>
   <feedback prefix="Rekursionscheck"> Die Methode "m()" enthält nicht die geforderte Rekursion.</feedback>
  </rule>
  </rule>
</syntaxhighlight>
Diese Regel überprüft, ob Methode <code>m</code> rekursiv arbeitet. Dabei ist es egal, ob sich die Methode direkt selber aufruft, oder über einen oder mehrere Zwischenschritte aufgerufen wird.
Diese Regel überprüft, ob Methode <code>m</code> rekursiv arbeitet. Dabei ist es egal, ob sich die Methode direkt selber aufruft, oder über einen oder mehrere Zwischenschritte aufgerufen wird.


<syntaxhighlight lang="xml" line='line'>
  <rule type="presence" points="5">
  <rule type="presence" points="5">
     <query>from m : V{MethodDeclaration}
     <query>from m : V{MethodDeclaration}
Zeile 152: Zeile 177:
   <feedback prefix="Rekursionscheck">Die Methode "m()" enthält nicht die geforderte Rekursion.</feedback>
   <feedback prefix="Rekursionscheck">Die Methode "m()" enthält nicht die geforderte Rekursion.</feedback>
  </rule>
  </rule>
</syntaxhighlight>
Diese Regel überprüft, ob Methode <code>m</code> rekursiv arbeitet und sich insbesondere ohne Zwischenschritte über andere Methoden selber wieder aufruft.
Diese Regel überprüft, ob Methode <code>m</code> rekursiv arbeitet und sich insbesondere ohne Zwischenschritte über andere Methoden selber wieder aufruft.


=== Methoden ===
=== Methoden ===
<syntaxhighlight lang="xml" line='line'>
  <rule type="presence" points="4">
  <rule type="presence" points="4">
   <query>from t : V{TypeDeclaration}, m : V{MethodDeclaration}
   <query>from t : V{TypeDeclaration}, m : V{MethodDeclaration}
Zeile 165: Zeile 192:
   <feedback prefix="Signaturcheck">Die Methode "public static String method(int param)" in der Klasse "A" fehlt. Hast du die vorgegebene Methodensignatur veraendert?</feedback>
   <feedback prefix="Signaturcheck">Die Methode "public static String method(int param)" in der Klasse "A" fehlt. Hast du die vorgegebene Methodensignatur veraendert?</feedback>
  </rule>
  </rule>
</syntaxhighlight>
Diese Regel überprüft, ob Klasse A eine Methode mit einer bestimmten Signatur enthält, wobei der Name des Methodenparameters unerheblich ist.
Diese Regel überprüft, ob Klasse A eine Methode mit einer bestimmten Signatur enthält, wobei der Name des Methodenparameters unerheblich ist.


<syntaxhighlight lang="xml" line='line'>
  <rule type="presence" points="4">
  <rule type="presence" points="4">
   <query>from t : V{TypeDeclaration}, m : V{MethodDeclaration}
   <query>from t : V{TypeDeclaration}, m : V{MethodDeclaration}
Zeile 186: Zeile 215:
   <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>
   <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>
  </rule>
</syntaxhighlight>
Diese Regel überprüft, ob Klasse A eine Methode mit einer bestimmten Signatur enthält, die nicht mit dem Modifier private versehen ist.
Diese Regel überprüft, ob Klasse A eine Methode mit einer bestimmten Signatur enthält, die nicht mit dem Modifier private versehen ist.


<syntaxhighlight lang="xml" line='line'>
  <rule type="presence" points="1">
  <rule type="presence" points="1">
     <query>from t : V{TypeDeclaration}, m : V{MethodDeclaration}, pt : V{ParameterizedType}, ptt : V{SimpleType}, pta : V{SimpleType}
     <query>from t : V{TypeDeclaration}, m : V{MethodDeclaration}, pt : V{ParameterizedType}, ptt : V{SimpleType}, pta : V{SimpleType}
Zeile 203: Zeile 234:
   <feedback prefix="Signatur">Der Methode "public B&lt;C&gt; m()" in der Klasse "A" fehlt. Hast du die vorgegebene Methodensignatur veraendert?</feedback>
   <feedback prefix="Signatur">Der Methode "public B&lt;C&gt; m()" in der Klasse "A" fehlt. Hast du die vorgegebene Methodensignatur veraendert?</feedback>
  </rule>
  </rule>
</syntaxhighlight>
Diese Regel überprüft, ob Klasse A eine Methode m mit parametrisierten Rückgabetyp B<C> enthält.
Diese Regel überprüft, ob Klasse A eine Methode m mit parametrisierten Rückgabetyp B<C> enthält.


=== Vererbungshierarchie ===
=== Vererbungshierarchie ===
<syntaxhighlight lang="xml" line='line'>
  <rule type="presence" points="5">
  <rule type="presence" points="5">
   <query>from t : V{TypeDeclaration}, st : V{SimpleType}
   <query>from t : V{TypeDeclaration}, st : V{SimpleType}
Zeile 216: Zeile 249:
   <feedback prefix="Typhierarchie">A ist nicht als Unterklasse von B modelliert.</feedback>
   <feedback prefix="Typhierarchie">A ist nicht als Unterklasse von B modelliert.</feedback>
  </rule>
  </rule>
</syntaxhighlight>
Diese Regel überprüft, ob Klasse A direkte Unterklasse von Klasse B ist.
Diese Regel überprüft, ob Klasse A direkte Unterklasse von Klasse B ist.


<syntaxhighlight lang="xml" line='line'>
  <rule type="presence" points="1">
  <rule type="presence" points="1">
     <query>from t : V{TypeDeclaration}, st : V{SimpleType}
     <query>from t : V{TypeDeclaration}, st : V{SimpleType}
Zeile 228: Zeile 263:
   <feedback prefix="Typhierarchie">A implementiert nicht das Interface B.</feedback>
   <feedback prefix="Typhierarchie">A implementiert nicht das Interface B.</feedback>
  </rule>
  </rule>
</syntaxhighlight>
Diese Regel überprüft, ob Klasse A das Interface B implementiert.
Diese Regel überprüft, ob Klasse A das Interface B implementiert.


<syntaxhighlight lang="xml" line='line'>
  <rule type="presence" points="1">
  <rule type="presence" points="1">
   <query>from t : V{TypeDeclaration}, pt : V{ParameterizedType}, ptt : V{SimpleType}, pta : V{SimpleType}
   <query>from t : V{TypeDeclaration}, pt : V{ParameterizedType}, ptt : V{SimpleType}, pta : V{SimpleType}
Zeile 243: Zeile 280:
   <feedback prefix="Typhierarchie">A implementiert nicht das Interface B&lt;C&gt;.</feedback>
   <feedback prefix="Typhierarchie">A implementiert nicht das Interface B&lt;C&gt;.</feedback>
  </rule>
  </rule>
</syntaxhighlight>
Diese Regel überprüft, ob Klasse A das Interface B<C> implementiert.
Diese Regel überprüft, ob Klasse A das Interface B<C> implementiert.


<syntaxhighlight lang="xml" line='line'>
  <rule type="presence" points="3">
  <rule type="presence" points="3">
   <query>from u : V{TypeDeclaration}, s : V{SimpleType}
   <query>from u : V{TypeDeclaration}, s : V{SimpleType}
Zeile 255: Zeile 294:
   <feedback>In der Klasse "A" sollte entweder das Interface "Runnable" implementieren oder von "Thread" erben.</feedback>
   <feedback>In der Klasse "A" sollte entweder das Interface "Runnable" implementieren oder von "Thread" erben.</feedback>
  </rule>
  </rule>
</syntaxhighlight>
Diese Regel überprüft, ob Klasse A das Interface Runnable implementiert oder von Thread erbt.
Diese Regel überprüft, ob Klasse A das Interface Runnable implementiert oder von Thread erbt.


=== Aufrufbeziehungen ===
=== Aufrufbeziehungen ===
<syntaxhighlight lang="xml" line='line'>
  <rule type="presence" points="5">
  <rule type="presence" points="5">
   <query>from u : V{TypeDeclaration}, x : V{MethodInvocation}, y : V{SimpleName}
   <query>from u : V{TypeDeclaration}, x : V{MethodInvocation}, y : V{SimpleName}
Zeile 269: Zeile 310:
   <feedback>In der Klasse "A" sollte "B.m()" aufgerufen werden.</feedback>
   <feedback>In der Klasse "A" sollte "B.m()" aufgerufen werden.</feedback>
  </rule>
  </rule>
</syntaxhighlight>
Diese Regel überprüft, ob Klasse A eine Methode B.m aufruft.
Diese Regel überprüft, ob Klasse A eine Methode B.m aufruft.


<syntaxhighlight lang="xml" line='line'>
  <rule type="presence" points="5">
  <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}
   <query>from u : V{TypeDeclaration}, x : V{MethodInvocation}, y : V{SimpleName}, z : V{VariableDeclarationStatement}, f : V{VariableDeclarationFragment}, t : V{SimpleType}
Zeile 285: Zeile 328:
   <feedback>In der Klasse "A" sollte "m()" auf einem Objekt vom Typ "B" aufgerufen werden.</feedback>
   <feedback>In der Klasse "A" sollte "m()" auf einem Objekt vom Typ "B" aufgerufen werden.</feedback>
  </rule>
  </rule>
</syntaxhighlight>
Diese Regel überprüft, ob Klasse A Methode m auf einem Objekt vom Typ B aufruft.
Diese Regel überprüft, ob Klasse A Methode m auf einem Objekt vom Typ B aufruft.


<syntaxhighlight lang="xml" line='line'>
  <rule type="presence" points="4">
  <rule type="presence" points="4">
   <query>from u : V{TypeDeclaration}, m : V{MethodDeclaration}, x : V{ClassInstanceCreation}, t : V{SimpleType}
   <query>from u : V{TypeDeclaration}, m : V{MethodDeclaration}, x : V{ClassInstanceCreation}, t : V{SimpleType}
Zeile 298: Zeile 343:
   <feedback>In der Klasse "A" muss in Methode m() mindestens eine Instanz von "B" erzeugt werden.</feedback>
   <feedback>In der Klasse "A" muss in Methode m() mindestens eine Instanz von "B" erzeugt werden.</feedback>
  </rule>
  </rule>
</syntaxhighlight>
Diese Regel überprüft, ob Klasse A in Methode m eine Instanz von Klasse B erstellt.
Diese Regel überprüft, ob Klasse A in Methode m eine Instanz von Klasse B erstellt.
== Beispiele für statische Prüfregeln für UML-Modelle im XMI2-Format ==
=== Klassendiagramme ===
<syntaxhighlight lang="xml" line='line'>
  <rule type="presence" points="11">
    <query>from x,y : V{Class}
          with
              x --> V{Property} --> V{Association} <-- V{Property} <-- y and
              isDefined(x.name) and x.name="A" and
              isDefined(y.name) and y.name="B"
          report 1 end
    </query>
    <feedback>Das Diagramm enthält keine Beziehung zwischen einem "A" und einem "B" oder keine Klassen mit diesen Namen.</feedback>
  </rule>
</syntaxhighlight>
Diese Regel überprüft, ob das Modell zwei Klassen "A" und "B" enthält, die über eine Assoziation verbunden sind.
<syntaxhighlight lang="xml" line='line'>
  <rule type="absence" points="0">
    <query>from x,y : V{Class}
          with
              x --> V{Property} --> V{Association} <-- V{Property} <-- y and
              isDefined(x.name) and x.name="A" and
              isDefined(y.name) and y.name="B"
          report 1 end
    </query>
    <feedback prefix="Hinweis">Im Diagramm sind die "B" eines "A" als eigene Klasse abgebildet. Das kannst du durch eine bessere Modellierung vermeiden.</feedback>
  </rule>
</syntaxhighlight>
Diese Regel überprüft ebenfalls, ob das Modell zwei Klassen "A" und "B" enthält, die über eine Assoziation verbunden sind, definiert dies aber als unerwünschte Situation mit entsprechendem Feedback.
<syntaxhighlight lang="xml" line='line'>
  <rule type="presence" points="11">
    <query>from x,y : V{Class}, z: V{Property}
          with
              x --> z and
              z --> V{Association} <-- V{Property} <-- y and
              isDefined(x.name) and x.name="A" and
              isDefined(y.name) and y.name="B" and
              isDefined(z.lower) and z.lower="1" and (not isDefined(z.upper) or z.upper="1")
          report 1 end
    </query>
    <feedback>Das Diagramm enthält keine Beziehung zwischen einem "A" und einem "B" mit der Kardinalität 1 oder keine Klassen mit diesen Namen.</feedback>
  </rule>
</syntaxhighlight>
Diese Regel überprüft, ob das Modell zwei Klassen "A" und "B" enthält, die über eine Assoziation mit Kardinalität 1 (jedes A kennt genau ein B) verbunden sind.
<syntaxhighlight lang="xml" line='line'>
  <rule type="presence" points="5">
    <query>from a,b : V{Class}, p: V{Property}
          with
              isEmpty(a -->&{Property} -->&{Association}) and
              b --> p and
              isDefined(p.aggregation) and p.aggregation="composite"
          report 1 end
    </query>
    <feedback>Es sollte im Diagramm zwei Klassen geben, bei denen die eine keine weiteren Bestandteile hat, während die andere weitere Bestandteile gemäß der Komposition hat.</feedback>
  </rule>
</syntaxhighlight>
Diese Regel überprüft, ob es im Modell eine Klasse ohne ausgehende Assoziationen gibt und eine weitere, die mindestens eine ausgehende Komposition hat.
<syntaxhighlight lang="xml" line='line'>
  <rule type="presence" points="5">
    <query>from x : V{Class}, y : V{Property}, z : V{PrimitiveType}
          with
              isDefined(x.name) and x.name="A" and
              x --> y and
              isDefined(y.name) and y.name="b" and
              y --> z and
              isDefined(z.name) and z.name="String"
          report 1 end
    </query>
    <feedback>Ein "A" soll ein Attribut für die Eigenschaft "b" bereitstellen.</feedback>
  </rule>
</syntaxhighlight>
Diese Regel überprüft, ob es im Modell eine Klasse "A" mit dem Attribut "b" vom Typ "String" gibt.
<syntaxhighlight lang="xml" line='line'>
  <rule type="presence" points="5">
    <query>from x : V{Class}, y : V{Operation}, z: V{Parameter}
          with
              isDefined(x.name) and x.name="A" and
              x --> y and
              isDefined(y.name) and stringLevenshteinDistance(y.name, "ausführen")<3 and
              y --> z
          report 1 end
    </query>
    <feedback>Ein "A" soll eine Methode bereitstellen, mit der sie etwas ausführen kann.</feedback>
  </rule>
</syntaxhighlight>
Diese Regel prüft, ob es im Modell eine Klasse "A" mit einer Operation gibt, deren Name "ausführen" oder ähnlich lautet.
<syntaxhighlight lang="xml" line='line'>
  <rule type="absence" points="4">
    <query>let c := count(from y : V{Operation} with isDefined(y.name) report y end) in
              from x : set(1)
              with
                c<>7
              report c as "count" end
    </query>
    <feedback>Das Diagramm sollte genau 7 Methoden enthalten, enthält aber {count}.</feedback>
  </rule>
</syntaxhighlight>
Diese Regel überprüft, ob das Modell genau 7 Methoden enthält und gibt im Falle einer anderen Anzahl diese im Feedback mit aus.
<syntaxhighlight lang="xml" line='line'>
  <rule type="presence" points="5">
    <query>from x : V{Class}
          with
              isDefined(x.name) and x.name=A" and
              x.isAbstract and
              not isEmpty(x <--&{Generalization})
          report 1 end
    </query>
    <feedback>Das Diagramm sollte eine abstrakte Klasse "A" enthalten, von der mindestens eine Klasse erbt.</feedback>
  </rule>
</syntaxhighlight>
Diese Regel überprüft, ob das Modell eine abstrakte Klasse "A" enthält, auf die in mindestens einer Generalisierung verwiesen wird.
<syntaxhighlight lang="xml" line='line'>
  <rule type="presence" points="5">
    <query>from a,b,c,d : V{Class}
          with
              isDefined(a.name) and a.name="A" and
              isDefined(b.name) and b.name="B" and
              isDefined(c.name) and c.name="C" and
              isDefined(d.name) and d.name="D" and
              a --> V{Generalization} --> d and
              b --> V{Generalization} --> d and
              c --> V{Generalization} --> d
          report 1 end
    </query>
    <feedback>Das Diagramm sollte Klassen "A", "B" und "C" enthalten, die von einer gemeinsamen Oberklasse "D" erben.</feedback>
  </rule>
</syntaxhighlight>
Diese Regel überprüft, ob das Modell eine Klasse "D" enthält, die drei direkte Unterklassen "A", "B" und "C" hat.
[[Category:R-GReQL]]
[[Category:R-GReQL]]

Version vom 23. Juli 2019, 10:53 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 <nowiki>&amp;lt;--&amp;amp;{FieldDeclaration} --&amp;gt;</nowiki> 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}*&amp;{WhileStatement}) and
             isEmpty(m -->{Child}*&amp;{DoStatement}) and
             isEmpty(m -->{Child}*&amp;{ForStatement}) and
             isEmpty(m -->{Child}*&amp;{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}&amp;{EmptyStatement}) or
               (not isEmpty(u -->* x -->{IfStatementThenStatement}&amp;{Block}) and isEmpty(u -->* x -->{IfStatementThenStatement}&amp;{Block} -->{Child}))
             ) and
             ( not isEmpty(u -->* x -->{IfStatementElseStatement}&amp;{EmptyStatement}) or
               (not isEmpty(u -->* x -->{IfStatementElseStatement}&amp;{Block}) and isEmpty(u -->* x -->{IfStatementElseStatement}&amp;{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}&amp;{EmptyStatement}) and
             isEmpty(x -->{IfStatementElseStatement}&amp;{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}&amp;{EmptyStatement}) or
             (not isEmpty(u -->* x -->{WhileStatementBody}&amp;{Block}) and
             isEmpty(u -->* x -->{WhileStatementBody}&amp;{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}*&amp;{MethodInvocation} -->{Access}&amp;{MethodDeclaration})* n and
              n -->{Child}*&amp;{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}*&amp;{MethodInvocation} -->{Access}&amp;{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}&amp;{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&lt;C&gt; 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&lt;C&gt;.</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.

Beispiele für statische Prüfregeln für UML-Modelle im XMI2-Format

Klassendiagramme

  <rule type="presence" points="11">
    <query>from x,y : V{Class}
           with
              x --> V{Property} --> V{Association} <-- V{Property} <-- y and
              isDefined(x.name) and x.name="A" and
              isDefined(y.name) and y.name="B"
           report 1 end
    </query>
    <feedback>Das Diagramm enthält keine Beziehung zwischen einem "A" und einem "B" oder keine Klassen mit diesen Namen.</feedback>
  </rule>

Diese Regel überprüft, ob das Modell zwei Klassen "A" und "B" enthält, die über eine Assoziation verbunden sind.

  <rule type="absence" points="0">
    <query>from x,y : V{Class}
           with
              x --> V{Property} --> V{Association} <-- V{Property} <-- y and
              isDefined(x.name) and x.name="A" and
              isDefined(y.name) and y.name="B"
           report 1 end
    </query>
    <feedback prefix="Hinweis">Im Diagramm sind die "B" eines "A" als eigene Klasse abgebildet. Das kannst du durch eine bessere Modellierung vermeiden.</feedback>
  </rule>

Diese Regel überprüft ebenfalls, ob das Modell zwei Klassen "A" und "B" enthält, die über eine Assoziation verbunden sind, definiert dies aber als unerwünschte Situation mit entsprechendem Feedback.

  <rule type="presence" points="11">
    <query>from x,y : V{Class}, z: V{Property}
           with
              x --> z and
              z --> V{Association} <-- V{Property} <-- y and
              isDefined(x.name) and x.name="A" and
              isDefined(y.name) and y.name="B" and
              isDefined(z.lower) and z.lower="1" and (not isDefined(z.upper) or z.upper="1")
           report 1 end
    </query>
    <feedback>Das Diagramm enthält keine Beziehung zwischen einem "A" und einem "B" mit der Kardinalität 1 oder keine Klassen mit diesen Namen.</feedback>
  </rule>

Diese Regel überprüft, ob das Modell zwei Klassen "A" und "B" enthält, die über eine Assoziation mit Kardinalität 1 (jedes A kennt genau ein B) verbunden sind.

  <rule type="presence" points="5">
    <query>from a,b : V{Class}, p: V{Property}
           with
              isEmpty(a -->&{Property} -->&{Association}) and
              b --> p and
              isDefined(p.aggregation) and p.aggregation="composite"
           report 1 end
    </query>
    <feedback>Es sollte im Diagramm zwei Klassen geben, bei denen die eine keine weiteren Bestandteile hat, während die andere weitere Bestandteile gemäß der Komposition hat.</feedback>
  </rule>

Diese Regel überprüft, ob es im Modell eine Klasse ohne ausgehende Assoziationen gibt und eine weitere, die mindestens eine ausgehende Komposition hat.

  <rule type="presence" points="5">
    <query>from x : V{Class}, y : V{Property}, z : V{PrimitiveType}
           with
              isDefined(x.name) and x.name="A" and
              x --> y and
              isDefined(y.name) and y.name="b" and
              y --> z and
              isDefined(z.name) and z.name="String"
           report 1 end
    </query>
    <feedback>Ein "A" soll ein Attribut für die Eigenschaft "b" bereitstellen.</feedback>
  </rule>

Diese Regel überprüft, ob es im Modell eine Klasse "A" mit dem Attribut "b" vom Typ "String" gibt.

  <rule type="presence" points="5">
    <query>from x : V{Class}, y : V{Operation}, z: V{Parameter}
           with
              isDefined(x.name) and x.name="A" and
              x --> y and
              isDefined(y.name) and stringLevenshteinDistance(y.name, "ausführen")<3 and
              y --> z
           report 1 end
    </query>
    <feedback>Ein "A" soll eine Methode bereitstellen, mit der sie etwas ausführen kann.</feedback>
  </rule>

Diese Regel prüft, ob es im Modell eine Klasse "A" mit einer Operation gibt, deren Name "ausführen" oder ähnlich lautet.

  <rule type="absence" points="4">
    <query>let c := count(from y : V{Operation} with isDefined(y.name) report y end) in
              from x : set(1)
              with
                 c<>7
              report c as "count" end
    </query>
    <feedback>Das Diagramm sollte genau 7 Methoden enthalten, enthält aber {count}.</feedback>
  </rule>

Diese Regel überprüft, ob das Modell genau 7 Methoden enthält und gibt im Falle einer anderen Anzahl diese im Feedback mit aus.

  <rule type="presence" points="5">
    <query>from x : V{Class}
           with
              isDefined(x.name) and x.name=A" and
              x.isAbstract and
              not isEmpty(x <--&{Generalization})
           report 1 end
    </query>
    <feedback>Das Diagramm sollte eine abstrakte Klasse "A" enthalten, von der mindestens eine Klasse erbt.</feedback>
  </rule>

Diese Regel überprüft, ob das Modell eine abstrakte Klasse "A" enthält, auf die in mindestens einer Generalisierung verwiesen wird.

  <rule type="presence" points="5">
    <query>from a,b,c,d : V{Class}
           with
              isDefined(a.name) and a.name="A" and
              isDefined(b.name) and b.name="B" and
              isDefined(c.name) and c.name="C" and
              isDefined(d.name) and d.name="D" and
              a --> V{Generalization} --> d and
              b --> V{Generalization} --> d and
              c --> V{Generalization} --> d
           report 1 end
    </query>
    <feedback>Das Diagramm sollte Klassen "A", "B" und "C" enthalten, die von einer gemeinsamen Oberklasse "D" erben.</feedback>
  </rule>

Diese Regel überprüft, ob das Modell eine Klasse "D" enthält, die drei direkte Unterklassen "A", "B" und "C" hat.