From 681f0aaa5e7916ac52bf7e9f498ae0167ce9b702 Mon Sep 17 00:00:00 2001 From: Mikhail Pyltsin Date: Wed, 18 Sep 2024 10:54:45 +0200 Subject: [PATCH] [java-console] IDEA-359033 incorrect place for class name in stacktrace for hprof GitOrigin-RevId: 149d972bbfbecaad86ceec3e29eeba46f35595d1 --- .../execution/filters/ExceptionWorker.java | 8 +++- .../filters/ExceptionWorkerTest.java | 47 ++++++++++++++++--- 2 files changed, 46 insertions(+), 9 deletions(-) diff --git a/java/execution/openapi/src/com/intellij/execution/filters/ExceptionWorker.java b/java/execution/openapi/src/com/intellij/execution/filters/ExceptionWorker.java index 2f61a0b81030..63c3cca6434e 100644 --- a/java/execution/openapi/src/com/intellij/execution/filters/ExceptionWorker.java +++ b/java/execution/openapi/src/com/intellij/execution/filters/ExceptionWorker.java @@ -2,6 +2,8 @@ package com.intellij.execution.filters; import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.text.CharFilter; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -104,7 +106,7 @@ public class ExceptionWorker { @Nullable private static ParsedLine parseStackTraceLine(@NotNull String line, boolean searchForRParenOnlyAfterAt) { int startIdx = findAtPrefix(line); - int rParenIdx = findRParenAfterLocation(line, searchForRParenOnlyAfterAt ? startIdx : 0); + int rParenIdx = findRParenAfterLocation(line, searchForRParenOnlyAfterAt ? startIdx : 0); if (rParenIdx < 0) return null; TextRange methodName = findMethodNameCandidateBefore(line, startIdx, rParenIdx); @@ -126,7 +128,9 @@ public class ExceptionWorker { // consider STANDALONE_AT here classNameIdx = startIdx + 1 + AT.length() + (line.charAt(startIdx) == 'a' ? 0 : 1); } else { - classNameIdx = 0; + //sometimes stacktrace can start with some whitespaces (for example, for hprof -> \t), let's eat them + classNameIdx = StringUtil.findFirst(line, CharFilter.NOT_WHITESPACE_FILTER); + if (classNameIdx < 0) classNameIdx = 0; //let's keep it safe } } diff --git a/java/java-tests/testSrc/com/intellij/java/execution/filters/ExceptionWorkerTest.java b/java/java-tests/testSrc/com/intellij/java/execution/filters/ExceptionWorkerTest.java index aabeb79eb72e..8e96f212071d 100644 --- a/java/java-tests/testSrc/com/intellij/java/execution/filters/ExceptionWorkerTest.java +++ b/java/java-tests/testSrc/com/intellij/java/execution/filters/ExceptionWorkerTest.java @@ -265,7 +265,7 @@ public class ExceptionWorkerTest extends LightJavaCodeInsightFixtureTestCase { """ import java.util.Collections; import java.util.List; - + /** @noinspection ALL*/ class SomeClass { public static void main(String[] args) { @@ -864,7 +864,7 @@ public class ExceptionWorkerTest extends LightJavaCodeInsightFixtureTestCase { /** @noinspection ALL*/ class Test { int length; - + public static void main(String[] args) { int[] arr = new int[0]; Test test = null, test2 = new Test(); @@ -1199,7 +1199,7 @@ public class ExceptionWorkerTest extends LightJavaCodeInsightFixtureTestCase { public void testVarHandle() { myFixture.addClass(""" package java.lang.invoke; - + interface VarHandle{ void set(Object... objects); } @@ -1210,9 +1210,9 @@ public class ExceptionWorkerTest extends LightJavaCodeInsightFixtureTestCase { import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; import java.lang.invoke.VarHandle; - + import static java.lang.foreign.ValueLayout.JAVA_BYTE; - + final class SomeClass { public static void main(String[] args) { var layout = MemoryLayout.structLayout( @@ -1223,11 +1223,11 @@ public class ExceptionWorkerTest extends LightJavaCodeInsightFixtureTestCase { JAVA_BYTE.withName("b"), JAVA_BYTE.withName("a") ).withName("b"); - + VarHandle flags = layout.varHandle( MemoryLayout.PathElement.groupElement("a") ); - + try (Arena arena = Arena.ofConfined()) { MemorySegment memorySegment = arena.allocate(layout); flags.set(memorySegment, 0x1); @@ -1274,6 +1274,39 @@ public class ExceptionWorkerTest extends LightJavaCodeInsightFixtureTestCase { checkColumnFinder(classText, traceAndPositions); } + public void testHprofOutput() { + @Language("JAVA") String classText = + """ + package org.example; + + import java.util.concurrent.ScheduledThreadPoolExecutor; + + public class CustomThreadPoolExecutorImpl extends ScheduledThreadPoolExecutor implements CustomThreadPoolExecutor { + + public CustomThreadPoolExecutorImpl(int corePoolSize) { + super(corePoolSize); + } + + public CustomThreadPoolExecutorImpl() { + super(1); + } + + @Override + public long getTaskCount() { + return getQueue().size(); + } + } + """; + + List traceAndPositions = Arrays.asList( + new LogItem( + "Thread 'main' with ID = 1", null, null), + new LogItem("\tjava.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.size(ScheduledThreadPoolExecutor.java:1069)\n", null, null), + new LogItem("\torg.example.CustomThreadPoolExecutorImpl.getTaskCount(CustomThreadPoolExecutorImpl.java:17)\n", 17, 27)); + + checkColumnFinder(classText, traceAndPositions); + } + public void testParseExceptionLine() { String exceptionLine = "Caused by: java.lang.AssertionError: expected same"; ExceptionInfo info = ExceptionInfo.parseMessage(exceptionLine, exceptionLine.length());