Skip to content

Commit

Permalink
Merge pull request #161 from pontem-network/receiver-style-parameter-…
Browse files Browse the repository at this point in the history
…hints

parameter info, inlay parameter hints for receiver style functions
  • Loading branch information
mkurnikov authored Jun 16, 2024
2 parents 3429500 + b17283b commit 99edaa7
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 30 deletions.
4 changes: 2 additions & 2 deletions src/main/kotlin/org/move/ide/annotator/MvErrorAnnotator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import com.intellij.psi.PsiElement
import org.move.ide.presentation.fullname
import org.move.ide.presentation.itemDeclaredInModule
import org.move.ide.utils.functionSignature
import org.move.ide.utils.signature
import org.move.ide.utils.getSignature
import org.move.lang.MvElementTypes.R_PAREN
import org.move.lang.core.psi.*
import org.move.lang.core.psi.ext.*
Expand Down Expand Up @@ -65,7 +65,7 @@ class MvErrorAnnotator: MvAnnotatorBase() {

override fun visitItemSpec(itemSpec: MvItemSpec) {
val funcItem = itemSpec.funcItem ?: return
val funcSignature = funcItem.signature ?: return
val funcSignature = funcItem.getSignature() ?: return
val itemSpecSignature = itemSpec.itemSpecSignature ?: return

val specSignature = itemSpecSignature.functionSignature
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package org.move.ide.annotator.fixes
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiFile
import org.move.ide.inspections.DiagnosticIntentionFix
import org.move.ide.utils.signature
import org.move.ide.utils.getSignature
import org.move.lang.core.psi.MvItemSpec
import org.move.lang.core.psi.ext.funcItem
import org.move.lang.core.psi.psiFactory
Expand All @@ -17,7 +17,7 @@ class ItemSpecSignatureFix(

override fun invoke(project: Project, file: PsiFile, element: MvItemSpec) {
val itemSpec = startElement
val actualSignature = itemSpec.funcItem?.signature ?: return
val actualSignature = itemSpec.funcItem?.getSignature() ?: return

val psiFactory = project.psiFactory
val newSpecSignature = psiFactory.itemSpecSignature(actualSignature)
Expand Down
16 changes: 11 additions & 5 deletions src/main/kotlin/org/move/ide/hints/FunctionParameterInfoHandler.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiFile
import org.move.ide.utils.FunctionSignature
import org.move.lang.MvElementTypes
import org.move.lang.core.psi.MvCallExpr
import org.move.lang.core.psi.MvMethodCall
import org.move.lang.core.psi.MvStructLitFieldsBlock
import org.move.lang.core.psi.MvValueArgumentList
import org.move.lang.core.psi.ext.MvCallable
import org.move.lang.core.psi.ext.ancestorOrSelf
import org.move.lang.core.psi.ext.startOffset
import org.move.utils.AsyncParameterInfoHandlerBase

class FunctionParameterInfoHandler : AsyncParameterInfoHandlerBase<MvValueArgumentList, ParamsDescription>() {
class FunctionParameterInfoHandler: AsyncParameterInfoHandlerBase<MvValueArgumentList, ParamsDescription>() {

override fun findTargetElement(file: PsiFile, offset: Int): MvValueArgumentList? {
val element = file.findElementAt(offset) ?: return null
Expand Down Expand Up @@ -80,9 +81,14 @@ class ParamsDescription(val parameters: Array<String>) {
* Finds declaration of the func/method and creates description of its arguments
*/
fun findDescription(args: MvValueArgumentList): ParamsDescription? {
val signature =
(args.parent as? MvCallExpr)?.let { FunctionSignature.resolve(it) } ?: return null
val params = signature.parameters.map { "${it.name}: ${it.type}" }
val callable = args.parent as? MvCallable ?: return null
val signature = FunctionSignature.resolve(callable) ?: return null
val params =
when (callable) {
is MvMethodCall -> signature.parameters.drop(1)
else -> signature.parameters
}
.map { "${it.name}: ${it.type}" }
return ParamsDescription(params.toTypedArray())
}
}
Expand Down
22 changes: 12 additions & 10 deletions src/main/kotlin/org/move/ide/hints/InlayParameterHints.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,27 @@ package org.move.ide.hints
import com.intellij.codeInsight.hints.InlayInfo
import com.intellij.psi.PsiElement
import org.move.ide.utils.FunctionSignature
import org.move.lang.core.psi.MvCallExpr
import org.move.lang.core.psi.MvRefExpr
import org.move.lang.core.psi.MvStructLitExpr
import org.move.lang.core.psi.*
import org.move.lang.core.psi.ext.MvCallable
import org.move.lang.core.psi.ext.argumentExprs
import org.move.lang.core.psi.ext.startOffset

@Suppress("UnstableApiUsage")
object InlayParameterHints {
fun provideHints(elem: PsiElement): List<InlayInfo> {
if (elem !is MvCallExpr) return emptyList()

val signature = FunctionSignature.resolve(elem) ?: return emptyList()
return signature.parameters
fun provideHints(element: PsiElement): List<InlayInfo> {
if (element !is MvCallable) return emptyList()
val signature = FunctionSignature.resolve(element) ?: return emptyList()
val parameters = when (element) {
is MvMethodCall -> signature.parameters.drop(1)
else -> signature.parameters
}
return parameters
.map { it.name }
.zip(elem.argumentExprs)
.zip(element.argumentExprs)
.asSequence()
.filter { (_, arg) -> arg != null }
// don't show argument, if just function call / variable / struct literal
// .filter { (_, arg) -> arg !is MvRefExpr && arg !is MvCallExpr && arg !is MvStructLitExpr }
// .filter { (_, arg) -> arg !is MvRefExpr && arg !is MvCallExpr && arg !is MvStructLitExpr }
.filter { (_, arg) -> arg !is MvRefExpr && arg !is MvStructLitExpr }
.filter { (hint, arg) -> !isSimilar(hint, arg!!.text) }
.filter { (hint, _) -> hint != "_" }
Expand Down
27 changes: 16 additions & 11 deletions src/main/kotlin/org/move/ide/utils/FunctionSignature.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@ import com.intellij.openapi.util.Key
import com.intellij.psi.util.CachedValue
import com.intellij.psi.util.CachedValueProvider
import org.move.lang.core.psi.*
import org.move.lang.core.psi.ext.ability
import org.move.lang.core.psi.ext.abilityBounds
import org.move.lang.core.psi.ext.bounds
import org.move.lang.core.psi.ext.name
import org.move.lang.core.psi.ext.*
import org.move.lang.core.types.ty.Ability
import org.move.utils.cache
import org.move.utils.cacheManager
Expand Down Expand Up @@ -44,10 +41,18 @@ data class FunctionSignature(
}

companion object {
fun resolve(callExpr: MvCallExpr): FunctionSignature? {
val function = callExpr.path.reference?.resolveWithAliases() as? MvFunction
return function?.signature
}
fun resolve(callable: MvCallable): FunctionSignature? =
when (callable) {
is MvCallExpr -> {
val function = callable.path.reference?.resolveWithAliases() as? MvFunction
function?.getSignature()
}
is MvMethodCall -> {
val function = callable.reference.resolveWithAliases() as? MvFunction
function?.getSignature()
}
else -> null
}

fun fromFunction(function: MvFunction): FunctionSignature? {
val typeParameters = function.typeParameters
Expand Down Expand Up @@ -87,10 +92,10 @@ data class FunctionSignature(
}
}

private val SIGNATURE_KEY: Key<CachedValue<FunctionSignature?>> = Key.create("SIGNATURE_KEY")
private val FUNCTION_SIGNATURE_KEY: Key<CachedValue<FunctionSignature?>> = Key.create("SIGNATURE_KEY")

val MvFunction.signature: FunctionSignature?
get() = project.cacheManager.cache(this, SIGNATURE_KEY) {
fun MvFunction.getSignature(): FunctionSignature? =
project.cacheManager.cache(this, FUNCTION_SIGNATURE_KEY) {
val signature = FunctionSignature.fromFunction(this)
CachedValueProvider.Result.create(
signature,
Expand Down
14 changes: 14 additions & 0 deletions src/test/kotlin/org/move/ide/hints/InlayParameterHintsTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package org.move.ide.hints

import com.intellij.codeInsight.daemon.impl.HintRenderer
import org.intellij.lang.annotations.Language
import org.move.utils.tests.CompilerV2
import org.move.utils.tests.MvTestBase

class InlayParameterHintsTest : MvTestBase() {
Expand Down Expand Up @@ -61,6 +62,19 @@ class InlayParameterHintsTest : MvTestBase() {
"""
)

@CompilerV2
fun `test receiver style fun`() = checkByText(
"""
module 0x1::m {
struct S { val: u8 }
fun get_val(self: &S, modifier: bool): u8 { self.val }
fun main(s: S) {
s.get_val(/*hint text="modifier:"*/true);
}
}
"""
)

private fun checkByText(@Language("Move") code: String) {
InlineFile(
code.trimIndent()
Expand Down
13 changes: 13 additions & 0 deletions src/test/kotlin/org/move/ide/hints/ParameterInfoHandlerTest.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.move.ide.hints

import org.move.lang.core.psi.MvValueArgumentList
import org.move.utils.tests.CompilerV2
import org.move.utils.tests.ParameterInfoHandlerTestCase

class ParameterInfoHandlerTest
Expand Down Expand Up @@ -124,4 +125,16 @@ class ParameterInfoHandlerTest
fun main() { call(42, 10, /*caret*/); }
}
""", "val1: u8, val2: u8, val3: u8", 2)

@CompilerV2
fun `test receiver style fun`() = checkByText(
"""
module 0x1::m {
struct S { val: u8 }
fun get_val(self: &S, modifier: bool): u8 { self.val }
fun main(s: S) {
s.get_val(/*caret*/);
}
}
""", "modifier: bool", 0)
}

0 comments on commit 99edaa7

Please sign in to comment.