Skip to content

Commit

Permalink
Merge pull request #169 from pontem-network/public-package
Browse files Browse the repository at this point in the history
Public package support for compiler v2
  • Loading branch information
mkurnikov authored Jul 5, 2024
2 parents 5a76d49 + 623c27f commit ac81360
Show file tree
Hide file tree
Showing 32 changed files with 532 additions and 67 deletions.
10 changes: 6 additions & 4 deletions src/main/grammars/MoveParser.bnf
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@
ENTRY = 'entry_kw'
INLINE = 'inline_kw'
FRIEND = 'friend_kw'
PACKAGE = 'package_kw'
FOR = 'for_kw'

READS = 'reads_kw'
Expand Down Expand Up @@ -380,7 +381,7 @@ NativeStructInner ::= Attr* NativeStructInnerFirst IDENTIFIER TypeParameterList?
}
private StructItem ::= StructInner | NativeStructInner

fake Function ::= Attr* native? FunctionVisibilityModifier? entry? inline?
fake Function ::= Attr* native? VisibilityModifier? entry? inline?
fun? IDENTIFIER? TypeParameterList? FunctionParameterList?
ReturnType? (ResourceAccessItemList | AcquiresType)?
(';' | CodeBlock)?
Expand Down Expand Up @@ -426,12 +427,13 @@ private FunctionSignatureInner ::= IDENTIFIER TypeParameterList?
private FunctionSignatureInner_recover ::= !('{' | '}' | ';' | <<eof>> | Item_first)

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

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

FunctionVisibilityModifier ::= public ('(' (SCRIPT_KW | friend) ')')?
VisibilityModifier ::= public ('(' (SCRIPT_KW | package | friend) ')')?

FunctionParameterList ::= '(' FunctionParameter_with_recover* ')' { pin = 1 }
private FunctionParameter_with_recover ::= !(')' | '{' | ';') FunctionParameter (',' | &')')
Expand Down
32 changes: 31 additions & 1 deletion src/main/kotlin/org/move/cli/MovePackage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import org.move.cli.manifest.AptosConfigYaml
import org.move.cli.manifest.MoveToml
import org.move.lang.core.psi.MvElement
import org.move.lang.moveProject
import org.move.lang.toNioPathOrNull
import org.move.openapiext.pathAsPath
import org.move.openapiext.resolveExisting
import java.nio.file.Path
import kotlin.io.path.relativeToOrNull

data class MovePackage(
val project: Project,
Expand All @@ -18,6 +21,7 @@ data class MovePackage(

val sourcesFolder: VirtualFile? get() = contentRoot.takeIf { it.isValid }?.findChild("sources")
val testsFolder: VirtualFile? get() = contentRoot.takeIf { it.isValid }?.findChild("tests")
val scriptsFolder: VirtualFile? get() = contentRoot.takeIf { it.isValid }?.findChild("scripts")

val aptosConfigYaml: AptosConfigYaml?
get() {
Expand All @@ -36,7 +40,7 @@ data class MovePackage(
return null
}

fun moveFolders(): List<VirtualFile> = listOfNotNull(sourcesFolder, testsFolder)
fun moveFolders(): List<VirtualFile> = listOfNotNull(sourcesFolder, testsFolder, scriptsFolder)

fun layoutPaths(): List<Path> {
val rootPath = contentRoot.takeIf { it.isValid }?.toNioPathOrNull() ?: return emptyList()
Expand All @@ -62,10 +66,36 @@ data class MovePackage(
return PackageAddresses(addresses, tomlMainAddresses.placeholders)
}

override fun hashCode(): Int {
return this.moveToml.tomlFile.toNioPathOrNull()?.hashCode() ?: this.hashCode()
}

override fun equals(other: Any?): Boolean {
if (other !is MovePackage) return false
val leftPath = this.moveToml.tomlFile.toNioPathOrNull() ?: return false
val rightPath = other.moveToml.tomlFile.toNioPathOrNull() ?: return false
return leftPath == rightPath
}

companion object {
fun fromMoveToml(moveToml: MoveToml): MovePackage {
val contentRoot = moveToml.tomlFile.virtualFile.parent
return MovePackage(moveToml.project, contentRoot, moveToml)
}
}
}

val MvElement.containingMovePackage: MovePackage?
get() {
val elementPath = this.containingFile?.toNioPathOrNull() ?: return null
val allPackages = this.moveProject?.movePackages().orEmpty()
return allPackages.find {
val folderPaths = it.moveFolders().mapNotNull { it.toNioPathOrNull() }
for (folderPath in folderPaths) {
if (elementPath.relativeToOrNull(folderPath) != null) {
return it
}
}
false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class MvProjectSettingsService(

val enableResourceAccessControl: Boolean get() = state.enableResourceAccessControl
val enableIndexExpr: Boolean get() = state.enableIndexExpr
val enablePublicPackage: Boolean get() = state.enablePublicPackage
val addCompilerV2CLIFlags: Boolean get() = state.addCompilerV2CLIFlags

// default values for settings
Expand All @@ -54,6 +55,9 @@ class MvProjectSettingsService(
@AffectsHighlighting
var enableIndexExpr: Boolean by property(false)

@AffectsHighlighting
var enablePublicPackage: Boolean by property(false)

@AffectsMoveProjectsMetadata
var fetchAptosDeps: Boolean by property(false)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,19 @@ class PerProjectAptosConfigurable(val project: Project): BoundConfigurable("Apto
row {
checkBox("Enable indexing")
.comment(
"Enables resource and vector indexing (i.e. v[0], R[@0x1]) " +
"for the Move files."
"Enables resource and vector indexing " +
"(i.e. <code>v[0]</code>, <code>R[@0x1]</code>) for the Move files."
)
.bindSelected(state::enableIndexExpr)
}
row {
checkBox("Enable public(package) visibility modifier")
.comment(
"Enables using <code>public(package)</code> visibility modifier " +
"to specify functions accessible to any module of the same package."
)
.bindSelected(state::enablePublicPackage)
}
}
group("Command Line Options") {
row {
Expand Down Expand Up @@ -111,6 +119,7 @@ class PerProjectAptosConfigurable(val project: Project): BoundConfigurable("Apto
it.dumpStateOnTestFailure = state.dumpStateOnTestFailure
it.enableResourceAccessControl = state.enableResourceAccessControl
it.enableIndexExpr = state.enableIndexExpr
it.enablePublicPackage = state.enablePublicPackage
it.addCompilerV2CLIFlags = state.addCompilerV2CLIFlags
it.fetchAptosDeps = state.fetchAptosDeps
}
Expand Down
36 changes: 35 additions & 1 deletion src/main/kotlin/org/move/ide/annotator/MvSyntaxErrorAnnotator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ class MvSyntaxErrorAnnotator: MvAnnotatorBase() {
override fun visitFunction(o: MvFunction) = checkFunction(moveHolder, o)
override fun visitSpecFunction(o: MvSpecFunction) = checkSpecFunction(moveHolder, o)
override fun visitIndexExpr(o: MvIndexExpr) = checkIndexExpr(moveHolder, o)

override fun visitModule(o: MvModule) {
checkVisibilityModifiers(moveHolder, o)
}
}
element.accept(visitor)
}
Expand Down Expand Up @@ -61,7 +65,7 @@ class MvSyntaxErrorAnnotator: MvAnnotatorBase() {
private fun checkIndexExpr(holder: MvAnnotationHolder, indexExpr: MvIndexExpr) {
if (!indexExpr.project.moveSettings.enableIndexExpr) {
Diagnostic
.IndexExprIsNotAllowed(indexExpr)
.IndexExprIsNotSupportedInCompilerV1(indexExpr)
.addToHolder(holder)
}
}
Expand All @@ -73,6 +77,36 @@ class MvSyntaxErrorAnnotator: MvAnnotatorBase() {
.addToHolder(holder)
}

private fun checkVisibilityModifiers(
holder: MvAnnotationHolder,
module: MvModule
) {
if (!module.project.moveSettings.enablePublicPackage) {
for (function in module.allFunctions()) {
val modifier = function.visibilityModifier ?: continue
if (modifier.isPublicPackage) {
Diagnostic.PublicPackageIsNotSupportedInCompilerV1(modifier)
.addToHolder(holder)
}
}
return
}

val allModifiers = module.allFunctions().map { it.visibilityFromPsi() }.toSet()
val friendAndPackageTogether =
FunctionVisibility.PUBLIC_PACKAGE in allModifiers
&& FunctionVisibility.PUBLIC_FRIEND in allModifiers
if (friendAndPackageTogether) {
for (function in module.allFunctions()) {
val modifier = function.visibilityModifier ?: continue
if (modifier.isPublicPackage || modifier.isPublicFriend) {
Diagnostic.PackageAndFriendModifiersCannotBeUsedTogether(modifier)
.addToHolder(holder)
}
}
}
}

private fun checkLitExpr(holder: MvAnnotationHolder, litExpr: MvLitExpr) {
val lit = litExpr.literal
when (lit) {
Expand Down
8 changes: 4 additions & 4 deletions src/main/kotlin/org/move/ide/formatter/impl/spacing.kt
Original file line number Diff line number Diff line change
Expand Up @@ -73,18 +73,18 @@ fun createSpacingBuilder(commonSettings: CommonCodeStyleSettings): SpacingBuilde
.between(TYPE_PARAMETER_LIST, FUNCTION_PARAMETER_LIST).spaceIf(false)
.before(VALUE_ARGUMENT_LIST).spaceIf(false)

.betweenInside(PUBLIC, L_PAREN, FUNCTION_VISIBILITY_MODIFIER).spaces(0)
.betweenInside(PUBLIC, L_PAREN, VISIBILITY_MODIFIER).spaces(0)
.betweenInside(
tokenSetOf(L_PAREN),
tokenSetOf(SCRIPT_KW, FRIEND),
FUNCTION_VISIBILITY_MODIFIER
VISIBILITY_MODIFIER
).spaces(0)
.betweenInside(
tokenSetOf(SCRIPT_KW, FRIEND),
tokenSetOf(R_PAREN),
FUNCTION_VISIBILITY_MODIFIER
VISIBILITY_MODIFIER
).spaces(0)
.after(FUNCTION_VISIBILITY_MODIFIER).spaces(1)
.after(VISIBILITY_MODIFIER).spaces(1)

.around(BINARY_OP).spaces(1)
.around(EQ).spaces(1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ import com.intellij.psi.PsiFile
import io.ktor.http.*
import org.move.cli.settings.moveSettings
import org.move.ide.inspections.DiagnosticIntentionFix
import org.move.ide.inspections.fixes.CompilerV2Feat.INDEXING
import org.move.ide.inspections.fixes.CompilerV2Feat.RESOURCE_CONTROL
import org.move.ide.inspections.fixes.CompilerV2Feat.*

enum class CompilerV2Feat(val title: String) {
INDEXING("Index notation"),
RESOURCE_CONTROL("Resource access control");
RESOURCE_CONTROL("Resource access control"),
PUBLIC_PACKAGE("`public(package)` function visibility");
}

class EnableCompilerV2FeatureFix(
Expand All @@ -23,7 +23,7 @@ class EnableCompilerV2FeatureFix(
DiagnosticIntentionFix<PsiElement>(element) {

override fun getText(): String =
"Enable ${feature.title.quote()} feature of Aptos Move V2 Compiler in the plugin settings"
"Enable ${feature.title.quote()} feature of Aptos Move V2 Compiler in the settings"

override fun invoke(project: Project, file: PsiFile, element: PsiElement) {
@Suppress("UnstableApiUsage")
Expand All @@ -32,6 +32,7 @@ class EnableCompilerV2FeatureFix(
when (feature) {
INDEXING -> it.enableIndexExpr = true
RESOURCE_CONTROL -> it.enableResourceAccessControl = true
PUBLIC_PACKAGE -> it.enablePublicPackage = true
}
}
}
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 packageKeyword(b: PsiBuilder, level: Int): Boolean = contextualKeyword(b, "package", PACKAGE)

@JvmStatic
fun forKeyword(b: PsiBuilder, level: Int): Boolean = contextualKeyword(b, "for", FOR)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class KeywordCompletionContributor: CompletionContributor() {
)
extend(
CompletionType.BASIC,
function().with(MvPsiPatterns.AfterSibling(FUNCTION_VISIBILITY_MODIFIER)),
function().with(MvPsiPatterns.AfterSibling(VISIBILITY_MODIFIER)),
KeywordCompletionProvider("fun", "entry", "inline")
)
extend(
Expand Down Expand Up @@ -159,6 +159,11 @@ class KeywordCompletionContributor: CompletionContributor() {
}

companion object {
private val VISIBILITY_MODIFIERS = arrayOf("public", "public(script)", "public(friend)")
private val VISIBILITY_MODIFIERS = arrayOf(
"public",
"public(script)",
"public(friend)",
"public(package)"
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ object ImportsCompletionProvider: MvCompletionProvider() {

val vs = when {
moduleRef.isSelf -> setOf(Visibility.Internal)
else -> Visibility.publicVisibilitiesFor(itemImport)
else -> Visibility.visibilityScopesForElement(itemImport)
}
val ns = setOf(Namespace.NAME, Namespace.TYPE, Namespace.FUNCTION)
val contextScopeInfo =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ abstract class MvPathCompletionProvider: MvCompletionProvider() {
?: return
val vs = when {
moduleRef.isSelf -> setOf(Visibility.Internal)
else -> Visibility.publicVisibilitiesFor(pathElement)
else -> Visibility.visibilityScopesForElement(pathElement)
}
processModuleItems(module, namespaces, vs, pathScopeInfo) {
val lookup =
Expand Down
19 changes: 6 additions & 13 deletions src/main/kotlin/org/move/lang/core/psi/ext/MvFunction.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,8 @@ enum class FunctionVisibility {
PRIVATE,
PUBLIC,
PUBLIC_FRIEND,
PUBLIC_PACKAGE,
PUBLIC_SCRIPT;

companion object {
fun fromInt(ordinal: Int): FunctionVisibility {
for (value in FunctionVisibility.values()) {
if (value.ordinal == ordinal) return value
}
error("Invalid value")
}
}
}

val MvFunction.visibility: FunctionVisibility
Expand All @@ -42,11 +34,12 @@ val MvFunction.visibility: FunctionVisibility
}

fun MvFunction.visibilityFromPsi(): FunctionVisibility {
val visibility = this.functionVisibilityModifier ?: return FunctionVisibility.PRIVATE
val visibility = this.visibilityModifier ?: return FunctionVisibility.PRIVATE
return when {
visibility.hasChild(MvElementTypes.FRIEND) -> FunctionVisibility.PUBLIC_FRIEND
visibility.hasChild(MvElementTypes.SCRIPT_KW) -> FunctionVisibility.PUBLIC_SCRIPT
visibility.hasChild(MvElementTypes.PUBLIC) -> FunctionVisibility.PUBLIC
visibility.isPublicFriend -> FunctionVisibility.PUBLIC_FRIEND
visibility.isPublicPackage -> FunctionVisibility.PUBLIC_PACKAGE
visibility.isPublicScript -> FunctionVisibility.PUBLIC_SCRIPT
visibility.isPublic -> FunctionVisibility.PUBLIC
else -> FunctionVisibility.PRIVATE
}
}
Expand Down
7 changes: 4 additions & 3 deletions src/main/kotlin/org/move/lang/core/psi/ext/MvMethodCall.kt
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,13 @@ fun getMethodVariants(element: MvMethodOrField, receiverTy: Ty, msl: Boolean): M
val moveProject = element.moveProject ?: return emptySequence()
val receiverTyItemModule = receiverTy.itemModule(moveProject) ?: return emptySequence()

val visibilities = Visibility.publicVisibilitiesFor(element).toMutableSet()
val elementScopes = Visibility.visibilityScopesForElement(element).toMutableSet()
if (element.containingModule == receiverTyItemModule) {
visibilities.add(Visibility.Internal)
elementScopes.add(Visibility.Internal)
}
val functions =
visibilities.flatMap { receiverTyItemModule.visibleFunctions(it) }
elementScopes
.flatMap { elementScope -> receiverTyItemModule.functionsVisibleInScope(elementScope) }
.filter {
val selfTy = it.selfParamTy(msl) ?: return@filter false
// need to use TyVar here, loweredType() erases them
Expand Down
Loading

0 comments on commit ac81360

Please sign in to comment.