Skip to content

add refresh button & fix some bugs after refactoring #361

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ class FocusAction(val path: Path) : AnAction("Show") {
?: error("Focus action should be disabled for path $path")

val project = e.activeProject()
val projectInstance = PsiManager.getInstance(project)
val psiManager = PsiManager.getInstance(project)


if (virtualFile.isDirectory) {
projectInstance.findDirectory(virtualFile)?.navigate(true)
psiManager.findDirectory(virtualFile)?.navigate(true)
} else {
projectInstance.findFile(virtualFile)?.navigate(true)
psiManager.findFile(virtualFile)?.navigate(true)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.utbot.cpp.clion.plugin.actions

import com.intellij.icons.AllIcons
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.components.service
import org.utbot.cpp.clion.plugin.ui.targetsToolWindow.UTBotTargetsController
import org.utbot.cpp.clion.plugin.utils.activeProject

class RefreshTargetsAction: AnAction() {
override fun actionPerformed(e: AnActionEvent) {
e.activeProject().service<UTBotTargetsController>().requestTargetsFromServer()
}

override fun update(e: AnActionEvent) {
e.presentation.isEnabledAndVisible = e.project != null
e.presentation.icon = AllIcons.Actions.Refresh
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.utbot.cpp.clion.plugin.client

import com.intellij.openapi.Disposable
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.Service
import com.intellij.openapi.project.Project
import org.utbot.cpp.clion.plugin.client.channels.GTestLogChannelImpl
Expand All @@ -22,11 +23,11 @@ class ClientManager(val project: Project): Disposable {
}

private fun subscribeToEvents() {
with(project.messageBus.connect()) {
with(ApplicationManager.getApplication().messageBus.connect()) {
subscribe(ConnectionSettingsListener.TOPIC, object : ConnectionSettingsListener {
override fun connectionSettingsChanged(newPort: Int, newServerName: String) {
if (newPort != client.port || newServerName != client.serverName) {
project.logger.trace{ "Connection settings changed. Setting up new client." }
project.logger.trace { "Connection settings changed. Setting up new client." }
client.dispose()
client = Client(project, clientId, loggingChannels)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,20 @@ import testsgen.TestsGenServiceGrpcKt
class ProjectTargetsRequest(
project: Project,
request: Testgen.ProjectTargetsRequest,
val processTargets: suspend (Testgen.ProjectTargetsResponse)->Unit
val processTargets: suspend (Testgen.ProjectTargetsResponse)->Unit,
val onError: suspend (Throwable) -> Unit
): BaseRequest<Testgen.ProjectTargetsRequest, Testgen.ProjectTargetsResponse>(request, project) {

override val logMessage: String = "Sending request to get project targets"

override suspend fun execute(stub: TestsGenServiceGrpcKt.TestsGenServiceCoroutineStub, cancellationJob: Job?) {
try {
super.execute(stub, cancellationJob)
} catch (e: Throwable) {
onError(e)
}
}

override suspend fun Testgen.ProjectTargetsResponse.handle(cancellationJob: Job?) = processTargets(this)

override suspend fun TestsGenServiceGrpcKt.TestsGenServiceCoroutineStub.send(cancellationJob: Job?): Testgen.ProjectTargetsResponse =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import org.utbot.cpp.clion.plugin.client.handlers.TestsStreamHandler
import org.utbot.cpp.clion.plugin.client.requests.BaseRequest
import org.utbot.cpp.clion.plugin.utils.getLongestCommonPathFromRoot
import org.utbot.cpp.clion.plugin.utils.isHeaderFile
import org.utbot.cpp.clion.plugin.utils.isSarifReport
import org.utbot.cpp.clion.plugin.utils.logger
import org.utbot.cpp.clion.plugin.utils.notifyInfo
import testsgen.Testgen
Expand Down Expand Up @@ -35,7 +36,7 @@ abstract class BaseTestsRequest<R>(request: R, project: Project, private val pro
}

open fun getFocusTarget(generatedTestFiles: List<Path>): Path? {
return generatedTestFiles.filter { !isHeaderFile(it.fileName.toString()) }.getLongestCommonPathFromRoot()
return generatedTestFiles.filter { !isHeaderFile(it) && !isSarifReport(it) }.getLongestCommonPathFromRoot()
}

override fun logRequest() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,14 @@ class UTBotAllProjectSettings(val project: Project) {
get() = project.service<UTBotProjectStoredSettings>().state

var projectPath: String
get() = storedSettings.projectPath ?: project.guessProjectDir()?.path
?: error("Could not guess project path! Should be specified in settings by user")
get() {
// if true then there is nothing persisted in xml files and plugin was launched for the first time
if (storedSettings.projectPath == null)
// so we should guess the project path
storedSettings.projectPath = project.guessProjectDir()?.path
return storedSettings.projectPath
?: error("Could not guess project path! Should be specified in settings by user")
}
set(value) {
storedSettings.projectPath = value
}
Expand Down Expand Up @@ -49,7 +55,8 @@ class UTBotAllProjectSettings(val project: Project) {
*/
val isRemoteScenario: Boolean
get() {
val isLocalHost = projectIndependentSettings.serverName == "localhost" || projectIndependentSettings.serverName == "127.0.0.01"
val isLocalHost =
projectIndependentSettings.serverName == "localhost" || projectIndependentSettings.serverName == "127.0.0.01"
return !(storedSettings.remotePath == projectPath && isLocalHost) || isWindows
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package org.utbot.cpp.clion.plugin.settings

import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.PersistentStateComponent
import com.intellij.openapi.components.Service
import com.intellij.openapi.components.State
import com.intellij.openapi.components.Storage
import org.utbot.cpp.clion.plugin.listeners.ConnectionSettingsListener

/**
* Settings that are the same for all projects
Expand All @@ -22,11 +24,17 @@ class UTBotProjectIndependentSettings : PersistentStateComponent<UTBotProjectInd
port = model.globalSettings.port
serverName = model.globalSettings.serverName
}

fun fireConnectionSettingsChanged() {
ApplicationManager.getApplication().messageBus.syncPublisher(ConnectionSettingsListener.TOPIC)
.connectionSettingsChanged(port, serverName)
}
}

private var myState: State = State()
override fun getState(): State = myState
override fun loadState(state: State) {
myState = state
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.utbot.cpp.clion.plugin.ui.targetsToolWindow

import com.intellij.openapi.components.Service
import com.intellij.openapi.project.Project
import com.intellij.ui.CollectionListModel
import org.utbot.cpp.clion.plugin.client.requests.ProjectTargetsRequest
Expand All @@ -13,13 +14,16 @@ import org.utbot.cpp.clion.plugin.utils.getCurrentClient
import org.utbot.cpp.clion.plugin.utils.invokeOnEdt
import org.utbot.cpp.clion.plugin.utils.logger
import org.utbot.cpp.clion.plugin.utils.relativize
import testsgen.Testgen

@Service
class UTBotTargetsController(val project: Project) {
private val settings: UTBotAllProjectSettings
get() = project.settings

private val listModel = CollectionListModel(mutableListOf(UTBotTarget.autoTarget))
private val logger = project.logger
private val listModel = CollectionListModel(mutableListOf<UTBotTarget>())
private val logger get() = project.logger
val targetsToolWindow: UTBotTargetsToolWindow by lazy { UTBotTargetsToolWindow(listModel, this) }

val targets: List<UTBotTarget>
get() = listModel.toList()
Expand All @@ -32,23 +36,35 @@ class UTBotTargetsController(val project: Project) {
fun requestTargetsFromServer() {
val currentClient = project.getCurrentClient()

invokeOnEdt {
listModel.removeAll()
targetsToolWindow.setBusy(true)
}
ProjectTargetsRequest(
project,
getProjectTargetsGrpcRequest(project),
) { targetsResponse ->
invokeOnEdt {
listModel.apply {
val oldTargetList = toList()
oldTargetList.addAll(
targetsResponse.targetsList.map { projectTarget ->
UTBotTarget(projectTarget, project)
})
listModel.replaceAll(oldTargetList.distinct())
processTargets = { targetsResponse: Testgen.ProjectTargetsResponse ->
invokeOnEdt {
targetsToolWindow.setBusy(false)

listModel.apply {
listModel.replaceAll(
targetsResponse.targetsList.map { projectTarget ->
UTBotTarget(projectTarget, project)
})
}
}
}
}.let { targetsRequest ->
},
onError = {
invokeOnEdt {
targetsToolWindow.setBusy(false)
}
}).let { targetsRequest ->
if (!currentClient.isServerAvailable()) {
logger.error { "Could not request targets from server: server is unavailable!" }
invokeOnEdt {
targetsToolWindow.setBusy(false)
}
return
}
logger.trace { "Requesting project targets from server!" }
Expand All @@ -68,8 +84,6 @@ class UTBotTargetsController(val project: Project) {
}
}

fun createTargetsToolWindow(): UTBotTargetsToolWindow = UTBotTargetsToolWindow(listModel, this)

fun selectionChanged(selectedTarget: UTBotTarget) {
// when user selects target update model
settings.storedSettings.targetPath = selectedTarget.path
Expand All @@ -94,7 +108,7 @@ class UTBotTargetsController(val project: Project) {
UTBotEventsListener.CONNECTION_CHANGED_TOPIC,
object : UTBotEventsListener {
override fun onConnectionChange(oldStatus: ConnectionStatus, newStatus: ConnectionStatus) {
if (newStatus != oldStatus && newStatus == ConnectionStatus.CONNECTED) {
if (newStatus != oldStatus) {
requestTargetsFromServer()
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
package org.utbot.cpp.clion.plugin.ui.targetsToolWindow

import com.intellij.openapi.actionSystem.ActionGroup
import com.intellij.openapi.actionSystem.ActionManager
import com.intellij.openapi.actionSystem.ActionPlaces
import com.intellij.openapi.actionSystem.ActionToolbar
import com.intellij.openapi.actionSystem.DefaultActionGroup
import com.intellij.openapi.project.DumbAware
import com.intellij.openapi.ui.SimpleToolWindowPanel
import com.intellij.ui.CollectionListModel
import com.intellij.ui.ColoredListCellRenderer
Expand All @@ -8,24 +14,47 @@ import com.intellij.ui.components.JBList
import com.intellij.ui.components.JBScrollPane
import javax.swing.JList
import javax.swing.ListSelectionModel
import org.utbot.cpp.clion.plugin.UTBot
import org.utbot.cpp.clion.plugin.actions.RefreshTargetsAction
import org.utbot.cpp.clion.plugin.utils.logger

class UTBotTargetsToolWindow(
listModel: CollectionListModel<UTBotTarget>,
private val controller: UTBotTargetsController,
): SimpleToolWindowPanel(true, true) {
private val controller: UTBotTargetsController
): SimpleToolWindowPanel(true, true), DumbAware {
private val uiList = JBList(listModel)

init {
val panel = JBScrollPane()
toolbar = createActionToolBar().let {
it.targetComponent = this.component
it.component
}

uiList.cellRenderer = Renderer()
uiList.selectionMode = ListSelectionModel.SINGLE_SELECTION
uiList.addListSelectionListener {
controller.selectionChanged(uiList.selectedValue)
if (!uiList.isSelectionEmpty)
controller.selectionChanged(uiList.selectedValue)
}
uiList.setEmptyText(UTBot.message("targets.notargets.description"))

val panel = JBScrollPane()
panel.setViewportView(uiList)
setContent(panel)
}

fun setBusy(busy: Boolean) {
uiList.setPaintBusy(busy)
}

private fun createActionToolBar(isHorizontal: Boolean = false): ActionToolbar {
return ActionManager.getInstance().createActionToolbar(ActionPlaces.TOOLBAR, createActionGroup(), isHorizontal)
}

private fun createActionGroup(): ActionGroup {
return DefaultActionGroup(RefreshTargetsAction())
}

private inner class Renderer : ColoredListCellRenderer<UTBotTarget>() {
override fun customizeCellRenderer(
list: JList<out UTBotTarget>,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.utbot.cpp.clion.plugin.ui.targetsToolWindow

import com.intellij.openapi.components.service
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.project.Project
import com.intellij.openapi.wm.ToolWindow
Expand All @@ -11,9 +12,9 @@ class UTBotTargetsToolWindowFactory : ToolWindowFactory {
override fun createToolWindowContent(project: Project, toolWindow: ToolWindow) {
logger.info("createToolWindowContent was called")
val contentManager = toolWindow.contentManager
val utbotToolWindow = UTBotTargetsController(project).createTargetsToolWindow()

val content = contentManager.factory.createContent(utbotToolWindow, null, false,)
contentManager.addContent(content)
val content = contentManager.factory.createContent(
project.service<UTBotTargetsController>().targetsToolWindow, null, false
)
toolWindow.contentManager.addContent(content)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class UTBotWizard(private val project: Project) : AbstractWizard<UTBotBaseWizard
override fun doOKAction() {
project.settings.storedSettings.fromSettingsModel(mySettingsModel)
projectIndependentSettings.fromSettingsModel(mySettingsModel)
projectIndependentSettings.fireConnectionSettingsChanged()

with(project.settings) {
fireUTBotSettingsChanged()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ package org.utbot.cpp.clion.plugin.utils
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.vfs.LocalFileSystem
import com.intellij.util.io.createFile
import java.nio.file.Files
import java.nio.file.Path
import com.intellij.util.io.exists
import kotlin.io.path.writeText
import java.nio.file.Path

fun refreshAndFindNioFile(file: Path) {
ApplicationManager.getApplication().invokeLater {
Expand All @@ -14,16 +14,20 @@ fun refreshAndFindNioFile(file: Path) {
}

fun createFileWithText(filePath: Path, text: String) {
if (!Files.isRegularFile(filePath))
error("File expected! But got: $filePath")

with(filePath) {
createFile()
if (!exists())
createFile()
writeText(text)
}
}

fun isCPPorCFileName(fileName: String) = """.*\.(cpp|hpp|c|h)""".toRegex().matches(fileName)
fun isCPPFileName(fileName: String) = """.*\.(cpp|hpp|h)""".toRegex().matches(fileName)


fun isHeaderFile(fileName: String) = """.*\.([ch])""".toRegex().matches(fileName)
fun isHeaderFile(path: Path) = isHeaderFile(path.fileName.toString())

fun isSarifReport(fileName: String) = fileName.endsWith(".sarif")

fun isSarifReport(path: Path) = isSarifReport(path.fileName.toString())
1 change: 1 addition & 0 deletions clion-plugin/src/main/resources/messages/UTBot.properties
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,4 @@ advanced.timeoutPerFunction.title=Timeout per function:
advanced.timeoutPerFunction.description=Maximum time (in seconds) alloted for generation tests per function. Set to non-positive number to disable it. <a href=https://github.com/UnitTestBot/UTBotCpp/wiki/vscode-extension-settings#timeout-per-function>Learn more</a>
advanced.timeoutPerTest.title=Timeout per test:
advanced.timeoutPerTest.description=Maximum time (in seconds) alloted for a single test run. Set to non-positive number to disable it. <a href=https://github.com/UnitTestBot/UTBotCpp/wiki/vscode-extension-settings#timeout-per-test>Learn more</a>
targets.notargets.description=No targets can be found by UTBot in current project