PsiClassType (@NotNull final PsiClass categoryAnnotationOwner) { return CachedValuesManager.getCachedValue(categoryAnnotationOwner, new CachedValueProvider<>() { @Override public Result<PsiClassType> compute() { return Result.create(inferCategoryType(categoryAnnotationOwner), PsiModificationTracker.MODIFICATION_COUNT); } @Nullable private static PsiClassType inferCategoryType(final PsiClass aClass) { return RecursionManager.doPreventingRecursion(aClass, true, (NullableComputable<PsiClassType>)() -> { final PsiModifierList modifierList = aClass.getModifierList(); if (modifierList == null) return null; final PsiAnnotation annotation = modifierList.findAnnotation(GroovyCommonClassNames.GROOVY_LANG_CATEGORY); if (annotation == null) return null; PsiAnnotationMemberValue value = annotation.findAttributeValue("value"); if (!(value instanceof GrReferenceExpression)) return null; if ("class".equals(((GrReferenceExpression)value).getReferenceName())) value = ((GrReferenceExpression)value).getQualifier(); if (!(value instanceof GrReferenceExpression)) return null; final PsiElement resolved = ((GrReferenceExpression)value).resolve(); if (!(resolved instanceof PsiClass)) return null; String className = ((PsiClass)resolved).getQualifiedName(); if (className == null) className = ((PsiClass)resolved).getName(); if (className == null) return null; return JavaPsiFacade.getElementFactory(aClass.getProject()).createTypeByFQClassName(className, resolved.getResolveScope()); }); } }); }