/* * Copyright 2010-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jetbrains.kotlin.idea.navigation; import com.google.common.base.Function; import com.google.common.collect.Lists; import com.google.common.collect.Ordering; import com.intellij.codeInsight.navigation.GotoTargetHandler; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.EditorFactory; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.testFramework.UsefulTestCase; import com.intellij.testFramework.fixtures.CodeInsightTestUtil; import com.intellij.util.PathUtil; import com.intellij.util.containers.MultiMap; import junit.framework.TestCase; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.test.InTextDirectivesUtils; import org.jetbrains.kotlin.test.ReferenceUtils; import org.junit.Assert; import java.util.*; public final class NavigationTestUtils { private NavigationTestUtils() { } public static GotoTargetHandler.GotoData invokeGotoImplementations(Editor editor, PsiFile psiFile) { return CodeInsightTestUtil.gotoImplementation(editor, psiFile); } public static void assertGotoDataMatching(Editor editor, GotoTargetHandler.GotoData gotoData) { // Get expected references from the tested document List<String> expectedReferences = InTextDirectivesUtils.findListWithPrefixes(editor.getDocument().getText(), "// REF:"); for (int i = 0; i < expectedReferences.size(); i++) { String expectedText = expectedReferences.get(i); expectedText = expectedText.replace("\\n", "\n"); if (!expectedText.startsWith("<")) { expectedText = PathUtil.toSystemDependentName(expectedText).replace("//", "/"); } expectedReferences.set(i, expectedText); } Collections.sort(expectedReferences); if (gotoData != null) { // Transform given reference result to strings List<String> psiElements = Lists.transform(Arrays.asList(gotoData.targets), new Function<PsiElement, String>() { @Override public String apply(@Nullable PsiElement element) { Assert.assertNotNull(element); return ReferenceUtils.renderAsGotoImplementation(element); } }); // Compare UsefulTestCase.assertOrderedEquals(Ordering.natural().sortedCopy(psiElements), expectedReferences); } else { UsefulTestCase.assertOrderedEquals(Collections.emptyList(), expectedReferences); } } public static String getNavigateElementsText(Project project, Collection<? extends PsiElement> navigableElements) { MultiMap<PsiFile, Pair<Integer, Integer>> filesToNumbersAndOffsets = new MultiMap<PsiFile, Pair<Integer, Integer>>(); int refNumber = 1; for (PsiElement navigationElement : navigableElements) { Pair<Integer, Integer> numberAndOffset = new Pair<Integer, Integer>(refNumber++, navigationElement.getTextOffset()); filesToNumbersAndOffsets.putValue(navigationElement.getContainingFile(), numberAndOffset); } if (filesToNumbersAndOffsets.isEmpty()) { return "<no references>"; } List<PsiFile> files = new ArrayList<PsiFile>(filesToNumbersAndOffsets.keySet()); Collections.sort(files, new Comparator<PsiFile>() { @Override public int compare(@NotNull PsiFile f1, @NotNull PsiFile f2) { return f1.getName().compareTo(f2.getName()); } }); StringBuilder result = new StringBuilder(); for (PsiFile file : files) { List<Pair<Integer, Integer>> numbersAndOffsets = new ArrayList<Pair<Integer, Integer>>(filesToNumbersAndOffsets.get(file)); Collections.sort(numbersAndOffsets, Collections.reverseOrder(new Comparator<Pair<Integer, Integer>>() { @Override public int compare(Pair<Integer, Integer> t1, Pair<Integer, Integer> t2) { int offsets = t1.second.compareTo(t2.second); return offsets == 0 ? t1.first.compareTo(t2.first) : offsets; } })); Document document = PsiDocumentManager.getInstance(project).getDocument(file); TestCase.assertNotNull(document); StringBuilder resultForFile = new StringBuilder(document.getText()); for (Pair<Integer, Integer> numberOffset : numbersAndOffsets) { resultForFile.insert(numberOffset.second, String.format("<%d>", numberOffset.first)); } int minLine = Integer.MAX_VALUE; int maxLine = Integer.MIN_VALUE; for (Pair<Integer, Integer> numberOffset : numbersAndOffsets) { int lineNumber = document.getLineNumber(numberOffset.second); minLine = Math.min(minLine, lineNumber); maxLine = Math.max(maxLine, lineNumber); } Document annotated = EditorFactory.getInstance().createDocument(resultForFile); String filePart = annotated.getText().substring(annotated.getLineStartOffset(minLine), annotated.getLineEndOffset(maxLine)); result.append(" ").append(file.getName()).append("\n"); result.append(filePart).append("\n"); } return result.toString(); } }