Skip to content

Commit

Permalink
refactor notifications (#235)
Browse files Browse the repository at this point in the history
  • Loading branch information
mkurnikov authored Nov 9, 2024
1 parent fa91cff commit 1b27c36
Show file tree
Hide file tree
Showing 13 changed files with 146 additions and 121 deletions.
10 changes: 5 additions & 5 deletions src/main/kotlin/org/move/bytecode/AptosDecompiler.kt
Original file line number Diff line number Diff line change
Expand Up @@ -80,18 +80,14 @@ class AptosBytecodeDecompiler: BinaryFileDecompiler {
}

fun getDecompilerTargetFileDirOnTemp(project: Project, file: VirtualFile): Path? {
val rootDecompilerDir = getArtifactsDir()
val rootDecompilerDir = decompiledArtifactsFolder()
val projectDecompilerDir = rootDecompilerDir.resolve(project.name)
val root = project.rootPath ?: return null
val relativeFilePath = file.parent.pathAsPath.relativeTo(root)
val targetFileDir = projectDecompilerDir.toPath().resolve(relativeFilePath)
return targetFileDir
}

fun getArtifactsDir(): File {
return File(FileUtil.getTempDirectory(), "intellij-move-decompiled-artifacts")
}

fun sourceFileName(file: VirtualFile): String {
val fileName = file.name
return "$fileName.move"
Expand All @@ -101,6 +97,10 @@ class AptosBytecodeDecompiler: BinaryFileDecompiler {
val fileName = file.name
return "$fileName#decompiled.move"
}

companion object {
fun decompiledArtifactsFolder() = File(FileUtil.getTempDirectory(), "intellij-move-decompiled-artifacts")
}
}

fun Project.createDisposableOnFileChange(file: VirtualFile): Disposable {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import org.move.cli.readString
import org.move.cli.runConfigurations.CommandConfigurationBase.CleanConfiguration.Companion.configurationError
import org.move.cli.runConfigurations.test.AptosTestConsoleProperties.Companion.TEST_TOOL_WINDOW_SETTING_KEY
import org.move.cli.runConfigurations.test.AptosTestRunState
import org.move.cli.settings.aptosExecPath
import org.move.cli.settings.aptosCliPath
import org.move.cli.writePath
import org.move.cli.writeString
import org.move.stdext.exists
Expand Down Expand Up @@ -68,7 +68,7 @@ abstract class CommandConfigurationBase(
val workingDirectory = workingDirectory
?: return configurationError("No working directory specified")

val aptosPath = project.aptosExecPath ?: return configurationError("No Aptos CLI specified")
val aptosPath = project.aptosCliPath ?: return configurationError("No Aptos CLI specified")
if (!aptosPath.exists()) {
return configurationError("Invalid Aptos CLI location: $aptosPath")
}
Expand Down
21 changes: 10 additions & 11 deletions src/main/kotlin/org/move/cli/settings/MvProjectSettingsService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -89,15 +89,16 @@ class MvProjectSettingsService(

val Project.moveSettings: MvProjectSettingsService get() = service()

fun Project.getAptosCli(parentDisposable: Disposable? = null): Aptos? {
val aptosExecPath =
AptosExecType.aptosExecPath(
this.moveSettings.aptosExecType,
this.moveSettings.localAptosPath
)
val aptos = aptosExecPath?.let { Aptos(it, parentDisposable) }
return aptos
}
val Project.aptosCliPath: Path?
get() {
val settings = this.moveSettings
return AptosExecType.aptosCliPath(settings.aptosExecType, settings.localAptosPath)
}

fun Project.getAptosCli(
parentDisposable: Disposable? = null
): Aptos? =
this.aptosCliPath?.let { Aptos(it, parentDisposable) }

val Project.isAptosConfigured: Boolean get() = this.getAptosCli() != null

Expand All @@ -106,8 +107,6 @@ fun Project.getAptosCliDisposedOnFileChange(file: VirtualFile): Aptos? {
return this.getAptosCli(anyChangeDisposable)
}

val Project.aptosExecPath: Path? get() = this.getAptosCli()?.cliLocation

fun Path?.isValidExecutable(): Boolean {
return this != null
&& this.toString().isNotBlank()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ enum class AptosExecType {

val bundledAptosCLIPath: Path? get() = BundledAptosManager.getBundledAptosPath()

fun aptosExecPath(execType: AptosExecType, localAptosPath: String?): Path? {
fun aptosCliPath(execType: AptosExecType, localAptosPath: String?): Path? {
val pathCandidate =
when (execType) {
BUNDLED -> bundledAptosCLIPath
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class MoveProjectGenerator: DirectoryProjectGeneratorBase<AptosProjectConfig>(),
) {
val packageName = project.name
val aptosPath =
AptosExecType.aptosExecPath(projectConfig.aptosExecType, projectConfig.localAptosPath)
AptosExecType.aptosCliPath(projectConfig.aptosExecType, projectConfig.localAptosPath)
?: error("validated before")
val aptos = Aptos(aptosPath, disposable)
val moveTomlFile =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class MoveProjectGeneratorPeer(val parentDisposable: Disposable): GeneratorPeerI
override fun validate(): ValidationInfo? {
val panelData = this.chooseAptosCliPanel.data
val aptosExecPath =
AptosExecType.aptosExecPath(panelData.aptosExecType, panelData.localAptosPath)
AptosExecType.aptosCliPath(panelData.aptosExecType, panelData.localAptosPath)
if (aptosExecPath == null) {
return ValidationInfo("Invalid path to Aptos executable")
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,38 +1,30 @@
package org.move.ide.notifications

import com.intellij.ide.impl.isTrusted
import com.intellij.openapi.project.DumbAware
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.ui.EditorNotificationPanel
import org.move.cli.settings.PerProjectAptosConfigurable
import org.move.cli.settings.aptos.AptosExecType.LOCAL
import org.move.cli.settings.aptosExecPath
import org.move.cli.settings.aptosCliPath
import org.move.cli.settings.isValidExecutable
import org.move.cli.settings.moveSettings
import org.move.lang.isMoveFile
import org.move.lang.isMoveTomlManifestFile
import org.move.openapiext.common.isUnitTestMode
import org.move.openapiext.showSettingsDialog
import org.move.stdext.getCliFromPATH

class InvalidBlockchainCliConfiguration(project: Project): MvEditorNotificationProvider(project),
DumbAware {
class InvalidAptosCliConfigurationNotification(project: Project): MvAptosEditorNotificationProvider(project),
DumbAware {

override val VirtualFile.disablingKey: String get() = NOTIFICATION_STATUS_KEY + path
override val notificationProviderId: String get() = NOTIFICATION_STATUS_KEY

override fun createNotificationPanel(file: VirtualFile, project: Project): EditorNotificationPanel? {
if (isUnitTestMode) return null
if (!(file.isMoveFile || file.isMoveTomlManifestFile)) return null
@Suppress("UnstableApiUsage")
if (!project.isTrusted()) return null
if (isNotificationDisabled(file)) return null
override fun createAptosNotificationPanel(file: VirtualFile, project: Project): EditorNotificationPanel? {

if (project.aptosExecPath.isValidExecutable()) return null
if (project.aptosCliPath.isValidExecutable()) return null

val aptosCliFromPATH = getCliFromPATH("aptos")?.toString()
return EditorNotificationPanel().apply {
text = "Aptos CLI path is not provided or invalid"

val aptosCliFromPATH = getCliFromPATH("aptos")?.toString()
if (aptosCliFromPATH != null) {
createActionLabel("Set to \"$aptosCliFromPATH\"") {
project.moveSettings.modify {
Expand All @@ -41,6 +33,7 @@ class InvalidBlockchainCliConfiguration(project: Project): MvEditorNotificationP
}
}
}

createActionLabel("Configure") {
project.showSettingsDialog<PerProjectAptosConfigurable>()
}
Expand All @@ -51,6 +44,10 @@ class InvalidBlockchainCliConfiguration(project: Project): MvEditorNotificationP
}
}

override val enableForScratchFiles: Boolean get() = true

override val enableForDecompiledFiles: Boolean get() = true

companion object {
private const val NOTIFICATION_STATUS_KEY = "org.move.hideMoveNotifications"
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package org.move.ide.notifications

import com.intellij.ide.impl.isTrusted
import com.intellij.ide.scratch.ScratchUtil
import com.intellij.ide.util.PropertiesComponent
import com.intellij.openapi.fileEditor.FileEditor
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.ui.EditorNotificationPanel
import com.intellij.ui.EditorNotificationProvider
import com.intellij.ui.EditorNotifications
import org.move.bytecode.AptosBytecodeDecompiler
import org.move.cli.settings.MvProjectSettingsServiceBase.*
import org.move.lang.isMoveFile
import org.move.lang.isMoveTomlManifestFile
import org.move.lang.toNioPathOrNull
import org.move.openapiext.common.isUnitTestMode
import java.util.function.Function
import javax.swing.JComponent
import kotlin.io.relativeToOrNull

fun updateAllNotifications(project: Project) {
EditorNotifications.getInstance(project).updateAllNotifications()
}

class UpdateNotificationsOnSettingsChangeListener(val project: Project): MoveSettingsListener {

override fun <T: MvProjectSettingsBase<T>> settingsChanged(e: SettingsChangedEventBase<T>) {
updateAllNotifications(project)
}
}

abstract class MvNotificationProvider(protected val project: Project): EditorNotificationProvider {

protected abstract val VirtualFile.disablingKey: String

override fun collectNotificationData(
project: Project,
file: VirtualFile
): Function<in FileEditor, out JComponent?> {
return Function {
createNotificationPanel(file, project)
}
}

abstract fun createNotificationPanel(file: VirtualFile, project: Project): EditorNotificationPanel?

protected fun disableNotification(file: VirtualFile) {
PropertiesComponent.getInstance(project).setValue(file.disablingKey, true)
}

protected fun isNotificationDisabled(file: VirtualFile): Boolean =
PropertiesComponent.getInstance(project).getBoolean(file.disablingKey)

protected fun updateAllNotifications() {
EditorNotifications.getInstance(project).updateAllNotifications()
}
}

abstract class MvAptosEditorNotificationProvider(project: Project): MvNotificationProvider(project) {

abstract val notificationProviderId: String

abstract fun createAptosNotificationPanel(file: VirtualFile, project: Project): EditorNotificationPanel?

open val enableForScratchFiles: Boolean = false
open val enableForDecompiledFiles: Boolean = false

override val VirtualFile.disablingKey: String get() = notificationProviderId + path

override fun createNotificationPanel(file: VirtualFile, project: Project): EditorNotificationPanel? {
// disable in unit tests
if (isUnitTestMode) return null

if (!enableForScratchFiles && ScratchUtil.isScratch(file)) return null
@Suppress("UnstableApiUsage")
if (!project.isTrusted()) return null

// only run for .move or Move.toml files
if (!file.isMoveFile && !file.isMoveTomlManifestFile) return null

val nioFile = file.toNioPathOrNull()?.toFile()
// skip non-physical file
if (nioFile == null) return null

if (!enableForDecompiledFiles) {
// check whether file is a decompiler artifact
val decompiledArtifactsFolder = AptosBytecodeDecompiler.decompiledArtifactsFolder()
// belongs to the decompiled artifacts directory
if (nioFile.relativeToOrNull(decompiledArtifactsFolder) != null) return null
}

// explicitly disabled in file
if (isNotificationDisabled(file)) return null

return createAptosNotificationPanel(file, project)
}

}
Loading

0 comments on commit 1b27c36

Please sign in to comment.