[evaluation-plugin] LME-104 Add IDE action to create dataset entities for Evaluation plugin

(cherry picked from commit 450af2f618f70d7b9e32420f6b41774bd0361321)

IJ-MR-145860

GitOrigin-RevId: 00b460dcdbc47dea38b21d5f89159391efe67b75
This commit is contained in:
Alexey Kalina
2024-10-01 10:53:41 +02:00
committed by intellij-monorepo-bot
parent ca69477b7c
commit 5e2212579a
6 changed files with 215 additions and 9 deletions

View File

@@ -1,4 +1,4 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.cce.actions
import com.google.gson.GsonBuilder
@@ -8,11 +8,16 @@ object ActionSerializer {
private val gson = GsonBuilder()
.registerTypeAdapter(Action::class.java, Action.JsonAdapter)
.registerTypeAdapter(TokenProperties::class.java, TokenProperties.JsonAdapter)
.setPrettyPrinting()
.create()
fun serialize(actions: FileActions): String = gson.toJson(actions)
fun serialize(actions: List<Action>): String = gson.toJson(actions)
fun deserialize(json: String): FileActions = gson.fromJson(json, FileActions::class.java)
fun deserialize(json: String): List<Action> = gson.fromJson(json, Array<Action>::class.java).toList()
fun serializeFileActions(actions: FileActions): String = gson.toJson(actions)
fun deserializeFileActions(json: String): FileActions = gson.fromJson(json, FileActions::class.java)
private data class FakeFileActions(val sessionsCount: Int)

View File

@@ -75,9 +75,10 @@ class ActionsBuilder {
actions.addAll(SessionBuilder().apply(init).build())
}
class SessionBuilder {
private val sessionId = UUID.randomUUID()
class SessionBuilder(
private val sessionId: UUID = UUID.randomUUID(),
private val actions: MutableList<Action> = mutableListOf()
) {
fun build(): List<Action> = actions.toList()

View File

@@ -1,4 +1,4 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.cce.workspace.storages.storage
import com.intellij.cce.actions.ActionSerializer
@@ -12,7 +12,7 @@ internal class ActionsMultiplyFilesStorage(storageDir: String) : ActionsStorage
override fun saveActions(actions: FileActions) {
filesCounter++
keyValueStorage.save("${Paths.get(actions.path).fileName}($filesCounter).json", ActionSerializer.serialize(actions))
keyValueStorage.save("${Paths.get(actions.path).fileName}($filesCounter).json", ActionSerializer.serializeFileActions(actions))
}
override fun computeSessionsCount(): Int {
@@ -27,6 +27,6 @@ internal class ActionsMultiplyFilesStorage(storageDir: String) : ActionsStorage
}
override fun getActions(path: String): FileActions {
return ActionSerializer.deserialize(keyValueStorage.get(path))
return ActionSerializer.deserializeFileActions(keyValueStorage.get(path))
}
}

View File

@@ -15,6 +15,11 @@
<registryKey key="evaluation.plugin.disable.sdk.check" defaultValue="false"
description="Disables check that project sdk configured properly" restartRequired="false"/>
<completion.ml.featuresOverride language="" implementationClass="com.intellij.cce.interpreter.DisableUserDependentFeatures"/>
<toolWindow id="Evaluation Dataset"
factoryClass="com.intellij.cce.ui.EvaluationDatasetToolWindowFactory"
anchor="bottom"
canCloseContents="false"/>
</extensions>
<extensionPoints>

View File

@@ -0,0 +1,189 @@
package com.intellij.cce.ui
import com.intellij.cce.actions.ActionArraySerializer
import com.intellij.cce.actions.ActionSerializer
import com.intellij.cce.actions.ActionsBuilder.SessionBuilder
import com.intellij.cce.actions.CallFeature
import com.intellij.cce.actions.FileActions
import com.intellij.cce.core.SimpleTokenProperties
import com.intellij.cce.core.SymbolLocation
import com.intellij.cce.core.TypeProperty
import com.intellij.cce.evaluable.chat.PROMPT_PROPERTY
import com.intellij.cce.util.FileTextUtil.computeChecksum
import com.intellij.cce.util.FilesHelper
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.fileEditor.FileEditorManager
import com.intellij.openapi.fileEditor.TextEditor
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.NlsSafe
import com.intellij.openapi.wm.ToolWindow
import com.intellij.openapi.wm.ToolWindowFactory
import com.intellij.ui.components.JBScrollPane
import com.intellij.ui.content.ContentFactory
import java.awt.BorderLayout
import java.awt.GridLayout
import javax.swing.JButton
import javax.swing.JPanel
import javax.swing.JTextArea
class EvaluationDatasetToolWindowFactory : ToolWindowFactory {
override fun createToolWindowContent(project: Project, toolWindow: ToolWindow) {
val myToolWindow = EvaluationDatasetToolWindow(project)
val contentFactory = ContentFactory.getInstance()
val content = contentFactory.createContent(myToolWindow.getContent(), toolWindow.id, false)
toolWindow.contentManager.addContent(content)
}
override suspend fun isApplicableAsync(project: Project): Boolean = ApplicationManager.getApplication().isInternal()
class EvaluationDatasetToolWindow(private val project: Project) {
private val myToolWindowContent: JPanel = JPanel(BorderLayout())
private val datasetArea = JTextArea()
private val leftButtonPanel = JPanel(GridLayout(6, 1))
private val rightButtonPanel = JPanel(GridLayout(6, 1))
private lateinit var session: SessionBuilder
private lateinit var fileActions: FileActions
private val actions = mutableListOf<FileActions>()
init {
val buttonPanel = JPanel(BorderLayout())
myToolWindowContent.add(buttonPanel, BorderLayout.WEST)
buttonPanel.add(leftButtonPanel, BorderLayout.WEST)
buttonPanel.add(rightButtonPanel, BorderLayout.EAST)
myToolWindowContent.add(JBScrollPane(datasetArea), BorderLayout.CENTER)
startPage()
}
fun getContent(): JPanel = myToolWindowContent
private fun startPage() {
clearButtons()
leftButtonPanel.add(createButton("Create Actions for File") {
fileActions = createFileActions()
newFileActionsPage()
})
displayDataset()
}
private fun newFileActionsPage() {
clearButtons()
leftButtonPanel.add(createButton("Create Session") {
loadFileActions()
session = SessionBuilder()
newSessionPage()
})
rightButtonPanel.add(createButton("Cancel") {
startPage()
})
rightButtonPanel.add(createButton("Save") {
loadFileActions()
actions.add(fileActions)
startPage()
})
displayFileActions()
}
private fun newSessionPage() {
clearButtons()
leftButtonPanel.add(createActionButton("Move caret") {
session.moveCaret(getCurrentOffset())
})
leftButtonPanel.add(createActionButton("Print text") {
session.printText(getCurrentSelectionText())
})
leftButtonPanel.add(createActionButton("Delete range") {
val (start, end) = getCurrentSelectionOffsets()
session.deleteRange(start, end)
})
leftButtonPanel.add(createActionButton("Select range") {
val (start, end) = getCurrentSelectionOffsets()
session.selectRange(start, end)
})
leftButtonPanel.add(createActionButton("Rename") {
session.rename(getCurrentOffset(), "_PLACEHOLDER_")
})
leftButtonPanel.add(createActionButton("Call feature") {
session.callFeature(
getCurrentSelectionText(),
getCurrentOffset(),
SimpleTokenProperties.create(TypeProperty.METHOD, SymbolLocation.PROJECT) {
put(PROMPT_PROPERTY, "_PROMPT_")
},
)
})
rightButtonPanel.add(createButton("Cancel") {
newFileActionsPage()
})
rightButtonPanel.add(createButton("Save") {
val resultActions = fileActions.actions + session.build()
fileActions = FileActions(fileActions.path, fileActions.checksum, resultActions.count { it is CallFeature }, resultActions)
newFileActionsPage()
})
displaySession()
}
private fun createActionButton(text: String, action: () -> Unit): JButton {
return createButton(text) {
loadSession()
action()
displaySession()
}
}
private fun createButton(@NlsSafe text: String, action: () -> Unit): JButton {
val button = JButton(text)
button.addActionListener {
action()
}
return button
}
private fun clearButtons() {
leftButtonPanel.removeAll()
rightButtonPanel.removeAll()
}
private fun displayDataset() {
datasetArea.text = ActionArraySerializer.serialize(actions.toTypedArray())
}
private fun displayFileActions() {
datasetArea.text = ActionSerializer.serializeFileActions(fileActions)
}
private fun displaySession() {
datasetArea.text = ActionSerializer.serialize(session.build())
}
private fun createFileActions(): FileActions = FileActions(
path = getCurrentEditor()?.virtualFile?.let { FilesHelper.getRelativeToProjectPath(project, it.path) } ?: "",
checksum = getCurrentEditor()?.document?.text?.let { computeChecksum(it) } ?: "",
sessionsCount = 0,
actions = emptyList()
)
private fun loadSession() {
val actions = ActionSerializer.deserialize(datasetArea.text)
if (actions.isEmpty()) return
session = SessionBuilder(actions.first().sessionId, actions.toMutableList())
}
private fun loadFileActions() {
fileActions = ActionSerializer.deserializeFileActions(datasetArea.text)
}
private fun getCurrentOffset(): Int = getCurrentEditor()?.caretModel?.currentCaret?.offset ?: -1
private fun getCurrentSelectionOffsets(): Pair<Int, Int> {
val editor = getCurrentEditor()
return (editor?.selectionModel?.selectionStart ?: -1) to (editor?.selectionModel?.selectionEnd ?: -1)
}
private fun getCurrentSelectionText(): String = getCurrentEditor()?.selectionModel?.selectedText ?: ""
private fun getCurrentEditor(): Editor? = (FileEditorManager.getInstance(project).selectedEditor as? TextEditor)?.editor
}
}

View File

@@ -59,14 +59,20 @@ class ActionSerializerTest {
}
private fun doTest(before: FileActions): FileActions {
val after = ActionSerializer.deserialize(ActionSerializer.serialize(before))
val after = ActionSerializer.deserializeFileActions(ActionSerializer.serializeFileActions(before))
assertEquals(before.path, after.path)
assertEquals(before.sessionsCount, after.sessionsCount)
assertEquals(before.checksum, after.checksum)
assertActionsEquals(before.actions, after.actions)
doTestActionsOnly(before.actions)
return after
}
private fun doTestActionsOnly(before: List<Action>) {
val after = ActionSerializer.deserialize(ActionSerializer.serialize(before))
assertActionsEquals(before, after)
}
private fun assertActionsEquals(before: List<Action>, after: List<Action>) {
assertEquals(before.size, after.size)
for ((actionBefore, actionAfter) in before.zip(after)) {