Skip to content

Commit

Permalink
fix run/view function call, remove automatic account fill
Browse files Browse the repository at this point in the history
  • Loading branch information
mkurnikov committed Mar 23, 2024
1 parent c204d38 commit 39c308b
Show file tree
Hide file tree
Showing 11 changed files with 98 additions and 93 deletions.
4 changes: 2 additions & 2 deletions src/main/kotlin/org/move/cli/MoveProjectsService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ class MoveProjectsService(val project: Project): Disposable {
}

// requires ReadAccess
fun findMoveProject(psiElement: PsiElement): MoveProject? {
fun findMoveProjectForPsiElement(psiElement: PsiElement): MoveProject? {
// read access required for the psiElement.containingFile
checkReadAccessAllowed()
val file = when (psiElement) {
Expand Down Expand Up @@ -115,7 +115,7 @@ class MoveProjectsService(val project: Project): Disposable {
return findMoveProjectForFile(file)
}

fun findMoveProject(path: Path): MoveProject? {
fun findMoveProjectForPath(path: Path): MoveProject? {
val file = path.toVirtualFile() ?: return null
return findMoveProjectForFile(file)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ abstract class CommandConfigurationHandler {

abstract fun getFunctionCompletionVariants(moveProject: MoveProject): Collection<String>

abstract fun getFunction(moveProject: MoveProject, functionQualName: String): MvFunction?
abstract fun getFunctionItem(moveProject: MoveProject, functionQualName: String): MvFunction?

abstract fun getFunctionByCmdName(moveProject: MoveProject, functionCmdName: String): MvFunction?

Expand All @@ -73,7 +73,9 @@ abstract class CommandConfigurationHandler {
typeParams,
params
).flatten()
return RsResult.Ok(commandArguments.joinToString(" "))
val command = commandArguments.joinToString(" ")
println("Command is $command")
return RsResult.Ok(command)
}

fun parseCommand(
Expand All @@ -91,14 +93,14 @@ abstract class CommandConfigurationHandler {
val function = getFunctionByCmdName(moveProject, functionId)
?: return RsResult.Err("function with this functionId does not exist in the current project")

val aptosConfig = moveProject.aptosConfigYaml
if (aptosConfig == null) {
return RsResult.Err("Aptos account is not initialized / is invalid for the current project")
}

if (profileName !in aptosConfig.profiles) {
return RsResult.Err("account '$profileName' is not present in the project's accounts")
}
// val aptosConfig = moveProject.aptosConfigYaml
// if (aptosConfig == null) {
// return RsResult.Err("Aptos account is not initialized / is invalid for the current project")
// }
//
// if (profileName !in aptosConfig.profiles) {
// return RsResult.Err("account '$profileName' is not present in the project's accounts")
// }
val transaction = FunctionCall.template(function)

val typeParameterNames = function.typeParameters.mapNotNull { it.name }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,18 @@ abstract class FunctionCallConfigurationBase(
val configurationHandler: CommandConfigurationHandler,
): CommandConfigurationBase(project, factory) {

var moveProject: MoveProject?
get() = workingDirectory?.let { project.moveProjectsService.findMoveProject(it) }
var moveProjectFromWorkingDirectory: MoveProject?
get() = workingDirectory?.let { wdir -> project.moveProjectsService.findMoveProjectForPath(wdir) }
set(value) {
workingDirectory = value?.contentRootPath
}

override fun getCliPath(project: Project): Path? = project.aptosPath

fun firstRunShouldOpenEditor(): Boolean {
val moveProject = moveProject ?: return true
val functionCall = configurationHandler
.parseCommand(moveProject, command).unwrapOrNull()?.second ?: return true
val moveProject = moveProjectFromWorkingDirectory ?: return true
val (_, functionCall) = configurationHandler
.parseCommand(moveProject, command).unwrapOrNull() ?: return true
return functionCall.parametersRequired()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ import org.move.cli.MoveProject
import org.move.cli.moveProjectsService
import org.move.stdext.RsResult
import org.move.utils.ui.whenItemSelectedFromUi
import org.move.utils.ui.whenTextChangedFromUi
import javax.swing.JComponent
import javax.swing.JLabel
import javax.swing.JTextField

data class MoveProjectItem(val moveProject: MoveProject) {
override fun toString(): String {
Expand All @@ -34,9 +36,9 @@ class FunctionCallConfigurationEditor<T : FunctionCallConfigurationBase>(
private var functionCall: FunctionCall? = null

private val projectComboBox: ComboBox<MoveProjectItem> = ComboBox()
private val accountComboBox: ComboBox<String> = ComboBox()
private val accountTextField = JTextField()

private val functionCallPanel = FunctionCallPanel(handler, moveProject)
private val functionParametersPanel = FunctionParametersPanel(handler, moveProject)

private val errorLabel = JLabel("")

Expand All @@ -51,27 +53,24 @@ class FunctionCallConfigurationEditor<T : FunctionCallConfigurationBase>(
projectComboBox.isEnabled = projectComboBox.model.size > 1
projectComboBox.selectedItem = MoveProjectItem(moveProject)

fillAccountsComboBox()

val editor = this
functionCallPanel.addFunctionCallListener(object : FunctionCallPanel.FunctionCallListener {
override fun functionCallChanged(functionCall: FunctionCall) {
functionParametersPanel.addFunctionCallListener(object : FunctionParameterPanelListener {
override fun functionParametersChanged(functionCall: FunctionCall) {
editor.functionCall = functionCall
}
})
functionCallPanel.reset(moveProject)
functionParametersPanel.setMoveProjectAndCompletionVariants(moveProject)
}

override fun resetEditorFrom(s: T) {
val moveProject = s.workingDirectory?.let { project.moveProjectsService.findMoveProject(it) }
val moveProject = s.workingDirectory?.let { project.moveProjectsService.findMoveProjectForPath(it) }
if (moveProject == null) {
setErrorText("Deserialization error: no Aptos project found in the specified working directory")
editorPanel.isVisible = false
this.signerAccount = null
this.functionCall = null
return
}
fillAccountsComboBox()

val res = handler.parseCommand(moveProject, s.command)
val (profile, functionCall) = when (res) {
Expand All @@ -85,27 +84,30 @@ class FunctionCallConfigurationEditor<T : FunctionCallConfigurationBase>(
}
}
this.signerAccount = profile
this.accountComboBox.selectedItem = profile
this.accountTextField.text = profile

functionCallPanel.updateFromFunctionCall(functionCall)
functionParametersPanel.updateFromFunctionCall(functionCall)
}

override fun applyEditorTo(s: T) {
functionParametersPanel.fireChangeEvent()
val moveProject = moveProject
val profile = signerAccount
val functionCall = functionCall

s.moveProject = moveProject
s.moveProjectFromWorkingDirectory = moveProject
if (profile != null && functionCall != null) {
s.command =
handler.generateCommand(moveProject, profile, functionCall).unwrapOrNull() ?: ""
} else {
s.command = ""
}

println("Command in applyEditorTo = ${s.command}")
}

override fun disposeEditor() {
Disposer.dispose(functionCallPanel)
Disposer.dispose(functionParametersPanel)
}

override fun createEditor(): JComponent {
Expand All @@ -132,21 +134,20 @@ class FunctionCallConfigurationEditor<T : FunctionCallConfigurationBase>(
.columns(COLUMNS_LARGE)
.whenItemSelectedFromUi {
moveProject = it.moveProject
fillAccountsComboBox()
functionCallPanel.reset(moveProject)
functionParametersPanel.setMoveProjectAndCompletionVariants(moveProject)
}
}
row("Account") {
cell(accountComboBox)
cell(accountTextField)
.align(AlignX.FILL)
// .horizontalAlign(HorizontalAlign.FILL)
.whenItemSelectedFromUi {
.whenTextChangedFromUi {
signerAccount = it
}
}
separator()
row {
cell(functionCallPanel)
cell(functionParametersPanel)
.align(AlignX.FILL + AlignY.FILL)
// .verticalAlign(VerticalAlign.FILL)
// .horizontalAlign(HorizontalAlign.FILL)
Expand All @@ -156,15 +157,6 @@ class FunctionCallConfigurationEditor<T : FunctionCallConfigurationBase>(
return editorPanel
}

fun fillAccountsComboBox() {
accountComboBox.removeAllItems()
val accounts = moveProject.aptosConfigYaml?.profiles.orEmpty()
accounts.forEach { accountName ->
accountComboBox.addItem(accountName)
}
accountComboBox.isEnabled = accountComboBox.model.size > 1
}

// private fun validateEditor() {
// val functionCall = this.functionCall
// if (functionCall == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import javax.swing.JButton
import javax.swing.JPanel

typealias TypeParamsMap = MutableMap<String, String?>
typealias ValueParamsMap = MutableMap<String, FunctionCallParam?>
//typealias ValueParamsMap = MutableMap<String, FunctionCallParam?>

class TypeParameterTextField(
project: Project,
Expand All @@ -48,18 +48,29 @@ class TypeParameterTextField(
}
}

class FunctionCallPanel(
val handler: CommandConfigurationHandler,
interface FunctionParameterPanelListener {
fun functionParametersChanged(functionCall: FunctionCall)
}

/**
* Panel that covers UI elements of transaction run / view Run Configurations
* Consists of:
* - function name (with completion variants)
* - type parameters
* - parameters
*/
class FunctionParametersPanel(
val commandHandler: CommandConfigurationHandler,
var moveProject: MoveProject,
) :
BorderLayoutPanel(), Disposable {

private lateinit var item: MvFunction
private lateinit var functionItem: MvFunction
private lateinit var typeParams: TypeParamsMap
private lateinit var valueParams: MutableMap<String, FunctionCallParam?>

private val functionCompletionField = CompletionTextField(project, "", emptyList())
private val functionApplyButton = JButton("Apply")
private val functionItemField = CompletionTextField(project, "", emptyList())
private val functionApplyButton = JButton("Select function")

private val functionValidator: ComponentValidator

Expand All @@ -68,63 +79,68 @@ class FunctionCallPanel(
init {
val panel = this

functionCompletionField.addDocumentListener(object : DocumentListener {
// enables Apply button if function name is changed and valid
functionItemField.addDocumentListener(object : DocumentListener {
override fun documentChanged(event: DocumentEvent) {
val oldFunctionName = panel.item.qualName?.editorText()
val oldFunctionName = panel.functionItem.qualName?.editorText()
val newFunctionName = event.document.text
functionApplyButton.isEnabled =
newFunctionName != oldFunctionName
&& handler.getFunction(moveProject, newFunctionName) != null
&& commandHandler.getFunctionItem(moveProject, newFunctionName) != null
}
})

// update type parameters form and value parameters form on "Apply" button click
functionApplyButton.addActionListener {
val itemName = functionCompletionField.text
val function = handler.getFunction(moveProject, itemName)
val itemName = functionItemField.text
val functionItem = commandHandler.getFunctionItem(moveProject, itemName)
?: error("Button should be disabled if function name is invalid")
val functionCall = function.instantiateCall()
val functionCall = functionItem.newFunctionCall()
this.updateFromFunctionCall(functionCall)
fireChangeEvent()
}

functionValidator = ComponentValidator(panel)
// validates
this.functionValidator = ComponentValidator(panel)
.withValidator(Supplier<ValidationInfo?> {
val text = functionCompletionField.text
if (text.isBlank()) return@Supplier ValidationInfo("Required", functionCompletionField)
val function = handler.getFunction(moveProject, text)
if (function == null) {
return@Supplier ValidationInfo("Invalid entry function", functionCompletionField)
val text = functionItemField.text
if (text.isBlank()) return@Supplier ValidationInfo("Required", functionItemField)
val functionItem = commandHandler.getFunctionItem(moveProject, text)
if (functionItem == null) {
return@Supplier ValidationInfo("Invalid entry function", functionItemField)
}
null
})
.andRegisterOnDocumentListener(functionCompletionField)
.installOn(functionCompletionField)
.andRegisterOnDocumentListener(functionItemField)
.installOn(functionItemField)
}

override fun dispose() {
}

fun updateFromFunctionCall(functionCall: FunctionCall) {
this.item = functionCall.item
this.functionItem = functionCall.item
this.typeParams = functionCall.typeParams
this.valueParams = functionCall.valueParams

this.functionCompletionField.text = functionCall.itemName() ?: ""
val completionVariants = handler.getFunctionCompletionVariants(moveProject)
this.functionCompletionField.setVariants(completionVariants)
this.functionItemField.text = functionCall.itemName() ?: ""

val completionVariants = commandHandler.getFunctionCompletionVariants(moveProject)
this.functionItemField.setVariants(completionVariants)

recreateInnerPanel()
functionValidator.revalidate()
}

fun reset(moveProject: MoveProject) {
fun setMoveProjectAndCompletionVariants(moveProject: MoveProject) {
this.moveProject = moveProject
val variants = handler.getFunctionCompletionVariants(moveProject)

this.item = variants.firstOrNull()
?.let { handler.getFunction(this.moveProject, it) }
val variants = commandHandler.getFunctionCompletionVariants(moveProject)
this.functionItem = variants.firstOrNull()
?.let { commandHandler.getFunctionItem(this.moveProject, it) }
?: error("Should always have one valid function")

val functionCall = this.item.instantiateCall()
val functionCall = this.functionItem.newFunctionCall()
updateFromFunctionCall(functionCall)
}

Expand All @@ -134,32 +150,28 @@ class FunctionCallPanel(
validate()
}

interface FunctionCallListener {
fun functionCallChanged(functionCall: FunctionCall)
}

private val eventListeners = mutableListOf<FunctionCallListener>()
private val eventListeners = mutableListOf<FunctionParameterPanelListener>()

fun addFunctionCallListener(listener: FunctionCallListener) {
fun addFunctionCallListener(listener: FunctionParameterPanelListener) {
eventListeners.add(listener)
}

private fun fireChangeEvent() {
val functionCall = FunctionCall(this.item, this.typeParams, this.valueParams)
fun fireChangeEvent() {
val functionCall = FunctionCall(this.functionItem, this.typeParams, this.valueParams)
eventListeners.forEach {
it.functionCallChanged(functionCall)
it.functionParametersChanged(functionCall)
}
}

private fun getInnerPanel(): JPanel {
val function = this.item
val function = this.functionItem
val outerPanel = this
return panel {
val typeParameters = function.typeParameters
val parameters = handler.getFunctionParameters(function).map { it.bindingPat }
val parameters = commandHandler.getFunctionParameters(function).map { it.bindingPat }

row("Function") {
cell(functionCompletionField)
cell(functionItemField)
.align(AlignX.FILL)
// .horizontalAlign(HorizontalAlign.FILL)
.resizableColumn()
Expand Down Expand Up @@ -224,4 +236,4 @@ class FunctionCallPanel(
}
}

fun MvFunction.instantiateCall(): FunctionCall = FunctionCall.template(this)
fun MvFunction.newFunctionCall(): FunctionCall = FunctionCall.template(this)
Loading

0 comments on commit 39c308b

Please sign in to comment.