I am trying to find logging lines in a project that log a throwable incorrectly. Examples of correct and incorrect usage:
// Correct
catch (Exception e)
{
Log.error(className, "something went wrong", e);
}
// Incorrect, exception not logged
catch (Throwable t)
{
String errMsg = "something went wrong";
Log.fatal(className, errMsg);
}
// Incorrect, exception name concatenated instead of providing exception to print stacktrace
catch (IOException exception)
{
Log.error(className, "Unable to read file " + exception);
}
Also shown are variants in exception types and names of the exception variable.
My current expression that's gotten me the closest is catch\s*\(\w+\s+(\w+)\)\s*\{[\s\S]*Log\s*\.\w+\(\s*\w+,[\s\S]*(?!,\b\1\b\);)\);
. It matches the start of a catch
block and captures the variable name used to hold the exception, then tries to find a Log.<level>(
line that does not end with the exception variable as the last parameter, i.e. , e);
It skips over the first example above and captures the other two.
The issue: I tried testing the expression here https://regexr.com/7p58l and it's missing an important case: where there's another place the logging is done correctly, regex does not find the first instance where it's done incorrectly.
catch (Exception e)
{
// Regex should capture here, but does not
Log.error(className, "something something exception");
}
void someMethod() {
catch (Exception e)
{
// Because this line hits the negative lookahead
Log.error(className, "something something exception", e);
}
}
All my attempts at adding characters after the negative lookahead seem to break it in some form. What needs to be added to find all the incorrect cases?
This is being put into Intellij's global find, so if a tool in Intellij would work better that would be appreciated
To achieve your goal, you can use a regular expression that ensures there is no correct logging of the exception within the catch block. The key is to make sure that if there is any logging within the catch block, it doesn't log the exception properly. Here's a modified regular expression that should work for your case:
catch\s*\(\w+\s+(\w+)\)\s*\{[\s\S]*?Log\.(?!error\s*\(\s*\w+,\s*"[^"]*",\s*\1\s*\);)[^\r\n;]*;\s*[\s\S]*?\}