diff --git a/idea/src/org/jetbrains/kotlin/idea/slicer/Slicer.kt b/idea/src/org/jetbrains/kotlin/idea/slicer/Slicer.kt index a1690991e71..75d18e5ccae 100644 --- a/idea/src/org/jetbrains/kotlin/idea/slicer/Slicer.kt +++ b/idea/src/org/jetbrains/kotlin/idea/slicer/Slicer.kt @@ -21,6 +21,7 @@ import com.intellij.codeInsight.highlighting.ReadWriteAccessDetector.Access import com.intellij.psi.PsiElement import com.intellij.psi.search.LocalSearchScope import com.intellij.psi.search.SearchScope +import com.intellij.psi.search.searches.ReferencesSearch import com.intellij.slicer.SliceUsage import com.intellij.usageView.UsageInfo import com.intellij.util.Processor @@ -48,6 +49,7 @@ import org.jetbrains.kotlin.idea.findUsages.KotlinPropertyFindUsagesOptions import org.jetbrains.kotlin.idea.findUsages.processAllExactUsages import org.jetbrains.kotlin.idea.refactoring.changeSignature.KotlinValVar import org.jetbrains.kotlin.idea.refactoring.changeSignature.toValVar +import org.jetbrains.kotlin.idea.references.KtPropertyDelegationMethodsReference import org.jetbrains.kotlin.idea.references.ReferenceAccess import org.jetbrains.kotlin.idea.references.readWriteAccessWithFullExpression import org.jetbrains.kotlin.idea.search.declarationsSearch.HierarchySearchRequest @@ -63,6 +65,7 @@ import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver import org.jetbrains.kotlin.resolve.source.getPsi +import org.jetbrains.kotlin.util.OperatorNameConventions import java.util.* private fun KtDeclaration.processHierarchyDownward(scope: SearchScope, processor: KtDeclaration.() -> Unit) { @@ -230,6 +233,16 @@ class InflowSlicer( return } + if (function is KtNamedFunction + && function.name == OperatorNameConventions.SET_VALUE.asString() + && function.hasModifier(KtTokens.OPERATOR_KEYWORD)) { + + ReferencesSearch + .search(function, parentUsage.scope.toSearchScope()) + .filterIsInstance() + .forEach { (it.element?.parent as? KtProperty)?.processPropertyAssignments() } + } + val parameterDescriptor = analyze()[BindingContext.VALUE_PARAMETER, this] ?: return (function as? KtFunction)?.processCalls(parentUsage.scope.toSearchScope()) body@ { diff --git a/idea/testData/slicer/inflow/settersViaDelegateForQualifiedRef.kt b/idea/testData/slicer/inflow/settersViaDelegateForQualifiedRef.kt new file mode 100644 index 00000000000..e688a13516f --- /dev/null +++ b/idea/testData/slicer/inflow/settersViaDelegateForQualifiedRef.kt @@ -0,0 +1,26 @@ +// FLOW: IN + +class Delegate { + private var _value: String = "" + operator fun getValue(thisRef: Any?, property: KProperty<*>) = _value + operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) { + _value = value + } +} + +class AClass(name1: String){ + var name by Delegate() + init { + name = name1 + } + + fun uses(){ + name = "bye" + println("Now my name is '$name'") + } +} + +fun main(args: Array) { + val a = AClass("hello") + println("My name is '${a.name}'") +} \ No newline at end of file diff --git a/idea/testData/slicer/inflow/settersViaDelegateForQualifiedRef.results.txt b/idea/testData/slicer/inflow/settersViaDelegateForQualifiedRef.results.txt new file mode 100644 index 00000000000..b0be23fe512 --- /dev/null +++ b/idea/testData/slicer/inflow/settersViaDelegateForQualifiedRef.results.txt @@ -0,0 +1,12 @@ +25 println("My name is '${a.name}'") +12 var name by Delegate() +5 operator fun getValue(thisRef: Any?, property: KProperty<*>) = _value +5 operator fun getValue(thisRef: Any?, property: KProperty<*>) = _value +4 private var _value: String = "" +4 private var _value: String = "" +7 _value = value +6 operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) { +14 name = name1 +11 class AClass(name1: String){ +24 val a = AClass("hello") +18 name = "bye" diff --git a/idea/testData/slicer/inflow/settersViaDelegateForSimpleRef.kt b/idea/testData/slicer/inflow/settersViaDelegateForSimpleRef.kt new file mode 100644 index 00000000000..f59e8b6a245 --- /dev/null +++ b/idea/testData/slicer/inflow/settersViaDelegateForSimpleRef.kt @@ -0,0 +1,26 @@ +// FLOW: IN + +class Delegate { + private var _value: String = "" + operator fun getValue(thisRef: Any?, property: KProperty<*>) = _value + operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) { + _value = value + } +} + +class AClass(name1: String){ + var name by Delegate() + init { + name = name1 + } + + fun uses(){ + name = "bye" + println("Now my name is '$name'") + } +} + +fun main(args: Array) { + val a = AClass("hello") + println("My name is '${a.name}'") +} \ No newline at end of file diff --git a/idea/testData/slicer/inflow/settersViaDelegateForSimpleRef.results.txt b/idea/testData/slicer/inflow/settersViaDelegateForSimpleRef.results.txt new file mode 100644 index 00000000000..e6a4390b677 --- /dev/null +++ b/idea/testData/slicer/inflow/settersViaDelegateForSimpleRef.results.txt @@ -0,0 +1,12 @@ +19 println("Now my name is '$name'") +12 var name by Delegate() +5 operator fun getValue(thisRef: Any?, property: KProperty<*>) = _value +5 operator fun getValue(thisRef: Any?, property: KProperty<*>) = _value +4 private var _value: String = "" +4 private var _value: String = "" +7 _value = value +6 operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) { +14 name = name1 +11 class AClass(name1: String){ +24 val a = AClass("hello") +18 name = "bye" diff --git a/idea/tests/org/jetbrains/kotlin/idea/slicer/SlicerTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/slicer/SlicerTestGenerated.java index de0237155b3..457bf4c12f1 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/slicer/SlicerTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/slicer/SlicerTestGenerated.java @@ -306,6 +306,18 @@ public class SlicerTestGenerated extends AbstractSlicerTest { doTest(fileName); } + @TestMetadata("inflow/settersViaDelegateForQualifiedRef.kt") + public void testInflow_SettersViaDelegateForQualifiedRef() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/settersViaDelegateForQualifiedRef.kt"); + doTest(fileName); + } + + @TestMetadata("inflow/settersViaDelegateForSimpleRef.kt") + public void testInflow_SettersViaDelegateForSimpleRef() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/settersViaDelegateForSimpleRef.kt"); + doTest(fileName); + } + @TestMetadata("inflow/topLevelVal.kt") public void testInflow_TopLevelVal() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/topLevelVal.kt");