-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Exclude from a report private empty constructors that do not have arguments #529
Conversation
331d669
to
44e5b8d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Godin This filter is definitely a quick win! I have two minor comments to improve the matcher API.
if (m != null && superClassName.equals(m.owner) | ||
&& "<init>".equals(m.name) && ("()V").equals(m.desc)) { | ||
nextIs(Opcodes.RETURN); | ||
return cursor != null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If nextIs()
would have an boolean return value, we could write this as:
return nextIs(Opcodes.Return)
Could also be used in other existing filters.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@marchof then there will be temptation to use it with &&
everywhere, but that is exactly what we were trying to avoid.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Godin It's internal API, I would try to keep the filter as readable as possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@marchof Then in case of preceding if
statement containing return
of a boolean, IDE start to suggest to combine them, making code unreadable. Also even if I don't see this in IntelliJ, static analyzers might warn about unused return value in other places.
|
||
private boolean match(final MethodNode methodNode, | ||
final String superClassName) { | ||
vars.put("this", THIS); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The trick with ASTORE
is to define a named argument. This looks surprising as there is no ASTORE
involved in private empty constructors.
For better documentation I would therefore prefer to encapsulate this within AbstractMatcher
and provide a method for this:
void defineLocal(int idx, String name)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@marchof I removed usage of nextIsVar
- it does not work for a first instruction in absence of preceding label.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Godin Ok, I see. I would still prefer to implement semantical matching premitives in AbstractMatcher
, so we can write e.g.
private boolean match(final MethodNode methodNode,
final String superClassName) {
cursor = methodNode.instructions.getFirst();
skipNonOpcodes();
nextIsVar(Opcodes.ALOAD, 0);
nextIsMethod(Opcodes.INVOKESPECIAL, superClassName, "<init>",
"()V");
return nextIs(Opcodes.RETURN);
}
[Updated]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@marchof I added skipNonOpcodes
, but nextIsVar
anyway can't be used for a very first instruction, because after skipNonOpcodes
we need to check current instruction, while semantic of next...
methods is to move to a next instruction. Change of semantic to check of current instruction - first of all will affect a lot of existing code relying on it, but anyway will lead to the same problem, a kind of, but at the end of method. IMO the only way - is to insert an artificial label at the beginning of all methods, but IMO this is an overkill compared just to a condition in if
here, which is IMO perfectly readable.
Replacement of another if
on method nextIsMethod
in abstract class IMO also an overkill, because its only usage will be here, and there won't be code-sharing with other places where we already check MethodInsnNode
(see references on it in TryWithResourcesJavacFilter
and TryWithResourcesEcjFilter
), and again IMO condition is perfectly readable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Godin Thanks for the explations. This would require to keep a state in AbstractMatcher
and replace the direct access to cursor
with simething like start(AbstractInsnNode)
.
But I agree that refactoring the matcher API soes not provide enough value for now.
private static class PrivateDefault { // $line-privateDefault$ | ||
} | ||
|
||
private static class PrivateEmptyNoArg { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Godin I wonder whether we should add another negative test for the case where the private non-arg constructor is not empty in source code:
private static class PrivateNonEmptyNoArg {
private PrivateNonEmptyNoArg() {
nop(); // $line-privateNonEmptyNoArg$
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Godin Thx! 👍
4c8aa24
to
d0b42ad
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Godin From my point of view this can be merged. Please do so if you don't have any open issues.
Do you have an estimate about when this could be released? |
@MonsieurBon Hopefully this year. You can use our snapshot builds in the meantime and help us testing! |
Snapshot build is fine with me, but I can't seem to test this.
what am I doing wrong? |
After reflecting for some time, I believe that we can unconditionally safely ignore private empty constructors that do not have arguments. Even despite the fact that they relate to a source code and not generated by compiler. Note that this will completely exclude from report unused classes that have only such constructor, but anyway revealing of those is not a job of code coverage tool.
This will also improve report for JaCoCo itself.