Extend incremental analysis to object declaration
Fixed #KT-37250
This commit is contained in:
+24
-15
@@ -223,6 +223,7 @@ class KotlinCodeBlockModificationListener(
|
||||
|
||||
val blockDeclaration =
|
||||
KtPsiUtil.getTopmostParentOfTypes(element, *BLOCK_DECLARATION_TYPES) as? KtDeclaration ?: return null
|
||||
// KtPsiUtil.getTopmostParentOfType<KtClassOrObject>(element) as? KtDeclaration ?: return null
|
||||
|
||||
// should not be local declaration
|
||||
if (KtPsiUtil.isLocal(blockDeclaration))
|
||||
@@ -230,6 +231,11 @@ class KotlinCodeBlockModificationListener(
|
||||
|
||||
when (blockDeclaration) {
|
||||
is KtNamedFunction -> {
|
||||
// if (blockDeclaration.visibilityModifierType()?.toVisibility() == Visibilities.PRIVATE) {
|
||||
// topClassLikeDeclaration(blockDeclaration)?.let {
|
||||
// return BlockModificationScopeElement(it, it)
|
||||
// }
|
||||
// }
|
||||
if (blockDeclaration.hasBlockBody()) {
|
||||
// case like `fun foo(): String {...<caret>...}`
|
||||
return blockDeclaration.bodyExpression
|
||||
@@ -244,18 +250,23 @@ class KotlinCodeBlockModificationListener(
|
||||
}
|
||||
|
||||
is KtProperty -> {
|
||||
// if (blockDeclaration.visibilityModifierType()?.toVisibility() == Visibilities.PRIVATE) {
|
||||
// topClassLikeDeclaration(blockDeclaration)?.let {
|
||||
// return BlockModificationScopeElement(it, it)
|
||||
// }
|
||||
// }
|
||||
if (blockDeclaration.typeReference != null) {
|
||||
val accessors =
|
||||
blockDeclaration.accessors.map { it.initializer ?: it.bodyExpression } + blockDeclaration.initializer
|
||||
for (accessor in accessors) {
|
||||
accessor?.takeIf {
|
||||
it.isAncestor(element) &&
|
||||
// adding annotations to accessor is the same as change contract of property
|
||||
(element !is KtAnnotated || element.annotationEntries.isEmpty())
|
||||
}
|
||||
it.isAncestor(element) &&
|
||||
// adding annotations to accessor is the same as change contract of property
|
||||
(element !is KtAnnotated || element.annotationEntries.isEmpty())
|
||||
}
|
||||
?.let { expression ->
|
||||
val declaration =
|
||||
KtPsiUtil.getTopmostParentOfTypes(blockDeclaration, KtClass::class.java) as? KtElement ?:
|
||||
KtPsiUtil.getTopmostParentOfTypes(blockDeclaration, KtClassOrObject::class.java) as? KtElement ?:
|
||||
// ktFile to check top level property declarations
|
||||
return null
|
||||
return BlockModificationScopeElement(declaration, expression)
|
||||
@@ -277,7 +288,7 @@ class KotlinCodeBlockModificationListener(
|
||||
blockDeclaration
|
||||
.takeIf { it.isAncestor(element) }
|
||||
?.let { ktClassInitializer ->
|
||||
(PsiTreeUtil.getParentOfType(blockDeclaration, KtClass::class.java) as? KtElement)?.let {
|
||||
(PsiTreeUtil.getParentOfType(blockDeclaration, KtClassOrObject::class.java))?.let {
|
||||
return BlockModificationScopeElement(it, ktClassInitializer)
|
||||
}
|
||||
}
|
||||
@@ -287,20 +298,18 @@ class KotlinCodeBlockModificationListener(
|
||||
blockDeclaration
|
||||
?.takeIf {
|
||||
it.bodyExpression?.isAncestor(element) ?: false || it.getDelegationCallOrNull()?.isAncestor(element) ?: false
|
||||
}
|
||||
?.let { ktConstructor ->
|
||||
(PsiTreeUtil.getParentOfType(blockDeclaration, KtClass::class.java) as? KtElement)?.let {
|
||||
}?.let { ktConstructor ->
|
||||
PsiTreeUtil.getParentOfType(blockDeclaration, KtClassOrObject::class.java)?.let {
|
||||
return BlockModificationScopeElement(it, ktConstructor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: still under consideration - is it worth to track changes of private properties / methods
|
||||
// problem could be in diagnostics - it is worth to manage it with modTracker
|
||||
// is KtClass -> {
|
||||
// is KtClassOrObject -> {
|
||||
// return when (element) {
|
||||
// is KtProperty -> if (element.visibilityModifierType()?.toVisibility() == Visibilities.PRIVATE) blockDeclaration else null
|
||||
// is KtNamedFunction -> if (element.visibilityModifierType()?.toVisibility() == Visibilities.PRIVATE) blockDeclaration else null
|
||||
// is KtProperty, is KtNamedFunction -> {
|
||||
// if ((element as? KtModifierListOwner)?.visibilityModifierType()?.toVisibility() == Visibilities.PRIVATE)
|
||||
// BlockModificationScopeElement(blockDeclaration, blockDeclaration) else null
|
||||
// }
|
||||
// else -> null
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
// OUT_OF_CODE_BLOCK: TRUE
|
||||
// TYPE: 'Int'
|
||||
// TODO: changes in private functions is still subject to OOCB
|
||||
class A {
|
||||
fun foo(): Int = 12
|
||||
|
||||
private fun bar(): <caret> = foo()
|
||||
}
|
||||
|
||||
// SKIP_ANALYZE_CHECK
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
// OUT_OF_CODE_BLOCK: TRUE
|
||||
|
||||
// as it's a class body not a named function body
|
||||
|
||||
class A {
|
||||
fun foo(): Int = 12
|
||||
|
||||
private fun bar(): Int = foo() + <caret>
|
||||
}
|
||||
|
||||
// TYPE: 1
|
||||
// SKIP_ANALYZE_CHECK
|
||||
@@ -0,0 +1,9 @@
|
||||
// OUT_OF_CODE_BLOCK: TRUE
|
||||
// TYPE: 'Int'
|
||||
// TODO: changes in private properties is still subject to OOCB
|
||||
class Test {
|
||||
val more : Int = 0
|
||||
private val test : <caret> = 0
|
||||
}
|
||||
|
||||
// SKIP_ANALYZE_CHECK
|
||||
@@ -0,0 +1,8 @@
|
||||
// OUT_OF_CODE_BLOCK: FALSE
|
||||
// ERROR: Unresolved reference: call
|
||||
|
||||
object Foo {
|
||||
fun foo() {
|
||||
c<caret>ll()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// OUT_OF_CODE_BLOCK: TRUE
|
||||
// TYPE: 'Int'
|
||||
// TODO: changes in private functions is still subject to OOCB
|
||||
object A {
|
||||
fun foo(): Int = 12
|
||||
|
||||
private fun bar(): <caret> = foo()
|
||||
}
|
||||
|
||||
// SKIP_ANALYZE_CHECK
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
// OUT_OF_CODE_BLOCK: TRUE
|
||||
|
||||
// as it's a object body not a named function body
|
||||
|
||||
object A {
|
||||
fun foo(): Int = 12
|
||||
|
||||
private fun bar(): Int = foo() + <caret>
|
||||
}
|
||||
|
||||
// TYPE: 1
|
||||
// SKIP_ANALYZE_CHECK
|
||||
@@ -0,0 +1,9 @@
|
||||
// OUT_OF_CODE_BLOCK: TRUE
|
||||
// TYPE: 'Int'
|
||||
// TODO: changes in private properties is still subject to OOCB
|
||||
object Test {
|
||||
val more : Int = 0
|
||||
private val test : <caret> = 0
|
||||
}
|
||||
|
||||
// SKIP_ANALYZE_CHECK
|
||||
@@ -0,0 +1,8 @@
|
||||
// OUT_OF_CODE_BLOCK: FALSE
|
||||
// ERROR: Unresolved reference: call
|
||||
|
||||
object Foo {
|
||||
init {
|
||||
c<caret>ll()
|
||||
}
|
||||
}
|
||||
+40
@@ -93,6 +93,21 @@ public class OutOfBlockModificationTestGenerated extends AbstractOutOfBlockModif
|
||||
runTest("idea/testData/codeInsight/outOfBlock/InClassInUninitializedPropertyAccessor.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("InClassPrivateFunctionReturnType.kt")
|
||||
public void testInClassPrivateFunctionReturnType() throws Exception {
|
||||
runTest("idea/testData/codeInsight/outOfBlock/InClassPrivateFunctionReturnType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("InClassPrivateFunctionWithoutInference.kt")
|
||||
public void testInClassPrivateFunctionWithoutInference() throws Exception {
|
||||
runTest("idea/testData/codeInsight/outOfBlock/InClassPrivateFunctionWithoutInference.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("InClassPrivatePropertyType.kt")
|
||||
public void testInClassPrivatePropertyType() throws Exception {
|
||||
runTest("idea/testData/codeInsight/outOfBlock/InClassPrivatePropertyType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("InClassPropertyAccessor.kt")
|
||||
public void testInClassPropertyAccessor() throws Exception {
|
||||
runTest("idea/testData/codeInsight/outOfBlock/InClassPropertyAccessor.kt");
|
||||
@@ -138,6 +153,11 @@ public class OutOfBlockModificationTestGenerated extends AbstractOutOfBlockModif
|
||||
runTest("idea/testData/codeInsight/outOfBlock/InFunInMultiDeclaration.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("InFunInObject.kt")
|
||||
public void testInFunInObject() throws Exception {
|
||||
runTest("idea/testData/codeInsight/outOfBlock/InFunInObject.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("InFunInProperty.kt")
|
||||
public void testInFunInProperty() throws Exception {
|
||||
runTest("idea/testData/codeInsight/outOfBlock/InFunInProperty.kt");
|
||||
@@ -198,6 +218,21 @@ public class OutOfBlockModificationTestGenerated extends AbstractOutOfBlockModif
|
||||
runTest("idea/testData/codeInsight/outOfBlock/InNestedClassFunNoTypeBlockExpression.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("InObjectPrivateFunctionReturnType.kt")
|
||||
public void testInObjectPrivateFunctionReturnType() throws Exception {
|
||||
runTest("idea/testData/codeInsight/outOfBlock/InObjectPrivateFunctionReturnType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("InObjectPrivateFunctionWithoutInference.kt")
|
||||
public void testInObjectPrivateFunctionWithoutInference() throws Exception {
|
||||
runTest("idea/testData/codeInsight/outOfBlock/InObjectPrivateFunctionWithoutInference.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("InObjectPrivatePropertyType.kt")
|
||||
public void testInObjectPrivatePropertyType() throws Exception {
|
||||
runTest("idea/testData/codeInsight/outOfBlock/InObjectPrivatePropertyType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("InPrimaryConstructor.kt")
|
||||
public void testInPrimaryConstructor() throws Exception {
|
||||
runTest("idea/testData/codeInsight/outOfBlock/InPrimaryConstructor.kt");
|
||||
@@ -293,6 +328,11 @@ public class OutOfBlockModificationTestGenerated extends AbstractOutOfBlockModif
|
||||
runTest("idea/testData/codeInsight/outOfBlock/InitBlockInLocalClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("InitBlockInObject.kt")
|
||||
public void testInitBlockInObject() throws Exception {
|
||||
runTest("idea/testData/codeInsight/outOfBlock/InitBlockInObject.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("LocalFunWithBody.kt")
|
||||
public void testLocalFunWithBody() throws Exception {
|
||||
runTest("idea/testData/codeInsight/outOfBlock/LocalFunWithBody.kt");
|
||||
|
||||
Reference in New Issue
Block a user