mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-16 22:51:17 +07:00
[java] Ignore static and final methods in OverrideOnlyInspection
#IDEA-367314 Fixed GitOrigin-RevId: 418750107648323fe36a75c492d05a9e499268b2
This commit is contained in:
committed by
intellij-monorepo-bot
parent
6c7da7b25a
commit
69ddce69ae
@@ -1,15 +1,14 @@
|
|||||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||||
package com.intellij.codeInspection
|
package com.intellij.codeInspection
|
||||||
|
|
||||||
import com.intellij.analysis.JvmAnalysisBundle
|
import com.intellij.analysis.JvmAnalysisBundle
|
||||||
import com.intellij.codeInsight.daemon.impl.analysis.HighlightMessageUtil
|
import com.intellij.codeInsight.daemon.impl.analysis.HighlightMessageUtil
|
||||||
import com.intellij.codeInspection.apiUsage.ApiUsageProcessor
|
import com.intellij.codeInspection.apiUsage.ApiUsageProcessor
|
||||||
import com.intellij.codeInspection.apiUsage.ApiUsageUastVisitor
|
import com.intellij.codeInspection.apiUsage.ApiUsageUastVisitor
|
||||||
|
import com.intellij.lang.jvm.JvmModifier
|
||||||
import com.intellij.openapi.roots.ProjectFileIndex
|
import com.intellij.openapi.roots.ProjectFileIndex
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
import com.intellij.psi.PsiElementVisitor
|
import com.intellij.psi.PsiElementVisitor
|
||||||
import com.intellij.psi.PsiMethod
|
import com.intellij.psi.PsiMethod
|
||||||
import com.intellij.psi.PsiModifier
|
|
||||||
import com.intellij.psi.PsiModifierListOwner
|
import com.intellij.psi.PsiModifierListOwner
|
||||||
import com.intellij.psi.util.MethodSignatureUtil
|
import com.intellij.psi.util.MethodSignatureUtil
|
||||||
import com.intellij.psi.util.PsiUtilCore
|
import com.intellij.psi.util.PsiUtilCore
|
||||||
@@ -28,7 +27,6 @@ private inline val ANNOTATION_NAME get() = ApiStatus.OverrideOnly::class.java.ca
|
|||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
class OverrideOnlyInspection : LocalInspectionTool() {
|
class OverrideOnlyInspection : LocalInspectionTool() {
|
||||||
|
|
||||||
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor =
|
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor =
|
||||||
if (AnnotatedApiUsageUtil.canAnnotationBeUsedInFile(ANNOTATION_NAME, holder.file)) {
|
if (AnnotatedApiUsageUtil.canAnnotationBeUsedInFile(ANNOTATION_NAME, holder.file)) {
|
||||||
ApiUsageUastVisitor.createPsiElementVisitor(OverrideOnlyProcessor(holder))
|
ApiUsageUastVisitor.createPsiElementVisitor(OverrideOnlyProcessor(holder))
|
||||||
@@ -38,19 +36,21 @@ class OverrideOnlyInspection : LocalInspectionTool() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class OverrideOnlyProcessor(private val problemsHolder: ProblemsHolder) : ApiUsageProcessor {
|
private class OverrideOnlyProcessor(private val problemsHolder: ProblemsHolder) : ApiUsageProcessor {
|
||||||
|
private fun PsiMethod.isOverridable(): Boolean {
|
||||||
private fun isLibraryElement(element: PsiElement): Boolean {
|
return !hasModifier(JvmModifier.PRIVATE) && !hasModifier(JvmModifier.FINAL) && !hasModifier(JvmModifier.STATIC)
|
||||||
val containingVirtualFile = PsiUtilCore.getVirtualFile(element)
|
|
||||||
return containingVirtualFile != null && ProjectFileIndex.getInstance(element.project).isInLibraryClasses(containingVirtualFile)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isOverrideOnlyMethod(method: PsiMethod) =
|
private fun isLibraryElement(method: PsiMethod): Boolean {
|
||||||
method.hasAnnotation(ANNOTATION_NAME) ||
|
val containingVirtualFile = PsiUtilCore.getVirtualFile(method)
|
||||||
!method.hasModifierProperty(PsiModifier.STATIC) && method.containingClass?.hasAnnotation(ANNOTATION_NAME) == true
|
return containingVirtualFile != null && ProjectFileIndex.getInstance(method.project).isInLibraryClasses(containingVirtualFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isOverrideOnlyMethod(method: PsiMethod): Boolean {
|
||||||
|
return method.hasAnnotation(ANNOTATION_NAME) || method.containingClass?.hasAnnotation(ANNOTATION_NAME) == true
|
||||||
|
}
|
||||||
|
|
||||||
private fun isInsideOverridenOnlyMethod(sourceNode: UElement, target: PsiMethod): Boolean = sourceNode.getContainingUMethod()?.let {
|
private fun isInsideOverridenOnlyMethod(sourceNode: UElement, target: PsiMethod): Boolean = sourceNode.getContainingUMethod()?.let {
|
||||||
val psiMethod = it.javaPsi as? PsiMethod ?: return false
|
MethodSignatureUtil.areSignaturesEqual(it.javaPsi, target)
|
||||||
MethodSignatureUtil.areSignaturesEqual(psiMethod, target)
|
|
||||||
} ?: false
|
} ?: false
|
||||||
|
|
||||||
private fun isSuperCall(qualifier: UExpression?) = qualifier is USuperExpression
|
private fun isSuperCall(qualifier: UExpression?) = qualifier is USuperExpression
|
||||||
@@ -67,7 +67,7 @@ class OverrideOnlyInspection : LocalInspectionTool() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun processReference(sourceNode: UElement, target: PsiModifierListOwner, qualifier: UExpression?) {
|
override fun processReference(sourceNode: UElement, target: PsiModifierListOwner, qualifier: UExpression?) {
|
||||||
if (target is PsiMethod && isOverrideOnlyMethod(target) && isLibraryElement(target)
|
if (target is PsiMethod && target.isOverridable() && isLibraryElement(target) && isOverrideOnlyMethod(target)
|
||||||
&& !isSuperOrDelegateCall(sourceNode, target, qualifier)) {
|
&& !isSuperOrDelegateCall(sourceNode, target, qualifier)) {
|
||||||
val elementToHighlight = sourceNode.sourcePsi ?: return
|
val elementToHighlight = sourceNode.sourcePsi ?: return
|
||||||
val methodName = HighlightMessageUtil.getSymbolName(target) ?: return
|
val methodName = HighlightMessageUtil.getSymbolName(target) ?: return
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -8,6 +8,7 @@ import library.KotlinInterface;
|
|||||||
|
|
||||||
import library.JavaClassOverrideOnly;
|
import library.JavaClassOverrideOnly;
|
||||||
import library.JavaInterfaceOverrideOnly;
|
import library.JavaInterfaceOverrideOnly;
|
||||||
|
import library.JavaMembersOverrideOnly;
|
||||||
import library.KotlinClassOverrideOnly;
|
import library.KotlinClassOverrideOnly;
|
||||||
import library.KotlinInterfaceOverrideOnly;
|
import library.KotlinInterfaceOverrideOnly;
|
||||||
|
|
||||||
@@ -20,6 +21,7 @@ class Invoker {
|
|||||||
|
|
||||||
JavaClassOverrideOnly javaClassOverrideOnly,
|
JavaClassOverrideOnly javaClassOverrideOnly,
|
||||||
JavaInterfaceOverrideOnly javaInterfaceOverrideOnly,
|
JavaInterfaceOverrideOnly javaInterfaceOverrideOnly,
|
||||||
|
JavaMembersOverrideOnly javeMembersOverrideOnly,
|
||||||
KotlinClassOverrideOnly kotlinClassOverrideOnly,
|
KotlinClassOverrideOnly kotlinClassOverrideOnly,
|
||||||
KotlinInterfaceOverrideOnly kotlinInterfaceOverrideOnly
|
KotlinInterfaceOverrideOnly kotlinInterfaceOverrideOnly
|
||||||
) {
|
) {
|
||||||
@@ -29,13 +31,17 @@ class Invoker {
|
|||||||
kotlinInterface.<warning descr="Method 'implementOnlyMethod()' can only be overridden">implementOnlyMethod</warning>();
|
kotlinInterface.<warning descr="Method 'implementOnlyMethod()' can only be overridden">implementOnlyMethod</warning>();
|
||||||
|
|
||||||
javaClassOverrideOnly.<warning descr="Method 'overrideOnlyMethod()' can only be overridden">overrideOnlyMethod</warning>();
|
javaClassOverrideOnly.<warning descr="Method 'overrideOnlyMethod()' can only be overridden">overrideOnlyMethod</warning>();
|
||||||
|
javaClassOverrideOnly.finalMethod(); // no warning because it's a final method
|
||||||
javaInterfaceOverrideOnly.<warning descr="Method 'implementOnlyMethod()' can only be overridden">implementOnlyMethod</warning>();
|
javaInterfaceOverrideOnly.<warning descr="Method 'implementOnlyMethod()' can only be overridden">implementOnlyMethod</warning>();
|
||||||
|
javeMembersOverrideOnly.<warning descr="Method 'implementOnlyMethod()' can only be overridden">implementOnlyMethod</warning>();
|
||||||
|
javeMembersOverrideOnly.finalMethod(); // no warning because it's a final method
|
||||||
kotlinClassOverrideOnly.<warning descr="Method 'overrideOnlyMethod()' can only be overridden">overrideOnlyMethod</warning>();
|
kotlinClassOverrideOnly.<warning descr="Method 'overrideOnlyMethod()' can only be overridden">overrideOnlyMethod</warning>();
|
||||||
kotlinInterfaceOverrideOnly.<warning descr="Method 'implementOnlyMethod()' can only be overridden">implementOnlyMethod</warning>();
|
kotlinInterfaceOverrideOnly.<warning descr="Method 'implementOnlyMethod()' can only be overridden">implementOnlyMethod</warning>();
|
||||||
|
|
||||||
//No warning
|
//No warning
|
||||||
JavaClassOverrideOnly.staticMethod();
|
JavaClassOverrideOnly.staticMethod();
|
||||||
JavaInterfaceOverrideOnly.staticMethod();
|
JavaInterfaceOverrideOnly.staticMethod();
|
||||||
|
JavaMembersOverrideOnly.staticMethod();
|
||||||
KotlinClassOverrideOnly.staticMethod();
|
KotlinClassOverrideOnly.staticMethod();
|
||||||
KotlinInterfaceOverrideOnly.staticMethod();
|
KotlinInterfaceOverrideOnly.staticMethod();
|
||||||
}
|
}
|
||||||
@@ -47,15 +53,19 @@ class Invoker {
|
|||||||
Consumer<KotlinInterface> d = KotlinInterface::<warning descr="Method 'implementOnlyMethod()' can only be overridden">implementOnlyMethod</warning>;
|
Consumer<KotlinInterface> d = KotlinInterface::<warning descr="Method 'implementOnlyMethod()' can only be overridden">implementOnlyMethod</warning>;
|
||||||
|
|
||||||
Consumer<JavaClassOverrideOnly> a1 = JavaClassOverrideOnly::<warning descr="Method 'overrideOnlyMethod()' can only be overridden">overrideOnlyMethod</warning>;
|
Consumer<JavaClassOverrideOnly> a1 = JavaClassOverrideOnly::<warning descr="Method 'overrideOnlyMethod()' can only be overridden">overrideOnlyMethod</warning>;
|
||||||
|
Consumer<JavaClassOverrideOnly> a2 = JavaClassOverrideOnly::finalMethod; // no warning because it's a final method
|
||||||
Consumer<JavaInterfaceOverrideOnly> b1 = JavaInterfaceOverrideOnly::<warning descr="Method 'implementOnlyMethod()' can only be overridden">implementOnlyMethod</warning>;
|
Consumer<JavaInterfaceOverrideOnly> b1 = JavaInterfaceOverrideOnly::<warning descr="Method 'implementOnlyMethod()' can only be overridden">implementOnlyMethod</warning>;
|
||||||
Consumer<KotlinClassOverrideOnly> c1 = KotlinClassOverrideOnly::<warning descr="Method 'overrideOnlyMethod()' can only be overridden">overrideOnlyMethod</warning>;
|
Consumer<JavaMembersOverrideOnly> c1 = JavaMembersOverrideOnly::<warning descr="Method 'implementOnlyMethod()' can only be overridden">implementOnlyMethod</warning>;
|
||||||
Consumer<KotlinInterfaceOverrideOnly> d1 = KotlinInterfaceOverrideOnly::<warning descr="Method 'implementOnlyMethod()' can only be overridden">implementOnlyMethod</warning>;
|
Consumer<JavaMembersOverrideOnly> c2 = JavaMembersOverrideOnly::finalMethod; // no warning because it's a final method
|
||||||
|
Consumer<KotlinClassOverrideOnly> d1 = KotlinClassOverrideOnly::<warning descr="Method 'overrideOnlyMethod()' can only be overridden">overrideOnlyMethod</warning>;
|
||||||
|
Consumer<KotlinInterfaceOverrideOnly> e1 = KotlinInterfaceOverrideOnly::<warning descr="Method 'implementOnlyMethod()' can only be overridden">implementOnlyMethod</warning>;
|
||||||
|
|
||||||
//No warning
|
//No warning
|
||||||
Runnable a2 = JavaClassOverrideOnly::staticMethod;
|
Runnable a3 = JavaClassOverrideOnly::staticMethod;
|
||||||
Runnable b2 = JavaInterfaceOverrideOnly::staticMethod;
|
Runnable b2 = JavaInterfaceOverrideOnly::staticMethod;
|
||||||
Runnable c2 = KotlinClassOverrideOnly::staticMethod;
|
Runnable c3 = JavaMembersOverrideOnly::staticMethod;
|
||||||
Runnable d2 = KotlinInterfaceOverrideOnly::staticMethod;
|
Runnable d2 = KotlinClassOverrideOnly::staticMethod;
|
||||||
|
Runnable e2 = KotlinInterfaceOverrideOnly::staticMethod;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,4 +8,6 @@ public abstract class JavaClassOverrideOnly {
|
|||||||
public abstract void overrideOnlyMethod();
|
public abstract void overrideOnlyMethod();
|
||||||
|
|
||||||
public static void staticMethod() { }
|
public static void staticMethod() { }
|
||||||
|
|
||||||
|
public final void finalMethod() { }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package library;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.ApiStatus.OverrideOnly;
|
||||||
|
|
||||||
|
public abstract class JavaMembersOverrideOnly {
|
||||||
|
@OverrideOnly
|
||||||
|
public abstract void implementOnlyMethod();
|
||||||
|
|
||||||
|
@OverrideOnly
|
||||||
|
public static void staticMethod() { }
|
||||||
|
|
||||||
|
@OverrideOnly
|
||||||
|
public final void finalMethod() { }
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user