Optimization

This commit is contained in:
Valentin Kipyatkov
2016-08-27 14:35:19 +03:00
parent 7a269a00af
commit 1e80ad3f98
@@ -198,34 +198,48 @@ private class Processor(
} }
} }
private enum class CallableToProcessKind {
HAS_DATA_CLASS_TYPE,
PROCESS_LAMBDAS
}
//TODO: check if it's operator (too expensive) //TODO: check if it's operator (too expensive)
/** /**
* Adds declaration whose type is our data class (or data class used anywhere inside that type) * Adds declaration whose type is our data class (or data class used anywhere inside that type)
* or which has parameter of functional type with our data class used inside * or which has parameter of functional type with our data class used inside
*/ */
private fun addCallableDeclarationToProcess(declaration: PsiElement) { private fun addCallableDeclarationToProcess(declaration: PsiElement, kind: CallableToProcessKind) {
data class ProcessCallableUsagesTask(val declaration: PsiElement) : Task { data class ProcessCallableUsagesTask(val declaration: PsiElement, val kind: CallableToProcessKind) : Task {
override fun perform() { override fun perform() {
ReferencesSearch.search(declaration, declarationUsageScope).forEach { reference -> ReferencesSearch.search(declaration, declarationUsageScope).forEach { reference ->
if (reference is KtDestructuringDeclarationReference) { // declaration usage in form of destructuring declaration when (kind) {
val entries = reference.element.entries CallableToProcessKind.HAS_DATA_CLASS_TYPE -> {
val componentIndex = when (declaration) { if (reference is KtDestructuringDeclarationReference) {
is KtParameter -> declaration.dataClassComponentFunction()?.name?.asString()?.let { getComponentIndex(it) } // declaration usage in form of destructuring declaration
is KtFunction -> declaration.name?.let { getComponentIndex(it) } val entries = reference.element.entries
//TODO: java component functions (see KT-13605) val componentIndex = when (declaration) {
else -> null is KtParameter -> declaration.dataClassComponentFunction()?.name?.asString()?.let { getComponentIndex(it) }
is KtFunction -> declaration.name?.let { getComponentIndex(it) }
//TODO: java component functions (see KT-13605)
else -> null
}
if (componentIndex != null && componentIndex <= entries.size) {
addCallableDeclarationToProcess(entries[componentIndex - 1], CallableToProcessKind.HAS_DATA_CLASS_TYPE)
}
}
else {
(reference.element as? KtReferenceExpression)?.let { processSuspiciousExpression(it) }
}
} }
if (componentIndex != null && componentIndex <= entries.size) {
addCallableDeclarationToProcess(entries[componentIndex - 1]) CallableToProcessKind.PROCESS_LAMBDAS -> {
(reference.element as? KtReferenceExpression)?.let { processLambdasForCallableReference(it) }
} }
} }
else {
(reference.element as? KtReferenceExpression)?.let { processSuspiciousExpression(it) }
}
} }
} }
} }
addTask(ProcessCallableUsagesTask(declaration)) addTask(ProcessCallableUsagesTask(declaration, kind))
} }
private fun addSamInterfaceToProcess(psiClass: PsiClass) { private fun addSamInterfaceToProcess(psiClass: PsiClass) {
@@ -238,7 +252,7 @@ private class Processor(
val parameter = ((reference as? PsiJavaCodeReferenceElement)?.parent as? PsiTypeElement)?.parent as? PsiParameter val parameter = ((reference as? PsiJavaCodeReferenceElement)?.parent as? PsiTypeElement)?.parent as? PsiParameter
val method = parameter?.declarationScope as? PsiMethod val method = parameter?.declarationScope as? PsiMethod
if (method != null) { if (method != null) {
addCallableDeclarationToProcess(method) addCallableDeclarationToProcess(method, CallableToProcessKind.PROCESS_LAMBDAS)
} }
} }
} }
@@ -274,14 +288,14 @@ private class Processor(
is KtCallableDeclaration -> { is KtCallableDeclaration -> {
when (typeRef) { when (typeRef) {
typeRefParent.typeReference -> { typeRefParent.typeReference -> {
addCallableDeclarationToProcess(typeRefParent) addCallableDeclarationToProcess(typeRefParent, CallableToProcessKind.HAS_DATA_CLASS_TYPE)
if (typeRefParent is KtParameter) { //TODO: what if functional type is declared with "FunctionN<...>"? if (typeRefParent is KtParameter) { //TODO: what if functional type is declared with "FunctionN<...>"?
val usedInsideFunctionalType = parent.parents.takeWhile { it != typeRef }.any { it is KtFunctionType } val usedInsideFunctionalType = parent.parents.takeWhile { it != typeRef }.any { it is KtFunctionType }
if (usedInsideFunctionalType) { if (usedInsideFunctionalType) {
val function = (typeRefParent.parent as? KtParameterList)?.parent as? KtFunction val function = (typeRefParent.parent as? KtParameterList)?.parent as? KtFunction
if (function != null) { if (function != null) {
addCallableDeclarationToProcess(function) addCallableDeclarationToProcess(function, CallableToProcessKind.PROCESS_LAMBDAS)
} }
} }
} }
@@ -392,14 +406,14 @@ private class Processor(
is PsiMethod -> { is PsiMethod -> {
if (prev == parent.returnTypeElement && !parent.isPrivateOrLocal()) { if (prev == parent.returnTypeElement && !parent.isPrivateOrLocal()) {
addCallableDeclarationToProcess(parent) addCallableDeclarationToProcess(parent, CallableToProcessKind.HAS_DATA_CLASS_TYPE)
} }
break@ParentsLoop break@ParentsLoop
} }
is PsiField -> { is PsiField -> {
if (prev == parent.typeElement && !parent.isPrivateOrLocal()) { if (prev == parent.typeElement && !parent.isPrivateOrLocal()) {
addCallableDeclarationToProcess(parent) addCallableDeclarationToProcess(parent, CallableToProcessKind.HAS_DATA_CLASS_TYPE)
} }
break@ParentsLoop break@ParentsLoop
} }
@@ -450,11 +464,12 @@ private class Processor(
} }
// use plain search in all lambdas and anonymous functions inside because they parameters or receiver can be implicitly typed with our data class // use plain search in all lambdas and anonymous functions inside because they parameters or receiver can be implicitly typed with our data class
affectedScope.forEachDescendantOfType<KtFunction> { usePlainSearchInLambdas(affectedScope)
if (it.nameIdentifier == null) { }
usePlainSearch(it)
} private fun processLambdasForCallableReference(expression: KtReferenceExpression) {
} //TODO: receiver?
usePlainSearchInLambdas(expression.parent)
} }
/** /**
@@ -475,7 +490,15 @@ private class Processor(
val descriptor = declaration.resolveToDescriptorIfAny() as? CallableDescriptor ?: return val descriptor = declaration.resolveToDescriptorIfAny() as? CallableDescriptor ?: return
val type = descriptor.returnType val type = descriptor.returnType
if (type != null && type.containsTypeOrDerivedInside(dataType)) { if (type != null && type.containsTypeOrDerivedInside(dataType)) {
addCallableDeclarationToProcess(declaration) addCallableDeclarationToProcess(declaration, CallableToProcessKind.HAS_DATA_CLASS_TYPE)
}
}
}
private fun usePlainSearchInLambdas(scope: PsiElement) {
scope.forEachDescendantOfType<KtFunction> {
if (it.nameIdentifier == null) {
usePlainSearch(it)
} }
} }
} }