SonarQube giving unused private method issue for lambda usage - java

I have the following logic;
..
if(list.stream()
.filter(MyClass::isEnabled)
.filter(this::isActive)
.count() > 0) {
//do smth
}
..
private boolean isActive(MyClass obj) {
return bool;
}
As you see, isActive method is being used in the stream structure, but when I build this class on Jenkins, I get the unused private method issue from SonarQube, it says you should delete this redundant private method. Is this a bug? If not, why haven't they still included lambda logic in their analyze structure?
Only solution is, obviously, to do this;
.filter(obj -> isActive(obj)), but it destroys the uniformity, and even the readability (imo).

This is a known issue of SonarQube java analyzer : https://jira.sonarsource.com/browse/SONARJAVA-583
This is due to a lack of semantic analysis to resolve properly method reference (thus identify to which method this::isActive refers to).

Related

Do we need Optional ifNotPresent for use in the middle of chain?

There are so many questions and threads about Optional API but I didn't found any for my case.
For example, I need first check emptiness of an Optional variable, for logging purpose, and then
check the value, if presents, with some predicate. Whatever check fails, I need to throw an exception.
Below is my real workaround for that
SomeValue value = someOptional.orElseThrow(() -> {
log.debug("nothing here");
return new NothingSpecialHereException();
});
if (!value.isSpecial()) {
log.debug("something here, but not special");
throw new NothingSpecialHereException();
}
When I was looking for an alternative solution for that, I tried something like that
SomeValue value = someOptional
.filter(SomeValue::isSpecial)
.orElseThrow(() -> {
log.debug("nothing special here"); // but this case for both "no value" and "value is not special"
return new NothingSpecialHereException();
});
I know that there's no any built-in solution for this situation in Java, but seems like I missing something like:
SomeValue value = someOptional
.ifNotPresent(() -> log.debug("nothing here")) // that method returns Optional for further invocatons
.filter(val -> {
if (!val.isSpecial()) {
log.debug("something here, but not special");
return false;
}
return true;
})
.orElseThrow(NothingSpecialHereException::new);
This is not the first time when I miss something like ifNotPresent or else* methods for use in the middle of pipe, not in the end. IMO sometimes that approach might be more readable, for example
optional
.map(...)
.filter(...)
.ifEmpty(...) // do smth after filter, maybe even throw
.map(...) // and continue processing
Maybe anyone encountered same problem? Or maybe I missed some better solution? Maybe there's a library that provides solutions for that?
The JDK Optional includes (since Java 9 only, which was a major oversight in Java 8) ifPresentOrElse, which could be used with a no-op first argument. Alternately, the Vavr library is a set of functional wrappers that is slightly more consistent than Optional and provides additional useful wrappers such as Try at the cost of having an extra dependency.
SomeValue value = Optional.ofNullable(someValue.isPresent()?
someValue.filter(SomeValue::isSpecial)
.orElseThrow(NothingSpecialHereException::new)
:null)
.orElseThrow(NothingHereException::new) ;
If someValue is present then the value can be set to special value or throw exception NothingSpecialHereException else if someValue is not present it will give Optinal it will check if null (someValue is not present) Throw NothingHereException.
Exception "NothingSpecialHereException" thrown only if value is present and not special.
Exception "NothingHereException" thrown only if value is not present.
Thanks to comments! I've checked out Vavr Option and Guava Optional APIs.
Guava Optional is even less rich in methods than Java Optional, so this is not a solution.
What I've found is the Vavr onEmpty method of Option class, that executes Runnable if the Option value is empty.
SomeValue value = Option.ofOptional(someOptional)
.onEmpty(() -> log.debug("nothing here"))
.filter(val -> {
if (!val.isSpecial()) {
log.debug("something here, but not special");
return false;
}
return true;
})
.getOrElseThrow(NothingHereException::new);
That example displays one of debug messages and throws exception only in one place. Looks a lot better.
However, Vavr is a big library with own collections, functional interfaces and monads like above. This is a big dependency for a project and it is hardly will be implemented in my project or any other long-time-existed project just for new fancy Optional replacement.
Plus, Vavr's Option does'nt have something like onEmptyThrow, so it's not so perfect =).
This thread is still open for suggestions, but now for Java 8 workaround I think this comment may be considered as answer.
UPDATE
Seems like I've found the best solution for problems like that.
Few days ago I found lombok's #ExtensionMethod annotation that makes possible solutions like below
class Extensions {
public static <T, E extends Throwable> Optional<T> ifNotPresentThrow(Optional<T> opt, Supplier<E> exceptionSupplier) throws E {
if (!opt.isPresent()) {
throw exceptionSupplier.get();
}
return opt;
}
}
#ExtensionMethod(Extensions.class)
class Test {
public static void main(String[] args) {
// assume there is someNullable variable
// instead of writing
Extensions.ifNotPresentThrow(Optional.ofNullable(someNullable), NothingHereException::new)
.map(...);
// I can write
Optional.ofNullable(someNullable)
.ifNotPresentThrow(NothingHereException::new)
.map(...); // now possible to continue if optional present
}
}
With that Kotlin-like extension methods it's possible to add any method to Optional's API. Lombok will just transform second variant into first during compilation.
However, this feature is experimental (seems like forever) and has possible bugs and decompiled bytecode looks pretty dirty (with various unnecessary local variables, etc.)

Writing unit test for #Nonnull annotated parameter

I have a method like this one:
public void foo(#Nonnull String value) {...}
I would like to write a unit test to make sure foo() throws an NPE when value is null but I can't since the compiler refuses to compile the unit test when static null pointer flow analysis is enabled in IDE.
How do I make this test compile (in Eclipse with "Enable annotation-based null analysis" enabled):
#Test(expected = NullPointerException.class)
public void test() {
T inst = ...
inst.foo(null);
}
Note: In theory the static null pointer of the compiler should prevent cases like that. But there is nothing stopping someone from writing another module with the static flow analysis turned off and calling the method with null.
Common case: Big messy old project without flow analysis. I start with annotating some utility module. In that case, I'll have existing or new unit tests which check how the code behaves for all the modules which don't use flow analysis yet.
My guess is that I have to move those tests into an unchecked module and move them around as I spread flow analysis. That would work and fit well into the philosophy but it would be a lot of manual work.
To put it another way: I can't easily write a test which says "success when code doesn't compile" (I'd have to put code pieces into files, invoke the compiler from unit tests, check the output for errors ... not pretty). So how can I test easily that the code fails as it should when callers ignore #Nonnull?
Hiding null within a method does the trick:
public void foo(#NonNull String bar) {
Objects.requireNonNull(bar);
}
/** Trick the Java flow analysis to allow passing <code>null</code>
* for #Nonnull parameters.
*/
#SuppressWarnings("null")
public static <T> T giveNull() {
return null;
}
#Test(expected = NullPointerException.class)
public void testFoo() {
foo(giveNull());
}
The above compiles fine (and yes, double-checked - when using foo(null) my IDE gives me a compile error - so "null checking" is enabled).
In contrast to the solution given via comments, the above has the nice side effect to work for any kind of parameter type (but might probably require Java8 to get the type inference correct always).
And yes, the test passes (as written above), and fails when commenting out the Objects.requireNonNull() line.
Why not just use plain old reflection?
try {
YourClass.getMethod("foo", String.class).invoke(someInstance, null);
fail("Expected InvocationException with nested NPE");
} catch(InvocationException e) {
if (e.getCause() instanceof NullPointerException) {
return; // success
}
throw e; // let the test fail
}
Note that this can break unexpectedly when refactoring (you rename the method, change the order of method parameters, move method to new type).
Using assertThrows from Jupiter assertions I was able to test this:
public MethodName(#NonNull final param1 dao) {....
assertThrows(IllegalArgumentException.class, () -> new MethodName(null));
Here design by contract comes to picture. You can not provide null value parameter to a method annotated with notNull argument.
You can use a field which you initialize and then set to null in a set up method:
private String nullValue = ""; // set to null in clearNullValue()
#Before
public void clearNullValue() {
nullValue = null;
}
#Test(expected = NullPointerException.class)
public void test() {
T inst = ...
inst.foo(nullValue);
}
As in GhostCat's answer, the compiler is unable to know whether and when clearNullValue() is called and has to assume that the field is not null.

Unit test: running programmatically a code that runs only at a real application instance

I am developing a plugin for PhpStorm, and in some point, it try to getContainingClass() from visited method. This method should return null when the class name is absent.
Just to make easier to explain, my visitPhpMethod() is like that:
final PhpClass methodClass = method.getContainingClass();
if (methodClass == null) {
return null;
}
My problem is justly to make the code-coverage of return null programmatically (from unit test) to proof that it is not a dead code. From a real instance of PhpStorm running my plugin I can reach this code when I just remove the class name like that:
Original code, that not access the return null:
class ThisIsMyClass { function x(){} }
Modified code without the class name, that access return null:
class { function x(){} }
But when I run the modified code from unit test, it give that:
class<error descr="Expected: class name"> </error>{ function x(){} }
And with that, my visitPhpMethod() is not triggered (while in real PhpStorm application it does). In this way, is impossible to coverage this part of code (but I like to do).
My best attempt: instead I relying on testHighlight() for that, I inputted with the functional code (that have the class name), then programatically I removed the class name (then the "expected class name" error don't happen anymore). Finally I run the visitPhpMethod() programmatically.
Unfortunatelly, the getContainingClass() instead of return null (that is what I expect to do), it just returns a PhpClass instance that don't have a name (and it should not works to me).
The code from this attempt could be seen here.
I tried to post the same problem on Intellij Community too, but without luck.
Okay, I found my issue.
On reality, the problem is not on getContaingClass(). It really doesn't returns null when called from visitPhpMethod(). I found my problem on another method that try to getNameIdentifier() from the containing class, in this case, it is really absent and I just try to return it from a #NotNull method.

slow JDK8 compilation

Trying to upgrade to JDK8 on a big project, compilation goes really slow on JDK8 compared to JDK7.
Running the compiler in verbose mode, JDK8 compiler stops at a big generated converter class(Mapping) for entities from server to client.
The converter methods in several cases call other converter methods from the same Mapping class.
As a workaround tried to split the Mapping file into multiple files. This visibly improved performance when only compiling the Mapping class or it's containing project(projectA). But compile time was very slow for other projects which invoke converter methods from projectA.
Another workaround was to make all convert methods return null, not calling anything else. Again, the performance was good for projectA but not for depending projects.
ProjectA uses generics but since it is compatible with JDK6, which didn't have generalized type inference introduced, maybe it's another JDK8 bug that causes this slowdown.
So possibly out of context but for generalized type inference, some threads like below suggest an upgrade to JDK9. But since it's not yet released, it's not a viable option as upgrade.
It'd be ideal if a backport of the fix would be done to JDK8. This was requested in the following StackOverflow thread but no reply from Oracle team yet.
Slow compilation with jOOQ 3.6+, plain SQL, and the javac compiler
I've attached 2 screenshots of how the heap looks in JDK7 vs JDK8. Could this be a cause for the JDK8 slowdown?
Thank you!
Update 20160314
The converter methods from Mapping class look like:
public static ResponseItemVO convert (ResponseItem pArg0){
if(pArg0==null){
return null;
}
ResponseItemVO ret = new ResponseItemVO();
ret.setErrorDetails(pArg0.getErrorDetails());
ret.setResult(Mapping.convert(pArg0.getResult()));
ret.setIdentifier(Mapping.convert(pArg0.getIdentifier()));
return ret;
}
And the VO looks like:
public class ResponseItemVO extends ResultVO<IdentifierVO, DetailsVO > {
public ResponseItemVO() {}
}
JDK7 Heap:
JDK8 Heap:
You've noticed already, there's a severe performance regression in Java 8 when it comes to overload resolution based on generic target typing. One of the reasons in your case might be the fact that the compiler needs to find the appropriate method from an assignment type
ResultVO<Something, Something> result = Mapping.convert(...);
// heavy lookup here ---------------------------^^^^^^^
If you're in control of the code generator, and not constrained by backwards compatibility, it might be worth thinking about avoiding the overloading of the convert() method. Without overloading, the compiler doesn't have to do the overload resolution work, neither inside of your mapping code, nor at the call site. This will certainly be much much faster.
Attempt 1: By using the parameter type in the method name:
class Mapping {
public static ResponseItemVO convertResponseItem(ResponseItem pArg0){
if (pArg0==null){
return null;
}
ResponseItemVO ret = new ResponseItemVO();
ret.setErrorDetails(pArg0.getErrorDetails());
ret.setResult(Mapping.convertResult(pArg0.getResult()));
ret.setIdentifier(Mapping.convertIdentifier(pArg0.getIdentifier()));
return ret;
}
}
Attempt 2: By moving the convert method elsewhere, e.g. into the VO type
class ResponseItemVO {
public static ResponseItemVO from(ResponseItem pArg0){
if (pArg0==null){
return null;
}
ResponseItemVO ret = new ResponseItemVO();
ret.setErrorDetails(pArg0.getErrorDetails());
ret.setResult(ResultVO.from(pArg0.getResult()));
ret.setIdentifier(IdentifierVO.from(pArg0.getIdentifier()));
return ret;
}
}
Or better...
class ResponseItem {
public ResponseItemVO toVO(){
ResponseItemVO ret = new ResponseItemVO();
ret.setErrorDetails(getErrorDetails());
ret.setResult(getResult().toVO());
ret.setIdentifier(getIdentifier().toVO());
return ret;
}
}

Method refactoring in Eclipse

I try to do the following refactoring steps in Eclipse IDE (JDT) and can not find the required refactoring and can not remember the name of all of the steps. I checked the refactoring at SourceMacking and do not find the correct one.
Let's take for example the following scenario:
class A {
method(B b) {
doSomethingWithA();
b.doSomethingWithB();
}
[...]
}
class B {
[...]
}
1) Make method static (missing name of the refactoring?):
class A {
static method(A a, B b) {
a.doSomethingWithA();
b.doSomethingWithB();
}
[...]
}
class B {
[...]
}
2) Move method:
class A {
[...]
}
class B {
static method(A a, B b) {
a.doSomethingWithA();
b.doSomethingWithB();
}
[...]
}
3) Convert to instance method:
class A {
[...]
}
class B {
method(A a) {
a.doSomethingWithA();
doSomethingWithB();
}
[...]
}
So anyone knowing something to do this step by step in Eclipse or do know the name of the refactoring is welcome. The goal is to have IDE support for every step.
Unfortunately, Eclipse's refactoring functionality is not as complete as other IDEs (for example Jetbrains' IntelliJ). I'll include instructions on how to perform each of the refactorings you requested with both IntelliJ and Eclipse.
With IntelliJ
Make Method Static
Move Instance Method
Convert to Instance Method
With Eclipse
Make Method Static: Eclipse doesn't directly support it, but we can achieve this using two other refactorings.
1.1. Introduce Indirection
Result
public static void method(A a, B b) {
a.method(b);
}
public void method(B b){
doSomethingWithA();
b.doSomethingWithB();
}
1.2. Inline
Result
public static void method(A a, B b) {
a.doSomethingWithA();
b.doSomethingWithB();
}
Move Static Members
Convert to Instance Method: Now, this is where it gets tricky. If you want to go from step 1 to step 3, you could just use Eclipse's Move Method and it'll handle everything perfectly fine. However, there are no ways that I know of to go from step 2 to step 3 using Eclipse's automated refactorings.
After having learned the refactoring is called 'Convert to Instance Method' I searched the bug database of Eclipse JDT and I found bad news:
Bug 10605
Bug 118032
Bug 338449
So basically it is a Won't-Fix noone cares feature request and so it might be time that I also switch to IntelliJ. I have to contemplate about this... .
Emond Papegaaij suggested in the discussion of Bug 118032 a work around:
A simple workaround is to create the static method, call this static method from the method you want to become static and inline the method call. This works for me in 4.3.1.
This is interesting but again would not be an automatic refactoring and defeat the purpose of refactoring in the first place. Adding someone's own code introduce the chance of failure and requires the rerun of the test-suite resulting in no chance of safely refactoring legacy code.

Categories

Resources