I know I can suppress warnings from IntelliJ IDEA inspections like that:
#SuppressWarnings("CollectionDeclaredAsConcreteClass")
public PropertiesExpander(Properties properties) {
this.properties.putAll(properties);
}
For person from outside it may not be clear for which tool this suppression is needed.
PMD uses prefixes for that:
#SuppressWarnings("PMD.UnusedLocalVariable")
FindBugs uses dedicated annotation:
#SuppressFBWarnings("NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR")
Is there any way to clearly indicate that this suppression is just for IntelliJ IDEA?
A way of suppressing this for method arguments is to use a javadoc tag instead:
/**
* #noinspection CollectionDeclaredAsConcreteClass
*/
public PropertiesExpander(Properties properties) {
this.properties.putAll(properties);
}
This javadoc tag is very IntelliJ specific so no other tool should have any troubles with it. And you can easily identify it by just recognize it as it is or by adding some comment to it:
/**
* #noinspection IntelliJ CollectionDeclaredAsConcreteClass
*/
public PropertiesExpander(Properties properties) {
this.properties.putAll(properties);
}
And of course you can shorten it up even more:
/** #noinspection CollectionDeclaredAsConcreteClass */
public PropertiesExpander(Properties properties) {
this.properties.putAll(properties);
}
General approach
It is possible to suppress some warnings on a one-by-one basis with special comments instead of the #SuppressWarnings annotation.
Here's an example with lots of warnings:
If you press Alt+Enter on notUsedLocalVariable you can then choose Suppress for statement with comment on the context menu (after going right when choosing Remove variable ...).
On some variables/fields/methods the selected suppression is just Suppress for statement.
And now most (not all) of the warnings has been suppressed if you look in the right-hand field:
As you can see there can be several suppressions on the same comment line.
This can seem to be a bit tedious but I think it's the best you can do.
I found a way how to achieve that with #SuppressWarnings:
#SuppressWarnings("idea: CollectionDeclaredAsConcreteClass")
public PropertiesExpander(Properties properties) {
this.properties.putAll(properties);
}
Note that there must be space after idea:, otherwise it doesn't work.
Related
I have an interface with a default method and a private method, where the private method is called from the default method.
When running Spotbugs, it issues an error that the private method is never called: UPM_UNCALLED_PRIVATE_METHOD.
public interface Foo {
default boolean foo(int value1, int value2) {
return bar(value1 + value2);
}
private boolean bar(int value) {
return value == 0;
}
}
I'm doing something wrong or it's a Spotbugs issue?
Note 1: When modifying the private method to static, it doesn't report the error.
Note 2: I've seen similar issues reported, but all are closed and related to class instead of interface.
UPDATE
A similar issue was recently reported on Github (#1988), but hasn't been solved yet.
Spotbugs 4.5.3 reports this as "low priority" bug.
IMHO you have basically two options:
report it to the Spotbugs project as issue (https://github.com/spotbugs/spotbugs/issues)
tell Spotbugs to ignore the problem:
either annotate the method with #SuppressFBWarnings("UPM")
or use a filter file (https://spotbugs.readthedocs.io/en/stable/filter.html)
The solution with the annotation is probably easier to implement but clutters your source code.
The solution with the filter file might be harder to implement (if you do not use a filter file already) and the connection between the actual code and the filter might get lost, but your source code is not cluttered with annotations just to mute a noisy tool.
I am trying to add JetBrains Annotations library to my code.
Now I come across, that if I generate JavaDoc of my code the appearance of them is duplicated. Once is without qualifier (the annotations are imported, so no one is needed) and the second one (sometimes) with qualifier.
There are also cases where the annotation is only once there but on two parameters one is without qualifier and the other with one.
A code snippet:
public Subnet(#NotNull String[] ip){/*...*/}
/*...*/
public Subnet(#NotNull int[] ip) {/*...*/}
Generated JavaDoc:
public Subnet(#NotNull #NotNull String[] ip){/*...*/}
/*...*/
public Subnet(#NotNull #org.jetbrains.annotations.NotNull int[] ip) {/*...*/}
I tried the -noqualifier option but it did not help.
I am using the JavaDoc plugin version 3.1.1 and Doclet version 11.0.7.
Is there a way to get rid of the duplicated annotations?
The Issue
I'm having a problem with ProGuard 4.11 (An application that can optimize, shrink and obfuscate Java code), using the proguard-maven-plugin (github.com/wvengen/proguard-maven-plugin) (Although that shouldn't matter that much, since the error is occurring at runtime and the maven plugin just calls the binary with some arguments as far as I know).
I have an annotation class which is stuctured like this (nothing special):
#Retention(RetentionPolicy.RUNTIME) #Target(ElementType.FIELD)
public #interface SqlValueCache {
String value();
SqlValueCache.Type type() default Type.OBJECT_UPDATE; //Type is just an ordinary enum
}
I also have some fields annotated with that annotation, but I'm skipping the type() parameter because I want to use the default value:
#SqlValueCache("nickname")
protected SqlValueHolder<String> nick;
Now I want to process that annotation at runtime:
SqlValueCache annotation = field.getAnnotation(SqlValueCache.class); //Skipped the validation
annotation.value(); //Works fine, because specified
annotation.type(); //java.lang.annotation.IncompleteAnnotationException, *not* using the default
As stated in the comment above, I get an IncompleteAnnotationException, stating that my annotation declaration is missing the type() value. But that value should be implied by the default Type.OBJECT_UPDATE! So now I'm wondering, why is that happening?
Assumptions
I assume that the default thing is stored in some kind of attribute that I need to specify in -keepattributes, but I haven't been able to figure out if this is true or which one it is.
Reproduction
It does work just as intended when not using ProGuard.
I have also made sure that the problem is in fact the missing implied value - The code runs as intended when using ProGuard, but explicitly specifying the type(), like so:
#SqlValueCache(value = "nickname", type = Type.OBJECT_UPDATE)
protected SqlValueHolder<String> nick;
I am using this method as a temporary workaround, but this isn't the prettiest solution in my opinion. Also, as stated above, I still want to know why this error is happening.
Thanks in advance for reading and investigating my question! :)
Appendix/Meta
Yes, I did search the web for solutions and did also use the StackOverflow searchbox. Using the title of this question and various other search queries, I could only find questions complaining about no annotations being kept at all or asking to keep subclasses of classes annotated, etc. I also searched for the exception, but the only useful result was the JavaDoc (docs.oracle.com/javase/7/docs/api/java/lang/annotation/IncompleteAnnotationException.html) of the exception I am encountering.
I'm sorry about the links, but I apparently need 10 reputation to post more than two, although I really like linking stuff :/
Stacktrace
I have attached the Stacktrace I got in console (class names won't be useful at all in my opinion - I can attach them if really necessary; My classes are also loaded by a custom class loader, but I doubt that that makes any difference):
java.lang.ExceptionInInitializerError
at <class with annotated field>
(...)
Caused by: java.lang.annotation.IncompleteAnnotationException: io.github.xxyy.common.sql.builder.annotation.SqlValueCache missing element type
at sun.reflect.annotation.AnnotationInvocationHandler.invoke(AnnotationInvocationHandler.java:72) ~[?:1.7.0_51]
at com.sun.proxy.$Proxy18.type(Unknown Source)
at <line accessing type() of SqlValueCache>
(...)
ProGuard config
Here's my ProGuard config, should that be of any help (That's the part I find relevant to this question - Full file here: pastebin.com/u6wt00cj):
-dontskipnonpubliclibraryclassmembers
-target 1.7
-dontshrink
-dontoptimize
-repackageclasses io.github.xxyy.obf.towerdefense.client
-keepattributes SourceFile,LineNumberTable,*Annotations*,LocalVariable*Table
-keep,allowobfuscation class ** {
<fields>;
<methods>;
}
-keep,allowshrinking class **.annotation** {
<fields>;
<methods>;
}
# Also keep - Enumerations. Keep the special static methods that are required in
# enumeration classes.
-keepclassmembers enum ** {
public static **[] values();
public static ** valueOf(java.lang.String);
}
You also need to keep the AnnotationDefault attribute:
-keepattributes AnnotationDefault
You can get the same effect by changing *Annotations* to *Annotation* in your current -keepattributes option, so the wildcards match AnnotationDefault.
I currently have an Enum, which has a constructor that can take null and contains with the following SuppressWarning annotation:
#SuppressWarnings("all")
public enum TheEnum {
...
AN_ENUM_VALUE(null),
...
...
private TheEnum(TheEnum ... args) {
if (args != null){
...
...
}
...
}
I'm currently using MyEclipse workbench 10.6, and it seems to pick up the annotation fine. During a compilation on a dev machine, however, I get warnings related to the 'TheEnum' class.
The strange this is that within the project, there are #SuppressWarnings("unchecked") all over the place, and the compiler manages to pick these up and ignore them just fine.
Because of legacy issues, we have to use JDK 1.5.0_17 to compile, but it looks like it should pick up the "all" suppression:
[root#xxx]:/opt/jdk1.5.0_17/bin# ./javac -X
...
-Xlint:{all,deprecation,unchecked,fallthrough,path,serial,finally,-deprecation,- unchecked,-fallthrough,-path,-serial,-finally}Enable or disable specific warnings
any suggestions as to where I should look to see why 'all' is being ignored?
Don't use it in the first place.
#SuppressWarnings("all")
says, you are doing something wrong. I would cancel a contract ASAP with any developer developing code like this. Warnings are there for a reason, and a blanket ignore says "I don't care if my code actually works" like nothing else. This is the total opposite to writing unit tests somewhat: blanket disabling the compiler checks.
Judging from http://docs.oracle.com/javase/6/docs/technotes/tools/solaris/javac.html#options "all" might be an eclipse extension. Sun/Oracle Java 6 compiler probably only supports the following values: unchecked, path, serial, finally, fallthrough and deprecation.
I have this warning on most of my classes and not sure why is that. This happens on both public normal classes and final classes which have private constructors, some no constructor at all. I tried changing my private class methods to protected, doesn't help. Any suggestions on how to turn this off?
Here's a class example
public final class PlanBenefitManagerAssembler {
private static final Logger LOGGER = Logger.getLogger(PlanBenefitManagerAssembler.class);
/**
* No Instance of the this class is allowed.
*/
private PlanBenefitManagerAssembler() {
}
public static List<BenefitDecisionDetailsBean> assembleBenefitDecisionDetailsBean(
List<BenefitDetails> benefitDecisionDetailsList, int relationalSequenceNumber) {
LOGGER.debug("Enter assembleBenefitDecisionDetailsBean");
List<BenefitDecisionDetailsBean> benefitDecisionDetailsBeanList = new ArrayList<BenefitDecisionDetailsBean>();
for (BenefitDetails benefitDecisionDetails : benefitDecisionDetailsList) {
BenefitDecisionDetailsBean benefitDecisionDetailsBean = new BenefitDecisionDetailsBean();
benefitDecisionDetailsBean.setBenefitTypeCode(benefitDecisionDetails.getBenefitTypeCode());
benefitDecisionDetailsBean.setRelationSequenceNumber(relationalSequenceNumber);
benefitDecisionDetailsBean.setBenefitStatusDescription(
benefitDecisionDetails.getBenefitStatusDescription());
benefitDecisionDetailsBean.setBenefitStatusCode(benefitDecisionDetails.getBenefitStatusCode());
benefitDecisionDetailsBean.setBenefitUnderwritingStatusCode(
benefitDecisionDetails.getBenefitUnderwritingStatusCode());
benefitDecisionDetailsBean.setBenefitUnderwritingStatusDescription(
benefitDecisionDetails.getBenefitUnderwritingStatusDescription());
benefitDecisionDetailsBean.setBenefitChangeReasonCode(
String.valueOf(benefitDecisionDetails.getBenefitChangeReasonCode()));
benefitDecisionDetailsBean.setBenefitChangeReasonDescription(
benefitDecisionDetails.getBenefitChangeReasonDescription());
benefitDecisionDetailsBean.setComponentNumber(benefitDecisionDetails.getBenefitNumber());
benefitDecisionDetailsBean.setBenefitVisible(benefitDecisionDetails.isExplicitBenefitDecisionRequired());
benefitDecisionDetailsBean.setModelChanged(false);
// * Set BenefitLoading and BenefitExclusion
List<ExclusionDetailsBean> exclusionDetailsBeanList =
PlanBenefitManagerAssembler.assembleExclusionDetailsList(benefitDecisionDetails
.getBenefitExclusionsDetailsList().getBenefitExclusionsDetailsList());
List<LoadingDetailsBean> loadingDetailsBeanList =
PlanBenefitManagerAssembler.assembleLoadingDetailsList(benefitDecisionDetails
.getBenefitLoadingsDetailsList().getBenefitLoadingsDetailsList());
benefitDecisionDetailsBean.setExclusionDetailsBeanList(exclusionDetailsBeanList);
benefitDecisionDetailsBean.setLoadingDetailsBeanList(loadingDetailsBeanList);
benefitDecisionDetailsBeanList.add(benefitDecisionDetailsBean);
}
LOGGER.debug("Exit assembleBenefitDecisionDetailsBean");
return benefitDecisionDetailsBeanList;
}
}
When Checkstyle produces a warning the warning text should include a short rule name which will allow you to look up the exact rule that is being triggered. "DesignForExtension", for example.
Given the rule name, you can look up more detail on what it means in the Checkstyle documentation: http://checkstyle.sourceforge.net/availablechecks.html
Post the full details of the rule being triggered and someone might be able to help.
You can always turn the warnings off, but they generally are here for a reason :)
Do you intend to make them abstract classes ? If so, declare them that way.
Will you need to instantiate them at some point ? If so, add a public constructor.
I'm pretty sure this will solve your problem.
On sourceforge it says that the AbstractClassName rule uses the following regex:
^Abstract.*$|^.*Factory$
This causes classes with a name starting with 'Abstract' or ending with 'Factory' to be flagged. I get the 'Abstract..' part of that, but why should all '..Factory' classes be abstract? Sometimes I create factories which use dependencies to do their work so I need an instance to inject into.
This however does not explain your case. I tried your example class and did not get any Checkstyle warning (I am using the Eclipse Checkstyle Plug-in version 5.3.0.201012121300).
Are you sure you are getting the AbstractClassName warning for this class? Which version of Checkstyle are you using?