public static @Nullable PluginId doFindPluginId(@NotNull Throwable t) {
    if (t instanceof PluginException) {
      return ((PluginException)t).getPluginId();
    }

    PluginId bundledId = null;
    Set<String> visitedClassNames = new HashSet<>();
    for (StackTraceElement element : t.getStackTrace()) {
      if (element != null) {
        String className = element.getClassName();
        if (visitedClassNames.add(className)) {
          PluginDescriptor descriptor = PluginManagerCore.getPluginDescriptorOrPlatformByClassName(className);
          PluginId id = descriptor == null ? null : descriptor.getPluginId();
          if (id != null && !PluginManagerCore.CORE_ID.equals(id)) {
            if (descriptor.isBundled()) {
              if (bundledId == null) {
                bundledId = id;
                logPluginDetection(className, id);
              }
            }
            else {
              logPluginDetection(className, id);
              return id;
            }
          }
        }
      }
    }

    if (t instanceof NoSuchMethodException) {
      // check is method called from plugin classes
      if (t.getMessage() != null) {
        StringBuilder className = new StringBuilder();
        StringTokenizer tok = new StringTokenizer(t.getMessage(), ".");
        while (tok.hasMoreTokens()) {
          String token = tok.nextToken();
          if (!token.isEmpty() && Character.isJavaIdentifierStart(token.charAt(0))) {
            className.append(token);
          }
        }

        PluginId pluginId = PluginManager.getPluginByClassNameAsNoAccessToClass(className.toString());
        if (pluginId != null) {
          return pluginId;
        }
      }
    }
    else if (t instanceof ClassNotFoundException) {
      // check is class from plugin classes
      if (t.getMessage() != null) {
        PluginId id = PluginManager.getPluginByClassNameAsNoAccessToClass(t.getMessage());
        if (id != null) {
          return id;
        }
      }
    }
    else if (t instanceof NoClassDefFoundError && t.getMessage() != null) {
      String className = StringUtil.substringAfterLast(t.getMessage(), " ");
      if (className == null) className = t.getMessage();
      if (className.indexOf('/') > 0) {
        className = className.replace('/', '.');
      }

      PluginId id = PluginManager.getPluginByClassNameAsNoAccessToClass(className);
      if (id != null) {
        return PluginManager.getPluginByClassNameAsNoAccessToClass(className);
      }
    }
    else if (t instanceof AbstractMethodError && t.getMessage() != null) {
      String s = t.getMessage();
      int pos = s.indexOf('(');
      if (pos >= 0) {
        s = s.substring(0, pos);
        pos = s.lastIndexOf('.');
        if (pos >= 0) {
          s = s.substring(0, pos);
          PluginId id = PluginManager.getPluginByClassNameAsNoAccessToClass(s);
          if (id != null) {
            return id;
          }
        }
      }
    }

    Throwable cause = t.getCause();
    PluginId causeId = cause == null ? null : doFindPluginId(cause);
    return causeId == null ? bundledId : causeId;
  }
public static @Nullable PluginId doFindPluginId(@NotNull Throwable t)