import com.siyeh.ig.psiutils.MethodMatcher;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.Set;
registerMethodCallError(call, aClass);
return;
}
- if (!myMethodMatcher.matches(method) &&
- findAnnotationInTree(method, Collections.singleton("javax.annotation.CheckReturnValue")) == null) {
+ final PsiAnnotation annotation = findAnnotationInTree(method, null, Collections.singleton("javax.annotation.CheckReturnValue"));
+ if (annotation != null) {
+ final PsiElement owner = (PsiElement)annotation.getOwner();
+ if (findAnnotationInTree(method, owner, Collections.singleton("com.google.errorprone.annotations.CanIgnoreReturnValue")) != null) {
+ return;
+ }
+ }
+ if (!myMethodMatcher.matches(method) && annotation == null) {
return;
}
+
registerMethodCallError(call, aClass);
}
- private PsiAnnotation findAnnotationInTree(PsiElement element, Set<String> fqAnnotationNames) {
+ @Nullable
+ private PsiAnnotation findAnnotationInTree(PsiElement element, @Nullable PsiElement stop, @NotNull Set<String> fqAnnotationNames) {
while (element != null) {
+ if (element == stop) {
+ return null;
+ }
if (element instanceof PsiModifierListOwner) {
final PsiModifierListOwner modifierListOwner = (PsiModifierListOwner)element;
final PsiAnnotation annotation =
"package java.util.regex; public class Matcher {" +
" public boolean find() {return true;}" +
"}",
+
"package javax.annotation;\n" +
"\n" +
"import java.lang.annotation.Documented;\n" +
"@Retention(RetentionPolicy.RUNTIME)\n" +
"public @interface CheckReturnValue {\n" +
" When when() default When.ALWAYS;\n" +
- "}"
+ "}",
+
+ "package com.google.errorprone.annotations;" +
+ "import java.lang.annotation.ElementType;\n" +
+ "import java.lang.annotation.Retention;\n" +
+ "import java.lang.annotation.RetentionPolicy;\n" +
+ "import java.lang.annotation.Target;\n" +
+ "@Target(value={ElementType.METHOD, ElementType.TYPE})\n" +
+ "@Retention(value=RetentionPolicy.CLASS)\n" +
+ "public @interface CanIgnoreReturnValue {}"
] as String[]
}
+ public void testCanIgnoreReturnValue() {
+ doTest("import com.google.errorprone.annotations.CanIgnoreReturnValue;\n" +
+ "import javax.annotation.CheckReturnValue;\n" +
+ "\n" +
+ "@CheckReturnValue\n" +
+ "class Test {\n" +
+ " int lookAtMe() { return 1; }\n" +
+ "\n" +
+ " @CanIgnoreReturnValue\n" +
+ " int ignoreMe() { return 2; }\n" +
+ "\n" +
+ " void run() {\n" +
+ " /*Result of 'Test.lookAtMe()' is ignored*/lookAtMe/**/(); // Bad! This line should produce a warning.\n" +
+ " ignoreMe(); // OK. This line should *not* produce a warning.\n" +
+ " }\n" +
+ "}");
+ }
+
public void testObjectMethods() {
doTest("class C {\n" +
" void foo(Object o, String s) {\n" +