void (@NotNull PsiElement element, @NotNull PsiFile containingFile, @NotNull Set<? super PsiFile> visitedInjectedFiles, @NotNull PairConsumer<? super PsiElement, ? super LineMarkerInfo<?>> consumer) { InjectedLanguageManager manager = InjectedLanguageManager.getInstance(containingFile.getProject()); if (manager.isInjectedFragment(containingFile)) return; InjectedLanguageManager.getInstance(containingFile.getProject()).enumerateEx(element, containingFile, false, (injectedPsi, places) -> { if (!visitedInjectedFiles.add(injectedPsi)) return; // there may be several concatenated literals making the one injected file Project project = injectedPsi.getProject(); Document document = PsiDocumentManager.getInstance(project).getCachedDocument(injectedPsi); if (!(document instanceof DocumentWindow)) return; List<PsiElement> injElements = CollectHighlightsUtil.getElementsInRange(injectedPsi, 0, injectedPsi.getTextLength()); List<LineMarkerProvider> providers = getMarkerProviders(injectedPsi.getLanguage(), project); queryProviders(injElements, injectedPsi, providers, (injectedElement, injectedMarkerInfo) -> { GutterIconRenderer gutterRenderer = injectedMarkerInfo.createGutterRenderer(); TextRange injectedRange = new TextRange(injectedMarkerInfo.startOffset, injectedMarkerInfo.endOffset); List<TextRange> editables = manager.intersectWithAllEditableFragments(injectedPsi, injectedRange); for (TextRange editable : editables) { TextRange hostRange = manager.injectedToHost(injectedPsi, editable); Icon icon = gutterRenderer == null ? null : gutterRenderer.getIcon(); //noinspection unchecked GutterIconNavigationHandler<PsiElement> navigationHandler = (GutterIconNavigationHandler<PsiElement>)injectedMarkerInfo.getNavigationHandler(); LineMarkerInfo<PsiElement> converted = icon == null ? new LineMarkerInfo<>(injectedElement, hostRange) : new LineMarkerInfo<>(injectedElement, hostRange, icon, e -> injectedMarkerInfo.getLineMarkerTooltip(), navigationHandler, GutterIconRenderer.Alignment.RIGHT, () -> gutterRenderer.getAccessibleName()); consumer.consume(injectedElement, converted); } }); }); }