private static AllowedValues getAllowedValuesFromMagic( @NotNull PsiModifierListOwner element, @NotNull PsiType type, PsiAnnotation magic) { if (magic == null) return null; PsiAnnotationMemberValue[] allowedValues; final boolean canBeOred; if (TypeConversionUtil.getTypeRank(type) <= TypeConversionUtil.LONG_RANK) { PsiAnnotationMemberValue intValues = magic.findAttributeValue("intValues"); allowedValues = intValues instanceof PsiArrayInitializerMemberValue ? ((PsiArrayInitializerMemberValue) intValues).getInitializers() : PsiAnnotationMemberValue.EMPTY_ARRAY; if (allowedValues.length == 0) { PsiAnnotationMemberValue orValue = magic.findAttributeValue("flags"); allowedValues = orValue instanceof PsiArrayInitializerMemberValue ? ((PsiArrayInitializerMemberValue) orValue).getInitializers() : PsiAnnotationMemberValue.EMPTY_ARRAY; canBeOred = true; } else { canBeOred = false; } } else if (type.equals( PsiType.getJavaLangString( element.getManager(), GlobalSearchScope.allScope(element.getProject())))) { PsiAnnotationMemberValue strValuesAttr = magic.findAttributeValue("stringValues"); allowedValues = strValuesAttr instanceof PsiArrayInitializerMemberValue ? ((PsiArrayInitializerMemberValue) strValuesAttr).getInitializers() : PsiAnnotationMemberValue.EMPTY_ARRAY; canBeOred = false; } else { return null; // other types not supported } if (allowedValues.length != 0) { return new AllowedValues(allowedValues, canBeOred); } // last resort: try valuesFromClass PsiAnnotationMemberValue[] values = readFromClass("valuesFromClass", magic, type); boolean ored = false; if (values == null) { values = readFromClass("flagsFromClass", magic, type); ored = true; } if (values == null) return null; return new AllowedValues(values, ored); }
private static PsiAnnotationMemberValue[] readFromClass( @NonNls String attributeName, @NotNull PsiAnnotation magic, PsiType type) { PsiAnnotationMemberValue fromClassAttr = magic.findAttributeValue(attributeName); PsiType fromClassType = fromClassAttr instanceof PsiClassObjectAccessExpression ? ((PsiClassObjectAccessExpression) fromClassAttr).getOperand().getType() : null; PsiClass fromClass = fromClassType instanceof PsiClassType ? ((PsiClassType) fromClassType).resolve() : null; if (fromClass == null) return null; String fqn = fromClass.getQualifiedName(); if (fqn == null) return null; List<PsiAnnotationMemberValue> constants = new ArrayList<PsiAnnotationMemberValue>(); for (PsiField field : fromClass.getFields()) { if (!field.hasModifierProperty(PsiModifier.PUBLIC) || !field.hasModifierProperty(PsiModifier.STATIC) || !field.hasModifierProperty(PsiModifier.FINAL)) continue; PsiType fieldType = field.getType(); if (!Comparing.equal(fieldType, type)) continue; PsiAssignmentExpression e = (PsiAssignmentExpression) JavaPsiFacade.getElementFactory(field.getProject()) .createExpressionFromText("x=" + fqn + "." + field.getName(), field); PsiReferenceExpression refToField = (PsiReferenceExpression) e.getRExpression(); constants.add(refToField); } if (constants.isEmpty()) return null; return constants.toArray(new PsiAnnotationMemberValue[constants.size()]); }
private static AllowedValues parseBeanInfo(@NotNull PsiModifierListOwner owner) { PsiMethod method = null; if (owner instanceof PsiParameter) { PsiParameter parameter = (PsiParameter) owner; PsiElement scope = parameter.getDeclarationScope(); if (!(scope instanceof PsiMethod)) return null; PsiElement nav = scope.getNavigationElement(); if (!(nav instanceof PsiMethod)) return null; method = (PsiMethod) nav; if (method.isConstructor()) { // not a property, try the @ConstructorProperties({"prop"}) PsiAnnotation annotation = AnnotationUtil.findAnnotation(method, "java.beans.ConstructorProperties"); if (annotation == null) return null; PsiAnnotationMemberValue value = annotation.findAttributeValue("value"); if (!(value instanceof PsiArrayInitializerMemberValue)) return null; PsiAnnotationMemberValue[] initializers = ((PsiArrayInitializerMemberValue) value).getInitializers(); PsiElement parent = parameter.getParent(); if (!(parent instanceof PsiParameterList)) return null; int index = ((PsiParameterList) parent).getParameterIndex(parameter); if (index >= initializers.length) return null; PsiAnnotationMemberValue initializer = initializers[index]; if (!(initializer instanceof PsiLiteralExpression)) return null; Object val = ((PsiLiteralExpression) initializer).getValue(); if (!(val instanceof String)) return null; PsiMethod setter = PropertyUtil.findPropertySetter( method.getContainingClass(), (String) val, false, false); if (setter == null) return null; // try the @beaninfo of the corresponding setter method = (PsiMethod) setter.getNavigationElement(); } } else if (owner instanceof PsiMethod) { PsiElement nav = owner.getNavigationElement(); if (!(nav instanceof PsiMethod)) return null; method = (PsiMethod) nav; } if (method == null) return null; PsiClass aClass = method.getContainingClass(); if (aClass == null) return null; if (PropertyUtil.isSimplePropertyGetter(method)) { List<PsiMethod> setters = PropertyUtil.getSetters(aClass, PropertyUtil.getPropertyNameByGetter(method)); if (setters.size() != 1) return null; method = setters.get(0); } if (!PropertyUtil.isSimplePropertySetter(method)) return null; PsiDocComment doc = method.getDocComment(); if (doc == null) return null; PsiDocTag beaninfo = doc.findTagByName("beaninfo"); if (beaninfo == null) return null; String data = StringUtil.join( beaninfo.getDataElements(), new Function<PsiElement, String>() { @Override public String fun(PsiElement element) { return element.getText(); } }, "\n"); int enumIndex = StringUtil.indexOfSubstringEnd(data, "enum:"); if (enumIndex == -1) return null; data = data.substring(enumIndex); int colon = data.indexOf(":"); int last = colon == -1 ? data.length() : data.substring(0, colon).lastIndexOf("\n"); data = data.substring(0, last); List<PsiAnnotationMemberValue> values = new ArrayList<PsiAnnotationMemberValue>(); for (String line : StringUtil.splitByLines(data)) { List<String> words = StringUtil.split(line, " ", true, true); if (words.size() != 2) continue; String ref = words.get(1); PsiExpression constRef = JavaPsiFacade.getElementFactory(aClass.getProject()) .createExpressionFromText(ref, aClass); if (!(constRef instanceof PsiReferenceExpression)) continue; PsiReferenceExpression expr = (PsiReferenceExpression) constRef; values.add(expr); } if (values.isEmpty()) return null; PsiAnnotationMemberValue[] array = values.toArray(new PsiAnnotationMemberValue[values.size()]); return new AllowedValues(array, false); }