Boolean (@NotNull JvmClass clazz) { if (clazz.getClassKind() != JvmClassKind.CLASS || clazz.hasModifier(JvmModifier.ABSTRACT) || !JvmInheritanceUtil.isInheritor(clazz, ActionUpdateThreadAware.class.getName())) { return false; } boolean isAnAction = false; boolean hasUpdateMethod = false; JBIterable<JvmReferenceType> superInterfaces = JBIterable.empty(); for (JvmClass c = clazz; c != null; c = JvmUtil.resolveClass(c.getSuperClassType())) { String className = c.getQualifiedName(); if (CommonClassNames.JAVA_LANG_OBJECT.equals(className) || (isAnAction = AnAction.class.getName().equals(className))) { break; } for (JvmMethod method : c.getMethods()) { String name = method.getName(); if ("getActionUpdateThread".equals(name) && method.getParameters().length == 0) { return null; } else if ("update".equals(name) && !hasUpdateMethod) { JvmParameter[] parameters = method.getParameters(); JvmType pt = parameters.length == 1 ? parameters[0].getType() : null; JvmClass pc = pt instanceof JvmReferenceType ? JvmUtil.resolveClass((JvmReferenceType)pt) : null; if (pc != null && AnActionEvent.class.getName().equals(pc.getQualifiedName())) { hasUpdateMethod = true; } } } superInterfaces = superInterfaces.append(JBIterable.of(c.getInterfaceTypes())); } if (!isAnAction) { // Check super-interfaces for default methods - no need to check if the method is default. // Default override is good, non-default override without the implementation is a compiler error. JBTreeTraverser<JvmClass> traverser = JBTreeTraverser.from(o -> JBIterable.of(o.getSuperClassType()) .filterMap(JvmUtil::resolveClass)); for (JvmClass c : traverser.unique().withRoots(superInterfaces.filterMap(JvmUtil::resolveClass))) { if (ActionUpdateThreadAware.class.getName().equals(c.getQualifiedName())) continue; for (JvmMethod method : c.getMethods()) { if ("getActionUpdateThread".equals(method.getName()) && method.getParameters().length == 0) { return null; } } } } if (!isAnAction || hasUpdateMethod) { sink.highlight(DevKitBundle.message("inspections.action.update.thread.message")); } return false; }