From b17c3b0ea2460c7a414d5a483d52e7b40bb5b861 Mon Sep 17 00:00:00 2001 From: "Pieter van den Hombergh (homberghp)" Date: Sat, 7 Jun 2025 16:40:10 +0200 Subject: [PATCH 1/9] solves issue8567 by reversing order of stack evaluation This version works for ant projects. --- .../junit/ant/ui/AntJUnitNodeOpener.java | 40 +++++++++++++------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java b/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java index 7742482d8225..ba6e16ccbf38 100644 --- a/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java +++ b/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java @@ -29,6 +29,7 @@ import javax.lang.model.element.ExecutableElement; import javax.lang.model.util.ElementFilter; import javax.swing.Action; +import jdk.internal.net.http.common.Log; import org.netbeans.api.extexecution.print.LineConvertors.FileLocator; import org.netbeans.api.java.source.CompilationController; import org.netbeans.api.java.source.JavaSource; @@ -38,6 +39,8 @@ import org.netbeans.modules.gsf.testrunner.api.CommonUtils; import org.netbeans.modules.gsf.testrunner.ui.api.TestMethodNode; import org.netbeans.modules.gsf.testrunner.ui.api.TestsuiteNode; +import org.netbeans.modules.java.testrunner.JavaRegexpPatterns; +import org.netbeans.modules.java.testrunner.JavaRegexpUtils; import org.openide.ErrorManager; import org.openide.filesystems.FileObject; import org.netbeans.modules.junit.api.JUnitTestSuite; @@ -157,6 +160,7 @@ public void openCallstackFrame(Node node, String frameInfo) { } // Method node might belong to an inner class FileObject testfo = methodNode.getTestcase().getClassFileObject(true); + String fqMethodName = methodNode.getTestcase().getClassName() + '.' + methodNode.getTestcase().getName(); if(testfo == null) { return; } @@ -164,22 +168,34 @@ public void openCallstackFrame(Node node, String frameInfo) { FileObject file = UIJavaUtils.getFile(frameInfo, lineNumStorage, locator); //lineNumStorage -1 means no regexp for stacktrace was matched. if ((file == null) && (methodNode.getTestcase().getTrouble() != null) && lineNumStorage[0] == -1) { - //213935 we could not recognize the stack trace line and map it to known file - //if it's a failure text, grab the testcase's own line from the stack. - boolean methodNodeParentOfStackTraceNode = false; String[] st = methodNode.getTestcase().getTrouble().getStackTrace(); if ((st != null) && (st.length > 0)) { - int index = st.length - 1; - //213935 we need to find the testcase linenumber to jump to. + int index = 0;//st.length - 1; + //Jump to the first line matching the fully qualified test method name. // and ignore the infrastructure stack lines in the process - while (!testfo.equals(file) && index != -1 && !methodNodeParentOfStackTraceNode) { - file = UIJavaUtils.getFile(st[index], lineNumStorage, locator); - index = index - 1; - // if frameInfo.isEmpty() == true, user clicked on a failed method node. - // Try to find if the stack trace node is relevant to the method node - if(file != null && frameInfo.isEmpty()) { - methodNodeParentOfStackTraceNode = FileUtil.isParentOf(testfo.getParent(), file); + while (index < st.length) { + if (st[index].contains(fqMethodName)) { + file = UIJavaUtils.getFile(st[index], lineNumStorage, locator); + break; } + index++; + } + // if not found, return top line of stack trace. + if (index == st.length) { + index=0; + while(true) { + String trimmed=JavaRegexpUtils.specialTrim(st[index]); + if (trimmed.startsWith(JavaRegexpUtils.CALLSTACK_LINE_PREFIX_CATCH) || + trimmed.startsWith(JavaRegexpUtils.CALLSTACK_LINE_PREFIX )){ + file = UIJavaUtils.getFile(st[index], lineNumStorage, locator); + break; + } + } + } + // if that fails, return the test file object. + if (file == null) { + + file = testfo; } } } From 01a18c722f68862ff47cf95b8ce071e07df94f54 Mon Sep 17 00:00:00 2001 From: Pieter van den Hombergh Date: Sun, 9 Nov 2025 11:12:40 +0100 Subject: [PATCH 2/9] Update java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matthias Bläsing --- .../org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java b/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java index ba6e16ccbf38..cc3cc311a5a6 100644 --- a/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java +++ b/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java @@ -183,7 +183,7 @@ public void openCallstackFrame(Node node, String frameInfo) { // if not found, return top line of stack trace. if (index == st.length) { index=0; - while(true) { + for(index=0; index < st.length; index++) { String trimmed=JavaRegexpUtils.specialTrim(st[index]); if (trimmed.startsWith(JavaRegexpUtils.CALLSTACK_LINE_PREFIX_CATCH) || trimmed.startsWith(JavaRegexpUtils.CALLSTACK_LINE_PREFIX )){ From c1f58c14a78dfe979db8d5bb753045f0b7c0b71d Mon Sep 17 00:00:00 2001 From: "Pieter van den Hombergh (homberghp)" Date: Tue, 31 Mar 2026 14:58:36 +0200 Subject: [PATCH 3/9] cleanup --- .../org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java b/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java index cc3cc311a5a6..6b5a7fcab074 100644 --- a/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java +++ b/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java @@ -182,7 +182,6 @@ public void openCallstackFrame(Node node, String frameInfo) { } // if not found, return top line of stack trace. if (index == st.length) { - index=0; for(index=0; index < st.length; index++) { String trimmed=JavaRegexpUtils.specialTrim(st[index]); if (trimmed.startsWith(JavaRegexpUtils.CALLSTACK_LINE_PREFIX_CATCH) || @@ -194,7 +193,6 @@ public void openCallstackFrame(Node node, String frameInfo) { } // if that fails, return the test file object. if (file == null) { - file = testfo; } } From f7d12cabd73a9df982ab2a0ea04a67b238902a3b Mon Sep 17 00:00:00 2001 From: "Pieter van den Hombergh (homberghp)" Date: Tue, 31 Mar 2026 15:03:32 +0200 Subject: [PATCH 4/9] cleanup --- .../modules/junit/ant/ui/AntJUnitNodeOpener.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java b/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java index 6b5a7fcab074..4d8667dc3a82 100644 --- a/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java +++ b/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java @@ -161,9 +161,9 @@ public void openCallstackFrame(Node node, String frameInfo) { // Method node might belong to an inner class FileObject testfo = methodNode.getTestcase().getClassFileObject(true); String fqMethodName = methodNode.getTestcase().getClassName() + '.' + methodNode.getTestcase().getName(); - if(testfo == null) { - return; - } + if (testfo == null) { + return; + } final int[] lineNumStorage = new int[1]; FileObject file = UIJavaUtils.getFile(frameInfo, lineNumStorage, locator); //lineNumStorage -1 means no regexp for stacktrace was matched. @@ -182,10 +182,10 @@ public void openCallstackFrame(Node node, String frameInfo) { } // if not found, return top line of stack trace. if (index == st.length) { - for(index=0; index < st.length; index++) { - String trimmed=JavaRegexpUtils.specialTrim(st[index]); - if (trimmed.startsWith(JavaRegexpUtils.CALLSTACK_LINE_PREFIX_CATCH) || - trimmed.startsWith(JavaRegexpUtils.CALLSTACK_LINE_PREFIX )){ + for (index = 0; index < st.length; index++) { + String trimmed = JavaRegexpUtils.specialTrim(st[index]); + if (trimmed.startsWith(JavaRegexpUtils.CALLSTACK_LINE_PREFIX_CATCH) + || trimmed.startsWith(JavaRegexpUtils.CALLSTACK_LINE_PREFIX)) { file = UIJavaUtils.getFile(st[index], lineNumStorage, locator); break; } From 4cd73a46aa72680b7da0cb5b569a0f712b4a47cd Mon Sep 17 00:00:00 2001 From: "Pieter van den Hombergh (homberghp)" Date: Tue, 31 Mar 2026 23:02:11 +0200 Subject: [PATCH 5/9] applied cleanup as suggested by matthiasblaesing --- .../org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java b/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java index 4d8667dc3a82..697dafee4ea2 100644 --- a/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java +++ b/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java @@ -187,7 +187,9 @@ public void openCallstackFrame(Node node, String frameInfo) { if (trimmed.startsWith(JavaRegexpUtils.CALLSTACK_LINE_PREFIX_CATCH) || trimmed.startsWith(JavaRegexpUtils.CALLSTACK_LINE_PREFIX)) { file = UIJavaUtils.getFile(st[index], lineNumStorage, locator); - break; + if (testfo.equals(file)) { + break; + } } } } From b17b9e27421d09124b26dbdb03d648f368c83688 Mon Sep 17 00:00:00 2001 From: "Pieter van den Hombergh (homberghp)" Date: Tue, 31 Mar 2026 23:10:52 +0200 Subject: [PATCH 6/9] when file not found, use methodnode to open the testMethod --- .../org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java b/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java index 697dafee4ea2..6a5b09112f94 100644 --- a/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java +++ b/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java @@ -195,7 +195,8 @@ public void openCallstackFrame(Node node, String frameInfo) { } // if that fails, return the test file object. if (file == null) { - file = testfo; + openTestMethod(methodNode); + return; } } } From a4c98e03467fc2b785975b271a7dea2ac4f3b67d Mon Sep 17 00:00:00 2001 From: "Pieter van den Hombergh (homberghp)" Date: Thu, 2 Apr 2026 13:37:55 +0200 Subject: [PATCH 7/9] reset the values so that the fallback ... can correctly hit. Suggested by matthiasblaesing. --- .../org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java b/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java index 6a5b09112f94..91800438e9de 100644 --- a/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java +++ b/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java @@ -189,6 +189,9 @@ public void openCallstackFrame(Node node, String frameInfo) { file = UIJavaUtils.getFile(st[index], lineNumStorage, locator); if (testfo.equals(file)) { break; + } else { + file = null; + lineNumStorage[0] = -1; } } } From f0f8efae51d15e3a98401cb0ae6f6e0337634356 Mon Sep 17 00:00:00 2001 From: "Pieter van den Hombergh (homberghp)" Date: Sat, 4 Apr 2026 22:35:59 +0200 Subject: [PATCH 8/9] 2nd loop in stack-natural top down order. --- .../netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java b/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java index 91800438e9de..455c69743785 100644 --- a/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java +++ b/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java @@ -29,7 +29,6 @@ import javax.lang.model.element.ExecutableElement; import javax.lang.model.util.ElementFilter; import javax.swing.Action; -import jdk.internal.net.http.common.Log; import org.netbeans.api.extexecution.print.LineConvertors.FileLocator; import org.netbeans.api.java.source.CompilationController; import org.netbeans.api.java.source.JavaSource; @@ -160,7 +159,7 @@ public void openCallstackFrame(Node node, String frameInfo) { } // Method node might belong to an inner class FileObject testfo = methodNode.getTestcase().getClassFileObject(true); - String fqMethodName = methodNode.getTestcase().getClassName() + '.' + methodNode.getTestcase().getName(); + String fqMethodNameParen = methodNode.getTestcase().getClassName() + '.' + methodNode.getTestcase().getName()+'('; if (testfo == null) { return; } @@ -174,7 +173,7 @@ public void openCallstackFrame(Node node, String frameInfo) { //Jump to the first line matching the fully qualified test method name. // and ignore the infrastructure stack lines in the process while (index < st.length) { - if (st[index].contains(fqMethodName)) { + if (st[index].contains(fqMethodNameParen)) { file = UIJavaUtils.getFile(st[index], lineNumStorage, locator); break; } From bafc4278ad38977f4bacd7f0904022d50bd937b3 Mon Sep 17 00:00:00 2001 From: "Pieter van den Hombergh (homberghp)" Date: Sat, 7 Jun 2025 16:40:10 +0200 Subject: [PATCH 9/9] solves issue8567 by correcting stack evaluation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This version works for ant projects. Update java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java Co-authored-by: Matthias Bläsing --- .../junit/ant/ui/AntJUnitNodeOpener.java | 49 +++++++++++++------ 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java b/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java index 7742482d8225..455c69743785 100644 --- a/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java +++ b/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java @@ -38,6 +38,8 @@ import org.netbeans.modules.gsf.testrunner.api.CommonUtils; import org.netbeans.modules.gsf.testrunner.ui.api.TestMethodNode; import org.netbeans.modules.gsf.testrunner.ui.api.TestsuiteNode; +import org.netbeans.modules.java.testrunner.JavaRegexpPatterns; +import org.netbeans.modules.java.testrunner.JavaRegexpUtils; import org.openide.ErrorManager; import org.openide.filesystems.FileObject; import org.netbeans.modules.junit.api.JUnitTestSuite; @@ -157,30 +159,47 @@ public void openCallstackFrame(Node node, String frameInfo) { } // Method node might belong to an inner class FileObject testfo = methodNode.getTestcase().getClassFileObject(true); - if(testfo == null) { - return; - } + String fqMethodNameParen = methodNode.getTestcase().getClassName() + '.' + methodNode.getTestcase().getName()+'('; + if (testfo == null) { + return; + } final int[] lineNumStorage = new int[1]; FileObject file = UIJavaUtils.getFile(frameInfo, lineNumStorage, locator); //lineNumStorage -1 means no regexp for stacktrace was matched. if ((file == null) && (methodNode.getTestcase().getTrouble() != null) && lineNumStorage[0] == -1) { - //213935 we could not recognize the stack trace line and map it to known file - //if it's a failure text, grab the testcase's own line from the stack. - boolean methodNodeParentOfStackTraceNode = false; String[] st = methodNode.getTestcase().getTrouble().getStackTrace(); if ((st != null) && (st.length > 0)) { - int index = st.length - 1; - //213935 we need to find the testcase linenumber to jump to. + int index = 0;//st.length - 1; + //Jump to the first line matching the fully qualified test method name. // and ignore the infrastructure stack lines in the process - while (!testfo.equals(file) && index != -1 && !methodNodeParentOfStackTraceNode) { - file = UIJavaUtils.getFile(st[index], lineNumStorage, locator); - index = index - 1; - // if frameInfo.isEmpty() == true, user clicked on a failed method node. - // Try to find if the stack trace node is relevant to the method node - if(file != null && frameInfo.isEmpty()) { - methodNodeParentOfStackTraceNode = FileUtil.isParentOf(testfo.getParent(), file); + while (index < st.length) { + if (st[index].contains(fqMethodNameParen)) { + file = UIJavaUtils.getFile(st[index], lineNumStorage, locator); + break; + } + index++; + } + // if not found, return top line of stack trace. + if (index == st.length) { + for (index = 0; index < st.length; index++) { + String trimmed = JavaRegexpUtils.specialTrim(st[index]); + if (trimmed.startsWith(JavaRegexpUtils.CALLSTACK_LINE_PREFIX_CATCH) + || trimmed.startsWith(JavaRegexpUtils.CALLSTACK_LINE_PREFIX)) { + file = UIJavaUtils.getFile(st[index], lineNumStorage, locator); + if (testfo.equals(file)) { + break; + } else { + file = null; + lineNumStorage[0] = -1; + } + } } } + // if that fails, return the test file object. + if (file == null) { + openTestMethod(methodNode); + return; + } } } UIJavaUtils.openFile(file, lineNumStorage[0]);