AnnotationContext (@NotNull UExpression expression) { PsiMethod method; PsiType returnType = null; PsiModifierListOwner next = null; UElement parent = expression.getUastParent(); if (parent instanceof UCallExpression) { // Nested annotations in Kotlin UAnnotation anno = UastContextKt.toUElement(parent.getSourcePsi(), UAnnotation.class); if (anno != null) { parent = anno; } } if (parent instanceof UAnnotationMethod) { UExpression defaultValue = ((UAnnotationMethod)parent).getUastDefaultValue(); if (defaultValue == null || !expressionsAreEquivalent(defaultValue, expression)) return EMPTY; method = ((UAnnotationMethod)parent).getPsi(); } else if (parent instanceof UNamedExpression) { method = UastUtils.getAnnotationMethod((UNamedExpression)parent); } else if (parent instanceof UAnnotation) { PsiClass psiClass = ((UAnnotation)parent).resolve(); if (psiClass == null || !psiClass.isAnnotationType()) return EMPTY; method = ArrayUtil.getFirstElement(psiClass.findMethodsByName("value", false)); } else { UElement jumpTarget = null; if (parent instanceof UReturnExpression) { jumpTarget = ((UReturnExpression)parent).getJumpTarget(); } else if (parent instanceof ULambdaExpression && expression instanceof UBlockExpression) { jumpTarget = parent; } if (jumpTarget instanceof UMethod) { method = ((UMethod)jumpTarget).getJavaPsi(); } else if (jumpTarget instanceof ULambdaExpression) { next = getFunctionalParameter((ULambdaExpression)jumpTarget); PsiType type = ((ULambdaExpression)jumpTarget).getFunctionalInterfaceType(); if (type == null) return fromModifierListOwner(next); returnType = LambdaUtil.getFunctionalInterfaceReturnType(type); method = LambdaUtil.getFunctionalInterfaceMethod(type); } else { return EMPTY; } } if (method == null) return EMPTY; AnnotationContext result = returnType == null ? fromModifierListOwner(method) : fromModifierListOwner(method).withType(returnType); if (next != null) { PsiModifierListOwner finalNext = next; return new AnnotationContext(result.myOwner, result.myType, () -> StreamEx.of(finalNext).append(result.secondaryItems())); } return result; }