[platform, debugger] Refactor attach host and host provider for coroutines support.

GitOrigin-RevId: 11f15a4de6d9054b9bf661e3a720a5f585f7dfce
This commit is contained in:
Alexander.Bondarev
2024-09-03 17:23:25 +02:00
committed by intellij-monorepo-bot
parent fc982f9baa
commit 9d36e55285
8 changed files with 128 additions and 88 deletions

View File

@@ -39,12 +39,26 @@ com.intellij.xdebugger.attach.XAttachDebuggerProvider
- a:isAttachHostApplicable(com.intellij.xdebugger.attach.XAttachHost):Z
com.intellij.xdebugger.attach.XAttachHost
- a:getProcessList():java.util.List
- getProcessListAsync(kotlin.coroutines.Continuation):java.lang.Object
- bs:getProcessListAsync$suspendImpl(com.intellij.xdebugger.attach.XAttachHost,kotlin.coroutines.Continuation):java.lang.Object
com.intellij.xdebugger.attach.XAttachHost$Async
- com.intellij.xdebugger.attach.XAttachHost
- getProcessList():java.util.List
- a:getProcessListAsync(kotlin.coroutines.Continuation):java.lang.Object
com.intellij.xdebugger.attach.XAttachHostPresentationGroup
- com.intellij.xdebugger.attach.XAttachPresentationGroup
com.intellij.xdebugger.attach.XAttachHostProvider
- sf:Companion:com.intellij.xdebugger.attach.XAttachHostProvider$Companion
- sf:EP:com.intellij.openapi.extensions.ExtensionPointName
- a:getAvailableHosts(com.intellij.openapi.project.Project):java.util.List
- getAvailableHostsAsync(com.intellij.openapi.project.Project,kotlin.coroutines.Continuation):java.lang.Object
- bs:getAvailableHostsAsync$suspendImpl(com.intellij.xdebugger.attach.XAttachHostProvider,com.intellij.openapi.project.Project,kotlin.coroutines.Continuation):java.lang.Object
- a:getPresentationGroup():com.intellij.xdebugger.attach.XAttachPresentationGroup
com.intellij.xdebugger.attach.XAttachHostProvider$Async
- com.intellij.xdebugger.attach.XAttachHostProvider
- getAvailableHosts(com.intellij.openapi.project.Project):java.util.List
- a:getAvailableHostsAsync(com.intellij.openapi.project.Project,kotlin.coroutines.Continuation):java.lang.Object
f:com.intellij.xdebugger.attach.XAttachHostProvider$Companion
com.intellij.xdebugger.attach.XAttachPresentationGroup
- java.util.Comparator
- a:getGroupName():java.lang.String

View File

@@ -1,33 +0,0 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.xdebugger.attach;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.process.ProcessInfo;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* This interface describes the host(local or remote), from which list of processes can be obtained
*/
public interface XAttachHost {
/**
* @return a list of running processes on this host
*/
@NotNull
List<ProcessInfo> getProcessList() throws ExecutionException;
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.xdebugger.attach
import com.intellij.execution.ExecutionException
import com.intellij.execution.process.ProcessInfo
import com.intellij.openapi.progress.runBlockingCancellable
/**
* This interface describes the host(local or remote), from which list of processes can be obtained
*/
interface XAttachHost {
/**
* @return a list of running processes on this host
*/
@Throws(ExecutionException::class)
@Deprecated("Use getProcessListAsync", replaceWith = ReplaceWith("getProcessListAsync"))
fun getProcessList(): List<ProcessInfo>
/**
* @return a list of running processes on this host
*/
@Suppress("DEPRECATION")
@Throws(ExecutionException::class)
suspend fun getProcessListAsync(): List<ProcessInfo> = getProcessList()
@Suppress("OVERRIDE_DEPRECATION")
interface Async : XAttachHost {
override fun getProcessList(): List<ProcessInfo> = runBlockingCancellable { getProcessListAsync() }
override suspend fun getProcessListAsync(): List<ProcessInfo>
}
}

View File

@@ -1,44 +0,0 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.xdebugger.attach;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* This interface describes the provider to enumerate different hosts/environments capable of attaching to with the debugger.
* The examples are local machine environment (see {@link LocalAttachHost}) or SSH connection to a remote server.
*/
public interface XAttachHostProvider<T extends XAttachHost> {
ExtensionPointName<XAttachHostProvider> EP = ExtensionPointName.create("com.intellij.xdebugger.attachHostProvider");
/**
* @return the group to which all connections provided by this provider belong
*/
@NotNull
XAttachPresentationGroup<? extends XAttachHost> getPresentationGroup();
/**
* @return a list of connections of this type, which is characterized by the provider
*/
@NotNull
List<T> getAvailableHosts(@Nullable Project project);
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.xdebugger.attach
import com.intellij.openapi.extensions.ExtensionPointName
import com.intellij.openapi.extensions.ExtensionPointName.Companion.create
import com.intellij.openapi.progress.runBlockingCancellable
import com.intellij.openapi.project.Project
/**
* This interface describes the provider to enumerate different hosts/environments capable of attaching to with the debugger.
* The examples are local machine environment (see [LocalAttachHost]) or SSH connection to a remote server.
*/
interface XAttachHostProvider<T : XAttachHost> {
companion object {
@JvmField
val EP: ExtensionPointName<XAttachHostProvider<*>> = create<XAttachHostProvider<*>>("com.intellij.xdebugger.attachHostProvider")
}
/**
* @return the group to which all connections provided by this provider belong
*/
fun getPresentationGroup(): XAttachPresentationGroup<out XAttachHost>
/**
* @return a list of connections of this type, which is characterized by the provider
*/
@Deprecated("Use getAvailableHostsAsync", replaceWith = ReplaceWith("getAvailableHostsAsync"))
fun getAvailableHosts(project: Project?): List<T>
/**
* @return a list of connections of this type, which is characterized by the provider
*/
@Suppress("DEPRECATION")
suspend fun getAvailableHostsAsync(project: Project?) = getAvailableHosts(project)
interface Async<T : XAttachHost> : XAttachHostProvider<T> {
@Deprecated("Use getAvailableHostsAsync", replaceWith = ReplaceWith("getAvailableHostsAsync"))
override fun getAvailableHosts(project: Project?): List<T> = runBlockingCancellable { getAvailableHostsAsync(project) }
override suspend fun getAvailableHostsAsync(project: Project?): List<T>
}
}

View File

@@ -4,7 +4,6 @@ package com.intellij.xdebugger.impl.ui.attach.dialog
import com.intellij.execution.ExecutionException
import com.intellij.execution.process.ProcessInfo
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.progress.coroutineToIndicator
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.UserDataHolderBase
import com.intellij.xdebugger.attach.XAttachDebuggerProvider
@@ -32,9 +31,7 @@ suspend fun collectAttachProcessItemsGroupByProcessInfo(
host: XAttachHost,
attachDebuggerProviders: List<XAttachDebuggerProvider>): AttachItemsInfo {
try {
val processes = coroutineToIndicator {
host.processList
}
val processes = host.getProcessListAsync()
val debuggerProviders = attachDebuggerProviders.filter { it.isAttachHostApplicable(host) }
val dataHolder = UserDataHolderBase()
@@ -69,7 +66,7 @@ suspend fun collectAttachProcessItemsGroupByProcessInfo(
catch (cancellationException: CancellationException) {
throw cancellationException
}
catch (executionException: ExecutionException) {
catch (_: ExecutionException) {
return AttachItemsInfo.EMPTY
}
catch (t: Throwable) {

View File

@@ -23,7 +23,7 @@ data class AttachHostAndProvider(
@Nls
override fun getPresentation(): String {
val presentationGroup = provider.presentationGroup as XAttachPresentationGroup<XAttachHost>
val presentationGroup = provider.getPresentationGroup() as XAttachPresentationGroup<XAttachHost>
return presentationGroup.getItemDisplayText(project, host, dataHolder)
}
@@ -33,7 +33,7 @@ data class AttachHostAndProvider(
}
override fun getIcon(): Icon {
val presentationGroup = provider.presentationGroup as XAttachPresentationGroup<XAttachHost>
val presentationGroup = provider.getPresentationGroup() as XAttachPresentationGroup<XAttachHost>
return presentationGroup.getItemIcon(project, host, dataHolder)
}

View File

@@ -14,6 +14,9 @@ import com.intellij.xdebugger.attach.XAttachHostProvider
import com.intellij.xdebugger.impl.actions.AttachToProcessAction
import com.intellij.xdebugger.impl.ui.attach.dialog.extensions.XAttachHostSettingsProvider
import com.intellij.xdebugger.impl.ui.attach.dialog.items.columns.AttachDialogColumnsLayout
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.coroutineScope
internal class AttachToRemoteProcessView(private val project: Project,
state: AttachDialogState,
@@ -47,9 +50,11 @@ internal class AttachToRemoteProcessView(private val project: Project,
override suspend fun getHosts(): List<AttachHostAndProvider> {
val dataHolder = UserDataHolderBase()
return attachHostProviders.flatMap { provider ->
provider.getAvailableHosts(project).map { AttachHostAndProvider(it, provider, project, dataHolder) }
}
return coroutineScope {
attachHostProviders.map { provider ->
async { provider.getAvailableHostsAsync(project).map { AttachHostAndProvider(it, provider, project, dataHolder) } }
}.awaitAll()
}.flatten()
}
override fun openSettings() {
@@ -93,7 +98,7 @@ internal class AttachToRemoteProcessView(private val project: Project,
override fun getHostActions(hosts: Set<AttachHostItem>, selectHost: (host: AttachHostItem) -> Unit): List<AnAction> {
val actions = mutableListOf<AnAction>()
for (providerAndHosts in hosts.filterIsInstance<AttachHostAndProvider>().groupBy { it.provider }.toList().sortedBy { it.first.presentationGroup.order }) {
for (providerAndHosts in hosts.filterIsInstance<AttachHostAndProvider>().groupBy { it.provider }.toList().sortedBy { it.first.getPresentationGroup().order }) {
for (host in providerAndHosts.second) {
actions.add(object : AnAction({ host.getPresentation() }, host.getIcon()) {
override fun actionPerformed(e: AnActionEvent) {