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

Explicit type annotation for lambda expr parameters, hide inlay type hints in some places #240

Merged
merged 2 commits into from
Nov 11, 2024
Merged
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
18 changes: 16 additions & 2 deletions src/main/grammars/MoveParser.bnf
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ Const ::= Attr* CONST_KW IDENTIFIER TypeAscription Initializer ';'
implements = [
"org.move.lang.core.psi.MvQualNamedElement"
"org.move.lang.core.psi.ext.MvItemElement"
"org.move.lang.core.psi.ext.MvTypeAscriptionOwner"
]
mixin = "org.move.lang.core.psi.ext.MvConstMixin"
stubClass = "org.move.lang.core.stubs.MvConstStub"
Expand Down Expand Up @@ -521,6 +522,9 @@ private FunctionParameter_recover ::= !(')' | '{' | ';' | IDENTIFIER)

FunctionParameter ::= PatBinding TypeAscription {
pin = 1
implements = [
"org.move.lang.core.psi.ext.MvTypeAscriptionOwner"
]
mixin = "org.move.lang.core.psi.ext.MvFunctionParameterMixin"
}

Expand Down Expand Up @@ -589,6 +593,7 @@ NamedFieldDecl ::= Attr* IDENTIFIER TypeAscription &(',' | '}')
"org.move.lang.core.psi.MvMandatoryNameIdentifierOwner"
"org.move.lang.core.psi.ext.MvDocAndAttributeOwner"
"org.move.lang.core.psi.ext.MvFieldDecl"
"org.move.lang.core.psi.ext.MvTypeAscriptionOwner"
]
mixin = "org.move.lang.core.psi.ext.MvNamedFieldDeclMixin"
hooks = [ leftBinder = "ADJACENT_LINE_COMMENTS" ]
Expand Down Expand Up @@ -819,6 +824,9 @@ private SpecExprStmt_items ::= AssumeSpecExpr | AssertSpecExpr | AbortsIfSpecExp

private post ::= <<postKeyword>>
fake LetStmt ::= let post? Pat? TypeAscription? Initializer? ';'?
{
implements = [ "org.move.lang.core.psi.ext.MvTypeAscriptionOwner" ]
}

LetMoveStmt ::= let Pat TypeAscription? Initializer? ';'
{
Expand Down Expand Up @@ -1090,7 +1098,10 @@ upper TupleLitExprUpper ::= ',' [ Expr (',' Expr)* ','? ] ')' {
LambdaExpr ::= LambdaParameterList Expr? { pin = 1 }

LambdaParameterList ::= '|' !',' <<comma_separated_list LambdaParameter>>? '|'
LambdaParameter ::= PatBinding
LambdaParameter ::= PatBinding TypeAscription?
{
implements = [ "org.move.lang.core.psi.ext.MvTypeAscriptionOwner" ]
}

RangeExpr ::= Expr '..' Expr { pin = 2 }

Expand Down Expand Up @@ -1421,6 +1432,7 @@ ItemSpecFunctionParameter ::= IDENTIFIER TypeAscription {
pin = 1
implements = [
"org.move.lang.core.resolve.ref.MvItemSpecParameterReferenceElement"
"org.move.lang.core.psi.ext.MvTypeAscriptionOwner"
]
mixin = "org.move.lang.core.psi.ext.MvItemSpecFunctionParameterMixin"
}
Expand Down Expand Up @@ -1484,6 +1496,7 @@ fake SchemaFieldStmt ::= local? PatBinding TypeAscription ';'
{
implements = [
"org.move.lang.core.psi.MslOnlyElement"
"org.move.lang.core.psi.ext.MvTypeAscriptionOwner"
]
}

Expand All @@ -1505,6 +1518,7 @@ GlobalVariableStmt ::= Attr* global IDENTIFIER TypeParameterList? TypeAscription
"org.move.lang.core.psi.MvNameIdentifierOwner"
"org.move.lang.core.psi.MslOnlyElement"
"org.move.lang.core.psi.ext.MvItemElement"
"org.move.lang.core.psi.ext.MvTypeAscriptionOwner"
]
mixin = "org.move.lang.core.psi.ext.MvGlobalVariableMixin"
}
Expand Down Expand Up @@ -1756,7 +1770,7 @@ RangeQuantBinding ::= PatBinding in Expr {
pin = 2
extends = QuantBinding
}
TypeQuantBinding ::= PatBinding ':' Type {
TypeQuantBinding ::= PatBinding TypeAscription {
pin = 2
extends = QuantBinding
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,7 @@ import org.move.lang.core.psi.MvStruct
import org.move.lang.core.psi.MvType
import org.move.lang.core.psi.MvTypeParameter
import org.move.lang.core.psi.MvTypeParameterList
import org.move.lang.core.psi.ext.MvDocAndAttributeOwner
import org.move.lang.core.psi.ext.abilityBounds
import org.move.lang.core.psi.ext.ancestorOrSelf
import org.move.lang.core.psi.ext.bindingOwner
import org.move.lang.core.psi.ext.fieldOwner
import org.move.lang.core.psi.ext.isMsl
import org.move.lang.core.psi.ext.isMslOnlyItem
import org.move.lang.core.psi.ext.isPhantom
import org.move.lang.core.psi.ext.itemElement
import org.move.lang.core.psi.ext.module
import org.move.lang.core.psi.ext.*
import org.move.lang.core.psi.isNative
import org.move.lang.core.psi.module
import org.move.lang.core.types.infer.inference
Expand Down Expand Up @@ -88,11 +79,11 @@ class MvDocumentationTarget(val element: PsiElement, private val originalElement

fun generateDoc(element: PsiElement?): String? {
val buffer = StringBuilder()

var docElement = element
if (
docElement is MvPatBinding && docElement.bindingOwner is MvConst
)
docElement = docElement.bindingOwner
if (docElement is MvPatBinding && docElement.bindingTypeOwner is MvConst) {
docElement = docElement.bindingTypeOwner
}

when (docElement) {
is MvNamedAddress -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,22 @@ import com.intellij.codeInsight.hints.declarative.HintFontSize.ABitSmallerThanIn
import com.intellij.openapi.editor.Editor
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import org.move.ide.presentation.hintText
import org.move.lang.core.psi.MvConst
import org.move.lang.core.psi.MvForIterCondition
import org.move.lang.core.psi.MvFunctionParameter
import org.move.lang.core.psi.MvLambdaParameter
import org.move.lang.core.psi.MvLetStmt
import org.move.lang.core.psi.MvPat
import org.move.lang.core.psi.MvPatBinding
import org.move.lang.core.psi.MvPatField
import org.move.lang.core.psi.MvPatFieldFull
import org.move.lang.core.psi.MvRangeQuantBinding
import org.move.lang.core.psi.MvSchemaFieldStmt
import org.move.lang.core.psi.ext.bindingOwner
import org.move.lang.core.psi.ext.endOffset
import org.move.lang.core.psi.ext.hasAncestor
import org.move.lang.core.psi.ext.isMsl
import org.move.lang.core.types.infer.inferenceOwner
import org.move.lang.core.psi.MvTypeQuantBinding
import org.move.lang.core.psi.ext.*
import org.move.lang.core.types.infer.inference
import org.move.lang.core.types.ty.*
import org.move.lang.core.types.infer.inferenceOwner
import org.move.lang.core.types.ty.TyUnknown

class MvTypeInlayHintsProvider2: InlayHintsProvider {

Expand All @@ -33,12 +37,32 @@ class MvTypeInlayHintsProvider2: InlayHintsProvider {
// skip private variables
if (patBinding.name.startsWith("_")) return

// does not show hints for bindings with explicit type annotations
val owner = patBinding.bindingOwner
if (owner is MvFunctionParameter || owner is MvSchemaFieldStmt) return
val parent = patBinding.bindingTypeOwner
when (parent) {
// require explicit type annotations
is MvFunctionParameter, is MvConst, is MvSchemaFieldStmt, is MvTypeQuantBinding -> return
is MvLambdaParameter -> {
// if lambda parameter has explicit type
if (parent.type != null) return
}
is MvPatFieldFull -> {
// skip hints for `field: field_alias`
return
}
is MvLetStmt -> {
// explicit type for let stmt
if (parent.type != null) return
}
is MvPatField -> {
// field shorthand, show type hint
}
is MvForIterCondition, is MvRangeQuantBinding -> {
// show hints for iteration indexes
}
else -> return
}

val contextInferenceOwner = patBinding.inferenceOwner() ?: return

val msl = patBinding.isMsl()
val ty = contextInferenceOwner.inference(msl).getBindingType(patBinding)
if (ty is TyUnknown) return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ class MvUnresolvedReferenceInspection: MvLocalInspectionTool() {
override fun visitSchemaLitField(field: MvSchemaLitField) {
if (field.isShorthand) {
val resolvedItems = field.reference.multiResolve()
val fieldBinding = resolvedItems.find { it is MvPatBinding && it.bindingOwner is MvSchemaFieldStmt }
val fieldBinding = resolvedItems
.find { it is MvPatBinding && it.bindingTypeOwner is MvSchemaFieldStmt }
if (fieldBinding == null) {
holder.registerProblem(
field.referenceNameElement,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ import com.intellij.psi.util.descendantsOfType
import org.move.ide.inspections.fixes.RemoveParameterFix
import org.move.ide.inspections.fixes.RenameFix
import org.move.lang.core.psi.*
import org.move.lang.core.psi.ext.bindingTypeOwner
import org.move.lang.core.psi.ext.isMsl
import org.move.lang.core.psi.ext.bindingOwner

class MvUnusedVariableInspection : MvLocalInspectionTool() {
class MvUnusedVariableInspection: MvLocalInspectionTool() {
override fun buildMvVisitor(holder: ProblemsHolder, isOnTheFly: Boolean) =
object : MvVisitor() {
object: MvVisitor() {
override fun visitLetStmt(o: MvLetStmt) {
val bindings = o.pat?.descendantsOfType<MvPatBinding>().orEmpty()
for (binding in bindings) {
Expand All @@ -37,7 +37,7 @@ class MvUnusedVariableInspection : MvLocalInspectionTool() {
// filter out #[test] attributes
.filter { it.element !is MvAttrItem }
if (references.none()) {
val fixes = when (binding.bindingOwner) {
val fixes = when (binding.bindingTypeOwner) {
is MvFunctionParameter -> arrayOf(
RenameFix(binding, "_$bindingName"),
RemoveParameterFix(binding, bindingName)
Expand Down
4 changes: 2 additions & 2 deletions src/main/kotlin/org/move/ide/presentation/PresentationInfo.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package org.move.ide.presentation

import org.move.lang.core.psi.*
import org.move.lang.core.psi.ext.bindingOwner
import org.move.lang.core.psi.ext.bindingTypeOwner

class PresentationInfo(
val element: MvNamedElement,
Expand All @@ -16,7 +16,7 @@ val MvNamedElement.presentationInfo: PresentationInfo?
val type = when (this) {
is MvTypeParameter -> "type parameter"
is MvPatBinding -> {
val owner = this.bindingOwner
val owner = this.bindingTypeOwner
when (owner) {
is MvFunctionParameter -> "value parameter"
is MvLetStmt -> "variable"
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/org/move/lang/MoveParserDefinition.kt
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,6 @@ class MoveParserDefinition : ParserDefinition {
/**
* Should be increased after any change of parser rules
*/
const val PARSER_VERSION: Int = LEXER_VERSION + 52
const val PARSER_VERSION: Int = LEXER_VERSION + 53
}
}
15 changes: 13 additions & 2 deletions src/main/kotlin/org/move/lang/core/psi/ext/MvBindingPat.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,23 @@ import org.move.lang.core.resolve2.ref.MvBindingPatReferenceImpl
import org.move.lang.core.types.ty.Mutability
import javax.swing.Icon

// todo: replace with bindingTypeOwner later
val MvPatBinding.bindingOwner: PsiElement?
get() = PsiTreeUtil.findFirstParent(this) {
it is MvLetStmt
|| it is MvFunctionParameter
|| it is MvSchemaFieldStmt
|| it is MvLambdaParameter
|| it is MvConst
}

val MvPatBinding.bindingTypeOwner: PsiElement?
get() {
var owner = this.parent
if (owner is MvPat) {
owner = this.findFirstParent { it is MvTypeAscriptionOwner }
}
return owner
}

sealed class RsBindingModeKind {
Expand All @@ -45,14 +56,14 @@ abstract class MvPatBindingMixin(node: ASTNode) : MvMandatoryNameIdentifierOwner
override val referenceName: String get() = name

override fun getIcon(flags: Int): Icon =
when (this.bindingOwner) {
when (this.bindingTypeOwner) {
is MvFunctionParameter -> MoveIcons.PARAMETER
is MvConst -> MoveIcons.CONST
else -> MoveIcons.VARIABLE
}

override fun getUseScope(): SearchScope {
return when (this.bindingOwner) {
return when (this.bindingTypeOwner) {
is MvFunctionParameter -> {
val function = this.ancestorStrict<MvFunction>() ?: return super.getUseScope()
var combinedScope: SearchScope = LocalSearchScope(function)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.move.lang.core.psi.ext

import org.move.lang.core.psi.MvElement
import org.move.lang.core.psi.MvType

interface MvTypeAscriptionOwner: MvElement {
val type: MvType?
}
41 changes: 41 additions & 0 deletions src/test/kotlin/org/move/ide/hints/InlayTypeHintsProvider2Test.kt
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,47 @@ class InlayTypeHintsProvider2Test: DeclarativeInlayHintsProviderTestCase() {
}
""")

fun `test no inlay hint if explicit lambda param declared`() = checkByText("""
module 0x1::m {
fun callback(elem: u8, ident: |u8|u8): u8 { ident(elem) }
fun main() {
callback(10, |elem: u8| elem + 1);
}
}
""")

fun `test no inlay hint if explicit let type`() = checkByText("""
module 0x1::m {
fun main() {
let a: u8 = 1;
}
}
""")

fun `test no inlay hints for struct pattern destructor`() = checkByText("""
module 0x1::m {
struct S { val: u8 }
fun main(s: S) {
let S { val: myval } = s;
}
}
""")

fun `test inlay hints for struct pattern destructor shorthand`() = checkByText("""
module 0x1::m {
struct S { val: u8 }
fun main(s: S) {
let S { val/*<# : |u8 #>*/ } = s;
}
}
""")

fun `test no inlay hint for const`() = checkByText("""
module 0x1::m {
const MY_CONST: u8 = 1;
}
""")

private fun checkByText(@Language("Move") code: String) {
doTestProvider("main.move", code, MvTypeInlayHintsProvider2())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class CompleteParsingTest: MvParsingTestCase("complete") {
fun `test loop invariants`() = doTest()
fun `test loop labels`() = doTest()
fun `test assign bin expr`() = doTest()
fun `test lambdas`() = doTest()

fun doTest() {
super.doTest(true, true)
Expand Down
6 changes: 6 additions & 0 deletions src/test/resources/org/move/lang/parser/complete/lambdas.move
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module 0x1::lambdas {
fun main() {
for_each(v, |f: &Function| {});
for_each(v, |i: u8, g: u8| {});
}
}
Loading