Skip to content

Commit

Permalink
Feature/144 enable to have a complete folder as scope (#170)
Browse files Browse the repository at this point in the history
* enable contextmenuaction on folders

Signed-off-by: Tim Herzig <tim.herzig@hotmail.com>

* add functionality to run on all classes in dir + subdirs

Signed-off-by: Tim Herzig <tim.herzig@hotmail.com>

* edit visualization to easier show where results came from

Signed-off-by: Tim Herzig <tim.herzig@hotmail.com>

* change pipeline to call updateAndExecuteRunConfig once with all classes

Signed-off-by: Tim Herzig <tim.herzig@hotmail.com>

* lint correction

Signed-off-by: Tim Herzig <tim.herzig@hotmail.com>

* restrict context menu to only main subbranches

Signed-off-by: Tim Herzig <tim.herzig@hotmail.com>

* Update pitmutationmate/src/main/kotlin/com/amos/pitmutationmate/pitmutationmate/actions/ContextMenuAction.kt

Co-authored-by: Lennart Heimbs <37455726+lheimbs@users.noreply.github.com>

* modify rules for which directories can be executed
exclude files ending in Test for the pitest run

Signed-off-by: Tim Herzig <tim.herzig@hotmail.com>

* lint correction

Signed-off-by: Tim Herzig <tim.herzig@hotmail.com>

---------

Signed-off-by: Tim Herzig <tim.herzig@hotmail.com>
Co-authored-by: Lennart Heimbs <37455726+lheimbs@users.noreply.github.com>
  • Loading branch information
timherzig and lheimbs authored Jan 17, 2024
1 parent 8b4501e commit 6feaf4e
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 32 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: 2023 Brianne Oberson <brianne.oberson@gmail.com>
// SPDX-FileCopyrightText: 2023 Brianne Oberson <brianne.oberson@gmail.com>, Tim Herzig <tim.herzig@hotmail.com>

package com.amos.pitmutationmate.pitmutationmate.actions

Expand All @@ -9,49 +9,102 @@ import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.openapi.components.service
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.LocalFileSystem
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiClassOwner
import com.intellij.psi.PsiDirectory
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiManager
import org.jetbrains.kotlin.psi.KtClass
import java.io.File

class ContextMenuAction : RunConfigurationAction() {
private val logger = Logger.getInstance(ContextMenuAction::class.java)
override fun actionPerformed(e: AnActionEvent) {
val editor = e.getData(CommonDataKeys.EDITOR)
val psiFile = e.getData(CommonDataKeys.PSI_FILE)
if (e.place == "EditorPopup") {
logger.info("ContextMenuAction: actionPerformed in EditorPopup for file $psiFile")
val psiElement = psiFile?.findElementAt(editor?.caretModel!!.offset)
val selectedClass = findEnclosingClass(psiElement)
if (selectedClass != null) {
var classFQN = ""
if (selectedClass is PsiClass) {
classFQN = selectedClass.qualifiedName.toString()
}
if (selectedClass is KtClass) {
classFQN = selectedClass.fqName.toString()
}

logger.info("ContextMenuAction: selected class is $classFQN.")
updateAndExecuteRunConfig(classFQN, e.project!!)
}
}
if (e.place == "ProjectViewPopup") {
private fun updateAndExecuteForFile(psiFileArray: Array<PsiFile>, project: Project) {
var classFQNs: String = ""
for (psiFile in psiFileArray) {
logger.info("ContextMenuAction: actionPerformed in ProjectViewPopup for file $psiFile")
val psiClasses = (psiFile as PsiClassOwner).classes
var classFQNs = ""
for (psiClass in psiClasses) {
val fqn = psiClass.qualifiedName
if (fqn != null) {
classFQNs = if (classFQNs != "") {
"$classFQNs,$fqn"
} else {
fqn
if (!fqn.endsWith("Test")) {
classFQNs = if (classFQNs != "") {
"$classFQNs,$fqn"
} else {
fqn
}
}
}
}
logger.info("ContextMenuAction: selected classes are $classFQNs.")
updateAndExecuteRunConfig(classFQNs, e.project!!)
}
logger.info("ContextMenuAction: selected classes are $classFQNs.")
updateAndExecuteRunConfig(classFQNs, project)
}

private fun getPsiFileFromPath(project: Project, filePath: String): PsiFile? {
return LocalFileSystem.getInstance().findFileByPath(filePath)
?.let { PsiManager.getInstance(project).findFile(it) }
}

private fun actionEditorPopup(e: AnActionEvent) {
val editor = e.getData(CommonDataKeys.EDITOR)
val psiFile = e.getData(CommonDataKeys.PSI_FILE)

logger.info("ContextMenuAction: actionPerformed in EditorPopup for file $psiFile")
val psiElement = psiFile?.findElementAt(editor?.caretModel!!.offset)
val selectedClass = findEnclosingClass(psiElement)
if (selectedClass != null) {
var classFQN = ""
if (selectedClass is PsiClass) {
classFQN = selectedClass.qualifiedName.toString()
}
if (selectedClass is KtClass) {
classFQN = selectedClass.fqName.toString()
}

logger.info("ContextMenuAction: selected class is $classFQN.")
updateAndExecuteRunConfig(classFQN, e.project!!)
}
}

private fun actionProjectViewPopupFile(e: AnActionEvent) {
val psiFile = e.getData(CommonDataKeys.PSI_FILE)

if (psiFile != null) {
updateAndExecuteForFile(arrayOf(psiFile), e.project!!)
}
}

private fun actionProjectViewPopupDir(e: AnActionEvent) {
val psiElement = e.getData(CommonDataKeys.PSI_ELEMENT)
var psiFileArray: Array<PsiFile> = emptyArray()
if (psiElement != null) {
if (psiElement is PsiDirectory) {
val path = psiElement.virtualFile.path.toString()
val directory = File(path)

directory.walk()
.filter { it.isFile && (it.extension == "kt" || it.extension == "java") }
.forEach { getPsiFileFromPath(e.project!!, it.toString())?.let { it1 -> psiFileArray += it1 } }
}
}

updateAndExecuteForFile(psiFileArray, e.project!!)
}

override fun actionPerformed(e: AnActionEvent) {
if (e.place == "EditorPopup") {
actionEditorPopup(e)
} else if (e.place == "ProjectViewPopup") {
if (e.getData(CommonDataKeys.PSI_ELEMENT).toString().startsWith("PsiDirectory")) {
actionProjectViewPopupDir(e)
} else {
actionProjectViewPopupFile(e)
}
}
}

Expand All @@ -78,6 +131,18 @@ class ContextMenuAction : RunConfigurationAction() {
val validClass = (findEnclosingClass(psiElement) != null)
return validFile && validClass
}
if (e.place == "ProjectViewPopup" && e.getData(CommonDataKeys.PSI_ELEMENT).toString().startsWith("PsiDirectory")) {
val psiElement = e.getData(CommonDataKeys.PSI_ELEMENT)
if (psiElement is PsiDirectory) {
val directory: File = File(psiElement.virtualFile.path.toString())
var returnValue: Boolean = false
directory.walk()
.filter { it.isFile && (it.extension == "kt" || it.extension == "java") }
.forEach { if (!it.name.contains("Test")) { returnValue = true } }
return returnValue
}
return false
}
return validFile
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ abstract class RunConfigurationAction : AnAction() {
// TODO: replace this by real results extracted by the HTMLParser
val toolWindow: ToolWindow? = ToolWindowManager.getInstance(project).getToolWindow("Pitest")
val coverageReport: XMLParser.CoverageReport = XMLParser.CoverageReport(
"Test",
classFQN.toString(),
"Test",
"Test",
lineCoveragePercentage = 80,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@ class PiTestClassReport(
fun getCustomHeight(): Int {
return this.height
}

fun getCoverageReport(): XMLParser.CoverageReport {
return this.coverageReport
}
}

class PiTestReports : JPanel() {
Expand Down Expand Up @@ -164,7 +168,7 @@ class PiTestReports : JPanel() {
if (i < 5) {
this.reports[i].renderer()
heights += this.reports[i].getCustomHeight()
rows += arrayOf(getLabel("Placeholder Class"), this.reports[i])
rows += arrayOf(getLabel(this.reports[i].getCoverageReport().fileName), this.reports[i])
} else {
this.summary.renderer()
heights += this.summary.getCustomHeight()
Expand Down
3 changes: 1 addition & 2 deletions pitmutationmate/src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,7 @@
<add-to-group group-id="EditorPopupMenu" anchor="first"/>
</action>
<action id="com.amos.pitmutationmate.pitmutationmate.actions.ContextMenuAction"
class="com.amos.pitmutationmate.pitmutationmate.actions.ContextMenuAction"
text="Run MutationMate on This Class"
class="com.amos.pitmutationmate.pitmutationmate.actions.ContextMenuAction" text="Run PIT MutationMate"
description="Initializes a PiTest run on the selected class"
icon="com.amos.pitmutationmate.pitmutationmate.icons.Icons.Logo16">
<add-to-group group-id="EditorPopupMenu" anchor="first"/>
Expand Down

0 comments on commit 6feaf4e

Please sign in to comment.