Inline function: process usages in children-first order

This commit is contained in:
Mikhail Glukhikh
2017-03-30 15:13:23 +03:00
parent fc0bf47067
commit 091e875551
2 changed files with 28 additions and 5 deletions
@@ -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(
usages: Collection<KtSimpleNameExpression>,
targetPsiElement: PsiElement,
@@ -98,8 +121,8 @@ fun UsageReplacementStrategy.replaceUsages(
val targetDeclaration = targetPsiElement as? KtNamedDeclaration
// NB: reversed order is better in case of composition like sqr(sqr(x))
for (usage in usages.reversed()) {
val usagesChildrenFirst = usages.sortChildrenFirst()
for (usage in usagesChildrenFirst) {
try {
if (!usage.isValid) {
invalidUsagesFound = true
@@ -1,8 +1,8 @@
class Point(val x: Double, val y: Double) {
// After sqr inlining, only first usage of sqr is replaced
fun distance(other: Point): Double {
val x1 = y - other.y
val x2 = x - other.x
return Math.sqrt(x2 * x2 + x1 * x1)
val x1 = x - other.x
val x2 = y - other.y
return Math.sqrt(x1 * x1 + x2 * x2)
}
}