diff --git a/.gitignore b/.gitignore index ab7acc07..c203ba4d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ # Build artifacts +/.intellijPlatform/ [Bb]in/ [Oo]bj/ build diff --git a/.idea/.name b/.idea/.name deleted file mode 100644 index 7b1d1701..00000000 --- a/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -riderefcore \ No newline at end of file diff --git a/.idea/dictionaries/mfilippov.xml b/.idea/dictionaries/mfilippov.xml new file mode 100644 index 00000000..1b94a898 --- /dev/null +++ b/.idea/dictionaries/mfilippov.xml @@ -0,0 +1,13 @@ + + + + dfus + didea + efcore + filippov + pregenerated + rdgen + xopt + + + \ No newline at end of file diff --git a/README.md b/README.md index 11a493fa..c4418df0 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,6 @@ This plugin introduces Entity Framework Core commands' UI inside JetBrains Rider. JetBrains Official - Version Build @@ -58,9 +57,6 @@ More about features and available dialogs you could read in [**the blog post**]( Before opening the issue, please make sure that your projects and development environment completely satisfies these requirements: -- IDE - - JetBrains Rider **2023.3+ or latest EAP** - - Target frameworks - `net8.0` (preview) - `net7.0` diff --git a/build.gradle.kts b/build.gradle.kts index 9b9c32f6..f2ae1724 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,65 +1,57 @@ @file:Suppress("HardCodedStringLiteral") +import com.jetbrains.plugin.structure.base.utils.isFile import org.jetbrains.changelog.exceptions.MissingVersionException +import org.jetbrains.intellij.platform.gradle.Constants +import org.jetbrains.intellij.platform.gradle.TestFrameworkType +import org.jetbrains.intellij.platform.gradle.tasks.PrepareSandboxTask import kotlin.collections.* - -buildscript { - repositories { - maven { setUrl("https://cache-redirector.jetbrains.com/maven-central") } - } -} +import kotlin.io.path.absolute +import kotlin.io.path.isDirectory repositories { + maven("https://cache-redirector.jetbrains.com/intellij-dependencies") + maven("https://cache-redirector.jetbrains.com/intellij-repository/releases") maven("https://cache-redirector.jetbrains.com/intellij-repository/snapshots") maven("https://cache-redirector.jetbrains.com/maven-central") + intellijPlatform { + defaultRepositories() + jetbrainsRuntime() + } } plugins { - // Version is configured in gradle.properties - id("com.jetbrains.rdgen") - id("me.filippov.gradle.jvm.wrapper") version "0.14.0" - // https://plugins.gradle.org/plugin/org.jetbrains.changelog + id("me.filippov.gradle.jvm.wrapper") id("org.jetbrains.changelog") version "2.2.0" - // https://plugins.gradle.org/plugin/org.jetbrains.intellij - id("org.jetbrains.intellij") version "1.16.0" - id("org.jetbrains.kotlin.jvm") version "1.8.20" -} - -apply { - plugin("com.jetbrains.rdgen") -} - -dependencies { - testImplementation("org.testng:testng:7.7.0") + id("org.jetbrains.intellij.platform") + id("org.jetbrains.kotlin.jvm") } -val riderPluginId: String by project val dotnetPluginId: String by project val productVersion: String by project val pluginVersion: String by project val buildConfiguration = ext.properties["buildConfiguration"] ?: "Debug" +val sinceProductVersion = run { + val yearWithMajor = productVersion.substringBefore("-") + val year = yearWithMajor.substringBefore(".") + val major = yearWithMajor.substringAfter(".") + "${year.substring(2)}$major.0".also { + logger.info("Using since build version: $it") + } +} + +intellijPlatform { + buildSearchableOptions = buildConfiguration == "Release" +} val publishToken: String by project val publishChannel: String by project -val rdLibDirectory: () -> File = { file("${tasks.setupDependencies.get().idea.get().classes}/lib/rd") } -extra["rdLibDirectory"] = rdLibDirectory - val dotNetSrcDir = File(projectDir, "src/dotnet") val nuGetSdkPackagesVersionsFile = File(dotNetSrcDir, "RiderSdk.PackageVersions.Generated.props") val nuGetConfigFile = File(dotNetSrcDir, "nuget.config") -val ktOutputRelativePath = "src/rider/main/kotlin/${riderPluginId.replace('.','/').lowercase()}/rd" - -val productMonorepoDir = getProductMonorepoRoot() -val monorepoPreGeneratedRootDir by lazy { productMonorepoDir?.resolve("dotnet/Plugins/_RiderEfCore.Pregenerated") ?: error("Building not in monorepo") } -val monorepoPreGeneratedFrontendDir by lazy { monorepoPreGeneratedRootDir.resolve("Frontend") } -val monorepoPreGeneratedBackendDir by lazy { monorepoPreGeneratedRootDir.resolve("BackendModel") } -val ktOutputMonorepoRoot by lazy { monorepoPreGeneratedFrontendDir.resolve(ktOutputRelativePath) } - -extra["productMonorepoDir"] = productMonorepoDir - version = pluginVersion fun File.writeTextIfChanged(content: String) { @@ -78,87 +70,61 @@ repositories { sourceSets { main { + kotlin.srcDir("src/rider/generated/kotlin") kotlin.srcDir("src/rider/main/kotlin") resources.srcDir("src/rider/main/resources") } } -apply(plugin = "com.jetbrains.rdgen") - -configure { - val inMonorepo = productMonorepoDir != null - val modelDir = file("$projectDir/protocol/src/main/kotlin/model") - val csOutput = - if (inMonorepo) monorepoPreGeneratedBackendDir - else file("$projectDir/src/dotnet/$dotnetPluginId/Rd") - val ktOutput = - if (inMonorepo) ktOutputMonorepoRoot - else file("$projectDir/$ktOutputRelativePath") - - verbose = true - if (inMonorepo) { - classpath({ - val riderModelClassPathFile: String by project - File(riderModelClassPathFile).readLines() - }) - } else { - classpath({ - "${rdLibDirectory()}/rider-model.jar" - }) - } - sources("$modelDir/rider") - - hashFolder = "$buildDir" - packages = "model.rider" - - generator { - language = "kotlin" - transform = "asis" - root = "com.jetbrains.rider.model.nova.ide.IdeRoot" - namespace = "com.jetbrains.rider.plugins.efcore.model" - directory = "$ktOutput" - if (inMonorepo) generatedFileSuffix = ".Pregenerated" - } +dependencies { + intellijPlatform { + rider(productVersion) + jetbrainsRuntime() + + instrumentationTools() - generator { - language = "csharp" - transform = "reversed" - root = "com.jetbrains.rider.model.nova.ide.IdeRoot" - namespace = "Rider.Plugins.EfCore" - directory = "$csOutput" - if (inMonorepo) generatedFileSuffix = ".Pregenerated" + bundledPlugin("com.intellij.database") + bundledPlugin("org.jetbrains.plugins.terminal") + + testFramework(TestFrameworkType.Bundled) } } -intellij { - type.set("RD") - version.set(productVersion) - downloadSources.set(false) - plugins.set(listOf( - "com.intellij.database", - "terminal" - )) +val riderModel: Configuration by configurations.creating { + isCanBeConsumed = true + isCanBeResolved = false +} + +artifacts { + add(riderModel.name, provider { + intellijPlatform.platformPath.resolve("lib/rd/rider-model.jar").also { + check(it.isFile) { + "rider-model.jar is not found at $riderModel" + } + } + }) { + builtBy(Constants.Tasks.INITIALIZE_INTELLIJ_PLATFORM_PLUGIN) + } } tasks { wrapper { - gradleVersion = "8.2.1" - distributionType = Wrapper.DistributionType.ALL + gradleVersion = "8.7" distributionUrl = "https://cache-redirector.jetbrains.com/services.gradle.org/distributions/gradle-${gradleVersion}-all.zip" } val riderSdkPath by lazy { - val path = setupDependencies.get().idea.get().classes.resolve("lib/DotNetSdkForRdPlugins") - if (!path.isDirectory) error("$path does not exist or not a directory") + val path = intellijPlatform.platformPath.resolve("lib/DotNetSdkForRdPlugins").absolute() + if (!path.isDirectory()) error("$path does not exist or not a directory") println("Rider SDK path: $path") return@lazy path } val prepareRiderBuildProps by registering { - val generatedFile = project.buildDir.resolve("DotNetSdkPath.generated.props") + val generatedFile = layout.buildDirectory.file("DotNetSdkPath.generated.props") - inputs.property("dotNetSdkFile", { riderSdkPath }) + inputs.property("dotNetSdkFile", { riderSdkPath.toString() }) outputs.file(generatedFile) doLast { @@ -187,14 +153,12 @@ tasks { } } - val rdgen by existing - register("prepare") { - dependsOn(rdgen, generateNuGetConfig, prepareRiderBuildProps) + dependsOn(":protocol:rdgen", generateNuGetConfig, prepareRiderBuildProps) } val compileDotNet by registering { - dependsOn(rdgen, generateNuGetConfig, prepareRiderBuildProps) + dependsOn(":protocol:rdgen", generateNuGetConfig, prepareRiderBuildProps) doLast { exec { workingDir(dotNetSrcDir) @@ -220,7 +184,7 @@ tasks { } withType { - dependsOn(rdgen) + dependsOn(":protocol:rdgen") kotlinOptions { jvmTarget = "17" freeCompilerArgs = freeCompilerArgs + "-Xopt-in=kotlin.RequiresOptIn" @@ -228,8 +192,7 @@ tasks { } patchPluginXml { - sinceBuild.set("233.0") - untilBuild.set("233.*") + sinceBuild.set(sinceProductVersion) val latestChangelog = try { changelog.getUnreleased() } catch (_: MissingVersionException) { @@ -249,7 +212,7 @@ tasks { dependsOn(compileDotNet) copy { - from("${buildDir}/distributions/${rootProject.name}-${version}.zip") + from(layout.buildDirectory.file("distributions/${rootProject.name}-${version}.zip")) into("${rootDir}/output") } } @@ -269,7 +232,7 @@ tasks { environment["LOCAL_ENV_RUN"] = "true" } - withType { + withType { dependsOn(compileDotNet) val outputFolder = file("$dotNetSrcDir/$dotnetPluginId/bin/$dotnetPluginId/$buildConfiguration") @@ -296,6 +259,11 @@ tasks { token.set(publishToken) channels.set(listOf(publishChannel)) } + + wrapper { + gradleVersion = "8.7" + distributionUrl = "https://cache-redirector.jetbrains.com/services.gradle.org/distributions/gradle-${gradleVersion}-bin.zip" + } } fun getProductMonorepoRoot(): File? { diff --git a/gradle.properties b/gradle.properties index 77c935d8..4b0bfe76 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,7 +7,10 @@ riderPluginId=com.jetbrains.rider.plugins.efcore # Should be bigger than actual version bundled via snapshot to not break local development pluginVersion=999.0.0-local -rdVersion=2024.1.1 +rdVersion=2024.3-pre2 +rdKotlinVersion=1.9.23 +intellijPlatformGradlePluginVersion=2.0.0-beta8 +gradleJvmWrapperVersion=0.14.0 buildConfiguration=Debug @@ -18,11 +21,11 @@ publishChannel=default # Release: 2020.2 # Nightly: 2020.3-SNAPSHOT # EAP: 2020.3-EAP2-SNAPSHOT -productVersion=2024.2-SNAPSHOT +productVersion=2025.1-SNAPSHOT # Kotlin 1.4 will bundle the stdlib dependency by default, causing problems with the version bundled with the IDE # https://blog.jetbrains.com/kotlin/2020/07/kotlin-1-4-rc-released/#stdlib-default kotlin.stdlib.default.dependency=false -# Fix for Kotlin 1.8.20 uses a new incremental compilation approach that can?t handle large JAR files, resulting in an OutOfMemory exception in the compileKotlin task. -kotlin.incremental.useClasspathSnapshot=false \ No newline at end of file +# Fix for Kotlin 1.8.20 uses a new incremental compilation approach that can't handle large JAR files, resulting in an OutOfMemory exception in the compileKotlin task. +kotlin.incremental.useClasspathSnapshot=false diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index c1962a79..e6441136 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 303d301b..371de143 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://cache-redirector.jetbrains.com/services.gradle.org/distributions/gradle-8.2.1-all.zip +distributionUrl=https\://cache-redirector.jetbrains.com/services.gradle.org/distributions/gradle-8.7-bin.zip networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 9e75d96c..df396029 100755 --- a/gradlew +++ b/gradlew @@ -83,7 +83,8 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -221,10 +222,13 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. @@ -232,7 +236,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -240,7 +244,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -289,11 +293,11 @@ fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/gradlew.bat b/gradlew.bat index f80956a0..8adb7782 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -119,11 +119,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -133,11 +133,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/protocol/build.gradle.kts b/protocol/build.gradle.kts index 9f2dc677..42874014 100644 --- a/protocol/build.gradle.kts +++ b/protocol/build.gradle.kts @@ -1,24 +1,89 @@ +import com.jetbrains.rd.generator.gradle.RdGenTask + plugins { - id("java") + // Version is configured in gradle.properties + id("com.jetbrains.rdgen") id("org.jetbrains.kotlin.jvm") } -val rdLibDirectory: () -> File by rootProject.extra -val productMonorepoDir: File? by rootProject.extra - repositories { - maven { setUrl("https://cache-redirector.jetbrains.com/maven-central") } - if (productMonorepoDir == null) { - flatDir { - dir(rdLibDirectory()) + maven("https://cache-redirector.jetbrains.com/intellij-dependencies") + maven("https://cache-redirector.jetbrains.com/maven-central") +} + +val isMonorepo = rootProject.projectDir != projectDir.parentFile +val efCoreRepoRoot: File = projectDir.parentFile + +sourceSets { + main { + kotlin { + srcDir(efCoreRepoRoot.resolve("protocol/src/main/kotlin/model")) } } } +data class EfCoreGeneratorSettings(val csOutput: File, val ktOutput: File, val suffix: String) + +val ktOutputRelativePath = "src/rider/generated/kotlin/com/jetbrains/rider/plugins/efcore/rd" +val efCoreGeneratorSettings = if (isMonorepo) { + val monorepoRoot = + buildscript.sourceFile?.parentFile?.parentFile?.parentFile?.parentFile?.parentFile ?: error("Cannot find products home") + check(monorepoRoot.resolve(".ultimate.root.marker").isFile) { + error("Incorrect location in monorepo: monorepoRoot='$monorepoRoot'") + } + val monorepoPreGeneratedRootDir = monorepoRoot.resolve("dotnet/Plugins/_RiderEfCore.Pregenerated") + val monorepoPreGeneratedFrontendDir = monorepoPreGeneratedRootDir.resolve("Frontend") + val monorepoPreGeneratedBackendDir = monorepoPreGeneratedRootDir.resolve("BackendModel") + val ktOutputMonorepoRoot = monorepoPreGeneratedFrontendDir.resolve(ktOutputRelativePath) + EfCoreGeneratorSettings(monorepoPreGeneratedBackendDir, ktOutputMonorepoRoot, ".Pregenerated") +} else { + EfCoreGeneratorSettings(efCoreRepoRoot.resolve("src/dotnet/Rider.Plugins.EfCore/Rd"), efCoreRepoRoot.resolve(ktOutputRelativePath), ".Generated") +} + +rdgen { + verbose = true + packages = "model" + + generator { + language = "kotlin" + transform = "asis" + root = "com.jetbrains.rider.model.nova.ide.IdeRoot" + namespace = "com.jetbrains.rider.plugins.efcore.model" + directory = efCoreGeneratorSettings.ktOutput.absolutePath + generatedFileSuffix = efCoreGeneratorSettings.suffix + } + + generator { + language = "csharp" + transform = "reversed" + root = "com.jetbrains.rider.model.nova.ide.IdeRoot" + namespace = "Rider.Plugins.EfCore" + directory = efCoreGeneratorSettings.csOutput.absolutePath + generatedFileSuffix = efCoreGeneratorSettings.suffix + } +} + +tasks.withType { + dependsOn(sourceSets["main"].runtimeClasspath) + classpath(sourceSets["main"].runtimeClasspath) +} + dependencies { - implementation("org.jetbrains.kotlin:kotlin-stdlib") - if (productMonorepoDir == null) { - implementation(group = "", name = "rd-gen") - implementation(group = "", name = "rider-model") + if (isMonorepo) { + implementation(project(":rider-model")) + } else { + val rdVersion: String by project + val rdKotlinVersion: String by project + + implementation("com.jetbrains.rd:rd-gen:$rdVersion") + implementation("org.jetbrains.kotlin:kotlin-stdlib:$rdKotlinVersion") + implementation( + project( + mapOf( + "path" to ":", + "configuration" to "riderModel" + ) + ) + ) } -} \ No newline at end of file +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 13653bac..6262bfdb 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,28 +1,39 @@ +rootProject.name = "rider-efcore" + pluginManagement { val rdVersion: String by settings + val rdKotlinVersion: String by settings + val intellijPlatformGradlePluginVersion: String by settings + val gradleJvmWrapperVersion: String by settings + repositories { - if (rdVersion == "SNAPSHOT") - mavenLocal() - maven("https://packages.jetbrains.team/maven/p/ij/intellij-dependencies") + maven("https://cache-redirector.jetbrains.com/intellij-dependencies") maven("https://cache-redirector.jetbrains.com/plugins.gradle.org") - maven("https://oss.sonatype.org/content/repositories/snapshots/") - gradlePluginPortal() + maven("https://cache-redirector.jetbrains.com/maven-central") + + if (rdVersion == "SNAPSHOT") { + mavenLocal() + } } + plugins { - id ("com.jetbrains.rdgen") version rdVersion + id("com.jetbrains.rdgen") version rdVersion + id("org.jetbrains.kotlin.jvm") version rdKotlinVersion + id("org.jetbrains.intellij.platform") version intellijPlatformGradlePluginVersion + id("me.filippov.gradle.jvm.wrapper") version gradleJvmWrapperVersion } + resolutionStrategy { eachPlugin { when (requested.id.name) { - // This required to correctly rd-gen plugin resolution. May be we should switch our naming to match Gradle plugin naming convention. + // This required to correctly rd-gen plugin resolution. + // Maybe we should switch our naming to match Gradle plugin naming convention. "rdgen" -> { - useModule("com.jetbrains.rd:rd-gen:$rdVersion") + useModule("com.jetbrains.rd:rd-gen:${rdVersion}") } } } } } -rootProject.name = "rider-efcore" - -include("protocol") \ No newline at end of file +include(":protocol") \ No newline at end of file diff --git a/src/dotnet/Rider.Plugins.EfCore.Tests/Rider.Plugins.EfCore.Tests.csproj b/src/dotnet/Rider.Plugins.EfCore.Tests/Rider.Plugins.EfCore.Tests.csproj index 827eae1e..dc30d1f5 100644 --- a/src/dotnet/Rider.Plugins.EfCore.Tests/Rider.Plugins.EfCore.Tests.csproj +++ b/src/dotnet/Rider.Plugins.EfCore.Tests/Rider.Plugins.EfCore.Tests.csproj @@ -1,18 +1,18 @@  - True + True False - net472 - false Rider.Plugins.EfCore.Tests + false $(MSBuildThisFileDirectory)PackagesLock.targets + net472 - + @@ -23,5 +23,4 @@ - - + \ No newline at end of file diff --git a/src/dotnet/Rider.Plugins.EfCore/Compatibility/SupportedMigrationsProjectsProvider.cs b/src/dotnet/Rider.Plugins.EfCore/Compatibility/SupportedMigrationsProjectsProvider.cs index ea14834a..fdb829b3 100644 --- a/src/dotnet/Rider.Plugins.EfCore/Compatibility/SupportedMigrationsProjectsProvider.cs +++ b/src/dotnet/Rider.Plugins.EfCore/Compatibility/SupportedMigrationsProjectsProvider.cs @@ -1,11 +1,12 @@ using System.Collections.Generic; using System.Linq; +using JetBrains.Application.Parts; using JetBrains.ProjectModel; using JetBrains.Util.Dotnet.TargetFrameworkIds; namespace Rider.Plugins.EfCore.Compatibility { - [SolutionComponent] + [SolutionComponent(InstantiationEx.LegacyDefault)] public class SupportedMigrationsProjectsProvider { private readonly ISolution _solution; @@ -29,6 +30,7 @@ private static bool IsSupportedInMigrationsProject(TargetFrameworkId targetFrame || targetFrameworkId.UniqueString.StartsWith(SupportedTargetFrameworks.Net6) || targetFrameworkId.UniqueString.StartsWith(SupportedTargetFrameworks.Net7) || targetFrameworkId.UniqueString.StartsWith(SupportedTargetFrameworks.Net8) + || targetFrameworkId.UniqueString.StartsWith(SupportedTargetFrameworks.Net9) || targetFrameworkId.UniqueString.StartsWith(SupportedTargetFrameworks.NetCore31) || targetFrameworkId.UniqueString.StartsWith(SupportedTargetFrameworks.NetStandard20) || targetFrameworkId.UniqueString.StartsWith(SupportedTargetFrameworks.NetStandard21); diff --git a/src/dotnet/Rider.Plugins.EfCore/Compatibility/SupportedStartupProjectsProvider.cs b/src/dotnet/Rider.Plugins.EfCore/Compatibility/SupportedStartupProjectsProvider.cs index 26e5100e..864f2c58 100644 --- a/src/dotnet/Rider.Plugins.EfCore/Compatibility/SupportedStartupProjectsProvider.cs +++ b/src/dotnet/Rider.Plugins.EfCore/Compatibility/SupportedStartupProjectsProvider.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using JetBrains.Application.Parts; using JetBrains.ProjectModel; using JetBrains.ProjectModel.NuGet.Packaging; using JetBrains.Util; @@ -9,7 +10,7 @@ namespace Rider.Plugins.EfCore.Compatibility { - [SolutionComponent] + [SolutionComponent(InstantiationEx.LegacyDefault)] public class SupportedStartupProjectsProvider { private readonly ISolution _solution; @@ -58,6 +59,7 @@ private static bool IsSupportedInStartupProject(TargetFrameworkId targetFramewor || targetFrameworkId.UniqueString.StartsWith(SupportedTargetFrameworks.Net6) || targetFrameworkId.UniqueString.StartsWith(SupportedTargetFrameworks.Net7) || targetFrameworkId.UniqueString.StartsWith(SupportedTargetFrameworks.Net8) + || targetFrameworkId.UniqueString.StartsWith(SupportedTargetFrameworks.Net9) || targetFrameworkId.UniqueString.StartsWith(SupportedTargetFrameworks.NetCore31); } } diff --git a/src/dotnet/Rider.Plugins.EfCore/Compatibility/SupportedTargetFrameworks.cs b/src/dotnet/Rider.Plugins.EfCore/Compatibility/SupportedTargetFrameworks.cs index 72604379..2056b99c 100644 --- a/src/dotnet/Rider.Plugins.EfCore/Compatibility/SupportedTargetFrameworks.cs +++ b/src/dotnet/Rider.Plugins.EfCore/Compatibility/SupportedTargetFrameworks.cs @@ -6,6 +6,7 @@ public static class SupportedTargetFrameworks public const string Net6 = "net6.0"; public const string Net7 = "net7.0"; public const string Net8 = "net8.0"; + public const string Net9 = "net9.0"; public const string NetCore31 = ".NETCoreApp,Version=v3.1"; public const string NetStandard20 = ".NETStandard,Version=v2.0"; public const string NetStandard21 = ".NETStandard,Version=v2.1"; diff --git a/src/dotnet/Rider.Plugins.EfCore/DbContext/DbContextProvider.cs b/src/dotnet/Rider.Plugins.EfCore/DbContext/DbContextProvider.cs index f741d7ea..998e2605 100644 --- a/src/dotnet/Rider.Plugins.EfCore/DbContext/DbContextProvider.cs +++ b/src/dotnet/Rider.Plugins.EfCore/DbContext/DbContextProvider.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using JetBrains.Application.Parts; using JetBrains.ProjectModel; using JetBrains.ReSharper.Psi; using JetBrains.ReSharper.Psi.Modules; @@ -9,7 +10,7 @@ namespace Rider.Plugins.EfCore.DbContext { - [SolutionComponent] + [SolutionComponent(InstantiationEx.LegacyDefault)] public class DbContextProvider { public IEnumerable GetDbContexts(IProject project) diff --git a/src/dotnet/Rider.Plugins.EfCore/Dependencies/EfCorePackagesProvider.cs b/src/dotnet/Rider.Plugins.EfCore/Dependencies/EfCorePackagesProvider.cs index 451d8f9a..7e5eaeb7 100644 --- a/src/dotnet/Rider.Plugins.EfCore/Dependencies/EfCorePackagesProvider.cs +++ b/src/dotnet/Rider.Plugins.EfCore/Dependencies/EfCorePackagesProvider.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using JetBrains.Application.Parts; using JetBrains.ProjectModel; using JetBrains.ProjectModel.NuGet.Operations; using JetBrains.ProjectModel.NuGet.Packaging; @@ -8,7 +9,7 @@ namespace Rider.Plugins.EfCore.Dependencies; -[SolutionComponent] +[SolutionComponent(InstantiationEx.LegacyDefault)] public class EfCorePackagesProvider { // Since it's hard to detect provider by NuGet package dependencies and structure, we will rely on a well-known list. diff --git a/src/dotnet/Rider.Plugins.EfCore/EntityFrameworkCoreHost.cs b/src/dotnet/Rider.Plugins.EfCore/EntityFrameworkCoreHost.cs index d4187b59..30de99a3 100644 --- a/src/dotnet/Rider.Plugins.EfCore/EntityFrameworkCoreHost.cs +++ b/src/dotnet/Rider.Plugins.EfCore/EntityFrameworkCoreHost.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using JetBrains.Application.Parts; using JetBrains.Core; using JetBrains.Lifetimes; using JetBrains.Platform.RdFramework.Impl; @@ -22,7 +23,7 @@ namespace Rider.Plugins.EfCore { - [SolutionComponent] + [SolutionComponent(InstantiationEx.LegacyDefault)] public class EntityFrameworkCoreHost { private readonly Lifetime _lifetime; diff --git a/src/dotnet/Rider.Plugins.EfCore/Migrations/MigrationsProvider.cs b/src/dotnet/Rider.Plugins.EfCore/Migrations/MigrationsProvider.cs index 2342db98..f3e8614a 100644 --- a/src/dotnet/Rider.Plugins.EfCore/Migrations/MigrationsProvider.cs +++ b/src/dotnet/Rider.Plugins.EfCore/Migrations/MigrationsProvider.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using JetBrains.Application.Parts; using JetBrains.ProjectModel; using JetBrains.ReSharper.Psi; using JetBrains.ReSharper.Psi.Modules; @@ -8,7 +9,7 @@ namespace Rider.Plugins.EfCore.Migrations { - [SolutionComponent] + [SolutionComponent(InstantiationEx.LegacyDefault)] public class MigrationsProvider { public bool HasMigrations(IProject project, string dbContextFullName) diff --git a/src/dotnet/Rider.Plugins.EfCore/PackagesLock.targets b/src/dotnet/Rider.Plugins.EfCore/PackagesLock.targets index 020f2324..2f3e7fd5 100644 --- a/src/dotnet/Rider.Plugins.EfCore/PackagesLock.targets +++ b/src/dotnet/Rider.Plugins.EfCore/PackagesLock.targets @@ -1,9 +1,9 @@  - - - - + + + + - \ No newline at end of file + diff --git a/src/dotnet/Rider.Plugins.EfCore/Rider.Plugins.EfCore.csproj b/src/dotnet/Rider.Plugins.EfCore/Rider.Plugins.EfCore.csproj index 80291574..5f8b56e6 100644 --- a/src/dotnet/Rider.Plugins.EfCore/Rider.Plugins.EfCore.csproj +++ b/src/dotnet/Rider.Plugins.EfCore/Rider.Plugins.EfCore.csproj @@ -1,39 +1,32 @@ - + + - True + True False - - $(MSBuildToolsPath)\Microsoft.CSharp.targets - - - - - - - net472 Rider.Plugins.EfCore - $(AssemblyName) - false $(DefineConstants);RIDER + false + $(MSBuildToolsPath)\Microsoft.CSharp.targets $(MSBuildThisFileDirectory)PackagesLock.targets + $(AssemblyName) + net472 - - + + + - + - - - + \ No newline at end of file diff --git a/src/dotnet/Rider.Plugins.EfCore/Tracking/NugetDependenciesListener.cs b/src/dotnet/Rider.Plugins.EfCore/Tracking/NugetDependenciesListener.cs index 563f76b5..e700127b 100644 --- a/src/dotnet/Rider.Plugins.EfCore/Tracking/NugetDependenciesListener.cs +++ b/src/dotnet/Rider.Plugins.EfCore/Tracking/NugetDependenciesListener.cs @@ -1,4 +1,5 @@ using System; +using JetBrains.Application.Parts; using JetBrains.Lifetimes; using JetBrains.ProjectModel; using JetBrains.ProjectModel.NuGet.Packaging; @@ -7,7 +8,7 @@ namespace Rider.Plugins.EfCore.Tracking { - [SolutionComponent] + [SolutionComponent(InstantiationEx.LegacyDefault)] public class NugetDependenciesListener { private readonly NuGetPackageReferenceTracker _nuGetPackageReferenceTracker; diff --git a/src/dotnet/Rider.Plugins.EfCore/Tracking/SolutionStructureChangedListener.cs b/src/dotnet/Rider.Plugins.EfCore/Tracking/SolutionStructureChangedListener.cs index aa6f56f0..534933e9 100644 --- a/src/dotnet/Rider.Plugins.EfCore/Tracking/SolutionStructureChangedListener.cs +++ b/src/dotnet/Rider.Plugins.EfCore/Tracking/SolutionStructureChangedListener.cs @@ -1,4 +1,5 @@ using System; +using JetBrains.Application.Parts; using JetBrains.ProjectModel; using JetBrains.ProjectModel.ProjectsHost.Impl; using JetBrains.ProjectModel.ProjectsHost.SolutionHost; @@ -7,7 +8,7 @@ namespace Rider.Plugins.EfCore.Tracking { - [SolutionComponent] + [SolutionComponent(InstantiationEx.LegacyDefault)] public class SolutionStructureChangedListener : SolutionHostSyncListener { private readonly ILogger _logger; diff --git a/src/dotnet/Rider.Plugins.EfCore/Tracking/SolutionTracker.cs b/src/dotnet/Rider.Plugins.EfCore/Tracking/SolutionTracker.cs index 0b7f0ccf..4e79d0b5 100644 --- a/src/dotnet/Rider.Plugins.EfCore/Tracking/SolutionTracker.cs +++ b/src/dotnet/Rider.Plugins.EfCore/Tracking/SolutionTracker.cs @@ -1,4 +1,5 @@ using System; +using JetBrains.Application.Parts; using JetBrains.Lifetimes; using JetBrains.ProjectModel; using JetBrains.ProjectModel.NuGet.DotNetTools; @@ -9,7 +10,7 @@ namespace Rider.Plugins.EfCore.Tracking { - [SolutionComponent] + [SolutionComponent(InstantiationEx.LegacyDefault)] public class SolutionTracker { private readonly Lifetime _lifetime; diff --git a/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/features/connections/DbConnectionsCollector.kt b/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/features/connections/DbConnectionsCollector.kt index 67f6473f..a00b5cf5 100644 --- a/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/features/connections/DbConnectionsCollector.kt +++ b/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/features/connections/DbConnectionsCollector.kt @@ -5,15 +5,15 @@ import com.intellij.openapi.components.service import com.intellij.openapi.project.Project import com.intellij.platform.backend.workspace.WorkspaceModel import com.jetbrains.rider.model.RdProjectDescriptor -import com.jetbrains.rider.projectView.workspace.findProjects import com.jetbrains.rider.plugins.efcore.features.connections.impl.AppSettingsConnectionProvider import com.jetbrains.rider.plugins.efcore.features.connections.impl.DataGripConnectionProvider import com.jetbrains.rider.plugins.efcore.features.connections.impl.UserSecretsConnectionProvider +import com.jetbrains.rider.projectView.workspace.findProjects import java.util.* @Service(Service.Level.PROJECT) @Suppress("UnstableApiUsage") -class DbConnectionsCollector(private val intellijProject: Project) { +internal class DbConnectionsCollector(private val intellijProject: Project) { companion object { fun getInstance(intellijProject: Project) = intellijProject.service() } diff --git a/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/features/connections/impl/AppSettingsConnectionProvider.kt b/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/features/connections/impl/AppSettingsConnectionProvider.kt index 7c1ffd4c..227b0fc5 100644 --- a/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/features/connections/impl/AppSettingsConnectionProvider.kt +++ b/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/features/connections/impl/AppSettingsConnectionProvider.kt @@ -19,11 +19,11 @@ class AppSettingsConnectionProvider(private val intellijProject: Project) : DbCo fun getInstance(intellijProject: Project) = intellijProject.service() } - private val serializer = intellijProject.service() + private val serializer = JsonSerializer.getInstance() override fun getAvailableConnections(project: RdProjectDescriptor) = buildList { - val directory = (project.location as RdCustomLocation?)?.customLocation?.let(::Path)?.parent ?: return@buildList + val directory = (project.location as? RdCustomLocation)?.customLocation?.let(::Path)?.parent ?: return@buildList @NonNls val connectionStrings = directory.listDirectoryEntries("appsettings*.json") .filter { it.isRegularFile() } diff --git a/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/features/connections/impl/JsonConnectionStringsManager.kt b/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/features/connections/impl/JsonConnectionStringsManager.kt index cd608cb1..5b8c5e39 100644 --- a/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/features/connections/impl/JsonConnectionStringsManager.kt +++ b/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/features/connections/impl/JsonConnectionStringsManager.kt @@ -32,9 +32,9 @@ class JsonConnectionStringsManager(intellijProject: Project) { * } */ private fun getConnectionsFromObject(fileName: String, jsonFile: JsonNode): List = buildList { - val obj = jsonFile.get("ConnectionStrings") as ObjectNode? ?: return emptyList() + val obj = jsonFile.get("ConnectionStrings") as? ObjectNode ?: return emptyList() obj.fieldNames().forEach { connName -> - val connString = (obj[connName] as TextNode?)?.textValue() + val connString = (obj[connName] as? TextNode)?.textValue() if (connString != null) add(DbConnectionInfo(connName, connString, fileName, null)) } @@ -53,7 +53,7 @@ class JsonConnectionStringsManager(intellijProject: Project) { null -> return@forEach else -> { val name = match.groups["name"]?.value ?: return@forEach - val connection = (jsonFile[settingsField] as TextNode?)?.textValue() ?: return@forEach + val connection = (jsonFile[settingsField] as? TextNode)?.textValue() ?: return@forEach add(DbConnectionInfo(name, connection, fileName, null)) } } diff --git a/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/features/connections/impl/UserSecretsConnectionProvider.kt b/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/features/connections/impl/UserSecretsConnectionProvider.kt index d86ba6c1..471f951e 100644 --- a/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/features/connections/impl/UserSecretsConnectionProvider.kt +++ b/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/features/connections/impl/UserSecretsConnectionProvider.kt @@ -23,7 +23,7 @@ class UserSecretsConnectionProvider(private val intellijProject: Project) : DbCo fun getInstance(intellijProject: Project) = intellijProject.service() } - private val serializer = intellijProject.service() + private val serializer = JsonSerializer.getInstance() override fun getAvailableConnections(project: RdProjectDescriptor) = buildList { diff --git a/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/features/eftools/SuppressEfCoreToolsInstallation.kt b/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/features/eftools/SuppressEfCoreToolsInstallation.kt new file mode 100644 index 00000000..3e9ce80b --- /dev/null +++ b/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/features/eftools/SuppressEfCoreToolsInstallation.kt @@ -0,0 +1,15 @@ +package com.jetbrains.rider.plugins.efcore.features.eftools + +import com.intellij.notification.Notification +import com.intellij.openapi.actionSystem.AnAction +import com.intellij.openapi.actionSystem.AnActionEvent +import com.jetbrains.rider.plugins.efcore.EfCoreUiBundle +import com.jetbrains.rider.plugins.efcore.state.CommonOptionsStateService + +class SuppressEfCoreToolsInstallation(private val notification : Notification) : AnAction(EfCoreUiBundle.message("action.install.ignore")) { + private val commonOptionsStateService by lazy { CommonOptionsStateService.getInstance() } + override fun actionPerformed(actionEvent: AnActionEvent) { + commonOptionsStateService.toolsInstallationSupressed = true + notification.hideBalloon() + } +} \ No newline at end of file diff --git a/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/features/shared/AnActionEventEx.kt b/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/features/shared/AnActionEventEx.kt index 0ec1bc57..cce41d79 100644 --- a/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/features/shared/AnActionEventEx.kt +++ b/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/features/shared/AnActionEventEx.kt @@ -1,6 +1,7 @@ package com.jetbrains.rider.plugins.efcore.features.shared import com.intellij.openapi.actionSystem.ActionPlaces +import com.intellij.openapi.actionSystem.ActionPlaces.MAIN_TOOLBAR import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.PlatformDataKeys import com.intellij.platform.backend.workspace.WorkspaceModel @@ -34,8 +35,8 @@ fun AnActionEvent.isSolutionModeContext(): Boolean { val extension = getData(PlatformDataKeys.VIRTUAL_FILE)?.extension return when { ActionPlaces.isMainMenuOrActionSearch(place) -> true - ActionPlaces.isMainToolbar(place) -> true - ActionPlaces.isPopupPlace(place) && extension == "sln" || extension == "slnf" -> true + place == MAIN_TOOLBAR -> true + isFromContextMenu && extension == "sln" || extension == "slnf" -> true else -> false } } diff --git a/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/features/shared/BaseCommandAction.kt b/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/features/shared/BaseCommandAction.kt index 28fd353f..2614b20d 100644 --- a/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/features/shared/BaseCommandAction.kt +++ b/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/features/shared/BaseCommandAction.kt @@ -37,7 +37,7 @@ abstract class BaseCommandAction : AnAction() { } } - override fun getActionUpdateThread() = ActionUpdateThread.EDT + override fun getActionUpdateThread() = ActionUpdateThread.BGT abstract fun createDialog( intellijProject: Project, diff --git a/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/features/shared/services/JsonSerializer.kt b/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/features/shared/services/JsonSerializer.kt index 726f9e04..02f98109 100644 --- a/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/features/shared/services/JsonSerializer.kt +++ b/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/features/shared/services/JsonSerializer.kt @@ -2,25 +2,25 @@ package com.jetbrains.rider.plugins.efcore.features.shared.services import com.fasterxml.jackson.core.JacksonException import com.fasterxml.jackson.core.JsonParser +import com.fasterxml.jackson.core.json.JsonReadFeature import com.fasterxml.jackson.databind.JsonNode import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import com.intellij.openapi.components.Service import com.intellij.openapi.components.service import com.intellij.openapi.diagnostic.logger -import com.intellij.openapi.project.Project -import com.jetbrains.rider.plugins.efcore.features.connections.impl.AppSettingsConnectionProvider import org.jetbrains.annotations.NonNls import java.io.File -@Service +@Service(Service.Level.APP) class JsonSerializer { companion object { private val json = jacksonObjectMapper() .enable(JsonParser.Feature.ALLOW_COMMENTS) .enable(JsonParser.Feature.ALLOW_SINGLE_QUOTES) + .enable(JsonReadFeature.ALLOW_TRAILING_COMMA.mappedFeature()) - fun getInstance(intellijProject: Project) = intellijProject.service() + fun getInstance() = service() } private val logger = logger() diff --git a/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/features/terminal/smartExecute/EFCoreShellCommandHandler.kt b/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/features/terminal/smartExecute/EFCoreShellCommandHandler.kt index 08fa337e..ec3e972d 100644 --- a/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/features/terminal/smartExecute/EFCoreShellCommandHandler.kt +++ b/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/features/terminal/smartExecute/EFCoreShellCommandHandler.kt @@ -3,7 +3,9 @@ package com.jetbrains.rider.plugins.efcore.features.terminal.smartExecute import com.intellij.execution.Executor import com.intellij.openapi.actionSystem.impl.SimpleDataContext import com.intellij.openapi.project.Project +import com.intellij.openapi.ui.popup.JBPopupFactory import com.intellij.terminal.TerminalShellCommandHandler +import com.jetbrains.rider.plugins.efcore.EfCoreUiBundle import com.jetbrains.rider.plugins.efcore.cli.api.models.DotnetEfVersion import com.jetbrains.rider.plugins.efcore.cli.execution.KnownEfCommands import com.jetbrains.rider.plugins.efcore.features.database.drop.DropDatabaseAction @@ -13,15 +15,12 @@ import com.jetbrains.rider.plugins.efcore.features.migrations.add.AddMigrationAc import com.jetbrains.rider.plugins.efcore.features.migrations.remove.RemoveLastMigrationAction import com.jetbrains.rider.plugins.efcore.features.migrations.script.GenerateScriptAction import com.jetbrains.rider.plugins.efcore.features.shared.BaseCommandAction +import com.jetbrains.rider.plugins.efcore.features.shared.QuickActionsGroup import com.jetbrains.rider.plugins.efcore.rd.riderEfCoreModel import com.jetbrains.rider.projectView.solution -import java.util.UUID -import com.intellij.openapi.ui.popup.JBPopupFactory -import com.jetbrains.rider.plugins.efcore.EfCoreUiBundle -import com.jetbrains.rider.plugins.efcore.features.shared.QuickActionsGroup - -class EFCoreShellCommandHandler : TerminalShellCommandHandler { +import java.util.* +private class EFCoreShellCommandHandler : TerminalShellCommandHandler { companion object { // Define dotnet ef constant string and commands private const val DOTNET_EF = "dotnet ef" diff --git a/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/settings/EfCoreUiConfigurable.kt b/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/settings/EfCoreUiConfigurable.kt index a2362f4e..231d0361 100644 --- a/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/settings/EfCoreUiConfigurable.kt +++ b/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/settings/EfCoreUiConfigurable.kt @@ -39,4 +39,6 @@ class EfCoreUiConfigurable : BoundConfigurable(EfCoreUiBundle.message("configura } } } + + override fun getHelpTopic(): String = "Settings_EF_Core" } \ No newline at end of file diff --git a/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/startup/EfCoreStartupListener.kt b/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/startup/EfCoreStartupListener.kt index 2a35298c..0863c29a 100644 --- a/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/startup/EfCoreStartupListener.kt +++ b/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/startup/EfCoreStartupListener.kt @@ -9,24 +9,30 @@ import com.jetbrains.rd.util.lifetime.Lifetime import com.jetbrains.rider.plugins.efcore.EfCoreUiBundle import com.jetbrains.rider.plugins.efcore.KnownNotificationGroups import com.jetbrains.rider.plugins.efcore.features.eftools.InstallDotnetEfAction +import com.jetbrains.rider.plugins.efcore.features.eftools.SuppressEfCoreToolsInstallation import com.jetbrains.rider.plugins.efcore.rd.RiderEfCoreModel +import com.jetbrains.rider.plugins.efcore.state.CommonOptionsStateService @Suppress("UnstableApiUsage") class EfCoreStartupListener : SolutionExtListener { + private val commonOptionsStateService by lazy { CommonOptionsStateService.getInstance() } override fun extensionCreated(lifetime: Lifetime, session: ClientProjectSession, model: RiderEfCoreModel) { - model.onMissingEfCoreToolsDetected.set { _, unit -> - NotificationGroupManager - .getInstance() - .getNotificationGroup(KnownNotificationGroups.efCore) - .createNotification( - EfCoreUiBundle.message("notification.title.ef.core.tools.required"), - EfCoreUiBundle.message("notification.content.ef.core.tools.are.required.to.execute.this.action"), - NotificationType.WARNING - ) - .addAction(InstallDotnetEfAction()) - .notify(session.project) + if(!commonOptionsStateService.toolsInstallationSupressed) { + model.onMissingEfCoreToolsDetected.set { _, unit -> + NotificationGroupManager + .getInstance() + .getNotificationGroup(KnownNotificationGroups.efCore) + .createNotification( + EfCoreUiBundle.message("notification.title.ef.core.tools.required"), + EfCoreUiBundle.message("notification.content.ef.core.tools.are.required.to.execute.this.action"), + NotificationType.WARNING + ) + .addAction(InstallDotnetEfAction()) + .addAction(SuppressEfCoreToolsInstallation(this)) + .notify(session.project) - RdTask.fromResult(unit) + RdTask.fromResult(unit) + } } } } \ No newline at end of file diff --git a/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/state/CommonOptionsState.kt b/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/state/CommonOptionsState.kt index 7cba1f40..ff3ab227 100644 --- a/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/state/CommonOptionsState.kt +++ b/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/state/CommonOptionsState.kt @@ -4,4 +4,5 @@ class CommonOptionsState { var solutionLevelOptions: MutableMap = mutableMapOf() var migrationsToStartupProjects: MutableMap = mutableMapOf() var startupToMigrationsProjects: MutableMap = mutableMapOf() + var toolsInstallationSupressed: Boolean = false } diff --git a/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/state/CommonOptionsStateService.kt b/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/state/CommonOptionsStateService.kt index 9657ef31..689205b3 100644 --- a/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/state/CommonOptionsStateService.kt +++ b/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/state/CommonOptionsStateService.kt @@ -1,8 +1,6 @@ package com.jetbrains.rider.plugins.efcore.state import com.intellij.openapi.components.* -import com.intellij.openapi.project.Project -import com.jetbrains.rider.plugins.efcore.features.shared.services.PreferredProjectsManager import java.util.* @Service @@ -59,4 +57,10 @@ class CommonOptionsStateService : PersistentStateComponent { myState.solutionLevelOptions[MIGRATIONS_PROJECT_KEY] = migrationsProjectId.toString() myState.solutionLevelOptions[STARTUP_PROJECT_KEY] = startupProjectId.toString() } + + var toolsInstallationSupressed : Boolean + get() = myState.toolsInstallationSupressed + set(value : Boolean){ + myState.toolsInstallationSupressed = value + } } \ No newline at end of file diff --git a/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/ui/DslExtensions.kt b/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/ui/DslExtensions.kt index 6fea8dcd..383322d8 100644 --- a/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/ui/DslExtensions.kt +++ b/src/rider/main/kotlin/com/jetbrains/rider/plugins/efcore/ui/DslExtensions.kt @@ -5,12 +5,13 @@ import com.intellij.openapi.editor.colors.EditorFontType import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory import com.intellij.openapi.project.Project import com.intellij.openapi.ui.TextFieldWithBrowseButton +import com.intellij.openapi.util.NlsContexts import com.intellij.ui.components.fields.ExpandableTextField import com.intellij.ui.dsl.builder.Cell import com.intellij.ui.dsl.builder.Row import com.intellij.ui.dsl.builder.bindText -import com.jetbrains.rdclient.util.idea.toIOFile import com.jetbrains.observables.ObservableProperty +import com.jetbrains.rdclient.util.idea.toIOFile import java.io.File import javax.swing.JComponent @@ -25,13 +26,12 @@ fun JComponent.monospaced(): JComponent = } fun Row.textFieldForRelativeFolder( - basePathGetter: () -> String, - project: Project? = null, - browseDialogTitle: String? = null, + basePathGetter: () -> String, + project: Project? = null, + browseDialogTitle: @NlsContexts.DialogTitle String? = null, ): Cell { - - val fileChooserDescriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor() - val textFieldWithBrowseButtonCell = textFieldWithBrowseButton(browseDialogTitle, project, fileChooserDescriptor) { + val fileChooserDescriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor().withTitle(browseDialogTitle) + val textFieldWithBrowseButtonCell = textFieldWithBrowseButton(fileChooserDescriptor, project) { val pathRelativeToAsFile = File(basePathGetter()).path it.toIOFile().relativeTo(File(pathRelativeToAsFile)).path } diff --git a/src/rider/main/resources/META-INF/plugin.xml b/src/rider/main/resources/META-INF/plugin.xml index 1d27ae3d..9f7ec9fa 100644 --- a/src/rider/main/resources/META-INF/plugin.xml +++ b/src/rider/main/resources/META-INF/plugin.xml @@ -1,9 +1,7 @@ me.seclerp.rider.plugins.efcore Entity Framework Core UI - _PLACEHOLDER_ - JetBrains - + JetBrains com.intellij.modules.rider com.intellij.database org.jetbrains.plugins.terminal diff --git a/src/rider/main/resources/messages/EfCoreUiBundle.properties b/src/rider/main/resources/messages/EfCoreUiBundle.properties index 922247a8..559714c3 100644 --- a/src/rider/main/resources/messages/EfCoreUiBundle.properties +++ b/src/rider/main/resources/messages/EfCoreUiBundle.properties @@ -152,6 +152,7 @@ tab.ef.core.command=EF Core Command # # Install EF Core tools action.install.text=Install +action.install.ignore=Don't show again ef.core.global.tools.have.been.successfully.installed=EF Core global tools have been successfully installed progress.title.getting.dotnet.ef.version=Getting dotnet-ef version\u2026 notification.content.ef.core.tools.are.required.to.execute.this.action=To use EF Core in the IDE, install dotnet-ef as a global tool diff --git a/src/test/kotlin/com/jetbrains/rider/plugins/efcore/cases/RiderTestDataMarker.kt b/src/test/kotlin/com/jetbrains/rider/plugins/efcore/cases/RiderTestDataMarker.kt new file mode 100644 index 00000000..6f571e36 --- /dev/null +++ b/src/test/kotlin/com/jetbrains/rider/plugins/efcore/cases/RiderTestDataMarker.kt @@ -0,0 +1,13 @@ +package com.jetbrains.rider.plugins.efcore.cases + +import com.jetbrains.rider.test.framework.testData.IRiderTestDataMarker +import java.io.File + +@Suppress("unused") +object RiderTestDataMarker : IRiderTestDataMarker { + override val testDataFromRoot: File + get() = File("src/test/testData") + + override val pluginDirectoryInUltimate: File + get() = File("dotnet/Plugins/rider-efcore") +} \ No newline at end of file diff --git a/testData/NuGet_template.config b/src/test/testData/NuGet_template.config similarity index 100% rename from testData/NuGet_template.config rename to src/test/testData/NuGet_template.config