@Override
 public <T> T commitAndRunReadAction(@NotNull final Computable<T> computation) {
   final Ref<T> ref = Ref.create(null);
   commitAndRunReadAction(
       new Runnable() {
         @Override
         public void run() {
           ref.set(computation.compute());
         }
       });
   return ref.get();
 }
 public static boolean hasInjections(@NotNull PsiLanguageInjectionHost host) {
   if (!host.isPhysical()) return false;
   final Ref<Boolean> result = Ref.create(false);
   enumerate(
       host,
       new PsiLanguageInjectionHost.InjectedPsiVisitor() {
         @Override
         public void visit(
             @NotNull final PsiFile injectedPsi,
             @NotNull final List<PsiLanguageInjectionHost.Shred> places) {
           result.set(true);
         }
       });
   return result.get().booleanValue();
 }
  @Nullable
  public static PsiType getQualifiedMemberReferenceType(
      @Nullable PsiType qualifierType, @NotNull final PsiMember member) {
    final Ref<PsiSubstitutor> subst = Ref.create(PsiSubstitutor.EMPTY);
    class MyProcessor extends BaseScopeProcessor implements NameHint, ElementClassHint {
      @Override
      public boolean execute(@NotNull PsiElement element, @NotNull ResolveState state) {
        if (element == member) {
          subst.set(state.get(PsiSubstitutor.KEY));
        }
        return true;
      }

      @Override
      public String getName(@NotNull ResolveState state) {
        return member.getName();
      }

      @Override
      public boolean shouldProcess(DeclarationKind kind) {
        return member instanceof PsiEnumConstant
            ? kind == DeclarationKind.ENUM_CONST
            : member instanceof PsiField
                ? kind == DeclarationKind.FIELD
                : kind == DeclarationKind.METHOD;
      }

      @Override
      public <T> T getHint(@NotNull Key<T> hintKey) {
        return hintKey == NameHint.KEY || hintKey == ElementClassHint.KEY ? (T) this : null;
      }
    }

    PsiScopesUtil.processTypeDeclarations(qualifierType, member, new MyProcessor());

    PsiType rawType =
        member instanceof PsiField
            ? ((PsiField) member).getType()
            : member instanceof PsiMethod
                ? ((PsiMethod) member).getReturnType()
                : JavaPsiFacade.getElementFactory(member.getProject())
                    .createType((PsiClass) member);
    return subst.get().substitute(rawType);
  }
  private static Trinity<PsiElement, TextRange, Value> getSelectedExpression(
      final Project project, final Editor editor, final Point point, final ValueHintType type) {
    final Ref<PsiElement> selectedExpression = Ref.create(null);
    final Ref<TextRange> currentRange = Ref.create(null);
    final Ref<Value> preCalculatedValue = Ref.create(null);

    PsiDocumentManager.getInstance(project)
        .commitAndRunReadAction(
            new Runnable() {
              public void run() {
                // Point -> offset
                final int offset = calculateOffset(editor, point);

                PsiFile psiFile =
                    PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());

                if (psiFile == null || !psiFile.isValid()) return;

                int selectionStart = editor.getSelectionModel().getSelectionStart();
                int selectionEnd = editor.getSelectionModel().getSelectionEnd();

                if ((type == ValueHintType.MOUSE_CLICK_HINT
                        || type == ValueHintType.MOUSE_ALT_OVER_HINT)
                    && (selectionStart <= offset && offset <= selectionEnd)) {
                  PsiElement ctx =
                      (selectionStart > 0)
                          ? psiFile.findElementAt(selectionStart - 1)
                          : psiFile.findElementAt(selectionStart);
                  try {
                    String text = editor.getSelectionModel().getSelectedText();
                    if (text != null && ctx != null) {
                      selectedExpression.set(
                          JVMElementFactories.getFactory(ctx.getLanguage(), project)
                              .createExpressionFromText(text, ctx));
                      currentRange.set(
                          new TextRange(
                              editor.getSelectionModel().getSelectionStart(),
                              editor.getSelectionModel().getSelectionEnd()));
                    }
                  } catch (IncorrectOperationException ignored) {
                  }
                }

                if (currentRange.get() == null) {
                  PsiElement elementAtCursor = psiFile.findElementAt(offset);
                  if (elementAtCursor == null) {
                    return;
                  }
                  Pair<PsiElement, TextRange> pair =
                      findExpression(
                          elementAtCursor,
                          type == ValueHintType.MOUSE_CLICK_HINT
                              || type == ValueHintType.MOUSE_ALT_OVER_HINT);
                  if (pair == null) {
                    if (type == ValueHintType.MOUSE_OVER_HINT) {
                      final DebuggerSession debuggerSession =
                          DebuggerManagerEx.getInstanceEx(project)
                              .getContext()
                              .getDebuggerSession();
                      if (debuggerSession != null && debuggerSession.isPaused()) {
                        final Pair<Method, Value> lastExecuted =
                            debuggerSession.getProcess().getLastExecutedMethod();
                        if (lastExecuted != null) {
                          final Method method = lastExecuted.getFirst();
                          if (method != null) {
                            final Pair<PsiElement, TextRange> expressionPair =
                                findExpression(elementAtCursor, true);
                            if (expressionPair != null
                                && expressionPair.getFirst() instanceof PsiMethodCallExpression) {
                              final PsiMethodCallExpression methodCallExpression =
                                  (PsiMethodCallExpression) expressionPair.getFirst();
                              final PsiMethod psiMethod = methodCallExpression.resolveMethod();
                              if (psiMethod != null) {
                                final JVMName jvmSignature = JVMNameUtil.getJVMSignature(psiMethod);
                                try {
                                  if (method.name().equals(psiMethod.getName())
                                      && method
                                          .signature()
                                          .equals(
                                              jvmSignature.getName(debuggerSession.getProcess()))) {
                                    pair = expressionPair;
                                    preCalculatedValue.set(lastExecuted.getSecond());
                                  }
                                } catch (EvaluateException ignored) {
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                  if (pair == null) {
                    return;
                  }
                  selectedExpression.set(pair.getFirst());
                  currentRange.set(pair.getSecond());
                }
              }
            });
    return Trinity.create(selectedExpression.get(), currentRange.get(), preCalculatedValue.get());
  }