@Nullable
  @Override
  public ConversionResult isConvertible(@NotNull PsiType targetType,
                                        @NotNull PsiType actualType,
                                        @NotNull Position position,
                                        @NotNull GroovyPsiElement context) {

    final PsiClassType objectType = TypesUtil.getJavaLangObject(context);
    boolean isCompileStatic = CompileStaticUtil.isCompileStatic(context);
    if (position == Position.RETURN_VALUE) {
      if (targetType.equals(objectType) && PsiTypes.voidType().equals(actualType)) {
        return OK;
      }
    }

    if (PsiTypes.voidType().equals(actualType)) {
      switch (position) {
        case RETURN_VALUE -> {
          // We can return void values from method. But it's very suspicious.
          return WARNING;
        }
        case ASSIGNMENT -> {
          if (targetType.equals(PsiTypes.booleanType())) return null;
          if (targetType.equals(PsiType.getJavaLangString(context.getManager(), context.getResolveScope()))) return WARNING;
          return isCompileStatic ? ERROR : WARNING;
        }
        default -> {
        }
      }
    }
    else if (actualType == PsiTypes.nullType()) {
      if (position == Position.RETURN_VALUE) {
        // We can return null from method returning primitive type, but runtime error will occur.
        if (targetType instanceof PsiPrimitiveType) return WARNING;
      }
      else {
        return targetType instanceof PsiPrimitiveType ? ERROR : OK;
      }
    }
    return null;
  }
@Nullable
  @Override
  public ConversionResult isConvertible(@NotNull PsiType targetType,
                                        @NotNull PsiType actualType,
                                        @NotNull Position position,
                                        @NotNull GroovyPsiElement context)