Skip to content

Commit

Permalink
[scalatest] ignore org.scalatest.Assertions classname when processi…
Browse files Browse the repository at this point in the history
…ng StackDepthException #SCL-21627 fixed

See scalatest/scalatest#2286 for the details.
It's better not to show any class name at all than to show a wrong one (`Assertions`).
Navigation will still work based on the file name.
However, we don't have a file path, we only have a short file name.
When we have multiple files with the same name, IDEA will show a chooser tooltip so the user can manually choose which file to open
  • Loading branch information
unkarjedy committed Sep 26, 2023
1 parent 532b670 commit 3b9dd67
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 7 deletions.
Expand Up @@ -19,7 +19,10 @@
import static org.jetbrains.plugins.scala.testingSupport.TestRunnerUtil.formatTimestamp;

/**
* Reporter for sequential execution of scalaTest test suites. Do not use it with -P key (parallel execution of suites).
* Reporter for sequential execution of scalaTest test suites.<br>
* Do not use it with -P key (parallel execution of suites).
* <p>
* See also {@code org.jetbrains.plugins.scala.testingSupport.util.scalatest.ScalaTestFailureLocationFilter}
*/
public class ScalaTestReporterWithLocation implements Reporter {
private TreeBuilder treeBuilder = new ParallelTreeBuilder();
Expand Down Expand Up @@ -119,7 +122,11 @@ public void apply(Event event) {

String className = stackTraceElement != null ? stackTraceElement.getClassName() : null;
if (fileNameAndLineNumber instanceof Some && className != null) {
failureLocation = "\nScalaTestFailureLocation: " + className + " at (" + fileNameAndLineNumber.get() + ")";
//NOTE: it's a workaround for SCL-21627 and https://github.com/scalatest/scalatest/issues/2286
// "org.scalatest.Assertions" means that stack trace item with original test position was not properly detected
boolean isAcceptableClassName = !className.equals("org.scalatest.Assertions");
String optionalClassPrefix = isAcceptableClassName ? className + " " : "";
failureLocation = "\nScalaTestFailureLocation: " + optionalClassPrefix + "at (" + fileNameAndLineNumber.get() + ")";
}
}
}
Expand Down
Expand Up @@ -17,14 +17,16 @@


/**
* A custom console outpit filter to build hyperlinks to exact test failure location in ScalaTest. Pretty much copies
* {@link com.intellij.execution.filters.ExceptionFilter}.
* A custom console output filter to build hyperlinks to exact test failure location in ScalaTest.<br>
* Pretty much copies {@link com.intellij.execution.filters.ExceptionFilter}.
*/
public class ScalaTestFailureLocationFilter implements Filter {

private final ExceptionInfoCache myCache;

// private final static Pattern fqnPattern = Pattern.compile("(\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*\\.)+\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*");

//See org.jetbrains.plugins.scala.testingSupport.scalaTest.ScalaTestReporterWithLocation.apply
private final static String testFailureLocationPrefix = "ScalaTestFailureLocation: ";

public ScalaTestFailureLocationFilter(@NotNull final Project project, @NotNull final GlobalSearchScope scope) {
Expand All @@ -36,10 +38,9 @@ public ScalaTestFailureLocationFilter(@NotNull final Project project, @NotNull f
public Result applyFilter(String line, int entireLength) {
Project myProject = myCache.getProject();
if (!line.startsWith(testFailureLocationPrefix)) return null;
int atKeywordLocation = line.indexOf(" at ");
final int atKeywordLocation = line.indexOf(" at ");
if (atKeywordLocation < 0) return null;
//get class name and make sure it is a fqn
String className = line.substring(testFailureLocationPrefix.length(), atKeywordLocation);
// if (!fqnPattern.matcher(className).matches()) return null;
int lparenthIndex = line.lastIndexOf("(");
int rparenthIndex = line.lastIndexOf(")");
Expand All @@ -50,9 +51,15 @@ public Result applyFilter(String line, int entireLength) {
int lineNumber = ScalaTestFailureLocationFilter.getLineNumber(fileAndLine.substring(colonIndex + 1));
if (lineNumber < 0) return null;
final var fileName = fileAndLine.substring(0, colonIndex).trim();

//NOTE: class name can be empty (see examples in SCL-21627 and https://github.com/scalatest/scalatest/issues/2286)
//in this case only file name will be used during resolution under the hood
final String className = line.substring(testFailureLocationPrefix.length(), atKeywordLocation).trim();
final var resolutionResult = myCache.resolveClassOrFile(className, fileName);

final var virtualFiles = resolutionResult.getClasses().keySet().stream().toList();
if (virtualFiles.isEmpty()) return null;
if (virtualFiles.isEmpty())
return null;

final int textStartOffset = entireLength - line.length();

Expand Down

0 comments on commit 3b9dd67

Please sign in to comment.