Rewrite out-of-block modifier increment algorithm

1. Search the top-level function or property (only they can produce blocks that won't affect other declarations)
    2. Check if current position is hidden by this declaration

    O^2 behaviour is removed
This commit is contained in:
Nikolay Krasko
2014-10-21 18:27:51 +04:00
parent 40bd9fbdf3
commit 5cdd5f580d
16 changed files with 204 additions and 62 deletions
@@ -107,81 +107,41 @@ public class KotlinCodeBlockModificationListener(modificationTracker: PsiModific
if (element is PsiFileSystemItem) return false
if (element == null || element.getParent() == null) return true
var parent = element
while (parent !is PsiFile && parent !is PsiDirectory && parent != null) {
if (parent is JetClass) return false // anonymous or local class
val blockDeclarationCandidate = JetPsiUtil.getTopmostParentOfTypes(
element,
javaClass<JetProperty>(),
javaClass<JetNamedFunction>())
if (parent is JetBlockExpression) {
if (!shouldChangeModificationCount(element)) {
return true;
}
}
parent = parent!!.getParent()
}
return false
}
public fun shouldChangeModificationCount(place: PsiElement): Boolean {
// false -> inside code block
// true -> means nothing, parent will be checked
val declaration = PsiTreeUtil.getParentOfType<JetDeclaration>(place, javaClass<JetDeclaration>(), true)
if (declaration == null) return true
return when (declaration) {
when (blockDeclarationCandidate) {
is JetNamedFunction -> {
val function: JetNamedFunction = declaration
if (function.hasDeclaredReturnType() || function.hasBlockBody()) {
takePartInDeclarationTypeInference(function)
val function = blockDeclarationCandidate : JetNamedFunction
if (function.hasBlockBody() && function.getBodyExpression().isAncestorOf(element)) {
return true
}
else {
shouldChangeModificationCount(function)
if (function.hasDeclaredReturnType() && function.getInitializer().isAncestorOf(element)) {
return true
}
}
is JetPropertyAccessor -> {
takePartInDeclarationTypeInference(declaration)
}
is JetProperty -> {
val property = declaration as JetProperty
if (property.getTypeReference() != null) {
takePartInDeclarationTypeInference(property)
}
else {
shouldChangeModificationCount(property)
}
}
is JetMultiDeclaration, is JetMultiDeclarationEntry, is JetFunctionLiteral -> {
shouldChangeModificationCount(declaration)
}
else -> {
true
}
}
}
private fun takePartInDeclarationTypeInference(place: PsiElement): Boolean {
val declaration = PsiTreeUtil.getParentOfType<JetDeclaration>(place, javaClass<JetDeclaration>(), true)
if (declaration != null) {
if (declaration is JetNamedFunction) {
val function = declaration as JetNamedFunction
if (!function.hasDeclaredReturnType() && !function.hasBlockBody()) {
val property = blockDeclarationCandidate : JetProperty
val typeReference = property.getTypeReference()
if (typeReference != null && property.getInitializer().isAncestorOf(element)) {
return true
}
}
else if (declaration is JetProperty) {
val property = declaration as JetProperty
if (property.getTypeReference() == null) {
return true
for (accessor in property.getAccessors()) {
when {
accessor.getInitializer().isAncestorOf(element) -> return true
accessor.getBodyExpression().isAncestorOf(element) -> return true
}
}
}
return takePartInDeclarationTypeInference(declaration)
}
return false
}
private fun PsiElement?.isAncestorOf(element: PsiElement) = PsiTreeUtil.isAncestor(this, element, false)
}
}