public static @NotNull BindingContext resolveToExpression(
      @NotNull final ResolveSession resolveSession, @NotNull JetExpression expression) {
    final DelegatingBindingTrace trace =
        new DelegatingBindingTrace(
            resolveSession.getBindingContext(), "trace to resolve expression", expression);
    JetFile file = (JetFile) expression.getContainingFile();

    @SuppressWarnings("unchecked")
    PsiElement topmostCandidateForAdditionalResolve =
        JetPsiUtil.getTopmostParentOfTypes(
            expression,
            JetNamedFunction.class,
            JetClassInitializer.class,
            JetProperty.class,
            JetDelegationSpecifierList.class);

    if (topmostCandidateForAdditionalResolve != null) {
      if (topmostCandidateForAdditionalResolve instanceof JetNamedFunction) {
        functionAdditionalResolve(
            resolveSession, (JetNamedFunction) topmostCandidateForAdditionalResolve, trace, file);
      } else if (topmostCandidateForAdditionalResolve instanceof JetClassInitializer) {
        initializerAdditionalResolve(
            resolveSession,
            (JetClassInitializer) topmostCandidateForAdditionalResolve,
            trace,
            file);
      } else if (topmostCandidateForAdditionalResolve instanceof JetProperty) {
        propertyAdditionalResolve(
            resolveSession, (JetProperty) topmostCandidateForAdditionalResolve, trace, file);
      } else if (topmostCandidateForAdditionalResolve instanceof JetDelegationSpecifierList) {
        delegationSpecifierAdditionalResolve(
            resolveSession,
            (JetDelegationSpecifierList) topmostCandidateForAdditionalResolve,
            trace,
            file);
      } else {
        assert false : "Invalid type of the topmost parent";
      }

      return trace.getBindingContext();
    }

    // Setup resolution scope explicitly
    if (trace.getBindingContext().get(BindingContext.RESOLUTION_SCOPE, expression) == null) {
      JetScope scope = getExpressionMemberScope(resolveSession, expression);
      if (scope != null) {
        trace.record(BindingContext.RESOLUTION_SCOPE, expression, scope);
      }
    }

    return trace.getBindingContext();
  }