Make changes in super call lambda not cause out-of-block modification (KT-13474)
#KT-13474 Fixed
This commit is contained in:
@@ -104,6 +104,7 @@ These artifacts include extensions for the types available in the latter JDKs, s
|
||||
- [`KT-13589`](https://youtrack.jetbrains.com/issue/KT-13589) Use TODO() consistently in implementation stubs
|
||||
- [`KT-13630`](https://youtrack.jetbrains.com/issue/KT-13630) Do not show Change Signature dialog when applying "Remove parameter" quick-fix
|
||||
- Re-highlight only single function after local modifications
|
||||
- [`KT-13474`](https://youtrack.jetbrains.com/issue/KT-13474) Fix performance of typing super call lambda
|
||||
|
||||
#### Intention actions, inspections and quickfixes
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ fun KtElement.getModificationStamp(): Long {
|
||||
return when (this) {
|
||||
is KtFile -> this.modificationStamp
|
||||
is KtDeclarationStub<*> -> this.modificationStamp
|
||||
is KtSuperTypeList -> this.modificationStamp
|
||||
else -> (parent as KtElement).getModificationStamp()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,8 +29,11 @@ import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
public class KtSuperTypeList extends KtElementImplStub<KotlinPlaceHolderStub<KtSuperTypeList>> {
|
||||
private final AtomicLong modificationStamp = new AtomicLong();
|
||||
|
||||
public KtSuperTypeList(@NotNull ASTNode node) {
|
||||
super(node);
|
||||
}
|
||||
@@ -66,4 +69,15 @@ public class KtSuperTypeList extends KtElementImplStub<KotlinPlaceHolderStub<KtS
|
||||
public List<KtSuperTypeListEntry> getEntries() {
|
||||
return Arrays.asList(getStubOrPsiChildren(KtStubElementTypes.SUPER_TYPE_LIST_ENTRIES, KtSuperTypeListEntry.ARRAY_FACTORY));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void subtreeChanged() {
|
||||
super.subtreeChanged();
|
||||
modificationStamp.getAndIncrement();
|
||||
}
|
||||
|
||||
public long getModificationStamp() {
|
||||
return modificationStamp.get();
|
||||
}
|
||||
}
|
||||
|
||||
+7
-1
@@ -68,7 +68,13 @@ class KotlinCodeBlockModificationListener(
|
||||
}
|
||||
|
||||
private fun isInsideCodeBlock(element: PsiElement): Boolean {
|
||||
//TODO: other types
|
||||
val lambda = KtPsiUtil.getTopmostParentOfTypes(element, KtLambdaExpression::class.java)
|
||||
if (lambda is KtLambdaExpression) {
|
||||
if (KtPsiUtil.getTopmostParentOfTypes(lambda, KtSuperTypeCallEntry::class.java) != null) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
val blockDeclaration = KtPsiUtil.getTopmostParentOfTypes(element, *BLOCK_DECLARATION_TYPES) ?: return false
|
||||
if (blockDeclaration.parents.any { it !is KtClassBody && it !is KtClassOrObject && it !is KtFile }) return false // should not be local declaration
|
||||
|
||||
|
||||
@@ -60,12 +60,15 @@ class ResolveElementCache(
|
||||
|
||||
private fun modificationStamp(resolveElement: KtElement): Long? {
|
||||
val file = resolveElement.containingFile
|
||||
return if (!file.isPhysical) // for non-physical file we don't get OUT_OF_CODE_BLOCK_MODIFICATION_COUNT increased and must reset data on any modification of the file
|
||||
file.modificationStamp
|
||||
else if (resolveElement is KtDeclaration && KotlinCodeBlockModificationListener.isBlockDeclaration(resolveElement))
|
||||
resolveElement.getModificationStamp()
|
||||
else
|
||||
null
|
||||
return when {
|
||||
// for non-physical file we don't get OUT_OF_CODE_BLOCK_MODIFICATION_COUNT increased and must reset
|
||||
// data on any modification of the file
|
||||
!file.isPhysical -> file.modificationStamp
|
||||
|
||||
resolveElement is KtDeclaration && KotlinCodeBlockModificationListener.isBlockDeclaration(resolveElement) -> resolveElement.getModificationStamp()
|
||||
resolveElement is KtSuperTypeList -> resolveElement.modificationStamp
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// FALSE
|
||||
|
||||
// Navigation from "class B: A()" should move to valid constructor even after changing type in lambda
|
||||
|
||||
open class A(l: String) {
|
||||
constructor(x: Int) : this("$x")
|
||||
}
|
||||
|
||||
fun <T> foo(l: () -> T) = l()
|
||||
|
||||
class B: A(foo { "1"<caret> })
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
// FALSE
|
||||
|
||||
open class A(a: () -> Unit)
|
||||
|
||||
class B: A({ "1"<caret> })
|
||||
@@ -0,0 +1,10 @@
|
||||
// TRUE
|
||||
// Can't result to false as there's no body expression, so it's considered to be changes in JavaCodeBlockModificationListener.
|
||||
|
||||
open class A(a: () -> Unit) {
|
||||
constructor(f: (String) -> Unit) : this({ -> f("") })
|
||||
}
|
||||
|
||||
class B: A({ s<caret> -> "1" })
|
||||
|
||||
// SKIP_ANALYZE_CHECK
|
||||
+18
@@ -191,6 +191,24 @@ public class OutOfBlockModificationTestGenerated extends AbstractOutOfBlockModif
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("InSuperTypeCallCallInLambdaInCall.kt")
|
||||
public void testInSuperTypeCallCallInLambdaInCall() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/outOfBlock/InSuperTypeCallCallInLambdaInCall.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("InSuperTypeCallInLambaInBody.kt")
|
||||
public void testInSuperTypeCallInLambaInBody() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/outOfBlock/InSuperTypeCallInLambaInBody.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("InSuperTypeCallInLambdaParameters.kt")
|
||||
public void testInSuperTypeCallInLambdaParameters() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/outOfBlock/InSuperTypeCallInLambdaParameters.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("InitBlock.kt")
|
||||
public void testInitBlock() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/outOfBlock/InitBlock.kt");
|
||||
|
||||
Reference in New Issue
Block a user