diff --git a/.github/workflows/runUiOctopusTests.yml b/.github/workflows/runUiOctopusTests.yml index 65314d0fc..65576aef1 100644 --- a/.github/workflows/runUiOctopusTests.yml +++ b/.github/workflows/runUiOctopusTests.yml @@ -23,7 +23,7 @@ jobs: - name: Run Idea run: | mkdir -p build/reports - gradle runIdeForUiTests -Doctopus.handler=false > build/reports/idea.log & + gradle testIdeUi -Doctopus.handler=false > build/reports/idea.log & - name: Wait for Idea started uses: jtalk/url-health-check-action@v3 with: @@ -63,7 +63,7 @@ jobs: # export DISPLAY=:99.0 # Xvfb -ac :99 -screen 0 1920x1080x16 & # mkdir -p build/reports -# gradle :runIdeForUiTests #> build/reports/idea.log +# gradle :testIdeUi #> build/reports/idea.log # - name: Wait for Idea started # uses: jtalk/url-health-check-action@1.5 # with: @@ -78,4 +78,4 @@ jobs: # with: # name: ui-test-fails-report-linux # path: | -# ui-test-example/build/reports \ No newline at end of file +# ui-test-example/build/reports diff --git a/.github/workflows/runUiPyTests.yml b/.github/workflows/runUiPyTests.yml index e67bd9fd3..2ac837779 100644 --- a/.github/workflows/runUiPyTests.yml +++ b/.github/workflows/runUiPyTests.yml @@ -26,7 +26,7 @@ jobs: - name: Run Idea run: | mkdir -p build/reports - gradle :runIdeForUiTests -PideaType=PC > build/reports/idea.log & + gradle :testIdeUi -PideaType=PC > build/reports/idea.log & - name: Wait for Idea started uses: jtalk/url-health-check-action@v3 with: @@ -49,4 +49,4 @@ jobs: path: | build/reports tests/ui-py-tests/build/reports - sandbox-idea-log \ No newline at end of file + sandbox-idea-log diff --git a/.github/workflows/runUiTests.yml b/.github/workflows/runUiTests.yml index 26f5f1023..9df972b86 100644 --- a/.github/workflows/runUiTests.yml +++ b/.github/workflows/runUiTests.yml @@ -23,7 +23,7 @@ jobs: - name: Run Idea run: | mkdir -p build/reports - gradle runIdeForUiTests > build/reports/idea.log & + gradle testIdeUi > build/reports/idea.log & - name: Wait for Idea started uses: jtalk/url-health-check-action@v3 with: @@ -63,7 +63,7 @@ jobs: # export DISPLAY=:99.0 # Xvfb -ac :99 -screen 0 1920x1080x16 & # mkdir -p build/reports -# gradle :runIdeForUiTests #> build/reports/idea.log +# gradle :testIdeUi #> build/reports/idea.log # - name: Wait for Idea started # uses: jtalk/url-health-check-action@1.5 # with: @@ -78,4 +78,4 @@ jobs: # with: # name: ui-test-fails-report-linux # path: | -# ui-test-example/build/reports \ No newline at end of file +# ui-test-example/build/reports diff --git a/.gitignore b/.gitignore index 50ac91409..85c6f93d2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ *.swp /.gradle/ +/.intellijPlatform/ /.idea/ !/.idea/scopes diff --git a/.idea/runConfigurations/IdeaVim_full_verification.xml b/.idea/runConfigurations/IdeaVim_full_verification.xml index d6b1b41af..9b6ac4c11 100644 --- a/.idea/runConfigurations/IdeaVim_full_verification.xml +++ b/.idea/runConfigurations/IdeaVim_full_verification.xml @@ -12,7 +12,7 @@ <option name="taskNames"> <list> <option value="check" /> - <option value="runPluginVerifier" /> + <option value="verifyPlugin" /> </list> </option> <option name="vmOptions" value="" /> @@ -20,6 +20,7 @@ <ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess> <ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess> <DebugAllEnabled>false</DebugAllEnabled> + <RunAsTest>false</RunAsTest> <method v="2" /> </configuration> </component> \ No newline at end of file diff --git a/.teamcity/_Self/buildTypes/PluginVerifier.kt b/.teamcity/_Self/buildTypes/PluginVerifier.kt index f25fa97c7..9d607db16 100644 --- a/.teamcity/_Self/buildTypes/PluginVerifier.kt +++ b/.teamcity/_Self/buildTypes/PluginVerifier.kt @@ -22,7 +22,7 @@ object PluginVerifier : IdeaVimBuildType({ steps { gradle { - tasks = "clean runPluginVerifier" + tasks = "clean verifyPlugin" buildFile = "" enableStacktrace = true } diff --git a/build.gradle.kts b/build.gradle.kts index aa6ac24bb..70024b739 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -32,6 +32,7 @@ import org.eclipse.jgit.api.Git import org.eclipse.jgit.lib.RepositoryBuilder import org.intellij.markdown.ast.getTextInNode import org.jetbrains.changelog.Changelog +import org.jetbrains.intellij.platform.gradle.TestFrameworkType import org.kohsuke.github.GHUser import java.net.HttpURLConnection import java.net.URL @@ -67,22 +68,20 @@ plugins { kotlin("jvm") version "1.9.22" application id("java-test-fixtures") - - id("org.jetbrains.intellij") version "1.17.3" + id("org.jetbrains.intellij.platform") version "2.0.0-beta7" id("org.jetbrains.changelog") version "2.2.0" - id("org.jetbrains.kotlinx.kover") version "0.6.1" id("com.dorongold.task-tree") version "4.0.0" - id("com.google.devtools.ksp") version "1.9.22-1.0.17" } +val moduleSources by configurations.registering + // Import variables from gradle.properties file val javaVersion: String by project val kotlinVersion: String by project val ideaVersion: String by project val ideaType: String by project -val downloadIdeaSources: String by project val instrumentPluginCode: String by project val remoteRobotVersion: String by project @@ -94,7 +93,9 @@ val youtrackToken: String by project repositories { mavenCentral() - maven { url = uri("https://cache-redirector.jetbrains.com/intellij-dependencies") } + intellijPlatform { + defaultRepositories() + } } dependencies { @@ -105,9 +106,26 @@ dependencies { compileOnly("org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion") compileOnly("org.jetbrains:annotations:24.1.0") - // --------- Test dependencies ---------- + intellijPlatform { + // Note that it is also possible to use local("...") to compile against a locally installed IDE + // E.g. local("/Users/{user}/Applications/IntelliJ IDEA Ultimate.app") + // Or something like: intellijIdeaUltimate(ideaVersion) + create(ideaType, ideaVersion) - testImplementation(testFixtures(project(":"))) + pluginVerifier() + zipSigner() + instrumentationTools() + + testFramework(TestFrameworkType.Platform) + testFramework(TestFrameworkType.JUnit5) + + // AceJump is an optional dependency. We use their SessionManager class to check if it's active + plugin("AceJump", "3.8.11") + } + + moduleSources(project(":vim-engine", "sourcesJarArtifacts")) + + // --------- Test dependencies ---------- testApi("com.squareup.okhttp3:okhttp:4.12.0") @@ -179,15 +197,28 @@ tasks { } } + // Note that this will run the plugin installed in the IDE specified in dependencies. To run in a different IDE, use + // a custom task (see below) runIde { systemProperty("octopus.handler", System.getProperty("octopus.handler") ?: true) } - downloadRobotServerPlugin { - version.set(remoteRobotVersion) - } + // Uncomment to run the plugin in a custom IDE, rather than the IDE specified as a compile target in dependencies + // Note that the version must be greater than the plugin's target version, for obvious reasons +// val runIdeCustom by registering(CustomRunIdeTask::class) { +// type = IntelliJPlatformType.Rider +// version = "2024.1.2" +// } - runIdeForUiTests { + // Uncomment to run the plugin in a locally installed IDE +// val runIdeLocal by registering(CustomRunIdeTask::class) { +// localPath = file("/Users/{user}/Applications/WebStorm.app") +// } + + // Start the default IDE with both IdeaVim and the robot server plugin installed, ready to run a UI test task. The + // robot server plugin is automatically added as a dependency to this task, and Gradle will take care of downloading. + // Note that the CustomTestIdeUiTask can be used to run tests against a different IDE + testIdeUi { systemProperty("robot-server.port", "8082") systemProperty("ide.mac.message.dialogs.as.sheets", "false") systemProperty("jb.privacy.policy.text", "<!--999.999-->") @@ -198,28 +229,21 @@ tasks { } // Add plugin open API sources to the plugin ZIP - val createOpenApiSourceJar by registering(Jar::class) { - // Java sources - from(sourceSets.main.get().java) { - include("**/com/maddyhome/idea/vim/**/*.java") - } - from(project(":vim-engine").sourceSets.main.get().java) { - include("**/com/maddyhome/idea/vim/**/*.java") - } - // Kotlin sources - from(kotlin.sourceSets.main.get().kotlin) { - include("**/com/maddyhome/idea/vim/**/*.kt") - } - from(project(":vim-engine").kotlin.sourceSets.main.get().kotlin) { - include("**/com/maddyhome/idea/vim/**/*.kt") - } + val sourcesJar by registering(Jar::class) { + dependsOn(moduleSources) destinationDirectory.set(layout.buildDirectory.dir("libs")) - archiveClassifier.set("src") + archiveClassifier.set(DocsType.SOURCES) + from(sourceSets.main.map { it.kotlin }) + from(provider { + moduleSources.map { + it.map { jarFile -> zipTree(jarFile) } + } + }) } buildPlugin { - dependsOn(createOpenApiSourceJar) - from(createOpenApiSourceJar) { into("lib/src") } + dependsOn(sourcesJar) + from(sourcesJar) { into("lib/src") } } } @@ -245,44 +269,41 @@ gradle.projectsEvaluated { // --- Intellij plugin -intellij { - version.set(ideaVersion) - type.set(ideaType) - pluginName.set("IdeaVim") +intellijPlatform { + pluginConfiguration { + name = "IdeaVim" + changeNotes.set( + """<a href="https://youtrack.jetbrains.com/issues/VIM?q=State:%20Fixed%20Fix%20versions:%20${version.get()}">Changelog</a>""" + ) - updateSinceUntilBuild.set(false) + ideaVersion { + // Set the since-build value, but leave until-build open ended (default is MAJOR.*) + // Don't forget to update plugin.xml + // TODO: Do we need this to be here *and* in plugin.xml? + sinceBuild.set("241.15989.150") + untilBuild.set(provider { null }) + } + } - downloadSources.set(downloadIdeaSources.toBoolean()) - instrumentCode.set(instrumentPluginCode.toBoolean()) - intellijRepository.set("https://www.jetbrains.com/intellij-repository") - plugins.set(listOf("AceJump:3.8.11")) -} - -tasks { - publishPlugin { + publishing { channels.set(publishChannels.split(",")) token.set(publishToken) } - signPlugin { + signing { certificateChain.set(providers.environmentVariable("CERTIFICATE_CHAIN")) privateKey.set(providers.environmentVariable("PRIVATE_KEY")) password.set(providers.environmentVariable("PRIVATE_KEY_PASSWORD")) } - runPluginVerifier { - downloadDir.set("${project.buildDir}/pluginVerifier/ides") - teamCityOutputFormat.set(true) + verifyPlugin { + teamCityOutputFormat = true + ides { + recommended() + } } - patchPluginXml { - // Don't forget to update plugin.xml - sinceBuild.set("241.15989.150") - - changeNotes.set( - """<a href="https://youtrack.jetbrains.com/issues/VIM?q=State:%20Fixed%20Fix%20versions:%20${version.get()}">Changelog</a>""" - ) - } + instrumentCode.set(instrumentPluginCode.toBoolean()) } ksp { @@ -884,12 +905,12 @@ fun changes(): List<Change> { println("Start changes processing") for (message in messages) { println("Processing '$message'...") - val lowercaseMessage = message.toLowerCase() + val lowercaseMessage = message.lowercase() val regex = "^fix\\((vim-\\d+)\\):".toRegex() val findResult = regex.find(lowercaseMessage) if (findResult != null) { println("Message matches") - val value = findResult.groups[1]!!.value.toUpperCase() + val value = findResult.groups[1]!!.value.uppercase() val shortMessage = message.drop(findResult.range.last + 1).trim() newFixes += Change(value, shortMessage) } else { diff --git a/gradle.properties b/gradle.properties index 9b769d771..1b6f8e933 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,11 +8,20 @@ # suppress inspection "UnusedProperty" for whole file +# ideaVersion is the version of the IDE that we'll add as a dependency. The format of the version string depends on the +# value of the `org.jetbrains.intellij.platform.buildFeature.useBinaryReleases` property/build feature. +# If enabled (default) then the IDE will be a normal, packaged release, which you could install and run like a retail +# version of the IDE, downloaded from CDN. The `ideaVersion` property should be a marketing version such as `2024.1` or +# `2024.1.1` (note no trailing `0`). You can find an example list of all versions for IDEA Community here: +# https://data.services.jetbrains.com/products?code=IC +# If the build feature is disabled, the IDE will be downloaded from Maven, and should match the format published in +# Maven, such as `2024.1` (again, no trailing `.0`), `2024.1.1`, `241-EAP-SNAPSHOT`, etc. +# You can see a list of release versions here: https://www.jetbrains.com/intellij-repository/releases +# And a list of snapshot versions here: https://www.jetbrains.com/intellij-repository/snapshots #ideaVersion=LATEST-EAP-SNAPSHOT ideaVersion=2024.1.1 # Values for type: https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#intellij-extension-type ideaType=IC -downloadIdeaSources=true instrumentPluginCode=true version=SNAPSHOT javaVersion=17 @@ -40,4 +49,12 @@ org.gradle.jvmargs='-Dfile.encoding=UTF-8' kotlin.stdlib.default.dependency=false # Disable incremental annotation processing -ksp.incremental=false \ No newline at end of file +ksp.incremental=false + +# Build features +# Temporarily disable downloading the IDE dependency from CDN, and use Maven The Plugin DevKit plugin is currently +# unable to download sources when the IDE is packaged as a normal binary release. This only affects developers working +# with and debugging IdeaVim. Once the fixed version of DevKit is available, IdeaVim developers can update and this flag +# can be removed. +# DevKit will be fixed in IDEA 2024.1.4 and a future EAP of 2024.2 +org.jetbrains.intellij.platform.buildFeature.useBinaryReleases=false diff --git a/tests/java-tests/build.gradle.kts b/tests/java-tests/build.gradle.kts index 0e8f29b89..47287a832 100644 --- a/tests/java-tests/build.gradle.kts +++ b/tests/java-tests/build.gradle.kts @@ -1,3 +1,5 @@ +import org.jetbrains.intellij.platform.gradle.TestFrameworkType + /* * Copyright 2003-2024 The IdeaVim authors * @@ -9,16 +11,20 @@ plugins { id("java") kotlin("jvm") - id("org.jetbrains.intellij") + id("org.jetbrains.intellij.platform.module") } val kotlinVersion: String by project +val ideaType: String by project val ideaVersion: String by project val javaVersion: String by project repositories { mavenCentral() - maven { url = uri("https://cache-redirector.jetbrains.com/intellij-dependencies") } + + intellijPlatform { + defaultRepositories() + } } dependencies { @@ -26,35 +32,24 @@ dependencies { compileOnly("org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion") testImplementation("org.jetbrains.kotlin:kotlin-test:$kotlinVersion") testImplementation(testFixtures(project(":"))) // The root project + + intellijPlatform { + create(ideaType, ideaVersion) + testFramework(TestFrameworkType.Platform) + testFramework(TestFrameworkType.JUnit5) + bundledPlugins("com.intellij.java", "org.jetbrains.plugins.yaml") + instrumentationTools() + } +} + +intellijPlatform { + buildSearchableOptions = false } tasks { test { useJUnitPlatform() } - - verifyPlugin { - enabled = false - } - - publishPlugin { - enabled = false - } - - runIde { - enabled = false - } - - runPluginVerifier { - enabled = false - } -} - -intellij { - version.set(ideaVersion) - type.set("IC") - // Yaml is only used for testing. It's part of the IdeaIC distribution, but needs to be included as a reference - plugins.set(listOf("java", "yaml")) } java { diff --git a/tests/long-running-tests/build.gradle.kts b/tests/long-running-tests/build.gradle.kts index a8d726b33..6b5962fea 100644 --- a/tests/long-running-tests/build.gradle.kts +++ b/tests/long-running-tests/build.gradle.kts @@ -1,15 +1,23 @@ +import org.jetbrains.intellij.platform.gradle.TestFrameworkType +import org.jetbrains.intellij.platform.gradle.extensions.intellijPlatform +import org.jetbrains.intellij.platform.gradle.tasks.CustomTestIdeTask + plugins { java kotlin("jvm") - id("org.jetbrains.intellij") + id("org.jetbrains.intellij.platform.module") } repositories { mavenCentral() - maven { url = uri("https://cache-redirector.jetbrains.com/intellij-dependencies") } + + intellijPlatform { + defaultRepositories() + } } val kotlinVersion: String by project +val ideaType: String by project val ideaVersion: String by project val javaVersion: String by project @@ -18,42 +26,32 @@ dependencies { compileOnly("org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion") testImplementation("org.jetbrains.kotlin:kotlin-test:$kotlinVersion") testImplementation(testFixtures(project(":"))) // The root project + + intellijPlatform { + create(ideaType, ideaVersion) + testFramework(TestFrameworkType.Platform) + testFramework(TestFrameworkType.JUnit5) + instrumentationTools() + } +} + +intellijPlatform { + buildSearchableOptions = false } tasks { // This task is disabled because it should be excluded from `gradle test` run (because it's slow) // I didn't find a better way to exclude except disabling and defining a new task with a different name + // Note that useJUnitTestPlatform() is required to prevent red code test { enabled = false useJUnitPlatform() } - register<Test>("testLongRunning") { + register<CustomTestIdeTask>("testLongRunning") { group = "verification" useJUnitPlatform() } - - verifyPlugin { - enabled = false - } - - publishPlugin { - enabled = false - } - - runIde { - enabled = false - } - - runPluginVerifier { - enabled = false - } -} - -intellij { - version.set(ideaVersion) - type.set("IC") - plugins.set(listOf("java")) } java { diff --git a/tests/property-tests/build.gradle.kts b/tests/property-tests/build.gradle.kts index 7fcbd7767..cd4bf458b 100644 --- a/tests/property-tests/build.gradle.kts +++ b/tests/property-tests/build.gradle.kts @@ -1,15 +1,23 @@ +import org.jetbrains.intellij.platform.gradle.TestFrameworkType +import org.jetbrains.intellij.platform.gradle.extensions.intellijPlatform +import org.jetbrains.intellij.platform.gradle.tasks.CustomTestIdeTask + plugins { java kotlin("jvm") - id("org.jetbrains.intellij") + id("org.jetbrains.intellij.platform.module") } repositories { mavenCentral() - maven { url = uri("https://cache-redirector.jetbrains.com/intellij-dependencies") } + + intellijPlatform { + defaultRepositories() + } } val kotlinVersion: String by project +val ideaType: String by project val ideaVersion: String by project val javaVersion: String by project @@ -18,6 +26,18 @@ dependencies { compileOnly("org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion") testImplementation("org.jetbrains.kotlin:kotlin-test:$kotlinVersion") testImplementation(testFixtures(project(":"))) // The root project + + intellijPlatform { + create(ideaType, ideaVersion) + bundledPlugins("com.intellij.java") + testFramework(TestFrameworkType.Platform) + testFramework(TestFrameworkType.JUnit5) + instrumentationTools() + } +} + +intellijPlatform { + buildSearchableOptions = false } tasks { @@ -28,32 +48,10 @@ tasks { enabled = false } - register<Test>("testPropertyBased") { + register<CustomTestIdeTask>("testPropertyBased") { group = "verification" useJUnitPlatform() } - - verifyPlugin { - enabled = false - } - - publishPlugin { - enabled = false - } - - runIde { - enabled = false - } - - runPluginVerifier { - enabled = false - } -} - -intellij { - version.set(ideaVersion) - type.set("IC") - plugins.set(listOf("java")) } java { diff --git a/vim-engine/build.gradle.kts b/vim-engine/build.gradle.kts index 9af976fa1..f5284e33f 100644 --- a/vim-engine/build.gradle.kts +++ b/vim-engine/build.gradle.kts @@ -16,6 +16,12 @@ plugins { antlr } +val sourcesJarArtifacts by configurations.registering { + attributes { + attribute(DocsType.DOCS_TYPE_ATTRIBUTE, objects.named(DocsType.SOURCES)) + } +} + val kotlinVersion: String by project val kotlinxSerializationVersion: String by project @@ -99,6 +105,8 @@ java { withJavadocJar() } +artifacts.add(sourcesJarArtifacts.name, tasks.named("sourcesJar")) + val spaceUsername: String by project val spacePassword: String by project val engineVersion: String by project @@ -122,4 +130,4 @@ publishing { } } } -} \ No newline at end of file +}