Skip to content
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

Add targets view #24

Closed
wants to merge 8 commits into from
Closed
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
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ jobs:

# Run Qodana inspections
- name: Qodana - Code Inspection
uses: JetBrains/qodana-action@v2.1-eap
uses: JetBrains/qodana-action@v3.2.1

# Run tests
- name: Run Tests
Expand Down
6 changes: 3 additions & 3 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ plugins {
// Kotlin support
id("org.jetbrains.kotlin.jvm") version "1.5.30"
// Gradle IntelliJ Plugin
id("org.jetbrains.intellij") version "1.1.6"
id("org.jetbrains.intellij") version "1.3.0"
// Gradle Changelog Plugin
id("org.jetbrains.changelog") version "1.3.0"
// Gradle Qodana Plugin
Expand Down Expand Up @@ -71,7 +71,7 @@ dependencies {
implementation("ch.qos.logback:logback-classic:1.2.3")

// yaml
implementation("com.charleskorn.kaml:kaml:0.36.0")
implementation("com.charleskorn.kaml:kaml:0.38.0")
}

protobuf {
Expand Down Expand Up @@ -119,7 +119,7 @@ intellij {
// use CLion version 2021.2.2
version.set(platformVersion)
type.set(platformType)
downloadSources.set(false)
// downloadSources.set(false)
updateSinceUntilBuild.set(true)

// to use auto-reload for ide instance
Expand Down
3 changes: 1 addition & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,10 @@ pluginUntilBuild = 212.*

# Plugin Verifier integration -> https://github.com/JetBrains/gradle-intellij-plugin#plugin-verifier-dsl
# See https://jb.gg/intellij-platform-builds-list for available build versions.
pluginVerifierIdeVersions = 2020.3.4, 2021.1.3, 2021.2.1
pluginVerifierIdeVersions = CL-2021.2.1

platformType = CL
platformVersion = 2021.2
platformDownloadSources = false

# Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html
# Example: platformPlugins = com.intellij.java, com.jetbrains.php:203.4449.22
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package com.github.vol0n.utbotcppclion.client

import com.charleskorn.kaml.Yaml
import com.github.vol0n.utbotcppclion.server.Server
import com.intellij.openapi.diagnostic.Logger

import io.grpc.ManagedChannel
import io.grpc.ManagedChannelBuilder
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.github.vol0n.utbotcppclion.messaging

import com.github.vol0n.utbotcppclion.services.ProjectSettings
import com.intellij.util.messages.Topic

fun interface UTBotSettingsChangedListener {
companion object {
val TOPIC = Topic.create(
"UTBot settings changed",
UTBotSettingsChangedListener::class.java
)
}

fun settingsChanged(settings: ProjectSettings)
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ class ProjectConfigurable(private val targetProject: Project) : BoundConfigurabl
fileChooserDescriptor = FileChooserDescriptorFactory.createSingleFileDescriptor()
) { file ->
file.path
}.apply {
component.isEditable = false
}
}
row {
Expand Down Expand Up @@ -94,7 +96,6 @@ class ProjectConfigurable(private val targetProject: Project) : BoundConfigurabl
|| (testsDirPath.get() != settingsState.testDirPath)
|| (synchronizeCode.get() != settingsState.synchronizeCode)
|| (sourcePathListModel.toList() != settingsState.sourcePaths)

}

override fun apply() {
Expand All @@ -105,6 +106,7 @@ class ProjectConfigurable(private val targetProject: Project) : BoundConfigurabl
settingsState.testDirPath = testsDirPath.get()
settingsState.synchronizeCode = synchronizeCode.get()
settingsState.sourcePaths = sourcePathListModel.toList()
settingsState.fireUTBotSettingsChanged()
}

override fun reset() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package com.github.vol0n.utbotcppclion.services

import com.github.vol0n.utbotcppclion.actions.utils.notifyError
import com.github.vol0n.utbotcppclion.messaging.UTBotSettingsChangedListener
import com.github.vol0n.utbotcppclion.utils.relativize
import com.intellij.openapi.components.PersistentStateComponent
import com.intellij.openapi.components.State
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.project.Project
import com.intellij.util.xmlb.XmlSerializerUtil
import com.jetbrains.cidr.cpp.cmake.model.CMakeConfiguration
import com.jetbrains.cidr.cpp.execution.CMakeAppRunConfiguration
import java.nio.file.Paths

Expand Down Expand Up @@ -87,6 +89,11 @@ data class ProjectSettings(
}
}

fun fireUTBotSettingsChanged() {
project ?: return
project.messageBus.syncPublisher(UTBotSettingsChangedListener.TOPIC).settingsChanged(this)
}

private fun checkForUninitializedDataAndInit() {
if (targetPath == null || buildDirPath == null || testDirPath == null)
init()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package com.github.vol0n.utbotcppclion.ui

import com.github.vol0n.utbotcppclion.messaging.UTBotSettingsChangedListener
import com.github.vol0n.utbotcppclion.services.ProjectSettings
import com.github.vol0n.utbotcppclion.utils.relativize
import com.intellij.execution.RunManager
import com.intellij.openapi.components.service
import com.intellij.openapi.project.Project
import com.intellij.ui.CollectionListModel
import com.jetbrains.cidr.cpp.cmake.workspace.CMakeWorkspaceListener
import com.jetbrains.cidr.cpp.execution.CMakeAppRunConfiguration
import java.nio.file.Paths

open class UTBotTarget(val targetAbsolutePath: String, val project: Project? = null) {
open val description: String
get(): String = project?.basePath?.let {
relativize(it, targetAbsolutePath)
} ?: ""

open val name: String get(): String = Paths.get(targetAbsolutePath).last().toString()

companion object {
val UTBOT_AUTO_TARGET: UTBotTarget = object : UTBotTarget("/utbot/auto/target/path") {
override val description: String
get() = "Automatically detects a target"

override val name = "/utbot/auto"
}
}
}

class UTBotTargetsController(val project: Project) {
private val projectSettings = project.service<ProjectSettings>()
private val listModel = CollectionListModel(mutableListOf(UTBotTarget.UTBOT_AUTO_TARGET))
init {
listModel.addAll(1, getCMakeTargets())
projectSettings.targetPath?.let { addTargetPathIfNotPresent(it) }
connectToEvents()
}

private fun addTargetPathIfNotPresent(possiblyNewTargetPath: String) {
listModel.apply {
toList().find { utbotTarget -> utbotTarget.targetAbsolutePath == possiblyNewTargetPath } ?: add(
UTBotTarget(possiblyNewTargetPath, project)
)
}
}

fun createTargetsToolWindow(): UTBotTargetsToolWindow {
return UTBotTargetsToolWindow(listModel, this)
}

private fun getCMakeTargets() =
RunManager.getInstance(project).allConfigurationsList.mapNotNull {
// BuildConfigurations can be 'release', 'debug' ...
(it as CMakeAppRunConfiguration).cMakeTarget?.buildConfigurations?.mapNotNull { cmakeConfig ->
cmakeConfig.productFile?.absolutePath?.let { targetPath ->
UTBotTarget(targetPath, project)
}
}
}.flatten()

fun selectionChanged(index: Int) {
// when user selects target update model
projectSettings.targetPath = listModel.getElementAt(index).targetAbsolutePath
}

fun getCurrentTargetPath() = projectSettings.targetPath

private fun connectToEvents() {
// when new targets are specified in CMakeLists, the view should be updated, it is done on after reloading
project.messageBus.connect().subscribe(CMakeWorkspaceListener.TOPIC, object : CMakeWorkspaceListener {
override fun reloadingFinished(canceled: Boolean) {
listModel.replaceAll(mutableListOf(UTBotTarget.UTBOT_AUTO_TARGET).apply {
addAll(getCMakeTargets())
projectSettings.targetPath?.let { addTargetPathIfNotPresent(it) }
})
}
})

// if user specifies some custom target path in settings, it will be added if not already present
project.messageBus.connect().subscribe(
UTBotSettingsChangedListener.TOPIC,
UTBotSettingsChangedListener { settings ->
val possiblyNewTargetPath = settings.targetPath ?: return@UTBotSettingsChangedListener
addTargetPathIfNotPresent(possiblyNewTargetPath)
})
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.github.vol0n.utbotcppclion.ui


import com.intellij.icons.AllIcons
import com.intellij.openapi.ui.SimpleToolWindowPanel
import com.intellij.ui.CollectionListModel
import com.intellij.ui.ColoredListCellRenderer
import com.intellij.ui.SimpleTextAttributes
import com.intellij.ui.components.JBList
import com.intellij.ui.components.JBScrollPane

import javax.swing.JList


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

init {
val panel = JBScrollPane()

uiList.cellRenderer = Renderer()
uiList.addListSelectionListener {
controller.selectionChanged(uiList.selectedIndex)
uiList.updateUI()
}
panel.setViewportView(uiList)
setContent(panel)
}

private inner class Renderer : ColoredListCellRenderer<UTBotTarget>() {
override fun customizeCellRenderer(
list: JList<out UTBotTarget>,
target: UTBotTarget,
index: Int,
selected: Boolean,
hasFocus: Boolean
) {
icon = if (target.targetAbsolutePath == controller.getCurrentTargetPath()) {
uiList.selectedIndex = index
AllIcons.Icons.Ide.MenuArrowSelected;
} else {
null
}
append(target.name, SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
append(" ")
append(target.description, SimpleTextAttributes.GRAYED_ATTRIBUTES);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.github.vol0n.utbotcppclion.ui

import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.project.Project
import com.intellij.openapi.wm.ToolWindow
import com.intellij.openapi.wm.ToolWindowFactory

class UTBotTargetsToolWindowFactory : ToolWindowFactory {
private val logger = Logger.getInstance(this::class.java)

override fun createToolWindowContent(project: Project, toolWindow: ToolWindow) {
logger.info("createToolWindowContent was called")
val contentManager = toolWindow.contentManager
val content = contentManager.factory.createContent(
UTBotTargetsController(project).createTargetsToolWindow(), null, false
)
toolWindow.contentManager.addContent(content)
}
}
16 changes: 16 additions & 0 deletions src/main/proto/testgen.proto
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,22 @@ service TestsGenService {
rpc RegisterClient(RegisterClientRequest) returns(DummyResponse) {}
rpc OpenGTestChannel(LogChannelRequest) returns(stream LogEntry) {}
rpc CloseGTestChannel(DummyRequest) returns(DummyResponse) {}
rpc GetProjectTargets(ProjectTargetsRequest) returns(ProjectTargetsResponse) {}
}

message ProjectTarget {
string name = 1;
string path = 2;
string description = 3;
}

message ProjectTargetsRequest {
ProjectContext projectContext = 1;
}

message ProjectTargetsResponse {
repeated ProjectTarget targets = 1;
ProjectTarget priorityTarget = 2;
}

message LogChannelRequest {
Expand Down
6 changes: 6 additions & 0 deletions src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<depends>com.intellij.modules.cidr.lang</depends>
<depends>com.intellij.modules.clion</depends>


<extensions defaultExtensionNs="com.intellij">
<applicationService serviceImplementation="com.github.vol0n.utbotcppclion.services.GeneratorSettings"/>
<projectService serviceImplementation="com.github.vol0n.utbotcppclion.services.ProjectSettings"/>
Expand All @@ -20,6 +21,11 @@
nonDefaultProject="true"/>
<notificationGroup id="Custom Notification Group" displayType="BALLOON"/>
<statusBarWidgetFactory implementation="com.github.vol0n.utbotcppclion.ui.StatusBar"/>

<toolWindow id="UTBot targets"
secondary="false"
anchor="bottom"
factoryClass="com.github.vol0n.utbotcppclion.ui.UTBotTargetsToolWindowFactory"/>
</extensions>

<actions>
Expand Down