Inline function: process usages in children-first order
This commit is contained in:
@@ -81,6 +81,29 @@ private fun UsageReplacementStrategy.doRefactoringInside(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sort them in the following order: children first, parents second
|
||||||
|
// NB: this is topological sort implementation
|
||||||
|
private fun Collection<KtSimpleNameExpression>.sortChildrenFirst(): List<KtSimpleNameExpression> {
|
||||||
|
val usagesSet = toSet()
|
||||||
|
val result = mutableListOf<KtSimpleNameExpression>()
|
||||||
|
val visited = hashSetOf<KtSimpleNameExpression>()
|
||||||
|
|
||||||
|
fun visit(expr: KtSimpleNameExpression) {
|
||||||
|
if (expr in visited) return
|
||||||
|
visited += expr
|
||||||
|
|
||||||
|
expr.parent.forEachDescendantOfType<KtSimpleNameExpression> {
|
||||||
|
if (it != expr && it in usagesSet) visit(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
result += expr
|
||||||
|
}
|
||||||
|
|
||||||
|
this.forEach(::visit)
|
||||||
|
assert(result.size == this.size)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
fun UsageReplacementStrategy.replaceUsages(
|
fun UsageReplacementStrategy.replaceUsages(
|
||||||
usages: Collection<KtSimpleNameExpression>,
|
usages: Collection<KtSimpleNameExpression>,
|
||||||
targetPsiElement: PsiElement,
|
targetPsiElement: PsiElement,
|
||||||
@@ -98,8 +121,8 @@ fun UsageReplacementStrategy.replaceUsages(
|
|||||||
|
|
||||||
val targetDeclaration = targetPsiElement as? KtNamedDeclaration
|
val targetDeclaration = targetPsiElement as? KtNamedDeclaration
|
||||||
|
|
||||||
// NB: reversed order is better in case of composition like sqr(sqr(x))
|
val usagesChildrenFirst = usages.sortChildrenFirst()
|
||||||
for (usage in usages.reversed()) {
|
for (usage in usagesChildrenFirst) {
|
||||||
try {
|
try {
|
||||||
if (!usage.isValid) {
|
if (!usage.isValid) {
|
||||||
invalidUsagesFound = true
|
invalidUsagesFound = true
|
||||||
|
|||||||
+3
-3
@@ -1,8 +1,8 @@
|
|||||||
class Point(val x: Double, val y: Double) {
|
class Point(val x: Double, val y: Double) {
|
||||||
// After sqr inlining, only first usage of sqr is replaced
|
// After sqr inlining, only first usage of sqr is replaced
|
||||||
fun distance(other: Point): Double {
|
fun distance(other: Point): Double {
|
||||||
val x1 = y - other.y
|
val x1 = x - other.x
|
||||||
val x2 = x - other.x
|
val x2 = y - other.y
|
||||||
return Math.sqrt(x2 * x2 + x1 * x1)
|
return Math.sqrt(x1 * x1 + x2 * x2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user