void (@NotNull PsiReferenceExpression expression) { if (myWritten && myRead) { return; } super.visitReferenceExpression(expression); if (!expression.isReferenceTo(myVariable)) return; if (PsiUtil.isAccessedForWriting(expression)) { final PsiElement parent = PsiTreeUtil.skipParentsOfType(expression, PsiParenthesizedExpression.class); if (parent instanceof PsiAssignmentExpression assignmentExpression) { final PsiExpression rhs = assignmentExpression.getRExpression(); if (mayBeAccessedElsewhere(rhs)) { myWritten = true; myRead = true; } else if (!isZeroSizeArrayExpression(rhs)) { myWritten = true; } if (!ExpressionUtils.isVoidContext(assignmentExpression)) { myWritten = true; myRead = true; } } return; } myIsReferenced = true; PsiElement parent = getParent(expression); if (parent instanceof PsiArrayAccessExpression arrayAccessExpression) { parent = getParent(parent); while (parent instanceof PsiArrayAccessExpression && ((PsiArrayAccessExpression)parent).getArrayExpression() == arrayAccessExpression) { arrayAccessExpression = (PsiArrayAccessExpression)parent; parent = getParent(parent); } final PsiType type = arrayAccessExpression.getType(); if (type != null) { final int dimensions = type.getArrayDimensions(); if (dimensions > 0 && dimensions != myVariable.getType().getArrayDimensions()) { myWritten = true; } } if (PsiUtil.isAccessedForWriting(arrayAccessExpression)) { myWritten = true; } if (PsiUtil.isAccessedForReading(arrayAccessExpression) && !goesToSameArray(arrayAccessExpression) && // compound writes like += are not considered as reads, because result result goes to the same array as well (!PsiUtil.isAccessedForWriting(arrayAccessExpression) || parent instanceof PsiExpression && !ExpressionUtils.isVoidContext((PsiExpression)parent))) { myRead = true; } } else if (parent instanceof PsiReferenceExpression referenceExpression) { final String name = referenceExpression.getReferenceName(); if ("clone".equals(name) && referenceExpression.getParent() instanceof PsiMethodCallExpression) { myRead = true; } } else if (parent instanceof PsiForeachStatement foreachStatement) { final PsiExpression iteratedValue = foreachStatement.getIteratedValue(); if (PsiTreeUtil.isAncestor(iteratedValue, expression, false)) { myRead = true; } } else if (parent instanceof PsiExpressionList expressionList) { parent = parent.getParent(); if (parent instanceof PsiMethodCallExpression methodCallExpression) { final PsiMethod method = methodCallExpression.resolveMethod(); if (method != null) { final PsiClass aClass = method.getContainingClass(); if (aClass != null) { final String methodName = method.getName(); final String qualifiedName = aClass.getQualifiedName(); if ("java.lang.System".equals(qualifiedName)) { if ("arraycopy".equals(methodName)) { final PsiExpression[] expressions = expressionList.getExpressions(); if (expressions.length == 5) { if (PsiTreeUtil.isAncestor(expressions[0], expression, false)) { myRead = true; return; } else if (PsiTreeUtil.isAncestor(expressions[2], expression, false)) { myWritten = true; return; } } } } else if (CommonClassNames.JAVA_UTIL_ARRAYS.equals(qualifiedName)) { if (("fill".equals(methodName) || "parallelPrefix".equals(methodName) || "parallelSetAll".equals(methodName) || "parallelSort".equals(methodName) || "setAll".equals(methodName) || "sort".equals(methodName)) && PsiTreeUtil.isAncestor(expressionList.getExpressions()[0], expression, false)) { myWritten = true; } else { myRead = true; } return; } } } } myRead = true; myWritten = true; } else { myWritten = true; myRead = true; } }