void () { TextExtractor delegate = TextExtractor.EP.forLanguage(MarkdownLanguage.INSTANCE); var countingExtractor = new TextExtractor() { int count = 0; @Override protected @NotNull List<TextContent> buildTextContents(@NotNull PsiElement element, @NotNull Set<TextContent.TextDomain> allowedDomains) { if (element instanceof MarkdownParagraph) { count++; } return delegate.buildTextContents(element, allowedDomains); } }; TextExtractor.EP.addExplicitExtension(MarkdownLanguage.INSTANCE, countingExtractor); disposeOnTearDown(() -> TextExtractor.EP.removeExplicitExtension(MarkdownLanguage.INSTANCE, countingExtractor)); PsiFile file = PsiFileFactory.getInstance(getProject()).createFileFromText( "a.md", MarkdownFileType.INSTANCE, "[Before ![AltText](http://www.google.com.au/images/nav_logo7.png) after](http://google.com.au/)"); for (int i = 0; i <= file.getTextLength(); i++) { TextExtractor.findTextAt(file, i, TextContent.TextDomain.ALL); } // should be invoked once, but allow some repetitions in case GC kicks in assertTrue(String.valueOf(countingExtractor.count), countingExtractor.count < 3); }