protected void checkFunction(
     JetNamedFunction function, SimpleFunctionDescriptor functionDescriptor) {
   reportErrorIfHasIllegalModifier(function);
   DeclarationDescriptor containingDescriptor = functionDescriptor.getContainingDeclaration();
   boolean hasAbstractModifier = function.hasModifier(JetTokens.ABSTRACT_KEYWORD);
   checkDeclaredTypeInPublicMember(function, functionDescriptor);
   if (containingDescriptor instanceof ClassDescriptor) {
     ClassDescriptor classDescriptor = (ClassDescriptor) containingDescriptor;
     boolean inTrait = classDescriptor.getKind() == ClassKind.INTERFACE;
     if (hasAbstractModifier && !classCanHaveAbstractMembers(classDescriptor)) {
       trace.report(
           ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS.on(
               function, functionDescriptor.getName().asString(), classDescriptor));
     }
     if (hasAbstractModifier && inTrait) {
       trace.report(ABSTRACT_MODIFIER_IN_TRAIT.on(function));
     }
     boolean hasBody = function.hasBody();
     if (hasBody && hasAbstractModifier) {
       trace.report(ABSTRACT_FUNCTION_WITH_BODY.on(function, functionDescriptor));
     }
     if (!hasBody && function.hasModifier(JetTokens.FINAL_KEYWORD) && inTrait) {
       trace.report(FINAL_FUNCTION_WITH_NO_BODY.on(function, functionDescriptor));
     }
     if (!hasBody && !hasAbstractModifier && !inTrait) {
       trace.report(NON_ABSTRACT_FUNCTION_WITH_NO_BODY.on(function, functionDescriptor));
     }
     return;
   }
   modifiersChecker.reportIllegalModalityModifiers(function);
   if (!function.hasBody() && !hasAbstractModifier) {
     trace.report(NON_MEMBER_FUNCTION_NO_BODY.on(function, functionDescriptor));
   }
 }