Skip to content

Commit

Permalink
refactor: 💡 avoid using self-param type parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
Xanonymous-GitHub committed Jul 20, 2024
1 parent 69651f0 commit d33f3b5
Show file tree
Hide file tree
Showing 6 changed files with 27 additions and 35 deletions.
2 changes: 1 addition & 1 deletion core/src/main/kotlin/tw/xcc/gumtree/api/tree/Comparable.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package tw.xcc.gumtree.api.tree
/**
* Comparable defines the basic methods for comparing two [Tree]s.
* */
internal interface Comparable<T> where T : Tree<T>, T : Any {
internal interface Comparable<T> where T : Tree, T : Any {
/**
* To compare whether this tree is strictly equal to another tree.
* All the node's properties must be equal.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package tw.xcc.gumtree.api.tree
/**
* Traversable defines the basic methods for traversing a [Tree].
* */
internal interface Traversable<out E> where E : Tree<E>, E : Any {
internal interface Traversable<out E> where E : Tree, E : Any {
/**
* Traverse the tree in pre-order. This means that the current node is visited before its children.
* */
Expand Down
10 changes: 5 additions & 5 deletions core/src/main/kotlin/tw/xcc/gumtree/api/tree/Tree.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ package tw.xcc.gumtree.api.tree
* A tree is a hierarchical structure that consists of nodes connected by edges.
* The number of children can be any non-negative integer.
* */
interface Tree<out T> where T : Tree<T>, T : Any {
interface Tree {
/**
* To check if the current node is a root node.
* */
Expand All @@ -24,15 +24,15 @@ interface Tree<out T> where T : Tree<T>, T : Any {
/**
* To get the child at the specified index.
* */
fun childAt(i: Int): T?
fun childAt(i: Int): Tree?

/**
* The children of the Tree.
* To get the children of the Tree.
* */
val children: List<T>
fun getChildren(): List<Tree>

/**
* To get the parent of the Tree.
* */
val parent: T?
fun getParent(): Tree?
}
30 changes: 14 additions & 16 deletions core/src/main/kotlin/tw/xcc/gumtree/model/BasicTree.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,19 @@ package tw.xcc.gumtree.model

import tw.xcc.gumtree.api.tree.Traversable
import tw.xcc.gumtree.api.tree.Tree
import tw.xcc.gumtree.helper.postOrdered
import tw.xcc.gumtree.helper.preOrdered
import java.util.concurrent.atomic.AtomicReference

/**
* The general thread-safe implementation of a tree structure.
* */
abstract class BasicTree<T> :
Tree<T>,
Traversable<T> where T : BasicTree<T> {
abstract class BasicTree<T> : Tree, Traversable<T> where T : BasicTree<T> {
protected abstract val self: T

protected abstract val traversalHelper: TraversalHelper<T>

private val _parent = AtomicReference<T?>()
final override val parent: T?
get() = synchronized(this) { _parent.get() }
private val parent = AtomicReference<T?>()

protected val childrenMap = AtomicReference(sortedMapOf<Int, T>())
final override val children: List<T>
get() = synchronized(this) { childrenMap.get().values.toList() }

val descendents: List<T> by lazy {
synchronized(this) {
Expand Down Expand Up @@ -49,21 +43,25 @@ abstract class BasicTree<T> :

fun setParentTo(parent: T?) {
synchronized(this) {
_parent.set(parent)
this.parent.set(parent)
}
}

final override fun getParent(): T? = synchronized(this) { parent.get() }

final override fun getChildren(): List<T> = synchronized(this) { childrenMap.get().values.toList() }

final override fun childAt(i: Int): T? = synchronized(this) { childrenMap.get()[i] }

final override fun childCount(): Int = synchronized(this) { childrenMap.get().size }
final override fun preOrdered(): List<T> = preOrdered(self)

final override fun isRoot(): Boolean = synchronized(this) { parent == null }
final override fun postOrdered(): List<T> = postOrdered(self)

final override fun isLeaf(): Boolean = synchronized(this) { childrenMap.get().isEmpty() }
final override fun childCount(): Int = synchronized(this) { childrenMap.get().size }

final override fun preOrdered(): List<T> = traversalHelper.preOrdered()
final override fun isRoot(): Boolean = synchronized(this) { parent.get() == null }

final override fun postOrdered(): List<T> = traversalHelper.postOrdered()
final override fun isLeaf(): Boolean = synchronized(this) { childrenMap.get().isEmpty() }

abstract fun similarityHashCode(): Int

Expand Down
5 changes: 1 addition & 4 deletions core/src/main/kotlin/tw/xcc/gumtree/model/GumTree.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ import java.util.concurrent.atomic.AtomicReference
class GumTree(
type: TreeType,
val label: String = EMPTY_LABEL
) : BasicTree<GumTree>(),
Comparable<GumTree> {
) : BasicTree<GumTree>(), Comparable<GumTree> {
private val compareHelper = CompareHelper(this)

var pos: Int = -1
Expand Down Expand Up @@ -66,8 +65,6 @@ class GumTree(
TODO("Not yet implemented")
}

override val traversalHelper = TraversalHelper(this)

override val self: GumTree
get() = this

Expand Down
13 changes: 5 additions & 8 deletions core/src/test/kotlin/BasicTreeTest.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import org.junit.jupiter.api.parallel.Execution
import org.junit.jupiter.api.parallel.ExecutionMode
import tw.xcc.gumtree.model.BasicTree
import tw.xcc.gumtree.model.TraversalHelper
import kotlin.test.BeforeTest
import kotlin.test.Test
import kotlin.test.assertContentEquals
Expand All @@ -20,13 +19,13 @@ internal class BasicTreeTest {

@Test
fun `test default parent`() {
val actualParent = givenTree.parent
val actualParent = givenTree.getParent()
assertEquals(null, actualParent)
}

@Test
fun `test default children`() {
val actualChildren = givenTree.children
val actualChildren = givenTree.getChildren()
assertContentEquals(emptyList(), actualChildren)
}

Expand All @@ -42,7 +41,7 @@ internal class BasicTreeTest {
val child2 = TestBasicTree()
givenTree.addChild(child1)
givenTree.addChild(child2)
val actualChildren = givenTree.children
val actualChildren = givenTree.getChildren()
assertContentEquals(listOf(child1, child2), actualChildren)
}

Expand All @@ -51,15 +50,15 @@ internal class BasicTreeTest {
val child1 = TestBasicTree()
val child2 = TestBasicTree()
givenTree.setChildrenTo(listOf(child1, child2))
val actualChildren = givenTree.children
val actualChildren = givenTree.getChildren()
assertContentEquals(listOf(child1, child2), actualChildren)
}

@Test
fun `test setParentTo`() {
val parent = TestBasicTree()
givenTree.setParentTo(parent)
val actualParent = givenTree.parent
val actualParent = givenTree.getParent()
assertEquals(parent, actualParent)
}

Expand Down Expand Up @@ -116,8 +115,6 @@ internal class BasicTreeTest {
private class TestBasicTree : BasicTree<TestBasicTree>() {
override val self: TestBasicTree
get() = this
override val traversalHelper: TraversalHelper<TestBasicTree>
get() = TraversalHelper(this)

override fun similarityHashCode(): Int = throw NotImplementedError()

Expand Down

0 comments on commit d33f3b5

Please sign in to comment.