mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-10-06 06:21:16 +07:00
[java-debugger][IDEA-375478] use eel api to provide the java-agent path
GitOrigin-RevId: d8d26f7200c617c5d537c7a1439c11d16f12a853
This commit is contained in:
committed by
intellij-monorepo-bot
parent
3e7f0329bf
commit
1f41a5f75f
@@ -28,9 +28,12 @@ import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.io.FileUtilRt;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.platform.eel.EelDescriptor;
|
||||
import com.intellij.platform.eel.annotations.NativePath;
|
||||
import com.intellij.platform.eel.provider.EelProviderUtil;
|
||||
import com.intellij.platform.eel.provider.LocalEelDescriptor;
|
||||
import com.intellij.platform.eel.provider.utils.EelPathUtils;
|
||||
import com.intellij.util.PathUtil;
|
||||
import com.intellij.util.SlowOperations;
|
||||
@@ -49,6 +52,8 @@ import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
|
||||
import static com.intellij.platform.eel.provider.EelNioBridgeServiceKt.asEelPath;
|
||||
|
||||
public final class AsyncStacksUtils {
|
||||
private static final Logger LOG = Logger.getInstance(AsyncStacksUtils.class);
|
||||
// TODO: obtain CaptureStorage fqn from the class somehow
|
||||
@@ -316,39 +321,35 @@ public final class AsyncStacksUtils {
|
||||
return;
|
||||
}
|
||||
|
||||
Path agentArtifactPath = getAgentArtifactPath(disposable);
|
||||
if (Files.exists(agentArtifactPath)) {
|
||||
String agentPath = JavaExecutionUtil.handleSpacesInAgentPath(agentArtifactPath.toAbsolutePath().toString(),
|
||||
"captureAgent", null,
|
||||
f -> f.getName().startsWith("debugger-agent"));
|
||||
if (agentPath != null) {
|
||||
try (AccessToken ignore = SlowOperations.knownIssue("IDEA-307303, EA-835503")) {
|
||||
parametersList.prepend(prefix + agentPath + generateAgentSettings(project));
|
||||
String agentPath = getAgentArtifactPath(project, disposable);
|
||||
if (agentPath != null) {
|
||||
try (AccessToken ignore = SlowOperations.knownIssue("IDEA-307303, EA-835503")) {
|
||||
parametersList.prepend(prefix + agentPath + generateAgentSettings(project));
|
||||
}
|
||||
if (Registry.is("debugger.async.stacks.coroutines", false)) {
|
||||
parametersList.addProperty("kotlinx.coroutines.debug.enable.creation.stack.trace", "false");
|
||||
parametersList.addProperty("debugger.agent.enable.coroutines", "true");
|
||||
if (Registry.is("debugger.async.stacks.flows", false)) {
|
||||
parametersList.addProperty("kotlinx.coroutines.debug.enable.flows.stack.trace", "true");
|
||||
}
|
||||
if (Registry.is("debugger.async.stacks.coroutines", false)) {
|
||||
parametersList.addProperty("kotlinx.coroutines.debug.enable.creation.stack.trace", "false");
|
||||
parametersList.addProperty("debugger.agent.enable.coroutines", "true");
|
||||
if (Registry.is("debugger.async.stacks.flows", false)) {
|
||||
parametersList.addProperty("kotlinx.coroutines.debug.enable.flows.stack.trace", "true");
|
||||
}
|
||||
if (Registry.is("debugger.async.stacks.state.flows", false)) {
|
||||
parametersList.addProperty("kotlinx.coroutines.debug.enable.mutable.state.flows.stack.trace", "true");
|
||||
}
|
||||
}
|
||||
if (!Registry.is("debugger.async.stack.trace.for.exceptions.printing", false)) {
|
||||
parametersList.addProperty("debugger.agent.support.throwable", "false");
|
||||
}
|
||||
if (Registry.is("debugger.async.stack.trace.for.all.threads")) {
|
||||
parametersList.addProperty("debugger.async.stack.trace.for.all.threads", "true");
|
||||
if (Registry.is("debugger.async.stacks.state.flows", false)) {
|
||||
parametersList.addProperty("kotlinx.coroutines.debug.enable.mutable.state.flows.stack.trace", "true");
|
||||
}
|
||||
}
|
||||
if (!Registry.is("debugger.async.stack.trace.for.exceptions.printing", false)) {
|
||||
parametersList.addProperty("debugger.agent.support.throwable", "false");
|
||||
}
|
||||
if (Registry.is("debugger.async.stack.trace.for.all.threads")) {
|
||||
parametersList.addProperty("debugger.async.stack.trace.for.all.threads", "true");
|
||||
}
|
||||
}
|
||||
else {
|
||||
LOG.error("Capture agent not found: " + agentArtifactPath);
|
||||
LOG.error("Capture agent not found: " + agentPath);
|
||||
}
|
||||
}
|
||||
|
||||
private static @NotNull Path getAgentArtifactPath(@Nullable Disposable disposable) {
|
||||
@NativePath
|
||||
private static @Nullable String getAgentArtifactPath(@Nullable Project project, @Nullable Disposable disposable) {
|
||||
String relevantJarsRoot = PathManager.getArchivedCompliedClassesLocation();
|
||||
Path classesRoot = Path.of(PathUtil.getJarPathForClass(DebuggerManagerImpl.class));
|
||||
// isDirectory(classesRoot) is used instead of `PluginManagerCore.isRunningFromSources()`
|
||||
@@ -356,43 +357,79 @@ public final class AsyncStacksUtils {
|
||||
// where the layout is quite the same as in installers.
|
||||
// but `PluginManagerCore.isRunningFromSources()` still returns `true` in this case
|
||||
if (Files.isDirectory(classesRoot) || (relevantJarsRoot != null && classesRoot.startsWith(relevantJarsRoot))) {
|
||||
// Code runs from IDEA run configuration (code from .class file in out/ directory)
|
||||
try {
|
||||
// The agent file must have a fixed name (AGENT_JAR_NAME) which is mentioned in MANIFEST.MF inside
|
||||
Path debuggerAgentDir =
|
||||
FileUtil.createTempDirectory(new File(PathManager.getTempPath()), "debugger-agent", "", disposable == null).toPath();
|
||||
if (disposable != null) {
|
||||
Disposer.register(disposable, () -> {
|
||||
try {
|
||||
FileUtilRt.deleteRecursively(debuggerAgentDir);
|
||||
}
|
||||
catch (IOException ignored) {
|
||||
}
|
||||
});
|
||||
}
|
||||
Path agentArtifactPath = debuggerAgentDir.resolve(AGENT_JAR_NAME);
|
||||
|
||||
Path communityRoot = Path.of(PathManager.getCommunityHomePath());
|
||||
Path iml = BuildDependenciesJps.getProjectModule(communityRoot, "intellij.java.debugger.agent.holder");
|
||||
Path downloadedAgent = BuildDependenciesJps.INSTANCE.getModuleLibrarySingleRootSync(
|
||||
iml,
|
||||
"debugger-agent",
|
||||
"https://cache-redirector.jetbrains.com/intellij-dependencies",
|
||||
new BuildDependenciesCommunityRoot(Path.of(PathManager.getCommunityHomePath())));
|
||||
|
||||
Files.copy(downloadedAgent, agentArtifactPath);
|
||||
|
||||
return agentArtifactPath;
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return getArtifactPathForDownloadedAgent(project, disposable);
|
||||
}
|
||||
else {
|
||||
return classesRoot.resolveSibling("rt").resolve(AGENT_JAR_NAME);
|
||||
return getArtifactPathForBundledAgent(classesRoot, project, disposable);
|
||||
}
|
||||
}
|
||||
|
||||
// Code runs from IDEA run configuration (code from .class file in out/ directory)
|
||||
@NativePath
|
||||
private static @NotNull String getArtifactPathForDownloadedAgent(@Nullable Project project, @Nullable Disposable disposable) {
|
||||
try {
|
||||
Path agentArtifactPath = createTemporaryAgentPath(project, disposable);
|
||||
|
||||
Path communityRoot = Path.of(PathManager.getCommunityHomePath());
|
||||
Path iml = BuildDependenciesJps.getProjectModule(communityRoot, "intellij.java.debugger.agent.holder");
|
||||
Path downloadedAgent = BuildDependenciesJps.INSTANCE.getModuleLibrarySingleRootSync(
|
||||
iml,
|
||||
"debugger-agent",
|
||||
"https://cache-redirector.jetbrains.com/intellij-dependencies",
|
||||
new BuildDependenciesCommunityRoot(Path.of(PathManager.getCommunityHomePath())));
|
||||
|
||||
// The agent file must have a fixed name (AGENT_JAR_NAME) which is mentioned in MANIFEST.MF inside
|
||||
Files.copy(downloadedAgent, agentArtifactPath);
|
||||
|
||||
return asEelPath(agentArtifactPath).toString();
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@NativePath
|
||||
private static @Nullable String getArtifactPathForBundledAgent(
|
||||
@NotNull Path classesRoot,
|
||||
@Nullable Project project,
|
||||
@Nullable Disposable disposable
|
||||
) {
|
||||
Path bundledAgentPath = classesRoot.resolveSibling("rt").resolve(AGENT_JAR_NAME);
|
||||
if (!Files.exists(bundledAgentPath)) {
|
||||
return null;
|
||||
}
|
||||
EelDescriptor projectEelDescriptor = project == null ? null : EelProviderUtil.getEelDescriptor(project);
|
||||
if (project == null || LocalEelDescriptor.INSTANCE.equals(projectEelDescriptor)) {
|
||||
return JavaExecutionUtil.handleSpacesInAgentPath(
|
||||
bundledAgentPath.toAbsolutePath().toString(),
|
||||
"captureAgent",
|
||||
null,
|
||||
f -> f.getName().startsWith("debugger-agent")
|
||||
);
|
||||
}
|
||||
Path temporaryAgentPath = createTemporaryAgentPath(project, disposable);
|
||||
EelPathUtils.transferLocalContentToRemote(
|
||||
bundledAgentPath,
|
||||
new EelPathUtils.TransferTarget.Explicit(temporaryAgentPath)
|
||||
);
|
||||
return asEelPath(temporaryAgentPath).toString();
|
||||
}
|
||||
|
||||
private static @NotNull Path createTemporaryAgentPath(@Nullable Project project, @Nullable Disposable disposable) {
|
||||
// The agent file must have a fixed name (AGENT_JAR_NAME) which is mentioned in MANIFEST.MF inside
|
||||
Path debuggerAgentDir = EelPathUtils.createTemporaryDirectory(project, "debugger-agent", "", disposable == null);
|
||||
if (disposable != null) {
|
||||
Disposer.register(disposable, () -> {
|
||||
try {
|
||||
FileUtilRt.deleteRecursively(debuggerAgentDir);
|
||||
}
|
||||
catch (IOException ignored) {
|
||||
}
|
||||
});
|
||||
}
|
||||
return debuggerAgentDir.resolve(AGENT_JAR_NAME);
|
||||
}
|
||||
|
||||
private static String generateAgentSettings(@Nullable Project project) {
|
||||
Properties properties = CaptureSettingsProvider.getPointsProperties(project);
|
||||
if (isSuspendHelperEnabled()) {
|
||||
|
||||
+20
-14
@@ -12,11 +12,7 @@ import com.intellij.platform.eel.fs.createTemporaryDirectory
|
||||
import com.intellij.platform.eel.fs.createTemporaryFile
|
||||
import com.intellij.platform.eel.isWindows
|
||||
import com.intellij.platform.eel.path.EelPath
|
||||
import com.intellij.platform.eel.provider.LocalEelDescriptor
|
||||
import com.intellij.platform.eel.provider.asEelPath
|
||||
import com.intellij.platform.eel.provider.asNioPath
|
||||
import com.intellij.platform.eel.provider.getEelDescriptor
|
||||
import com.intellij.platform.eel.provider.toEelApiBlocking
|
||||
import com.intellij.platform.eel.provider.*
|
||||
import com.intellij.platform.eel.provider.utils.EelPathUtils.transferLocalContentToRemote
|
||||
import com.intellij.util.concurrency.annotations.RequiresBackgroundThread
|
||||
import kotlinx.coroutines.*
|
||||
@@ -105,21 +101,31 @@ object EelPathUtils {
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@OptIn(ExperimentalPathApi::class)
|
||||
@RequiresBackgroundThread(generateAssertion = false)
|
||||
fun createTemporaryDirectory(project: Project?, prefix: String = "", suffix: String = ""): Path {
|
||||
if (project == null || isProjectLocal(project)) {
|
||||
return Files.createTempDirectory(prefix)
|
||||
fun createTemporaryDirectory(project: Project?, prefix: String = "", suffix: String = "", deleteOnExit: Boolean = false): Path {
|
||||
if (project == null || isProjectLocal(project) || project.projectFilePath == null) {
|
||||
val dir = Files.createTempDirectory(prefix)
|
||||
if (deleteOnExit) {
|
||||
Runtime.getRuntime().addShutdownHook(Thread {
|
||||
dir.deleteRecursively()
|
||||
})
|
||||
}
|
||||
return dir
|
||||
}
|
||||
val projectFilePath = project.projectFilePath ?: return Files.createTempDirectory(prefix)
|
||||
return runBlockingMaybeCancellable {
|
||||
val eel = Path.of(projectFilePath).getEelDescriptor().toEelApi()
|
||||
createTemporaryDirectory(eel, prefix, suffix)
|
||||
val eel = Path.of(project.projectFilePath!!).getEelDescriptor().toEelApi()
|
||||
createTemporaryDirectory(eel, prefix, suffix, deleteOnExit)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
suspend fun createTemporaryDirectory(eelApi: EelApi, prefix: String = "", suffix: String = ""): Path {
|
||||
val file = eelApi.fs.createTemporaryDirectory().prefix(prefix).suffix(suffix).getOrThrowFileSystemException()
|
||||
suspend fun createTemporaryDirectory(eelApi: EelApi, prefix: String = "", suffix: String = "", deleteOnExit: Boolean = false): Path {
|
||||
val file = eelApi.fs.createTemporaryDirectory()
|
||||
.prefix(prefix)
|
||||
.suffix(suffix)
|
||||
.deleteOnExit(deleteOnExit)
|
||||
.getOrThrowFileSystemException()
|
||||
return file.asNioPath()
|
||||
}
|
||||
|
||||
@@ -333,7 +339,7 @@ object EelPathUtils {
|
||||
|
||||
private suspend fun EelApi.createTempFor(source: Path, deleteOnExit: Boolean): Path {
|
||||
return if (source.isDirectory()) {
|
||||
fs.createTemporaryDirectory().deleteOnExit(deleteOnExit).getOrThrowFileSystemException().asNioPath()
|
||||
createTemporaryDirectory(eelApi = this, deleteOnExit = deleteOnExit)
|
||||
}
|
||||
else {
|
||||
fs.createTemporaryFile().suffix(source.name).deleteOnExit(deleteOnExit).getOrThrowFileSystemException().asNioPath()
|
||||
|
||||
+2
@@ -108,6 +108,8 @@ class ScriptMavenExecutionTest : MavenExecutionTest() {
|
||||
val debugOpts = debugExecInfo.stdout.lines().singleOrNull { it.startsWith("MAVEN_OPTS") }
|
||||
assertNotNull(debugExecInfo.toString(), debugOpts)
|
||||
assertTrue(debugOpts, debugOpts!!.contains("-agentlib:jdwp=transport=dt_socket"))
|
||||
// maven.use.scripts.debug.agent = true is set to `true` by default
|
||||
assertTrue(debugOpts, debugOpts.contains("debugger-agent.jar"))
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user