diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/ExplicitThisInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/ExplicitThisInspection.kt index 803ad36388e..e16419a7547 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/ExplicitThisInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/ExplicitThisInspection.kt @@ -23,11 +23,13 @@ import com.intellij.codeInspection.ProblemsHolder import com.intellij.openapi.project.Project import org.jetbrains.kotlin.config.LanguageFeature.CallableReferencesToClassMembersWithEmptyLHS import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.idea.intentions.getCallableDescriptor import org.jetbrains.kotlin.idea.project.languageVersionSettings import org.jetbrains.kotlin.idea.util.* import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getChildOfType import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor class ExplicitThisInspection : AbstractKotlinInspection() { @@ -52,15 +54,16 @@ class ExplicitThisInspection : AbstractKotlinInspection() { val context = expression.analyze() val scope = expression.getResolutionScope(context) ?: return - val referenceExpression = reference as? KtNameReferenceExpression - ?: reference.getChildOfType() - ?: return + val referenceExpression = reference as? KtNameReferenceExpression ?: reference.getChildOfType() ?: return //we avoid overload-related problems by enforcing that there is only one candidate val name = referenceExpression.getReferencedNameAsName() val candidates = scope.getAllAccessibleVariables(name) + scope.getAllAccessibleFunctions(name) - if (candidates.size != 1) return - + if (referenceExpression.getCallableDescriptor() is SyntheticJavaPropertyDescriptor) { + if (candidates.map { it.containingDeclaration }.distinct().size != 1) return + } else { + if (candidates.size != 1) return + } val receiverType = context[BindingContext.EXPRESSION_TYPE_INFO, thisExpression]?.type ?: return val expressionFactory = scope.getFactoryForImplicitReceiverWithSubtypeOf(receiverType) ?: return diff --git a/idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty.1.java b/idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty.1.java new file mode 100644 index 00000000000..b6d317c430d --- /dev/null +++ b/idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty.1.java @@ -0,0 +1,11 @@ +public class Foo { + private String s; + + public String getS() { + return s; + } + + public void setS(String s) { + this.s = s; + } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty.kt b/idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty.kt new file mode 100644 index 00000000000..e5d90adb048 --- /dev/null +++ b/idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty.kt @@ -0,0 +1,7 @@ +// WITH_RUNTIME + +fun test1() { + Foo().apply { + this.s = "" + } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty.kt.after b/idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty.kt.after new file mode 100644 index 00000000000..57eb9509b83 --- /dev/null +++ b/idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty.kt.after @@ -0,0 +1,7 @@ +// WITH_RUNTIME + +fun test1() { + Foo().apply { + s = "" + } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty_nestedReceiver.1.java b/idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty_nestedReceiver.1.java new file mode 100644 index 00000000000..72778357ad0 --- /dev/null +++ b/idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty_nestedReceiver.1.java @@ -0,0 +1,23 @@ +public class Foo { + private boolean isB; + + public boolean isB() { + return isB; + } + + public void setB(boolean b) { + isB = b; + } +} + +public class Bar { + private boolean isB; + + public boolean isB() { + return isB; + } + + public void setB(boolean b) { + isB = b; + } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty_nestedReceiver.kt b/idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty_nestedReceiver.kt new file mode 100644 index 00000000000..e8a5907db4d --- /dev/null +++ b/idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty_nestedReceiver.kt @@ -0,0 +1,10 @@ +// WITH_RUNTIME +// PROBLEM: none + +fun test() { + Foo().apply { + Bar().run { + this@apply.isB = true + } + } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty_sameClassNestedReceiver.1.java b/idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty_sameClassNestedReceiver.1.java new file mode 100644 index 00000000000..0ec915aca79 --- /dev/null +++ b/idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty_sameClassNestedReceiver.1.java @@ -0,0 +1,11 @@ +public class Foo { + private boolean isB; + + public boolean isB() { + return isB; + } + + public void setB(boolean b) { + isB = b; + } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty_sameClassNestedReceiver.kt b/idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty_sameClassNestedReceiver.kt new file mode 100644 index 00000000000..4ebf32eab9b --- /dev/null +++ b/idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty_sameClassNestedReceiver.kt @@ -0,0 +1,10 @@ +// WITH_RUNTIME +// PROBLEM: none + +fun test() { + Foo().apply { + Foo().run { + this@apply.isB = true + } + } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty_sameNameJavaProperty.1.java b/idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty_sameNameJavaProperty.1.java new file mode 100644 index 00000000000..0ec915aca79 --- /dev/null +++ b/idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty_sameNameJavaProperty.1.java @@ -0,0 +1,11 @@ +public class Foo { + private boolean isB; + + public boolean isB() { + return isB; + } + + public void setB(boolean b) { + isB = b; + } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty_sameNameJavaProperty.kt b/idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty_sameNameJavaProperty.kt new file mode 100644 index 00000000000..0781fd8c187 --- /dev/null +++ b/idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty_sameNameJavaProperty.kt @@ -0,0 +1,7 @@ +// WITH_RUNTIME + +fun test() { + Foo().apply { + this.isB = true + } +} diff --git a/idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty_sameNameJavaProperty.kt.after b/idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty_sameNameJavaProperty.kt.after new file mode 100644 index 00000000000..4c6c231f53b --- /dev/null +++ b/idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty_sameNameJavaProperty.kt.after @@ -0,0 +1,7 @@ +// WITH_RUNTIME + +fun test() { + Foo().apply { + isB = true + } +} diff --git a/idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty_sameNameVariable.1.java b/idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty_sameNameVariable.1.java new file mode 100644 index 00000000000..0ec915aca79 --- /dev/null +++ b/idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty_sameNameVariable.1.java @@ -0,0 +1,11 @@ +public class Foo { + private boolean isB; + + public boolean isB() { + return isB; + } + + public void setB(boolean b) { + isB = b; + } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty_sameNameVariable.kt b/idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty_sameNameVariable.kt new file mode 100644 index 00000000000..2926a6f04e8 --- /dev/null +++ b/idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty_sameNameVariable.kt @@ -0,0 +1,11 @@ +// WITH_RUNTIME +// PROBLEM: none + +fun test() { + + val isB = true + + Foo().apply { + this.isB = true + } +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java index fa328b3f935..cdae52a8182 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java @@ -1629,6 +1629,31 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest { runTest("idea/testData/inspectionsLocal/explicitThis/propertyReference.kt"); } + @TestMetadata("syntheticJavaProperty.kt") + public void testSyntheticJavaProperty() throws Exception { + runTest("idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty.kt"); + } + + @TestMetadata("syntheticJavaProperty_nestedReceiver.kt") + public void testSyntheticJavaProperty_nestedReceiver() throws Exception { + runTest("idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty_nestedReceiver.kt"); + } + + @TestMetadata("syntheticJavaProperty_sameClassNestedReceiver.kt") + public void testSyntheticJavaProperty_sameClassNestedReceiver() throws Exception { + runTest("idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty_sameClassNestedReceiver.kt"); + } + + @TestMetadata("syntheticJavaProperty_sameNameJavaProperty.kt") + public void testSyntheticJavaProperty_sameNameJavaProperty() throws Exception { + runTest("idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty_sameNameJavaProperty.kt"); + } + + @TestMetadata("syntheticJavaProperty_sameNameVariable.kt") + public void testSyntheticJavaProperty_sameNameVariable() throws Exception { + runTest("idea/testData/inspectionsLocal/explicitThis/syntheticJavaProperty_sameNameVariable.kt"); + } + @TestMetadata("variableWithSameName.kt") public void testVariableWithSameName() throws Exception { runTest("idea/testData/inspectionsLocal/explicitThis/variableWithSameName.kt");