int (PsiField target) { // Final field: written either in field initializer or in class initializer block which directly writes this field // Non-final field: written either in field initializer, in class initializer which directly writes this field or calls any method, // or in other field initializer which directly writes this field or calls any method boolean isFinal = target.hasModifierProperty(PsiModifier.FINAL); int offset = Integer.MAX_VALUE; PsiExpression fieldInitializer = target.getInitializer(); if (fieldInitializer != null) { offset = fieldInitializer.getTextOffset(); if (isFinal) return offset; } PsiClass aClass = Objects.requireNonNull(target.getContainingClass()); PsiClassInitializer[] initializers = aClass.getInitializers(); Predicate<PsiElement> writesToTarget = element -> !PsiTreeUtil.processElements(element, e -> !(e instanceof PsiExpression) || !PsiUtil.isAccessedForWriting((PsiExpression)e) || !ExpressionUtils.isReferenceTo((PsiExpression)e, target)); Predicate<PsiElement> hasSideEffectCall = element -> !PsiTreeUtil.findChildrenOfType(element, PsiMethodCallExpression.class).stream() .map(PsiMethodCallExpression::resolveMethod).allMatch(method -> method != null && JavaMethodContractUtil.isPure(method)); for (PsiClassInitializer initializer : initializers) { if (initializer.hasModifierProperty(PsiModifier.STATIC) != target.hasModifierProperty(PsiModifier.STATIC)) continue; if (!isFinal && hasSideEffectCall.test(initializer)) { // non-final field could be written indirectly (via method call), so assume it's written in the first applicable initializer offset = Math.min(offset, initializer.getTextRange().getStartOffset()); break; } if (writesToTarget.test(initializer)) { offset = Math.min(offset, initializer.getTextRange().getStartOffset()); if (isFinal) return offset; break; } } if (!isFinal) { for (PsiField field : aClass.getFields()) { if (field.hasModifierProperty(PsiModifier.STATIC) != target.hasModifierProperty(PsiModifier.STATIC)) continue; if (hasSideEffectCall.test(field.getInitializer()) || writesToTarget.test(field)) { offset = Math.min(offset, field.getTextRange().getStartOffset()); break; } } } return offset; }