diff --git a/plugins/devkit/devkit-core/src/navigation/ExtensionPointDeclarationRelatedItemLineMarkerProvider.kt b/plugins/devkit/devkit-core/src/navigation/ExtensionPointDeclarationRelatedItemLineMarkerProvider.kt index fc8e92ae5553..ab56c9a75b69 100644 --- a/plugins/devkit/devkit-core/src/navigation/ExtensionPointDeclarationRelatedItemLineMarkerProvider.kt +++ b/plugins/devkit/devkit-core/src/navigation/ExtensionPointDeclarationRelatedItemLineMarkerProvider.kt @@ -2,133 +2,84 @@ package org.jetbrains.idea.devkit.navigation import com.intellij.codeInsight.daemon.RelatedItemLineMarkerInfo -import com.intellij.openapi.extensions.ExtensionPointName -import com.intellij.openapi.extensions.ProjectExtensionPointName -import com.intellij.openapi.project.Project -import com.intellij.openapi.util.KeyedExtensionCollector +import com.intellij.openapi.roots.ProjectFileIndex +import com.intellij.psi.PsiClass import com.intellij.psi.PsiElement import com.intellij.psi.SmartPointerManager -import com.intellij.psi.util.InheritanceUtil -import com.intellij.psi.util.PsiTypesUtil -import org.jetbrains.annotations.NonNls -import org.jetbrains.idea.devkit.dom.index.ExtensionPointIndex +import org.jetbrains.idea.devkit.dom.ExtensionPoint +import org.jetbrains.idea.devkit.dom.index.ExtensionPointClassIndex import org.jetbrains.idea.devkit.util.ExtensionPointCandidate import org.jetbrains.idea.devkit.util.PluginRelatedLocatorsUtils -import org.jetbrains.uast.UCallExpression -import org.jetbrains.uast.UDeclaration -import org.jetbrains.uast.UExpression -import org.jetbrains.uast.UField -import org.jetbrains.uast.UQualifiedReferenceExpression -import org.jetbrains.uast.UastCallKind -import org.jetbrains.uast.evaluateString -import org.jetbrains.uast.expressions.UInjectionHost -import org.jetbrains.uast.getParentOfType -import org.jetbrains.uast.getUParentForIdentifier -import org.jetbrains.uast.sourcePsiElement +import org.jetbrains.uast.UClass +import org.jetbrains.uast.toUElement /** - * Provides gutter icon for EP code declaration to matching `` in `plugin.xml`. + * Provides gutter icon for EP interface class to matching `` in `plugin.xml`. */ internal class ExtensionPointDeclarationRelatedItemLineMarkerProvider : DevkitRelatedLineMarkerProviderBase() { + override fun collectNavigationMarkers(element: PsiElement, result: MutableCollection?>) { - val uElement = getUParentForIdentifier(element) - if (uElement is UField) { - if (!isExtensionPointNameDeclarationField(uElement)) return - process(resolveEpFqn(uElement), uElement, element.getProject(), result) - } else if (uElement is UCallExpression) { - if (!isExtensionPointNameDeclarationViaSuperCall(uElement)) return + val uClass = element.toUElement(UClass::class.java) ?: return + val psiClass = uClass.javaPsi + val project = psiClass.project + val scope = PluginRelatedLocatorsUtils.getCandidatesScope(project) - val uDeclaration = checkNotNull(uElement.getParentOfType(UDeclaration::class.java)) { uElement.asSourceString() } - process(resolveEpFqn(uElement), uDeclaration, element.getProject(), result) - } - } + val extensionPoints = ExtensionPointClassIndex.getExtensionPointsByClass(project, psiClass, scope) + if (extensionPoints.isEmpty()) return - private fun process( - @NonNls epFqn: @NonNls String?, - uDeclaration: UDeclaration, - project: Project, - result: MutableCollection?> - ) { - if (epFqn == null) return + // Filter to only include EPs where this class is the interface or with.implements, not just the beanClass + val relevantEps = filterRelevantExtensionPoints(psiClass, extensionPoints) + if (relevantEps.isEmpty()) return - val point = ExtensionPointIndex.findExtensionPoint(project, PluginRelatedLocatorsUtils.getCandidatesScope(project), epFqn) - if (point == null) return + val classIdentifier = uClass.uastAnchor?.sourcePsi ?: return - val identifier = uDeclaration.uastAnchor.sourcePsiElement - if (identifier == null) return - - val candidate = ExtensionPointCandidate(SmartPointerManager.createPointer(point.getXmlTag()), epFqn) - val info = LineMarkerInfoHelper.createExtensionPointLineMarkerInfo(mutableListOf(candidate), identifier) + val targets = relevantEps.map { ExtensionPointCandidate(SmartPointerManager.createPointer(it.xmlTag), it.effectiveQualifiedName) } + val info = LineMarkerInfoHelper.createExtensionPointLineMarkerInfo(targets, classIdentifier) result.add(info) } - private fun isExtensionPointNameDeclarationViaSuperCall(uCallExpression: UCallExpression): Boolean { - if (uCallExpression.valueArgumentCount != 1) return false - if (uCallExpression.kind !== UastCallKind.CONSTRUCTOR_CALL) { - if (uCallExpression.kind !== UastCallKind.METHOD_CALL && uCallExpression.methodName != "super") { - return false + /** + * Filters extension points to only include those where the class is referenced as + * `interface` or `with.implements`, excluding those where it's only `beanClass` + * (it would show hundreds of inlay hints for classes like `LanguageExtensionPoint`). + */ + private fun filterRelevantExtensionPoints(psiClass: PsiClass, extensionPoints: List): List { + val classQualifiedName = psiClass.qualifiedName ?: return emptyList() + + val relevantEps = extensionPoints.filter { ep -> + // include if class is the EP interface + if (ep.`interface`.stringValue == classQualifiedName) { + return@filter true } + // include if class is the implementationClass of EP's `with` + for (withElement in ep.withElements) { + if (withElement.attribute.stringValue == "implementationClass" && withElement.implements.stringValue == classQualifiedName) { + return@filter true + } + } + false } - // Kotlin EP_NAME field with CTOR call -> handled by UField branch - if (uCallExpression.getParentOfType(UField::class.java) != null) { - return false + // handle duplications from Kotlin compiler frontend (OSIP-191) + val epsByQualifiedName = relevantEps.groupBy { it.effectiveQualifiedName } + return epsByQualifiedName.values.flatMap { + if (it.size > 1) { + val epsWithoutLibs = extensionPointsWithoutLibs(psiClass, it) + if (epsWithoutLibs.any()) { + return@flatMap epsWithoutLibs + } + } + it } - - val resolvedMethod = uCallExpression.resolve() - if (resolvedMethod == null) return false - if (!resolvedMethod.isConstructor()) return false - return InheritanceUtil.isInheritor(resolvedMethod.getContainingClass(), KeyedExtensionCollector::class.java.name) } - - @NonNls - private fun resolveEpFqn(uCallExpression: UCallExpression): @NonNls String? { - val uParameter = uCallExpression.getArgumentForParameter(0) - if (uParameter == null) return null - return uParameter.evaluateString() - } - - @NonNls - private fun resolveEpFqn(uField: UField): @NonNls String? { - val initializer = uField.uastInitializer - - var epNameExpression: UExpression? = null - if (initializer is UCallExpression) { - epNameExpression = initializer.getArgumentForParameter(0) - } else if (initializer is UQualifiedReferenceExpression) { - val selector = initializer.selector - - if (selector !is UCallExpression) return null - epNameExpression = selector.getArgumentForParameter(0) + private fun extensionPointsWithoutLibs(psiClass: PsiClass, relevantEps: List): List { + val project = psiClass.project + val projectFileIndex = ProjectFileIndex.getInstance(project) + val epsWithoutLibs = relevantEps.filter { + val virtualFile = it.xmlElement?.containingFile?.virtualFile ?: return@filter false + !projectFileIndex.isInLibrary(virtualFile) } - if (epNameExpression == null) return null - - if (epNameExpression is UInjectionHost) { - return epNameExpression.evaluateToString() - } - // constants - return epNameExpression.evaluateString() - } - - private fun isExtensionPointNameDeclarationField(uField: UField): Boolean { - if (!uField.isFinal) { - return false - } - - val initializer = uField.uastInitializer - if (initializer !is UCallExpression && initializer !is UQualifiedReferenceExpression) { - return false - } - - val fieldClass = PsiTypesUtil.getPsiClass(uField.getType()) - if (fieldClass == null) { - return false - } - - val qualifiedClassName = fieldClass.getQualifiedName() - return ExtensionPointName::class.java.name == qualifiedClassName || - ProjectExtensionPointName::class.java.name == qualifiedClassName || - InheritanceUtil.isInheritor(fieldClass, false, KeyedExtensionCollector::class.java.name) + return epsWithoutLibs } } diff --git a/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyBeanClassInterface.java b/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyBeanClassInterface.java new file mode 100644 index 000000000000..3e99e8f5c9b9 --- /dev/null +++ b/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyBeanClassInterface.java @@ -0,0 +1,2 @@ +public interface MyBeanClassInterface { +} diff --git a/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyBeanClassStringEP.java b/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyBeanClassStringEP.java deleted file mode 100644 index 760b26597d2a..000000000000 --- a/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyBeanClassStringEP.java +++ /dev/null @@ -1,10 +0,0 @@ -import com.intellij.openapi.extensions.ExtensionPointName; - -import java.lang.String; - -public class MyBeanClassStringEP { - - public static final ExtensionPointName EP_NAME = - ExtensionPointName.create("com.intellij.myBeanClassStringEP"); - -} \ No newline at end of file diff --git a/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyClass.java b/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyClass.java new file mode 100644 index 000000000000..a2f2ec6d955a --- /dev/null +++ b/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyClass.java @@ -0,0 +1,2 @@ +public class MyClass { +} diff --git a/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyInterface.java b/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyInterface.java new file mode 100644 index 000000000000..3795096324ff --- /dev/null +++ b/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyInterface.java @@ -0,0 +1,2 @@ +public interface MyInterface { +} diff --git a/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyMultipleEPsInterface.java b/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyMultipleEPsInterface.java new file mode 100644 index 000000000000..a605377d05a5 --- /dev/null +++ b/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyMultipleEPsInterface.java @@ -0,0 +1,2 @@ +public interface MyMultipleEPsInterface { +} diff --git a/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyStringEP.java b/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyStringEP.java deleted file mode 100644 index 23891c6d0158..000000000000 --- a/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyStringEP.java +++ /dev/null @@ -1,10 +0,0 @@ -import com.intellij.openapi.extensions.ExtensionPointName; - -import java.lang.String; - -public class MyStringEP { - - public static final ExtensionPointName EP_NAME = - ExtensionPointName.create("com.intellij.myStringEP"); - -} \ No newline at end of file diff --git a/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyStringEPConstructor.java b/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyStringEPConstructor.java deleted file mode 100644 index a0dc902ad0f8..000000000000 --- a/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyStringEPConstructor.java +++ /dev/null @@ -1,11 +0,0 @@ -import com.intellij.openapi.extensions.ExtensionPointName; - -import java.lang.String; - -public class MyStringEPConstructor { - - // private is allowed - private static final ExtensionPointName EP_NAME = - new ExtensionPointName("com.intellij.myStringEP"); - -} \ No newline at end of file diff --git a/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyStringEPLanguageExtension.java b/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyStringEPLanguageExtension.java deleted file mode 100644 index e0dd78d6b878..000000000000 --- a/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyStringEPLanguageExtension.java +++ /dev/null @@ -1,9 +0,0 @@ -import com.intellij.lang.LanguageExtension; -import java.lang.String; - -public class MyStringEP { - - public static final LanguageExtension EP_NAME = - new LanguageExtension("com.intellij.myStringEP", "My Default Implementation"); - -} \ No newline at end of file diff --git a/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyStringEPViaConstant.java b/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyStringEPViaConstant.java deleted file mode 100644 index 15c7ea02dff4..000000000000 --- a/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyStringEPViaConstant.java +++ /dev/null @@ -1,12 +0,0 @@ -import com.intellij.openapi.extensions.ExtensionPointName; - -import java.lang.String; - -public class MyStringEPViaConstant { - - public static final String EP_ID = "com.intellij.myStringEP"; - - public static final ExtensionPointName EP_NAME = - ExtensionPointName.create(EP_ID); - -} \ No newline at end of file diff --git a/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyStringEPViaLanguageExtensionSuperCall.java b/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyStringEPViaLanguageExtensionSuperCall.java deleted file mode 100644 index 131d5c9cef8f..000000000000 --- a/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyStringEPViaLanguageExtensionSuperCall.java +++ /dev/null @@ -1,7 +0,0 @@ -import com.intellij.lang.LanguageExtension; - -public class MyStringEPViaLanguageExtensionSuperCall extends LanguageExtension { - private MyStringEPViaLanguageExtensionSuperCall() { - super("com.intellij.myStringEP") - } -} \ No newline at end of file diff --git a/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyStringKeyedLazyInstanceEP.java b/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyStringKeyedLazyInstanceEP.java deleted file mode 100644 index 76b7969a3aeb..000000000000 --- a/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyStringKeyedLazyInstanceEP.java +++ /dev/null @@ -1,9 +0,0 @@ -import com.intellij.openapi.extensions.ExtensionPointName; -import com.intellij.util.KeyedLazyInstance; - -public class MyStringEP { - - public static final ExtensionPointName> EP_NAME = - ExtensionPointName.create("com.intellij.myStringEP"); - -} \ No newline at end of file diff --git a/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyStringProjectEP.java b/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyStringProjectEP.java deleted file mode 100644 index 870636e99750..000000000000 --- a/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyStringProjectEP.java +++ /dev/null @@ -1,10 +0,0 @@ -import com.intellij.openapi.extensions.ProjectExtensionPointName; - -import java.lang.String; - -public class MyStringProjectEP { - - public static final ProjectExtensionPointName EP_NAME = - new ProjectExtensionPointName<>("com.intellij.myStringEP"); - -} \ No newline at end of file diff --git a/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyWithImplementsInterface.java b/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyWithImplementsInterface.java new file mode 100644 index 000000000000..df97c444cc1e --- /dev/null +++ b/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/MyWithImplementsInterface.java @@ -0,0 +1,2 @@ +public interface MyWithImplementsInterface { +} diff --git a/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/extensionPointDeclarationEPs.xml b/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/extensionPointDeclarationEPs.xml index 3a8186231719..759a4d68ee9f 100644 --- a/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/extensionPointDeclarationEPs.xml +++ b/plugins/devkit/devkit-java-tests/testData/navigation/extensionPointDeclaration/extensionPointDeclarationEPs.xml @@ -1,11 +1,23 @@ - + + + + + + + + - - - + + + + + + + + \ No newline at end of file diff --git a/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/navigation/ExtensionPointDeclarationRelatedItemLineMarkerProviderTest.java b/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/navigation/ExtensionPointDeclarationRelatedItemLineMarkerProviderTest.java index 0dc1984cf0be..42f66b22f11e 100644 --- a/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/navigation/ExtensionPointDeclarationRelatedItemLineMarkerProviderTest.java +++ b/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/navigation/ExtensionPointDeclarationRelatedItemLineMarkerProviderTest.java @@ -1,4 +1,4 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.idea.devkit.navigation; import com.intellij.testFramework.TestDataPath; @@ -17,36 +17,4 @@ public class ExtensionPointDeclarationRelatedItemLineMarkerProviderTest protected String getExtension() { return ".java"; } - - public void testMyStringEP() { - assertStringEP(); - } - - public void testMyStringEPViaConstant() { - assertStringEP(); - } - - public void testMyStringEPConstructor() { - assertStringEP(); - } - - public void testMyStringEPLanguageExtension() { - assertStringEP(); - } - - public void testMyStringProjectEP() { - assertStringEP(); - } - - public void testMyStringKeyedLazyInstanceEP() { - assertStringEP(); - } - - public void testMyStringEPViaLanguageExtensionSuperCall() { - assertStringEP(); - } - - public void testMyBeanClassStringEP() { - assertSingleEPDeclaration("MyBeanClassStringEP.java", "com.intellij.myBeanClassStringEP"); - } -} \ No newline at end of file +} diff --git a/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyBeanClassInterface.kt b/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyBeanClassInterface.kt new file mode 100644 index 000000000000..a4e310e50f83 --- /dev/null +++ b/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyBeanClassInterface.kt @@ -0,0 +1 @@ +interface MyBeanClassInterface diff --git a/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyClass.kt b/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyClass.kt new file mode 100644 index 000000000000..bb5f1b0fbd9d --- /dev/null +++ b/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyClass.kt @@ -0,0 +1 @@ +interface MyClass diff --git a/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyInterface.kt b/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyInterface.kt new file mode 100644 index 000000000000..348d59ad33f8 --- /dev/null +++ b/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyInterface.kt @@ -0,0 +1 @@ +interface MyInterface diff --git a/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyMultipleEPsInterface.kt b/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyMultipleEPsInterface.kt new file mode 100644 index 000000000000..1bf9f468f7e3 --- /dev/null +++ b/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyMultipleEPsInterface.kt @@ -0,0 +1 @@ +interface MyMultipleEPsInterface diff --git a/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyStringEP.kt b/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyStringEP.kt deleted file mode 100644 index cf9b6938e371..000000000000 --- a/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyStringEP.kt +++ /dev/null @@ -1,8 +0,0 @@ -import com.intellij.openapi.extensions.ExtensionPointName - -class MyStringEP { - - companion object { - private val EP_NAME = ExtensionPointName.create("com.intellij.myStringEP") - } -} \ No newline at end of file diff --git a/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyStringEPConstructor.kt b/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyStringEPConstructor.kt deleted file mode 100644 index c642184d1ccd..000000000000 --- a/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyStringEPConstructor.kt +++ /dev/null @@ -1,8 +0,0 @@ -import com.intellij.openapi.extensions.ExtensionPointName - -class MyStringEPConstructor { - - companion object { - val EP_NAME = ExtensionPointName("com.intellij.myStringEP") - } -} \ No newline at end of file diff --git a/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyStringEPInterface.kt b/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyStringEPInterface.kt deleted file mode 100644 index 45246a621dd3..000000000000 --- a/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyStringEPInterface.kt +++ /dev/null @@ -1,7 +0,0 @@ -import com.intellij.openapi.extensions.ExtensionPointName -interface MyStringEPInterface { - - companion object { - private val EP_NAME = ExtensionPointName.create("com.intellij.myStringEP") - } -} \ No newline at end of file diff --git a/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyStringEPLanguageExtension.kt b/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyStringEPLanguageExtension.kt deleted file mode 100644 index 090868b23aa3..000000000000 --- a/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyStringEPLanguageExtension.kt +++ /dev/null @@ -1,8 +0,0 @@ -import com.intellij.lang.LanguageExtension - -class MyStringEPLanguageExtension { - - companion object { - val EP_NAME = LanguageExtension("com.intellij.myStringEP", "My Default Implementation") - } -} \ No newline at end of file diff --git a/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyStringEPViaConstant.kt b/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyStringEPViaConstant.kt deleted file mode 100644 index 018e6af072c8..000000000000 --- a/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyStringEPViaConstant.kt +++ /dev/null @@ -1,10 +0,0 @@ -import com.intellij.openapi.extensions.ExtensionPointName - - class MyStringEPViaConstant { - - companion object { - val EP_ID = "com.intellij.myStringEP" - - val EP_NAME = ExtensionPointName.create(EP_ID) - } - } diff --git a/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyStringEPViaInterpolation.kt b/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyStringEPViaInterpolation.kt deleted file mode 100644 index feb7efb2c6e6..000000000000 --- a/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyStringEPViaInterpolation.kt +++ /dev/null @@ -1,9 +0,0 @@ -import com.intellij.openapi.extensions.ExtensionPointName - -class MyStringEPViaInterpolation { - - companion object { - const val EP_SHORT_NAME = "myStringEP" - private val EP_NAME = ExtensionPointName.create("com.intellij.$EP_SHORT_NAME") - } -} \ No newline at end of file diff --git a/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyStringEPViaLanguageExtensionSuperCall.kt b/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyStringEPViaLanguageExtensionSuperCall.kt deleted file mode 100644 index 2e37443ed51a..000000000000 --- a/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyStringEPViaLanguageExtensionSuperCall.kt +++ /dev/null @@ -1,3 +0,0 @@ -import com.intellij.lang.LanguageExtension - -class MyStringEPViaLanguageExtensionSuperCall : LanguageExtension("com.intellij.myStringEP") {} \ No newline at end of file diff --git a/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyStringProjectEP.kt b/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyStringProjectEP.kt deleted file mode 100644 index bbbad7c429db..000000000000 --- a/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyStringProjectEP.kt +++ /dev/null @@ -1,8 +0,0 @@ -import com.intellij.openapi.extensions.ProjectExtensionPointName - -class MyStringProjectEP { - - companion object { - private val EP_NAME = ProjectExtensionPointName("com.intellij.myStringEP") - } -} \ No newline at end of file diff --git a/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyWithImplementsInterface.kt b/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyWithImplementsInterface.kt new file mode 100644 index 000000000000..0346873f1100 --- /dev/null +++ b/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/MyWithImplementsInterface.kt @@ -0,0 +1 @@ +interface MyWithImplementsInterface diff --git a/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/extensionPointDeclarationEPs.xml b/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/extensionPointDeclarationEPs.xml index 3a8186231719..759a4d68ee9f 100644 --- a/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/extensionPointDeclarationEPs.xml +++ b/plugins/devkit/devkit-kotlin-tests/testData/navigation/extensionPointDeclaration/extensionPointDeclarationEPs.xml @@ -1,11 +1,23 @@ - + + + + + + + + - - - + + + + + + + + \ No newline at end of file diff --git a/plugins/devkit/devkit-kotlin-tests/testSrc/org/jetbrains/idea/devkit/kotlin/navigation/KtExtensionPointDeclarationRelatedItemLineMarkerProviderTest.java b/plugins/devkit/devkit-kotlin-tests/testSrc/org/jetbrains/idea/devkit/kotlin/navigation/KtExtensionPointDeclarationRelatedItemLineMarkerProviderTest.java index 80abdb54e159..d848158d3135 100644 --- a/plugins/devkit/devkit-kotlin-tests/testSrc/org/jetbrains/idea/devkit/kotlin/navigation/KtExtensionPointDeclarationRelatedItemLineMarkerProviderTest.java +++ b/plugins/devkit/devkit-kotlin-tests/testSrc/org/jetbrains/idea/devkit/kotlin/navigation/KtExtensionPointDeclarationRelatedItemLineMarkerProviderTest.java @@ -1,4 +1,4 @@ -// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.idea.devkit.kotlin.navigation; import com.intellij.testFramework.TestDataPath; @@ -6,8 +6,9 @@ import org.jetbrains.idea.devkit.kotlin.DevkitKtTestsUtil; import org.jetbrains.idea.devkit.navigation.ExtensionPointDeclarationRelatedItemLineMarkerProviderTestBase; @TestDataPath("$CONTENT_ROOT/testData/navigation/extensionPointDeclaration") -public class KtExtensionPointDeclarationRelatedItemLineMarkerProviderTest extends - ExtensionPointDeclarationRelatedItemLineMarkerProviderTestBase { +public class KtExtensionPointDeclarationRelatedItemLineMarkerProviderTest + extends ExtensionPointDeclarationRelatedItemLineMarkerProviderTestBase { + @Override protected String getBasePath() { return DevkitKtTestsUtil.TESTDATA_PATH + "navigation/extensionPointDeclaration"; @@ -17,36 +18,4 @@ public class KtExtensionPointDeclarationRelatedItemLineMarkerProviderTest extend protected String getExtension() { return ".kt"; } - - public void testMyStringEP() { - assertStringEP(); - } - - public void testMyStringEPInterface() { - assertStringEP(); - } - - public void testMyStringEPViaConstant() { - assertStringEP(); - } - - public void testMyStringEPViaInterpolation() { - assertStringEP(); - } - - public void testMyStringEPConstructor() { - assertStringEP(); - } - - public void testMyStringEPLanguageExtension() { - assertStringEP(); - } - - public void testMyStringProjectEP() { - assertStringEP(); - } - - public void testMyStringEPViaLanguageExtensionSuperCall() { - assertStringEP(); - } } diff --git a/plugins/devkit/devkit-tests/testSrc/org/jetbrains/idea/devkit/navigation/ExtensionPointDeclarationRelatedItemLineMarkerProviderTestBase.java b/plugins/devkit/devkit-tests/testSrc/org/jetbrains/idea/devkit/navigation/ExtensionPointDeclarationRelatedItemLineMarkerProviderTestBase.java index fbd49ebdde5e..3536edf1af2a 100644 --- a/plugins/devkit/devkit-tests/testSrc/org/jetbrains/idea/devkit/navigation/ExtensionPointDeclarationRelatedItemLineMarkerProviderTestBase.java +++ b/plugins/devkit/devkit-tests/testSrc/org/jetbrains/idea/devkit/navigation/ExtensionPointDeclarationRelatedItemLineMarkerProviderTestBase.java @@ -1,4 +1,4 @@ -// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.idea.devkit.navigation; import com.intellij.codeInsight.daemon.GutterMark; @@ -24,8 +24,39 @@ public abstract class ExtensionPointDeclarationRelatedItemLineMarkerProviderTest moduleBuilder.addLibrary("platform-core", PathUtil.getJarPathForClass(LanguageExtension.class)); } - protected void assertStringEP() { - assertSingleEPDeclaration(getTestName(false) + getExtension(), "com.intellij.myStringEP"); + public void testMyInterface() { + assertSingleEPDeclaration("MyInterface" + getExtension(), "com.intellij.myInterfaceEP"); + } + + public void testMyClass() { + assertSingleEPDeclaration("MyClass" + getExtension(), "com.intellij.myClassEP"); + } + + public void testMyWithImplementsInterface() { + assertSingleEPDeclaration("MyWithImplementsInterface" + getExtension(), "com.intellij.myWithImplementsEP"); + } + + public void testMyBeanClassInterface() { + // Negative test - should NOT show gutter for beanClass only + myFixture.copyFileToProject("extensionPointDeclarationEPs.xml"); + + final GutterMark gutter = myFixture.findGutter("MyBeanClassInterface" + getExtension()); + assertNull("Gutter should not appear for beanClass-only EP", gutter); + } + + public void testMyMultipleEPsInterface() { + // Should show gutter when multiple EPs reference the same interface + VirtualFile pluginXmlFile = myFixture.copyFileToProject("extensionPointDeclarationEPs.xml"); + PsiFile pluginPsiFile = getPsiManager().findFile(pluginXmlFile); + assertNotNull(pluginPsiFile); + + final GutterMark gutter = myFixture.findGutter("MyMultipleEPsInterface" + getExtension()); + assertNotNull(gutter); + + // Should list both EPs in tooltip + DevKitGutterTargetsChecker.checkGutterTargets(gutter, + "    com.intellij.myMultipleEPs1
    com.intellij.myMultipleEPs2
", + DevkitCoreIcons.Gutter.Plugin, "extensionPoint", "extensionPoint"); } protected void assertSingleEPDeclaration(String filePath, String epFqn) {