diff --git a/build.gradle b/build.gradle
index c1debbc81d5825e18577199ed7ec6f042a377ff4..c9cce3932ec4cbf0e1a7146114cb1cbba23e7c33 100644
--- a/build.gradle
+++ b/build.gradle
@@ -3,14 +3,14 @@ plugins {
   id 'java-gradle-plugin'
 }
 
-group 'org.jastadd.relast'
-version '0.2.4'
+group 'org.jastadd.preprocessor'
+version '0.2.5'
 
 gradlePlugin {
     plugins {
         RelastPlugin {
-            id = 'relast-test'
-            implementationClass = 'org.jastadd.relast.plugin.RelastPlugin'
+            id = 'testing'
+            implementationClass = 'org.jastadd.preprocessor.testing.plugin.PreprocessorPlugin'
         }
     }
 }
@@ -19,8 +19,8 @@ gradlePlugin {
 publishing {
     publications {
         maven(MavenPublication) {
-          groupId = "org.jastadd.relast"
-          artifactId = "relast-test"
+          groupId = "org.jastadd.preprocessor"
+          artifactId = "testing"
         }
     }
     repositories {
diff --git a/src/main/java/org/jastadd/preprocessor/testing/plugin/CompilerLocationExtension.java b/src/main/java/org/jastadd/preprocessor/testing/plugin/CompilerLocationExtension.java
new file mode 100644
index 0000000000000000000000000000000000000000..1cb967b0db8e6906bfaa5eb3991475ef9152fc7c
--- /dev/null
+++ b/src/main/java/org/jastadd/preprocessor/testing/plugin/CompilerLocationExtension.java
@@ -0,0 +1,27 @@
+package org.jastadd.preprocessor.testing.plugin;
+
+import org.gradle.api.Project;
+import org.gradle.api.provider.Property;
+
+/**
+ * TODO: Add description.
+ *
+ * @author rschoene - Initial contribution
+ */
+public class CompilerLocationExtension {
+  public Property<String> relastCompilerLocation;
+  public Property<String> ragconnectCompilerLocation;
+
+  public CompilerLocationExtension(Project project) {
+    relastCompilerLocation = project.getObjects().property(String.class);
+    ragconnectCompilerLocation = project.getObjects().property(String.class);
+  }
+
+  public Property<String> getRelastCompilerLocation() {
+    return relastCompilerLocation;
+  }
+
+  public Property<String> getRagconnectCompilerLocation() {
+    return ragconnectCompilerLocation;
+  }
+}
diff --git a/src/main/java/org/jastadd/preprocessor/testing/plugin/JastAddConfiguration.java b/src/main/java/org/jastadd/preprocessor/testing/plugin/JastAddConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..960ce586056d1c10e21991a8b92e5a83c9507ed6
--- /dev/null
+++ b/src/main/java/org/jastadd/preprocessor/testing/plugin/JastAddConfiguration.java
@@ -0,0 +1,37 @@
+package org.jastadd.preprocessor.testing.plugin;
+
+import org.gradle.api.tasks.Input;
+import org.gradle.api.tasks.InputFiles;
+import org.gradle.api.tasks.Optional;
+import org.gradle.api.tasks.OutputDirectory;
+
+import java.io.File;
+import java.nio.file.Paths;
+import java.util.List;
+
+/**
+ * Configuration options for JastAdd.
+ *
+ * @author rschoene - Initial contribution
+ */
+public class JastAddConfiguration {
+  @Optional
+  @Input
+  String jastAddList;
+
+  @Input
+  String packageName;
+
+  @InputFiles
+  List<File> inputFiles;
+
+  @Input
+  boolean run = true;
+
+  @Optional
+  @Input
+  List<String> extraOptions;
+
+  @OutputDirectory
+  File outputDir = Paths.get("src", "test", "java-gen").toFile();
+}
diff --git a/src/main/java/org/jastadd/preprocessor/testing/plugin/PreprocessorPlugin.java b/src/main/java/org/jastadd/preprocessor/testing/plugin/PreprocessorPlugin.java
new file mode 100644
index 0000000000000000000000000000000000000000..76016dfecadeef73b608f3702f5061d4e9ef1367
--- /dev/null
+++ b/src/main/java/org/jastadd/preprocessor/testing/plugin/PreprocessorPlugin.java
@@ -0,0 +1,55 @@
+package org.jastadd.preprocessor.testing.plugin;
+
+import org.gradle.api.Plugin;
+import org.gradle.api.Project;
+import org.gradle.api.Task;
+import org.gradle.api.tasks.TaskCollection;
+
+import java.util.Set;
+
+/**
+ * Plugin for preprocessor.testing.
+ *
+ * @author rschoene - Initial contribution
+ */
+public class PreprocessorPlugin implements Plugin<Project> {
+
+  private Task testTask;
+
+  @Override
+  public void apply(Project project) {
+    CompilerLocationExtension extension = project.getExtensions().create(
+        "preprocessor.testing",
+        CompilerLocationExtension.class,
+        project);
+
+    Set<Task> tasks = project.getTasksByName("compileTestJava", false);
+    // there should be only one task "compileTestJava"
+    testTask = tasks.iterator().next();
+    TaskCollection<RelastTest> relastTests = project.getTasks().withType(RelastTest.class);
+    relastTests.forEach(relastTest -> setupRelastTest(relastTest,
+        extension.getRelastCompilerLocation().getOrNull()));
+//    relastTests.whenTaskAdded(relastTest -> setupRelastTest(relastTest, extension.getRelastCompilerLocation().getOrNull()));
+    TaskCollection<RagConnectTest> ragconnectTests = project.getTasks().withType(RagConnectTest.class);
+    ragconnectTests.forEach(relastTest -> setupRagconnectTest(relastTest,
+        extension.getRelastCompilerLocation().getOrNull(),
+        extension.getRagconnectCompilerLocation().getOrNull()));
+  }
+
+  private void setupRelastTest(RelastTest relastTest, String compilerLocation) {
+    testTask.dependsOn(relastTest);
+    relastTest.setCompilerLocation(compilerLocation);
+    relastTest.setGroup("verification");
+    relastTest.setDescription("Runs a relast test");
+  }
+
+  private void setupRagconnectTest(RagConnectTest ragConnectTest,
+                                   String relastCompilerLocation,
+                                   String ragconnectCompilerLocation) {
+    testTask.dependsOn(ragConnectTest);
+    ragConnectTest.setRelastCompilerLocation(relastCompilerLocation);
+    ragConnectTest.setRagconnectCompilerLocation(ragconnectCompilerLocation);
+    ragConnectTest.setGroup("verification");
+    ragConnectTest.setDescription("Runs a ragconnect test");
+  }
+}
diff --git a/src/main/java/org/jastadd/preprocessor/testing/plugin/PreprocessorTest.java b/src/main/java/org/jastadd/preprocessor/testing/plugin/PreprocessorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..43732a8f856b6ec3aebede454febcbc12ebabca4
--- /dev/null
+++ b/src/main/java/org/jastadd/preprocessor/testing/plugin/PreprocessorTest.java
@@ -0,0 +1,9 @@
+package org.jastadd.preprocessor.testing.plugin;
+
+/**
+ * Abstract base class for all tests.
+ *
+ * @author rschoene - Initial contribution
+ */
+public abstract class PreprocessorTest {
+}
diff --git a/src/main/java/org/jastadd/preprocessor/testing/plugin/RagConnectConfiguration.java b/src/main/java/org/jastadd/preprocessor/testing/plugin/RagConnectConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..da413dfe6ede5218aac33439d8dcbeedb451e12f
--- /dev/null
+++ b/src/main/java/org/jastadd/preprocessor/testing/plugin/RagConnectConfiguration.java
@@ -0,0 +1,37 @@
+package org.jastadd.preprocessor.testing.plugin;
+
+import org.gradle.api.tasks.Input;
+import org.gradle.api.tasks.InputFiles;
+import org.gradle.api.tasks.Optional;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * Configuration options for RagConnect.
+ *
+ * @author rschoene - Initial contribution
+ */
+public class RagConnectConfiguration {
+  @Input
+  String rootNode;
+
+  @Input
+  boolean logReads;
+
+  @Input
+  boolean logWrites;
+
+  @Input
+  String outputDir;
+
+  @Optional
+  @Input
+  List<String> protocols;
+
+  @InputFiles
+  List<File> inputFiles;
+
+  @Input
+  boolean verbose = false;
+}
diff --git a/src/main/java/org/jastadd/preprocessor/testing/plugin/RagConnectTest.java b/src/main/java/org/jastadd/preprocessor/testing/plugin/RagConnectTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..f3a7ed834cb519e06ebb7848e185b3c7cc083def
--- /dev/null
+++ b/src/main/java/org/jastadd/preprocessor/testing/plugin/RagConnectTest.java
@@ -0,0 +1,92 @@
+package org.jastadd.preprocessor.testing.plugin;
+
+import org.gradle.api.DefaultTask;
+import org.gradle.api.Project;
+import org.gradle.api.file.FileCollection;
+import org.gradle.api.plugins.JavaPlugin;
+import org.gradle.api.tasks.Nested;
+import org.gradle.api.tasks.SourceSet;
+import org.gradle.api.tasks.SourceSetContainer;
+import org.gradle.api.tasks.TaskAction;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * RagConnect Test Task.
+ *
+ * @author rschoene - Initial contribution
+ */
+public class RagConnectTest extends DefaultTask {
+
+  @Nested
+  RagConnectConfiguration ragconnect;
+
+  @Nested
+  RelastConfiguration relast;
+
+  @Nested
+  JastAddConfiguration jastadd;
+
+  private String relastCompilerLocation;
+  private String ragconnectCompilerLocation;
+
+  public void setRelastCompilerLocation(String relastCompilerLocation) {
+    this.relastCompilerLocation = relastCompilerLocation;
+  }
+
+  public void setRagconnectCompilerLocation(String ragconnectCompilerLocation) {
+    this.ragconnectCompilerLocation = ragconnectCompilerLocation;
+  }
+
+  @TaskAction
+  void taskAction() throws IOException {
+    runTest();
+  }
+
+  protected void runTest() throws IOException {
+    // run ragconnect before
+    Project project = getProject();
+    String absoluteProjectPath = project.getProjectDir().getAbsolutePath();
+    // TODO maybe generated files should be deleted here?
+    project.getPlugins().withType(JavaPlugin.class, javaPlugin -> {
+      SourceSetContainer sourceSets = (SourceSetContainer) project.getProperties().get("sourceSets");
+      FileCollection runtimeClasspath = sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME).getRuntimeClasspath();
+      project.javaexec(javaExecSpec -> {
+        List<Object> args = new ArrayList<>();
+        javaExecSpec.setClasspath(runtimeClasspath);
+        if (ragconnectCompilerLocation != null) {
+          javaExecSpec.setMain("-jar");
+          args.add(ragconnectCompilerLocation);
+        } else {
+          javaExecSpec.setMain("org.jastadd.ragconnect.compiler.Compiler");
+        }
+        args.add("--o=" + ragconnect.outputDir);
+        args.add("--rootNode=" + ragconnect.rootNode);
+        if (ragconnect.logReads) {
+          args.add("--logReads");
+        }
+        if (ragconnect.logWrites) {
+          args.add("--logWrites");
+        }
+        if (ragconnect.verbose) {
+          args.add("--verbose");
+        }
+        if (ragconnect.protocols != null && !ragconnect.protocols.isEmpty()) {
+          args.add("--protocols=" + String.join(",", ragconnect.protocols));
+        }
+        args.addAll(ragconnect.inputFiles);
+        javaExecSpec.args(args);
+      }).assertNormalExitValue();
+    });
+
+
+    // now run relast + jastadd
+    RelastTest relastTest = new RelastTest();
+    relastTest.jastadd = jastadd;
+    relastTest.relast = relast;
+    relastTest.setCompilerLocation(relastCompilerLocation);
+    relastTest.runTest();
+  }
+}
diff --git a/src/main/java/org/jastadd/preprocessor/testing/plugin/RelastConfiguration.java b/src/main/java/org/jastadd/preprocessor/testing/plugin/RelastConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..8a05d205057f6cde87c42f428d44a50e65ce6657
--- /dev/null
+++ b/src/main/java/org/jastadd/preprocessor/testing/plugin/RelastConfiguration.java
@@ -0,0 +1,42 @@
+package org.jastadd.preprocessor.testing.plugin;
+
+import org.gradle.api.tasks.Input;
+import org.gradle.api.tasks.InputFiles;
+import org.gradle.api.tasks.Optional;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * Configuration options for Relast.
+ *
+ * @author rschoene - Initial contribution
+ */
+public class RelastConfiguration {
+  @Input
+  boolean useJastAddNames;
+
+  @Input
+  String grammarName;
+
+  @InputFiles
+  @Optional
+  List<File> inputFiles;
+
+  @Input
+  boolean writeToFile = true;
+
+  @Input
+  boolean resolverHelper = true;
+
+  @Optional
+  @Input
+  String listClass;
+
+  @Optional
+  @Input
+  String serializer;
+
+  @Input
+  boolean verbose = false;
+}
diff --git a/src/main/java/org/jastadd/preprocessor/testing/plugin/RelastTest.java b/src/main/java/org/jastadd/preprocessor/testing/plugin/RelastTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..a9c4cbc1783ef100ab8d0d728ad0e00651afd925
--- /dev/null
+++ b/src/main/java/org/jastadd/preprocessor/testing/plugin/RelastTest.java
@@ -0,0 +1,173 @@
+package org.jastadd.preprocessor.testing.plugin;
+
+import org.gradle.api.DefaultTask;
+import org.gradle.api.Project;
+import org.gradle.api.file.FileCollection;
+import org.gradle.api.plugins.JavaPlugin;
+import org.gradle.api.tasks.Nested;
+import org.gradle.api.tasks.SourceSet;
+import org.gradle.api.tasks.SourceSetContainer;
+import org.gradle.api.tasks.TaskAction;
+
+import java.io.IOException;
+import java.nio.file.FileAlreadyExistsException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * RelAst Test Task
+ *
+ * @author rschoene - Initial contribution
+ */
+public class RelastTest extends DefaultTask {
+  // configuration from plugin
+  private String compilerLocation;
+
+  @Nested
+  RelastConfiguration relast;
+
+  @Nested
+  JastAddConfiguration jastadd;
+
+  public void setCompilerLocation(String compilerLocation) {
+    this.compilerLocation = compilerLocation;
+  }
+
+  private final String[] genSuffixes = {".ast", ".jadd", "RefResolver.jadd", "ResolverStubs.jrag", "Serializer.jadd"};
+
+  private Path pathToAbsoluteProject(String filename) {
+    return Paths.get(getProject().getProjectDir().getAbsolutePath(), filename);
+  }
+
+  @TaskAction
+  void taskAction() throws IOException {
+    runTest();
+  }
+
+  protected void runTest() throws IOException {
+    Project project = getProject();
+    if (relast.verbose) {
+      System.out.println("Running relast test in " + project.getDisplayName());
+      System.out.println("relast files: " + relast.inputFiles);
+      System.out.println("Deleting files");
+    }
+    // first, delete generated files
+    List<Path> genFiles = new ArrayList<>();
+    for (String suffix : genSuffixes) {
+      genFiles.add(pathToAbsoluteProject(relast.grammarName + suffix));
+    }
+    if (relast.verbose) {
+      System.out.println("gen files: " + genFiles);
+    }
+    project.delete(deleteSpec -> {
+      deleteSpec.delete(genFiles);
+//      deleteSpec.delete(Paths.get(jastadd.outputDir, jastadd.packageName));
+      deleteSpec.delete(jastadd.outputDir.toPath().resolve(jastadd.packageName));
+    });
+    // create output directories, if not existing
+    createDirectory(pathToAbsoluteProject(jastadd.outputDir.getName()));
+    createDirectory(pathToAbsoluteProject(relast.grammarName).getParent());
+    if (relast.verbose) {
+      System.out.println("Pre processing, running relast");
+    }
+    // then, run relast pre processing
+    project.getPlugins().withType(JavaPlugin.class, javaPlugin -> {
+      SourceSetContainer sourceSets = (SourceSetContainer) project.getProperties().get("sourceSets");
+      FileCollection runtimeClasspath = sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME).getRuntimeClasspath();
+      project.javaexec(javaExecSpec -> {
+        List<Object> args = new ArrayList<>();
+        javaExecSpec.setClasspath(runtimeClasspath);
+        if (compilerLocation != null) {
+          javaExecSpec.setMain("-jar");
+          args.add(compilerLocation);
+        } else {
+          javaExecSpec.setMain("org.jastadd.relast.compiler.Compiler");
+        }
+        args.addAll(relast.inputFiles.stream().map(filename -> pathToAbsoluteProject(filename.getName())).collect(Collectors.toList()));
+        args.add("--quiet");
+        if (relast.writeToFile) {
+          args.add("--file");
+        }
+        if (relast.useJastAddNames) {
+          args.add("--useJastAddNames");
+        }
+        if (relast.resolverHelper) {
+          args.add("--resolverHelper");
+        }
+        if (jastadd.jastAddList != null) {
+          args.add("--jastAddList=" + jastadd.jastAddList);
+        }
+        if (relast.listClass != null) {
+          args.add("--listClass=" + relast.listClass);
+        }
+        if (relast.serializer != null) {
+          args.add("--serializer=" + relast.serializer);
+        }
+        args.add("--grammarName=" + pathToAbsoluteProject(relast.grammarName));
+        if (relast.verbose) {
+          System.out.println("Start relast with args: " + args);
+        }
+        javaExecSpec.args(args);
+      }).assertNormalExitValue();
+    });
+    if (jastadd.run) {
+      if (relast.verbose) {
+        System.out.println("Compile with JastAdd");
+      }
+      // check which files were actually generated
+      genFiles.removeIf(this::verboseFileNotExists);
+      // finally, compile generated files
+      project.getPlugins().withType(JavaPlugin.class, javaPlugin -> {
+        SourceSetContainer sourceSets = (SourceSetContainer) project.getProperties().get("sourceSets");
+        FileCollection runtimeClasspath = sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME).getRuntimeClasspath();
+        project.javaexec(javaExecSpec -> {
+          javaExecSpec.setClasspath(runtimeClasspath);
+          javaExecSpec.setMain("org.jastadd.JastAdd");
+          List<Object> args = new ArrayList<>();
+          args.add("--o=" + pathToAbsoluteProject(jastadd.outputDir.getName()));
+          args.add("--package=" + jastadd.packageName);
+          if (jastadd.jastAddList != null) {
+            args.add("--List=" + jastadd.jastAddList);
+          }
+          args.addAll(jastadd.extraOptions);
+          args.addAll(genFiles);
+          args.addAll(jastadd.inputFiles);
+          if (relast.verbose) {
+            System.out.println("Start JastAdd with args: " + args);
+          }
+          javaExecSpec.args(args);
+        });
+      });
+    }
+  }
+
+  private boolean verboseFileNotExists(Path path) {
+    boolean fileDoesNotExist = !Files.exists(path);
+    if (fileDoesNotExist && relast.verbose) {
+      System.out.println("Do not include " + path);
+    }
+    return fileDoesNotExist;
+  }
+
+  private void createDirectory(Path path) throws IOException {
+    if (Files.exists(path) && Files.isDirectory(path)) {
+      return;
+    }
+    if (relast.verbose) {
+      System.out.println("Creating " + path.toAbsolutePath());
+    }
+    try {
+      Files.createDirectories(path);
+    } catch (FileAlreadyExistsException e) {
+      System.err.println("Skipping creation of already existing " + path);
+    } catch (IOException e) {
+      System.err.println("Could not create output directory " + path);
+      throw e;
+    }
+  }
+
+}
diff --git a/src/main/java/org/jastadd/relast/plugin/CompilerLocationExtension.java b/src/main/java/org/jastadd/relast/plugin/CompilerLocationExtension.java
deleted file mode 100644
index d28d7131797be7eac9869b9c7f0b58ed05739b14..0000000000000000000000000000000000000000
--- a/src/main/java/org/jastadd/relast/plugin/CompilerLocationExtension.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.jastadd.relast.plugin;
-
-import org.gradle.api.Project;
-import org.gradle.api.provider.Property;
-
-/**
- * TODO: Add description.
- *
- * @author rschoene - Initial contribution
- */
-public class CompilerLocationExtension {
-  public Property<String> compilerLocation;
-
-  public CompilerLocationExtension(Project project) {
-    compilerLocation = project.getObjects().property(String.class);
-  }
-
-  public Property<String> getCompilerLocation() {
-    return compilerLocation;
-  }
-}
diff --git a/src/main/java/org/jastadd/relast/plugin/RelastPlugin.java b/src/main/java/org/jastadd/relast/plugin/RelastPlugin.java
deleted file mode 100644
index 1ce9e963b27c2efdf53092a91335680e708e7509..0000000000000000000000000000000000000000
--- a/src/main/java/org/jastadd/relast/plugin/RelastPlugin.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.jastadd.relast.plugin;
-
-import org.gradle.api.Plugin;
-import org.gradle.api.Project;
-import org.gradle.api.Task;
-import org.gradle.api.tasks.TaskCollection;
-
-import java.util.Set;
-
-/**
- * Plugin for RelAst-Test.
- *
- * @author rschoene - Initial contribution
- */
-public class RelastPlugin implements Plugin<Project> {
-
-  private Task testTask;
-
-  @Override
-  public void apply(Project project) {
-    CompilerLocationExtension extension = project.getExtensions().create(
-        "relastTest",
-        CompilerLocationExtension.class,
-        project);
-
-    Set<Task> tasks = project.getTasksByName("test", false);
-    // there should be only one task "test"
-    testTask = tasks.iterator().next();
-    TaskCollection<RelastTest> relastTests = project.getTasks().withType(RelastTest.class);
-    relastTests.forEach(relastTest -> setupRelastTest(relastTest, extension.getCompilerLocation().getOrNull()));
-    relastTests.whenTaskAdded(relastTest -> setupRelastTest(relastTest, extension.getCompilerLocation().getOrNull()));
-  }
-
-  private void setupRelastTest(RelastTest relastTest, String compilerLocation) {
-    testTask.dependsOn(relastTest);
-    relastTest.setCompilerLocation(compilerLocation);
-    relastTest.setGroup("verification");
-  }
-}
diff --git a/src/main/java/org/jastadd/relast/plugin/RelastTest.java b/src/main/java/org/jastadd/relast/plugin/RelastTest.java
deleted file mode 100644
index a2a817162fa15ee5828ad2f2a8c139540e804a97..0000000000000000000000000000000000000000
--- a/src/main/java/org/jastadd/relast/plugin/RelastTest.java
+++ /dev/null
@@ -1,340 +0,0 @@
-package org.jastadd.relast.plugin;
-
-import org.gradle.api.DefaultTask;
-import org.gradle.api.Project;
-import org.gradle.api.file.FileCollection;
-import org.gradle.api.plugins.JavaPlugin;
-import org.gradle.api.tasks.Input;
-import org.gradle.api.tasks.Optional;
-import org.gradle.api.tasks.SourceSet;
-import org.gradle.api.tasks.SourceSetContainer;
-import org.gradle.api.tasks.TaskAction;
-
-import java.io.IOException;
-import java.nio.file.*;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Collectors;
-
-/**
- * RelAst Test Task
- *
- * @author rschoene - Initial contribution
- */
-@SuppressWarnings({"unused", "WeakerAccess"})
-public class RelastTest extends DefaultTask {
-  // configuration from plugin
-  private String compilerLocation;
-  // general options
-  private boolean verbose = false;
-  // pre-process options
-  private List<String> relastFiles = new ArrayList<>();
-  private boolean useJastAddNames;
-  private boolean resolverHelper;
-  private boolean writeToFile = true;
-  private String grammarName;
-  private String listClass;
-  private String jastAddList;
-  private String serializer;
-
-  // compile options
-  private boolean runJastAdd = true;
-  private String outputDir = "src/test/java-gen/";
-  private String packageName;
-  private final List<String> moreInputFiles = new ArrayList<>();
-  private List<String> extraJastAddOptions = new ArrayList<>();
-
-  public void setCompilerLocation(String compilerLocation) {
-    this.compilerLocation = compilerLocation;
-  }
-
-  @Input
-  public boolean isVerbose() {
-    return verbose;
-  }
-
-  public void setVerbose(boolean verbose) {
-    this.verbose = verbose;
-  }
-
-  // pre-process options
-  @Input
-  public List<String> getRelastFiles() {
-    return relastFiles;
-  }
-
-  public void relastFiles(String relastFile) {
-    this.relastFiles.add(relastFile);
-  }
-
-  public void relastFiles(String[] relastFilesArray) {
-    this.relastFiles = Arrays.asList(relastFilesArray);
-  }
-
-  @Input
-  public boolean isUseJastAddNames() {
-    return useJastAddNames;
-  }
-
-  public void setUseJastAddNames(boolean useJastAddNames) {
-    this.useJastAddNames = useJastAddNames;
-  }
-
-  @Input
-  public boolean isResolverHelper() {
-    return resolverHelper;
-  }
-
-  public void setResolverHelper(boolean resolverHelper) {
-    this.resolverHelper = resolverHelper;
-  }
-
-  @Input
-  public boolean isWriteToFile() {
-    return writeToFile;
-  }
-
-  public void setWriteToFile(boolean writeToFile) {
-    this.writeToFile = writeToFile;
-  }
-
-  @Input
-  public String getGrammarName() {
-    return grammarName;
-  }
-
-  public void setGrammarName(String grammarName) {
-    this.grammarName = grammarName;
-  }
-
-  @Optional
-  @Input
-  public String getListClass() {
-    return listClass;
-  }
-
-  public void setListClass(String listClass) {
-    this.listClass = listClass;
-  }
-
-  @Optional
-  @Input
-  public String getJastAddList() {
-    return jastAddList;
-  }
-
-  public void setJastAddList(String jastAddList) {
-    this.jastAddList = jastAddList;
-  }
-
-  @Optional
-  @Input
-  public String getSerializer() {
-    return serializer;
-  }
-
-  public void setSerializer(String serializer) {
-    this.serializer = serializer;
-  }
-
-  // compile options
-  @Input
-  public boolean isRunJastAdd() {
-    return runJastAdd;
-  }
-
-  public void setRunJastAdd(boolean runJastAdd) {
-    this.runJastAdd = runJastAdd;
-  }
-
-  @Optional
-  @Input
-  public String getOutputDir() {
-    return outputDir;
-  }
-
-  public void setOutputDir(String outputDir) {
-    this.outputDir = outputDir;
-  }
-
-  @Input
-  public String getPackageName() {
-    return packageName;
-  }
-
-  public void setPackageName(String packageName) {
-    this.packageName = packageName;
-  }
-
-  @Optional
-  @Input
-  public List<String> getExtraJastAddOptions() {
-    return extraJastAddOptions;
-  }
-
-  public void extraJastAddOptions(String f) {
-    this.extraJastAddOptions.add(f);
-  }
-
-  public void extraJastAddOptions(String[] fileArray) {
-    this.extraJastAddOptions.addAll(Arrays.asList(fileArray));
-  }
-
-  @Optional
-  @Input
-  public List<String> getMoreInputFiles() {
-    return moreInputFiles;
-  }
-
-  public void moreInputFiles(String f) {
-    this.moreInputFiles.add(f);
-  }
-
-  public void moreInputFiles(String[] fileArray) {
-    this.moreInputFiles.addAll(Arrays.asList(fileArray));
-  }
-
-  private boolean isSet(String option) {
-    return option != null && !option.isEmpty();
-  }
-
-  private final String[] genSuffixes = {".ast", ".jadd", "RefResolver.jadd", "ResolverStubs.jrag", "Serializer.jadd"};
-
-  private Path pathToAbsoluteProject(String filename) {
-    return Paths.get(getProject().getProjectDir().getAbsolutePath(), filename);
-  }
-
-  @TaskAction
-  void runTest() throws IOException {
-    setGroup("verification");
-    setDescription("Runs a relast test");
-    Project project = getProject();
-    String absoluteProjectPath = project.getProjectDir().getAbsolutePath();
-    if (isVerbose()) {
-      System.out.println("Running relast test in " + project.getDisplayName());
-      System.out.println("relast files: " + getRelastFiles());
-      System.out.println("Deleting files");
-    }
-    // first, delete generated files
-    List<Path> genFiles = new ArrayList<>();
-    for (String suffix : genSuffixes) {
-      genFiles.add(pathToAbsoluteProject(getGrammarName() + suffix));
-    }
-    if (isVerbose()) {
-      System.out.println("gen files: " + genFiles);
-    }
-    project.delete(deleteSpec -> {
-      deleteSpec.delete(genFiles);
-      if (isSet(getPackageName())) {
-        deleteSpec.delete(Paths.get(getOutputDir(), getPackageName()));
-      }
-    });
-    // create output directories, if not existing
-    createDirectory(pathToAbsoluteProject(getOutputDir()));
-    createDirectory(pathToAbsoluteProject(getGrammarName()).getParent());
-    if (isVerbose()) {
-      System.out.println("Pre processing, running relast");
-    }
-    // then, run relast pre processing
-    project.getPlugins().withType(JavaPlugin.class, javaPlugin -> {
-      SourceSetContainer sourceSets = (SourceSetContainer) project.getProperties().get("sourceSets");
-      FileCollection runtimeClasspath = sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME).getRuntimeClasspath();
-      project.javaexec(javaExecSpec -> {
-        List<Object> args = new ArrayList<>();
-        javaExecSpec.setClasspath(runtimeClasspath);
-        if (compilerLocation != null) {
-          javaExecSpec.setMain("-jar");
-          args.add(compilerLocation);
-        } else {
-          javaExecSpec.setMain("org.jastadd.relast.compiler.Compiler");
-        }
-        args.addAll(getRelastFiles().stream().map(this::pathToAbsoluteProject).collect(Collectors.toList()));
-        args.add("--quiet");
-        if (isWriteToFile()) {
-          args.add("--file");
-        }
-        if (isUseJastAddNames()) {
-          args.add("--useJastAddNames");
-        }
-        if (isResolverHelper()) {
-          args.add("--resolverHelper");
-        }
-        if (isSet(getJastAddList())) {
-          args.add("--jastAddList=" + getJastAddList());
-        }
-        if (isSet(getListClass())) {
-          args.add("--listClass=" + getListClass());
-        }
-        if (isSet(getSerializer())) {
-          args.add("--serializer=" + getSerializer());
-        }
-        args.add("--grammarName=" + pathToAbsoluteProject(getGrammarName()));
-        if (isVerbose()) {
-          System.out.println("Start relast with args: " + args);
-        }
-        javaExecSpec.args(args);
-      }).assertNormalExitValue();
-    });
-    if (isRunJastAdd()) {
-      if (isVerbose()) {
-        System.out.println("Compile with JastAdd");
-      }
-      // check which files were actually generated
-      genFiles.removeIf(this::verboseFileNotExists);
-      // finally, compile generated files
-      project.getPlugins().withType(JavaPlugin.class, javaPlugin -> {
-        SourceSetContainer sourceSets = (SourceSetContainer) project.getProperties().get("sourceSets");
-        FileCollection runtimeClasspath = sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME).getRuntimeClasspath();
-        project.javaexec(javaExecSpec -> {
-          javaExecSpec.setClasspath(runtimeClasspath);
-          javaExecSpec.setMain("org.jastadd.JastAdd");
-          List<Object> args = new ArrayList<>();
-          args.add("--o=" + pathToAbsoluteProject(getOutputDir()));
-          args.add("--package=" + getPackageName());
-          if (isSet(getJastAddList())) {
-            args.add("--List=" + getJastAddList());
-          }
-          args.addAll(getExtraJastAddOptions());
-          args.addAll(genFiles);
-          args.addAll(getMoreInputFiles().stream().map(this::pathToAbsoluteProject).collect(Collectors.toList()));
-          if (isVerbose()) {
-            System.out.println("Start JastAdd with args: " + args);
-          }
-          javaExecSpec.args(args);
-        });
-      });
-    }
-  }
-
-  private String fileExtension(String filename) {
-    int indexOfDot = filename.lastIndexOf('.');
-    return indexOfDot == -1 ? filename : filename.substring(indexOfDot + 1);
-  }
-
-  private boolean verboseFileNotExists(Path path) {
-    boolean fileDoesNotExist = !Files.exists(path);
-    if (fileDoesNotExist && isVerbose()) {
-      System.out.println("Do not include " + path);
-    }
-    return fileDoesNotExist;
-  }
-
-  private void createDirectory(Path path) throws IOException {
-    if (Files.exists(path) && Files.isDirectory(path)) {
-      return;
-    }
-    if (isVerbose()) {
-      System.out.println("Creating " + path.toAbsolutePath());
-    }
-    try {
-      Files.createDirectories(path);
-    } catch (FileAlreadyExistsException e) {
-      System.err.println("Skipping creation of already existing " + path);
-    } catch (IOException e) {
-      System.err.println("Could not create output directory " + path);
-      throw e;
-    }
-  }
-
-}