From a76cdcd4b30046897d7e10b5f971a870994bf9fc Mon Sep 17 00:00:00 2001 From: Maksim Kurnikov Date: Mon, 11 Nov 2024 13:55:36 +0100 Subject: [PATCH 1/4] merge method or field completion provider into common --- gradle.properties | 2 +- .../completion/CommonCompletionContributor.kt | 1 - .../MethodOrFieldCompletionProvider.kt | 77 ------------------- .../providers/ReferenceCompletionProvider.kt | 58 ++++++++++++-- 4 files changed, 52 insertions(+), 86 deletions(-) delete mode 100644 src/main/kotlin/org/move/lang/core/completion/providers/MethodOrFieldCompletionProvider.kt diff --git a/gradle.properties b/gradle.properties index 78499311b..9c2d53acf 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,6 +17,6 @@ org.gradle.jvmargs=-Xms512m -Xmx4096m "-XX:MaxMetaspaceSize=512m" propertiesPluginEnvironmentNameProperty=shortPlatformVersion # properties files # pass ORG_GRADLE_PROJECT_shortPlatformVersion environment variable to overwrite -shortPlatformVersion=243-SNAPSHOT +shortPlatformVersion=242 useInstaller=true diff --git a/src/main/kotlin/org/move/lang/core/completion/CommonCompletionContributor.kt b/src/main/kotlin/org/move/lang/core/completion/CommonCompletionContributor.kt index 301164942..0973334a8 100644 --- a/src/main/kotlin/org/move/lang/core/completion/CommonCompletionContributor.kt +++ b/src/main/kotlin/org/move/lang/core/completion/CommonCompletionContributor.kt @@ -27,7 +27,6 @@ class CommonCompletionContributor: CompletionContributor() { extend(CompletionType.BASIC, BoolsCompletionProvider) extend(CompletionType.BASIC, AssertMacroCompletionProvider) extend(CompletionType.BASIC, VectorLiteralCompletionProvider) - extend(CompletionType.BASIC, MethodOrFieldCompletionProvider) extend(CompletionType.BASIC, ReferenceCompletionProvider) } diff --git a/src/main/kotlin/org/move/lang/core/completion/providers/MethodOrFieldCompletionProvider.kt b/src/main/kotlin/org/move/lang/core/completion/providers/MethodOrFieldCompletionProvider.kt deleted file mode 100644 index 774073f7f..000000000 --- a/src/main/kotlin/org/move/lang/core/completion/providers/MethodOrFieldCompletionProvider.kt +++ /dev/null @@ -1,77 +0,0 @@ -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.jetbrains.annotations.VisibleForTesting -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.* -import org.move.lang.core.psi.tyVarsSubst -import org.move.lang.core.resolve.collectCompletionVariants -import org.move.lang.core.resolve.createProcessor -import org.move.lang.core.resolve2.processMethodResolveVariants -import org.move.lang.core.types.infer.InferenceContext -import org.move.lang.core.types.infer.substitute -import org.move.lang.core.types.ty.* -import org.move.lang.core.withParent - -object MethodOrFieldCompletionProvider: MvCompletionProvider() { - override val elementPattern: ElementPattern - get() = - PlatformPatterns - .psiElement() - .withParent() - - override fun addCompletions( - parameters: CompletionParameters, - context: ProcessingContext, - result: CompletionResultSet - ) { - val pos = parameters.position - val element = pos.parent as MvMethodOrField - - addMethodOrFieldVariants(element, result) - } - - @VisibleForTesting - fun addMethodOrFieldVariants(element: MvMethodOrField, result: CompletionResultSet) { - val msl = element.isMsl() - val receiverTy = element.inferReceiverTy(msl).knownOrNull() ?: return - val expectedTy = getExpectedTypeForEnclosingPathOrDotExpr(element, msl) - - val ctx = MvCompletionContext(element, msl, expectedTy) - - val tyAdt = receiverTy.derefIfNeeded() as? TyAdt - if (tyAdt != null) { - collectCompletionVariants(result, ctx, subst = tyAdt.substitution) { - processNamedFieldVariants(element, tyAdt, msl, it) - } - } - - processMethodResolveVariants(element, receiverTy, ctx.msl, createProcessor { e -> - val function = e.element as? MvFunction ?: return@createProcessor - val subst = function.tyVarsSubst - val declaredFuncTy = function.functionTy(msl).substitute(subst) as TyFunction - val declaredSelfTy = declaredFuncTy.paramTypes.first() - val autoborrowedReceiverTy = - TyReference.autoborrow(receiverTy, declaredSelfTy) - ?: error("unreachable, references always compatible") - - val inferenceCtx = InferenceContext(msl) - inferenceCtx.combineTypes(declaredSelfTy, autoborrowedReceiverTy) - - result.addElement( - createLookupElement( - e, - ctx, - subst = inferenceCtx.resolveTypeVarsIfPossible(subst) - ) - ) - }) - } -} \ No newline at end of file diff --git a/src/main/kotlin/org/move/lang/core/completion/providers/ReferenceCompletionProvider.kt b/src/main/kotlin/org/move/lang/core/completion/providers/ReferenceCompletionProvider.kt index b7a217e85..aa659726b 100644 --- a/src/main/kotlin/org/move/lang/core/completion/providers/ReferenceCompletionProvider.kt +++ b/src/main/kotlin/org/move/lang/core/completion/providers/ReferenceCompletionProvider.kt @@ -6,22 +6,24 @@ 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.MvCompletionContext -import org.move.lang.core.psi.MvItemSpecRef -import org.move.lang.core.psi.MvLabel -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.completion.createLookupElement +import org.move.lang.core.psi.* +import org.move.lang.core.psi.ext.* 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.createProcessor import org.move.lang.core.resolve.ref.MvReferenceElement import org.move.lang.core.resolve.ref.processItemSpecRefResolveVariants import org.move.lang.core.resolve.wrapWithFilter import org.move.lang.core.resolve2.processLabelResolveVariants +import org.move.lang.core.resolve2.processMethodResolveVariants import org.move.lang.core.resolve2.processPatBindingResolveVariants +import org.move.lang.core.types.infer.InferenceContext +import org.move.lang.core.types.infer.substitute +import org.move.lang.core.types.ty.* object ReferenceCompletionProvider: MvCompletionProvider() { override val elementPattern: ElementPattern @@ -42,6 +44,11 @@ object ReferenceCompletionProvider: MvCompletionProvider() { val completionCtx = MvCompletionContext(element, msl, expectedTy) + // handles dot expr + if (element is MvMethodOrField) { + addMethodOrFieldVariants(element, result) + } + addCompletionVariants(element, result, completionCtx) } @@ -68,6 +75,43 @@ object ReferenceCompletionProvider: MvCompletionProvider() { } } } + + @VisibleForTesting + fun addMethodOrFieldVariants(element: MvMethodOrField, result: CompletionResultSet) { + val msl = element.isMsl() + val receiverTy = element.inferReceiverTy(msl).knownOrNull() ?: return + val expectedTy = getExpectedTypeForEnclosingPathOrDotExpr(element, msl) + + val ctx = MvCompletionContext(element, msl, expectedTy) + + val tyAdt = receiverTy.derefIfNeeded() as? TyAdt + if (tyAdt != null) { + collectCompletionVariants(result, ctx, subst = tyAdt.substitution) { + processNamedFieldVariants(element, tyAdt, msl, it) + } + } + + processMethodResolveVariants(element, receiverTy, ctx.msl, createProcessor { e -> + val function = e.element as? MvFunction ?: return@createProcessor + val subst = function.tyVarsSubst + val declaredFuncTy = function.functionTy(msl).substitute(subst) as TyFunction + val declaredSelfTy = declaredFuncTy.paramTypes.first() + val autoborrowedReceiverTy = + TyReference.autoborrow(receiverTy, declaredSelfTy) + ?: error("unreachable, references always compatible") + + val inferenceCtx = InferenceContext(msl) + inferenceCtx.combineTypes(declaredSelfTy, autoborrowedReceiverTy) + + result.addElement( + createLookupElement( + e, + ctx, + subst = inferenceCtx.resolveTypeVarsIfPossible(subst) + ) + ) + }) + } } private fun skipAlreadyProvidedFields( From 32dd71e0f101874446d5b16bf7f64cc01d40007d Mon Sep 17 00:00:00 2001 From: Maksim Kurnikov Date: Mon, 11 Nov 2024 13:56:34 +0100 Subject: [PATCH 2/4] reference completion -> common completionm --- .../completion/CommonCompletionContributor.kt | 2 +- .../providers/CommonCompletionProvider.kt | 123 +++++++++++++---- .../providers/ReferenceCompletionProvider.kt | 129 ------------------ 3 files changed, 100 insertions(+), 154 deletions(-) delete mode 100644 src/main/kotlin/org/move/lang/core/completion/providers/ReferenceCompletionProvider.kt diff --git a/src/main/kotlin/org/move/lang/core/completion/CommonCompletionContributor.kt b/src/main/kotlin/org/move/lang/core/completion/CommonCompletionContributor.kt index 0973334a8..e2091cb66 100644 --- a/src/main/kotlin/org/move/lang/core/completion/CommonCompletionContributor.kt +++ b/src/main/kotlin/org/move/lang/core/completion/CommonCompletionContributor.kt @@ -28,7 +28,7 @@ class CommonCompletionContributor: CompletionContributor() { extend(CompletionType.BASIC, AssertMacroCompletionProvider) extend(CompletionType.BASIC, VectorLiteralCompletionProvider) - extend(CompletionType.BASIC, ReferenceCompletionProvider) + extend(CompletionType.BASIC, CommonCompletionProvider) } fun extend(type: CompletionType?, provider: MvCompletionProvider) { diff --git a/src/main/kotlin/org/move/lang/core/completion/providers/CommonCompletionProvider.kt b/src/main/kotlin/org/move/lang/core/completion/providers/CommonCompletionProvider.kt index 50e0b9fc5..3e5c713fa 100644 --- a/src/main/kotlin/org/move/lang/core/completion/providers/CommonCompletionProvider.kt +++ b/src/main/kotlin/org/move/lang/core/completion/providers/CommonCompletionProvider.kt @@ -6,14 +6,27 @@ 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.safeGetOriginalOrSelf -import org.move.lang.core.psi.ext.isMsl +import org.jetbrains.annotations.VisibleForTesting +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.psiElement +import org.move.lang.core.resolve.RsResolveProcessor +import org.move.lang.core.resolve.collectCompletionVariants +import org.move.lang.core.resolve.createProcessor import org.move.lang.core.resolve.ref.MvReferenceElement -import org.move.lang.core.resolve2.ref.ResolutionContext +import org.move.lang.core.resolve.ref.processItemSpecRefResolveVariants +import org.move.lang.core.resolve.wrapWithFilter +import org.move.lang.core.resolve2.processLabelResolveVariants +import org.move.lang.core.resolve2.processMethodResolveVariants +import org.move.lang.core.resolve2.processPatBindingResolveVariants +import org.move.lang.core.types.infer.InferenceContext +import org.move.lang.core.types.infer.substitute +import org.move.lang.core.types.ty.* object CommonCompletionProvider: MvCompletionProvider() { - override val elementPattern: ElementPattern + override val elementPattern: ElementPattern get() = PlatformPatterns.psiElement().withParent(psiElement()) override fun addCompletions( @@ -22,33 +35,95 @@ object CommonCompletionProvider: MvCompletionProvider() { result: CompletionResultSet ) { // Use original position if possible to re-use caches of the real file - val position = parameters.position.safeGetOriginalOrSelf() + 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 resolutionCtx = ResolutionContext(element, true) -// val completionContext = CompletionContext( -// element, -// msl, -// expectedTy, -// resolutionCtx = resolutionCtx, -// structAsType, -// ) + val completionCtx = MvCompletionContext(element, msl, expectedTy) + // handles dot expr + if (element is MvMethodOrField) { + addMethodOrFieldVariants(element, result) + } + + addCompletionVariants(element, result, completionCtx) + } + + fun addCompletionVariants( + element: MvReferenceElement, + result: CompletionResultSet, + completionCtx: MvCompletionContext, + ) { + collectCompletionVariants(result, completionCtx) { + 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) + } + // loop labels + is MvLabel -> processLabelResolveVariants(element, it) + // `spec ITEM {}` module items, where ITEM is a reference to the function/struct/enum + is MvItemSpecRef -> processItemSpecRefResolveVariants(element, it) + } + } + } + + @VisibleForTesting + fun addMethodOrFieldVariants(element: MvMethodOrField, result: CompletionResultSet) { + val msl = element.isMsl() + val receiverTy = element.inferReceiverTy(msl).knownOrNull() ?: return + val expectedTy = getExpectedTypeForEnclosingPathOrDotExpr(element, msl) + + val ctx = MvCompletionContext(element, msl, expectedTy) + + val tyAdt = receiverTy.derefIfNeeded() as? TyAdt + if (tyAdt != null) { + collectCompletionVariants(result, ctx, subst = tyAdt.substitution) { + processNamedFieldVariants(element, tyAdt, msl, it) + } + } + + processMethodResolveVariants(element, receiverTy, ctx.msl, createProcessor { e -> + val function = e.element as? MvFunction ?: return@createProcessor + val subst = function.tyVarsSubst + val declaredFuncTy = function.functionTy(msl).substitute(subst) as TyFunction + val declaredSelfTy = declaredFuncTy.paramTypes.first() + val autoborrowedReceiverTy = + TyReference.autoborrow(receiverTy, declaredSelfTy) + ?: error("unreachable, references always compatible") + + val inferenceCtx = InferenceContext(msl) + inferenceCtx.combineTypes(declaredSelfTy, autoborrowedReceiverTy) + + result.addElement( + createLookupElement( + e, + ctx, + subst = inferenceCtx.resolveTypeVarsIfPossible(subst) + ) + ) + }) } +} -// @VisibleForTesting -// fun addCompletionVariants( -// element: MvReferenceElement, -// result: CompletionResultSet, -// context: CompletionContext, -// processedPathNames: MutableSet -// ) { -// collectCompletionVariants(result, context) { -// -// } -// } +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 } } \ No newline at end of file diff --git a/src/main/kotlin/org/move/lang/core/completion/providers/ReferenceCompletionProvider.kt b/src/main/kotlin/org/move/lang/core/completion/providers/ReferenceCompletionProvider.kt deleted file mode 100644 index aa659726b..000000000 --- a/src/main/kotlin/org/move/lang/core/completion/providers/ReferenceCompletionProvider.kt +++ /dev/null @@ -1,129 +0,0 @@ -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.jetbrains.annotations.VisibleForTesting -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.psiElement -import org.move.lang.core.resolve.RsResolveProcessor -import org.move.lang.core.resolve.collectCompletionVariants -import org.move.lang.core.resolve.createProcessor -import org.move.lang.core.resolve.ref.MvReferenceElement -import org.move.lang.core.resolve.ref.processItemSpecRefResolveVariants -import org.move.lang.core.resolve.wrapWithFilter -import org.move.lang.core.resolve2.processLabelResolveVariants -import org.move.lang.core.resolve2.processMethodResolveVariants -import org.move.lang.core.resolve2.processPatBindingResolveVariants -import org.move.lang.core.types.infer.InferenceContext -import org.move.lang.core.types.infer.substitute -import org.move.lang.core.types.ty.* - -object ReferenceCompletionProvider: MvCompletionProvider() { - override val elementPattern: ElementPattern - get() = PlatformPatterns.psiElement().withParent(psiElement()) - - 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) - - // handles dot expr - if (element is MvMethodOrField) { - addMethodOrFieldVariants(element, result) - } - - addCompletionVariants(element, result, completionCtx) - } - - fun addCompletionVariants( - element: MvReferenceElement, - result: CompletionResultSet, - completionCtx: MvCompletionContext, - ) { - collectCompletionVariants(result, completionCtx) { - 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) - } - // loop labels - is MvLabel -> processLabelResolveVariants(element, it) - // `spec ITEM {}` module items, where ITEM is a reference to the function/struct/enum - is MvItemSpecRef -> processItemSpecRefResolveVariants(element, it) - } - } - } - - @VisibleForTesting - fun addMethodOrFieldVariants(element: MvMethodOrField, result: CompletionResultSet) { - val msl = element.isMsl() - val receiverTy = element.inferReceiverTy(msl).knownOrNull() ?: return - val expectedTy = getExpectedTypeForEnclosingPathOrDotExpr(element, msl) - - val ctx = MvCompletionContext(element, msl, expectedTy) - - val tyAdt = receiverTy.derefIfNeeded() as? TyAdt - if (tyAdt != null) { - collectCompletionVariants(result, ctx, subst = tyAdt.substitution) { - processNamedFieldVariants(element, tyAdt, msl, it) - } - } - - processMethodResolveVariants(element, receiverTy, ctx.msl, createProcessor { e -> - val function = e.element as? MvFunction ?: return@createProcessor - val subst = function.tyVarsSubst - val declaredFuncTy = function.functionTy(msl).substitute(subst) as TyFunction - val declaredSelfTy = declaredFuncTy.paramTypes.first() - val autoborrowedReceiverTy = - TyReference.autoborrow(receiverTy, declaredSelfTy) - ?: error("unreachable, references always compatible") - - val inferenceCtx = InferenceContext(msl) - inferenceCtx.combineTypes(declaredSelfTy, autoborrowedReceiverTy) - - result.addElement( - createLookupElement( - e, - ctx, - subst = inferenceCtx.resolveTypeVarsIfPossible(subst) - ) - ) - }) - } -} - -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 } -} \ No newline at end of file From 554aa4fae21379c156666ec89bcee8d1d946d1ab Mon Sep 17 00:00:00 2001 From: Maksim Kurnikov Date: Mon, 11 Nov 2024 14:41:27 +0100 Subject: [PATCH 3/4] named tuple field completion --- .../providers/CommonCompletionProvider.kt | 3 +- .../move/lang/core/psi/ext/MvFieldLookup.kt | 35 ------------------- .../lang/core/resolve2/NameResolution2.kt | 8 ++--- .../completion/lookups/LookupElementTest.kt | 4 +-- .../names/DotAccessCompletionTest.kt | 12 +++++++ 5 files changed, 19 insertions(+), 43 deletions(-) diff --git a/src/main/kotlin/org/move/lang/core/completion/providers/CommonCompletionProvider.kt b/src/main/kotlin/org/move/lang/core/completion/providers/CommonCompletionProvider.kt index 3e5c713fa..878eaf9ea 100644 --- a/src/main/kotlin/org/move/lang/core/completion/providers/CommonCompletionProvider.kt +++ b/src/main/kotlin/org/move/lang/core/completion/providers/CommonCompletionProvider.kt @@ -18,6 +18,7 @@ import org.move.lang.core.resolve.createProcessor import org.move.lang.core.resolve.ref.MvReferenceElement import org.move.lang.core.resolve.ref.processItemSpecRefResolveVariants import org.move.lang.core.resolve.wrapWithFilter +import org.move.lang.core.resolve2.processFieldLookupResolveVariants import org.move.lang.core.resolve2.processLabelResolveVariants import org.move.lang.core.resolve2.processMethodResolveVariants import org.move.lang.core.resolve2.processPatBindingResolveVariants @@ -87,7 +88,7 @@ object CommonCompletionProvider: MvCompletionProvider() { val tyAdt = receiverTy.derefIfNeeded() as? TyAdt if (tyAdt != null) { collectCompletionVariants(result, ctx, subst = tyAdt.substitution) { - processNamedFieldVariants(element, tyAdt, msl, it) + processFieldLookupResolveVariants(element, tyAdt, msl, it) } } diff --git a/src/main/kotlin/org/move/lang/core/psi/ext/MvFieldLookup.kt b/src/main/kotlin/org/move/lang/core/psi/ext/MvFieldLookup.kt index adfc18799..d2b112c09 100644 --- a/src/main/kotlin/org/move/lang/core/psi/ext/MvFieldLookup.kt +++ b/src/main/kotlin/org/move/lang/core/psi/ext/MvFieldLookup.kt @@ -3,46 +3,11 @@ package org.move.lang.core.psi.ext import com.intellij.lang.ASTNode import com.intellij.psi.PsiElement import org.move.lang.core.psi.* -import org.move.lang.core.resolve.* import org.move.lang.core.resolve.ref.MvPolyVariantReference import org.move.lang.core.resolve.ref.MvPolyVariantReferenceBase -import org.move.lang.core.resolve.ref.NONE -import org.move.lang.core.resolve2.ref.FieldResolveVariant import org.move.lang.core.types.infer.inference -import org.move.lang.core.types.ty.TyAdt import org.move.stdext.wrapWithList -fun processNamedFieldVariants( - element: MvMethodOrField, - receiverTy: TyAdt, - msl: Boolean, - processor: RsResolveProcessor -): Boolean { - val receiverItem = receiverTy.item - if (!isFieldsAccessible(element, receiverItem, msl)) return false - - return when (receiverItem) { - is MvStruct -> processor.processAll(NONE, receiverItem.namedFields) - is MvEnum -> { - val visitedFields = mutableSetOf() - for (variant in receiverItem.variants) { - val visitedVariantFields = mutableSetOf() - for (namedField in variant.namedFields) { - val fieldName = namedField.name - if (fieldName in visitedFields) continue - if (processor.process(NONE, namedField)) return true - // collect all names for the variant - visitedVariantFields.add(fieldName) - } - // add variant fields to the global fields list to skip them in the next variants - visitedFields.addAll(visitedVariantFields) - } - false - } - else -> error("unreachable") - } -} - // todo: change into VisibilityFilter fun isFieldsAccessible( element: MvElement, diff --git a/src/main/kotlin/org/move/lang/core/resolve2/NameResolution2.kt b/src/main/kotlin/org/move/lang/core/resolve2/NameResolution2.kt index 4b171938c..0860cc0d7 100644 --- a/src/main/kotlin/org/move/lang/core/resolve2/NameResolution2.kt +++ b/src/main/kotlin/org/move/lang/core/resolve2/NameResolution2.kt @@ -13,7 +13,7 @@ import org.move.lang.core.types.ty.TyAdt import org.move.lang.index.MvModuleIndex fun processFieldLookupResolveVariants( - fieldLookup: MvFieldLookup, + fieldLookup: MvMethodOrField, receiverTy: TyAdt, msl: Boolean, originalProcessor: RsResolveProcessorBase @@ -21,13 +21,11 @@ fun processFieldLookupResolveVariants( val receiverItem = receiverTy.item if (!isFieldsAccessible(fieldLookup, receiverItem, msl)) return false - val processor = originalProcessor.wrapWithMapper { it: ScopeEntry -> - FieldResolveVariant(it.name, it.element) - } + val processor = originalProcessor + .wrapWithMapper { it: ScopeEntry -> FieldResolveVariant(it.name, it.element) } return when (receiverItem) { is MvStruct -> processFieldDeclarations(receiverItem, processor) -// is MvStruct -> processor.processAll(NONE, receiverItem.fields) is MvEnum -> { val visitedFields = mutableSetOf() for (variant in receiverItem.variants) { diff --git a/src/test/kotlin/org/move/lang/completion/lookups/LookupElementTest.kt b/src/test/kotlin/org/move/lang/completion/lookups/LookupElementTest.kt index 1535092b8..166056460 100644 --- a/src/test/kotlin/org/move/lang/completion/lookups/LookupElementTest.kt +++ b/src/test/kotlin/org/move/lang/completion/lookups/LookupElementTest.kt @@ -10,7 +10,7 @@ import com.intellij.psi.NavigatablePsiElement import org.intellij.lang.annotations.Language import org.move.lang.core.completion.MvCompletionContext import org.move.lang.core.completion.createLookupElement -import org.move.lang.core.completion.providers.MethodOrFieldCompletionProvider +import org.move.lang.core.completion.providers.CommonCompletionProvider import org.move.lang.core.psi.MvElement import org.move.lang.core.psi.MvNamedElement import org.move.lang.core.psi.ext.MvMethodOrField @@ -237,7 +237,7 @@ class LookupElementTest: MvTestBase() { } if (element is MvMethodOrField) { - MethodOrFieldCompletionProvider.addMethodOrFieldVariants(element, result) + CommonCompletionProvider.addMethodOrFieldVariants(element, result) } val lookup = lookups.single { diff --git a/src/test/kotlin/org/move/lang/completion/names/DotAccessCompletionTest.kt b/src/test/kotlin/org/move/lang/completion/names/DotAccessCompletionTest.kt index fca2cb8f0..e4a362eaf 100644 --- a/src/test/kotlin/org/move/lang/completion/names/DotAccessCompletionTest.kt +++ b/src/test/kotlin/org/move/lang/completion/names/DotAccessCompletionTest.kt @@ -100,4 +100,16 @@ module 0x1::M { } """ ) + + fun `test named tuple field completion`() = checkContainsCompletionExact( + listOf("0", "1"), + """ + module 0x1::m { + struct S(u8, u8); + fun main(s: S) { + s./*caret*/ + } + } + """ + ) } From b0748418b45a115285f026099c3b5d44dca658cb Mon Sep 17 00:00:00 2001 From: Maksim Kurnikov Date: Mon, 11 Nov 2024 14:54:59 +0100 Subject: [PATCH 4/4] proper lookup element for named tuple field completion --- src/main/kotlin/org/move/ide/MoveIcons.kt | 1 - .../org/move/lang/core/completion/LookupElements2.kt | 7 ++----- .../org/move/lang/core/psi/ext/MvStructField.kt | 2 +- .../lang/completion/lookups/LookupElementTest.kt | 12 ++++++++++++ 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/main/kotlin/org/move/ide/MoveIcons.kt b/src/main/kotlin/org/move/ide/MoveIcons.kt index 3a30b8e10..4a8b03c2f 100644 --- a/src/main/kotlin/org/move/ide/MoveIcons.kt +++ b/src/main/kotlin/org/move/ide/MoveIcons.kt @@ -20,7 +20,6 @@ object MoveIcons { val MODULE = load("/icons/module.svg") val STRUCT = load("/icons/struct.svg") - val STRUCT_FIELD = AllIcons.Nodes.Field val SCHEMA = AllIcons.Nodes.Static val FIELD = load("/icons/nodes/field.svg") diff --git a/src/main/kotlin/org/move/lang/core/completion/LookupElements2.kt b/src/main/kotlin/org/move/lang/core/completion/LookupElements2.kt index 07442e1d8..c7cb40c50 100644 --- a/src/main/kotlin/org/move/lang/core/completion/LookupElements2.kt +++ b/src/main/kotlin/org/move/lang/core/completion/LookupElements2.kt @@ -5,10 +5,7 @@ import com.intellij.codeInsight.lookup.LookupElement import com.intellij.codeInsight.lookup.LookupElementBuilder import org.move.ide.presentation.text import org.move.lang.core.psi.* -import org.move.lang.core.psi.ext.MvMethodOrField -import org.move.lang.core.psi.ext.addressRef -import org.move.lang.core.psi.ext.joinToSignature -import org.move.lang.core.psi.ext.outerFileName +import org.move.lang.core.psi.ext.* import org.move.lang.core.resolve.ScopeEntry import org.move.lang.core.types.infer.* import org.move.lang.core.types.ty.TyUnknown @@ -66,7 +63,7 @@ fun MvNamedElement.getLookupElementBuilder2( .withTypeText(this.containingFile?.name) } - is MvNamedFieldDecl -> { + is MvFieldDecl -> { val fieldTy = this.type?.loweredType(msl)?.substitute(subst) ?: TyUnknown base .withTypeText(fieldTy.text(false)) diff --git a/src/main/kotlin/org/move/lang/core/psi/ext/MvStructField.kt b/src/main/kotlin/org/move/lang/core/psi/ext/MvStructField.kt index 8804085ac..bfa0edd0c 100644 --- a/src/main/kotlin/org/move/lang/core/psi/ext/MvStructField.kt +++ b/src/main/kotlin/org/move/lang/core/psi/ext/MvStructField.kt @@ -16,5 +16,5 @@ val MvNamedFieldDecl.fieldOwner: MvFieldsOwner get() = blockFields?.parent as Mv abstract class MvNamedFieldDeclMixin(node: ASTNode) : MvMandatoryNameIdentifierOwnerImpl(node), MvNamedFieldDecl { - override fun getIcon(flags: Int): Icon = MoveIcons.STRUCT_FIELD + override fun getIcon(flags: Int): Icon = MoveIcons.FIELD } \ No newline at end of file diff --git a/src/test/kotlin/org/move/lang/completion/lookups/LookupElementTest.kt b/src/test/kotlin/org/move/lang/completion/lookups/LookupElementTest.kt index 166056460..98db0bfea 100644 --- a/src/test/kotlin/org/move/lang/completion/lookups/LookupElementTest.kt +++ b/src/test/kotlin/org/move/lang/completion/lookups/LookupElementTest.kt @@ -157,6 +157,18 @@ class LookupElementTest: MvTestBase() { } """, tailText = "(&mut self)", typeText = "u8" ) + + fun `test named tuple field lookup`() = checkMethodOrFieldProvider( + """ + module 0x1::m { + struct S(u8, u8); + fun main(s: S) { + s.0; + //^ + } + } + """, typeText = "u8" + ) // // fun `test import module lookup`() = checkNamedItem(""" // module 0x1::m {