Skip to content

Commit

Permalink
Merge pull request #186 from pontem-network/enums-completion
Browse files Browse the repository at this point in the history
restrict types visibility, add binding completion for match arms
  • Loading branch information
mkurnikov authored Aug 30, 2024
2 parents 15c01ad + 64f0766 commit d090ecd
Show file tree
Hide file tree
Showing 34 changed files with 420 additions and 114 deletions.
2 changes: 1 addition & 1 deletion src/main/kotlin/org/move/ide/annotator/MvErrorAnnotator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ class MvErrorAnnotator: MvAnnotatorBase() {
val nameElement = o.path.referenceNameElement ?: return
val refStruct = o.path.maybeStruct ?: return
checkMissingFields(
moveHolder, nameElement, o.providedFieldNames, refStruct
moveHolder, nameElement, o.fieldNames, refStruct
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,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 Down Expand Up @@ -41,13 +43,12 @@ object ImportCandidateCollector {
}

fun getCompletionCandidates(
parameters: CompletionParameters,
project: Project,
prefixMatcher: PrefixMatcher,
processedPathNames: Set<String>,
importContext: ImportContext,
// itemFilter: (PsiElement) -> Boolean = { true }
): List<ImportCandidate> {
val project = parameters.position.project
val keys = hashSetOf<String>().apply {
val names = MvNamedElementIndex.getAllKeys(project)
addAll(names)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import org.move.lang.core.MvPsiPattern
import org.move.lang.core.completion.providers.*
import org.move.lang.core.completion.sort.COMPLETION_WEIGHERS_GROUPED
import org.move.lang.core.psi.MvModule
import org.move.lang.core.psi.ext.nextNonWsSibling
import org.move.lang.core.psi.ext.prevNonWsSibling

class CommonCompletionContributor: CompletionContributor() {
Expand All @@ -35,7 +34,7 @@ class CommonCompletionContributor: CompletionContributor() {
extend(CompletionType.BASIC, VectorLiteralCompletionProvider)
extend(CompletionType.BASIC, MethodOrFieldCompletionProvider)

// extend(CompletionType.BASIC, CommonCompletionProvider)
extend(CompletionType.BASIC, ReferenceCompletionProvider)
}

fun extend(type: CompletionType?, provider: MvCompletionProvider) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ fun MvNamedElement.createLookupElementWithIcon(): LookupElementBuilder {
.withLookupString(this.name ?: "")
}

data class CompletionContext(
data class MvCompletionContext(
val contextElement: MvElement,
val msl: Boolean,
val expectedTy: Ty? = null,
Expand All @@ -63,7 +63,7 @@ data class CompletionContext(
)

fun MvNamedElement.createLookupElement(
completionContext: CompletionContext,
completionContext: MvCompletionContext,
subst: Substitution = emptySubstitution,
priority: Double = DEFAULT_PRIORITY,
insertHandler: InsertHandler<LookupElement> = DefaultInsertHandler(completionContext),
Expand Down Expand Up @@ -126,7 +126,7 @@ class AngleBracketsInsertHandler: InsertHandler<LookupElement> {
}
}

open class DefaultInsertHandler(val completionCtx: CompletionContext? = null): InsertHandler<LookupElement> {
open class DefaultInsertHandler(val completionCtx: MvCompletionContext? = null): InsertHandler<LookupElement> {

final override fun handleInsert(context: InsertionContext, item: LookupElement) {
val element = item.psiElement as? MvElement ?: return
Expand Down Expand Up @@ -205,7 +205,7 @@ open class DefaultInsertHandler(val completionCtx: CompletionContext? = null): I
}

private fun MvNamedElement.getLookupElementBuilder(
completionCtx: CompletionContext,
completionCtx: MvCompletionContext,
subst: Substitution = emptySubstitution,
structAsType: Boolean = false
): LookupElementBuilder {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import org.move.lang.core.types.ty.TyUnknown

fun createLookupElement(
scopeEntry: ScopeEntry,
completionContext: CompletionContext,
completionContext: MvCompletionContext,
subst: Substitution = emptySubstitution,
priority: Double = DEFAULT_PRIORITY,
insertHandler: InsertHandler<LookupElement> = DefaultInsertHandler(completionContext)
Expand All @@ -29,7 +29,7 @@ fun createLookupElement(
}

private fun MvNamedElement.getLookupElementBuilder(
context: CompletionContext,
context: MvCompletionContext,
scopeName: String,
subst: Substitution = emptySubstitution,
): LookupElementBuilder {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ data class LookupElementProperties(
fun getLookupElementProperties(
element: MvNamedElement,
subst: Substitution,
context: CompletionContext
context: MvCompletionContext
): LookupElementProperties {
var props = LookupElementProperties()
val expectedTy = context.expectedTy
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,9 @@ import com.intellij.patterns.ElementPattern
import com.intellij.patterns.PlatformPatterns
import com.intellij.psi.PsiElement
import com.intellij.util.ProcessingContext
import org.jetbrains.annotations.VisibleForTesting
import org.move.lang.core.completion.CompletionContext
import org.move.lang.core.completion.getOriginalOrSelf
import org.move.lang.core.completion.safeGetOriginalOrSelf
import org.move.lang.core.psi.ext.isMsl
import org.move.lang.core.psiElement
import org.move.lang.core.resolve.collectCompletionVariants
import org.move.lang.core.resolve.ref.MvReferenceElement
import org.move.lang.core.resolve2.ref.ResolutionContext

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import com.intellij.patterns.PlatformPatterns
import com.intellij.psi.PsiElement
import com.intellij.util.ProcessingContext
import org.jetbrains.annotations.VisibleForTesting
import org.move.lang.core.completion.CompletionContext
import org.move.lang.core.completion.MvCompletionContext
import org.move.lang.core.completion.createLookupElement
import org.move.lang.core.psi.MvFunction
import org.move.lang.core.psi.ext.*
Expand Down Expand Up @@ -44,7 +44,7 @@ object MethodOrFieldCompletionProvider: MvCompletionProvider() {
val receiverTy = element.inferReceiverTy(msl).knownOrNull() ?: return
val expectedTy = getExpectedTypeForEnclosingPathOrDotExpr(element, msl)

val ctx = CompletionContext(element, msl, expectedTy)
val ctx = MvCompletionContext(element, msl, expectedTy)

val tyAdt = receiverTy.derefIfNeeded() as? TyAdt
if (tyAdt != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import org.move.ide.inspections.imports.ImportContext
import org.move.ide.utils.imports.ImportCandidate
import org.move.ide.utils.imports.ImportCandidateCollector
import org.move.lang.core.MvPsiPattern.path
import org.move.lang.core.completion.CompletionContext
import org.move.lang.core.completion.MvCompletionContext
import org.move.lang.core.completion.UNIMPORTED_ITEM_PRIORITY
import org.move.lang.core.completion.createLookupElement
import org.move.lang.core.completion.getOriginalOrSelf
Expand Down Expand Up @@ -50,7 +50,7 @@ object MvPathCompletionProvider2: MvCompletionProvider() {
val ns = pathKind.ns
val structAsType = TYPES_N_ENUMS.intersects(ns)

val completionContext = CompletionContext(
val completionContext = MvCompletionContext(
pathElement,
msl,
expectedTy,
Expand All @@ -66,7 +66,7 @@ object MvPathCompletionProvider2: MvCompletionProvider() {
fun addPathVariants(
pathElement: MvPath,
parameters: CompletionParameters,
completionContext: CompletionContext,
completionContext: MvCompletionContext,
ns: Set<Namespace>,
result: CompletionResultSet,
) {
Expand All @@ -91,20 +91,38 @@ object MvPathCompletionProvider2: MvCompletionProvider() {
)
}

addCompletionsForOutOfScopeItems(
parameters,
pathElement,
result,
completionContext,
ns,
processedNames
)
}

private fun addCompletionsForOutOfScopeItems(
parameters: CompletionParameters,
path: MvPath,
result: CompletionResultSet,
completionContext: MvCompletionContext,
ns: Set<Namespace>,
processedNames: MutableSet<String>,
) {
// disable auto-import in module specs for now
if (pathElement.containingModuleSpec != null) return
if (path.containingModuleSpec != null) return

// no out-of-scope completions for use specks
if (pathElement.isUseSpeck) return
if (path.isUseSpeck) return

// no import candidates for qualified paths
if (pathElement.pathKind(true) is PathKind.QualifiedPath) return
if (path.pathKind(true) is PathKind.QualifiedPath) return

val originalPathElement = parameters.originalPosition?.parent as? MvPath ?: return
val importContext = ImportContext.from(originalPathElement, true, ns) ?: return
val candidates =
ImportCandidateCollector.getCompletionCandidates(
parameters,
path.project,
result.prefixMatcher,
processedNames,
importContext,
Expand All @@ -118,7 +136,8 @@ object MvPathCompletionProvider2: MvCompletionProvider() {
)
result.addElement(lookupElement)
}
candidatesCollector = applySharedCompletionFilters(ns, resolutionCtx, candidatesCollector)
candidatesCollector =
applySharedCompletionFilters(ns, completionContext.resolutionCtx!!, candidatesCollector)
candidatesCollector.processAll(
candidates.map { CandidateScopeEntry(it.qualName.itemName, it.element, ns, it) }
)
Expand Down Expand Up @@ -149,7 +168,7 @@ fun applySharedCompletionFilters(
}

fun filterCompletionVariantsByVisibility(
context: MvMethodOrPath,
context: MvElement,
processor: RsResolveProcessor
): RsResolveProcessor {
return processor.wrapWithFilter { e ->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package org.move.lang.core.completion.providers

import com.intellij.codeInsight.completion.CompletionParameters
import com.intellij.codeInsight.completion.CompletionResultSet
import com.intellij.patterns.ElementPattern
import com.intellij.patterns.PlatformPatterns
import com.intellij.psi.PsiElement
import com.intellij.util.ProcessingContext
import org.move.lang.core.completion.MvCompletionContext
import org.move.lang.core.psi.MvPatBinding
import org.move.lang.core.psi.MvPatField
import org.move.lang.core.psi.ext.fieldNames
import org.move.lang.core.psi.ext.isMsl
import org.move.lang.core.psi.ext.parentPatStruct
import org.move.lang.core.psiElement
import org.move.lang.core.resolve.RsResolveProcessor
import org.move.lang.core.resolve.collectCompletionVariants
import org.move.lang.core.resolve.ref.MvReferenceElement
import org.move.lang.core.resolve.wrapWithFilter
import org.move.lang.core.resolve2.processPatBindingResolveVariants

object ReferenceCompletionProvider: MvCompletionProvider() {
override val elementPattern: ElementPattern<out PsiElement>
get() = PlatformPatterns.psiElement().withParent(psiElement<MvReferenceElement>())

override fun addCompletions(
parameters: CompletionParameters,
context: ProcessingContext,
result: CompletionResultSet
) {
// Use original position if possible to re-use caches of the real file
val position = parameters.position
val element = position.parent as MvReferenceElement
if (position !== element.referenceNameElement) return

val msl = element.isMsl()
val expectedTy = getExpectedTypeForEnclosingPathOrDotExpr(element, msl)

val completionCtx = MvCompletionContext(element, msl, expectedTy)

addCompletionVariants(element, result, completionCtx)
}

fun addCompletionVariants(
element: MvReferenceElement,
result: CompletionResultSet,
context: MvCompletionContext,
) {
collectCompletionVariants(result, context) {
val processor0 = filterCompletionVariantsByVisibility(element, it)
// todo: filter test functions
when (element) {
// `let Res/*caret*/ =`
// catches all modules, enums, enum variants and struct patterns
is MvPatBinding -> {
// for struct pat / lit, it filters out all the fields already existing in the body
val processor = skipAlreadyProvidedFields(element, processor0)
processPatBindingResolveVariants(element, true, processor)
}
}
}
}
}

private fun skipAlreadyProvidedFields(
refElement: MvReferenceElement,
processor0: RsResolveProcessor
): RsResolveProcessor {
val parent = refElement.parent
val providedFieldNames = when (parent) {
// shorthand, skip all provided fields
is MvPatField -> parent.parentPatStruct.fieldNames
// is MvStructLitField -> parent.parentStructLitExpr.providedFieldNames
else -> emptySet()
}
return processor0.wrapWithFilter { e -> e.name !in providedFieldNames }
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import com.intellij.patterns.ElementPattern
import com.intellij.patterns.PlatformPatterns
import com.intellij.psi.PsiElement
import com.intellij.util.ProcessingContext
import org.move.lang.core.completion.CompletionContext
import org.move.lang.core.completion.MvCompletionContext
import org.move.lang.core.completion.getOriginalOrSelf
import org.move.lang.core.psi.MvSchemaLitField
import org.move.lang.core.psi.ext.fields
Expand Down Expand Up @@ -35,7 +35,7 @@ object SchemaFieldsCompletionProvider: MvCompletionProvider() {
.filter { !it.textRange.contains(pos.textOffset) }
.map { it.referenceName }

val completionCtx = CompletionContext(literalField, literalField.isMsl())
val completionCtx = MvCompletionContext(literalField, literalField.isMsl())
collectCompletionVariants(result, completionCtx) {
val processor = it.wrapWithFilter { e -> e.name !in existingFieldNames }
processSchemaLitFieldResolveVariants(literalField, processor)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,11 @@ import com.intellij.patterns.PlatformPatterns
import com.intellij.patterns.StandardPatterns
import com.intellij.psi.PsiElement
import com.intellij.util.ProcessingContext
import org.move.lang.core.MvPsiPattern.bindingPat
import org.move.lang.core.completion.CompletionContext
import org.move.lang.core.completion.MvCompletionContext
import org.move.lang.core.completion.createLookupElement
import org.move.lang.core.psi.*
import org.move.lang.core.psi.ext.*
import org.move.lang.core.withParent
import org.move.lang.core.withSuperParent

object StructFieldsCompletionProvider: MvCompletionProvider() {
override val elementPattern: ElementPattern<out PsiElement>
Expand All @@ -24,8 +22,8 @@ object StructFieldsCompletionProvider: MvCompletionProvider() {
PlatformPatterns
.psiElement()
.withParent<MvPatField>(),
bindingPat()
.withSuperParent<MvPatField>(2),
// bindingPat()
// .withSuperParent<MvPatField>(2),
)

override fun addCompletions(
Expand All @@ -38,19 +36,19 @@ object StructFieldsCompletionProvider: MvCompletionProvider() {

if (element is MvPatBinding) element = element.parent as MvElement

val completionCtx = CompletionContext(element, element.isMsl())
val completionCtx = MvCompletionContext(element, element.isMsl())
when (element) {
is MvPatField -> {
val patStruct = element.patStruct
val patStruct = element.parentPatStruct
addFieldsToCompletion(
patStruct.path.maybeStruct ?: return,
patStruct.providedFieldNames,
patStruct.fieldNames,
result,
completionCtx
)
}
is MvStructLitField -> {
val structLit = element.structLitExpr
val structLit = element.parentStructLitExpr
addFieldsToCompletion(
structLit.path.maybeStruct ?: return,
structLit.providedFieldNames,
Expand All @@ -66,7 +64,7 @@ object StructFieldsCompletionProvider: MvCompletionProvider() {
referredStruct: MvStruct,
providedFieldNames: Set<String>,
result: CompletionResultSet,
completionContext: CompletionContext,
completionContext: MvCompletionContext,
) {
for (field in referredStruct.namedFields.filter { it.name !in providedFieldNames }) {
result.addElement(
Expand Down
Loading

0 comments on commit d090ecd

Please sign in to comment.