boolean (@NotNull PsiCallExpression call) { PsiType type = call.getType(); boolean immutable = isImmutable(type); // If pure method returns mutable object, then it's possible that further mutation of that object will modify the original collection if (!immutable) { immutable = call instanceof PsiNewExpression && CollectionUtils.isConcreteCollectionClass(type); } PsiMethod method = call.resolveMethod(); if (!immutable && method != null) { PsiClass returnType = PsiUtil.resolveClassInClassTypeOnly(method.getReturnType()); if (returnType instanceof PsiTypeParameter) { // method returning unbounded type parameter is unlikely to allow modify original collection via the returned value immutable = ((PsiTypeParameter)returnType).getExtendsList().getReferencedTypes().length == 0; } if (!immutable) { immutable = Mutability.getMutability(method).isUnmodifiable(); } } return immutable && !SideEffectChecker.mayHaveSideEffects(call); }