public static PsiType getType(@NotNull PsiClassObjectAccessExpression classAccessExpression) {
    GlobalSearchScope resolveScope = classAccessExpression.getResolveScope();
    PsiManager manager = classAccessExpression.getManager();
    final PsiClass classClass =
        JavaPsiFacade.getInstance(manager.getProject()).findClass("java.lang.Class", resolveScope);
    if (classClass == null) {
      return new PsiClassReferenceType(
          new LightClassReference(manager, "Class", "java.lang.Class", resolveScope), null);
    }
    if (!PsiUtil.isLanguageLevel5OrHigher(classAccessExpression)) {
      // Raw java.lang.Class
      return JavaPsiFacade.getInstance(manager.getProject())
          .getElementFactory()
          .createType(classClass);
    }

    PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
    PsiType operandType = classAccessExpression.getOperand().getType();
    if (operandType instanceof PsiPrimitiveType && !PsiType.NULL.equals(operandType)) {
      if (PsiType.VOID.equals(operandType)) {
        operandType =
            JavaPsiFacade.getInstance(manager.getProject())
                .getElementFactory()
                .createTypeByFQClassName("java.lang.Void", classAccessExpression.getResolveScope());
      } else {
        operandType = ((PsiPrimitiveType) operandType).getBoxedType(classAccessExpression);
      }
    }
    final PsiTypeParameter[] typeParameters = classClass.getTypeParameters();
    if (typeParameters.length == 1) {
      substitutor = substitutor.put(typeParameters[0], operandType);
    }

    return new PsiImmediateClassType(classClass, substitutor);
  }
 @Override
 protected final void doFix(Project project, ProblemDescriptor descriptor)
     throws IncorrectOperationException {
   final PsiElement element = descriptor.getPsiElement();
   final PsiTypeElement castTypeElement;
   final PsiReferenceExpression reference;
   if (element instanceof PsiTypeCastExpression) {
     final PsiTypeCastExpression typeCastExpression = (PsiTypeCastExpression) element;
     castTypeElement = typeCastExpression.getCastType();
     final PsiExpression operand = typeCastExpression.getOperand();
     if (!(operand instanceof PsiReferenceExpression)) {
       return;
     }
     reference = (PsiReferenceExpression) operand;
   } else if (element instanceof PsiMethodCallExpression) {
     final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression) element;
     final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
     final PsiExpression qualifier = methodExpression.getQualifierExpression();
     if (!(qualifier instanceof PsiClassObjectAccessExpression)) {
       return;
     }
     final PsiClassObjectAccessExpression classObjectAccessExpression =
         (PsiClassObjectAccessExpression) qualifier;
     castTypeElement = classObjectAccessExpression.getOperand();
     final PsiExpressionList argumentList = methodCallExpression.getArgumentList();
     final PsiExpression[] arguments = argumentList.getExpressions();
     if (arguments.length != 1) {
       return;
     }
     final PsiExpression argument = arguments[0];
     if (!(argument instanceof PsiReferenceExpression)) {
       return;
     }
     reference = (PsiReferenceExpression) argument;
   } else {
     return;
   }
   if (castTypeElement == null) {
     return;
   }
   final PsiInstanceOfExpression conflictingInstanceof =
       InstanceOfUtils.getConflictingInstanceof(castTypeElement.getType(), reference, element);
   final PsiTypeElement instanceofTypeElement = conflictingInstanceof.getCheckType();
   if (instanceofTypeElement == null) {
     return;
   }
   final PsiElement newElement = replace(castTypeElement, instanceofTypeElement);
   final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project);
   codeStyleManager.shortenClassReferences(newElement);
 }
 @Override
 public void visitMethodCallExpression(PsiMethodCallExpression expression) {
   super.visitMethodCallExpression(expression);
   final PsiReferenceExpression methodExpression = expression.getMethodExpression();
   final String methodName = methodExpression.getReferenceName();
   if (!"cast".equals(methodName)) {
     return;
   }
   final PsiMethod method = expression.resolveMethod();
   if (method == null) {
     return;
   }
   final PsiClass containingClass = method.getContainingClass();
   if (containingClass == null) {
     return;
   }
   final String qualifiedName = containingClass.getQualifiedName();
   if (!"java.lang.Class".equals(qualifiedName)) {
     return;
   }
   final PsiExpression qualifier = methodExpression.getQualifierExpression();
   if (!(qualifier instanceof PsiClassObjectAccessExpression)) {
     return;
   }
   final PsiClassObjectAccessExpression classObjectAccessExpression =
       (PsiClassObjectAccessExpression) qualifier;
   final PsiTypeElement operand = classObjectAccessExpression.getOperand();
   final PsiType castType = operand.getType();
   if (!(castType instanceof PsiClassType)) {
     return;
   }
   final PsiExpressionList argumentList = expression.getArgumentList();
   final PsiExpression[] arguments = argumentList.getExpressions();
   if (arguments.length != 1) {
     return;
   }
   final PsiExpression argument = arguments[0];
   if (!(argument instanceof PsiReferenceExpression)) {
     return;
   }
   final PsiReferenceExpression referenceExpression = (PsiReferenceExpression) argument;
   final PsiInstanceOfExpression conflictingInstanceof =
       InstanceOfUtils.getConflictingInstanceof(castType, referenceExpression, expression);
   if (conflictingInstanceof == null) {
     return;
   }
   final PsiTypeElement instanceofTypeElement = conflictingInstanceof.getCheckType();
   registerError(expression, referenceExpression, operand, instanceofTypeElement);
 }
 private static boolean classObjectAccessExpressionsAreEquivalent(
     PsiClassObjectAccessExpression expression1, PsiClassObjectAccessExpression expression2) {
   final PsiTypeElement operand1 = expression1.getOperand();
   final PsiTypeElement operand2 = expression2.getOperand();
   return typeElementsAreEquivalent(operand1, operand2);
 }
 @Override
 public void visitClassObjectAccessExpression(PsiClassObjectAccessExpression expression) {
   super.visitClassObjectAccessExpression(expression);
   PsiElement parent = expression.getParent();
   if (parent instanceof PsiReferenceExpression) {
     final PsiReferenceExpression referenceExpression = (PsiReferenceExpression) parent;
     if (!expression.equals(referenceExpression.getQualifierExpression())) {
       return;
     }
     @NonNls final String name = referenceExpression.getReferenceName();
     if (!"getName".equals(name)) {
       return;
     }
     final PsiElement grandParent = referenceExpression.getParent();
     if (!(grandParent instanceof PsiMethodCallExpression)) {
       return;
     }
     final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression) grandParent;
     final PsiExpressionList list = methodCallExpression.getArgumentList();
     if (list.getExpressions().length != 0) {
       return;
     }
     parent = methodCallExpression.getParent();
   }
   if (!(parent instanceof PsiExpressionList)) {
     return;
   }
   final PsiElement grandParent = parent.getParent();
   if (!(grandParent instanceof PsiMethodCallExpression)) {
     return;
   }
   final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression) grandParent;
   final PsiExpressionList argumentList = methodCallExpression.getArgumentList();
   final PsiExpression[] expressions = argumentList.getExpressions();
   if (expressions.length != 1) {
     return;
   }
   final PsiClass containingClass = PsiTreeUtil.getParentOfType(expression, PsiClass.class);
   if (containingClass == null) {
     return;
   }
   final String containingClassName = containingClass.getName();
   if (containingClassName == null) {
     return;
   }
   final PsiMethod method = methodCallExpression.resolveMethod();
   if (method == null) {
     return;
   }
   final PsiClass aClass = method.getContainingClass();
   if (aClass == null) {
     return;
   }
   final String className = aClass.getQualifiedName();
   final int index = loggerFactoryClassNames.indexOf(className);
   if (index < 0) {
     return;
   }
   final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
   final String referenceName = methodExpression.getReferenceName();
   final String loggerFactoryMethodName = loggerFactoryMethodNames.get(index);
   if (!loggerFactoryMethodName.equals(referenceName)) {
     return;
   }
   final PsiTypeElement operand = expression.getOperand();
   final PsiType type = operand.getType();
   if (!(type instanceof PsiClassType)) {
     return;
   }
   final PsiClassType classType = (PsiClassType) type;
   final PsiClass initializerClass = classType.resolve();
   if (initializerClass == null) {
     return;
   }
   if (containingClass.equals(initializerClass)) {
     return;
   }
   registerError(expression, containingClassName);
 }