diff --git a/.gitignore b/.gitignore
index 86e47157fa6c8bbc68059db2fc8faf3afb8ef89b..8045f43301dea7e2249ce93bde03b26057360f6a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,8 +7,6 @@
 # Ignore Gradle GUI config
 gradle-app.setting
 
-# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
-!gradle-wrapper.jar
 
 # Cache of project
 .gradletasknamecache
@@ -44,6 +42,9 @@ gen
 *.tar.gz
 *.rar
 
+# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
+!gradle-wrapper.jar
+
 # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
 hs_err_pid*
 
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..6dcf081d1f4524c59f36726cbdf1aa5cf08f78cd
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,14 @@
+stages:
+    - build
+    - test
+    - jar
+    - deploy
+
+jar:
+    image: openjdk:11
+    stage: jar
+    script:
+        - ./gradlew --continue --console=plain --info buildPlugin
+    artifacts:
+        paths:
+            - "/builds/jastadd/*/build/libs/JastAddGrammar-*.jar"
diff --git a/build.gradle.kts b/build.gradle.kts
index a3635732989a196f93e7cf9de53dfec463fe5da3..7810d31ee16be8aed0338be9eca4e75fd5f12b75 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,65 +1,62 @@
-import org.jetbrains.changelog.closure
+import io.gitlab.arturbosch.detekt.Detekt
 import org.jetbrains.changelog.markdownToHTML
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
 import org.jetbrains.grammarkit.tasks.GenerateLexer
 import org.jetbrains.grammarkit.tasks.GenerateParser
 
+fun properties(key: String) = project.findProperty(key).toString()
+
 plugins {
-    // IDE support
-    idea
+
+    id("idea")
     // Java support
     id("java")
+    // Kotlin support
+    id("org.jetbrains.kotlin.jvm") version "1.5.10"
     // gradle-intellij-plugin - read more: https://github.com/JetBrains/gradle-intellij-plugin
-    id("org.jetbrains.intellij") version "0.6.5"
+    id("org.jetbrains.intellij") version "1.0"
     // gradle-changelog-plugin - read more: https://github.com/JetBrains/gradle-changelog-plugin
-    id("org.jetbrains.changelog") version "0.6.2"
-    // Grammar-Kit - read more: https://github.com/JetBrains/Grammar-Kit
-    id("org.jetbrains.grammarkit") version "2020.3.2"
-}
-
-// Import variables from gradle.properties file
-val pluginGroup: String by project
-// `pluginName_` variable ends with `_` because of the collision with Kotlin magic getter in the `intellij` closure.
-// Read more about the issue: https://github.com/JetBrains/intellij-platform-plugin-template/issues/29
-val pluginName_: String by project
-val pluginVersion: String by project
-val pluginSinceBuild: String by project
-val pluginUntilBuild: String by project
-val pluginVerifierIdeVersions: String by project
-
-val platformType: String by project
-val platformVersion: String by project
-val platformPlugins: String by project
-val platformDownloadSources: String by project
-
+    id("org.jetbrains.changelog") version "1.1.2"
+    // detekt linter - read more: https://detekt.github.io/detekt/gradle.html
+    id("io.gitlab.arturbosch.detekt") version "1.17.1"
+    // ktlint linter - read more: https://github.com/JLLeitschuh/ktlint-gradle
+    id("org.jlleitschuh.gradle.ktlint") version "10.0.0"
 
-
-apply {
-    plugin("idea")
-    plugin("org.jetbrains.grammarkit")
-    plugin("org.jetbrains.intellij")
+    id("org.jetbrains.grammarkit") version "2021.1.3"
 }
 
-group = pluginGroup
-version = pluginVersion
+group = properties("pluginGroup")
+version = properties("pluginVersion")
 
 // Configure project's dependencies
 repositories {
     mavenCentral()
-    jcenter()
-    maven(url="https://www.jetbrains.com/intellij-repository/releases")
+}
+dependencies {
+    detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:1.17.1")
+}
+java {
+    sourceCompatibility = JavaVersion.VERSION_1_8
+    targetCompatibility = JavaVersion.VERSION_1_8
+}
+
+idea {
+    module {
+        generatedSourceDirs.add(file("./src/gen"))
+    }
 }
 
 // Configure gradle-intellij-plugin plugin.
 // Read more: https://github.com/JetBrains/gradle-intellij-plugin
 intellij {
-    pluginName = pluginName_
-    version = platformVersion
-    type = platformType
-    downloadSources = platformDownloadSources.toBoolean()
-    updateSinceUntilBuild = true
+    pluginName.set(properties("pluginName"))
+    version.set(properties("platformVersion"))
+    type.set(properties("platformType"))
+    downloadSources.set(properties("platformDownloadSources").toBoolean())
+    updateSinceUntilBuild.set(true)
 
     // Plugin Dependencies. Uses `platformPlugins` property from the gradle.properties file.
-    setPlugins("java")
+    plugins.set(properties("platformPlugins").split(',').map(String::trim).filter(String::isNotEmpty))
 }
 
 sourceSets {
@@ -68,20 +65,24 @@ sourceSets {
     }
 }
 
-idea {
-    module {
-        generatedSourceDirs.add(file("src/gen/java"))
-    }
+// Configure gradle-changelog-plugin plugin.
+// Read more: https://github.com/JetBrains/gradle-changelog-plugin
+changelog {
+    version = properties("pluginVersion")
+    groups = emptyList()
 }
 
-//import org.jetbrains.grammarkit.tasks.*
-//
-grammarKit {
-    // version of IntelliJ patched JFlex (see bintray link below), Default is 1.7.0-1
-    jflexRelease = "1.7.0-1"
+// Configure detekt plugin.
+// Read more: https://detekt.github.io/detekt/kotlindsl.html
+detekt {
+    config = files("./detekt-config.yml")
+    buildUponDefaultConfig = true
 
-    // tag or short commit hash of Grammar-Kit to use (see link below). Default is 2020.3.1
-    grammarKitRelease = "2020.3.1"
+    reports {
+        html.enabled = false
+        xml.enabled = false
+        txt.enabled = false
+    }
 }
 
 tasks {
@@ -126,59 +127,51 @@ tasks {
         dependsOn(generateAspectParser)
     }
 
+    // Set the compatibility versions to 1.8
     withType<JavaCompile> {
-        sourceCompatibility = "11" // "1.8"
-        targetCompatibility = "11" // "1.8"
+        sourceCompatibility = "1.8"
+        targetCompatibility = "1.8"
     }
-
-    runIde {
-        jvmArgs("--add-exports", "java.base/jdk.internal.vm=ALL-UNNAMED")
+    withType<KotlinCompile> {
+        kotlinOptions.jvmTarget = "1.8"
     }
 
-    buildSearchableOptions {
-        jvmArgs("--add-exports", "java.base/jdk.internal.vm=ALL-UNNAMED")
-        enabled = false // see https://youtrack.jetbrains.com/issue/KTIJ-782
+    withType<Detekt> {
+        jvmTarget = "1.8"
     }
 
     patchPluginXml {
-
-        version(pluginVersion)
-        setSinceBuild(pluginSinceBuild)
-        untilBuild(pluginUntilBuild)
+        version.set(properties("pluginVersion"))
+        sinceBuild.set(properties("pluginSinceBuild"))
+        untilBuild.set(properties("pluginUntilBuild"))
 
         // Extract the <!-- Plugin description --> section from README.md and provide for the plugin's manifest
-        pluginDescription(
-            closure {
-                File("./README.md").readText().lines().run {
-                    val start = "<!-- Plugin description -->"
-                    val end = "<!-- Plugin description end -->"
-
-                    if (!containsAll(listOf(start, end))) {
-                        throw GradleException("Plugin description section not found in README.md:\n$start ... $end")
-                    }
-                    subList(indexOf(start) + 1, indexOf(end))
-                }.joinToString("\n").run { markdownToHTML(this) }
-            }
+        pluginDescription.set(
+            File(projectDir, "README.md").readText().lines().run {
+                val start = "<!-- Plugin description -->"
+                val end = "<!-- Plugin description end -->"
+
+                if (!containsAll(listOf(start, end))) {
+                    throw GradleException("Plugin description section not found in README.md:\n$start ... $end")
+                }
+                subList(indexOf(start) + 1, indexOf(end))
+            }.joinToString("\n").run { markdownToHTML(this) }
         )
 
         // Get the latest available change notes from the changelog file
-        changeNotes(
-            closure {
-                changelog.getLatest().toHTML()
-            }
-        )
+        changeNotes.set(provider { changelog.getLatest().toHTML() })
     }
 
     runPluginVerifier {
-        ideVersions(pluginVerifierIdeVersions)
+        ideVersions.set(properties("pluginVerifierIdeVersions").split(',').map(String::trim).filter(String::isNotEmpty))
     }
 
     publishPlugin {
         dependsOn("patchChangelog")
-        token(System.getenv("PUBLISH_TOKEN"))
+        token.set(System.getenv("PUBLISH_TOKEN"))
         // pluginVersion is based on the SemVer (https://semver.org) and supports pre-release labels, like 2.1.7-alpha.3
         // Specify pre-release label to publish the plugin in a custom Release Channel automatically. Read more:
-        // https://jetbrains.org/intellij/sdk/docs/tutorials/build_system/deployment.html#specifying-a-release-channel
-        channels(pluginVersion.split('-').getOrElse(1) { "default" }.split('.').first())
+        // https://plugins.jetbrains.com/docs/intellij/deployment.html#specifying-a-release-channel
+        channels.set(listOf(properties("pluginVersion").split('-').getOrElse(1) { "default" }.split('.').first()))
     }
 }
diff --git a/detect-config.yml b/detect-config.yml
new file mode 100644
index 0000000000000000000000000000000000000000..874b29a3babcdeedc0e1a1762d8e8c71734ec90f
--- /dev/null
+++ b/detect-config.yml
@@ -0,0 +1,8 @@
+# Default detekt configuration:
+# https://github.com/detekt/detekt/blob/master/detekt-core/src/main/resources/default-detekt-config.yml
+
+formatting:
+    Indentation:
+        continuationIndentSize: 8
+    ParameterListWrapping:
+        indentSize: 8
diff --git a/gradle.properties b/gradle.properties
index 98ab0196494bc73724234c44127c9080ec1143af..19460023251dd6ea417b96cbe01183702a969fe4 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,22 +1,27 @@
 # IntelliJ Platform Artifacts Repositories
-# -> https://www.jetbrains.org/intellij/sdk/docs/reference_guide/intellij_artifacts.html
+# -> https://plugins.jetbrains.com/docs/intellij/intellij-artifacts.html
+
+pluginGroup = org.jetbrains.plugins.template
+pluginName = IntelliJ Platform Plugin Template
+pluginVersion = 0.10.1
+
+# See https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
+# for insight into build numbers and IntelliJ Platform versions.
+pluginSinceBuild = 202
+pluginUntilBuild = 211.*
 
-pluginGroup = org.jastadd
-pluginName_ = JastAddGrammar
-pluginVersion = 0.1.0
-pluginSinceBuild = 201
-pluginUntilBuild = 203.*
 # Plugin Verifier integration -> https://github.com/JetBrains/gradle-intellij-plugin#plugin-verifier-dsl
-# See https://jb.gg/intellij-platform-builds-list for available build versions
-pluginVerifierIdeVersions = 2020.3.2
+# See https://jb.gg/intellij-platform-builds-list for available build versions.
+pluginVerifierIdeVersions = 2020.2.4, 2020.3.4, 2021.1.1
 
 platformType = IC
-platformVersion = 2020.3.2
+platformVersion = 2020.2.4
 platformDownloadSources = true
-# Plugin Dependencies -> https://www.jetbrains.org/intellij/sdk/docs/basics/plugin_structure/plugin_dependencies.html
+
+# Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html
 # Example: platformPlugins = com.intellij.java, com.jetbrains.php:203.4449.22
-platformPlugins = com.intellij.modules.java
+platformPlugins = com.intellij.java
 
 # Opt-out flag for bundling Kotlin standard library.
-# See https://kotlinlang.org/docs/reference/using-gradle.html#dependency-on-the-standard-library for details.
+# See https://plugins.jetbrains.com/docs/intellij/kotlin.html#kotlin-standard-library for details.
 kotlin.stdlib.default.dependency = false
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000000000000000000000000000000000000..62d4c053550b91381bbd28b1afc82d634bf73a8a
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/src/main/java/org/jastadd/tooling/grammar/GrammarCompletionContributor.java b/src/main/java/org/jastadd/tooling/grammar/GrammarCompletionContributor.java
index 86de3833f8575b8671122acd4cec7032db2adf42..d99a87af62575e278205a8ee3009f5a8ea3e2804 100644
--- a/src/main/java/org/jastadd/tooling/grammar/GrammarCompletionContributor.java
+++ b/src/main/java/org/jastadd/tooling/grammar/GrammarCompletionContributor.java
@@ -19,7 +19,7 @@ public class GrammarCompletionContributor extends CompletionContributor {
 
     // add completion in definition of relations
     extend(CompletionType.BASIC, PlatformPatterns.psiElement(GrammarTypes.ID).afterLeaf("rel", "<->", "->", "<-"),
-      new CompletionProvider<>() {
+      new CompletionProvider<CompletionParameters>() {
         public void addCompletions(@NotNull CompletionParameters parameters,
                                    @NotNull ProcessingContext context,
                                    @NotNull CompletionResultSet resultSet) {
@@ -37,7 +37,7 @@ public class GrammarCompletionContributor extends CompletionContributor {
         .afterLeaf(".")
         .afterLeaf(PlatformPatterns.psiElement().afterLeaf(PlatformPatterns.psiElement(GrammarTypes.ID)))
         .afterLeaf(PlatformPatterns.psiElement().afterLeaf(PlatformPatterns.psiElement().afterLeaf("rel"))),
-      new CompletionProvider<>() {
+      new CompletionProvider<CompletionParameters>() {
         public void addCompletions(@NotNull CompletionParameters parameters,
                                    @NotNull ProcessingContext context,
                                    @NotNull CompletionResultSet resultSet) {
@@ -54,7 +54,7 @@ public class GrammarCompletionContributor extends CompletionContributor {
         .afterLeaf(".")
         .afterLeaf(PlatformPatterns.psiElement().afterLeaf(PlatformPatterns.psiElement(GrammarTypes.ID)))
         .afterLeaf(PlatformPatterns.psiElement().afterLeaf(PlatformPatterns.psiElement().afterLeaf("<-", "<->"))),
-      new CompletionProvider<>() {
+      new CompletionProvider<CompletionParameters>() {
         public void addCompletions(@NotNull CompletionParameters parameters,
                                    @NotNull ProcessingContext context,
                                    @NotNull CompletionResultSet resultSet) {
@@ -70,7 +70,7 @@ public class GrammarCompletionContributor extends CompletionContributor {
         .afterLeaf(PlatformPatterns.psiElement().afterLeaf("."))
         .afterLeaf(PlatformPatterns.psiElement().afterLeaf(PlatformPatterns.psiElement().afterLeaf(PlatformPatterns.psiElement(GrammarTypes.ID))))
         .afterLeaf(PlatformPatterns.psiElement().afterLeaf(PlatformPatterns.psiElement().afterLeaf(PlatformPatterns.psiElement().afterLeaf("rel")))),
-      new CompletionProvider<>() {
+      new CompletionProvider<CompletionParameters>() {
         public void addCompletions(@NotNull CompletionParameters parameters,
                                    @NotNull ProcessingContext context,
                                    @NotNull CompletionResultSet resultSet) {
@@ -87,7 +87,7 @@ public class GrammarCompletionContributor extends CompletionContributor {
         .afterLeaf(PlatformPatterns.psiElement().afterLeaf(PlatformPatterns.psiElement().afterLeaf(".")))
         .afterLeaf(PlatformPatterns.psiElement().afterLeaf(PlatformPatterns.psiElement().afterLeaf(PlatformPatterns.psiElement().afterLeaf(PlatformPatterns.psiElement(GrammarTypes.ID)))))
         .afterLeaf(PlatformPatterns.psiElement().afterLeaf(PlatformPatterns.psiElement().afterLeaf(PlatformPatterns.psiElement().afterLeaf(PlatformPatterns.psiElement().afterLeaf("rel"))))),
-      new CompletionProvider<>() {
+      new CompletionProvider<CompletionParameters>() {
         public void addCompletions(@NotNull CompletionParameters parameters,
                                    @NotNull ProcessingContext context,
                                    @NotNull CompletionResultSet resultSet) {
@@ -102,7 +102,7 @@ public class GrammarCompletionContributor extends CompletionContributor {
     extend(CompletionType.BASIC, PlatformPatterns.psiElement(GrammarTypes.ID)
         .withTextLengthLongerThan(COMPLETION_ELEMENT_SUFFIX.length()) // see https://intellij-support.jetbrains.com/hc/en-us/community/posts/206752355-The-dreaded-IntellijIdeaRulezzz-string
         .afterLeaf("rel", "<->", "<-"),
-      new CompletionProvider<>() {
+      new CompletionProvider<CompletionParameters>() {
         public void addCompletions(@NotNull CompletionParameters parameters,
                                    @NotNull ProcessingContext context,
                                    @NotNull CompletionResultSet resultSet) {
@@ -115,7 +115,7 @@ public class GrammarCompletionContributor extends CompletionContributor {
     extend(CompletionType.BASIC, PlatformPatterns.psiElement(GrammarTypes.ID)
         .afterLeaf(PlatformPatterns.psiElement(GrammarTypes.ID))
         .afterLeaf(PlatformPatterns.psiElement().afterLeaf("rel")),
-      new CompletionProvider<>() {
+      new CompletionProvider<CompletionParameters>() {
         public void addCompletions(@NotNull CompletionParameters parameters,
                                    @NotNull ProcessingContext context,
                                    @NotNull CompletionResultSet resultSet) {
diff --git a/src/main/java/org/jastadd/tooling/grammar/GrammarFormattingModelBuilder.java b/src/main/java/org/jastadd/tooling/grammar/GrammarFormattingModelBuilder.java
index e945b6fc3f35edab6b53be3de5806fb18ef02a05..1b5ec3834789aeab5e0e715c6e6144793582b1fb 100644
--- a/src/main/java/org/jastadd/tooling/grammar/GrammarFormattingModelBuilder.java
+++ b/src/main/java/org/jastadd/tooling/grammar/GrammarFormattingModelBuilder.java
@@ -3,6 +3,7 @@ package org.jastadd.tooling.grammar;
 import com.intellij.formatting.*;
 import com.intellij.lang.ASTNode;
 import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiFile;
 import com.intellij.psi.codeStyle.CodeStyleSettings;
 import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
@@ -37,16 +38,15 @@ public class GrammarFormattingModelBuilder implements FormattingModelBuilder {
       .beforeInside(GrammarTypes.SLASH, GrammarTypes.NTA_COMPONENT).none();
   }
 
-  @NotNull
   @Override
-  public FormattingModel createModel(FormattingContext context) {
+  public @NotNull FormattingModel createModel(PsiElement element, CodeStyleSettings settings) {
     return FormattingModelProvider
-      .createFormattingModelForPsiFile(context.getPsiElement().getContainingFile(),
-        new GrammarBlock(context.getPsiElement().getNode(),
+      .createFormattingModelForPsiFile(element.getContainingFile(),
+        new GrammarBlock(element.getNode(),
           Wrap.createWrap(WrapType.NONE, false),
           Alignment.createAlignment(),
-          createSpaceBuilder(context.getCodeStyleSettings())),
-        context.getCodeStyleSettings());
+          createSpaceBuilder(settings)),
+        settings);
   }
 
   @Nullable