package fr.adrienbrault.idea.symfony2plugin.tests; import com.intellij.codeInsight.completion.CodeCompletionHandlerBase; import com.intellij.codeInsight.completion.CompletionProgressIndicator; import com.intellij.codeInsight.completion.CompletionType; import com.intellij.codeInsight.daemon.LineMarkerInfo; import com.intellij.codeInsight.daemon.LineMarkerProvider; import com.intellij.codeInsight.daemon.LineMarkerProviders; import com.intellij.codeInsight.daemon.RelatedItemLineMarkerInfo; import com.intellij.codeInsight.daemon.impl.AnnotationHolderImpl; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInsight.intention.IntentionManager; import com.intellij.codeInsight.lookup.Lookup; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementPresentation; import com.intellij.codeInsight.navigation.actions.GotoDeclarationHandler; import com.intellij.codeInspection.*; import com.intellij.lang.LanguageAnnotators; import com.intellij.lang.annotation.Annotation; import com.intellij.lang.annotation.AnnotationSession; import com.intellij.lang.annotation.Annotator; import com.intellij.navigation.GotoRelatedItem; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.LogicalPosition; import com.intellij.openapi.editor.event.CaretEvent; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.LanguageFileType; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.patterns.ElementPattern; import com.intellij.patterns.PlatformPatterns; import com.intellij.psi.*; import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; import com.intellij.util.Processor; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.indexing.FileBasedIndex; import com.intellij.util.indexing.ID; import com.intellij.util.ui.UIUtil; import com.jetbrains.php.lang.psi.elements.Function; import com.jetbrains.php.lang.psi.elements.Method; import com.jetbrains.php.lang.psi.elements.PhpReference; import fr.adrienbrault.idea.symfony2plugin.Settings; import fr.adrienbrault.idea.symfony2plugin.codeInsight.caret.overlay.CaretTextOverlayArguments; import fr.adrienbrault.idea.symfony2plugin.codeInsight.caret.overlay.CaretTextOverlayElement; import fr.adrienbrault.idea.symfony2plugin.codeInsight.caret.overlay.util.CaretTextOverlayUtil; import org.jetbrains.annotations.NotNull; import java.io.File; import java.util.*; public abstract class SymfonyLightCodeInsightFixtureTestCase extends LightCodeInsightFixtureTestCase { @Override public void setUp() throws Exception { super.setUp(); Settings.getInstance(myFixture.getProject()).pluginEnabled = true; } public void assertCompletionContains(LanguageFileType languageFileType, String configureByText, String... lookupStrings) { myFixture.configureByText(languageFileType, configureByText); myFixture.completeBasic(); checkContainsCompletion(lookupStrings); } public void assertAtTextCompletionContains(String findByText, String... lookupStrings) { final PsiElement element = myFixture.findElementByText(findByText, PsiElement.class); assert element != null : "No element found by text: " + findByText; myFixture.getEditor().getCaretModel().moveToOffset(element.getTextOffset() + 1); myFixture.completeBasic(); checkContainsCompletion(lookupStrings); } public void assertCompletionNotContains(String text, String configureByText, String... lookupStrings) { myFixture.configureByText(text, configureByText); myFixture.completeBasic(); assertFalse(myFixture.getLookupElementStrings().containsAll(Arrays.asList(lookupStrings))); } public void assertCompletionNotContains(LanguageFileType languageFileType, String configureByText, String... lookupStrings) { myFixture.configureByText(languageFileType, configureByText); myFixture.completeBasic(); assertFalse(myFixture.getLookupElementStrings().containsAll(Arrays.asList(lookupStrings))); } public void assertCompletionContains(String filename, String configureByText, String... lookupStrings) { myFixture.configureByText(filename, configureByText); myFixture.completeBasic(); completionContainsAssert(lookupStrings); } private void completionContainsAssert(String[] lookupStrings) { if(lookupStrings.length == 0) { fail("No lookup element given"); } List<String> lookupElements = myFixture.getLookupElementStrings(); if(lookupElements == null || lookupElements.size() == 0) { fail(String.format("failed that empty completion contains %s", Arrays.toString(lookupStrings))); } for (String s : Arrays.asList(lookupStrings)) { if(!lookupElements.contains(s)) { fail(String.format("failed that completion contains %s in %s", s, lookupElements.toString())); } } } public void assertNavigationContains(LanguageFileType languageFileType, String configureByText, String targetShortcut) { myFixture.configureByText(languageFileType, configureByText); PsiElement psiElement = myFixture.getFile().findElementAt(myFixture.getCaretOffset()); assertNavigationContains(psiElement, targetShortcut); } public void assertNavigationContains(PsiElement psiElement, String targetShortcut) { if(!targetShortcut.startsWith("\\")) { targetShortcut = "\\" + targetShortcut; } Set<String> classTargets = new HashSet<String>(); for (GotoDeclarationHandler gotoDeclarationHandler : Extensions.getExtensions(GotoDeclarationHandler.EP_NAME)) { PsiElement[] gotoDeclarationTargets = gotoDeclarationHandler.getGotoDeclarationTargets(psiElement, 0, myFixture.getEditor()); if(gotoDeclarationTargets != null && gotoDeclarationTargets.length > 0) { for (PsiElement gotoDeclarationTarget : gotoDeclarationTargets) { if(gotoDeclarationTarget instanceof Method) { String meName = ((Method) gotoDeclarationTarget).getName(); String clName = ((Method) gotoDeclarationTarget).getContainingClass().getPresentableFQN(); if(!clName.startsWith("\\")) { clName = "\\" + clName; } classTargets.add(clName + "::" + meName); } else if(gotoDeclarationTarget instanceof Function) { classTargets.add("\\" + ((Function) gotoDeclarationTarget).getName()); } } } } if(!classTargets.contains(targetShortcut)) { fail(String.format("failed that PsiElement (%s) navigate to %s on %s", psiElement.toString(), targetShortcut, classTargets.toString())); } } public void assertNavigationMatchWithParent(LanguageFileType languageFileType, String configureByText, IElementType iElementType) { assertNavigationMatch(languageFileType, configureByText, PlatformPatterns.psiElement().withParent(PlatformPatterns.psiElement(iElementType))); } public void assertNavigationMatch(String filename, String configureByText, ElementPattern<?> pattern) { myFixture.configureByText(filename, configureByText); assertNavigationMatch(pattern); } public void assertNavigationMatch(LanguageFileType languageFileType, String configureByText, ElementPattern<?> pattern) { myFixture.configureByText(languageFileType, configureByText); assertNavigationMatch(pattern); } public void assertNavigationMatch(LanguageFileType languageFileType, String configureByText) { myFixture.configureByText(languageFileType, configureByText); assertNavigationMatch(PlatformPatterns.psiElement()); } public void assertNavigationMatch(String filename, String configureByText) { myFixture.configureByText(filename, configureByText); assertNavigationMatch(PlatformPatterns.psiElement()); } public void assertNavigationIsEmpty(LanguageFileType languageFileType, String configureByText) { myFixture.configureByText(languageFileType, configureByText); assertNavigationIsEmpty(); } public void assertNavigationIsEmpty(String content, String configureByText) { myFixture.configureByText(content, configureByText); assertNavigationIsEmpty(); } private void assertNavigationIsEmpty() { PsiElement psiElement = myFixture.getFile().findElementAt(myFixture.getCaretOffset()); for (GotoDeclarationHandler gotoDeclarationHandler : Extensions.getExtensions(GotoDeclarationHandler.EP_NAME)) { PsiElement[] gotoDeclarationTargets = gotoDeclarationHandler.getGotoDeclarationTargets(psiElement, 0, myFixture.getEditor()); if(gotoDeclarationTargets != null && gotoDeclarationTargets.length > 0) { fail(String.format("failed that PsiElement (%s) navigate is empty; found target in '%s'", psiElement.toString(), gotoDeclarationHandler.getClass())); } } } private void assertNavigationMatch(ElementPattern<?> pattern) { PsiElement psiElement = myFixture.getFile().findElementAt(myFixture.getCaretOffset()); Set<String> targetStrings = new HashSet<String>(); for (GotoDeclarationHandler gotoDeclarationHandler : Extensions.getExtensions(GotoDeclarationHandler.EP_NAME)) { PsiElement[] gotoDeclarationTargets = gotoDeclarationHandler.getGotoDeclarationTargets(psiElement, 0, myFixture.getEditor()); if(gotoDeclarationTargets == null || gotoDeclarationTargets.length == 0) { continue; } for (PsiElement gotoDeclarationTarget : gotoDeclarationTargets) { targetStrings.add(gotoDeclarationTarget.toString()); if(pattern.accepts(gotoDeclarationTarget)) { return; } } } fail(String.format("failed that PsiElement (%s) navigate matches one of %s", psiElement.toString(), targetStrings.toString())); } public void assertNavigationContainsFile(LanguageFileType languageFileType, String configureByText, String targetShortcut) { myFixture.configureByText(languageFileType, configureByText); PsiElement psiElement = myFixture.getFile().findElementAt(myFixture.getCaretOffset()); Set<String> targets = new HashSet<String>(); for (GotoDeclarationHandler gotoDeclarationHandler : Extensions.getExtensions(GotoDeclarationHandler.EP_NAME)) { PsiElement[] gotoDeclarationTargets = gotoDeclarationHandler.getGotoDeclarationTargets(psiElement, 0, myFixture.getEditor()); if (gotoDeclarationTargets != null && gotoDeclarationTargets.length > 0) { for (PsiElement gotoDeclarationTarget : gotoDeclarationTargets) { if(gotoDeclarationTarget instanceof PsiFile) { targets.add(((PsiFile) gotoDeclarationTarget).getVirtualFile().getUrl()); } } } } // its possible to have memory fields, // so simple check for ending conditions // temp:///src/interchange.en.xlf for (String target : targets) { if(target.endsWith(targetShortcut)) { return; } } fail(String.format("failed that PsiElement (%s) navigate to file %s", psiElement.toString(), targetShortcut)); } public void assertCompletionLookupContainsPresentableItem(LanguageFileType languageFileType, String configureByText, LookupElementPresentationAssert.Assert presentationAssert) { myFixture.configureByText(languageFileType, configureByText); myFixture.completeBasic(); LookupElement[] lookupElements = myFixture.getLookupElements(); if(lookupElements == null) { fail("failed to find lookup presentable on empty collection"); } for (LookupElement lookupElement : lookupElements) { LookupElementPresentation presentation = new LookupElementPresentation(); lookupElement.renderElement(presentation); if(presentationAssert.match(presentation)) { return; } } fail("failed to find lookup presentable"); } public void assertCompletionLookupTailEquals(LanguageFileType languageFileType, String configureByText, String lookupString, String tailText) { myFixture.configureByText(languageFileType, configureByText); myFixture.completeBasic(); for (LookupElement lookupElement : myFixture.getLookupElements()) { if(!lookupElement.getLookupString().equals(lookupString)) { continue; } LookupElementPresentation presentation = new LookupElementPresentation(); lookupElement.renderElement(presentation); if(presentation.getTailText() == null) { fail(String.format("failed to check '%s'", lookupString)); } if(!presentation.getTailText().equals(tailText)) { fail(String.format("failed that on '%s' '%s' is equal '%s'", lookupString, tailText, presentation.getTailText())); } return; } fail(String.format("failed to check '%s' because it's unknown", lookupString)); } public void assertPhpReferenceResolveTo(LanguageFileType languageFileType, String configureByText, ElementPattern<?> pattern) { myFixture.configureByText(languageFileType, configureByText); PsiElement psiElement = myFixture.getFile().findElementAt(myFixture.getCaretOffset()); psiElement = PsiTreeUtil.getParentOfType(psiElement, PhpReference.class); if (psiElement == null) { fail("Element is not PhpReference."); } PsiElement resolve = ((PhpReference) psiElement).resolve(); if(!pattern.accepts(resolve)) { fail(String.format("failed pattern matches element of '%s'", resolve == null ? "null" : resolve.toString())); } assertTrue(pattern.accepts(resolve)); } public void assertPhpReferenceNotResolveTo(LanguageFileType languageFileType, String configureByText, ElementPattern<?> pattern) { myFixture.configureByText(languageFileType, configureByText); PsiElement psiElement = myFixture.getFile().findElementAt(myFixture.getCaretOffset()); psiElement = PsiTreeUtil.getParentOfType(psiElement, PhpReference.class); if (psiElement == null) { fail("Element is not PhpReference."); } assertFalse(pattern.accepts(((PhpReference) psiElement).resolve())); } public void assertPhpReferenceSignatureEquals(LanguageFileType languageFileType, String configureByText, String typeSignature) { PsiElement psiElement = assertGetPhpReference(languageFileType, configureByText); assertEquals(typeSignature, ((PhpReference) psiElement).getSignature()); } public void assertPhpReferenceSignatureContains(LanguageFileType languageFileType, String configureByText, String typeSignature) { PsiElement psiElement = assertGetPhpReference(languageFileType, configureByText); assertTrue(((PhpReference) psiElement).getSignature().contains(typeSignature)); } @NotNull private PsiElement assertGetPhpReference(LanguageFileType languageFileType, String configureByText) { myFixture.configureByText(languageFileType, configureByText); PsiElement psiElement = myFixture.getFile().findElementAt(myFixture.getCaretOffset()); psiElement = PsiTreeUtil.getParentOfType(psiElement, PhpReference.class); if (psiElement == null) { fail("Element is not PhpReference."); } return psiElement; } public void assertCompletionResultEquals(String filename, String complete, String result) { myFixture.configureByText(filename, complete); myFixture.completeBasic(); myFixture.checkResult(result); } public void assertCompletionResultEquals(@NotNull FileType fileType, @NotNull String contents, @NotNull String result, @NotNull LookupElementInsert.Assert assertion) { myFixture.configureByText(fileType, contents); UIUtil.invokeAndWaitIfNeeded(new MyLookupElementConditionalInsertRunnable(assertion)); myFixture.checkResult(result); } public void assertCompletionResultEquals(LanguageFileType languageFileType, String complete, String result) { myFixture.configureByText(languageFileType, complete); myFixture.completeBasic(); myFixture.checkResult(result); } public void assertCheckHighlighting(String filename, String result) { myFixture.configureByText(filename, result); myFixture.checkHighlighting(); } public void assertIndexContains(@NotNull ID<String, ?> id, @NotNull String... keys) { assertIndex(id, false, keys); } public void assertIndexNotContains(@NotNull ID<String, ?> id, @NotNull String... keys) { assertIndex(id, true, keys); } public void assertIndex(@NotNull ID<String, ?> id, boolean notCondition, @NotNull String... keys) { for (String key : keys) { final Collection<VirtualFile> virtualFiles = new ArrayList<VirtualFile>(); FileBasedIndex.getInstance().getFilesWithKey(id, new HashSet<String>(Arrays.asList(key)), new Processor<VirtualFile>() { @Override public boolean process(VirtualFile virtualFile) { virtualFiles.add(virtualFile); return true; } }, GlobalSearchScope.allScope(getProject())); if(notCondition && virtualFiles.size() > 0) { fail(String.format("Fail that ID '%s' not contains '%s'", id.toString(), key)); } else if(!notCondition && virtualFiles.size() == 0) { fail(String.format("Fail that ID '%s' contains '%s'", id.toString(), key)); } } } public void assertIndexContainsKeyWithValue(@NotNull ID<String, String> id, @NotNull String key, @NotNull String value) { assertContainsElements(FileBasedIndex.getInstance().getValues(id, key, GlobalSearchScope.allScope(getProject())), value); } public <T> void assertIndexContainsKeyWithValue(@NotNull ID<String, T> id, @NotNull String key, @NotNull IndexValue.Assert<T> tAssert) { List<T> values = FileBasedIndex.getInstance().getValues(id, key, GlobalSearchScope.allScope(getProject())); for (T t : values) { if(tAssert.match(t)) { return; } } fail(String.format("Fail that Key '%s' matches on of '%s' values", key, values.size())); } public void assertLocalInspectionContains(String filename, String content, String contains) { Set<String> matches = new HashSet<String>(); Pair<List<ProblemDescriptor>, Integer> localInspectionsAtCaret = getLocalInspectionsAtCaret(filename, content); for (ProblemDescriptor result : localInspectionsAtCaret.getFirst()) { TextRange textRange = result.getPsiElement().getTextRange(); if (textRange.contains(localInspectionsAtCaret.getSecond()) && result.toString().equals(contains)) { return; } matches.add(result.toString()); } fail(String.format("Fail matches '%s' with one of %s", contains, matches)); } public void assertAnnotationContains(String filename, String content, String contains) { List<String> matches = new ArrayList<String>(); for (Annotation annotation : getAnnotationsAtCaret(filename, content)) { matches.add(annotation.toString()); if(annotation.getMessage().contains(contains)) { return; } } fail(String.format("Fail matches '%s' with one of %s", contains, matches)); } @NotNull private AnnotationHolderImpl getAnnotationsAtCaret(String filename, String content) { PsiFile psiFile = myFixture.configureByText(filename, content); PsiElement psiElement = myFixture.getFile().findElementAt(myFixture.getCaretOffset()); AnnotationHolderImpl annotations = new AnnotationHolderImpl(new AnnotationSession(psiFile)); for (Annotator annotator : LanguageAnnotators.INSTANCE.allForLanguage(psiFile.getLanguage())) { annotator.annotate(psiElement, annotations); } return annotations; } public void assertAnnotationNotContains(String filename, String content, String contains) { for (Annotation annotation : getAnnotationsAtCaret(filename, content)) { if(annotation.getMessage().contains(contains)) { fail(String.format("Fail not matching '%s' with '%s'", contains, annotation)); } } } public void assertIntentionIsAvailable(LanguageFileType languageFileType, String configureByText, String intentionText) { myFixture.configureByText(languageFileType, configureByText); PsiElement psiElement = myFixture.getFile().findElementAt(myFixture.getCaretOffset()); Set<String> items = new HashSet<>(); for (IntentionAction intentionAction : IntentionManager.getInstance().getIntentionActions()) { if(!intentionAction.isAvailable(getProject(), getEditor(), psiElement.getContainingFile())) { continue; } String text = intentionAction.getText(); items.add(text); if(!text.equals(intentionText)) { continue; } return; } fail(String.format("Fail intention action '%s' is available in element '%s' with '%s'", intentionText, psiElement.getText(), items)); } public void assertLocalInspectionNotContains(String filename, String content, String contains) { Pair<List<ProblemDescriptor>, Integer> localInspectionsAtCaret = getLocalInspectionsAtCaret(filename, content); for (ProblemDescriptor result : localInspectionsAtCaret.getFirst()) { TextRange textRange = result.getPsiElement().getTextRange(); if (textRange.contains(localInspectionsAtCaret.getSecond()) && result.toString().contains(contains)) { fail(String.format("Fail inspection not contains '%s'", contains)); } } } private Pair<List<ProblemDescriptor>, Integer> getLocalInspectionsAtCaret(String filename, String content) { PsiElement psiFile = myFixture.configureByText(filename, content); int caretOffset = myFixture.getCaretOffset(); if(caretOffset <= 0) { fail("Please provide <caret> tag"); } ProblemsHolder problemsHolder = new ProblemsHolder(InspectionManager.getInstance(getProject()), psiFile.getContainingFile(), false); for (LocalInspectionEP localInspectionEP : LocalInspectionEP.LOCAL_INSPECTION.getExtensions()) { Object object = localInspectionEP.getInstance(); if(!(object instanceof LocalInspectionTool)) { continue; } final PsiElementVisitor psiElementVisitor = ((LocalInspectionTool) object).buildVisitor(problemsHolder, false); psiFile.acceptChildren(new PsiRecursiveElementVisitor() { @Override public void visitElement(PsiElement element) { psiElementVisitor.visitElement(element); super.visitElement(element); } }); psiElementVisitor.visitFile(psiFile.getContainingFile());; } return new Pair<List<ProblemDescriptor>, Integer>(problemsHolder.getResults(), caretOffset); } protected void assertLocalInspectionIsEmpty(String filename, String content) { Pair<List<ProblemDescriptor>, Integer> localInspectionsAtCaret = getLocalInspectionsAtCaret(filename, content); for (ProblemDescriptor result : localInspectionsAtCaret.getFirst()) { TextRange textRange = result.getPsiElement().getTextRange(); if (textRange.contains(localInspectionsAtCaret.getSecond())) { fail("Fail that matches is empty"); } } } protected void createDummyFiles(String... files) throws Exception { for (String file : files) { String path = myFixture.getProject().getBaseDir().getPath() + "/" + file; File f = new File(path); f.getParentFile().mkdirs(); f.createNewFile(); } } private void checkContainsCompletion(String[] lookupStrings) { completionContainsAssert(lookupStrings); } public void assertLineMarker(@NotNull PsiElement psiElement, @NotNull LineMarker.Assert assertMatch) { final List<PsiElement> elements = collectPsiElementsRecursive(psiElement); for (LineMarkerProvider lineMarkerProvider : LineMarkerProviders.INSTANCE.allForLanguage(psiElement.getLanguage())) { Collection<LineMarkerInfo> lineMarkerInfos = new ArrayList<LineMarkerInfo>(); lineMarkerProvider.collectSlowLineMarkers(elements, lineMarkerInfos); if(lineMarkerInfos.size() == 0) { continue; } for (LineMarkerInfo lineMarkerInfo : lineMarkerInfos) { if(assertMatch.match(lineMarkerInfo)) { return; } } } fail(String.format("Fail that '%s' matches on of '%s' PsiElements", assertMatch.getClass(), elements.size())); } public void assertLineMarkerIsEmpty(@NotNull PsiElement psiElement) { final List<PsiElement> elements = collectPsiElementsRecursive(psiElement); for (LineMarkerProvider lineMarkerProvider : LineMarkerProviders.INSTANCE.allForLanguage(psiElement.getLanguage())) { Collection<LineMarkerInfo> lineMarkerInfos = new ArrayList<LineMarkerInfo>(); lineMarkerProvider.collectSlowLineMarkers(elements, lineMarkerInfos); if(lineMarkerInfos.size() > 0) { fail(String.format("Fail that line marker is empty because it matches '%s'", lineMarkerProvider.getClass())); } } } public void assertReferenceMatchOnParent(@NotNull FileType fileType, @NotNull String contents, @NotNull ElementPattern<?> pattern) { myFixture.configureByText(fileType, contents); PsiElement psiElement = myFixture.getFile().findElementAt(myFixture.getCaretOffset()); if(psiElement == null) { fail("Fail to find element in caret"); } PsiElement parent = psiElement.getParent(); if(parent == null) { fail("Fail to find parent element in caret"); } assertReferences(pattern, parent); } public void assertReferenceMatch(@NotNull FileType fileType, @NotNull String contents, @NotNull ElementPattern<?> pattern) { myFixture.configureByText(fileType, contents); PsiElement psiElement = myFixture.getFile().findElementAt(myFixture.getCaretOffset()); if(psiElement == null) { fail("Fail to find element in caret"); } assertReferences(pattern, psiElement); } private void assertReferences(@NotNull ElementPattern<?> pattern, PsiElement psiElement) { for (PsiReference reference : psiElement.getReferences()) { // single resolve; should also match first multi by design PsiElement element = reference.resolve(); if (pattern.accepts(element)) { return; } // multiResolve support if(element instanceof PsiPolyVariantReference) { for (ResolveResult resolveResult : ((PsiPolyVariantReference) element).multiResolve(true)) { if (pattern.accepts(resolveResult.getElement())) { return; } } } } fail(String.format("Fail that '%s' match given pattern", psiElement.toString())); } @NotNull private List<PsiElement> collectPsiElementsRecursive(@NotNull PsiElement psiElement) { final List<PsiElement> elements = new ArrayList<PsiElement>(); elements.add(psiElement.getContainingFile()); psiElement.acceptChildren(new PsiRecursiveElementVisitor() { @Override public void visitElement(PsiElement element) { elements.add(element); super.visitElement(element); } }); return elements; } @NotNull protected PsiElement findElementAt(@NotNull FileType fileType, @NotNull String content) { myFixture.configureByText(fileType, content); PsiElement psiElement = myFixture.getFile().findElementAt(myFixture.getCaretOffset()); if(psiElement == null) { fail("No element at caret found"); } return psiElement; } public void assertCaretTextOverlay(LanguageFileType languageFileType, String configureByText, CaretTextOverlay.Assert assertMatch) { myFixture.configureByText(languageFileType, configureByText); PsiElement psiElement = myFixture.getFile().findElementAt(myFixture.getCaretOffset()); CaretTextOverlayArguments args = new CaretTextOverlayArguments( new CaretEvent(getEditor(), new LogicalPosition(0, 0), new LogicalPosition(0, 0)), psiElement.getContainingFile(), psiElement ); for (fr.adrienbrault.idea.symfony2plugin.codeInsight.caret.overlay.CaretTextOverlay caretTextOverlay : CaretTextOverlayUtil.getExtensions()) { CaretTextOverlayElement overlay = caretTextOverlay.getOverlay(args); if(overlay != null && assertMatch.match(overlay)) { return; } } fail(String.format("Fail that CaretTextOverlay '%s' matches on of '%s' PsiElements", assertMatch.getClass(), psiElement.getText())); } public void assertCaretTextOverlayEmpty(LanguageFileType languageFileType, String configureByText) { myFixture.configureByText(languageFileType, configureByText); PsiElement psiElement = myFixture.getFile().findElementAt(myFixture.getCaretOffset()); CaretTextOverlayArguments args = new CaretTextOverlayArguments( new CaretEvent(getEditor(), new LogicalPosition(0, 0), new LogicalPosition(0, 0)), psiElement.getContainingFile(), psiElement ); for (fr.adrienbrault.idea.symfony2plugin.codeInsight.caret.overlay.CaretTextOverlay caretTextOverlay : CaretTextOverlayUtil.getExtensions()) { CaretTextOverlayElement overlay = caretTextOverlay.getOverlay(args); if(overlay != null) { fail(String.format("Fail that CaretTextOverlay is empty matching '%s'", overlay.getClass())); } } } public static class IndexValue { public interface Assert<T> { boolean match(@NotNull T value); } } public static class LineMarker { public interface Assert { boolean match(@NotNull LineMarkerInfo markerInfo); } public static class ToolTipEqualsAssert implements Assert { @NotNull private final String toolTip; public ToolTipEqualsAssert(@NotNull String toolTip) { this.toolTip = toolTip; } @Override public boolean match(@NotNull LineMarkerInfo markerInfo) { return markerInfo.getLineMarkerTooltip() != null && markerInfo.getLineMarkerTooltip().equals(toolTip); } } public static class TargetAcceptsPattern implements Assert { @NotNull private final String toolTip; @NotNull private final ElementPattern<? extends PsiElement> pattern; public TargetAcceptsPattern(@NotNull String toolTip, @NotNull ElementPattern<? extends PsiElement> pattern) { this.toolTip = toolTip; this.pattern = pattern; } @Override public boolean match(@NotNull LineMarkerInfo markerInfo) { if(markerInfo.getLineMarkerTooltip() == null || !markerInfo.getLineMarkerTooltip().equals(toolTip)) { return false; } if(!(markerInfo instanceof RelatedItemLineMarkerInfo)) { return false; } for (Object o : ((RelatedItemLineMarkerInfo) markerInfo).createGotoRelatedItems()) { if(o instanceof GotoRelatedItem && this.pattern.accepts(((GotoRelatedItem) o).getElement())) { return true; } } return false; } } } public static class CaretTextOverlay { public interface Assert { boolean match(@NotNull CaretTextOverlayElement caretTextOverlay); } public static class TextEqualsAssert implements Assert { @NotNull private final String text; public TextEqualsAssert(@NotNull String text) { this.text = text; } @Override public boolean match(@NotNull CaretTextOverlayElement caretTextOverlay) { return this.text.equals(caretTextOverlay.getText()); } } } public static class LookupElementInsert { public interface Assert { boolean match(@NotNull LookupElement lookupElement); } public static class Icon implements Assert { @NotNull private final javax.swing.Icon icon; public Icon(@NotNull javax.swing.Icon icon) { this.icon = icon; } @Override public boolean match(@NotNull LookupElement lookupElement) { LookupElementPresentation presentation = new LookupElementPresentation(); lookupElement.renderElement(presentation); return presentation.getIcon() == this.icon; } } } public static class LookupElementPresentationAssert { public interface Assert { boolean match(@NotNull LookupElementPresentation lookupElement); } } private class MyLookupElementConditionalInsertRunnable implements Runnable { @NotNull private final LookupElementInsert.Assert insert; public MyLookupElementConditionalInsertRunnable(@NotNull LookupElementInsert.Assert insert) { this.insert = insert; } @Override public void run() { CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() { @Override public void run() { final CodeCompletionHandlerBase handler = new CodeCompletionHandlerBase(CompletionType.BASIC) { @Override protected void completionFinished(final CompletionProgressIndicator indicator, boolean hasModifiers) { // find our lookup element final LookupElement lookupElement = ContainerUtil.find(indicator.getLookup().getItems(), new Condition<LookupElement>() { @Override public boolean value(LookupElement lookupElement) { return insert.match(lookupElement); } }); if(lookupElement == null) { fail("No matching lookup element found"); } // overwrite behavior and force completion + insertHandler CommandProcessor.getInstance().executeCommand(indicator.getProject(), new Runnable() { @Override public void run() { indicator.setMergeCommand(); indicator.getLookup().finishLookup(Lookup.AUTO_INSERT_SELECT_CHAR, lookupElement); } }, "Autocompletion", null); } }; Editor editor = InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(getEditor(), getFile()); handler.invokeCompletion(getProject(), editor); PsiDocumentManager.getInstance(getProject()).commitAllDocuments(); } }, null, null); } } }