From 437726c6c03345ca3560ea743586f934e96ed48b Mon Sep 17 00:00:00 2001 From: Maksim Kurnikov Date: Sat, 3 Aug 2024 17:01:30 +0300 Subject: [PATCH 1/3] initial enum parser support --- src/main/grammars/MoveParser.bnf | 18 +- .../org/move/lang/core/MoveParserUtil.kt | 3 + .../move/lang/parser/CompleteParsingTest.kt | 1 + .../org/move/lang/parser/complete/enums.move | 24 ++ .../org/move/lang/parser/complete/enums.txt | 241 ++++++++++++++++++ 5 files changed, 285 insertions(+), 2 deletions(-) create mode 100644 src/test/resources/org/move/lang/parser/complete/enums.move create mode 100644 src/test/resources/org/move/lang/parser/complete/enums.txt diff --git a/src/main/grammars/MoveParser.bnf b/src/main/grammars/MoveParser.bnf index 0dd885318..2ff4b6e87 100644 --- a/src/main/grammars/MoveParser.bnf +++ b/src/main/grammars/MoveParser.bnf @@ -114,6 +114,7 @@ STRUCT_KW = 'struct_kw' CONST_KW = 'const_kw' SCHEMA_KW = 'schema_kw' + ENUM_KW = 'enum_kw' LOCAL = 'local_kw' GLOBAL = 'global_kw' @@ -251,13 +252,14 @@ private ModuleItem ::= !('}' | <>) ModuleItem_item recoverWhile = Item_recover } // top-level recovery -private Item_first ::= use | public | native | fun | CONST_KW | STRUCT_KW | spec | friend | Attr | entry | inline +private Item_first ::= use | public | native | fun | CONST_KW | STRUCT_KW | spec | '#' + | "friend" | "entry" | "inline" | "enum" private Item_recover ::= !('}' | <> | Item_first) private ModuleItem_item ::= UseStmt -// | UseStmt | FriendDecl | StructItem + | Enum | FunctionItem | SpecFunctionItem | Const @@ -382,6 +384,17 @@ NativeStructInner ::= Attr* NativeStructInnerFirst IDENTIFIER TypeParameterList? } private StructItem ::= StructInner | NativeStructInner +Enum ::= enum IDENTIFIER TypeParameterList? AbilitiesList? EnumBody +{ + pin = "enum" + hooks = [ leftBinder = "ADJACENT_LINE_COMMENTS" ] +} +EnumBody ::= '{' (EnumVariant ','?)* '}' +{ + pin = 1 +} +EnumVariant ::= Attr* IDENTIFIER StructBlock? + fake Function ::= Attr* native? VisibilityModifier? entry? inline? fun? IDENTIFIER? TypeParameterList? FunctionParameterList? ReturnType? (ResourceAccessItemList | AcquiresType)? @@ -429,6 +442,7 @@ private FunctionSignatureInner ::= IDENTIFIER TypeParameterList? private FunctionSignatureInner_recover ::= !('{' | '}' | ';' | <> | Item_first) private friend ::= <> +private enum ::= <> private package ::= <> private for ::= <> diff --git a/src/main/kotlin/org/move/lang/core/MoveParserUtil.kt b/src/main/kotlin/org/move/lang/core/MoveParserUtil.kt index 588ccec0c..789c748a4 100644 --- a/src/main/kotlin/org/move/lang/core/MoveParserUtil.kt +++ b/src/main/kotlin/org/move/lang/core/MoveParserUtil.kt @@ -352,6 +352,9 @@ object MoveParserUtil: GeneratedParserUtilBase() { @JvmStatic fun friendKeyword(b: PsiBuilder, level: Int): Boolean = contextualKeyword(b, "friend", FRIEND) + @JvmStatic + fun enumKeyword(b: PsiBuilder, level: Int): Boolean = contextualKeyword(b, "enum", ENUM_KW) + @JvmStatic fun packageKeyword(b: PsiBuilder, level: Int): Boolean = contextualKeyword(b, "package", PACKAGE) diff --git a/src/test/kotlin/org/move/lang/parser/CompleteParsingTest.kt b/src/test/kotlin/org/move/lang/parser/CompleteParsingTest.kt index 33366f34c..a80514bf2 100644 --- a/src/test/kotlin/org/move/lang/parser/CompleteParsingTest.kt +++ b/src/test/kotlin/org/move/lang/parser/CompleteParsingTest.kt @@ -49,6 +49,7 @@ class CompleteParsingTest: MvParsingTestCase("complete") { // compiler v2 fun `test index expr`() = doTest() fun `test public package`() = doTest() + fun `test enums`() = doTest() // feature declaration is required here, as it's a parser-level feature @CompilerV2Features(RESOURCE_CONTROL) diff --git a/src/test/resources/org/move/lang/parser/complete/enums.move b/src/test/resources/org/move/lang/parser/complete/enums.move new file mode 100644 index 000000000..27b3988cd --- /dev/null +++ b/src/test/resources/org/move/lang/parser/complete/enums.move @@ -0,0 +1,24 @@ +module 0x1::enums { + enum Color has copy, drop { + RGB{red: u64, green: u64, blue: u64}, + Red, + Blue, + } + + enum ColorUsesBlockNoComma { + RGB{red: u64, green: u64, blue: u64} + Red, + Blue, + } + + enum CommonFields { + Foo{x: u64, y: u8}, + Bar{x: u64, z: u32} + } + + enum Outer { + None, + One{i: Inner}, + Two{i: Inner, b: Box}, + } +} diff --git a/src/test/resources/org/move/lang/parser/complete/enums.txt b/src/test/resources/org/move/lang/parser/complete/enums.txt new file mode 100644 index 000000000..996c3cc48 --- /dev/null +++ b/src/test/resources/org/move/lang/parser/complete/enums.txt @@ -0,0 +1,241 @@ +FILE + MvModuleImpl(MODULE) + PsiElement(module)('module') + PsiWhiteSpace(' ') + MvAddressRefImpl(ADDRESS_REF) + PsiElement(DIEM_ADDRESS)('0x1') + PsiElement(::)('::') + PsiElement(IDENTIFIER)('enums') + PsiWhiteSpace(' ') + MvModuleBlockImpl(MODULE_BLOCK) + PsiElement({)('{') + PsiWhiteSpace('\n ') + MvEnumImpl(ENUM) + PsiElement(enum_kw)('enum') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('Color') + PsiWhiteSpace(' ') + MvAbilitiesListImpl(ABILITIES_LIST) + PsiElement(has_kw)('has') + PsiWhiteSpace(' ') + MvAbilityImpl(ABILITY) + PsiElement(copy)('copy') + PsiElement(,)(',') + PsiWhiteSpace(' ') + MvAbilityImpl(ABILITY) + PsiElement(IDENTIFIER)('drop') + PsiWhiteSpace(' ') + MvEnumBodyImpl(ENUM_BODY) + PsiElement({)('{') + PsiWhiteSpace('\n ') + MvEnumVariantImpl(ENUM_VARIANT) + PsiElement(IDENTIFIER)('RGB') + MvStructBlockImpl(STRUCT_BLOCK) + PsiElement({)('{') + MvStructFieldImpl(STRUCT_FIELD) + PsiElement(IDENTIFIER)('red') + MvTypeAnnotationImpl(TYPE_ANNOTATION) + PsiElement(:)(':') + PsiWhiteSpace(' ') + MvPathTypeImpl(PATH_TYPE) + MvPathImpl(PATH) + PsiElement(IDENTIFIER)('u64') + PsiElement(,)(',') + PsiWhiteSpace(' ') + MvStructFieldImpl(STRUCT_FIELD) + PsiElement(IDENTIFIER)('green') + MvTypeAnnotationImpl(TYPE_ANNOTATION) + PsiElement(:)(':') + PsiWhiteSpace(' ') + MvPathTypeImpl(PATH_TYPE) + MvPathImpl(PATH) + PsiElement(IDENTIFIER)('u64') + PsiElement(,)(',') + PsiWhiteSpace(' ') + MvStructFieldImpl(STRUCT_FIELD) + PsiElement(IDENTIFIER)('blue') + MvTypeAnnotationImpl(TYPE_ANNOTATION) + PsiElement(:)(':') + PsiWhiteSpace(' ') + MvPathTypeImpl(PATH_TYPE) + MvPathImpl(PATH) + PsiElement(IDENTIFIER)('u64') + PsiElement(})('}') + PsiElement(,)(',') + PsiWhiteSpace('\n ') + MvEnumVariantImpl(ENUM_VARIANT) + PsiElement(IDENTIFIER)('Red') + PsiElement(,)(',') + PsiWhiteSpace('\n ') + MvEnumVariantImpl(ENUM_VARIANT) + PsiElement(IDENTIFIER)('Blue') + PsiElement(,)(',') + PsiWhiteSpace('\n ') + PsiElement(})('}') + PsiWhiteSpace('\n\n ') + MvEnumImpl(ENUM) + PsiElement(enum_kw)('enum') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('ColorUsesBlockNoComma') + PsiWhiteSpace(' ') + MvEnumBodyImpl(ENUM_BODY) + PsiElement({)('{') + PsiWhiteSpace('\n ') + MvEnumVariantImpl(ENUM_VARIANT) + PsiElement(IDENTIFIER)('RGB') + MvStructBlockImpl(STRUCT_BLOCK) + PsiElement({)('{') + MvStructFieldImpl(STRUCT_FIELD) + PsiElement(IDENTIFIER)('red') + MvTypeAnnotationImpl(TYPE_ANNOTATION) + PsiElement(:)(':') + PsiWhiteSpace(' ') + MvPathTypeImpl(PATH_TYPE) + MvPathImpl(PATH) + PsiElement(IDENTIFIER)('u64') + PsiElement(,)(',') + PsiWhiteSpace(' ') + MvStructFieldImpl(STRUCT_FIELD) + PsiElement(IDENTIFIER)('green') + MvTypeAnnotationImpl(TYPE_ANNOTATION) + PsiElement(:)(':') + PsiWhiteSpace(' ') + MvPathTypeImpl(PATH_TYPE) + MvPathImpl(PATH) + PsiElement(IDENTIFIER)('u64') + PsiElement(,)(',') + PsiWhiteSpace(' ') + MvStructFieldImpl(STRUCT_FIELD) + PsiElement(IDENTIFIER)('blue') + MvTypeAnnotationImpl(TYPE_ANNOTATION) + PsiElement(:)(':') + PsiWhiteSpace(' ') + MvPathTypeImpl(PATH_TYPE) + MvPathImpl(PATH) + PsiElement(IDENTIFIER)('u64') + PsiElement(})('}') + PsiWhiteSpace('\n ') + MvEnumVariantImpl(ENUM_VARIANT) + PsiElement(IDENTIFIER)('Red') + PsiElement(,)(',') + PsiWhiteSpace('\n ') + MvEnumVariantImpl(ENUM_VARIANT) + PsiElement(IDENTIFIER)('Blue') + PsiElement(,)(',') + PsiWhiteSpace('\n ') + PsiElement(})('}') + PsiWhiteSpace('\n\n ') + MvEnumImpl(ENUM) + PsiElement(enum_kw)('enum') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('CommonFields') + PsiWhiteSpace(' ') + MvEnumBodyImpl(ENUM_BODY) + PsiElement({)('{') + PsiWhiteSpace('\n ') + MvEnumVariantImpl(ENUM_VARIANT) + PsiElement(IDENTIFIER)('Foo') + MvStructBlockImpl(STRUCT_BLOCK) + PsiElement({)('{') + MvStructFieldImpl(STRUCT_FIELD) + PsiElement(IDENTIFIER)('x') + MvTypeAnnotationImpl(TYPE_ANNOTATION) + PsiElement(:)(':') + PsiWhiteSpace(' ') + MvPathTypeImpl(PATH_TYPE) + MvPathImpl(PATH) + PsiElement(IDENTIFIER)('u64') + PsiElement(,)(',') + PsiWhiteSpace(' ') + MvStructFieldImpl(STRUCT_FIELD) + PsiElement(IDENTIFIER)('y') + MvTypeAnnotationImpl(TYPE_ANNOTATION) + PsiElement(:)(':') + PsiWhiteSpace(' ') + MvPathTypeImpl(PATH_TYPE) + MvPathImpl(PATH) + PsiElement(IDENTIFIER)('u8') + PsiElement(})('}') + PsiElement(,)(',') + PsiWhiteSpace('\n ') + MvEnumVariantImpl(ENUM_VARIANT) + PsiElement(IDENTIFIER)('Bar') + MvStructBlockImpl(STRUCT_BLOCK) + PsiElement({)('{') + MvStructFieldImpl(STRUCT_FIELD) + PsiElement(IDENTIFIER)('x') + MvTypeAnnotationImpl(TYPE_ANNOTATION) + PsiElement(:)(':') + PsiWhiteSpace(' ') + MvPathTypeImpl(PATH_TYPE) + MvPathImpl(PATH) + PsiElement(IDENTIFIER)('u64') + PsiElement(,)(',') + PsiWhiteSpace(' ') + MvStructFieldImpl(STRUCT_FIELD) + PsiElement(IDENTIFIER)('z') + MvTypeAnnotationImpl(TYPE_ANNOTATION) + PsiElement(:)(':') + PsiWhiteSpace(' ') + MvPathTypeImpl(PATH_TYPE) + MvPathImpl(PATH) + PsiElement(IDENTIFIER)('u32') + PsiElement(})('}') + PsiWhiteSpace('\n ') + PsiElement(})('}') + PsiWhiteSpace('\n\n ') + MvEnumImpl(ENUM) + PsiElement(enum_kw)('enum') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('Outer') + PsiWhiteSpace(' ') + MvEnumBodyImpl(ENUM_BODY) + PsiElement({)('{') + PsiWhiteSpace('\n ') + MvEnumVariantImpl(ENUM_VARIANT) + PsiElement(IDENTIFIER)('None') + PsiElement(,)(',') + PsiWhiteSpace('\n ') + MvEnumVariantImpl(ENUM_VARIANT) + PsiElement(IDENTIFIER)('One') + MvStructBlockImpl(STRUCT_BLOCK) + PsiElement({)('{') + MvStructFieldImpl(STRUCT_FIELD) + PsiElement(IDENTIFIER)('i') + MvTypeAnnotationImpl(TYPE_ANNOTATION) + PsiElement(:)(':') + PsiWhiteSpace(' ') + MvPathTypeImpl(PATH_TYPE) + MvPathImpl(PATH) + PsiElement(IDENTIFIER)('Inner') + PsiElement(})('}') + PsiElement(,)(',') + PsiWhiteSpace('\n ') + MvEnumVariantImpl(ENUM_VARIANT) + PsiElement(IDENTIFIER)('Two') + MvStructBlockImpl(STRUCT_BLOCK) + PsiElement({)('{') + MvStructFieldImpl(STRUCT_FIELD) + PsiElement(IDENTIFIER)('i') + MvTypeAnnotationImpl(TYPE_ANNOTATION) + PsiElement(:)(':') + PsiWhiteSpace(' ') + MvPathTypeImpl(PATH_TYPE) + MvPathImpl(PATH) + PsiElement(IDENTIFIER)('Inner') + PsiElement(,)(',') + PsiWhiteSpace(' ') + MvStructFieldImpl(STRUCT_FIELD) + PsiElement(IDENTIFIER)('b') + MvTypeAnnotationImpl(TYPE_ANNOTATION) + PsiElement(:)(':') + PsiWhiteSpace(' ') + MvPathTypeImpl(PATH_TYPE) + MvPathImpl(PATH) + PsiElement(IDENTIFIER)('Box') + PsiElement(})('}') + PsiElement(,)(',') + PsiWhiteSpace('\n ') + PsiElement(})('}') + PsiWhiteSpace('\n') + PsiElement(})('}') \ No newline at end of file From a804cfbdd166b93fad69bb29ab2e5e424495bac7 Mon Sep 17 00:00:00 2001 From: Maksim Kurnikov Date: Sat, 3 Aug 2024 17:20:02 +0300 Subject: [PATCH 2/3] struct field parser renames --- src/main/grammars/MoveParser.bnf | 22 ++++++----- .../ide/annotator/HighlightingAnnotator.kt | 2 +- .../move/ide/annotator/MvErrorAnnotator.kt | 2 +- .../move/ide/docs/MvDocumentationProvider.kt | 2 +- .../org/move/ide/folding/MvFoldingBuilder.kt | 4 +- .../org/move/ide/formatter/impl/spacing.kt | 2 +- .../org/move/ide/formatter/impl/utils.kt | 2 +- .../ide/inspections/MvTypeCheckInspection.kt | 2 +- .../MvUnresolvedReferenceInspection.kt | 2 +- .../move/ide/refactoring/MvRenameProcessor.kt | 2 +- .../lang/core/completion/LookupElements.kt | 2 +- .../lang/core/completion/LookupElements2.kt | 2 +- .../lang/core/completion/MvLookupElement.kt | 2 +- .../org/move/lang/core/psi/ext/MvStruct.kt | 8 ++-- .../lang/core/psi/ext/MvStructDotField.kt | 6 ++- .../move/lang/core/psi/ext/MvStructField.kt | 14 +++---- .../lang/core/psi/ext/MvStructLitField.kt | 20 +--------- .../core/types/infer/TypeInferenceWalker.kt | 2 +- .../move/lang/parser/complete/attributes.txt | 2 +- .../org/move/lang/parser/complete/enums.txt | 38 +++++++++---------- .../move/lang/parser/complete/index_expr.txt | 8 ++-- .../parser/complete/struct_declarations.txt | 18 ++++----- .../move/lang/parser/partial/struct_decls.txt | 2 +- .../lang/parser/partial/struct_fields.txt | 28 +++++++------- 24 files changed, 92 insertions(+), 102 deletions(-) diff --git a/src/main/grammars/MoveParser.bnf b/src/main/grammars/MoveParser.bnf index 2ff4b6e87..2fa295b96 100644 --- a/src/main/grammars/MoveParser.bnf +++ b/src/main/grammars/MoveParser.bnf @@ -355,7 +355,7 @@ SpecInlineFunctionStmt ::= SpecInlineFunctionInner } fake Struct ::= Attr* native? STRUCT_KW IDENTIFIER? TypeParameterList? AbilitiesList? - (';' | StructBlock)? + (';' | BlockFields)? { implements = [ "org.move.lang.core.psi.MvQualNamedElement" @@ -369,7 +369,7 @@ fake Struct ::= Attr* native? STRUCT_KW IDENTIFIER? TypeParameterList? Abilities private StructInnerFirst ::= STRUCT_KW StructInner ::= Attr* StructInnerFirst IDENTIFIER TypeParameterList? AbilitiesList? - StructBlock + BlockFields { pin = StructInnerFirst elementType = Struct @@ -393,7 +393,7 @@ EnumBody ::= '{' (EnumVariant ','?)* '}' { pin = 1 } -EnumVariant ::= Attr* IDENTIFIER StructBlock? +EnumVariant ::= Attr* IDENTIFIER BlockFields? fake Function ::= Attr* native? VisibilityModifier? entry? inline? fun? IDENTIFIER? TypeParameterList? FunctionParameterList? @@ -446,6 +446,9 @@ private enum ::= <> private package ::= <> private for ::= <> +private AttrsAndVis_first ::= '#' +//private AttrsAndVis_first ::= '#' | public + private FunctionModifierSetInner ::= <> private NativeFunctionModifierSetInner ::= <> @@ -507,15 +510,15 @@ Ability ::= copy | IDENTIFIER name = "ability" } -StructBlock ::= '{' StructField_with_recover* '}' { pin = 1 } -private StructField_with_recover ::= !'}' StructField (',' | &'}') +BlockFields ::= '{' NamedFieldDecl_with_recover* '}' { pin = 1 } +private NamedFieldDecl_with_recover ::= !'}' NamedFieldDecl (',' | &'}') { pin = 1 - recoverWhile = StructField_recover + recoverWhile = NamedFieldDecl_recover } -private StructField_recover ::= !('}' | IDENTIFIER) +private NamedFieldDecl_recover ::= !('}' | NamedFieldDecl_first) -StructField ::= Attr* IDENTIFIER TypeAnnotation &(',' | '}') +NamedFieldDecl ::= Attr* IDENTIFIER TypeAnnotation &(',' | '}') { pin = 2 implements = [ @@ -523,9 +526,10 @@ StructField ::= Attr* IDENTIFIER TypeAnnotation &(',' | '}') "org.move.lang.core.psi.ext.MvDocAndAttributeOwner" "org.move.lang.core.psi.MvTypeAnnotationOwner" ] - mixin = "org.move.lang.core.psi.ext.MvStructFieldMixin" + mixin = "org.move.lang.core.psi.ext.MvNamedFieldDeclMixin" hooks = [ leftBinder = "ADJACENT_LINE_COMMENTS" ] } +private NamedFieldDecl_first ::= AttrsAndVis_first | IDENTIFIER FriendDecl ::= Attr* friend PathImpl ';' { diff --git a/src/main/kotlin/org/move/ide/annotator/HighlightingAnnotator.kt b/src/main/kotlin/org/move/ide/annotator/HighlightingAnnotator.kt index decacf0d5..59fbc7a31 100644 --- a/src/main/kotlin/org/move/ide/annotator/HighlightingAnnotator.kt +++ b/src/main/kotlin/org/move/ide/annotator/HighlightingAnnotator.kt @@ -71,7 +71,7 @@ class HighlightingAnnotator: MvAnnotatorBase() { else -> MvColor.FUNCTION } if (element is MvStruct) return MvColor.STRUCT - if (element is MvStructField) return MvColor.FIELD + if (element is MvNamedFieldDecl) return MvColor.FIELD if (element is MvStructDotField) return MvColor.FIELD if (element is MvMethodCall) return MvColor.METHOD_CALL if (element is MvStructPatField) return MvColor.FIELD diff --git a/src/main/kotlin/org/move/ide/annotator/MvErrorAnnotator.kt b/src/main/kotlin/org/move/ide/annotator/MvErrorAnnotator.kt index 6eaedfbee..1babfd7b2 100644 --- a/src/main/kotlin/org/move/ide/annotator/MvErrorAnnotator.kt +++ b/src/main/kotlin/org/move/ide/annotator/MvErrorAnnotator.kt @@ -32,7 +32,7 @@ class MvErrorAnnotator: MvAnnotatorBase() { override fun visitModule(o: MvModule) = checkModuleDef(moveHolder, o) - override fun visitStructField(o: MvStructField) = checkDuplicates(moveHolder, o) + override fun visitNamedFieldDecl(o: MvNamedFieldDecl) = checkDuplicates(moveHolder, o) override fun visitPath(o: MvPath) = checkMethodOrPath(o, moveHolder) override fun visitMethodCall(o: MvMethodCall) = checkMethodOrPath(o, moveHolder) diff --git a/src/main/kotlin/org/move/ide/docs/MvDocumentationProvider.kt b/src/main/kotlin/org/move/ide/docs/MvDocumentationProvider.kt index 27190ebb8..d715f15ec 100644 --- a/src/main/kotlin/org/move/ide/docs/MvDocumentationProvider.kt +++ b/src/main/kotlin/org/move/ide/docs/MvDocumentationProvider.kt @@ -129,7 +129,7 @@ fun MvElement.signature(builder: StringBuilder) { ?.joinToWithBuffer(buffer, ", ", " has ") { generateDocumentation(it) } } - is MvStructField -> { + is MvNamedFieldDecl -> { val module = this.structItem.module // val itemContext = this.structItem.outerItemContext(msl) buffer += module.qualName?.editorText() ?: "unknown" diff --git a/src/main/kotlin/org/move/ide/folding/MvFoldingBuilder.kt b/src/main/kotlin/org/move/ide/folding/MvFoldingBuilder.kt index b01a4ec29..7d0e799e4 100644 --- a/src/main/kotlin/org/move/ide/folding/MvFoldingBuilder.kt +++ b/src/main/kotlin/org/move/ide/folding/MvFoldingBuilder.kt @@ -87,8 +87,8 @@ class MvFoldingBuilder: CustomFoldingBuilder(), DumbAware { fold(o) } - override fun visitStructBlock(o: MvStructBlock) { - if (o.structFieldList.isNotEmpty()) + override fun visitBlockFields(o: MvBlockFields) { + if (o.namedFieldDeclList.isNotEmpty()) fold(o) } diff --git a/src/main/kotlin/org/move/ide/formatter/impl/spacing.kt b/src/main/kotlin/org/move/ide/formatter/impl/spacing.kt index a4785577d..b860482c0 100644 --- a/src/main/kotlin/org/move/ide/formatter/impl/spacing.kt +++ b/src/main/kotlin/org/move/ide/formatter/impl/spacing.kt @@ -25,7 +25,7 @@ import org.move.lang.core.tokenSetOf fun createSpacingBuilder(commonSettings: CommonCodeStyleSettings): SpacingBuilder { return SpacingBuilder(commonSettings) - .afterInside(COMMA, STRUCT_BLOCK).parentDependentLFSpacing(1, 1, true, 1) + .afterInside(COMMA, BLOCK_FIELDS).parentDependentLFSpacing(1, 1, true, 1) .after(COMMA).spacing(1, 1, 0, true, 0) .before(COMMA).spaceIf(false) .after(COLON).spaceIf(true) diff --git a/src/main/kotlin/org/move/ide/formatter/impl/utils.kt b/src/main/kotlin/org/move/ide/formatter/impl/utils.kt index f31ecc6a2..1ef08fed9 100644 --- a/src/main/kotlin/org/move/ide/formatter/impl/utils.kt +++ b/src/main/kotlin/org/move/ide/formatter/impl/utils.kt @@ -31,7 +31,7 @@ val STRUCT_LITERAL_BLOCKS = ts(STRUCT_PAT_FIELDS_BLOCK, STRUCT_LIT_FIELDS_BLOCK) val DEF_BLOCKS = ts( SCRIPT_BLOCK, ADDRESS_BLOCK, MODULE_BLOCK, CODE_BLOCK, MODULE_SPEC_BLOCK, SPEC_CODE_BLOCK, - STRUCT_BLOCK, SCHEMA_FIELDS_BLOCK + BLOCK_FIELDS, SCHEMA_FIELDS_BLOCK ) val BLOCK_LIKE = orSet(STRUCT_LITERAL_BLOCKS, DEF_BLOCKS) diff --git a/src/main/kotlin/org/move/ide/inspections/MvTypeCheckInspection.kt b/src/main/kotlin/org/move/ide/inspections/MvTypeCheckInspection.kt index 9f9fbdd8f..25b842fe6 100644 --- a/src/main/kotlin/org/move/ide/inspections/MvTypeCheckInspection.kt +++ b/src/main/kotlin/org/move/ide/inspections/MvTypeCheckInspection.kt @@ -60,7 +60,7 @@ class MvTypeCheckInspection : MvLocalInspectionTool() { } } - override fun visitStructField(field: MvStructField) { + override fun visitNamedFieldDecl(field: MvNamedFieldDecl) { val structItem = field.structItem for (innerType in field.type?.descendantsOfType().orEmpty()) { val typeItem = innerType.path.reference?.resolve() as? MvStruct ?: continue diff --git a/src/main/kotlin/org/move/ide/inspections/MvUnresolvedReferenceInspection.kt b/src/main/kotlin/org/move/ide/inspections/MvUnresolvedReferenceInspection.kt index 13e576680..a0aec6a2b 100644 --- a/src/main/kotlin/org/move/ide/inspections/MvUnresolvedReferenceInspection.kt +++ b/src/main/kotlin/org/move/ide/inspections/MvUnresolvedReferenceInspection.kt @@ -120,7 +120,7 @@ class MvUnresolvedReferenceInspection: MvLocalInspectionTool() { } if (litField.isShorthand) { val resolvedItems = litField.reference.multiResolve() - val resolvedStructField = resolvedItems.find { it is MvStructField } + val resolvedStructField = resolvedItems.find { it is MvNamedFieldDecl } if (resolvedStructField == null) { holder.registerProblem( litField.referenceNameElement, diff --git a/src/main/kotlin/org/move/ide/refactoring/MvRenameProcessor.kt b/src/main/kotlin/org/move/ide/refactoring/MvRenameProcessor.kt index 2299b9a3d..bbc21ef74 100644 --- a/src/main/kotlin/org/move/ide/refactoring/MvRenameProcessor.kt +++ b/src/main/kotlin/org/move/ide/refactoring/MvRenameProcessor.kt @@ -36,7 +36,7 @@ class MvRenameProcessor : RenamePsiElementProcessor() { } } } - is MvStructField -> { + is MvNamedFieldDecl -> { usages.forEach { val usage = it.element when { diff --git a/src/main/kotlin/org/move/lang/core/completion/LookupElements.kt b/src/main/kotlin/org/move/lang/core/completion/LookupElements.kt index 4b247524a..fd5320ed7 100644 --- a/src/main/kotlin/org/move/lang/core/completion/LookupElements.kt +++ b/src/main/kotlin/org/move/lang/core/completion/LookupElements.kt @@ -240,7 +240,7 @@ private fun MvNamedElement.getLookupElementBuilder( .withTypeText(this.containingFile?.name) } - is MvStructField -> { + is MvNamedFieldDecl -> { val fieldTy = this.type?.loweredType(msl)?.substitute(subst) ?: TyUnknown lookupElementBuilder .withTypeText(fieldTy.text(false)) 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 f6a4e9742..3f35cea86 100644 --- a/src/main/kotlin/org/move/lang/core/completion/LookupElements2.kt +++ b/src/main/kotlin/org/move/lang/core/completion/LookupElements2.kt @@ -64,7 +64,7 @@ private fun MvNamedElement.getLookupElementBuilder( .withTypeText(this.containingFile?.name) } - is MvStructField -> { + is MvNamedFieldDecl -> { val fieldTy = this.type?.loweredType(msl)?.substitute(subst) ?: TyUnknown base .withTypeText(fieldTy.text(false)) diff --git a/src/main/kotlin/org/move/lang/core/completion/MvLookupElement.kt b/src/main/kotlin/org/move/lang/core/completion/MvLookupElement.kt index a594b24f9..31444c364 100644 --- a/src/main/kotlin/org/move/lang/core/completion/MvLookupElement.kt +++ b/src/main/kotlin/org/move/lang/core/completion/MvLookupElement.kt @@ -72,7 +72,7 @@ fun getLookupElementProperties( // so changing to infallible getPatTypeOrUnknown() inference?.getPatTypeOrUnknown(element) ?: TyUnknown } - is MvStructField -> element.type?.loweredType(msl) ?: TyUnknown + is MvNamedFieldDecl -> element.type?.loweredType(msl) ?: TyUnknown else -> TyUnknown } val itemTy = declaredTy.substitute(subst) diff --git a/src/main/kotlin/org/move/lang/core/psi/ext/MvStruct.kt b/src/main/kotlin/org/move/lang/core/psi/ext/MvStruct.kt index 6217a96e6..beb0bf3ca 100644 --- a/src/main/kotlin/org/move/lang/core/psi/ext/MvStruct.kt +++ b/src/main/kotlin/org/move/lang/core/psi/ext/MvStruct.kt @@ -16,10 +16,10 @@ import org.move.lang.core.types.ty.TyStruct import org.move.stdext.withAdded import javax.swing.Icon -val MvStruct.fields: List - get() = structBlock?.structFieldList.orEmpty() +val MvStruct.fields: List + get() = blockFields?.namedFieldDeclList.orEmpty() -val MvStruct.fieldsMap: Map +val MvStruct.fieldsMap: Map get() { return fields.associateBy { it.name } } @@ -73,7 +73,7 @@ fun MvStruct.addAbility(ability: String) { this.abilitiesList?.replace(newAbilitiesList) } else { val anchor = when { - this.structBlock != null -> this.structBlock + this.blockFields != null -> this.blockFields this.hasChild(MvElementTypes.SEMICOLON) -> this.getChild(MvElementTypes.SEMICOLON) else -> return } diff --git a/src/main/kotlin/org/move/lang/core/psi/ext/MvStructDotField.kt b/src/main/kotlin/org/move/lang/core/psi/ext/MvStructDotField.kt index 42441ae3a..bbd467238 100644 --- a/src/main/kotlin/org/move/lang/core/psi/ext/MvStructDotField.kt +++ b/src/main/kotlin/org/move/lang/core/psi/ext/MvStructDotField.kt @@ -9,7 +9,11 @@ import org.move.lang.core.types.infer.inference import org.move.lang.core.types.ty.TyStruct import org.move.stdext.wrapWithList -fun getFieldVariants(element: MvMethodOrField, receiverTy: TyStruct, msl: Boolean): MatchSequence { +fun getFieldVariants( + element: MvMethodOrField, + receiverTy: TyStruct, + msl: Boolean +): MatchSequence { val structItem = receiverTy.item if (!msl) { // cannot resolve field if not in the same module as struct definition 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 075676a58..ec8934838 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 @@ -4,22 +4,22 @@ import com.intellij.ide.projectView.PresentationData import com.intellij.lang.ASTNode import com.intellij.navigation.ItemPresentation import org.move.ide.MoveIcons +import org.move.lang.core.psi.MvBlockFields +import org.move.lang.core.psi.MvNamedFieldDecl import org.move.lang.core.psi.MvStruct -import org.move.lang.core.psi.MvStructBlock -import org.move.lang.core.psi.MvStructField import org.move.lang.core.psi.impl.MvMandatoryNameIdentifierOwnerImpl import javax.swing.Icon -val MvStructField.fieldsDefBlock: MvStructBlock? +val MvNamedFieldDecl.fieldsDefBlock: MvBlockFields? get() = - parent as? MvStructBlock + parent as? MvBlockFields -val MvStructField.structItem: MvStruct +val MvNamedFieldDecl.structItem: MvStruct get() = fieldsDefBlock?.parent as MvStruct -abstract class MvStructFieldMixin(node: ASTNode) : MvMandatoryNameIdentifierOwnerImpl(node), - MvStructField { +abstract class MvNamedFieldDeclMixin(node: ASTNode) : MvMandatoryNameIdentifierOwnerImpl(node), + MvNamedFieldDecl { override fun getIcon(flags: Int): Icon = MoveIcons.STRUCT_FIELD diff --git a/src/main/kotlin/org/move/lang/core/psi/ext/MvStructLitField.kt b/src/main/kotlin/org/move/lang/core/psi/ext/MvStructLitField.kt index 767076220..bb0caa3fa 100644 --- a/src/main/kotlin/org/move/lang/core/psi/ext/MvStructLitField.kt +++ b/src/main/kotlin/org/move/lang/core/psi/ext/MvStructLitField.kt @@ -21,7 +21,7 @@ val MvStructLitField.isShorthand: Boolean inline fun MvStructLitField.resolveToElement(): T? = reference.multiResolve().filterIsInstance().singleOrNull() -fun MvStructLitField.resolveToDeclaration(): MvStructField? = resolveToElement() +fun MvStructLitField.resolveToDeclaration(): MvNamedFieldDecl? = resolveToElement() fun MvStructLitField.resolveToBinding(): MvBindingPat? = resolveToElement() interface MvStructRefField: MvMandatoryReferenceElement @@ -30,11 +30,6 @@ abstract class MvStructLitFieldMixin(node: ASTNode): MvElementImpl(node), MvStructLitField { override fun getReference(): MvPolyVariantReference = MvStructRefFieldReferenceImpl(this, shorthand = this.isShorthand) -// if (this.isShorthand) { -// return MvStructLitShorthandFieldReferenceImpl(this) -// } else { -// return MvStructRefFieldReferenceImpl(this) -// } } class MvStructRefFieldReferenceImpl( @@ -47,16 +42,10 @@ class MvStructRefFieldReferenceImpl( var variants = collectResolveVariants(referenceName) { processStructRefFieldResolveVariants(element, it) } -// var variants = resolveIntoStructField(element) if (shorthand) { variants += resolveBindingForFieldShorthand(element) -// variants += resolveLocalItem(element, setOf(Namespace.NAME)) } return variants -// return listOf( -// resolveIntoStructField(element), -// resolveLocalItem(element, setOf(Namespace.NAME)) -// ).flatten() } } @@ -71,13 +60,6 @@ fun processStructRefFieldResolveVariants( } } -fun resolveIntoStructField(element: MvStructRefField): List { - val structItem = element.maybeStruct ?: return emptyList() - val referenceName = element.referenceName - return structItem.fields - .filter { it.name == referenceName } -} - private val MvStructRefField.maybeStruct: MvStruct? get() { return when (this) { diff --git a/src/main/kotlin/org/move/lang/core/types/infer/TypeInferenceWalker.kt b/src/main/kotlin/org/move/lang/core/types/infer/TypeInferenceWalker.kt index 4abd2066f..3efc20d34 100644 --- a/src/main/kotlin/org/move/lang/core/types/infer/TypeInferenceWalker.kt +++ b/src/main/kotlin/org/move/lang/core/types/infer/TypeInferenceWalker.kt @@ -298,7 +298,7 @@ class TypeInferenceWalker( is MvBindingPat -> ctx.getPatType(item) is MvConst -> item.type?.loweredType(msl) ?: TyUnknown is MvGlobalVariableStmt -> item.type?.loweredType(true) ?: TyUnknown - is MvStructField -> item.type?.loweredType(msl) ?: TyUnknown + is MvNamedFieldDecl -> item.type?.loweredType(msl) ?: TyUnknown is MvStruct -> { if (project.moveSettings.enableIndexExpr && refExpr.parent is MvIndexExpr) { TyLowering.lowerPath(refExpr.path, item, ctx.msl) diff --git a/src/test/resources/org/move/lang/parser/complete/attributes.txt b/src/test/resources/org/move/lang/parser/complete/attributes.txt index ba7abfed8..4167aadae 100644 --- a/src/test/resources/org/move/lang/parser/complete/attributes.txt +++ b/src/test/resources/org/move/lang/parser/complete/attributes.txt @@ -73,7 +73,7 @@ FILE PsiWhiteSpace(' ') PsiElement(IDENTIFIER)('SomeStruct') PsiWhiteSpace(' ') - MvStructBlockImpl(STRUCT_BLOCK) + MvBlockFieldsImpl(BLOCK_FIELDS) PsiElement({)('{') PsiElement(})('}') PsiWhiteSpace('\n\n ') diff --git a/src/test/resources/org/move/lang/parser/complete/enums.txt b/src/test/resources/org/move/lang/parser/complete/enums.txt index 996c3cc48..b1edad581 100644 --- a/src/test/resources/org/move/lang/parser/complete/enums.txt +++ b/src/test/resources/org/move/lang/parser/complete/enums.txt @@ -30,9 +30,9 @@ FILE PsiWhiteSpace('\n ') MvEnumVariantImpl(ENUM_VARIANT) PsiElement(IDENTIFIER)('RGB') - MvStructBlockImpl(STRUCT_BLOCK) + MvBlockFieldsImpl(BLOCK_FIELDS) PsiElement({)('{') - MvStructFieldImpl(STRUCT_FIELD) + MvNamedFieldDeclImpl(NAMED_FIELD_DECL) PsiElement(IDENTIFIER)('red') MvTypeAnnotationImpl(TYPE_ANNOTATION) PsiElement(:)(':') @@ -42,7 +42,7 @@ FILE PsiElement(IDENTIFIER)('u64') PsiElement(,)(',') PsiWhiteSpace(' ') - MvStructFieldImpl(STRUCT_FIELD) + MvNamedFieldDeclImpl(NAMED_FIELD_DECL) PsiElement(IDENTIFIER)('green') MvTypeAnnotationImpl(TYPE_ANNOTATION) PsiElement(:)(':') @@ -52,7 +52,7 @@ FILE PsiElement(IDENTIFIER)('u64') PsiElement(,)(',') PsiWhiteSpace(' ') - MvStructFieldImpl(STRUCT_FIELD) + MvNamedFieldDeclImpl(NAMED_FIELD_DECL) PsiElement(IDENTIFIER)('blue') MvTypeAnnotationImpl(TYPE_ANNOTATION) PsiElement(:)(':') @@ -83,9 +83,9 @@ FILE PsiWhiteSpace('\n ') MvEnumVariantImpl(ENUM_VARIANT) PsiElement(IDENTIFIER)('RGB') - MvStructBlockImpl(STRUCT_BLOCK) + MvBlockFieldsImpl(BLOCK_FIELDS) PsiElement({)('{') - MvStructFieldImpl(STRUCT_FIELD) + MvNamedFieldDeclImpl(NAMED_FIELD_DECL) PsiElement(IDENTIFIER)('red') MvTypeAnnotationImpl(TYPE_ANNOTATION) PsiElement(:)(':') @@ -95,7 +95,7 @@ FILE PsiElement(IDENTIFIER)('u64') PsiElement(,)(',') PsiWhiteSpace(' ') - MvStructFieldImpl(STRUCT_FIELD) + MvNamedFieldDeclImpl(NAMED_FIELD_DECL) PsiElement(IDENTIFIER)('green') MvTypeAnnotationImpl(TYPE_ANNOTATION) PsiElement(:)(':') @@ -105,7 +105,7 @@ FILE PsiElement(IDENTIFIER)('u64') PsiElement(,)(',') PsiWhiteSpace(' ') - MvStructFieldImpl(STRUCT_FIELD) + MvNamedFieldDeclImpl(NAMED_FIELD_DECL) PsiElement(IDENTIFIER)('blue') MvTypeAnnotationImpl(TYPE_ANNOTATION) PsiElement(:)(':') @@ -135,9 +135,9 @@ FILE PsiWhiteSpace('\n ') MvEnumVariantImpl(ENUM_VARIANT) PsiElement(IDENTIFIER)('Foo') - MvStructBlockImpl(STRUCT_BLOCK) + MvBlockFieldsImpl(BLOCK_FIELDS) PsiElement({)('{') - MvStructFieldImpl(STRUCT_FIELD) + MvNamedFieldDeclImpl(NAMED_FIELD_DECL) PsiElement(IDENTIFIER)('x') MvTypeAnnotationImpl(TYPE_ANNOTATION) PsiElement(:)(':') @@ -147,7 +147,7 @@ FILE PsiElement(IDENTIFIER)('u64') PsiElement(,)(',') PsiWhiteSpace(' ') - MvStructFieldImpl(STRUCT_FIELD) + MvNamedFieldDeclImpl(NAMED_FIELD_DECL) PsiElement(IDENTIFIER)('y') MvTypeAnnotationImpl(TYPE_ANNOTATION) PsiElement(:)(':') @@ -160,9 +160,9 @@ FILE PsiWhiteSpace('\n ') MvEnumVariantImpl(ENUM_VARIANT) PsiElement(IDENTIFIER)('Bar') - MvStructBlockImpl(STRUCT_BLOCK) + MvBlockFieldsImpl(BLOCK_FIELDS) PsiElement({)('{') - MvStructFieldImpl(STRUCT_FIELD) + MvNamedFieldDeclImpl(NAMED_FIELD_DECL) PsiElement(IDENTIFIER)('x') MvTypeAnnotationImpl(TYPE_ANNOTATION) PsiElement(:)(':') @@ -172,7 +172,7 @@ FILE PsiElement(IDENTIFIER)('u64') PsiElement(,)(',') PsiWhiteSpace(' ') - MvStructFieldImpl(STRUCT_FIELD) + MvNamedFieldDeclImpl(NAMED_FIELD_DECL) PsiElement(IDENTIFIER)('z') MvTypeAnnotationImpl(TYPE_ANNOTATION) PsiElement(:)(':') @@ -198,9 +198,9 @@ FILE PsiWhiteSpace('\n ') MvEnumVariantImpl(ENUM_VARIANT) PsiElement(IDENTIFIER)('One') - MvStructBlockImpl(STRUCT_BLOCK) + MvBlockFieldsImpl(BLOCK_FIELDS) PsiElement({)('{') - MvStructFieldImpl(STRUCT_FIELD) + MvNamedFieldDeclImpl(NAMED_FIELD_DECL) PsiElement(IDENTIFIER)('i') MvTypeAnnotationImpl(TYPE_ANNOTATION) PsiElement(:)(':') @@ -213,9 +213,9 @@ FILE PsiWhiteSpace('\n ') MvEnumVariantImpl(ENUM_VARIANT) PsiElement(IDENTIFIER)('Two') - MvStructBlockImpl(STRUCT_BLOCK) + MvBlockFieldsImpl(BLOCK_FIELDS) PsiElement({)('{') - MvStructFieldImpl(STRUCT_FIELD) + MvNamedFieldDeclImpl(NAMED_FIELD_DECL) PsiElement(IDENTIFIER)('i') MvTypeAnnotationImpl(TYPE_ANNOTATION) PsiElement(:)(':') @@ -225,7 +225,7 @@ FILE PsiElement(IDENTIFIER)('Inner') PsiElement(,)(',') PsiWhiteSpace(' ') - MvStructFieldImpl(STRUCT_FIELD) + MvNamedFieldDeclImpl(NAMED_FIELD_DECL) PsiElement(IDENTIFIER)('b') MvTypeAnnotationImpl(TYPE_ANNOTATION) PsiElement(:)(':') diff --git a/src/test/resources/org/move/lang/parser/complete/index_expr.txt b/src/test/resources/org/move/lang/parser/complete/index_expr.txt index 6935a2ef5..e4821c4e6 100644 --- a/src/test/resources/org/move/lang/parser/complete/index_expr.txt +++ b/src/test/resources/org/move/lang/parser/complete/index_expr.txt @@ -34,10 +34,10 @@ FILE MvAbilityImpl(ABILITY) PsiElement(IDENTIFIER)('store') PsiWhiteSpace(' ') - MvStructBlockImpl(STRUCT_BLOCK) + MvBlockFieldsImpl(BLOCK_FIELDS) PsiElement({)('{') PsiWhiteSpace('\n ') - MvStructFieldImpl(STRUCT_FIELD) + MvNamedFieldDeclImpl(NAMED_FIELD_DECL) PsiElement(IDENTIFIER)('value') MvTypeAnnotationImpl(TYPE_ANNOTATION) PsiElement(:)(':') @@ -68,10 +68,10 @@ FILE MvAbilityImpl(ABILITY) PsiElement(IDENTIFIER)('drop') PsiWhiteSpace(' ') - MvStructBlockImpl(STRUCT_BLOCK) + MvBlockFieldsImpl(BLOCK_FIELDS) PsiElement({)('{') PsiWhiteSpace('\n ') - MvStructFieldImpl(STRUCT_FIELD) + MvNamedFieldDeclImpl(NAMED_FIELD_DECL) PsiElement(IDENTIFIER)('field') MvTypeAnnotationImpl(TYPE_ANNOTATION) PsiElement(:)(':') diff --git a/src/test/resources/org/move/lang/parser/complete/struct_declarations.txt b/src/test/resources/org/move/lang/parser/complete/struct_declarations.txt index 70209cd50..08d95b3a8 100644 --- a/src/test/resources/org/move/lang/parser/complete/struct_declarations.txt +++ b/src/test/resources/org/move/lang/parser/complete/struct_declarations.txt @@ -28,7 +28,7 @@ FILE PsiElement(IDENTIFIER)('CoinType2') PsiElement(>)('>') PsiWhiteSpace(' ') - MvStructBlockImpl(STRUCT_BLOCK) + MvBlockFieldsImpl(BLOCK_FIELDS) PsiElement({)('{') PsiElement(})('}') PsiWhiteSpace('\n\n ') @@ -52,10 +52,10 @@ FILE MvAbilityImpl(ABILITY) PsiElement(IDENTIFIER)('drop') PsiWhiteSpace(' ') - MvStructBlockImpl(STRUCT_BLOCK) + MvBlockFieldsImpl(BLOCK_FIELDS) PsiElement({)('{') PsiWhiteSpace('\n ') - MvStructFieldImpl(STRUCT_FIELD) + MvNamedFieldDeclImpl(NAMED_FIELD_DECL) PsiElement(IDENTIFIER)('val1') MvTypeAnnotationImpl(TYPE_ANNOTATION) PsiElement(:)(':') @@ -65,7 +65,7 @@ FILE PsiElement(IDENTIFIER)('u8') PsiElement(,)(',') PsiWhiteSpace('\n ') - MvStructFieldImpl(STRUCT_FIELD) + MvNamedFieldDeclImpl(NAMED_FIELD_DECL) PsiElement(IDENTIFIER)('val2') MvTypeAnnotationImpl(TYPE_ANNOTATION) PsiElement(:)(':') @@ -99,10 +99,10 @@ FILE PsiElement(copy)('copy') PsiElement(>)('>') PsiWhiteSpace(' ') - MvStructBlockImpl(STRUCT_BLOCK) + MvBlockFieldsImpl(BLOCK_FIELDS) PsiElement({)('{') PsiWhiteSpace('\n ') - MvStructFieldImpl(STRUCT_FIELD) + MvNamedFieldDeclImpl(NAMED_FIELD_DECL) PsiElement(IDENTIFIER)('val1') MvTypeAnnotationImpl(TYPE_ANNOTATION) PsiElement(:)(':') @@ -112,7 +112,7 @@ FILE PsiElement(IDENTIFIER)('u8') PsiElement(,)(',') PsiWhiteSpace('\n ') - MvStructFieldImpl(STRUCT_FIELD) + MvNamedFieldDeclImpl(NAMED_FIELD_DECL) PsiElement(IDENTIFIER)('val2') MvTypeAnnotationImpl(TYPE_ANNOTATION) PsiElement(:)(':') @@ -129,7 +129,7 @@ FILE PsiElement(>)('>') PsiElement(,)(',') PsiWhiteSpace('\n ') - MvStructFieldImpl(STRUCT_FIELD) + MvNamedFieldDeclImpl(NAMED_FIELD_DECL) PsiElement(IDENTIFIER)('operator_account') MvTypeAnnotationImpl(TYPE_ANNOTATION) PsiElement(:)(':') @@ -146,7 +146,7 @@ FILE PsiElement(>)('>') PsiElement(,)(',') PsiWhiteSpace('\n ') - MvStructFieldImpl(STRUCT_FIELD) + MvNamedFieldDeclImpl(NAMED_FIELD_DECL) PsiElement(IDENTIFIER)('operator_account2') MvTypeAnnotationImpl(TYPE_ANNOTATION) PsiElement(:)(':') diff --git a/src/test/resources/org/move/lang/parser/partial/struct_decls.txt b/src/test/resources/org/move/lang/parser/partial/struct_decls.txt index 202c6fa83..77202a0e4 100644 --- a/src/test/resources/org/move/lang/parser/partial/struct_decls.txt +++ b/src/test/resources/org/move/lang/parser/partial/struct_decls.txt @@ -34,7 +34,7 @@ FILE PsiErrorElement:IDENTIFIER expected, got '{' PsiWhiteSpace(' ') - MvStructBlockImpl(STRUCT_BLOCK) + MvBlockFieldsImpl(BLOCK_FIELDS) PsiElement({)('{') PsiElement(})('}') PsiWhiteSpace('\n ') diff --git a/src/test/resources/org/move/lang/parser/partial/struct_fields.txt b/src/test/resources/org/move/lang/parser/partial/struct_fields.txt index b03f53f0b..575623954 100644 --- a/src/test/resources/org/move/lang/parser/partial/struct_fields.txt +++ b/src/test/resources/org/move/lang/parser/partial/struct_fields.txt @@ -12,20 +12,20 @@ FILE PsiWhiteSpace(' ') PsiElement(IDENTIFIER)('T') PsiWhiteSpace(' ') - MvStructBlockImpl(STRUCT_BLOCK) + MvBlockFieldsImpl(BLOCK_FIELDS) PsiElement({)('{') - PsiErrorElement: expected, got ':' + PsiErrorElement: expected, got ':' PsiWhiteSpace('\n ') PsiElement(:)(':') PsiWhiteSpace(' ') - MvStructFieldImpl(STRUCT_FIELD) + MvNamedFieldDeclImpl(NAMED_FIELD_DECL) PsiElement(IDENTIFIER)('u8') PsiErrorElement: expected, got ',' PsiElement(,)(',') PsiWhiteSpace('\n ') - MvStructFieldImpl(STRUCT_FIELD) + MvNamedFieldDeclImpl(NAMED_FIELD_DECL) PsiElement(IDENTIFIER)('my_field') MvTypeAnnotationImpl(TYPE_ANNOTATION) PsiElement(:)(':') @@ -41,10 +41,10 @@ FILE PsiWhiteSpace(' ') PsiElement(IDENTIFIER)('T') PsiWhiteSpace(' ') - MvStructBlockImpl(STRUCT_BLOCK) + MvBlockFieldsImpl(BLOCK_FIELDS) PsiElement({)('{') PsiWhiteSpace('\n ') - MvStructFieldImpl(STRUCT_FIELD) + MvNamedFieldDeclImpl(NAMED_FIELD_DECL) PsiElement(IDENTIFIER)('my_field') MvTypeAnnotationImpl(TYPE_ANNOTATION) PsiElement(:)(':') @@ -53,7 +53,7 @@ FILE PsiWhiteSpace(' ') PsiElement(,)(',') PsiWhiteSpace('\n ') - MvStructFieldImpl(STRUCT_FIELD) + MvNamedFieldDeclImpl(NAMED_FIELD_DECL) PsiElement(IDENTIFIER)('my_field') MvTypeAnnotationImpl(TYPE_ANNOTATION) PsiElement(:)(':') @@ -69,10 +69,10 @@ FILE PsiWhiteSpace(' ') PsiElement(IDENTIFIER)('T') PsiWhiteSpace(' ') - MvStructBlockImpl(STRUCT_BLOCK) + MvBlockFieldsImpl(BLOCK_FIELDS) PsiElement({)('{') PsiWhiteSpace('\n ') - MvStructFieldImpl(STRUCT_FIELD) + MvNamedFieldDeclImpl(NAMED_FIELD_DECL) PsiElement(IDENTIFIER)('my_field') MvTypeAnnotationImpl(TYPE_ANNOTATION) PsiElement(:)(':') @@ -83,7 +83,7 @@ FILE PsiErrorElement:',', '::', or '}' expected, got 'my_field' PsiWhiteSpace('\n ') - MvStructFieldImpl(STRUCT_FIELD) + MvNamedFieldDeclImpl(NAMED_FIELD_DECL) PsiElement(IDENTIFIER)('my_field') MvTypeAnnotationImpl(TYPE_ANNOTATION) PsiElement(:)(':') @@ -99,16 +99,16 @@ FILE PsiWhiteSpace(' ') PsiElement(IDENTIFIER)('NoTypesFields') PsiWhiteSpace(' ') - MvStructBlockImpl(STRUCT_BLOCK) + MvBlockFieldsImpl(BLOCK_FIELDS) PsiElement({)('{') PsiWhiteSpace('\n ') - MvStructFieldImpl(STRUCT_FIELD) + MvNamedFieldDeclImpl(NAMED_FIELD_DECL) PsiElement(IDENTIFIER)('field1') PsiErrorElement: expected, got ',' PsiElement(,)(',') PsiWhiteSpace('\n ') - MvStructFieldImpl(STRUCT_FIELD) + MvNamedFieldDeclImpl(NAMED_FIELD_DECL) PsiElement(IDENTIFIER)('field2') MvTypeAnnotationImpl(TYPE_ANNOTATION) PsiElement(:)(':') @@ -116,7 +116,7 @@ FILE PsiElement(,)(',') PsiWhiteSpace('\n ') - MvStructFieldImpl(STRUCT_FIELD) + MvNamedFieldDeclImpl(NAMED_FIELD_DECL) PsiElement(IDENTIFIER)('field3') PsiErrorElement: expected, got '}' From e362fdf3afc68fd7aa181545dbb07e79dbdac0c0 Mon Sep 17 00:00:00 2001 From: Maksim Kurnikov Date: Sat, 3 Aug 2024 20:38:18 +0300 Subject: [PATCH 3/3] enum name resolution in type context --- src/main/grammars/MoveParser.bnf | 20 ++- .../org/move/lang/core/psi/ext/MvEnum.kt | 21 +++ .../move/lang/core/psi/ext/MvEnumVariant.kt | 18 +++ .../org/move/lang/core/psi/ext/MvModule.kt | 2 + .../org/move/lang/core/psi/ext/MvPath.kt | 92 +++++-------- .../move/lang/core/resolve2/ItemResolution.kt | 1 + .../core/resolve2/LexicalDeclarations2.kt | 7 +- .../move/lang/core/resolve2/Visibility2.kt | 6 +- .../core/resolve2/ref/Path2ReferenceImpl.kt | 11 +- .../org/move/lang/core/stubs/StubIndexing.kt | 8 ++ .../kotlin/org/move/lang/core/stubs/Stubs.kt | 68 ++++++++++ .../move/lang/core/stubs/impl/MvFileStub.kt | 2 +- .../org/move/lang/resolve/ResolveTypesTest.kt | 121 ++++++++++++++++++ .../org/move/lang/parser/complete/enums.move | 2 + .../org/move/lang/parser/complete/enums.txt | 48 +++++++ 15 files changed, 359 insertions(+), 68 deletions(-) create mode 100644 src/main/kotlin/org/move/lang/core/psi/ext/MvEnum.kt create mode 100644 src/main/kotlin/org/move/lang/core/psi/ext/MvEnumVariant.kt diff --git a/src/main/grammars/MoveParser.bnf b/src/main/grammars/MoveParser.bnf index 2fa295b96..4c9823bc0 100644 --- a/src/main/grammars/MoveParser.bnf +++ b/src/main/grammars/MoveParser.bnf @@ -384,9 +384,16 @@ NativeStructInner ::= Attr* NativeStructInnerFirst IDENTIFIER TypeParameterList? } private StructItem ::= StructInner | NativeStructInner -Enum ::= enum IDENTIFIER TypeParameterList? AbilitiesList? EnumBody +Enum ::= Attr* enum IDENTIFIER TypeParameterList? AbilitiesList? EnumBody { pin = "enum" + implements = [ + "org.move.lang.core.psi.MvTypeParametersOwner" + "org.move.lang.core.psi.ext.MvItemElement" + ] + mixin = "org.move.lang.core.psi.ext.MvEnumMixin" + stubClass = "org.move.lang.core.stubs.MvEnumStub" + elementTypeFactory = "org.move.lang.core.stubs.StubsKt.factory" hooks = [ leftBinder = "ADJACENT_LINE_COMMENTS" ] } EnumBody ::= '{' (EnumVariant ','?)* '}' @@ -394,6 +401,17 @@ EnumBody ::= '{' (EnumVariant ','?)* '}' pin = 1 } EnumVariant ::= Attr* IDENTIFIER BlockFields? +{ + pin = 2 + implements = [ + "org.move.lang.core.psi.MvNameIdentifierOwner" + "org.move.lang.core.psi.ext.MvDocAndAttributeOwner" + ] + mixin = "org.move.lang.core.psi.ext.MvEnumVariantMixin" + stubClass = "org.move.lang.core.stubs.MvEnumVariantStub" + elementTypeFactory = "org.move.lang.core.stubs.StubsKt.factory" + hooks = [ leftBinder = "ADJACENT_LINE_COMMENTS" ] +} fake Function ::= Attr* native? VisibilityModifier? entry? inline? fun? IDENTIFIER? TypeParameterList? FunctionParameterList? diff --git a/src/main/kotlin/org/move/lang/core/psi/ext/MvEnum.kt b/src/main/kotlin/org/move/lang/core/psi/ext/MvEnum.kt new file mode 100644 index 000000000..3a6cbb8f2 --- /dev/null +++ b/src/main/kotlin/org/move/lang/core/psi/ext/MvEnum.kt @@ -0,0 +1,21 @@ +package org.move.lang.core.psi.ext + +import com.intellij.lang.ASTNode +import com.intellij.psi.stubs.IStubElementType +import org.move.ide.MoveIcons +import org.move.lang.core.psi.MvEnum +import org.move.lang.core.psi.MvEnumVariant +import org.move.lang.core.stubs.MvEnumStub +import org.move.lang.core.stubs.MvStubbedNamedElementImpl +import javax.swing.Icon + +val MvEnum.variants: List get() = enumBody?.enumVariantList.orEmpty() + +abstract class MvEnumMixin: MvStubbedNamedElementImpl, + MvEnum { + constructor(node: ASTNode): super(node) + + constructor(stub: MvEnumStub, nodeType: IStubElementType<*, *>): super(stub, nodeType) + + override fun getIcon(flags: Int): Icon = MoveIcons.STRUCT +} \ No newline at end of file diff --git a/src/main/kotlin/org/move/lang/core/psi/ext/MvEnumVariant.kt b/src/main/kotlin/org/move/lang/core/psi/ext/MvEnumVariant.kt new file mode 100644 index 000000000..b99a56e52 --- /dev/null +++ b/src/main/kotlin/org/move/lang/core/psi/ext/MvEnumVariant.kt @@ -0,0 +1,18 @@ +package org.move.lang.core.psi.ext + +import com.intellij.lang.ASTNode +import com.intellij.psi.stubs.IStubElementType +import org.move.ide.MoveIcons +import org.move.lang.core.psi.MvEnumVariant +import org.move.lang.core.stubs.MvEnumVariantStub +import org.move.lang.core.stubs.MvStubbedNamedElementImpl +import javax.swing.Icon + +abstract class MvEnumVariantMixin: MvStubbedNamedElementImpl, + MvEnumVariant { + constructor(node: ASTNode): super(node) + + constructor(stub: MvEnumVariantStub, nodeType: IStubElementType<*, *>): super(stub, nodeType) + + override fun getIcon(flags: Int): Icon = MoveIcons.STRUCT +} \ No newline at end of file diff --git a/src/main/kotlin/org/move/lang/core/psi/ext/MvModule.kt b/src/main/kotlin/org/move/lang/core/psi/ext/MvModule.kt index 6ff04f33a..6da77e2fd 100644 --- a/src/main/kotlin/org/move/lang/core/psi/ext/MvModule.kt +++ b/src/main/kotlin/org/move/lang/core/psi/ext/MvModule.kt @@ -97,6 +97,8 @@ fun builtinSpecFunction(text: String, project: Project): MvSpecFunction { return project.psiFactory.specFunction(trimmedText, moduleName = "builtin_spec_functions") } +fun MvModule.enums(): List = this.moduleBlock?.enumList.orEmpty() + fun MvModule.structs(): List { return getProjectPsiDependentCache(this) { val stub = it.greenStub diff --git a/src/main/kotlin/org/move/lang/core/psi/ext/MvPath.kt b/src/main/kotlin/org/move/lang/core/psi/ext/MvPath.kt index effaa9cdf..a77cdc9f8 100644 --- a/src/main/kotlin/org/move/lang/core/psi/ext/MvPath.kt +++ b/src/main/kotlin/org/move/lang/core/psi/ext/MvPath.kt @@ -10,6 +10,7 @@ import org.move.ide.inspections.imports.basePathType import org.move.lang.core.psi.* import org.move.lang.core.resolve.ref.MvPath2Reference import org.move.lang.core.resolve.ref.Namespace +import org.move.lang.core.resolve.ref.Namespace.* import org.move.lang.core.resolve2.ref.Path2ReferenceImpl import java.util.* @@ -42,11 +43,6 @@ fun MvPath.isPrimitiveType(): Boolean = this.parent is MvPathType && this.referenceName in PRIMITIVE_TYPE_IDENTIFIERS.union(BUILTIN_TYPE_IDENTIFIERS) -//fun MvPath.isAttrItem(): Boolean { -// val attrItem = this.ancestorStrict() ?: return false -// return attrItem.name == "expected_failure" -//} - fun MvPath.isSpecPrimitiveType(): Boolean = this.parent is MvPathType && this.referenceName in PRIMITIVE_TYPE_IDENTIFIERS @@ -68,64 +64,42 @@ val MvPath.isUpdateFieldArg2: Boolean val MvPath.identifierName: String? get() = identifier?.text -//val MvPath.nullModuleRef: Boolean -// get() = -// identifier != null && this.moduleRef == null - val MvPath.maybeStruct get() = reference?.resolveFollowingAliases() as? MvStruct val MvPath.maybeSchema get() = reference?.resolveFollowingAliases() as? MvSchema fun MvPath.allowedNamespaces(): Set { - val parent = this.parent -// return when (parent) { -// is MvPath, -// is MvPathType -> TYPES -// else -> VALUES -// } - return if (parent is MvPath) EnumSet.of(Namespace.MODULE) else rootNamespace(this) -// return when { -// parent is MvSchemaLit || parent is MvSchemaRef -> setOf(Namespace.SCHEMA) -// parent is MvPathType -> setOf(Namespace.TYPE) -// parent is MvCallExpr -> setOf(Namespace.FUNCTION) -// parent is MvRefExpr && parent.isAbortCodeConst() -> setOf(Namespace.CONST) -// parent is MvRefExpr -> setOf(Namespace.NAME) -//// parent is MvRefExpr && this.nullModuleRef -> setOf(Namespace.NAME) -//// parent is MvRefExpr && !this.nullModuleRef -> setOf(Namespace.NAME, Namespace.MODULE) -// // TODO: it's own namespace? -// parent is MvStructLitExpr || parent is MvStructPat -> setOf(Namespace.NAME) -// parent is MvAccessSpecifier -> setOf(Namespace.TYPE) -// parent is MvAddressSpecifierArg -> setOf(Namespace.FUNCTION) -// parent is MvAddressSpecifierCallParam -> setOf(Namespace.NAME) -// else -> debugErrorOrFallback( -// "Cannot build path namespaces: unhandled parent type ${parent.elementType}", -// setOf(Namespace.NAME) -// ) -// } -} + val qualifierPath = this.path + val parentElement = this.parent + + // m::S, S::One + // ^ ^ + if (parentElement is MvPath && qualifierPath == null) return EnumSet.of(MODULE, TYPE) + + // m::S::One + // ^ + if (parentElement is MvPath && parentElement.parent is MvPath) return EnumSet.of(MODULE) + + // m::S::One + // ^ + if (parentElement is MvPath/* && qualifierPath != null*/) return EnumSet.of(TYPE) -private fun rootNamespace(rootPath: MvPath): Set { - val parent = rootPath.parent - check(parent !is MvPath) return when { - parent is MvSchemaLit || parent is MvSchemaRef -> EnumSet.of(Namespace.SCHEMA) - parent is MvPathType -> EnumSet.of(Namespace.TYPE) - parent is MvCallExpr -> EnumSet.of(Namespace.FUNCTION) -// parent is MvRefExpr && parent.isAbortCodeConst() -> EnumSet.of(Namespace.CONST) - parent is MvRefExpr && rootPath.hasAncestor() -> EnumSet.of(Namespace.NAME, Namespace.MODULE) - parent is MvRefExpr -> EnumSet.of(Namespace.NAME) -// parent is MvRefExpr -> EnumSet.of(Namespace.NAME, Namespace.CONST) - parent is MvStructLitExpr || parent is MvStructPat -> EnumSet.of(Namespace.TYPE) -// parent is MvStructLitExpr || parent is MvStructPat -> EnumSet.of(Namespace.NAME) - parent is MvAccessSpecifier -> EnumSet.of(Namespace.TYPE) - parent is MvAddressSpecifierArg -> EnumSet.of(Namespace.FUNCTION) - parent is MvAddressSpecifierCallParam -> EnumSet.of(Namespace.NAME) - parent is MvFriendDecl -> EnumSet.of(Namespace.MODULE) - parent is MvModuleSpec -> EnumSet.of(Namespace.MODULE) - parent is MvUseSpeck -> Namespace.all() + parentElement is MvSchemaLit || parentElement is MvSchemaRef -> EnumSet.of(SCHEMA) + parentElement is MvPathType -> EnumSet.of(TYPE) + parentElement is MvCallExpr -> EnumSet.of(FUNCTION) + parentElement is MvRefExpr && this.hasAncestor() -> EnumSet.of(NAME, MODULE) + parentElement is MvRefExpr -> EnumSet.of(NAME) + parentElement is MvStructLitExpr || parentElement is MvStructPat -> EnumSet.of(TYPE) + parentElement is MvAccessSpecifier -> EnumSet.of(TYPE) + parentElement is MvAddressSpecifierArg -> EnumSet.of(FUNCTION) + parentElement is MvAddressSpecifierCallParam -> EnumSet.of(NAME) + parentElement is MvFriendDecl -> EnumSet.of(MODULE) + parentElement is MvModuleSpec -> EnumSet.of(MODULE) + parentElement is MvUseSpeck -> Namespace.all() else -> debugErrorOrFallback( - "Cannot build path namespaces: unhandled parent type ${parent.elementType}", - EnumSet.of(Namespace.NAME) + "Cannot build path namespaces: unhandled parent type ${parentElement.elementType}", + EnumSet.of(NAME) ) } } @@ -149,13 +123,13 @@ abstract class MvPathMixin(node: ASTNode): MvElementImpl(node), MvPath { fun MvPath.importCandidateNamespaces(): Set { val parent = this.parent return when (parent) { - is MvPathType -> setOf(Namespace.TYPE) - is MvSchemaLit, is MvSchemaRef -> setOf(Namespace.SCHEMA) + is MvPathType -> setOf(TYPE) + is MvSchemaLit, is MvSchemaRef -> setOf(SCHEMA) else -> { val baseBaseType = this.basePathType() when (baseBaseType) { - is BasePathType.Module -> EnumSet.of(Namespace.MODULE) - else -> EnumSet.of(Namespace.NAME, Namespace.FUNCTION) + is BasePathType.Module -> EnumSet.of(MODULE) + else -> EnumSet.of(NAME, FUNCTION) } } } diff --git a/src/main/kotlin/org/move/lang/core/resolve2/ItemResolution.kt b/src/main/kotlin/org/move/lang/core/resolve2/ItemResolution.kt index 5a6c1e804..4bf76119f 100644 --- a/src/main/kotlin/org/move/lang/core/resolve2/ItemResolution.kt +++ b/src/main/kotlin/org/move/lang/core/resolve2/ItemResolution.kt @@ -26,6 +26,7 @@ val MvNamedElement.namespace get() = when (this) { is MvFunctionLike -> Namespace.FUNCTION is MvStruct -> Namespace.TYPE + is MvEnum -> Namespace.TYPE is MvConst -> Namespace.NAME is MvSchema -> Namespace.SCHEMA is MvModule -> Namespace.MODULE diff --git a/src/main/kotlin/org/move/lang/core/resolve2/LexicalDeclarations2.kt b/src/main/kotlin/org/move/lang/core/resolve2/LexicalDeclarations2.kt index 716a5fa03..996c884f6 100644 --- a/src/main/kotlin/org/move/lang/core/resolve2/LexicalDeclarations2.kt +++ b/src/main/kotlin/org/move/lang/core/resolve2/LexicalDeclarations2.kt @@ -181,7 +181,11 @@ fun processItemsInScope( } is MvModuleBlock -> { val module = scope.parent as MvModule - processor.processAllItems(ns, module.structs()) + processor.processAllItems( + ns, + module.structs(), + module.enums() + ) } is MvApplySchemaStmt -> { val toPatterns = scope.applyTo?.functionPatternList.orEmpty() @@ -200,6 +204,7 @@ fun processItemsInScope( is MvModuleSpecBlock -> processor.processAllItems(ns, scope.schemaList, scope.specFunctionList) else -> false } + else -> false } if (stop) return true diff --git a/src/main/kotlin/org/move/lang/core/resolve2/Visibility2.kt b/src/main/kotlin/org/move/lang/core/resolve2/Visibility2.kt index dbe37c32e..aee6ab9d5 100644 --- a/src/main/kotlin/org/move/lang/core/resolve2/Visibility2.kt +++ b/src/main/kotlin/org/move/lang/core/resolve2/Visibility2.kt @@ -36,9 +36,6 @@ fun ItemVisibilityInfo.createFilter(): VisibilityFilter { // inside msl everything is visible if (element.isMsl()) return@VisibilityFilter Visible - // types are always visible, their correct usage is checked in a separate inspection - if (namespaces.contains(TYPE)) return@VisibilityFilter Visible - // if inside MvAttrItem like abort_code= val attrItem = element.ancestorStrict() if (attrItem != null) return@VisibilityFilter Visible @@ -80,6 +77,9 @@ fun ItemVisibilityInfo.createFilter(): VisibilityFilter { // local methods, Self::method - everything is visible if (itemModule == pathModule) return@VisibilityFilter Visible + // types visibility is ignored, their correct usage is checked in a separate inspection + if (namespaces.contains(TYPE)) return@VisibilityFilter Visible + when (visibility) { is Restricted -> { when (visibility) { diff --git a/src/main/kotlin/org/move/lang/core/resolve2/ref/Path2ReferenceImpl.kt b/src/main/kotlin/org/move/lang/core/resolve2/ref/Path2ReferenceImpl.kt index 9774c8bd2..1407c21ff 100644 --- a/src/main/kotlin/org/move/lang/core/resolve2/ref/Path2ReferenceImpl.kt +++ b/src/main/kotlin/org/move/lang/core/resolve2/ref/Path2ReferenceImpl.kt @@ -5,6 +5,7 @@ import org.move.cli.MoveProject import org.move.lang.core.psi.* import org.move.lang.core.psi.ext.MvMethodOrPath import org.move.lang.core.psi.ext.useSpeck +import org.move.lang.core.psi.ext.variants import org.move.lang.core.resolve.* import org.move.lang.core.resolve.ref.* import org.move.lang.core.resolve2.* @@ -61,8 +62,10 @@ fun processPathResolveVariants( return when (pathKind) { is NamedAddress, is ValueAddress -> false is PathKind.UnqualifiedPath -> { - // Self:: - if (processor.lazy("Self") { ctx.containingModule }) return true + if (Namespace.MODULE in pathKind.ns) { + // Self:: + if (processor.lazy("Self") { ctx.containingModule }) return true + } // local processNestedScopesUpwards(ctx.element, pathKind.ns, ctx, processor) } @@ -99,12 +102,14 @@ fun processQualifiedPathResolveVariants( } if (resolvedQualifier is MvModule) { if (processor.process("Self", resolvedQualifier)) return true - val moduleBlock = resolvedQualifier.moduleBlock if (moduleBlock != null) { if (processItemDeclarations(moduleBlock, ns, processor)) return true } } + if (resolvedQualifier is MvEnum) { + if (processor.processAll(resolvedQualifier.variants)) return true + } return false } diff --git a/src/main/kotlin/org/move/lang/core/stubs/StubIndexing.kt b/src/main/kotlin/org/move/lang/core/stubs/StubIndexing.kt index cc1d05afc..43d4e55ad 100644 --- a/src/main/kotlin/org/move/lang/core/stubs/StubIndexing.kt +++ b/src/main/kotlin/org/move/lang/core/stubs/StubIndexing.kt @@ -44,6 +44,14 @@ fun IndexSink.indexStructStub(stub: MvStructStub) { indexNamedStub(stub) } +fun IndexSink.indexEnumStub(stub: MvEnumStub) { + indexNamedStub(stub) +} + +fun IndexSink.indexEnumVariantStub(stub: MvEnumVariantStub) { + indexNamedStub(stub) +} + fun IndexSink.indexSchemaStub(stub: MvSchemaStub) { indexNamedStub(stub) } diff --git a/src/main/kotlin/org/move/lang/core/stubs/Stubs.kt b/src/main/kotlin/org/move/lang/core/stubs/Stubs.kt index 6b57bd873..516bc12a0 100644 --- a/src/main/kotlin/org/move/lang/core/stubs/Stubs.kt +++ b/src/main/kotlin/org/move/lang/core/stubs/Stubs.kt @@ -280,6 +280,72 @@ class MvStructStub( } } +class MvEnumStub( + parent: StubElement<*>?, + elementType: IStubElementType<*, *>, + override val name: String?, + override val flags: Int, +) : MvAttributeOwnerStubBase(parent, elementType), MvNamedStub { + + object Type : MvStubElementType("ENUM") { + override fun deserialize(dataStream: StubInputStream, parentStub: StubElement<*>?): MvEnumStub { + val name = dataStream.readNameAsString() + val flags = dataStream.readInt() + return MvEnumStub(parentStub, this, name, flags) + } + + override fun serialize(stub: MvEnumStub, dataStream: StubOutputStream) = + with(dataStream) { + writeName(stub.name) + writeInt(stub.flags) + } + + override fun createPsi(stub: MvEnumStub): MvEnum = + MvEnumImpl(stub, this) + + override fun createStub(psi: MvEnum, parentStub: StubElement<*>?): MvEnumStub { + val attrs = QueryAttributes(psi.attrList.asSequence()) + val flags = MvAttributeOwnerStub.extractFlags(attrs) + return MvEnumStub(parentStub, this, psi.name, flags) + } + + override fun indexStub(stub: MvEnumStub, sink: IndexSink) = sink.indexEnumStub(stub) + } +} + +class MvEnumVariantStub( + parent: StubElement<*>?, + elementType: IStubElementType<*, *>, + override val name: String?, + override val flags: Int, +) : MvAttributeOwnerStubBase(parent, elementType), MvNamedStub { + + object Type : MvStubElementType("ENUM_VARIANT") { + override fun deserialize(dataStream: StubInputStream, parentStub: StubElement<*>?): MvEnumVariantStub { + val name = dataStream.readNameAsString() + val flags = dataStream.readInt() + return MvEnumVariantStub(parentStub, this, name, flags) + } + + override fun serialize(stub: MvEnumVariantStub, dataStream: StubOutputStream) = + with(dataStream) { + writeName(stub.name) + writeInt(stub.flags) + } + + override fun createPsi(stub: MvEnumVariantStub): MvEnumVariant = + MvEnumVariantImpl(stub, this) + + override fun createStub(psi: MvEnumVariant, parentStub: StubElement<*>?): MvEnumVariantStub { + val attrs = QueryAttributes(psi.attrList.asSequence()) + val flags = MvAttributeOwnerStub.extractFlags(attrs) + return MvEnumVariantStub(parentStub, this, psi.name, flags) + } + + override fun indexStub(stub: MvEnumVariantStub, sink: IndexSink) = sink.indexEnumVariantStub(stub) + } +} + class MvSchemaStub( parent: StubElement<*>?, elementType: IStubElementType<*, *>, @@ -376,6 +442,8 @@ fun factory(name: String): MvStubElementType<*, *> = when (name) { "FUNCTION" -> MvFunctionStub.Type "SPEC_FUNCTION" -> MvSpecFunctionStub.Type "STRUCT" -> MvStructStub.Type + "ENUM" -> MvEnumStub.Type + "ENUM_VARIANT" -> MvEnumVariantStub.Type "SCHEMA" -> MvSchemaStub.Type "CONST" -> MvConstStub.Type "MODULE_SPEC" -> MvModuleSpecStub.Type diff --git a/src/main/kotlin/org/move/lang/core/stubs/impl/MvFileStub.kt b/src/main/kotlin/org/move/lang/core/stubs/impl/MvFileStub.kt index 9cf7ac2c4..7a4710bee 100644 --- a/src/main/kotlin/org/move/lang/core/stubs/impl/MvFileStub.kt +++ b/src/main/kotlin/org/move/lang/core/stubs/impl/MvFileStub.kt @@ -17,7 +17,7 @@ class MvFileStub(file: MoveFile?) : PsiFileStubImpl(file) { override fun getType() = Type object Type : IStubFileElementType(MoveLanguage) { - private const val STUB_VERSION = 25 + private const val STUB_VERSION = 26 // Bump this number if Stub structure changes override fun getStubVersion(): Int = MoveParserDefinition.PARSER_VERSION + STUB_VERSION diff --git a/src/test/kotlin/org/move/lang/resolve/ResolveTypesTest.kt b/src/test/kotlin/org/move/lang/resolve/ResolveTypesTest.kt index bc2573a80..8b3021ed5 100644 --- a/src/test/kotlin/org/move/lang/resolve/ResolveTypesTest.kt +++ b/src/test/kotlin/org/move/lang/resolve/ResolveTypesTest.kt @@ -364,4 +364,125 @@ module 0x1::m { } } """) + + fun `test resolve enum type`() = checkByCode(""" + module 0x1::m { + enum S { One, Two } + //X + fun main(one: S::One) { + //^ + } + } + """) + + fun `test resolve enum type from module`() = checkByCode(""" + module 0x1::m { + enum S { One, Two } + //X + } + module 0x1::main { + use 0x1::m; + fun main(one: m::S) { + //^ + } + } + """) + + fun `test resolve enum type from module with variant`() = checkByCode(""" + module 0x1::m { + enum S { One, Two } + //X + } + module 0x1::main { + use 0x1::m; + fun main(one: m::S::One) { + //^ + } + } + """) + + fun `test resolve enum type from module with the same name`() = checkByCode(""" + module 0x1::S { + enum S { One, Two } + //X + } + module 0x1::main { + use 0x1::S; + fun main(one: S::S::One) { + //^ + } + } + """) + + fun `test resolve enum type from fully qualified`() = checkByCode(""" + module 0x1::m { + enum S { One, Two } + //X + } + module 0x1::main { + fun main(one: 0x1::m::S) { + //^ + } + } + """) + + fun `test resolve enum type from fully qualified with variant`() = checkByCode(""" + module 0x1::m { + enum S { One, Two } + //X + } + module 0x1::main { + fun main(one: 0x1::m::S::One) { + //^ + } + } + """) + + fun `test resolve enum type from item import`() = checkByCode(""" + module 0x1::m { + enum S { One, Two } + //X + } + module 0x1::main { + use 0x1::m::S; + fun main(one: S::One) { + //^ + } + } + """) + + fun `test resolve enum variant`() = checkByCode(""" + module 0x1::m { + enum S { One, Two } + //X + fun main(one: S::One) { + //^ + } + } + """) + + fun `test resolve enum variant from module`() = checkByCode(""" + module 0x1::m { + enum S { One, Two } + //X + } + module 0x1::main { + use 0x1::m; + fun main(one: m::S::One) { + //^ + } + } + """) + + fun `test resolve enum variant from module fully qualified`() = checkByCode(""" + module 0x1::m { + enum S { One, Two } + //X + } + module 0x1::main { + fun main(one: 0x1::m::S::One) { + //^ + } + } + """) } diff --git a/src/test/resources/org/move/lang/parser/complete/enums.move b/src/test/resources/org/move/lang/parser/complete/enums.move index 27b3988cd..e7364542b 100644 --- a/src/test/resources/org/move/lang/parser/complete/enums.move +++ b/src/test/resources/org/move/lang/parser/complete/enums.move @@ -21,4 +21,6 @@ module 0x1::enums { One{i: Inner}, Two{i: Inner, b: Box}, } + + fun main(one: 0x1::m::S::One, two: m::S::Two) {} } diff --git a/src/test/resources/org/move/lang/parser/complete/enums.txt b/src/test/resources/org/move/lang/parser/complete/enums.txt index b1edad581..77ba7f836 100644 --- a/src/test/resources/org/move/lang/parser/complete/enums.txt +++ b/src/test/resources/org/move/lang/parser/complete/enums.txt @@ -237,5 +237,53 @@ FILE PsiElement(,)(',') PsiWhiteSpace('\n ') PsiElement(})('}') + PsiWhiteSpace('\n\n ') + MvFunctionImpl(FUNCTION) + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('main') + MvFunctionParameterListImpl(FUNCTION_PARAMETER_LIST) + PsiElement(()('(') + MvFunctionParameterImpl(FUNCTION_PARAMETER) + MvBindingPatImpl(BINDING_PAT) + PsiElement(IDENTIFIER)('one') + MvTypeAnnotationImpl(TYPE_ANNOTATION) + PsiElement(:)(':') + PsiWhiteSpace(' ') + MvPathTypeImpl(PATH_TYPE) + MvPathImpl(PATH) + MvPathImpl(PATH) + MvPathImpl(PATH) + MvPathImpl(PATH) + MvPathAddressImpl(PATH_ADDRESS) + PsiElement(DIEM_ADDRESS)('0x1') + PsiElement(::)('::') + PsiElement(IDENTIFIER)('m') + PsiElement(::)('::') + PsiElement(IDENTIFIER)('S') + PsiElement(::)('::') + PsiElement(IDENTIFIER)('One') + PsiElement(,)(',') + PsiWhiteSpace(' ') + MvFunctionParameterImpl(FUNCTION_PARAMETER) + MvBindingPatImpl(BINDING_PAT) + PsiElement(IDENTIFIER)('two') + MvTypeAnnotationImpl(TYPE_ANNOTATION) + PsiElement(:)(':') + PsiWhiteSpace(' ') + MvPathTypeImpl(PATH_TYPE) + MvPathImpl(PATH) + MvPathImpl(PATH) + MvPathImpl(PATH) + PsiElement(IDENTIFIER)('m') + PsiElement(::)('::') + PsiElement(IDENTIFIER)('S') + PsiElement(::)('::') + PsiElement(IDENTIFIER)('Two') + PsiElement())(')') + PsiWhiteSpace(' ') + MvCodeBlockImpl(CODE_BLOCK) + PsiElement({)('{') + PsiElement(})('}') PsiWhiteSpace('\n') PsiElement(})('}') \ No newline at end of file