diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9ca79920..d93a9bcb 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,7 +3,7 @@ annotations = "24.0.1" # plugins -kotlin = "1.9.20" +kotlin = "1.9.21" changelog = "2.2.0" gradleIntelliJPlugin = "1.16.0" qodana = "0.1.13" diff --git a/src/dotnet/aspire-plugin/RunnableProject/AspireRunnableProjectProvider.cs b/src/dotnet/aspire-plugin/RunnableProject/AspireRunnableProjectProvider.cs index 7435af35..1b49703e 100644 --- a/src/dotnet/aspire-plugin/RunnableProject/AspireRunnableProjectProvider.cs +++ b/src/dotnet/aspire-plugin/RunnableProject/AspireRunnableProjectProvider.cs @@ -9,21 +9,41 @@ namespace AspirePlugin.RunnableProject; [SolutionComponent] -public class AspireRunnableProjectProvider : IRunnableProjectProvider +public class AspireRunnableProjectProvider( + ProjectRunnableOutputDetector projectRunnableOutputDetector, + ILogger logger +) : IRunnableProjectProvider { - public JetBrains.Rider.Model.RunnableProject? CreateRunnableProject(IProject project, string name, string fullName, IconModel? icon) + public JetBrains.Rider.Model.RunnableProject? CreateRunnableProject( + IProject project, + string name, + string fullName, + IconModel? icon) { if (!project.IsDotNetCoreProject()) return null; var isAspireHost = project.GetUniqueRequestedProjectProperty(IsAspireHost); if (isAspireHost.IsNullOrEmpty() || isAspireHost != "true") return null; + var projectOutputs = new List(); + foreach (var tfm in project.TargetFrameworkIds) + { + var projectOutput = projectRunnableOutputDetector.CalculateProjectOutput(project, tfm); + if (projectOutput == null) + { + logger.Trace("Unable to find output for project for {0}", tfm); + continue; + } + + projectOutputs.Add(projectOutput); + } + return new JetBrains.Rider.Model.RunnableProject( name, fullName, project.ProjectFileLocation.NormalizeSeparators(FileSystemPathEx.SeparatorStyle.Unix), AspireRunnableProjectKinds.AspireHost, - [], + projectOutputs, [], null, [] diff --git a/src/dotnet/aspire-plugin/ZoneMarker.cs b/src/dotnet/aspire-plugin/ZoneMarker.cs index 07d72bbd..46382b8f 100644 --- a/src/dotnet/aspire-plugin/ZoneMarker.cs +++ b/src/dotnet/aspire-plugin/ZoneMarker.cs @@ -1,8 +1,7 @@ using JetBrains.Application.BuildScript.Application.Zones; -using JetBrains.ProjectModel; -using JetBrains.ReSharper.Psi.CSharp; +using JetBrains.ReSharper.Features.Running; namespace AspirePlugin; [ZoneMarker] -public class ZoneMarker : IRequire, IRequire; \ No newline at end of file +public class ZoneMarker : IRequire; \ No newline at end of file diff --git a/src/main/kotlin/com/github/rafaelldi/aspireplugin/run/AspireHostConfigurationFactory.kt b/src/main/kotlin/com/github/rafaelldi/aspireplugin/run/AspireHostConfigurationFactory.kt index 5d3db753..8a506e70 100644 --- a/src/main/kotlin/com/github/rafaelldi/aspireplugin/run/AspireHostConfigurationFactory.kt +++ b/src/main/kotlin/com/github/rafaelldi/aspireplugin/run/AspireHostConfigurationFactory.kt @@ -6,6 +6,8 @@ import com.jetbrains.rider.run.configurations.project.DotNetStartBrowserParamete class AspireHostConfigurationFactory(type: AspireHostConfigurationType) : DotNetConfigurationFactoryBase(type) { + override fun getId() = "Aspire Host" + override fun createTemplateConfiguration(project: Project) = AspireHostConfiguration( project, this, diff --git a/src/main/kotlin/com/github/rafaelldi/aspireplugin/run/AspireHostConfigurationParameters.kt b/src/main/kotlin/com/github/rafaelldi/aspireplugin/run/AspireHostConfigurationParameters.kt index 33cc0430..67879976 100644 --- a/src/main/kotlin/com/github/rafaelldi/aspireplugin/run/AspireHostConfigurationParameters.kt +++ b/src/main/kotlin/com/github/rafaelldi/aspireplugin/run/AspireHostConfigurationParameters.kt @@ -1,6 +1,12 @@ package com.github.rafaelldi.aspireplugin.run +import com.intellij.execution.configurations.RunConfiguration +import com.intellij.execution.configurations.RunProfile import com.intellij.execution.configurations.RuntimeConfigurationError +import com.intellij.execution.process.ProcessHandler +import com.intellij.execution.runners.ExecutionEnvironment +import com.intellij.ide.browsers.BrowserStarter +import com.intellij.ide.browsers.StartBrowserSettings import com.intellij.openapi.project.Project import com.intellij.openapi.util.JDOMExternalizerUtil import com.jetbrains.rider.model.RunnableProject @@ -22,6 +28,19 @@ class AspireHostConfigurationParameters( private const val TRACK_URL = "TRACK_URL" } + val startBrowserAction: (ExecutionEnvironment, RunProfile, ProcessHandler) -> Unit = + { _, runProfile, processHandler -> + if (startBrowserParameters.startAfterLaunch && runProfile is RunConfiguration) { + val startBrowserSettings = StartBrowserSettings().apply { + isSelected = startBrowserParameters.startAfterLaunch + url = startBrowserParameters.url + browser = startBrowserParameters.browser + isStartJavaScriptDebugger = startBrowserParameters.withJavaScriptDebugger + } + BrowserStarter(runProfile, startBrowserSettings, processHandler).start() + } + } + fun validate() { val runnableProjects = project.solution.runnableProjectsModel.projects.valueOrNull if (project.solution.isLoaded.valueOrNull != true || runnableProjects == null) { diff --git a/src/main/kotlin/com/github/rafaelldi/aspireplugin/run/AspireHostExecutorFactory.kt b/src/main/kotlin/com/github/rafaelldi/aspireplugin/run/AspireHostExecutorFactory.kt index 107e8d13..945cea93 100644 --- a/src/main/kotlin/com/github/rafaelldi/aspireplugin/run/AspireHostExecutorFactory.kt +++ b/src/main/kotlin/com/github/rafaelldi/aspireplugin/run/AspireHostExecutorFactory.kt @@ -6,8 +6,16 @@ import com.intellij.execution.executors.DefaultDebugExecutor import com.intellij.execution.executors.DefaultRunExecutor import com.intellij.execution.runners.ExecutionEnvironment import com.intellij.openapi.project.Project +import com.intellij.util.execution.ParametersListUtil import com.jetbrains.rd.util.lifetime.Lifetime +import com.jetbrains.rider.model.RunnableProject +import com.jetbrains.rider.model.runnableProjectsModel +import com.jetbrains.rider.projectView.solution import com.jetbrains.rider.run.configurations.AsyncExecutorFactory +import com.jetbrains.rider.run.configurations.project.DotNetProjectConfigurationParameters +import com.jetbrains.rider.run.configurations.project.getRunOptions +import com.jetbrains.rider.runtime.DotNetExecutable +import com.jetbrains.rider.runtime.RiderDotNetActiveRuntimeHost class AspireHostExecutorFactory( private val project: Project, @@ -17,9 +25,50 @@ class AspireHostExecutorFactory( executorId: String, environment: ExecutionEnvironment, lifetime: Lifetime - ): RunProfileState = when (executorId) { - DefaultDebugExecutor.EXECUTOR_ID -> throw CantRunException("") - DefaultRunExecutor.EXECUTOR_ID -> throw CantRunException("") - else -> throw CantRunException("") + ): RunProfileState { + val activeRuntime = RiderDotNetActiveRuntimeHost.getInstance(project).dotNetCoreRuntime.value + ?: throw CantRunException("Unable to find appropriate runtime") + + val projects = project.solution.runnableProjectsModel.projects.valueOrNull + ?: throw CantRunException(DotNetProjectConfigurationParameters.SOLUTION_IS_LOADING) + + val runnableProject = projects.singleOrNull { + AspireHostConfigurationType.isTypeApplicable(it.kind) && it.projectFilePath == parameters.projectFilePath + } ?: throw CantRunException(DotNetProjectConfigurationParameters.PROJECT_NOT_SPECIFIED) + + val executable = getDotNetExecutable( + runnableProject + ) + + return when (executorId) { + DefaultDebugExecutor.EXECUTOR_ID -> activeRuntime.createRunState(executable, environment) + DefaultRunExecutor.EXECUTOR_ID -> activeRuntime.createRunState(executable, environment) + else -> throw CantRunException("") + } + } + + private fun getDotNetExecutable( + runnableProject: RunnableProject + ): DotNetExecutable { + val projectOutput = runnableProject.projectOutputs.firstOrNull() + ?: throw CantRunException("Unable to find project output") + + return DotNetExecutable( + projectOutput.exePath, + projectOutput.tfm, + projectOutput.workingDirectory, + ParametersListUtil.join(projectOutput.defaultArguments), + false, + false, + mapOf( + "DEBUG_SESSION_PORT" to "localhost:5000", + "DEBUG_SESSION_TOKEN" to "123" + ), + true, + parameters.startBrowserAction, + null, + "", + true + ) } } \ No newline at end of file diff --git a/src/main/kotlin/com/github/rafaelldi/aspireplugin/run/AspireHostProgramRunner.kt b/src/main/kotlin/com/github/rafaelldi/aspireplugin/run/AspireHostProgramRunner.kt new file mode 100644 index 00000000..efd99a72 --- /dev/null +++ b/src/main/kotlin/com/github/rafaelldi/aspireplugin/run/AspireHostProgramRunner.kt @@ -0,0 +1,8 @@ +package com.github.rafaelldi.aspireplugin.run + +import com.intellij.execution.configurations.RunProfile +import com.jetbrains.rider.debugger.DotNetProgramRunner + +class AspireHostProgramRunner : DotNetProgramRunner() { + override fun canRun(executorId: String, runConfiguration: RunProfile) = runConfiguration is AspireHostConfiguration +} \ No newline at end of file diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index e3d667d8..d0c5c94e 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -11,6 +11,7 @@ +