@Nullable
  public static PsiExpression substituteThis(@Nullable PsiElement expressionWithThis, PsiExpression howToEvaluateThis, Value howToEvaluateThisValue)
    throws EvaluateException {
    if (!(expressionWithThis instanceof PsiExpression)) return null;
    PsiExpression result = (PsiExpression)expressionWithThis.copy();

    PsiClass thisClass = PsiTreeUtil.getContextOfType(result, PsiClass.class, true);

    boolean castNeeded = true;

    if (thisClass != null) {
      PsiType type = howToEvaluateThis.getType();
      if (type != null) {
        if (type instanceof PsiClassType) {
          PsiClass psiClass = ((PsiClassType)type).resolve();
          if (psiClass != null && (psiClass == thisClass || psiClass.isInheritor(thisClass, true))) {
            castNeeded = false;
          }
        }
        else if (type instanceof PsiArrayType && PsiUtil.isArrayClass(thisClass)) {
          castNeeded = false;
        }
      }
    }

    if (castNeeded) {
      howToEvaluateThis = castToRuntimeType(howToEvaluateThis, howToEvaluateThisValue);
    }

    ChangeContextUtil.encodeContextInfo(result, false);
    PsiExpression psiExpression;
    try {
      psiExpression = (PsiExpression)ChangeContextUtil.decodeContextInfo(result, thisClass, howToEvaluateThis);
    }
    catch (IncorrectOperationException e) {
      throw new EvaluateException(
        JavaDebuggerBundle.message("evaluation.error.invalid.this.expression", result.getText(), howToEvaluateThis.getText()), null);
    }

    try {
      PsiExpression res = JavaPsiFacade.getElementFactory(howToEvaluateThis.getProject())
        .createExpressionFromText(psiExpression.getText(), howToEvaluateThis.getContext());
      res.putUserData(ADDITIONAL_IMPORTS_KEY, howToEvaluateThis.getUserData(ADDITIONAL_IMPORTS_KEY));
      return res;
    }
    catch (IncorrectOperationException e) {
      throw new EvaluateException(e.getMessage(), e);
    }
  }
@Nullable
  public static PsiExpression substituteThis(@Nullable PsiElement expressionWithThis, PsiExpression howToEvaluateThis, Value howToEvaluateThisValue)