diff --git a/java/java-psi-api/src/com/intellij/codeInsight/AnnotationUtil.java b/java/java-psi-api/src/com/intellij/codeInsight/AnnotationUtil.java index 55d6b3cfe7d9..e464e9f3d3ec 100644 --- a/java/java-psi-api/src/com/intellij/codeInsight/AnnotationUtil.java +++ b/java/java-psi-api/src/com/intellij/codeInsight/AnnotationUtil.java @@ -1,32 +1,16 @@ -/* - * Copyright 2000-2017 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.codeInsight; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; import com.intellij.psi.*; import com.intellij.psi.util.*; -import com.intellij.util.ArrayUtil; -import com.intellij.util.Consumer; -import com.intellij.util.Processor; -import com.intellij.util.Processors; +import com.intellij.util.*; import com.intellij.util.containers.ConcurrentFactoryMap; import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashMap; import gnu.trove.THashSet; +import org.intellij.lang.annotations.MagicConstant; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -35,6 +19,8 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Proxy; import java.util.*; +import static com.intellij.util.BitUtil.isSet; + /** * @author max */ @@ -256,7 +242,7 @@ public class AnnotationUtil { } public static boolean isAnnotated(@NotNull PsiModifierListOwner listOwner, @NotNull String annotationFQN, boolean checkHierarchy) { - return isAnnotated(listOwner, annotationFQN, checkHierarchy, true, true, null); + return isAnnotated(listOwner, annotationFQN, checkHierarchy, true, true); } public static boolean isAnnotated(@NotNull PsiModifierListOwner listOwner, @@ -271,15 +257,30 @@ public class AnnotationUtil { boolean checkHierarchy, boolean skipExternal, boolean skipInferred) { - return isAnnotated(listOwner, annotationFQN, checkHierarchy, skipExternal, skipInferred, null); + int flags = CHECK_TYPE; + if (checkHierarchy) flags |= CHECK_HIERARCHY; + if (!skipExternal) flags |= CHECK_EXTERNAL; + if (!skipInferred) flags |= CHECK_INFERRED; + return isAnnotated(listOwner, annotationFQN, flags, null); } - private static boolean isAnnotated(@NotNull PsiModifierListOwner listOwner, - @NotNull String annotationFQN, - boolean checkHierarchy, - boolean skipExternal, - boolean skipInferred, - @Nullable Set processed) { + public static final int CHECK_HIERARCHY = 0x01; + public static final int CHECK_EXTERNAL = 0x02; + public static final int CHECK_INFERRED = 0x04; + public static final int CHECK_TYPE = 0x08; + + @MagicConstant(flags = {CHECK_HIERARCHY, CHECK_EXTERNAL, CHECK_INFERRED, CHECK_TYPE}) + public @interface Flags { } + + public static boolean isAnnotated(@NotNull PsiModifierListOwner listOwner, @NotNull Collection annotations, @Flags int flags) { + return annotations.stream().anyMatch(annotation -> isAnnotated(listOwner, annotation, flags)); + } + + public static boolean isAnnotated(@NotNull PsiModifierListOwner listOwner, @NotNull String annotationFqn, @Flags int flags) { + return isAnnotated(listOwner, annotationFqn, flags, null); + } + + private static boolean isAnnotated(PsiModifierListOwner listOwner, String annotationFQN, int flags, @Nullable Set processed) { if (!listOwner.isValid()) return false; PsiModifierList modifierList = listOwner.getModifierList(); @@ -288,38 +289,40 @@ public class AnnotationUtil { PsiAnnotation annotation = modifierList.findAnnotation(annotationFQN); if (annotation != null) return true; - PsiType type = null; - if (listOwner instanceof PsiMethod) { - type = ((PsiMethod)listOwner).getReturnType(); - } - else if (listOwner instanceof PsiVariable) { - type = ((PsiVariable)listOwner).getType(); - } - if (type != null && type.findAnnotation(annotationFQN) != null) { - return true; + if (isSet(flags, CHECK_TYPE)) { + PsiType type = null; + if (listOwner instanceof PsiMethod) { + type = ((PsiMethod)listOwner).getReturnType(); + } + else if (listOwner instanceof PsiVariable) { + type = ((PsiVariable)listOwner).getType(); + } + if (type != null && type.findAnnotation(annotationFQN) != null) { + return true; + } } - if (!skipExternal) { + if (isSet(flags, CHECK_EXTERNAL)) { Project project = listOwner.getProject(); if (ExternalAnnotationsManager.getInstance(project).findExternalAnnotation(listOwner, annotationFQN) != null) { return true; } } - if (!skipInferred) { + if (isSet(flags, CHECK_INFERRED)) { Project project = listOwner.getProject(); if (InferredAnnotationsManager.getInstance(project).findInferredAnnotation(listOwner, annotationFQN) != null) { return true; } } - if (checkHierarchy) { + if (isSet(flags, CHECK_HIERARCHY)) { if (listOwner instanceof PsiMethod) { PsiMethod method = (PsiMethod)listOwner; if (processed == null) processed = new THashSet<>(); if (!processed.add(method)) return false; for (PsiMethod superMethod : method.findSuperMethods()) { - if (isAnnotated(superMethod, annotationFQN, true, skipExternal, skipInferred, processed)) { + if (isAnnotated(superMethod, annotationFQN, flags, processed)) { return true; } } @@ -329,7 +332,7 @@ public class AnnotationUtil { if (processed == null) processed = new THashSet<>(); if (!processed.add(clazz)) return false; for (PsiClass superClass : clazz.getSupers()) { - if (isAnnotated(superClass, annotationFQN, true, skipExternal, skipInferred, processed)) { + if (isAnnotated(superClass, annotationFQN, flags, processed)) { return true; } }