diff --git a/java/java-analysis-api/resources/messages/JavaAnalysisBundle.properties b/java/java-analysis-api/resources/messages/JavaAnalysisBundle.properties
index a73cc6b97596..ba30ba12af2e 100644
--- a/java/java-analysis-api/resources/messages/JavaAnalysisBundle.properties
+++ b/java/java-analysis-api/resources/messages/JavaAnalysisBundle.properties
@@ -148,6 +148,7 @@ scope.package=Package {0}
0.field.is.always.initialized.not.null=@{0} field is always initialized not-null
access.can.be.0=Access can be {0}
access.to.field.code.ref.code.outside.of.declared.guards.loc=Access to field #ref outside of declared guards #loc
+call.to.method.code.ref.code.outside.of.declared.guards.loc=Call to method #ref() outside of declared guards #loc
annotate.as.safevarargs=Annotate as @SafeVarargs
annotate.overridden.methods.parameters.family.name=Annotate overridden method parameters
annotate.overridden.methods.parameters=Annotate overridden method parameters as ''@{0}''
diff --git a/java/java-analysis-impl/src/META-INF/JavaAnalysisPlugin.xml b/java/java-analysis-impl/src/META-INF/JavaAnalysisPlugin.xml
index 891ddc6b6fa7..e0f0d9d59992 100644
--- a/java/java-analysis-impl/src/META-INF/JavaAnalysisPlugin.xml
+++ b/java/java-analysis-impl/src/META-INF/JavaAnalysisPlugin.xml
@@ -145,7 +145,7 @@
-
annotations = ConcurrencyAnnotationsManager.getInstance(member.getProject()).getGuardedByAnnotations();
+ final PsiAnnotation annotation = AnnotationUtil.findAnnotation(member, annotations);
if (annotation != null) {
return getGuardValue(annotation);
}
- if (member instanceof PsiCompiledElement) {
- member = (PsiMember)member.getNavigationElement();
- if (member == null || member instanceof PsiCompiledElement) {
- return null; // can't analyze compiled code
+ if (member instanceof PsiDocCommentOwner) {
+ PsiDocCommentOwner commentOwner = (PsiDocCommentOwner)member;
+ PsiDocComment comment = commentOwner.getDocComment();
+ if (comment != null) {
+ PsiDocTag[] tags = comment.getTags();
+ for (int i = tags.length - 1; i >= 0; i--) {
+ String value = getGuardValue(tags[i]);
+ if (value != null) {
+ return value;
+ }
+ }
}
}
- final GuardedTagVisitor visitor = new GuardedTagVisitor();
- member.accept(visitor);
- return visitor.getGuardString();
+ return null;
}
static boolean isGuardedBy(@NotNull PsiMember member, @NotNull String guard) {
@@ -81,18 +74,12 @@ public class JCiPUtil {
return annotation != null && guard.equals(getGuardValue(annotation));
}
- public static boolean isGuardedBy(PsiMember member, PsiField field) {
- return isGuardedBy(member, field.getName());
- }
-
static boolean isGuardedByAnnotation(@NotNull PsiAnnotation annotation) {
return ConcurrencyAnnotationsManager.getInstance(annotation.getProject()).getGuardedByAnnotations().contains(annotation.getQualifiedName());
}
static boolean isGuardedByTag(PsiDocTag tag) {
- final String text = tag.getText();
-
- return text.startsWith("@GuardedBy") && text.contains("(") && text.contains(")");
+ return tag.getText().startsWith("@GuardedBy");
}
@Nullable
@@ -100,38 +87,38 @@ public class JCiPUtil {
final PsiAnnotationMemberValue psiAnnotationMemberValue = annotation.findAttributeValue("value");
if (psiAnnotationMemberValue instanceof PsiLiteralExpression) {
final Object value = ((PsiLiteralExpression)psiAnnotationMemberValue).getValue();
- if ("itself".equals(value)) {
- final PsiMember member = PsiTreeUtil.getParentOfType(annotation, PsiMember.class);
- if (member != null) return member.getName();
- }
if (value instanceof String) {
- return (String)value;
+ return resolveItself((String)value, annotation);
}
}
return null;
}
- @NotNull
+ @Nullable
static String getGuardValue(PsiDocTag tag) {
- final String text = tag.getText();
- return text.substring(text.indexOf((int)'(') + 1, text.indexOf((int)')')).trim();
+ if ("GuardedBy".equals(tag.getName())) {
+ final PsiDocTagValue value = tag.getValueElement();
+ if (value == null) return "";
+ return resolveItself(value.getText(), tag);
+ }
+ else {
+ final String text = tag.getText();
+ if (!text.startsWith("@GuardedBy")) return null;
+ int start = text.indexOf('(');
+ int end = text.indexOf(')');
+ if (start >= end || start < 0) return "";
+ return resolveItself(text.substring(start + 1, end), tag);
+ }
}
- private static class GuardedTagVisitor extends JavaRecursiveElementWalkingVisitor {
- private String guardString;
-
- @Override
- public void visitDocTag(PsiDocTag tag) {
- super.visitDocTag(tag);
- final String text = tag.getText();
- if (text.startsWith("@GuardedBy") && text.contains("(") && text.contains(")")) {
- guardString = text.substring(text.indexOf((int)'(') + 1, text.indexOf((int)')'));
+ private static String resolveItself(String value, PsiElement context) {
+ if ("itself".equals(value)) {
+ final PsiMember member = PsiTreeUtil.getParentOfType(context, PsiMember.class);
+ if (!(member instanceof PsiField)) {
+ return "itself";
}
+ return member.getName();
}
-
- @Nullable
- private String getGuardString() {
- return guardString;
- }
+ return value;
}
}
diff --git a/java/java-tests/testData/inspection/guarded/fieldAccessNotGuarded.java b/java/java-tests/testData/inspection/guarded/fieldAccessNotGuarded.java
index 412352f2940c..43a32bb07059 100644
--- a/java/java-tests/testData/inspection/guarded/fieldAccessNotGuarded.java
+++ b/java/java-tests/testData/inspection/guarded/fieldAccessNotGuarded.java
@@ -114,4 +114,18 @@ class Example4 {
Object o = field;
}
}
+}
+class No {
+
+ @GuardedBy("this")
+ void x() {
+ notify();
+ }
+
+ void y() {
+ x(); // warn here
+ }
+ synchronized void z() {
+ x(); // don't warn here
+ }
}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/unknownGuard/UnknownGuard.java b/java/java-tests/testData/inspection/unknownGuard/UnknownGuard.java
index d30dfca2a763..cc67c67aa63a 100644
--- a/java/java-tests/testData/inspection/unknownGuard/UnknownGuard.java
+++ b/java/java-tests/testData/inspection/unknownGuard/UnknownGuard.java
@@ -80,4 +80,12 @@ class UnknownGuard {
@GuardedBy("Nothing.LOCK")
private Object twentytwo = new Object();
+
+ /**
+ * @GuardedBy itself
+ */
+ private Object twentythree = new Object();
+
+ @GuardedBy("itself")
+ private void method() {}
}
\ No newline at end of file