From 2021b5fa007f11a139b1690b813594f932702a8a Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Mon, 4 Jan 2016 13:07:14 +0100 Subject: [PATCH] accept javax.annotation.concurrent as JSR 305 annotations for concurrency group inspections (IDEA-75733) --- .../concurrencyAnnotations/JCiPUtil.java | 23 +++--- .../ConcurrencyAnnotationsManager.java | 74 +++++++++++++++++++ .../inspection/guarded/javax_itself.java | 19 +++++ ...FieldAccessedNotGuardedInspectionTest.java | 22 ++++-- resources/src/META-INF/IdeaPlugin.xml | 3 + 5 files changed, 120 insertions(+), 21 deletions(-) create mode 100644 java/java-psi-api/src/com/intellij/codeInsight/ConcurrencyAnnotationsManager.java create mode 100644 java/java-tests/testData/inspection/guarded/javax_itself.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/concurrencyAnnotations/JCiPUtil.java b/java/java-analysis-impl/src/com/intellij/codeInspection/concurrencyAnnotations/JCiPUtil.java index c77b8529f482..f9f622fefae2 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/concurrencyAnnotations/JCiPUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/concurrencyAnnotations/JCiPUtil.java @@ -16,20 +16,15 @@ package com.intellij.codeInspection.concurrencyAnnotations; import com.intellij.codeInsight.AnnotationUtil; +import com.intellij.codeInsight.ConcurrencyAnnotationsManager; import com.intellij.psi.*; import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.javadoc.PsiDocTag; import com.intellij.psi.util.PsiTreeUtil; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; class JCiPUtil { - @NonNls - private static final String IMMUTABLE = "net.jcip.annotations.Immutable"; - @NonNls - private static final String GUARDED_BY = "net.jcip.annotations.GuardedBy"; - static boolean isJCiPAnnotation(String ref) { return "Immutable".equals(ref) || "GuardedBy".equals(ref) || "ThreadSafe".equals(ref) || "NotThreadSafe".equals(ref); } @@ -37,8 +32,8 @@ class JCiPUtil { private JCiPUtil() { } - public static boolean isImmutable(PsiClass aClass) { - final PsiAnnotation annotation = AnnotationUtil.findAnnotation(aClass, IMMUTABLE); + public static boolean isImmutable(@NotNull PsiClass aClass) { + final PsiAnnotation annotation = AnnotationUtil.findAnnotation(aClass, ConcurrencyAnnotationsManager.getInstance(aClass.getProject()).getImmutableAnnotations()); if (annotation != null) { return true; } @@ -47,8 +42,8 @@ class JCiPUtil { } @Nullable - static String findGuardForMember(PsiMember member) { - final PsiAnnotation annotation = AnnotationUtil.findAnnotation(member, GUARDED_BY); + static String findGuardForMember(@NotNull PsiMember member) { + final PsiAnnotation annotation = AnnotationUtil.findAnnotation(member, ConcurrencyAnnotationsManager.getInstance(member.getProject()).getGuardedByAnnotations()); if (annotation != null) { return getGuardValue(annotation); } @@ -63,9 +58,9 @@ class JCiPUtil { return visitor.getGuardString(); } - static boolean isGuardedBy(PsiMember member, String guard) { + static boolean isGuardedBy(@NotNull PsiMember member, String guard) { - final PsiAnnotation annotation = AnnotationUtil.findAnnotation(member, GUARDED_BY); + final PsiAnnotation annotation = AnnotationUtil.findAnnotation(member, ConcurrencyAnnotationsManager.getInstance(member.getProject()).getGuardedByAnnotations()); if (annotation != null) { final PsiAnnotationParameterList parameters = annotation.getParameterList(); final PsiNameValuePair[] pairs = parameters.getAttributes(); @@ -87,8 +82,8 @@ class JCiPUtil { return isGuardedBy(member, field.getName()); } - static boolean isGuardedByAnnotation(PsiAnnotation annotation) { - return GUARDED_BY.equals(annotation.getQualifiedName()); + static boolean isGuardedByAnnotation(@NotNull PsiAnnotation annotation) { + return ConcurrencyAnnotationsManager.getInstance(annotation.getProject()).getGuardedByAnnotations().contains(annotation.getQualifiedName()); } static boolean isGuardedByTag(PsiDocTag tag) { diff --git a/java/java-psi-api/src/com/intellij/codeInsight/ConcurrencyAnnotationsManager.java b/java/java-psi-api/src/com/intellij/codeInsight/ConcurrencyAnnotationsManager.java new file mode 100644 index 000000000000..f48a9a0fca8a --- /dev/null +++ b/java/java-psi-api/src/com/intellij/codeInsight/ConcurrencyAnnotationsManager.java @@ -0,0 +1,74 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInsight; + +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.project.Project; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; + +import java.util.ArrayList; +import java.util.List; + +public class ConcurrencyAnnotationsManager { + private static final String[] FRAMEWORKS = {"net.jcip.annotations", "javax.annotation.concurrent", "org.apache.http.annotation"}; + + private static final String IMMUTABLE = "Immutable"; + private static final String GUARDED_BY = "GuardedBy"; + private static final String THREAD_SAFE = "ThreadSafe"; + private static final String NOT_THREAD_SAFE = "NotThreadSafe"; + + private List myImmutableList = new ArrayList(); + private List myGuardedByList = new ArrayList(); + private List myThreadSafeList = new ArrayList(); + private List myNotThreadSafeList = new ArrayList(); + + public ConcurrencyAnnotationsManager() { + fillDefaults(myImmutableList, IMMUTABLE); + fillDefaults(myGuardedByList, GUARDED_BY); + fillDefaults(myThreadSafeList, THREAD_SAFE); + fillDefaults(myNotThreadSafeList, NOT_THREAD_SAFE); + } + + private static void fillDefaults(List list, final String annoName) { + list.addAll(ContainerUtil.map(FRAMEWORKS, new Function() { + @Override + public String fun(String framework) { + return framework + "." + annoName; + } + })); + } + + public static ConcurrencyAnnotationsManager getInstance(Project project) { + return ServiceManager.getService(project, ConcurrencyAnnotationsManager.class); + } + + public List getImmutableAnnotations() { + return myImmutableList; + } + + public List getGuardedByAnnotations() { + return myGuardedByList; + } + + public List getThreadSafeList() { + return myThreadSafeList; + } + + public List getNotThreadSafeList() { + return myNotThreadSafeList; + } +} diff --git a/java/java-tests/testData/inspection/guarded/javax_itself.java b/java/java-tests/testData/inspection/guarded/javax_itself.java new file mode 100644 index 000000000000..8a8010c83ce6 --- /dev/null +++ b/java/java-tests/testData/inspection/guarded/javax_itself.java @@ -0,0 +1,19 @@ +import javax.annotation.concurrent.GuardedBy; + +import java.lang.String; + +class A { + + @GuardedBy("itself") + private String _foo; + + public String getFoo() { + synchronized (_foo) { + return _foo; + } + } + + public void setFoo(String foo) { + _foo = foo; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/FieldAccessedNotGuardedInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/FieldAccessedNotGuardedInspectionTest.java index 88fd4ce21e21..d9fad819d34d 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/FieldAccessedNotGuardedInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/FieldAccessedNotGuardedInspectionTest.java @@ -18,21 +18,29 @@ package com.intellij.codeInspection; import com.intellij.JavaTestUtil; import com.intellij.codeInspection.concurrencyAnnotations.FieldAccessNotGuardedInspection; -import com.intellij.openapi.application.PluginPathManager; import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; import org.jetbrains.annotations.NotNull; public class FieldAccessedNotGuardedInspectionTest extends LightCodeInsightFixtureTestCase { public void testItself() throws Exception { - myFixture.addClass("package net.jcip.annotations;\n" + - "@java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD})\n" + - "@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)\n" + - "public @interface GuardedBy {\n" + - " java.lang.String value();\n" + - "}"); + myFixture.addClass("package net.jcip.annotations;\n" + getGuardedByAnnotationText()); myFixture.testHighlighting(true, false, false, getTestName(true) + ".java"); } + public void testJavax_itself() throws Exception { + myFixture.addClass("package javax.annotation.concurrent;\n" + getGuardedByAnnotationText()); + myFixture.testHighlighting(true, false, false, getTestName(true) + ".java"); + } + + @NotNull + private static String getGuardedByAnnotationText() { + return "@java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD})\n" + + "@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)\n" + + "public @interface GuardedBy {\n" + + " java.lang.String value();\n" + + "}"; + } + @Override protected void setUp() throws Exception { diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index b7ad68c1e127..498469b3dc12 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -538,6 +538,9 @@ + +