[duplicates] enable duplicates analysis in PyCharm/WebStorm/PhpStorm/RubyMine
[idea/community.git] / java / java-psi-api / src / com / intellij / codeInsight / CheckerFrameworkNullityUtil.java
1 // Copyright 2000-2018 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.
2 package com.intellij.codeInsight;
3
4 import com.intellij.psi.*;
5 import com.intellij.psi.util.PsiUtil;
6 import com.intellij.util.containers.ContainerUtil;
7 import org.jetbrains.annotations.Nullable;
8
9 import java.util.Set;
10
11 /**
12  * @author peter
13  */
14 class CheckerFrameworkNullityUtil {
15   private static final String DEFAULT_QUALIFIER = "org.checkerframework.framework.qual.DefaultQualifier";
16   private static final String DEFAULT_QUALIFIERS = "org.checkerframework.framework.qual.DefaultQualifiers";
17
18   @Nullable
19   static NullabilityAnnotationInfo isCheckerDefault(PsiAnnotation anno, PsiAnnotation.TargetType[] types) {
20     String qName = anno.getQualifiedName();
21     if (DEFAULT_QUALIFIER.equals(qName)) {
22       PsiAnnotationMemberValue value = anno.findAttributeValue(PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME);
23       if (value instanceof PsiClassObjectAccessExpression &&
24           hasAppropriateTarget(types, anno.findAttributeValue("locations"))) {
25         PsiClass valueClass = PsiUtil.resolveClassInClassTypeOnly(((PsiClassObjectAccessExpression)value).getOperand().getType());
26         if (valueClass != null) {
27           NullableNotNullManager instance = NullableNotNullManager.getInstance(value.getProject());
28           if (instance.getNullables().contains(valueClass.getQualifiedName())) {
29             return new NullabilityAnnotationInfo(anno, Nullability.NULLABLE, true);
30           }
31           if (instance.getNotNulls().contains(valueClass.getQualifiedName())) {
32             return new NullabilityAnnotationInfo(anno, Nullability.NOT_NULL, true);
33           }
34         }
35       }
36       return null;
37     }
38     
39     if (DEFAULT_QUALIFIERS.equals(qName)) {
40       PsiAnnotationMemberValue value = anno.findAttributeValue(PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME);
41       for (PsiAnnotationMemberValue initializer : AnnotationUtil.arrayAttributeValues(value)) {
42         if (initializer instanceof PsiAnnotation) {
43           NullabilityAnnotationInfo result = isCheckerDefault((PsiAnnotation)initializer, types);
44           if (result != null) {
45             return result;
46           }
47         }
48       }
49     }
50     return null;
51   }
52
53   private static boolean hasAppropriateTarget(PsiAnnotation.TargetType[] types, PsiAnnotationMemberValue locations) {
54     Set<String> locationNames = ContainerUtil.map2SetNotNull(AnnotationUtil.arrayAttributeValues(locations), l -> l instanceof PsiReferenceExpression ? ((PsiReferenceExpression)l).getReferenceName() : null);
55     if (locationNames.contains("ALL")) return true;
56     for (PsiAnnotation.TargetType type : types) {
57       if (type == PsiAnnotation.TargetType.FIELD) return locationNames.contains("FIELD");
58       if (type == PsiAnnotation.TargetType.METHOD) return locationNames.contains("RETURN");
59       if (type == PsiAnnotation.TargetType.PARAMETER) return locationNames.contains("PARAMETER");
60     }
61     return false;
62   }
63 }