From 39c308bc94bfaa163ffb972d7ac317e28bceb553 Mon Sep 17 00:00:00 2001 From: Maksim Kurnikov Date: Sun, 24 Mar 2024 02:37:49 +0300 Subject: [PATCH] fix run/view function call, remove automatic account fill --- .../org/move/cli/MoveProjectsService.kt | 4 +- .../aptos/CommandConfigurationHandler.kt | 22 +++-- .../aptos/FunctionCallConfigurationBase.kt | 10 +- .../aptos/FunctionCallConfigurationEditor.kt | 46 ++++----- ...allPanel.kt => FunctionParametersPanel.kt} | 96 +++++++++++-------- .../run/RunCommandConfigurationHandler.kt | 2 +- .../view/ViewCommandConfigurationHandler.kt | 2 +- .../ide/inspections/MvLocalInspectionTool.kt | 2 +- src/main/kotlin/org/move/lang/MoveFile.kt | 3 +- .../org/move/lang/core/psi/ext/MvElement.kt | 2 +- .../org/move/lang/NamedAddressValuesTest.kt | 2 +- 11 files changed, 98 insertions(+), 93 deletions(-) rename src/main/kotlin/org/move/cli/runConfigurations/aptos/{FunctionCallPanel.kt => FunctionParametersPanel.kt} (69%) diff --git a/src/main/kotlin/org/move/cli/MoveProjectsService.kt b/src/main/kotlin/org/move/cli/MoveProjectsService.kt index 36e473a52..444de64df 100644 --- a/src/main/kotlin/org/move/cli/MoveProjectsService.kt +++ b/src/main/kotlin/org/move/cli/MoveProjectsService.kt @@ -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) { @@ -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) } diff --git a/src/main/kotlin/org/move/cli/runConfigurations/aptos/CommandConfigurationHandler.kt b/src/main/kotlin/org/move/cli/runConfigurations/aptos/CommandConfigurationHandler.kt index 3b8baf9f2..4c7b18e54 100644 --- a/src/main/kotlin/org/move/cli/runConfigurations/aptos/CommandConfigurationHandler.kt +++ b/src/main/kotlin/org/move/cli/runConfigurations/aptos/CommandConfigurationHandler.kt @@ -48,7 +48,7 @@ abstract class CommandConfigurationHandler { abstract fun getFunctionCompletionVariants(moveProject: MoveProject): Collection - abstract fun getFunction(moveProject: MoveProject, functionQualName: String): MvFunction? + abstract fun getFunctionItem(moveProject: MoveProject, functionQualName: String): MvFunction? abstract fun getFunctionByCmdName(moveProject: MoveProject, functionCmdName: String): MvFunction? @@ -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( @@ -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 } diff --git a/src/main/kotlin/org/move/cli/runConfigurations/aptos/FunctionCallConfigurationBase.kt b/src/main/kotlin/org/move/cli/runConfigurations/aptos/FunctionCallConfigurationBase.kt index be7ca1399..54796a53c 100644 --- a/src/main/kotlin/org/move/cli/runConfigurations/aptos/FunctionCallConfigurationBase.kt +++ b/src/main/kotlin/org/move/cli/runConfigurations/aptos/FunctionCallConfigurationBase.kt @@ -14,8 +14,8 @@ 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 } @@ -23,9 +23,9 @@ abstract class FunctionCallConfigurationBase( 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() } } diff --git a/src/main/kotlin/org/move/cli/runConfigurations/aptos/FunctionCallConfigurationEditor.kt b/src/main/kotlin/org/move/cli/runConfigurations/aptos/FunctionCallConfigurationEditor.kt index ad22f82aa..a87eafe6f 100644 --- a/src/main/kotlin/org/move/cli/runConfigurations/aptos/FunctionCallConfigurationEditor.kt +++ b/src/main/kotlin/org/move/cli/runConfigurations/aptos/FunctionCallConfigurationEditor.kt @@ -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 { @@ -34,9 +36,9 @@ class FunctionCallConfigurationEditor( private var functionCall: FunctionCall? = null private val projectComboBox: ComboBox = ComboBox() - private val accountComboBox: ComboBox = ComboBox() + private val accountTextField = JTextField() - private val functionCallPanel = FunctionCallPanel(handler, moveProject) + private val functionParametersPanel = FunctionParametersPanel(handler, moveProject) private val errorLabel = JLabel("") @@ -51,19 +53,17 @@ class FunctionCallConfigurationEditor( 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 @@ -71,7 +71,6 @@ class FunctionCallConfigurationEditor( this.functionCall = null return } - fillAccountsComboBox() val res = handler.parseCommand(moveProject, s.command) val (profile, functionCall) = when (res) { @@ -85,27 +84,30 @@ class FunctionCallConfigurationEditor( } } 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 { @@ -132,21 +134,20 @@ class FunctionCallConfigurationEditor( .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) @@ -156,15 +157,6 @@ class FunctionCallConfigurationEditor( 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) { diff --git a/src/main/kotlin/org/move/cli/runConfigurations/aptos/FunctionCallPanel.kt b/src/main/kotlin/org/move/cli/runConfigurations/aptos/FunctionParametersPanel.kt similarity index 69% rename from src/main/kotlin/org/move/cli/runConfigurations/aptos/FunctionCallPanel.kt rename to src/main/kotlin/org/move/cli/runConfigurations/aptos/FunctionParametersPanel.kt index 9ed45caa2..cca7983d0 100644 --- a/src/main/kotlin/org/move/cli/runConfigurations/aptos/FunctionCallPanel.kt +++ b/src/main/kotlin/org/move/cli/runConfigurations/aptos/FunctionParametersPanel.kt @@ -21,7 +21,7 @@ import javax.swing.JButton import javax.swing.JPanel typealias TypeParamsMap = MutableMap -typealias ValueParamsMap = MutableMap +//typealias ValueParamsMap = MutableMap class TypeParameterTextField( project: Project, @@ -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 - 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 @@ -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 { - 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) } @@ -134,32 +150,28 @@ class FunctionCallPanel( validate() } - interface FunctionCallListener { - fun functionCallChanged(functionCall: FunctionCall) - } - - private val eventListeners = mutableListOf() + private val eventListeners = mutableListOf() - 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() @@ -224,4 +236,4 @@ class FunctionCallPanel( } } -fun MvFunction.instantiateCall(): FunctionCall = FunctionCall.template(this) +fun MvFunction.newFunctionCall(): FunctionCall = FunctionCall.template(this) diff --git a/src/main/kotlin/org/move/cli/runConfigurations/aptos/run/RunCommandConfigurationHandler.kt b/src/main/kotlin/org/move/cli/runConfigurations/aptos/run/RunCommandConfigurationHandler.kt index 29153e3bd..66a97b635 100644 --- a/src/main/kotlin/org/move/cli/runConfigurations/aptos/run/RunCommandConfigurationHandler.kt +++ b/src/main/kotlin/org/move/cli/runConfigurations/aptos/run/RunCommandConfigurationHandler.kt @@ -17,7 +17,7 @@ class RunCommandConfigurationHandler : CommandConfigurationHandler() { override fun functionPredicate(function: MvFunction): Boolean = function.isEntry && !function.hasTestAttr - override fun getFunction(moveProject: MoveProject, functionQualName: String): MvFunction? { + override fun getFunctionItem(moveProject: MoveProject, functionQualName: String): MvFunction? { return getEntryFunction(moveProject, functionQualName) } diff --git a/src/main/kotlin/org/move/cli/runConfigurations/aptos/view/ViewCommandConfigurationHandler.kt b/src/main/kotlin/org/move/cli/runConfigurations/aptos/view/ViewCommandConfigurationHandler.kt index 2c6a8224d..185e40a94 100644 --- a/src/main/kotlin/org/move/cli/runConfigurations/aptos/view/ViewCommandConfigurationHandler.kt +++ b/src/main/kotlin/org/move/cli/runConfigurations/aptos/view/ViewCommandConfigurationHandler.kt @@ -17,7 +17,7 @@ class ViewCommandConfigurationHandler : CommandConfigurationHandler() { override fun functionPredicate(function: MvFunction): Boolean = function.isView && !function.hasTestAttr - override fun getFunction(moveProject: MoveProject, functionQualName: String): MvFunction? { + override fun getFunctionItem(moveProject: MoveProject, functionQualName: String): MvFunction? { return getViewFunction(moveProject, functionQualName) } diff --git a/src/main/kotlin/org/move/ide/inspections/MvLocalInspectionTool.kt b/src/main/kotlin/org/move/ide/inspections/MvLocalInspectionTool.kt index 810b9b6ef..71100a487 100644 --- a/src/main/kotlin/org/move/ide/inspections/MvLocalInspectionTool.kt +++ b/src/main/kotlin/org/move/ide/inspections/MvLocalInspectionTool.kt @@ -44,7 +44,7 @@ abstract class MvLocalInspectionTool : LocalInspectionTool() { private fun isApplicableTo(file: MoveFile): Boolean { if (isUnitTestMode) return true if (isSyntaxOnly) return true - return file.project.moveProjectsService.findMoveProject(file) != null + return file.project.moveProjectsService.findMoveProjectForPsiElement(file) != null } } diff --git a/src/main/kotlin/org/move/lang/MoveFile.kt b/src/main/kotlin/org/move/lang/MoveFile.kt index 4419bfe65..e65dc18d4 100644 --- a/src/main/kotlin/org/move/lang/MoveFile.kt +++ b/src/main/kotlin/org/move/lang/MoveFile.kt @@ -17,7 +17,6 @@ import org.move.lang.core.psi.* import org.move.lang.core.psi.ext.ancestorOrSelf import org.move.lang.core.psi.ext.childrenOfType import org.move.lang.core.psi.ext.modules -import org.move.openapiext.checkReadAccessAllowed import org.move.openapiext.resolveAbsPath import org.move.openapiext.toPsiFile import org.move.stdext.chain @@ -38,7 +37,7 @@ fun findMoveTomlPath(currentFilePath: Path): Path? { // requires ReadAccess val PsiElement.moveProject: MoveProject? get() { - return project.moveProjectsService.findMoveProject(this) + return project.moveProjectsService.findMoveProjectForPsiElement(this) } fun VirtualFile.hasChild(name: String) = this.findChild(name) != null diff --git a/src/main/kotlin/org/move/lang/core/psi/ext/MvElement.kt b/src/main/kotlin/org/move/lang/core/psi/ext/MvElement.kt index a489699a5..d7d2807c8 100644 --- a/src/main/kotlin/org/move/lang/core/psi/ext/MvElement.kt +++ b/src/main/kotlin/org/move/lang/core/psi/ext/MvElement.kt @@ -21,7 +21,7 @@ fun MvElement.isInsideAssignmentLhs(): Boolean { fun PsiFileSystemItem.findMoveProject(): MoveProject? { if (this is MoveFile) return this.moveProject val path = virtualFile.toNioPathOrNull() ?: return null - return project.moveProjectsService.findMoveProject(path) + return project.moveProjectsService.findMoveProjectForPath(path) } //private val MSL_KEY: Key> = Key.create("SIGNATURE_KEY") diff --git a/src/test/kotlin/org/move/lang/NamedAddressValuesTest.kt b/src/test/kotlin/org/move/lang/NamedAddressValuesTest.kt index b0c65d83e..64a3c25b5 100644 --- a/src/test/kotlin/org/move/lang/NamedAddressValuesTest.kt +++ b/src/test/kotlin/org/move/lang/NamedAddressValuesTest.kt @@ -189,7 +189,7 @@ class NamedAddressValuesTest : MvProjectTestBase() { val (address, data) = myFixture.findElementAndDataInEditor() val expectedValue = data.trim() - val moveProject = project.moveProjectsService.findMoveProject(address)!! + val moveProject = project.moveProjectsService.findMoveProjectForPsiElement(address)!! val actualValue = moveProject.getNamedAddress(address.referenceName)!!.text() check(actualValue == expectedValue) {