Rewrite KotlinHierarchyViewTestBase with light fixture tests

This commit is contained in:
Nikolay Krasko
2018-12-03 14:49:40 +03:00
parent 5055308064
commit 9cc88c13f5
4 changed files with 57 additions and 307 deletions
@@ -16,23 +16,36 @@
package org.jetbrains.kotlin.idea; package org.jetbrains.kotlin.idea;
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess; import com.intellij.ide.hierarchy.HierarchyTreeStructure;
import com.intellij.testFramework.codeInsight.hierarchy.HierarchyViewTestBase; import com.intellij.openapi.util.Computable;
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil; import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.kotlin.test.KotlinTestUtils; import com.intellij.testFramework.codeInsight.hierarchy.HierarchyViewTestFixture;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase;
public abstract class KotlinHierarchyViewTestBase extends HierarchyViewTestBase { import java.io.File;
@Override import java.io.IOException;
protected void setUp() throws Exception {
VfsRootAccess.allowRootAccess(KotlinTestUtils.getHomeDirectory()); public abstract class KotlinHierarchyViewTestBase extends KotlinLightCodeInsightFixtureTestCase {
super.setUp(); private final HierarchyViewTestFixture hierarchyFixture = new HierarchyViewTestFixture();
ConfigLibraryUtil.INSTANCE.configureKotlinRuntime(myModule);
protected void doHierarchyTest(
@NotNull Computable<? extends HierarchyTreeStructure> treeStructureComputable,
@NotNull String... fileNames
) throws Exception {
configure(fileNames);
String expectedStructure = loadExpectedStructure();
hierarchyFixture.doHierarchyTest(treeStructureComputable.compute(), expectedStructure);
} }
@Override private void configure(@NotNull String[] fileNames) {
protected void tearDown() throws Exception { myFixture.configureByFiles(fileNames);
ConfigLibraryUtil.INSTANCE.unConfigureKotlinRuntime(myModule); }
super.tearDown();
VfsRootAccess.disallowRootAccess(KotlinTestUtils.getHomeDirectory()); @NotNull
private String loadExpectedStructure() throws IOException {
String verificationFilePath = getTestDataPath() + "/" + getTestName(false) + "_verification.xml";
return FileUtil.loadFile(new File(verificationFilePath));
} }
} }
@@ -27,12 +27,12 @@ import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.impl.text.TextEditorPsiDataProvider; import com.intellij.openapi.fileEditor.impl.text.TextEditorPsiDataProvider;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.FileUtil;
import com.intellij.psi.*; import com.intellij.psi.*;
import com.intellij.refactoring.util.CommonRefactoringUtil.RefactoringErrorHintException; import com.intellij.refactoring.util.CommonRefactoringUtil.RefactoringErrorHintException;
import com.intellij.rt.execution.junit.ComparisonDetailsExtractor; import com.intellij.rt.execution.junit.ComparisonDetailsExtractor;
import com.intellij.testFramework.LightProjectDescriptor;
import com.intellij.testFramework.MapDataContext; import com.intellij.testFramework.MapDataContext;
import com.intellij.util.ArrayUtil; import com.intellij.util.ArrayUtil;
import com.intellij.util.Processor; import com.intellij.util.Processor;
@@ -42,7 +42,7 @@ import org.jetbrains.kotlin.idea.KotlinHierarchyViewTestBase;
import org.jetbrains.kotlin.idea.hierarchy.calls.KotlinCalleeTreeStructure; import org.jetbrains.kotlin.idea.hierarchy.calls.KotlinCalleeTreeStructure;
import org.jetbrains.kotlin.idea.hierarchy.calls.KotlinCallerTreeStructure; import org.jetbrains.kotlin.idea.hierarchy.calls.KotlinCallerTreeStructure;
import org.jetbrains.kotlin.idea.hierarchy.overrides.KotlinOverrideTreeStructure; import org.jetbrains.kotlin.idea.hierarchy.overrides.KotlinOverrideTreeStructure;
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase; import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor;
import org.jetbrains.kotlin.psi.KtCallableDeclaration; import org.jetbrains.kotlin.psi.KtCallableDeclaration;
import org.jetbrains.kotlin.psi.KtElement; import org.jetbrains.kotlin.psi.KtElement;
import org.jetbrains.kotlin.test.KotlinTestUtils; import org.jetbrains.kotlin.test.KotlinTestUtils;
@@ -84,6 +84,7 @@ public abstract class AbstractHierarchyTest extends KotlinHierarchyViewTestBase
protected void doCallerJavaHierarchyTest(@NotNull String folderName) throws Exception { protected void doCallerJavaHierarchyTest(@NotNull String folderName) throws Exception {
this.folderName = folderName; this.folderName = folderName;
doHierarchyTest(getCallerJavaHierarchyStructure(), getFilesToConfigure()); doHierarchyTest(getCallerJavaHierarchyStructure(), getFilesToConfigure());
} }
protected void doCalleeHierarchyTest(@NotNull String folderName) throws Exception { protected void doCalleeHierarchyTest(@NotNull String folderName) throws Exception {
@@ -223,7 +224,9 @@ public abstract class AbstractHierarchyTest extends KotlinHierarchyViewTestBase
} }
@Override @Override
protected void doHierarchyTest(Computable<HierarchyTreeStructure> treeStructureComputable, String... fileNames) throws Exception { protected void doHierarchyTest(
@NotNull Computable<? extends HierarchyTreeStructure> treeStructureComputable, @NotNull String... fileNames
) throws Exception {
try { try {
super.doHierarchyTest(treeStructureComputable, fileNames); super.doHierarchyTest(treeStructureComputable, fileNames);
} }
@@ -240,23 +243,22 @@ public abstract class AbstractHierarchyTest extends KotlinHierarchyViewTestBase
catch (ComparisonFailure failure) { catch (ComparisonFailure failure) {
String actual = ComparisonDetailsExtractor.getActual(failure); String actual = ComparisonDetailsExtractor.getActual(failure);
String verificationFilePath = String verificationFilePath =
getTestDataPath() + "/" + getBasePath() + "/" + getTestName(false) + "_verification.xml"; getTestDataPath() + "/" + getTestName(false) + "_verification.xml";
KotlinTestUtils.assertEqualsToFile(new File(verificationFilePath), actual); KotlinTestUtils.assertEqualsToFile(new File(verificationFilePath), actual);
} }
} }
@Override @Override
protected String getBasePath() { @NotNull
return folderName.substring("idea/testData/".length()); protected LightProjectDescriptor getProjectDescriptor() {
return KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE;
} }
@NotNull
@Override @Override
protected String getTestDataPath() { protected String getTestDataPath() {
return PluginTestCaseBase.getTestDataPathBase(); String testRoot = super.getTestDataPath();
} String testDir = KotlinTestUtils.getTestDataFileName(this.getClass(), getName());
return testRoot + "/" + testDir;
@Override
protected Sdk getTestProjectJdk() {
return PluginTestCaseBase.mockJdk();
} }
} }
@@ -1,264 +0,0 @@
/*
* 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.hierarchy;
import com.intellij.ide.hierarchy.*;
import com.intellij.ide.hierarchy.actions.BrowseHierarchyActionBase;
import com.intellij.ide.hierarchy.call.CallerMethodsTreeStructure;
import com.intellij.ide.hierarchy.type.SubtypesHierarchyTreeStructure;
import com.intellij.ide.hierarchy.type.SupertypesHierarchyTreeStructure;
import com.intellij.ide.hierarchy.type.TypeHierarchyTreeStructure;
import com.intellij.lang.LanguageExtension;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.impl.text.TextEditorPsiDataProvider;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.psi.*;
import com.intellij.refactoring.util.CommonRefactoringUtil.RefactoringErrorHintException;
import com.intellij.rt.execution.junit.ComparisonDetailsExtractor;
import com.intellij.testFramework.MapDataContext;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Processor;
import junit.framework.ComparisonFailure;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.idea.KotlinHierarchyViewTestBase;
import org.jetbrains.kotlin.idea.hierarchy.calls.KotlinCalleeTreeStructure;
import org.jetbrains.kotlin.idea.hierarchy.calls.KotlinCallerTreeStructure;
import org.jetbrains.kotlin.idea.hierarchy.overrides.KotlinOverrideTreeStructure;
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase;
import org.jetbrains.kotlin.psi.KtCallableDeclaration;
import org.jetbrains.kotlin.psi.KtElement;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/*
Test Hierarchy view
Format: test build hierarchy for element at caret, file with caret should be the first in the sorted list of files.
Test accept more than one file, file extension should be .java or .kt
*/
public abstract class AbstractHierarchyTest extends KotlinHierarchyViewTestBase {
protected String folderName;
protected void doTypeClassHierarchyTest(@NotNull String folderName) throws Exception {
this.folderName = folderName;
doHierarchyTest(getTypeHierarchyStructure(), getFilesToConfigure());
}
protected void doSuperClassHierarchyTest(@NotNull String folderName) throws Exception {
this.folderName = folderName;
doHierarchyTest(getSuperTypesHierarchyStructure(), getFilesToConfigure());
}
protected void doSubClassHierarchyTest(@NotNull String folderName) throws Exception {
this.folderName = folderName;
doHierarchyTest(getSubTypesHierarchyStructure(), getFilesToConfigure());
}
protected void doCallerHierarchyTest(@NotNull String folderName) throws Exception {
this.folderName = folderName;
doHierarchyTest(getCallerHierarchyStructure(), getFilesToConfigure());
}
protected void doCallerJavaHierarchyTest(@NotNull String folderName) throws Exception {
this.folderName = folderName;
doHierarchyTest(getCallerJavaHierarchyStructure(), getFilesToConfigure());
}
protected void doCalleeHierarchyTest(@NotNull String folderName) throws Exception {
this.folderName = folderName;
doHierarchyTest(getCalleeHierarchyStructure(), getFilesToConfigure());
}
protected void doOverrideHierarchyTest(@NotNull String folderName) throws Exception {
this.folderName = folderName;
doHierarchyTest(getOverrideHierarchyStructure(), getFilesToConfigure());
}
private Computable<HierarchyTreeStructure> getSuperTypesHierarchyStructure() {
return new Computable<HierarchyTreeStructure>() {
@Override
public HierarchyTreeStructure compute() {
return new SupertypesHierarchyTreeStructure(
getProject(),
(PsiClass) getElementAtCaret(LanguageTypeHierarchy.INSTANCE)
);
}
};
}
private Computable<HierarchyTreeStructure> getSubTypesHierarchyStructure() {
return new Computable<HierarchyTreeStructure>() {
@Override
public HierarchyTreeStructure compute() {
return new SubtypesHierarchyTreeStructure(
getProject(),
(PsiClass) getElementAtCaret(LanguageTypeHierarchy.INSTANCE),
HierarchyBrowserBaseEx.SCOPE_PROJECT
);
}
};
}
private Computable<HierarchyTreeStructure> getTypeHierarchyStructure() {
return new Computable<HierarchyTreeStructure>() {
@Override
public HierarchyTreeStructure compute() {
return new TypeHierarchyTreeStructure(
getProject(),
(PsiClass) getElementAtCaret(LanguageTypeHierarchy.INSTANCE),
HierarchyBrowserBaseEx.SCOPE_PROJECT
);
}
};
}
private Computable<HierarchyTreeStructure> getCallerHierarchyStructure() {
return new Computable<HierarchyTreeStructure>() {
@Override
public HierarchyTreeStructure compute() {
return new KotlinCallerTreeStructure(
(KtElement) getElementAtCaret(LanguageCallHierarchy.INSTANCE),
HierarchyBrowserBaseEx.SCOPE_PROJECT
);
}
};
}
private Computable<HierarchyTreeStructure> getCallerJavaHierarchyStructure() {
return new Computable<HierarchyTreeStructure>() {
@Override
public HierarchyTreeStructure compute() {
return new CallerMethodsTreeStructure(
getProject(),
(PsiMethod) getElementAtCaret(LanguageCallHierarchy.INSTANCE),
HierarchyBrowserBaseEx.SCOPE_PROJECT
);
}
};
}
private Computable<HierarchyTreeStructure> getCalleeHierarchyStructure() {
return new Computable<HierarchyTreeStructure>() {
@Override
public HierarchyTreeStructure compute() {
return new KotlinCalleeTreeStructure(
(KtElement) getElementAtCaret(LanguageCallHierarchy.INSTANCE),
HierarchyBrowserBaseEx.SCOPE_PROJECT
);
}
};
}
private Computable<HierarchyTreeStructure> getOverrideHierarchyStructure() {
return new Computable<HierarchyTreeStructure>() {
@Override
public HierarchyTreeStructure compute() {
return new KotlinOverrideTreeStructure(
getProject(),
(KtCallableDeclaration) getElementAtCaret(LanguageMethodHierarchy.INSTANCE)
);
}
};
}
private PsiElement getElementAtCaret(LanguageExtension<HierarchyProvider> extension) {
PsiFile file = PsiDocumentManager.getInstance(getProject()).getPsiFile(getEditor().getDocument());
HierarchyProvider provider = BrowseHierarchyActionBase.findProvider(extension, file, file, getDataContext());
PsiElement target = provider != null ? provider.getTarget(getDataContext()) : null;
if (target == null) throw new RefactoringErrorHintException("Cannot apply action for element at caret");
return target;
}
private DataContext getDataContext() {
Editor editor = getEditor();
MapDataContext context = new MapDataContext();
context.put(CommonDataKeys.PROJECT, getProject());
context.put(CommonDataKeys.EDITOR, editor);
PsiElement targetElement = (PsiElement) new TextEditorPsiDataProvider().getData(
CommonDataKeys.PSI_ELEMENT.getName(),
editor,
editor.getCaretModel().getCurrentCaret()
);
context.put(CommonDataKeys.PSI_ELEMENT, targetElement);
return context;
}
protected String[] getFilesToConfigure() {
final List<String> files = new ArrayList<String>(2);
FileUtil.processFilesRecursively(new File(folderName), new Processor<File>() {
@Override
public boolean process(File file) {
String fileName = file.getName();
if (fileName.endsWith(".kt") || fileName.endsWith(".java")) {
files.add(fileName);
}
return true;
}
});
Collections.sort(files);
return ArrayUtil.toStringArray(files);
}
@Override
protected void doHierarchyTest(
@NotNull Computable<? extends HierarchyTreeStructure> treeStructureComputable, @NotNull String... fileNames
) throws Exception {
try {
super.doHierarchyTest(treeStructureComputable, fileNames);
}
catch (RefactoringErrorHintException e) {
File file = new File(folderName, "messages.txt");
if (file.exists()) {
String expectedMessage = FileUtil.loadFile(file, true);
assertEquals(expectedMessage, e.getLocalizedMessage());
}
else {
fail("Unexpected error: " + e.getLocalizedMessage());
}
}
catch (ComparisonFailure failure) {
String actual = ComparisonDetailsExtractor.getActual(failure);
String verificationFilePath =
getTestDataPath() + "/" + getBasePath() + "/" + getTestName(false) + "_verification.xml";
KotlinTestUtils.assertEqualsToFile(new File(verificationFilePath), actual);
}
}
@Override
protected String getBasePath() {
return folderName.substring("idea/testData/".length());
}
@Override
protected String getTestDataPath() {
return PluginTestCaseBase.getTestDataPathBase();
}
@Override
protected Sdk getTestProjectJdk() {
return PluginTestCaseBase.mockJdk();
}
}
@@ -22,37 +22,34 @@ import com.intellij.openapi.util.Computable
import com.intellij.psi.PsiClass import com.intellij.psi.PsiClass
import com.intellij.psi.impl.java.stubs.index.JavaFullClassNameIndex import com.intellij.psi.impl.java.stubs.index.JavaFullClassNameIndex
import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.idea.test.ModuleKind import com.intellij.testFramework.LightProjectDescriptor
import org.jetbrains.kotlin.idea.test.configureAs import org.jetbrains.kotlin.idea.test.ProjectDescriptorWithStdlibSources
import org.jetbrains.kotlin.test.InTextDirectivesUtils import org.jetbrains.kotlin.test.InTextDirectivesUtils
import org.jetbrains.kotlin.test.KotlinTestUtils import org.jetbrains.kotlin.test.KotlinTestUtils
import java.io.File import java.io.File
abstract class AbstractHierarchyWithLibTest : AbstractHierarchyTest() { abstract class AbstractHierarchyWithLibTest : AbstractHierarchyTest() {
override fun setUp() {
super.setUp()
myModule.configureAs(ModuleKind.KOTLIN_JVM_WITH_STDLIB_SOURCES)
}
protected fun doTest(folderName: String) { protected fun doTest(folderName: String) {
this.folderName = folderName this.folderName = folderName
val filesToConfigure = filesToConfigure val filesToConfigure = filesToConfigure
val file = filesToConfigure.first() val file = filesToConfigure.first()
val directive = InTextDirectivesUtils.findLinesWithPrefixesRemoved( val directive = InTextDirectivesUtils.findLinesWithPrefixesRemoved(
File("${KotlinTestUtils.getHomeDirectory()}/$folderName/$file").readText(), File("${KotlinTestUtils.getHomeDirectory()}/$folderName/$file").readText(),
"// BASE_CLASS: " "// BASE_CLASS: "
).singleOrNull() ?: error("File should contain BASE_CLASS directive") ).singleOrNull() ?: error("File should contain BASE_CLASS directive")
doHierarchyTest( doHierarchyTest(
Computable { Computable {
val targetClass = findTargetJavaClass(directive.trim()) val targetClass = findTargetJavaClass(directive.trim())
TypeHierarchyTreeStructure( TypeHierarchyTreeStructure(
project, project,
targetClass, targetClass,
HierarchyBrowserBaseEx.SCOPE_PROJECT) HierarchyBrowserBaseEx.SCOPE_PROJECT
}, *filesToConfigure) )
}, *filesToConfigure
)
} }
private fun findTargetJavaClass(targetClass: String): PsiClass { private fun findTargetJavaClass(targetClass: String): PsiClass {
@@ -60,4 +57,6 @@ abstract class AbstractHierarchyWithLibTest : AbstractHierarchyTest() {
it.qualifiedName == targetClass it.qualifiedName == targetClass
} ?: error("Could not find java class: $targetClass") } ?: error("Could not find java class: $targetClass")
} }
override fun getProjectDescriptor(): LightProjectDescriptor = ProjectDescriptorWithStdlibSources.INSTANCE
} }