Skip to content

Commit

Permalink
Add info when no mcc metric was found #3685
Browse files Browse the repository at this point in the history
  • Loading branch information
Nereboss committed Sep 10, 2024
1 parent d6f07d0 commit 1e6fefd
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import de.maibornwolff.codecharta.model.AttributeType
import de.maibornwolff.codecharta.model.BlacklistItem
import de.maibornwolff.codecharta.model.Edge
import de.maibornwolff.codecharta.model.MutableNode
import de.maibornwolff.codecharta.model.Node
import de.maibornwolff.codecharta.model.Project
import de.maibornwolff.codecharta.model.ProjectBuilder

Expand All @@ -13,6 +14,12 @@ class MetricRenamer(
private val newName: String = "complexity"
) {
fun rename(): Project {

if (!doesProjectContainMCC(project)) {
println("INFO: Project has not been altered as no MCC metric was found!")
return project
}

val updatedRoot = renameMCCRecursivelyInNodes(project.rootNode.toMutableNode())
val updatedAttributeTypes = updatedAttributeTypes(project.attributeTypes)
val updatedAttributesDescriptors = updatedAttributeDescriptors(project.attributeDescriptors)
Expand Down Expand Up @@ -81,4 +88,28 @@ class MetricRenamer(
private fun copyBlacklist(): MutableList<BlacklistItem> {
return project.blacklist.toMutableList()
}

private fun doesProjectContainMCC(project: Project): Boolean {
return doesMccExistInNodes(project.rootNode) ||
doesMccExistInAttributeTypes(project.attributeTypes) ||
doesMccExistInAttributeDescriptors(project.attributeDescriptors)
}

private fun doesMccExistInNodes(node: Node): Boolean {
if (node.attributes.containsKey("mcc")) return true

if (node.children.isEmpty()) return false

val resultOfChildNodes = node.children.any { doesMccExistInNodes(it) }
return resultOfChildNodes
}

private fun doesMccExistInAttributeTypes(attributeTypes: Map<String, MutableMap<String, AttributeType>>): Boolean {
val nodeAttributeTypes = attributeTypes["nodes"] ?: return false
return nodeAttributeTypes.containsKey("mcc")
}

private fun doesMccExistInAttributeDescriptors(attributeDescriptors: Map<String, AttributeDescriptor>): Boolean {
return attributeDescriptors.containsKey("mcc")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import de.maibornwolff.codecharta.serialization.ProjectDeserializer
import org.assertj.core.api.Assertions
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.PrintStream

class MetricRenamerTest {
private lateinit var attributeDescriptorsProject: Project
Expand All @@ -28,19 +30,24 @@ class MetricRenamerTest {

@Test
fun `should rename all occurrences of mcc in the projects nodes to complexity when the project contains this metric`() {
val bufferedReader = File("src/test/resources/sample_project.cc.json").bufferedReader()
//given
val bufferedReader = File("src/test/resources/merged_project.cc.json").bufferedReader()
val sampleProject = ProjectDeserializer.deserializeProject(bufferedReader)

//when
val result = MetricRenamer(sampleProject).rename()

//then
Assertions.assertThat(doesAttributeExistInNode(result.rootNode.toMutableNode(), "mcc")).isFalse()
Assertions.assertThat(doesAttributeExistInNode(result.rootNode.toMutableNode(), "complexity")).isTrue()
}

@Test
fun `should rename all occurrences of mcc in the attributeDescriptors and attributeTypes when it is present`() {
//when
val result = MetricRenamer(attributeDescriptorsProject).rename()

//then
val attributeTypeNodes = result.attributeTypes["nodes"]!!
Assertions.assertThat(attributeTypeNodes.containsKey("mcc")).isFalse()
Assertions.assertThat(attributeTypeNodes.containsKey("complexity")).isTrue()
Expand All @@ -52,8 +59,10 @@ class MetricRenamerTest {

@Test
fun `should not rename other metrics that contain mcc as part of their name`() {
//when
val result = MetricRenamer(attributeDescriptorsProject).rename()

//then
Assertions.assertThat(doesAttributeExistInNode(result.rootNode.toMutableNode(), "mcc")).isFalse()
Assertions.assertThat(doesAttributeExistInNode(result.rootNode.toMutableNode(), "ymcc")).isTrue()

Expand All @@ -67,16 +76,30 @@ class MetricRenamerTest {

@Test
fun `should rename mcc to sonar_complexity when specified`() {
//when
val result = MetricRenamer(attributeDescriptorsProject, "sonar_complexity").rename()

//then
Assertions.assertThat(doesAttributeExistInNode(result.rootNode.toMutableNode(), "mcc")).isFalse()
Assertions.assertThat(doesAttributeExistInNode(result.rootNode.toMutableNode(), "complexity")).isFalse()
Assertions.assertThat(doesAttributeExistInNode(result.rootNode.toMutableNode(), "sonar_complexity")).isTrue()
}

@Test //TODO: revisit
fun `should do something if the input file did not contain mcc metric`() {
Assertions.assertThat(true).isFalse()
@Test
fun `should print info and not alter file when the input file did not contain mcc metric`() {
//given
val outContent = ByteArrayOutputStream()
System.setOut(PrintStream(outContent))

val bufferedReader = File("src/test/resources/sample_project.cc.json").bufferedReader()
val sampleProject = ProjectDeserializer.deserializeProject(bufferedReader)

//when
val result = MetricRenamer(sampleProject).rename()

//then
Assertions.assertThat(outContent.toString()).contains("INFO: Project has not been altered as no MCC metric was found!")
Assertions.assertThat(result).isEqualTo(sampleProject)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class NodeRemoverTest {

@Test
fun `Should replicate project when non existent path specified`() {
// when
// when
val subProjectExtractor = NodeRemover(sampleProject)
val result = subProjectExtractor.remove(arrayOf("/root/somethig"))

Expand All @@ -34,7 +34,7 @@ class NodeRemoverTest {

@Test
fun `Should keep non affected nodes when removal is specified`() {
// when
// when
val subProjectExtractor = NodeRemover(sampleProject)
val result = subProjectExtractor.remove(arrayOf("/root/src/main"))
val testFolder = result.rootNode.children.first().children.first()
Expand All @@ -45,7 +45,7 @@ class NodeRemoverTest {

@Test
fun `Should remove correct nodes when single node is specified for removal`() {
// when
// when
val subProjectExtractor = NodeRemover(sampleProject)
val result = subProjectExtractor.remove(arrayOf("/root/src/main"))
val srcContent = result.rootNode.children.first().children
Expand All @@ -61,7 +61,7 @@ class NodeRemoverTest {

@Test
fun `Should remove correct nodes when multiple nodes are specified for removal`() {
// when
// when
val subProjectExtractor = NodeRemover(sampleProject)
val result = subProjectExtractor.remove(arrayOf("/root/src/main/file1.java", "root/src/folder3/"))
val srcContent = result.rootNode.children.first().children
Expand All @@ -82,7 +82,7 @@ class NodeRemoverTest {

@Test
fun `Should remove affected edges when removal is specified`() {
// when
// when
val subProjectExtractor = NodeRemover(sampleProject)
val result = subProjectExtractor.remove(arrayOf("/root/foo"))

Expand All @@ -102,7 +102,8 @@ class NodeRemoverTest {
}

@Test
fun `Should remove affected edges when multiple removals are specified`() { // given
fun `Should remove affected edges when multiple removals are specified`() {
// given
val toExclude = arrayOf("/root/foo/file1", "root/else/")
val shouldBeExcluded = listOf("/root/foo/file1", "root/else/file1", "root/else")

Expand All @@ -126,7 +127,7 @@ class NodeRemoverTest {

@Test
fun `Should remove correct blacklist items when node removal specified`() {
// when
// when
val subProjectExtractor = NodeRemover(sampleProject)
val result = subProjectExtractor.remove(arrayOf("/root/foo"))

Expand All @@ -139,7 +140,8 @@ class NodeRemoverTest {
}

@Test
fun `Should keep attributes when only node removal specified`() { // given
fun `Should keep attributes when only node removal specified`() {
// given
val input = InputStreamReader(this.javaClass.classLoader.getResourceAsStream(DESCRIPTOR_TEST_PATH)!!)
val attributeProject = ProjectDeserializer.deserializeProject(input)

Expand All @@ -151,7 +153,8 @@ class NodeRemoverTest {
}

@Test
fun `Should remove unused attributeDescriptors when nodes are removed`() { // given
fun `Should remove unused attributeDescriptors when nodes are removed`() {
// given
val input = InputStreamReader(this.javaClass.classLoader.getResourceAsStream(DESCRIPTOR_TEST_PATH)!!)
val attributeProject = ProjectDeserializer.deserializeProject(input)

Expand All @@ -165,7 +168,8 @@ class NodeRemoverTest {
}

@Test
fun `Should correctly remove node when another node in a different subfolder has the same name`() { // given
fun `Should correctly remove node when another node in a different subfolder has the same name`() {
// given
val bufferedReader = File("src/test/resources/merged_project.cc.json").bufferedReader()
val mergedProject = ProjectDeserializer.deserializeProject(bufferedReader)
val subProjectExtractor = NodeRemover(mergedProject)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ class StructureModifierTest {
@Test
fun `should rename mcc to complexity when rename flag is specified`() {
//when
val cliResult = executeForOutput("", arrayOf("src/test/resources/sample_project.cc.json", "--rename-mcc"))
val cliResult = executeForOutput("", arrayOf("src/test/resources/merged_project.cc.json", "--rename-mcc"))

//then
assertThat(cliResult).doesNotContain("mcc")
Expand All @@ -251,7 +251,7 @@ class StructureModifierTest {
@Test
fun `should rename mcc to sonar_complexity when rename flag is specified with sonar option`() {
//when
val cliResult = executeForOutput("", arrayOf("src/test/resources/sample_project.cc.json", "--rename-mcc=sonar"))
val cliResult = executeForOutput("", arrayOf("src/test/resources/merged_project.cc.json", "--rename-mcc=sonar"))

//then
assertThat(cliResult).doesNotContain("mcc")
Expand All @@ -264,7 +264,7 @@ class StructureModifierTest {
System.setErr(PrintStream(errContent))

// when
executeForOutput("", arrayOf("src/test/resources/sample_project.cc.json", "--rename-mcc=invalid"))
executeForOutput("", arrayOf("src/test/resources/merged_project.cc.json", "--rename-mcc=invalid"))

// then
assertThat(errContent.toString()).contains("Invalid value for rename flag, stopping execution...")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,14 @@
"name": "file1.java",
"type": "File",
"attributes": {
"nloc": 80.0,
"mcc": 1
"nloc": 80.0
}
},
{
"name": "file2.java",
"type": "File",
"attributes": {
"nloc": 80.0,
"mcc": 2
"nloc": 80.0
}
}
]
Expand All @@ -40,8 +38,7 @@
"name": "otherFile.java",
"type": "File",
"attributes": {
"nloc": 80.0,
"mcc": 3
"nloc": 80.0
}
}
]
Expand All @@ -54,8 +51,7 @@
"name": "otherFile2.java",
"type": "File",
"attributes": {
"nloc": 80.0,
"mcc": 80.0
"nloc": 80.0
}
}
]
Expand Down

0 comments on commit 1e6fefd

Please sign in to comment.