mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-04-16 08:31:26 +00:00
Better testing via logging of performed operations
This commit is contained in:
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
||||
import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName
|
||||
import org.jetbrains.kotlin.idea.references.KtDestructuringDeclarationReference
|
||||
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinRequestResultProcessor
|
||||
import org.jetbrains.kotlin.idea.search.restrictToKotlinSources
|
||||
@@ -61,7 +62,9 @@ enum class DestructuringDeclarationUsageSearch {
|
||||
ALWAYS_SMART, ALWAYS_PLAIN, PLAIN_WHEN_NEEDED
|
||||
}
|
||||
|
||||
// for tests
|
||||
var destructuringDeclarationUsageSearchMode = if (ApplicationManager.getApplication().isUnitTestMode) ALWAYS_SMART else PLAIN_WHEN_NEEDED
|
||||
var destructuringDeclarationUsageSearchLog: MutableList<String>? = null
|
||||
|
||||
//TODO: check if it's too expensive
|
||||
|
||||
@@ -108,7 +111,8 @@ fun findDestructuringDeclarationUsages(
|
||||
ktDeclaration,
|
||||
scope,
|
||||
consumer,
|
||||
plainSearchHandler = { searchScope -> doPlainSearch(ktDeclaration, searchScope, optimizer) }
|
||||
plainSearchHandler = { searchScope -> doPlainSearch(ktDeclaration, searchScope, optimizer) },
|
||||
testLog = destructuringDeclarationUsageSearchLog
|
||||
).run()
|
||||
}
|
||||
|
||||
@@ -124,13 +128,15 @@ private class Processor(
|
||||
private val target: KtDeclaration,
|
||||
private val searchScope: SearchScope,
|
||||
private val consumer: Processor<PsiReference>,
|
||||
private val plainSearchHandler: (SearchScope) -> Unit
|
||||
plainSearchHandler: (SearchScope) -> Unit,
|
||||
private val testLog: MutableList<String>?
|
||||
) {
|
||||
private val project = target.project
|
||||
private val plainSearchHandler: (SearchScope) -> Unit = { scope ->
|
||||
testLog?.add("Used plain search in ${scope.logPresentation()}")
|
||||
plainSearchHandler(scope)
|
||||
}
|
||||
|
||||
// we don't need to search usages of declarations in Java because Java doesn't have implicitly typed declarations so such usages cannot affect Kotlin code
|
||||
//TODO: what about Scala and other JVM-languages?
|
||||
private val declarationUsageScope = GlobalSearchScope.projectScope(project).restrictToKotlinSources()
|
||||
private val project = target.project
|
||||
|
||||
// note: a Task must define equals & hashCode!
|
||||
private interface Task {
|
||||
@@ -159,8 +165,10 @@ private class Processor(
|
||||
|
||||
val parameters = ClassInheritorsSearch.SearchParameters(psiClass, GlobalSearchScope.allScope(project), true, true, false)
|
||||
val classesToSearch = listOf(psiClass) + ClassInheritorsSearch.search(parameters).findAll()
|
||||
testLog?.add("Searched inheritors of ${psiClass.logPresentation()}")
|
||||
|
||||
for (classToSearch in classesToSearch) {
|
||||
testLog?.add("Searched references to ${classToSearch.logPresentation()}")
|
||||
ReferencesSearch.search(classToSearch).forEach(Processor processor@ { reference -> //TODO: see KT-13607
|
||||
if (processDataClassUsage(reference)) return@processor true
|
||||
|
||||
@@ -211,7 +219,11 @@ private class Processor(
|
||||
private fun addCallableDeclarationToProcess(declaration: PsiElement, kind: CallableToProcessKind) {
|
||||
data class ProcessCallableUsagesTask(val declaration: PsiElement, val kind: CallableToProcessKind) : Task {
|
||||
override fun perform() {
|
||||
ReferencesSearch.search(declaration, declarationUsageScope).forEach { reference ->
|
||||
// we don't need to search usages of declarations in Java because Java doesn't have implicitly typed declarations so such usages cannot affect Kotlin code
|
||||
//TODO: what about Scala and other JVM-languages?
|
||||
val scope = GlobalSearchScope.projectScope(project).restrictToKotlinSources()
|
||||
testLog?.add("Searched references to ${declaration.logPresentation()} in Kotlin files")
|
||||
ReferencesSearch.search(declaration, scope).forEach { reference ->
|
||||
when (kind) {
|
||||
CallableToProcessKind.HAS_DATA_CLASS_TYPE -> {
|
||||
if (reference is KtDestructuringDeclarationReference) {
|
||||
@@ -247,6 +259,7 @@ private class Processor(
|
||||
override fun perform() {
|
||||
//TODO: what about other JVM languages?
|
||||
val scope = GlobalSearchScope.getScopeRestrictedByFileTypes(GlobalSearchScope.projectScope(project), JavaFileType.INSTANCE)
|
||||
testLog?.add("Searched references to ${psiClass.logPresentation()} in java files")
|
||||
ReferencesSearch.search(psiClass, scope).forEach { reference ->
|
||||
// check if the reference is method parameter type
|
||||
val parameter = ((reference as? PsiJavaCodeReferenceElement)?.parent as? PsiTypeElement)?.parent as? PsiParameter
|
||||
@@ -563,4 +576,43 @@ private class Processor(
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
private fun PsiElement.logPresentation(): String? {
|
||||
val fqName = getKotlinFqName()?.asString()
|
||||
?: (this as? KtNamedDeclaration)?.name
|
||||
return when (this) {
|
||||
is PsiMethod, is KtFunction -> fqName + "()"
|
||||
is KtParameter -> "parameter ${this.name} in ${this.ownerFunction?.logPresentation()}"
|
||||
else -> fqName
|
||||
}
|
||||
}
|
||||
|
||||
private fun SearchScope.logPresentation(): String {
|
||||
return when (this) {
|
||||
searchScope -> "whole search scope"
|
||||
|
||||
is LocalSearchScope -> {
|
||||
scope
|
||||
.map { element ->
|
||||
" " + when (element) {
|
||||
is KtFunctionLiteral -> element.text
|
||||
is KtWhenEntry -> {
|
||||
if (element.isElse)
|
||||
"KtWhenEntry \"else\""
|
||||
else
|
||||
"KtWhenEntry \"" + element.conditions.joinToString(", ") { it.text } + "\""
|
||||
}
|
||||
is KtNamedDeclaration -> element.node.elementType.toString() + ":" + element.name
|
||||
else -> element.toString()
|
||||
}
|
||||
}
|
||||
.toList()
|
||||
.sorted()
|
||||
.joinToString("\n", "LocalSearchScope:\n")
|
||||
}
|
||||
|
||||
else -> this.displayName
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,9 +131,10 @@ abstract class KotlinFindMemberUsagesHandler<T : KtNamedDeclaration>
|
||||
val uniqueProcessor = CommonProcessors.UniqueProcessor(processor)
|
||||
|
||||
if (options.isUsages) {
|
||||
val searchParameters = KotlinReferencesSearchParameters(element,
|
||||
scope = options.searchScope,
|
||||
kotlinOptions = createKotlinReferencesSearchOptions(options))
|
||||
// we disable searchForComponentConventions for ReferencesSearch because they will be searched by MethodReferencesSearch
|
||||
val kotlinSearchOptions = createKotlinReferencesSearchOptions(options)
|
||||
.copy(searchForComponentConventions = false)
|
||||
val searchParameters = KotlinReferencesSearchParameters(element, options.searchScope, kotlinOptions = kotlinSearchOptions)
|
||||
|
||||
with(applyQueryFilters(element, options, ReferencesSearch.search(searchParameters))) {
|
||||
if (!forEach(referenceProcessor)) return false
|
||||
|
||||
7
idea/testData/findUsages/kotlin/conventions/components/componentFunForGenericType1.log
vendored
Normal file
7
idea/testData/findUsages/kotlin/conventions/components/componentFunForGenericType1.log
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
Searched inheritors of X
|
||||
Searched references to X
|
||||
Searched references to f() in Kotlin files
|
||||
Used plain search in LocalSearchScope:
|
||||
CLASS:X
|
||||
FUN:component1
|
||||
FUN:component2
|
||||
9
idea/testData/findUsages/kotlin/conventions/components/componentFunForGenericType2.log
vendored
Normal file
9
idea/testData/findUsages/kotlin/conventions/components/componentFunForGenericType2.log
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
Searched inheritors of X
|
||||
Searched references to X
|
||||
Searched references to f() in Kotlin files
|
||||
Used plain search in LocalSearchScope:
|
||||
CLASS:X
|
||||
FUN:component1
|
||||
FUN:component1
|
||||
FUN:component2
|
||||
FUN:component2
|
||||
53
idea/testData/findUsages/kotlin/conventions/components/dataClass.log
vendored
Normal file
53
idea/testData/findUsages/kotlin/conventions/components/dataClass.log
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
Searched inheritors of pack.A
|
||||
Searched inheritors of pack.B
|
||||
Searched inheritors of pack.C
|
||||
Searched references to JavaClass.getA() in Kotlin files
|
||||
Searched references to JavaClass.takeSAM() in Kotlin files
|
||||
Searched references to JavaSAM in java files
|
||||
Searched references to a in Kotlin files
|
||||
Searched references to a in Kotlin files
|
||||
Searched references to a1 in Kotlin files
|
||||
Searched references to f() in Kotlin files
|
||||
Searched references to g() in Kotlin files
|
||||
Searched references to h() in Kotlin files
|
||||
Searched references to list in Kotlin files
|
||||
Searched references to listOfA() in Kotlin files
|
||||
Searched references to pack.A
|
||||
Searched references to pack.B
|
||||
Searched references to pack.C
|
||||
Searched references to pack.C.component1() in Kotlin files
|
||||
Searched references to pack4.takeExtFun() in Kotlin files
|
||||
Searched references to pack4.takeFun1() in Kotlin files
|
||||
Searched references to pack4.takeFun2() in Kotlin files
|
||||
Searched references to pack4.takeFun3() in Kotlin files
|
||||
Searched references to pack4.takeFuns() in Kotlin files
|
||||
Searched references to pack5.v in Kotlin files
|
||||
Searched references to parameter a in B() in Kotlin files
|
||||
Searched references to parameter a in null in Kotlin files
|
||||
Searched references to parameter b in pack.f() in Kotlin files
|
||||
Searched references to parameter c in pack.f() in Kotlin files
|
||||
Searched references to parameter p in pack4.foo() in Kotlin files
|
||||
Searched references to parameter p in pack4.takeExtFun() in Kotlin files
|
||||
Searched references to parameter p in pack4.takeFun1() in Kotlin files
|
||||
Searched references to parameter p in pack4.takeFun2() in Kotlin files
|
||||
Searched references to parameter p in pack4.takeFun3() in Kotlin files
|
||||
Searched references to parameter p in pack4.takeFuns() in Kotlin files
|
||||
Used plain search in LocalSearchScope:
|
||||
CLASS:A
|
||||
FUN:ext1
|
||||
FUN:ext1
|
||||
FUN:x
|
||||
KtWhenEntry "else"
|
||||
KtWhenEntry "is A"
|
||||
{ a, n -> val (x, y) = a!! }
|
||||
{ val (x, y ) = it }
|
||||
{ val (x, y) = it }
|
||||
{ val (x, y) = it }
|
||||
{ val (x, y) = it }
|
||||
{ val (x, y) = it }
|
||||
{ val (x, y) = it[0] }
|
||||
{ val (x, y) = this }
|
||||
Used plain search in LocalSearchScope:
|
||||
CLASS:B
|
||||
Used plain search in LocalSearchScope:
|
||||
CLASS:C
|
||||
5
idea/testData/findUsages/kotlin/conventions/components/dataClassComponentByRef.log
vendored
Normal file
5
idea/testData/findUsages/kotlin/conventions/components/dataClassComponentByRef.log
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
Searched inheritors of A
|
||||
Searched references to A
|
||||
Searched references to a in Kotlin files
|
||||
Used plain search in LocalSearchScope:
|
||||
CLASS:A
|
||||
1
idea/testData/findUsages/kotlin/conventions/components/dataClassFromStdlib.log
vendored
Normal file
1
idea/testData/findUsages/kotlin/conventions/components/dataClassFromStdlib.log
vendored
Normal file
@@ -0,0 +1 @@
|
||||
Used plain search in whole search scope
|
||||
10
idea/testData/findUsages/kotlin/conventions/components/extensionComponentFun.log
vendored
Normal file
10
idea/testData/findUsages/kotlin/conventions/components/extensionComponentFun.log
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
Searched inheritors of X
|
||||
Searched references to X
|
||||
Searched references to Y
|
||||
Searched references to f() in Kotlin files
|
||||
Used plain search in LocalSearchScope:
|
||||
CLASS:X
|
||||
CLASS:Y
|
||||
FUN:component1
|
||||
FUN:component2
|
||||
FUN:ext
|
||||
11
idea/testData/findUsages/kotlin/conventions/components/memberComponentFun.log
vendored
Normal file
11
idea/testData/findUsages/kotlin/conventions/components/memberComponentFun.log
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
Searched inheritors of X
|
||||
Searched references to X
|
||||
Searched references to Y
|
||||
Searched references to Z
|
||||
Searched references to f() in Kotlin files
|
||||
Searched references to g() in Kotlin files
|
||||
Searched references to h() in Kotlin files
|
||||
Used plain search in LocalSearchScope:
|
||||
CLASS:X
|
||||
CLASS:Y
|
||||
CLASS:Z
|
||||
@@ -0,0 +1,4 @@
|
||||
Searched inheritors of test.KotlinDataClass
|
||||
Searched references to test.KotlinDataClass
|
||||
Used plain search in LocalSearchScope:
|
||||
CLASS:KotlinDataClass
|
||||
@@ -58,6 +58,7 @@ import org.jetbrains.kotlin.idea.findUsages.KotlinClassFindUsagesOptions;
|
||||
import org.jetbrains.kotlin.idea.findUsages.KotlinFindUsagesHandlerFactory;
|
||||
import org.jetbrains.kotlin.idea.findUsages.KotlinFunctionFindUsagesOptions;
|
||||
import org.jetbrains.kotlin.idea.findUsages.KotlinPropertyFindUsagesOptions;
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.DestructuringDeclarationUsagesKt;
|
||||
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase;
|
||||
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor;
|
||||
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase;
|
||||
@@ -69,9 +70,7 @@ import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
public abstract class AbstractFindUsagesTest extends KotlinLightCodeInsightFixtureTestCase {
|
||||
|
||||
@@ -399,7 +398,22 @@ public abstract class AbstractFindUsagesTest extends KotlinLightCodeInsightFixtu
|
||||
) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
|
||||
boolean highlightingMode = InTextDirectivesUtils.isDirectiveDefined(mainFileText, "// HIGHLIGHTING");
|
||||
|
||||
Collection<UsageInfo> usageInfos = findUsages(caretElement, options, highlightingMode);
|
||||
Collection<UsageInfo> usageInfos;
|
||||
String log = null;
|
||||
try {
|
||||
DestructuringDeclarationUsagesKt.setDestructuringDeclarationUsageSearchLog(new ArrayList<String>());
|
||||
|
||||
usageInfos = findUsages(caretElement, options, highlightingMode);
|
||||
}
|
||||
finally {
|
||||
List<String> logList = DestructuringDeclarationUsagesKt.getDestructuringDeclarationUsageSearchLog();
|
||||
assert logList != null;
|
||||
DestructuringDeclarationUsagesKt.setDestructuringDeclarationUsageSearchLog(null);
|
||||
if (logList.size() > 0) {
|
||||
Collections.sort(logList);
|
||||
log = StringUtil.join(logList, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
Collection<UsageFilteringRule> filteringRules = instantiateClasses(mainFileText, "// FILTERING_RULES: ");
|
||||
final Collection<UsageGroupingRule> groupingRules = instantiateClasses(mainFileText, "// GROUPING_RULES: ");
|
||||
@@ -458,6 +472,10 @@ public abstract class AbstractFindUsagesTest extends KotlinLightCodeInsightFixtu
|
||||
|
||||
Collection<String> finalUsages = Ordering.natural().sortedCopy(Collections2.transform(filteredUsages, convertToString));
|
||||
KotlinTestUtils.assertEqualsToFile(new File(rootPath, prefix + "results.txt"), StringUtil.join(finalUsages, "\n"));
|
||||
|
||||
if (log != null) {
|
||||
KotlinTestUtils.assertEqualsToFile(new File(rootPath, prefix + "log"), log);
|
||||
}
|
||||
}
|
||||
|
||||
protected Collection<UsageInfo> findUsages(
|
||||
|
||||
Reference in New Issue
Block a user