Skip to content

Commit

Permalink
Merge pull request #229 from pontem-network/match-improvements
Browse files Browse the repository at this point in the history
Match improvements
  • Loading branch information
mkurnikov authored Nov 8, 2024
2 parents 069a603 + 6c04aba commit 282b595
Show file tree
Hide file tree
Showing 13 changed files with 119 additions and 41 deletions.
2 changes: 1 addition & 1 deletion src/main/grammars/MoveParser.bnf
Original file line number Diff line number Diff line change
Expand Up @@ -1135,7 +1135,7 @@ MatchExpr ::= Attr* <<remapContextualKwOnRollback (match MatchArgument MatchBody
{
implements = [ "org.move.lang.core.psi.ext.MvDocAndAttributeOwner" ]
}
MatchArgument ::= '(' Expr ')'
MatchArgument ::= '(' Expr ')' { pin = 1 }

MatchBody ::= '{' MatchArm_with_recover* '}' { pin = 1 }
MatchArm ::= Attr* Pat MatchArmGuard? '=>' Expr ','?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,13 @@ class MvStructureViewTreeElement(val element: NavigatablePsiElement): StructureV
listOf(
element.consts(),
element.structs(),
element.enumList,
element.allFunctions(),
element.specFunctions(),
).flatten()
}
is MvStruct -> element.namedFields
is MvFieldsOwner -> element.namedFields
is MvEnum -> element.variants
else -> emptyList()
}
return items.map { MvStructureViewTreeElement(it) }.toTypedArray()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package org.move.ide.utils.imports

import com.intellij.codeInsight.completion.CompletionParameters
import com.intellij.codeInsight.completion.PrefixMatcher
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import org.move.ide.inspections.imports.ImportContext
import org.move.lang.core.psi.MvQualNamedElement
import org.move.lang.core.resolve.VisibilityStatus.Visible
Expand All @@ -21,9 +19,12 @@ object ImportCandidateCollector {

val candidates = mutableListOf<ImportCandidate>()
val elementsFromIndex = MvNamedElementIndex.getElementsByName(project, targetName, indexSearchScope)
for (elementFromIndex in elementsFromIndex) {
if (elementFromIndex !is MvQualNamedElement) continue

for ((i, elementFromIndex) in elementsFromIndex.withIndex()) {
// check for cancellation sometimes
if (i % 100 == 0) ProgressManager.checkCanceled()

if (elementFromIndex !is MvQualNamedElement) continue
if (elementFromIndex.namespace !in ns) continue

val visFilter = elementFromIndex.visInfo().createFilter()
Expand All @@ -47,18 +48,15 @@ object ImportCandidateCollector {
prefixMatcher: PrefixMatcher,
processedPathNames: Set<String>,
importContext: ImportContext,
// itemFilter: (PsiElement) -> Boolean = { true }
): List<ImportCandidate> {
val keys = hashSetOf<String>().apply {
val names = MvNamedElementIndex.getAllKeys(project)
addAll(names)
removeAll(processedPathNames)
}

return prefixMatcher.sortMatching(keys)
.flatMap { targetName ->
ProgressManager.checkCanceled()
getImportCandidates(importContext, targetName).distinctBy { it.element }
}
val matchingKeys = prefixMatcher.sortMatching(keys)
return matchingKeys.flatMap { targetName ->
getImportCandidates(importContext, targetName).distinctBy { it.element }
}
}
}
1 change: 1 addition & 0 deletions src/main/kotlin/org/move/ide/utils/imports/ImportUtils.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.move.ide.utils.imports

import com.intellij.util.concurrency.annotations.RequiresWriteLock
import org.move.ide.inspections.imports.usageScope
import org.move.lang.core.psi.*
import org.move.lang.core.psi.ext.*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package org.move.lang.core.completion.providers

import com.intellij.codeInsight.completion.CompletionParameters
import com.intellij.codeInsight.completion.CompletionResultSet
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.progress.checkCanceled
import com.intellij.patterns.ElementPattern
import com.intellij.psi.PsiElement
import com.intellij.util.ProcessingContext
Expand Down Expand Up @@ -91,6 +93,8 @@ object MvPathCompletionProvider2: MvCompletionProvider() {
)
}

ProgressManager.checkCanceled()

addCompletionsForOutOfScopeItems(
parameters,
pathElement,
Expand Down Expand Up @@ -127,6 +131,7 @@ object MvPathCompletionProvider2: MvCompletionProvider() {
processedNames,
importContext,
)

var candidatesCollector = createProcessor { e ->
e as CandidateScopeEntry
val lookupElement = e.element.createLookupElement(
Expand All @@ -138,6 +143,7 @@ object MvPathCompletionProvider2: MvCompletionProvider() {
}
candidatesCollector =
applySharedCompletionFilters(ns, completionContext.resolutionCtx!!, candidatesCollector)

candidatesCollector.processAll(
candidates.map { CandidateScopeEntry(it.qualName.itemName, it.element, ns, it) }
)
Expand Down
12 changes: 12 additions & 0 deletions src/main/kotlin/org/move/lang/core/psi/ext/MvEnum.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.move.lang.core.psi.ext

import com.intellij.ide.projectView.PresentationData
import com.intellij.lang.ASTNode
import com.intellij.navigation.ItemPresentation
import com.intellij.psi.PsiElement
import com.intellij.psi.stubs.IStubElementType
import org.move.ide.MoveIcons
Expand Down Expand Up @@ -41,5 +43,15 @@ abstract class MvEnumMixin: MvStubbedNamedElementImpl<MvEnumStub>,
return ItemQualName(this, moduleFQName.address, moduleFQName.itemName, itemName)
}

override fun getPresentation(): ItemPresentation? {
val enumName = this.name ?: return null
return PresentationData(
enumName,
this.locationString(true),
MoveIcons.STRUCT,
null
)
}

override val abilitiesList: MvAbilitiesList? get() = abilitiesListList.firstOrNull()
}
23 changes: 23 additions & 0 deletions src/main/kotlin/org/move/lang/core/psi/ext/MvEnumVariant.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.move.lang.core.psi.ext

import com.intellij.ide.projectView.PresentationData
import com.intellij.lang.ASTNode
import com.intellij.navigation.ItemPresentation
import com.intellij.psi.stubs.IStubElementType
import org.move.ide.MoveIcons
import org.move.lang.core.psi.MvEnum
Expand All @@ -20,4 +22,25 @@ abstract class MvEnumVariantMixin: MvStubbedNamedElementImpl<MvEnumVariantStub>,
constructor(stub: MvEnumVariantStub, nodeType: IStubElementType<*, *>): super(stub, nodeType)

override fun getIcon(flags: Int): Icon = MoveIcons.STRUCT

override fun getPresentation(): ItemPresentation? {
val variant = this
val variantName = this.name ?: return null
val presentationText = buildString {
append(variantName)
val fields = variant.tupleFields
if (fields != null) {
append('(')
val xs = fields.tupleFieldDeclList.map { it.type.text }
append(xs.joinToString(", "))
append(')')
}
}
return PresentationData(
presentationText,
this.locationString(true),
MoveIcons.ENUM_VARIANT,
null
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1179,10 +1179,11 @@ class TypeInferenceWalker(
}

private fun inferMatchExprTy(matchExpr: MvMatchExpr): Ty {
val matchingTy = ctx.resolveTypeVarsIfPossible(matchExpr.matchArgument.expr.inferType())
val matchArgExpr = matchExpr.matchArgument.expr ?: return TyUnknown
val matchArgTy = ctx.resolveTypeVarsIfPossible(matchArgExpr.inferType())
val arms = matchExpr.arms
for (arm in arms) {
arm.pat.extractBindings(matchingTy)
arm.pat.extractBindings(patTy = matchArgTy)
arm.expr?.inferType()
arm.matchArmGuard?.expr?.inferType(TyBool)
}
Expand Down Expand Up @@ -1212,8 +1213,8 @@ class TypeInferenceWalker(
updateStmt.exprList.forEach { it.inferType() }
}

private fun MvPat.extractBindings(ty: Ty) {
this.extractBindings(this@TypeInferenceWalker, ty)
private fun MvPat.extractBindings(patTy: Ty) {
this.extractBindings(this@TypeInferenceWalker, patTy)
}

private fun checkTypeMismatch(
Expand Down
4 changes: 2 additions & 2 deletions src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,10 @@

<completion.confidence language="Move"
implementationClass="org.move.lang.core.completion.MvCompletionConfidence" />
<completion.contributor language="Move"
implementationClass="org.move.lang.core.completion.CommonCompletionContributor" />
<completion.contributor language="Move"
implementationClass="org.move.lang.core.completion.KeywordCompletionContributor" />
<completion.contributor language="Move"
implementationClass="org.move.lang.core.completion.CommonCompletionContributor" />
<completion.contributor language="Move"
implementationClass="org.move.lang.core.completion.MoveTextFieldCompletionContributor" />
<completion.contributor language="TOML"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ address 0x1 {
struct Struct2 {
field2: u8
}
enum S { One, Two, Three { val: u8 }, Four(u8, u8)}
public fun call_pub() {}
public(friend) fun call_pub_friend() {}
entry fun call_entry() {}
Expand All @@ -59,6 +60,12 @@ address 0x1 {
field1: u8
-Struct2
field2: u8
-S
One
Two
-Three
val: u8
Four(u8, u8)
call_pub()
call_pub_friend()
call_entry()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,18 @@ module 0x1::Main {
"""
)

@MoveV2
fun `test match keyword should be before the main function`() = checkCompletionsOrder(
listOf("match", "main"),
"""
module 0x1::mod {
fun main() {
m/*caret*/
}
}
"""
)

private fun checkCompletionsOrder(listStart: List<String>, @Language("Move") code: String) {
val variants = completionFixture.invokeCompletion(code)
val lookupStrings = variants.map { it.lookupString }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,7 @@ module 0x1::enum_match {
match (s) { Red }
match (s) { Red => }
match (s) { Red => true, Blue => }

match () {}
}
}
58 changes: 36 additions & 22 deletions src/test/resources/org/move/lang/parser/partial/enum_match.txt
Original file line number Diff line number Diff line change
Expand Up @@ -100,37 +100,51 @@ FILE
PsiWhiteSpace(' ')
PsiElement(})('}')
PsiWhiteSpace('\n ')
MvExprStmtImpl(EXPR_STMT)
MvMatchExprImpl(MATCH_EXPR)
PsiElement(match_kw)('match')
PsiWhiteSpace(' ')
MvMatchArgumentImpl(MATCH_ARGUMENT)
PsiElement(()('(')
MvPathExprImpl(PATH_EXPR)
MvPathImpl(PATH)
PsiElement(IDENTIFIER)('s')
PsiElement())(')')
PsiWhiteSpace(' ')
MvMatchBodyImpl(MATCH_BODY)
PsiElement({)('{')
PsiWhiteSpace(' ')
MvMatchArmImpl(MATCH_ARM)
MvPatBindingImpl(PAT_BINDING)
PsiElement(IDENTIFIER)('Red')
PsiWhiteSpace(' ')
PsiElement(=>)('=>')
PsiWhiteSpace(' ')
MvLitExprImpl(LIT_EXPR)
PsiElement(BOOL_LITERAL)('true')
PsiElement(,)(',')
PsiWhiteSpace(' ')
MvMatchArmImpl(MATCH_ARM)
MvPatBindingImpl(PAT_BINDING)
PsiElement(IDENTIFIER)('Blue')
PsiWhiteSpace(' ')
PsiElement(=>)('=>')
PsiErrorElement:<expression> expected, got '}'
<empty list>
PsiWhiteSpace(' ')
PsiElement(})('}')
PsiWhiteSpace('\n\n ')
MvMatchExprImpl(MATCH_EXPR)
PsiElement(match_kw)('match')
PsiWhiteSpace(' ')
MvMatchArgumentImpl(MATCH_ARGUMENT)
PsiElement(()('(')
MvPathExprImpl(PATH_EXPR)
MvPathImpl(PATH)
PsiElement(IDENTIFIER)('s')
PsiErrorElement:<expression> expected, got ')'
<empty list>
PsiElement())(')')
PsiWhiteSpace(' ')
MvMatchBodyImpl(MATCH_BODY)
PsiElement({)('{')
PsiWhiteSpace(' ')
MvMatchArmImpl(MATCH_ARM)
MvPatBindingImpl(PAT_BINDING)
PsiElement(IDENTIFIER)('Red')
PsiWhiteSpace(' ')
PsiElement(=>)('=>')
PsiWhiteSpace(' ')
MvLitExprImpl(LIT_EXPR)
PsiElement(BOOL_LITERAL)('true')
PsiElement(,)(',')
PsiWhiteSpace(' ')
MvMatchArmImpl(MATCH_ARM)
MvPatBindingImpl(PAT_BINDING)
PsiElement(IDENTIFIER)('Blue')
PsiWhiteSpace(' ')
PsiElement(=>)('=>')
PsiErrorElement:<expression> expected, got '}'
<empty list>
PsiWhiteSpace(' ')
PsiElement(})('}')
PsiWhiteSpace('\n ')
PsiElement(})('}')
Expand Down

0 comments on commit 282b595

Please sign in to comment.