plugins/toolkit/jetbrains-rider/build.gradle.kts (306 lines of code) (raw):

// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 import com.jetbrains.rd.generator.gradle.RdGenExtension import com.jetbrains.rd.generator.gradle.RdGenPlugin import com.jetbrains.rd.generator.gradle.RdGenTask import io.gitlab.arturbosch.detekt.Detekt import io.gitlab.arturbosch.detekt.DetektCreateBaselineTask import org.jetbrains.intellij.platform.gradle.TestFrameworkType import org.jetbrains.intellij.platform.gradle.tasks.PrepareSandboxTask import org.jetbrains.kotlin.com.intellij.openapi.util.SystemInfo import software.aws.toolkits.gradle.intellij.IdeFlavor import software.aws.toolkits.gradle.intellij.IdeVersions import java.nio.file.Path buildscript { // Cannot be removed or else it will fail to compile @Suppress("RemoveRedundantQualifierName") val rdversion = software.aws.toolkits.gradle.intellij.IdeVersions.ideProfile(project).rider.rdGenVersion println("Using rd-gen: $rdversion") dependencies { if (rdversion.contains("pre")) { classpath(fileTree("bin/$rdversion")) } else { classpath("com.jetbrains.rd:rd-gen:$rdversion") } } } val ideProfile = IdeVersions.ideProfile(project) plugins { id("toolkit-kotlin-conventions") id("toolkit-testing") id("toolkit-intellij-subplugin") id("toolkit-integration-testing") } intellijToolkit { ideFlavor.set(IdeFlavor.RD) } sourceSets { main { java.srcDirs(layout.buildDirectory.dir("generated-src")) } } // FIX_WHEN_MIN_IS_251 // org.gradle.internal.resolve.ModuleVersionNotFoundException: // Could not find any version that matches com.jetbrains.intellij.platform:test-framework:{strictly [243, 243.21565.192]; prefer 243.21565.192}. if (providers.gradleProperty("ideProfileName").get() == "2024.3") { configurations.all { resolutionStrategy.dependencySubstitution { listOf( "com.jetbrains.intellij.java:java-test-framework", "com.jetbrains.intellij.platform:test-framework", "com.jetbrains.intellij.platform:test-framework-junit5" ).forEach { substitute(module(it)) .using(module("$it:243.21565.193")) .because("Rider 2024.3.0 requires a newer version of test-framework") } } } } dependencies { intellijPlatform { localPlugin(project(":plugin-core")) testFramework(TestFrameworkType.Bundled) // FIX_WHEN_MIN_IS_251: https://github.com/JetBrains/intellij-platform-gradle-plugin/issues/1774 when (providers.gradleProperty("ideProfileName").get()) { "2024.2", "2024.3", "2025.1" -> { bundledModule("intellij.rider") } } } implementation(project(":plugin-toolkit:jetbrains-core")) testImplementation(project(path = ":plugin-toolkit:jetbrains-core", configuration = "testArtifacts")) testImplementation(testFixtures(project(":plugin-core:jetbrains-community"))) } /** * RESHARPER */ // Not published to gradle plugin portal, use old syntax apply<RdGenPlugin>() tasks.register<RdGenTask>("generateModels") val resharperPluginPath = File(projectDir, "ReSharper.AWS") val resharperBuildPath = File(project.buildDir, "dotnetBuild") val resharperParts = listOf( "AWS.Daemon", "AWS.Localization", "AWS.Project", "AWS.Psi", "AWS.Settings" ) val buildConfiguration = project.extra.properties["BuildConfiguration"] ?: "Debug" // TODO: Do we ever want to make a release build? // Protocol val protocolGroup = "protocol" // gradle recommends keeping this lazy as long as possible https://docs.gradle.org/current/userguide/upgrading_version_8.html#project_builddir val nonLazyBuildDir = layout.buildDirectory.get().asFile val csDaemonGeneratedOutput = File(resharperPluginPath, "src/AWS.Daemon/Protocol") val csPsiGeneratedOutput = File(resharperPluginPath, "src/AWS.Psi/Protocol") val csAwsSettingsGeneratedOutput = File(resharperPluginPath, "src/AWS.Settings/Protocol") val csAwsProjectGeneratedOutput = File(resharperPluginPath, "src/AWS.Project/Protocol") val riderGeneratedSources = File("$nonLazyBuildDir/generated-src/software/aws/toolkits/jetbrains/protocol") val modelDir = File(projectDir, "protocol/model") val rdgenDir = File("$nonLazyBuildDir/rdgen/") rdgenDir.mkdirs() // https://github.com/JetBrains/resharper-unity/blob/master/rider/build.gradle.kts val rdLibDirectory: () -> File = { file(intellijPlatform.platformPath.resolve("lib/rd/")) } val rdModelJarFile: File by lazy { val jarFile = File(rdLibDirectory(), "rider-model.jar").canonicalFile assert(jarFile.isFile) return@lazy jarFile } configure<RdGenExtension> { verbose = true hashFolder = rdgenDir.toString() classpath({ rdModelJarFile }) sources(projectDir.resolve("protocol/model")) packages = "model" } // TODO: migrate to official rdgen gradle plugin https://www.jetbrains.com/help/resharper/sdk/Rider.html#plugin-project-jvm val generateModels = tasks.named<JavaExec>("generateModels") { group = protocolGroup description = "Generates protocol models" inputs.dir(file("protocol/model")) outputs.dir(riderGeneratedSources) outputs.dir(csDaemonGeneratedOutput) outputs.dir(csPsiGeneratedOutput) outputs.dir(csAwsSettingsGeneratedOutput) outputs.dir(csAwsProjectGeneratedOutput) systemProperty("ktDaemonGeneratedOutput", riderGeneratedSources.resolve("DaemonProtocol").absolutePath) systemProperty("csDaemonGeneratedOutput", csDaemonGeneratedOutput.absolutePath) systemProperty("ktPsiGeneratedOutput", riderGeneratedSources.resolve("PsiProtocol").absolutePath) systemProperty("csPsiGeneratedOutput", csPsiGeneratedOutput.absolutePath) systemProperty("ktAwsSettingsGeneratedOutput", riderGeneratedSources.resolve("AwsSettingsProtocol").absolutePath) systemProperty("csAwsSettingsGeneratedOutput", csAwsSettingsGeneratedOutput.absolutePath) systemProperty("ktAwsProjectGeneratedOutput", riderGeneratedSources.resolve("AwsProjectProtocol").absolutePath) systemProperty("csAwsProjectGeneratedOutput", csAwsProjectGeneratedOutput.absolutePath) } val cleanGenerateModels = tasks.register<Delete>("cleanGenerateModels") { group = protocolGroup description = "Clean up generated protocol models" delete(generateModels) } // Backend val backendGroup = "backend" val codeArtifactNugetUrl: Provider<String> = providers.environmentVariable("CODEARTIFACT_NUGET_URL") val prepareBuildProps = tasks.register("prepareBuildProps") { val riderSdkVersionPropsPath = File(resharperPluginPath, "RiderSdkPackageVersion.props") group = backendGroup inputs.property("riderNugetSdkVersion", ideProfile.rider.nugetVersion) outputs.file(riderSdkVersionPropsPath) doLast { val netFrameworkTarget = ideProfile.rider.netFrameworkTarget val riderSdkVersion = ideProfile.rider.nugetVersion val configText = """<Project> <PropertyGroup> <NetFrameworkTarget>$netFrameworkTarget</NetFrameworkTarget> <RiderSDKVersion>[$riderSdkVersion]</RiderSDKVersion> <DefineConstants>PROFILE_${ideProfile.name.replace(".", "_")}</DefineConstants> </PropertyGroup> </Project> """ riderSdkVersionPropsPath.writeText(configText) } } val prepareNuGetConfig = tasks.register("prepareNuGetConfig") { group = backendGroup val nugetConfigPath = File(projectDir, "NuGet.Config") // FIX_WHEN_MIN_IS_211 remove the projectDir one above val nugetConfigPath211 = Path.of(projectDir.absolutePath, "testData", "NuGet.config").toFile() inputs.property("rdVersion", ideProfile.rider.sdkVersion) outputs.files(nugetConfigPath, nugetConfigPath211) doLast { val nugetPath = getNugetPackagesPath() val codeArtifactConfigText = """<?xml version="1.0" encoding="utf-8"?> <configuration> <packageSources> ${ if (codeArtifactNugetUrl.isPresent) { """ | <clear /> | <add key="codeartifact-nuget" value="${codeArtifactNugetUrl.get()}v3/index.json" /> """.trimMargin("|") } else { "" } } </packageSources> </configuration> """ val configText = """<?xml version="1.0" encoding="utf-8"?> <configuration> <packageSources> <add key="resharper-sdk" value="$nugetPath" /> </packageSources> </configuration> """ nugetConfigPath.writeText(codeArtifactConfigText) nugetConfigPath211.writeText(configText) } } val buildReSharperPlugin = tasks.register("buildReSharperPlugin") { group = backendGroup description = "Builds the full ReSharper backend plugin solution" dependsOn(generateModels, prepareBuildProps, prepareNuGetConfig) inputs.dir(resharperPluginPath) outputs.dir(resharperBuildPath) doLast { val arguments = listOf( "build", "--verbosity", "normal", "${resharperPluginPath.canonicalPath}/ReSharper.AWS.sln" ) exec { executable = "dotnet" args = arguments } } } fun getNugetPackagesPath(): File { val sdkPath = intellijPlatform.platformPath println("SDK path: $sdkPath") val riderSdk = sdkPath.resolve("lib").resolve("DotNetSdkForRdPlugins").toAbsolutePath().toFile() println("NuGet packages: $riderSdk") if (!riderSdk.isDirectory) error("$riderSdk does not exist or not a directory") return riderSdk } val resharperDlls = configurations.create("resharperDlls") { isCanBeResolved = false } val resharperDllsDir = tasks.register<Sync>("resharperDllsDir") { from(buildReSharperPlugin) { include("**/bin/**/$buildConfiguration/**/AWS*.dll") include("**/bin/**/$buildConfiguration/**/AWS*.pdb") // TODO: see if there is better way to do this exclude("**/AWSSDK*") } into("$nonLazyBuildDir/$name") includeEmptyDirs = false eachFile { path = name // Clear out the path to flatten it } // TODO how is this being called twice? Can we fix it? duplicatesStrategy = DuplicatesStrategy.INCLUDE } artifacts { add(resharperDlls.name, resharperDllsDir) } val cleanNetBuilds = tasks.register<Delete>("cleanNetBuilds") { group = protocolGroup description = "Clean up obj/ bin/ folders under ReSharper.AWS" delete(resharperBuildPath) } tasks.clean { dependsOn(cleanGenerateModels, cleanNetBuilds) } // Tasks: // // `buildPlugin` depends on `prepareSandbox` task and then zips up the sandbox dir and puts the file in rider/build/distributions // `runIde` depends on `prepareSandbox` task and then executes IJ inside the sandbox dir // `prepareSandbox` depends on the standard Java `jar` and then copies everything into the sandbox dir intellijPlatform { // kotlin and .NET parts of the plugin need to be in the same plugin base directroy projectName = "aws-toolkit-jetbrains" } tasks.withType<PrepareSandboxTask>().configureEach { // com.jetbrains.rd.platform.diagnostics.BackendException: // There is more than one package with the same ID JetBrains.Platform.UIInteractive.Common in the current deployed packages list. // An item with the same key has already been added. Key: JetBrains.Platform.UIInteractive.Common disabledPlugins.add("com.jetbrains.dotTrace.dotMemory") dependsOn(resharperDllsDir) intoChild(intellijPlatform.projectName.map { "$it/dotnet" }) .from(resharperDllsDir) } tasks.compileKotlin { dependsOn(generateModels) } tasks.withType<Detekt>().configureEach { // Make sure kotlin code is generated before we execute detekt dependsOn(generateModels) } tasks.integrationTest { // linux: computeSystemScaleFactor "Must be precomputed" systemProperty("hidpi", false) } tasks.test { if (SystemInfo.isWindows) { // extremely flaky filter.excludeTestsMatching("software.aws.toolkits.jetbrains.services.lambda.dotnet.LambdaGutterMarkHighlightingTest*") } // On Windows, complains that the computeSystemScaleFactor "Must be precomputed" systemProperty("hidpi", false) useTestNG() environment("LOCAL_ENV_RUN", true) maxHeapSize = "1024m" } tasks.integrationTest { useTestNG() environment("LOCAL_ENV_RUN", true) maxHeapSize = "1024m" // test detection is broken for tests inheriting from JB test framework: https://youtrack.jetbrains.com/issue/IDEA-278926 setScanForTestClasses(false) include("**/*Test.class") } // https://youtrack.jetbrains.com/issue/IJPL-180442 tasks.withType<Test>().configureEach { classpath -= classpath.filter { (it.name.startsWith("localization-") && it.name.endsWith(".jar")) || it.name == "cwm-plugin.jar" } } // fix implicit dependency on generated source tasks.withType<DetektCreateBaselineTask>().configureEach { dependsOn(generateModels) } configurations.all { if (name.contains("detekt") || name.contains("kotlinCompiler") || name.contains("rdGen")) { return@all } // test runner not happy with coroutines, but not clear where it's coming from: // java.lang.Throwable: Thread context was already set: InstalledThreadContext(snapshot=null, context=EmptyCoroutineContext). // Most likely, you are using 'runBlocking' instead of 'runBlockingCancellable' somewhere in the asynchronous stack. exclude("org.jetbrains.kotlinx") }