@Override protected void collectNavigationMarkers( @NotNull PsiElement element, Collection<? super RelatedItemLineMarkerInfo> result) { final PsiElement pythonStub = getPythonStub(element); if (pythonStub != null) { final List<GotoRelatedItem> relatedItems = GotoRelatedItem.createItems(Collections.singletonList(pythonStub)); result.add( new RelatedItemLineMarkerInfo<PsiElement>( element, element.getTextRange(), ICON, Pass.LINE_MARKERS, element1 -> "Has stub item in " + pythonStub.getContainingFile().getName(), new GutterIconNavigationHandler<PsiElement>() { @Override public void navigate(MouseEvent e, PsiElement elt) { final PsiElement pythonStub = getPythonStub(elt); if (pythonStub != null) { PsiNavigateUtil.navigate(pythonStub); } } }, GutterIconRenderer.Alignment.RIGHT, relatedItems)); } }
public class ExtensionPointDeclarationRelatedItemLineMarkerProvider extends DevkitRelatedLineMarkerProviderBase { private static final NotNullFunction<ExtensionPointCandidate, Collection<? extends PsiElement>> CONVERTER = candidate -> Collections.singleton(candidate.pointer.getElement()); private static final NotNullFunction< ExtensionPointCandidate, Collection<? extends GotoRelatedItem>> RELATED_ITEM_PROVIDER = candidate -> GotoRelatedItem.createItems( Collections.singleton(candidate.pointer.getElement()), "DevKit"); @Override protected void collectNavigationMarkers( @NotNull PsiElement element, Collection<? super RelatedItemLineMarkerInfo> result) { if (element instanceof PsiField) { process((PsiField) element, result); } } private static void process( PsiField psiField, Collection<? super RelatedItemLineMarkerInfo> result) { if (!isExtensionPointNameDeclarationField(psiField)) return; final PsiClass epClass = resolveExtensionPointClass(psiField); if (epClass == null) return; final String epName = resolveEpName(psiField); if (epName == null) return; ExtensionPointLocator locator = new ExtensionPointLocator(epClass); List<ExtensionPointCandidate> targets = ContainerUtil.filter( locator.findDirectCandidates(), new Condition<ExtensionPointCandidate>() { @Override public boolean value(ExtensionPointCandidate candidate) { return epName.equals(candidate.epName); } }); final RelatedItemLineMarkerInfo<PsiElement> info = NavigationGutterIconBuilder.create(AllIcons.Nodes.Plugin, CONVERTER, RELATED_ITEM_PROVIDER) .setTargets(targets) .setPopupTitle("Choose Extension Point") .setTooltipText("Extension Point Declaration") .setAlignment(GutterIconRenderer.Alignment.RIGHT) .createLineMarkerInfo(psiField.getNameIdentifier()); result.add(info); } @Nullable private static PsiClass resolveExtensionPointClass(PsiField psiField) { final PsiType typeParameter = PsiUtil.substituteTypeParameter( psiField.getType(), ExtensionPointName.class.getName(), 0, false); return PsiUtil.resolveClassInClassTypeOnly(typeParameter); } private static String resolveEpName(PsiField psiField) { final PsiExpression initializer = psiField.getInitializer(); PsiExpressionList expressionList = null; if (initializer instanceof PsiMethodCallExpression) { expressionList = ((PsiMethodCallExpression) initializer).getArgumentList(); } else if (initializer instanceof PsiNewExpression) { expressionList = ((PsiNewExpression) initializer).getArgumentList(); } if (expressionList == null) return null; final PsiExpression[] expressions = expressionList.getExpressions(); if (expressions.length != 1) return null; final PsiExpression epNameExpression = expressions[0]; final PsiConstantEvaluationHelper helper = JavaPsiFacade.getInstance(psiField.getProject()).getConstantEvaluationHelper(); final Object o = helper.computeConstantExpression(epNameExpression); return o instanceof String ? (String) o : null; } private static boolean isExtensionPointNameDeclarationField(PsiField psiField) { // *do* allow non-public if (!psiField.hasModifierProperty(PsiModifier.FINAL) || !psiField.hasModifierProperty(PsiModifier.STATIC) || psiField.hasModifierProperty(PsiModifier.ABSTRACT)) { return false; } if (!psiField.hasInitializer()) { return false; } final PsiExpression initializer = psiField.getInitializer(); if (!(initializer instanceof PsiMethodCallExpression) && !(initializer instanceof PsiNewExpression)) { return false; } final PsiClass fieldClass = PsiTypesUtil.getPsiClass(psiField.getType()); if (fieldClass == null) { return false; } return ExtensionPointName.class.getName().equals(fieldClass.getQualifiedName()); } }