files = new ArrayList<>();
@@ -125,6 +134,10 @@ public class JavaCompilerCheckFacade {
JavaCompiler.CompilationTask task = compiler.getTask(output, fileManager, diagnostics,
options, classes, compilationUnits);
+ if (universe) {
+ task.setProcessors(Collections.singletonList(new UniverseChecker()));
+ }
+
return CompletableFuture.supplyAsync(() -> {
long start = System.currentTimeMillis();
var b = task.call();
diff --git a/key.ui/src/main/java/de/uka/ilkd/key/gui/plugins/javac/JavacExtension.java b/key.ui/src/main/java/de/uka/ilkd/key/gui/plugins/javac/JavacExtension.java
index a36732b5390..a0ca18c5526 100644
--- a/key.ui/src/main/java/de/uka/ilkd/key/gui/plugins/javac/JavacExtension.java
+++ b/key.ui/src/main/java/de/uka/ilkd/key/gui/plugins/javac/JavacExtension.java
@@ -34,6 +34,9 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.stream.Collectors;
+import java.util.Objects;
+
/**
* Extension provides Javac checks for recent-loaded Java files.
*
@@ -150,7 +153,7 @@ private void loadProof(Proof selectedProof) throws RuntimeException {
return;
}
- Path bootClassPath = jm.getBootClassPath() != null ? jm.getBootClassPath() : null;
+ Path bootClassPath = jm.getBootClassPath(); // may be null
List classpath = jm.getClassPath();
JavacSettings settings = JavacSettingsProvider.getJavacSettings();
@@ -158,8 +161,11 @@ private void loadProof(Proof selectedProof) throws RuntimeException {
if (settings.getUseProcessors()) {
if (classpath == null) classpath = new ArrayList<>();
- classpath.addAll(Arrays.asList(settings.getClassPaths().split(System.lineSeparator()))
- .stream().map(p -> Paths.get(p)).toList());
+ String classpaths = settings.getClassPaths();
+ if (!classpaths.isEmpty()) {
+ classpath.addAll(Arrays.asList(classpaths.split(System.lineSeparator()))
+ .stream().map(p -> Paths.get(p)).toList());
+ }
processors = Arrays.asList(settings.getProcessors().split(System.lineSeparator()));
}
diff --git a/key.ui/src/test/java/de/uka/ilkd/key/gui/plugins/javac/JavaCompilerCheckFacadeTest.java b/key.ui/src/test/java/de/uka/ilkd/key/gui/plugins/javac/JavaCompilerCheckFacadeTest.java
index 5cae7320876..d3851cd755b 100644
--- a/key.ui/src/test/java/de/uka/ilkd/key/gui/plugins/javac/JavaCompilerCheckFacadeTest.java
+++ b/key.ui/src/test/java/de/uka/ilkd/key/gui/plugins/javac/JavaCompilerCheckFacadeTest.java
@@ -4,15 +4,24 @@
package de.uka.ilkd.key.gui.plugins.javac;
import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.Arrays;
import java.util.Collections;
import java.util.concurrent.ExecutionException;
import de.uka.ilkd.key.proof.ProofAggregate;
import de.uka.ilkd.key.proof.init.ProblemInitializer;
import de.uka.ilkd.key.proof.init.ProofOblInput;
+import de.uka.ilkd.key.gui.PositionedIssueString;
import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
/**
* @author Alexander Weigl
* @version 1 (29.01.23)
@@ -20,7 +29,24 @@
class JavaCompilerCheckFacadeTest {
@Test
void compile1() throws ExecutionException, InterruptedException {
- File src = new File("examples/firstTouch/06-BinarySearch/src/").getAbsoluteFile();
+ Path src = Paths.get("examples/firstTouch/06-BinarySearch/src/");
+ assertEquals(checkFile(src, Collections.emptyList()).size(), 0);
+ }
+
+ @Test
+ void compileUniverseCorrect() throws ExecutionException, InterruptedException {
+ Path src = Paths.get("src/test/resources/plugins/javac/Correct.java");
+ assertEquals(checkFile(src, Arrays.asList("universe.UniverseChecker")).size(), 0);
+ }
+
+ @Test
+ void compileUniverseIncorrect() throws ExecutionException, InterruptedException, IOException {
+ Path src = Paths.get("src/test/resources/plugins/javac/Incorrect.java");
+ assertEquals(checkFile(src, Collections.emptyList()).size(), 0);
+ assertEquals(checkFile(src, Arrays.asList("universe.UniverseChecker")).size(), 1);
+ }
+
+ List checkFile(Path src, List processors) throws ExecutionException, InterruptedException {
System.out.println(src);
ProblemInitializer.ProblemInitializerListener emptyListener =
new ProblemInitializer.ProblemInitializerListener() {
@@ -48,8 +74,7 @@ public void reportException(Object sender, ProofOblInput input, Exception e) {}
};
var promise =
JavaCompilerCheckFacade.check(emptyListener, null, Collections.emptyList(),
- src.toPath());
- promise.get();
+ src, processors);
+ return promise.get();
}
-
}
diff --git a/key.ui/src/test/resources/plugins/javac/Correct.java b/key.ui/src/test/resources/plugins/javac/Correct.java
new file mode 100644
index 00000000000..195a49c866a
--- /dev/null
+++ b/key.ui/src/test/resources/plugins/javac/Correct.java
@@ -0,0 +1,141 @@
+import universe.qual.Rep;
+import universe.qual.Peer;
+import universe.qual.Payload;
+
+class Client {
+ /*@ normal_behaviour
+ @ requires t1 != t2;
+ @ requires t2.isConst(0);
+ @ requires \invariant_for(t1) && \invariant_for(t2);
+ @ ensures t2.isConst(0);
+ */
+ void increment(@Rep Tree t1, @Rep Tree t2) {
+ t1.increment();
+ }
+
+ /*@ normal_behaviour
+ @ requires t1 != t2;
+ @ requires t2.isConst(t2.value);
+ @ requires \invariant_for(t1);
+ @ requires \invariant_for(t2);
+ @ requires t1.isConst(t1.value);
+ @ ensures t1.value == \old(t1.value) + 1;
+ @ ensures t1.isConst(t1.value);
+ @ ensures t2.isConst(\old(t2.value));
+ */
+ void increment2(@Rep Tree t1, @Rep Tree t2) {
+ t1.increment();
+ }
+
+ /*@ normal_behaviour
+ @ requires t1 != t2;
+ @ requires t2.isConst(t2.value);
+ @ requires \invariant_for(t2);
+ @ requires \invariant_for(t1);
+ @ ensures t1.contains(value);
+ @ ensures t2.isConst(\old(t2.value));
+ */
+ void append(@Rep Tree t1, int value, @Rep Tree t2) {
+ t1.append(value);
+ }
+
+ /*@ normal_behaviour
+ @ requires t1 != t2;
+ @ requires t2.isConst(t2.value);
+ @ requires \invariant_for(t2);
+ @ requires \invariant_for(t1);
+ @ requires t1.contains(0);
+ @ ensures t1.contains(1);
+ @ ensures t2.isConst(\old(t2.value));
+ */
+ void append(@Rep Tree t1, @Rep Tree t2) {
+ t1.increment();
+ }
+}
+
+final class Tree {
+ public @Rep /*@ nullable */ Tree left;
+ public @Rep /*@ nullable */ Tree right;
+ public int value;
+
+ //@ public ghost \dl_tree t;
+ //@ public accessible \inv: \dl_createdRepfp(this);
+ //@ public invariant t == \dl_Node(left == null ? \dl_Leaf() : left.t, value, right == null ? \dl_Leaf() : right.t);
+ //@ public invariant \dl_tree_count(t) >= 0;
+ //@ public invariant left != null ==> \invariant_for(left);
+ //@ public invariant right != null ==> \invariant_for(right);
+ //@ public invariant left != null && right != null ==> right != left;
+
+ /*@ public normal_behaviour
+ @ ensures left == null && right == null && value == v;
+ @ ensures t == \dl_Node(\dl_Leaf(), v, \dl_Leaf());
+ @*/
+ public /*@ pure */ Tree(int v) {
+ left = null;
+ right = null;
+ value = v;
+ //@ set t = \dl_Node(\dl_Leaf(), v, \dl_Leaf());
+ }
+
+ /*@ public normal_behaviour
+ @ ensures \result == \dl_tree_is_const(t, v);
+ @ measured_by \dl_tree_count(t);
+ @ accessible \dl_createdRepfp(this);
+ @*/
+ public /*@ pure */ boolean isConst(int v) {
+ if (value != v) return false;
+ if (left != null && !left.isConst(v)) return false;
+ if (right != null && !right.isConst(v)) return false;
+ return true;
+ }
+
+ /*@ public normal_behaviour
+ @ ensures \result == \dl_tree_contains(t, v);
+ @ measured_by \dl_tree_count(t);
+ @ accessible \dl_createdRepfp(this);
+ @*/
+ public /*@ pure */ boolean contains(int v) {
+ if (value == v) return true;
+ if (left != null && left.contains(v)) return true;
+ if (right != null && right.contains(v)) return true;
+ return false;
+ }
+
+ /*@ public normal_behaviour
+ @ ensures t == \dl_tree_append(\old(t), v);
+ @ ensures \dl_tree_count(t) == \dl_tree_count(\old(t)) + 1;
+ @ measured_by \dl_tree_count(t);
+ @ assignable \dl_createdRepfp(this);
+ @*/
+ public void append(int v) {
+ if (v <= value) {
+ if (left == null) {
+ left = new @Rep Tree(v);
+ } else {
+ left.append(v);
+ }
+ } else {
+ if (right == null) {
+ right = new @Rep Tree(v);
+ } else {
+ right.append(v);
+ }
+ }
+
+ //@ set t = \dl_Node(left == null ? \dl_Leaf() : left.t, value, right == null ? \dl_Leaf() : right.t);
+ }
+
+ /*@ public normal_behaviour
+ @ ensures t == \dl_tree_increment(\old(t));
+ @ ensures \dl_tree_count(t) == \dl_tree_count(\old(t));
+ @ measured_by \dl_tree_count(t);
+ @ assignable \dl_createdRepfp(this);
+ @*/
+ public void increment() {
+ value++;
+ if (left != null) left.increment();
+ if (right != null) right.increment();
+
+ //@ set t = \dl_Node(left == null ? \dl_Leaf() : left.t, value, right == null ? \dl_Leaf() : right.t);
+ }
+}
diff --git a/key.ui/src/test/resources/plugins/javac/Incorrect.java b/key.ui/src/test/resources/plugins/javac/Incorrect.java
new file mode 100644
index 00000000000..31187ea8bfe
--- /dev/null
+++ b/key.ui/src/test/resources/plugins/javac/Incorrect.java
@@ -0,0 +1,7 @@
+import universe.qual.*;
+
+class Client {
+ void client(@Rep Object t1, @Peer Object t2) {
+ t1 = t2;
+ }
+}
diff --git a/keyext.isabelletranslation/build.gradle b/keyext.isabelletranslation/build.gradle
index e2119425bdb..0a75bb1bb8b 100644
--- a/keyext.isabelletranslation/build.gradle
+++ b/keyext.isabelletranslation/build.gradle
@@ -14,4 +14,4 @@ dependencies {
*/
configurations.configureEach {
exclude group: 'org.slf4j', module: 'slf4j-simple'
-}
\ No newline at end of file
+}