Skip to content

Commit

Permalink
Merge pull request #170 from pontem-network/receiver-style-feature-flag
Browse files Browse the repository at this point in the history
Receiver style feature flag
  • Loading branch information
mkurnikov authored Jul 8, 2024
2 parents ce809e3 + 0feedeb commit 7fe22f1
Show file tree
Hide file tree
Showing 36 changed files with 701 additions and 496 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class MvProjectSettingsService(
val skipFetchLatestGitDeps: Boolean get() = state.skipFetchLatestGitDeps
val dumpStateOnTestFailure: Boolean get() = state.dumpStateOnTestFailure

val enableReceiverStyleFunctions: Boolean get() = state.enableReceiverStyleFunctions
val enableResourceAccessControl: Boolean get() = state.enableResourceAccessControl
val enableIndexExpr: Boolean get() = state.enableIndexExpr
val enablePublicPackage: Boolean get() = state.enablePublicPackage
Expand All @@ -49,6 +50,9 @@ class MvProjectSettingsService(
@AffectsMoveProjectsMetadata
var localAptosPath: String? by string()

@AffectsHighlighting
var enableReceiverStyleFunctions: Boolean by property(false)

@AffectsParseTree
var enableResourceAccessControl: Boolean by property(false)

Expand Down
178 changes: 93 additions & 85 deletions src/main/kotlin/org/move/cli/settings/PerProjectAptosConfigurable.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,131 +17,139 @@ class PerProjectAptosConfigurable(val project: Project): BoundConfigurable("Apto

override fun createPanel(): DialogPanel {
val chooseAptosCliPanel = ChooseAptosCliPanel(versionUpdateListener = null)
val configurablePanel =
panel {
val settings = project.moveSettings
val state = settings.state.copy()
this.disposable?.let {
Disposer.register(it, chooseAptosCliPanel)
}
return panel {
val settings = project.moveSettings
val state = settings.state.copy()

chooseAptosCliPanel.attachToLayout(this)
chooseAptosCliPanel.attachToLayout(this)

group {
group {
row {
checkBox("Fetch external packages on project reload")
.bindSelected(state::fetchAptosDeps)
link("Configure project reload schedule") {
ProjectManager.getInstance().defaultProject.showSettingsDialog<ExternalSystemGroupConfigurable>()
}
.align(AlignX.RIGHT)
}
group("Compiler V2") {
row {
checkBox("Fetch external packages on project reload")
.bindSelected(state::fetchAptosDeps)
link("Configure project reload schedule") {
ProjectManager.getInstance().defaultProject.showSettingsDialog<ExternalSystemGroupConfigurable>()
}
.align(AlignX.RIGHT)
checkBox("Set Compiler V2 flags for CLI")
.comment(
"Adds `--compiler-version v2 --language-version 2.0` " +
"to all generated Aptos CLI commands"
)
.bindSelected(state::addCompilerV2CLIFlags)
}
group("Compiler V2") {
group("Language features") {
row {
checkBox("Set Compiler V2 for CLI")
checkBox("Receiver-Style functions")
.comment(
"Adds `--compiler-version v2 --language-version 2.0` " +
"to all generated Aptos CLI commands"
"Allows calling functions with special " +
"first <b><code>self</code></b> parameter as a methods through dot expression."
)
.bindSelected(state::addCompilerV2CLIFlags)
.bindSelected(state::enableReceiverStyleFunctions)
}
row {
checkBox("Enable resource-access control")
checkBox("Resource-Access control")
.comment(
"Enables resource access control specifies " +
"(<code>reads, writes, pure</code> for functions) in the parser. " +
"Allows specifying resource access attributes " +
"(<code>reads, writes, pure</code> for functions). " +
"Requires re-parsing of all Move files in the project, can be slow."
)
.bindSelected(state::enableResourceAccessControl)
}
row {
checkBox("Enable indexing")
checkBox("Index notation")
.comment(
"Enables resource and vector indexing " +
"(i.e. <code>v[0]</code>, <code>R[@0x1]</code>) for the Move files."
"Allows resource (<code>R[@0x1]</code>) and vector (<code>v[0]</code>) index operators."
)
.bindSelected(state::enableIndexExpr)
}
row {
checkBox("Enable public(package) visibility modifier")
checkBox("public(package) visibility modifier")
.comment(
"Enables using <code>public(package)</code> visibility modifier " +
"Allows <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 {
checkBox("Disable telemetry for new Run Configurations")
.comment(
"Adds APTOS_DISABLE_TELEMETRY=true to every generated Aptos command."
)
.bindSelected(state::disableTelemetry)
}
row {
checkBox("Skip updating to the latest git dependencies")
.comment(
"Adds --skip-fetch-latest-git-deps to the sync and test runs."
)
.bindSelected(state::skipFetchLatestGitDeps)

}
row {
checkBox("Dump storage to console on test failures")
.comment(
"Adds --dump to generated test runs."
)
.bindSelected(state::dumpStateOnTestFailure)
}
}
}
group("Command Line Options") {
row {
checkBox("Disable telemetry for new Run Configurations")
.comment(
"Adds APTOS_DISABLE_TELEMETRY=true to every generated Aptos command."
)
.bindSelected(state::disableTelemetry)
}
row {
checkBox("Skip updating to the latest git dependencies")
.comment(
"Adds --skip-fetch-latest-git-deps to the sync and test runs."
)
.bindSelected(state::skipFetchLatestGitDeps)

if (!project.isDefault) {
}
row {
link("Set default project settings") {
ProjectManager.getInstance().defaultProject.showSettingsDialog<PerProjectAptosConfigurable>()
}
.align(AlignX.RIGHT)
checkBox("Dump storage to console on test failures")
.comment(
"Adds --dump to generated test runs."
)
.bindSelected(state::dumpStateOnTestFailure)
}
}
}

// saves values from Swing form back to configurable (OK / Apply)
onApply {
settings.modify {
it.aptosExecType = chooseAptosCliPanel.data.aptosExecType
if (!project.isDefault) {
row {
link("Set default project settings") {
ProjectManager.getInstance().defaultProject.showSettingsDialog<PerProjectAptosConfigurable>()
}
.align(AlignX.RIGHT)
}
}

val localAptosSdkPath = chooseAptosCliPanel.data.localAptosPath
if (localAptosSdkPath != null) {
chooseAptosCliPanel.updateAptosSdks(localAptosSdkPath)
}
it.localAptosPath = localAptosSdkPath
// saves values from Swing form back to configurable (OK / Apply)
onApply {
settings.modify {
it.aptosExecType = chooseAptosCliPanel.data.aptosExecType

it.disableTelemetry = state.disableTelemetry
it.skipFetchLatestGitDeps = state.skipFetchLatestGitDeps
it.dumpStateOnTestFailure = state.dumpStateOnTestFailure
it.enableResourceAccessControl = state.enableResourceAccessControl
it.enableIndexExpr = state.enableIndexExpr
it.enablePublicPackage = state.enablePublicPackage
it.addCompilerV2CLIFlags = state.addCompilerV2CLIFlags
it.fetchAptosDeps = state.fetchAptosDeps
val localAptosSdkPath = chooseAptosCliPanel.data.localAptosPath
if (localAptosSdkPath != null) {
chooseAptosCliPanel.updateAptosSdks(localAptosSdkPath)
}
}
it.localAptosPath = localAptosSdkPath

// loads settings from configurable to swing form
onReset {
chooseAptosCliPanel.data =
ChooseAptosCliPanel.Data(state.aptosExecType, state.localAptosPath)
it.disableTelemetry = state.disableTelemetry
it.skipFetchLatestGitDeps = state.skipFetchLatestGitDeps
it.dumpStateOnTestFailure = state.dumpStateOnTestFailure
it.enableReceiverStyleFunctions = state.enableReceiverStyleFunctions
it.enableResourceAccessControl = state.enableResourceAccessControl
it.enableIndexExpr = state.enableIndexExpr
it.enablePublicPackage = state.enablePublicPackage
it.addCompilerV2CLIFlags = state.addCompilerV2CLIFlags
it.fetchAptosDeps = state.fetchAptosDeps
}
}

/// checks whether any settings are modified (should be fast)
onIsModified {
val aptosPanelData = chooseAptosCliPanel.data
aptosPanelData.aptosExecType != settings.aptosExecType
|| aptosPanelData.localAptosPath != settings.localAptosPath
}
// loads settings from configurable to swing form
onReset {
chooseAptosCliPanel.data =
ChooseAptosCliPanel.Data(state.aptosExecType, state.localAptosPath)
}

/// checks whether any settings are modified (should be fast)
onIsModified {
val aptosPanelData = chooseAptosCliPanel.data
aptosPanelData.aptosExecType != settings.aptosExecType
|| aptosPanelData.localAptosPath != settings.localAptosPath
}
this.disposable?.let {
Disposer.register(it, chooseAptosCliPanel)
}
return configurablePanel
}

// override fun disposeUIResources() {
Expand Down
15 changes: 12 additions & 3 deletions src/main/kotlin/org/move/ide/annotator/HighlightingAnnotator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package org.move.ide.annotator
import com.intellij.lang.annotation.AnnotationHolder
import com.intellij.psi.PsiElement
import com.intellij.psi.impl.source.tree.LeafPsiElement
import org.move.cli.settings.moveSettings
import org.move.ide.colors.MvColor
import org.move.lang.MvElementTypes.HEX_INTEGER_LITERAL
import org.move.lang.MvElementTypes.IDENTIFIER
Expand Down Expand Up @@ -61,7 +62,7 @@ class HighlightingAnnotator: MvAnnotatorBase() {
if (element is MvAbility) return MvColor.ABILITY
if (element is MvTypeParameter) return MvColor.TYPE_PARAMETER
if (element is MvItemSpecTypeParameter) return MvColor.TYPE_PARAMETER
if (element is MvModuleRef && element.isSelf) return MvColor.KEYWORD
if (element is MvModuleRef && element.isSelfModuleRef) return MvColor.KEYWORD
if (element is MvUseItem && element.text == "Self") return MvColor.KEYWORD
if (element is MvFunction)
return when {
Expand Down Expand Up @@ -90,7 +91,9 @@ class HighlightingAnnotator: MvAnnotatorBase() {

private fun highlightBindingPat(bindingPat: MvBindingPat): MvColor {
val bindingOwner = bindingPat.parent
if (bindingOwner is MvFunctionParameter && bindingOwner.isSelf) {
if (bindingPat.isReceiverStyleFunctionsEnabled &&
bindingOwner is MvFunctionParameter && bindingOwner.isSelfParam
) {
return MvColor.SELF_PARAMETER
}
val msl = bindingPat.isMslOnlyItem
Expand Down Expand Up @@ -147,7 +150,9 @@ class HighlightingAnnotator: MvAnnotatorBase() {
item is MvConst -> MvColor.CONSTANT
else -> {
val itemParent = item.parent
if (itemParent is MvFunctionParameter && itemParent.isSelf) {
if (itemParent.isReceiverStyleFunctionsEnabled
&& itemParent is MvFunctionParameter && itemParent.isSelfParam
) {
MvColor.SELF_PARAMETER
} else {
val msl = path.isMslScope
Expand Down Expand Up @@ -185,4 +190,8 @@ class HighlightingAnnotator: MvAnnotatorBase() {
itemTy is TyStruct && itemTy.item.hasKey -> MvColor.KEY_OBJECT
else -> MvColor.VARIABLE
}

private val PsiElement.isReceiverStyleFunctionsEnabled
get() =
project.moveSettings.enableReceiverStyleFunctions
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ 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 visitMethodCall(o: MvMethodCall) = checkMethodCall(moveHolder, o)

override fun visitModule(o: MvModule) {
checkVisibilityModifiers(moveHolder, o)
Expand Down Expand Up @@ -107,6 +108,13 @@ class MvSyntaxErrorAnnotator: MvAnnotatorBase() {
}
}

private fun checkMethodCall(holder: MvAnnotationHolder, methodCall: MvMethodCall) {
if (!methodCall.project.moveSettings.enableReceiverStyleFunctions) {
Diagnostic.ReceiverStyleFunctionsIsNotSupportedInCompilerV1(methodCall)
.addToHolder(holder)
}
}

private fun checkLitExpr(holder: MvAnnotationHolder, litExpr: MvLitExpr) {
val lit = litExpr.literal
when (lit) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import org.move.ide.inspections.fixes.CompilerV2Feat.*

enum class CompilerV2Feat(val title: String) {
INDEXING("Index notation"),
RECEIVER_STYLE_FUNCTIONS("Receiver-Style functions"),
RESOURCE_CONTROL("Resource access control"),
PUBLIC_PACKAGE("`public(package)` function visibility");
}
Expand All @@ -31,6 +32,7 @@ class EnableCompilerV2FeatureFix(
project.moveSettings.modify {
when (feature) {
INDEXING -> it.enableIndexExpr = true
RECEIVER_STYLE_FUNCTIONS -> it.enableReceiverStyleFunctions = true
RESOURCE_CONTROL -> it.enableResourceAccessControl = true
PUBLIC_PACKAGE -> it.enablePublicPackage = true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import org.move.lang.core.completion.createSelfLookup
import org.move.lang.core.psi.MvModule
import org.move.lang.core.psi.MvUseItem
import org.move.lang.core.psi.MvUseItemGroup
import org.move.lang.core.psi.ext.isSelf
import org.move.lang.core.psi.ext.isSelfModuleRef
import org.move.lang.core.psi.ext.itemUseSpeck
import org.move.lang.core.psi.ext.names
import org.move.lang.core.psi.refItemScopes
Expand Down Expand Up @@ -47,7 +47,7 @@ object ImportsCompletionProvider: MvCompletionProvider() {
}

val vs = when {
moduleRef.isSelf -> setOf(Visibility.Internal)
moduleRef.isSelfModuleRef -> setOf(Visibility.Internal)
else -> Visibility.visibilityScopesForElement(itemImport)
}
val ns = setOf(Namespace.NAME, Namespace.TYPE, Namespace.FUNCTION)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import org.move.lang.core.psi.*
import org.move.lang.core.psi.ext.ancestors
import org.move.lang.core.psi.ext.endOffset
import org.move.lang.core.psi.ext.isMslScope
import org.move.lang.core.psi.ext.isSelf
import org.move.lang.core.psi.ext.isSelfModuleRef
import org.move.lang.core.resolve.*
import org.move.lang.core.resolve.ref.MvReferenceElement
import org.move.lang.core.resolve.ref.Namespace
Expand Down Expand Up @@ -62,7 +62,7 @@ abstract class MvPathCompletionProvider: MvCompletionProvider() {
val module = moduleRef.reference?.resolveWithAliases() as? MvModule
?: return
val vs = when {
moduleRef.isSelf -> setOf(Visibility.Internal)
moduleRef.isSelfModuleRef -> setOf(Visibility.Internal)
else -> Visibility.visibilityScopesForElement(pathElement)
}
processModuleItems(module, namespaces, vs, pathScopeInfo) {
Expand Down
7 changes: 5 additions & 2 deletions src/main/kotlin/org/move/lang/core/psi/MvFunctionLike.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package org.move.lang.core.psi

import com.intellij.ide.projectView.PresentationData
import com.intellij.openapi.editor.colors.TextAttributesKey
import org.move.cli.settings.moveSettings
import org.move.ide.MoveIcons
import org.move.lang.MvElementTypes
import org.move.lang.core.completion.CompletionContext
Expand Down Expand Up @@ -119,8 +120,10 @@ val MvFunctionLike.signatureText: String
return "$paramsText$retTypeSuffix"
}

val MvFunction.selfParam: MvFunctionParameter? get() =
this.parameters.firstOrNull()?.takeIf { it.name == "self" }
val MvFunction.selfParam: MvFunctionParameter? get() {
if (!project.moveSettings.enableReceiverStyleFunctions) return null
return this.parameters.firstOrNull()?.takeIf { it.name == "self" }
}

fun MvFunction.selfParamTy(msl: Boolean): Ty? = this.selfParam?.type?.loweredType(msl)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ val MvFunctionParameter.name: String get() = this.bindingPat.name
val MvFunctionParameter.paramIndex: Int get() =
(this.parent as MvFunctionParameterList).functionParameterList.indexOf(this)

val MvFunctionParameter.isSelf: Boolean get() =
val MvFunctionParameter.isSelfParam: Boolean get() =
this.bindingPat.name == "self" && this.paramIndex == 0

var MvFunctionParameter.resolveContext: MvFunction?
Expand Down
Loading

0 comments on commit 7fe22f1

Please sign in to comment.