Skip to content

Commit

Permalink
Merge pull request #218 from amosproj/Feature/208-Historical-data-tab
Browse files Browse the repository at this point in the history
Feature/208 historical data tab
  • Loading branch information
QW3RAT authored Jan 31, 2024
2 parents cb29d62 + d4ce5d4 commit 001377b
Show file tree
Hide file tree
Showing 5 changed files with 184 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.amos.pitmutationmate.pitmutationmate.reporting.XMLParser
import com.intellij.openapi.components.Service
import com.intellij.openapi.components.service
import com.intellij.openapi.project.Project
import java.io.File
import kotlin.io.path.exists

@Service(Service.Level.PROJECT)
Expand All @@ -30,4 +31,39 @@ class MutationResultService(private val project: Project) {
lastMutationResult = getMutationResult()
return lastMutationResult
}

fun getHistoricMutationResults(): XMLParser.ResultData {
val maxNumberOfRecentReportsToLookUp = 3
val directory = project.service<ReportPathGeneratorService>().getArchivePath().toFile()

return getHistoricMutationResults(maxNumberOfRecentReportsToLookUp, directory)
}

private fun getHistoricMutationResults(maxNumberOfRecentReportsToLookUp: Int, directory: File): XMLParser.ResultData {
val result: XMLParser.ResultData = XMLParser.ResultData()

if (directory.exists() && directory.isDirectory) {
val parser = XMLParser()
val files = directory.listFiles()

val sortedFiles = files?.sortedByDescending { it.lastModified() }
val mostRecentFiles = sortedFiles?.take(maxNumberOfRecentReportsToLookUp)

if (mostRecentFiles != null) {
for (file in mostRecentFiles) {
val service = project.service<ReportPathGeneratorService>()
val mutationReportPath = service.getMutationInformationPath(file.path)
val coverageReportPath = service.getCoverageInformationPath(file.path)

if (mutationReportPath.exists() && coverageReportPath.exists()) {
val resultData = parser.loadResultsFromXmlReport(mutationReportPath.toString(), coverageReportPath.toString())
result.coverageReports.addAll(resultData.coverageReports)
result.packageReports.addAll(resultData.packageReports)
result.totalResult = resultData.totalResult
}
}
}
}
return result
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.project.Project
import java.nio.file.Files
import java.nio.file.Path
import kotlin.io.path.exists

/**
* A service that generates the path to the report directory.
Expand Down Expand Up @@ -79,6 +78,14 @@ class ReportPathGeneratorService(private val project: Project) {
return Path.of("$path/coverageInformation.xml")
}

fun getMutationInformationPath(path: String): Path {
return Path.of("$path/coverageInformation.xml")
}

fun getCoverageInformationPath(path: String): Path {
return Path.of("$path/coverageInformation.xml")
}

fun setBuildType(buildType: String?) {
this.buildType = buildType
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import com.amos.pitmutationmate.pitmutationmate.services.PluginCheckerService
import com.amos.pitmutationmate.pitmutationmate.visualization.ConfigurationErrorPanel
import com.amos.pitmutationmate.pitmutationmate.visualization.PiTestClassReport
import com.amos.pitmutationmate.pitmutationmate.visualization.PiTestReports
import com.amos.pitmutationmate.pitmutationmate.visualization.treestructure.TreeStructureTable
import com.amos.pitmutationmate.pitmutationmate.visualization.treestructure.HistoricalDataTable
import com.amos.pitmutationmate.pitmutationmate.visualization.treestructure.PackageBreakdownTable
import com.amos.pitmutationmate.pitmutationmate.visualization.treestructure.TreeTableModel
import com.intellij.openapi.components.service
import com.intellij.openapi.project.DumbAware
Expand Down Expand Up @@ -48,11 +49,12 @@ internal class ToolWindowFactory : ToolWindowFactory, DumbAware {
toolWindow.contentManager.removeAllContents(true)

val coverageReport = ContentFactory.getInstance().createContent(PiTestReports(), PiTestReports.TITLE, false)
val table =
ContentFactory.getInstance().createContent(TreeStructureTable(project), TreeStructureTable.TITLE, false)
val packageBreakdownTable = ContentFactory.getInstance().createContent(PackageBreakdownTable(project), PackageBreakdownTable.TITLE, false)
val historicalDataTable = ContentFactory.getInstance().createContent(HistoricalDataTable(project), HistoricalDataTable.TITLE, false)

toolWindow.contentManager.addContent(coverageReport)
toolWindow.contentManager.addContent(table)
toolWindow.contentManager.addContent(packageBreakdownTable)
toolWindow.contentManager.addContent(historicalDataTable)

val reportGeneratorService = project.service<MutationResultService>()
val newCoverageReports = reportGeneratorService.updateLastMutationResult()
Expand All @@ -79,15 +81,25 @@ internal class ToolWindowFactory : ToolWindowFactory, DumbAware {
}
}

val treeStructureContent = toolWindow.contentManager.findContent(TreeStructureTable.TITLE) ?: return
val treeStructureContent = toolWindow.contentManager.findContent(PackageBreakdownTable.TITLE) ?: return
val treeStructure = treeStructureContent.component

if (treeStructure is TreeStructureTable) {
if (treeStructure is PackageBreakdownTable) {
ToolWindowManager.getInstance(project).invokeLater {
val newRootNode = treeStructure.createDataStructure(project)
(treeStructure.treeTable.tableModel as TreeTableModel).updateData(newRootNode)
}
}

val historicalDataContent = toolWindow.contentManager.findContent(HistoricalDataTable.TITLE) ?: return
val historicalData = historicalDataContent.component

if (historicalData is HistoricalDataTable) {
ToolWindowManager.getInstance(project).invokeLater {
val newRootNode = historicalData.createDataStructure(project)
(historicalData.treeTable.tableModel as TreeTableModel).updateData(newRootNode)
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
// SPDX-FileCopyrightText: 2023 2023
//
// SPDX-License-Identifier: MIT

package com.amos.pitmutationmate.pitmutationmate.visualization.treestructure

import com.amos.pitmutationmate.pitmutationmate.reporting.XMLParser
import com.amos.pitmutationmate.pitmutationmate.services.MutationResultService
import com.intellij.openapi.components.service
import com.intellij.openapi.project.Project
import com.intellij.ui.treeStructure.treetable.TreeTable
import java.awt.GridLayout
import javax.swing.JPanel
import javax.swing.JScrollPane

class HistoricalDataTable(project: Project) : JPanel() {

private var rootNode: DataNode = DataNode(
"",
"",
"",
"",
"",
mutableListOf()
)
private var alreadyFoundData: MutableList<String> = mutableListOf()
var treeTable: TreeTable
companion object {
const val ID = "HistoricalData"
const val TITLE = "Historical Data"
}

init {
layout = GridLayout(0, 1)
val treeTableModel = TreeTableModel(createDataStructure(project))
treeTable = TreeTable(treeTableModel)
treeTable.setRootVisible(true)
treeTable.apply {
tree.apply {
showsRootHandles = true
isRootVisible = true
}
}
treeTable.tableHeader.reorderingAllowed = false
treeTable.tableHeader.resizingAllowed = true
this.add(JScrollPane(treeTable))
setSize(1000, 800)
}

fun createDataStructure(project: Project): DataNode {
deleteTree(rootNode)
alreadyFoundData.clear()

val bundledReports = project.service<MutationResultService>().getHistoricMutationResults()
val coverageReports = bundledReports.coverageReports
val packageReports = bundledReports.packageReports
val totalReport = bundledReports.totalResult

rootNode = if (totalReport != null) {
createReportDataNode("All", totalReport, mutableListOf())
} else {
DataNode("All", "", "", "", "", mutableListOf())
}
// iterate over reports and add them to data node structure
for (report in coverageReports) {
var packageNode = rootNode.children.find { it.name == report.packageName }
if (packageNode != null) {
if (!checkIfAlreadyFound(report.fileName)) {
packageNode.children.add(createReportDataNode(report.fileName, report))
}
} else {
val packageReport = packageReports.find { it.packageName == report.packageName }
if (packageReport != null) {
if (!checkIfAlreadyFound(packageReport.packageName)) {
packageNode = createReportDataNode(packageReport.packageName, packageReport)
if (!checkIfAlreadyFound(report.fileName)) {
packageNode.children.add(createReportDataNode(report.fileName, report))
}
rootNode.children.add(packageNode)
}
}
}
}

return rootNode
}

private fun deleteTree(rootNode: DataNode) {
if (rootNode.children.isEmpty()) {
return
}
for (child in rootNode.children) {
deleteTree(child)
}
rootNode.children.removeAll(rootNode.children)
}

private fun createReportDataNode(
name: String,
report: XMLParser.CoverageReport,
children: MutableList<DataNode> = mutableListOf()
): DataNode {
return DataNode(
name,
report.numberOfClasses.toString(),
report.lineCoverageTextRatio,
report.mutationCoverageTextRatio,
report.testStrengthTextRatio,
children
)
}

private fun checkIfAlreadyFound(name: String): Boolean {
return if (!alreadyFoundData.contains(name)) {
alreadyFoundData.add(name)
false
} else {
true
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import java.awt.GridLayout
import javax.swing.JPanel
import javax.swing.JScrollPane

class TreeStructureTable(project: Project) : JPanel() {
class PackageBreakdownTable(project: Project) : JPanel() {

private var rootNode: DataNode = DataNode(
"",
Expand Down

0 comments on commit 001377b

Please sign in to comment.