Skip to content

Commit

Permalink
Merge pull request #175 from pontem-network/enums
Browse files Browse the repository at this point in the history
Enums parser support and basic name resolution
  • Loading branch information
mkurnikov authored Aug 3, 2024
2 parents a254667 + e362fdf commit f84ae1e
Show file tree
Hide file tree
Showing 39 changed files with 715 additions and 151 deletions.
56 changes: 46 additions & 10 deletions src/main/grammars/MoveParser.bnf
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -251,13 +252,14 @@ private ModuleItem ::= !('}' | <<eof>>) 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 ::= !('}' | <<eof>> | Item_first)

private ModuleItem_item ::= UseStmt
// | UseStmt
| FriendDecl
| StructItem
| Enum
| FunctionItem
| SpecFunctionItem
| Const
Expand Down Expand Up @@ -353,7 +355,7 @@ SpecInlineFunctionStmt ::= SpecInlineFunctionInner
}

fake Struct ::= Attr* native? STRUCT_KW IDENTIFIER? TypeParameterList? AbilitiesList?
(';' | StructBlock)?
(';' | BlockFields)?
{
implements = [
"org.move.lang.core.psi.MvQualNamedElement"
Expand All @@ -367,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
Expand All @@ -382,6 +384,35 @@ NativeStructInner ::= Attr* NativeStructInnerFirst IDENTIFIER TypeParameterList?
}
private StructItem ::= StructInner | NativeStructInner

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 ','?)* '}'
{
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?
ReturnType? (ResourceAccessItemList | AcquiresType)?
Expand Down Expand Up @@ -429,9 +460,13 @@ private FunctionSignatureInner ::= IDENTIFIER TypeParameterList?
private FunctionSignatureInner_recover ::= !('{' | '}' | ';' | <<eof>> | Item_first)

private friend ::= <<friendKeyword>>
private enum ::= <<enumKeyword>>
private package ::= <<packageKeyword>>
private for ::= <<forKeyword>>

private AttrsAndVis_first ::= '#'
//private AttrsAndVis_first ::= '#' | public

private FunctionModifierSetInner ::= <<functionModifierSet VisibilityModifier>>
private NativeFunctionModifierSetInner ::= <<nativeFunctionModifierSet VisibilityModifier>>

Expand Down Expand Up @@ -493,25 +528,26 @@ 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 = [
"org.move.lang.core.psi.MvMandatoryNameIdentifierOwner"
"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 ';'
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/org/move/ide/annotator/MvErrorAnnotator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
4 changes: 2 additions & 2 deletions src/main/kotlin/org/move/ide/folding/MvFoldingBuilder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/org/move/ide/formatter/impl/spacing.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/org/move/ide/formatter/impl/utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<MvPathType>().orEmpty()) {
val typeItem = innerType.path.reference?.resolve() as? MvStruct ?: continue
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class MvRenameProcessor : RenamePsiElementProcessor() {
}
}
}
is MvStructField -> {
is MvNamedFieldDecl -> {
usages.forEach {
val usage = it.element
when {
Expand Down
3 changes: 3 additions & 0 deletions src/main/kotlin/org/move/lang/core/MoveParserUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
21 changes: 21 additions & 0 deletions src/main/kotlin/org/move/lang/core/psi/ext/MvEnum.kt
Original file line number Diff line number Diff line change
@@ -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<MvEnumVariant> get() = enumBody?.enumVariantList.orEmpty()

abstract class MvEnumMixin: MvStubbedNamedElementImpl<MvEnumStub>,
MvEnum {
constructor(node: ASTNode): super(node)

constructor(stub: MvEnumStub, nodeType: IStubElementType<*, *>): super(stub, nodeType)

override fun getIcon(flags: Int): Icon = MoveIcons.STRUCT
}
18 changes: 18 additions & 0 deletions src/main/kotlin/org/move/lang/core/psi/ext/MvEnumVariant.kt
Original file line number Diff line number Diff line change
@@ -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<MvEnumVariantStub>,
MvEnumVariant {
constructor(node: ASTNode): super(node)

constructor(stub: MvEnumVariantStub, nodeType: IStubElementType<*, *>): super(stub, nodeType)

override fun getIcon(flags: Int): Icon = MoveIcons.STRUCT
}
2 changes: 2 additions & 0 deletions src/main/kotlin/org/move/lang/core/psi/ext/MvModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ fun builtinSpecFunction(text: String, project: Project): MvSpecFunction {
return project.psiFactory.specFunction(trimmedText, moduleName = "builtin_spec_functions")
}

fun MvModule.enums(): List<MvEnum> = this.moduleBlock?.enumList.orEmpty()

fun MvModule.structs(): List<MvStruct> {
return getProjectPsiDependentCache(this) {
val stub = it.greenStub
Expand Down
Loading

0 comments on commit f84ae1e

Please sign in to comment.