diff --git a/README.md b/README.md
index ec0acbb..0560bb2 100644
--- a/README.md
+++ b/README.md
@@ -30,11 +30,11 @@ But if statement **already exists** in `*.sbt` files, `sdap.sbt` will not be cre
Just click on the icon and wait for the analysis:
-![](./docs/gotoAnalyze1.jpg)
+
When the analysis is complete:
-![](./docs/dependencyTreeConflicts.jpg)
+
## For more details
@@ -44,6 +44,28 @@ When the analysis is complete:
4. `reload` reload project on-demand.
5. `update` update dependencies on-demand.
+## Advanced Setup
+
+> If you are not sure, you do not need to use these configurations!
+
+Using configurations, analysis wait times can be dramatically reduced:
+
+
+
+**File Cache Timeout**
+
+If the file hasn't been changed for more than `3600` seconds, plugin will execute the `dependencyDot` task, otherwise use the one that already exists, unless using `Refresh`.
+
+**Organization**
+
+If you set this value, the `organization` task will not be used to get your project's organization.
+
+**Disable Scope**
+
+If you don't need to analyze all scopes, just disable it.
+
+Configurations are persistent and associated with each intellij project.
+
## Troubleshooting issues
### "Caused by: java.io.IOException: Could not create lock for ..."
@@ -54,8 +76,7 @@ Caused by: java.io.IOException: Could not create lock for \\.\pipe\sbt-load59647
```
Using sbt shell to reload or build the project avoids this issue:
-![](docs/sbtShellUseForReload.jpg)
-
+
### Can't analyze dependencies between modules?
diff --git a/build.sbt b/build.sbt
index c0ec2e4..d8580d1 100644
--- a/build.sbt
+++ b/build.sbt
@@ -47,9 +47,10 @@ lazy val `sbt-dependency-analyzer` = (project in file("."))
// Some("xxx") // or None if password is not set(or via PLUGIN_SIGN_KEY_PWD env var)
),
pluginVerifierOptions := pluginVerifierOptions.value.copy(
- version = "1.301", // use a specific verifier version
- offline = true, // forbid the verifier from reaching the internet
- failureLevels = Set(FailureLevel.DEPRECATED_API_USAGES) // only fail if deprecated APIs are used
+ version = "1.301", // use a specific verifier version
+ offline = true, // forbid the verifier from reaching the internet
+ failureLevels =
+ Set(FailureLevel.INTERNAL_API_USAGES, FailureLevel.COMPATIBILITY_PROBLEMS, FailureLevel.COMPATIBILITY_WARNINGS)
),
Global / intellijAttachSources := true,
intellijPlugins ++= Seq("com.intellij.java", "com.intellij.java-i18n", "org.intellij.scala").map(_.toPlugin),
diff --git a/docs/settings.png b/docs/settings.png
new file mode 100644
index 0000000..8e56619
Binary files /dev/null and b/docs/settings.png differ
diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml
index 71a04c8..8477555 100644
--- a/src/main/resources/META-INF/plugin.xml
+++ b/src/main/resources/META-INF/plugin.xml
@@ -16,8 +16,8 @@
-
-
+
+
@@ -26,7 +26,10 @@
description="Force translation for notification"/>
-
+
+
@@ -116,6 +119,12 @@
0.2.0-RC3-231.9392.1
+
+ - 🎉Add Intellij Settings.
+
+
+
0.2.0-RC2-231.9392.1
- Update description and action name.
diff --git a/src/main/resources/messages/SbtDependencyAnalyzerBundle.properties b/src/main/resources/messages/SbtDependencyAnalyzerBundle.properties
index 6147b08..e7a0475 100644
--- a/src/main/resources/messages/SbtDependencyAnalyzerBundle.properties
+++ b/src/main/resources/messages/SbtDependencyAnalyzerBundle.properties
@@ -7,6 +7,7 @@ analyzer.action.gotoAction.text=Goto Dependency
analyzer.notification.gotoSdap=Goto "{0}"
analyzer.notification.addSdap.title=Sbt Dependency Analyzer is ready
analyzer.notification.addSdap.text=The "{0}" has been added or updated, please wait a moment, go to see more.
+analyzer.notification.setting.changed.title=Sbt Dependency Analyzer settings have been changed
analyzer.notification.updated.title={0} plugin updated to v{1}
analyzer.notification.updated.text=Thank you for downloading \
Sbt Dependency Analyzer! \
@@ -17,6 +18,7 @@ analyzer.refresh.dependencies.text=Refresh Dependencies
analyzer.refresh.dependencies.description=Refresh dependencies using reimport
analyzer.refresh.snapshot.dependencies.text=Refresh Snapshot Dependencies
analyzer.refresh.snapshot.dependencies.description=Set the "COURSIER_TTL=0s" to refresh snapshot dependencies
+analyzer.settings.page.name=Sbt Dependency Analyzer
diff --git a/src/main/resources/messages/SbtDependencyAnalyzerBundle_zh.properties b/src/main/resources/messages/SbtDependencyAnalyzerBundle_zh.properties
index 0515fa5..b9d36d4 100644
--- a/src/main/resources/messages/SbtDependencyAnalyzerBundle_zh.properties
+++ b/src/main/resources/messages/SbtDependencyAnalyzerBundle_zh.properties
@@ -7,6 +7,7 @@ analyzer.action.gotoAction.text=查看依赖
analyzer.notification.gotoSdap=打开 “{0}”
analyzer.notification.addSdap.title=Sbt Dependency Analyzer 已就绪
analyzer.notification.addSdap.text=已添加或更新文件 “{0}”,请稍等片刻,前往查看更多
+analyzer.notification.setting.changed.title=Sbt Dependency Analyzer 配置已被更改
analyzer.notification.updated.title={0} 插件已更新为 v{1}
analyzer.notification.updated.text=感谢下载 \
Sbt Dependency Analyzer! \
@@ -16,4 +17,5 @@ analyzer.notification.updated.gotoBrowser=去看看
analyzer.refresh.dependencies.text=刷新依赖
analyzer.refresh.dependencies.description=重新导入以刷新依赖
analyzer.refresh.snapshot.dependencies.text=刷新快照依赖
-analyzer.refresh.snapshot.dependencies.description=设置 “COURSIER_TTL=0s” 以刷新快照依赖
\ No newline at end of file
+analyzer.refresh.snapshot.dependencies.description=设置 “COURSIER_TTL=0s” 以刷新快照依赖
+analyzer.settings.page.name=Sbt 依赖分析
diff --git a/src/main/scala/bitlap/sbt/analyzer/Constants.scala b/src/main/scala/bitlap/sbt/analyzer/Constants.scala
index 65dfd09..5eab664 100644
--- a/src/main/scala/bitlap/sbt/analyzer/Constants.scala
+++ b/src/main/scala/bitlap/sbt/analyzer/Constants.scala
@@ -24,8 +24,6 @@ object Constants:
final val IntervalTimeout = 1010.milliseconds
- final val FileLifespan = 1000 * 60 * 60L
-
final val ChangeNotesSeparator = ""
end Constants
diff --git a/src/main/scala/bitlap/sbt/analyzer/SbtDependencyAnalyzerConfigurable.scala b/src/main/scala/bitlap/sbt/analyzer/SbtDependencyAnalyzerConfigurable.scala
new file mode 100644
index 0000000..7c401a9
--- /dev/null
+++ b/src/main/scala/bitlap/sbt/analyzer/SbtDependencyAnalyzerConfigurable.scala
@@ -0,0 +1,34 @@
+package bitlap.sbt.analyzer
+
+import javax.swing.JComponent
+
+import com.intellij.openapi.options.*
+import com.intellij.openapi.options.Configurable.Composite
+import com.intellij.openapi.project.Project
+
+/** @author
+ * 梦境迷离
+ * @version 1.0,2023/9/7
+ */
+final class SbtDependencyAnalyzerConfigurable(project: Project) extends SearchableConfigurable {
+
+ // create a ui form
+ private val panel: SbtDependencyAnalyzerPanel = new SbtDependencyAnalyzerPanel(project)
+
+ override def getId(): String = SbtDependencyAnalyzerPlugin.PLUGIN_ID
+
+ override def getDisplayName(): String = SbtDependencyAnalyzerBundle.message("analyzer.settings.page.name")
+
+ override def getHelpTopic(): String = "default"
+
+ override def createComponent(): JComponent = panel.$$$getRootComponent$$$()
+
+ override def isModified(): Boolean = panel.isModified
+
+ override def apply(): Unit = panel.apply()
+
+ override def reset(): Unit = panel.from()
+
+ override def disposeUIResources(): Unit = {}
+
+}
diff --git a/src/main/scala/bitlap/sbt/analyzer/SbtDependencyAnalyzerContributor.scala b/src/main/scala/bitlap/sbt/analyzer/SbtDependencyAnalyzerContributor.scala
index b7e14b6..c76ba44 100644
--- a/src/main/scala/bitlap/sbt/analyzer/SbtDependencyAnalyzerContributor.scala
+++ b/src/main/scala/bitlap/sbt/analyzer/SbtDependencyAnalyzerContributor.scala
@@ -24,6 +24,7 @@ import org.jetbrains.sbt.project.data.ModuleNode
import com.intellij.buildsystem.model.unified.UnifiedCoordinates
import com.intellij.openapi.Disposable
+import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.externalSystem.dependency.analyzer.{ DependencyAnalyzerDependency as Dependency, * }
import com.intellij.openapi.externalSystem.dependency.analyzer.DependencyAnalyzerDependency.Data
import com.intellij.openapi.externalSystem.model.ProjectKeys
@@ -138,7 +139,7 @@ final class SbtDependencyAnalyzerContributor(project: Project) extends Dependenc
)
}
- private def deleteExistAnalysisFiles(modulePath: String)(using ParserTypeEnum): Unit = {
+ private def deleteExistAnalysisFiles(modulePath: String): Unit = {
DependencyScopeEnum.values
.map(scope => Path.of(modulePath + analysisFilePath(scope, summon[ParserTypeEnum])))
.foreach(p => Files.deleteIfExists(p))
@@ -206,7 +207,12 @@ final class SbtDependencyAnalyzerContributor(project: Project) extends Dependenc
private def getOrganization(project: Project): String =
// When force refresh, we will not re-read the settings, such organization,moduleName, because refreshing makes efficiency lower.
- // Usually, Uses do not change frequently, so it's better to keep caching until the view is reopene.
+ // Usually, Uses do not change frequently, so it's better to keep caching until the view is reopen.
+ val org = SettingsState.getSettings(project).organization
+ if (org != null && org != Constants.EmptyString) {
+ return org
+ }
+
if (organization != null) return organization
organization = SbtShellOutputAnalysisTask.organizationTask.executeCommand(project)
organization
@@ -242,16 +248,25 @@ final class SbtDependencyAnalyzerContributor(project: Project) extends Dependenc
}
}
-object SbtDependencyAnalyzerContributor:
+object SbtDependencyAnalyzerContributor extends SettingsState.SettingsChangeListener:
final val isAvailable = new AtomicBoolean(true)
+ // if data change
+ override def onAnalyzerConfigurationChanged(project: Project, settingsState: SettingsState): Unit = {
+ // TODO
+ isAvailable.set(false)
+ SbtUtils.refreshProject(project)
+ }
+
+ ApplicationManager.getApplication.getMessageBus.connect().subscribe(SettingsState._Topic, this)
+
private final val isNotifying = new AtomicBoolean(false)
- private def isValidFile(file: String): Boolean = {
+ private def isValidFile(project: Project, file: String): Boolean = {
if (isAvailable.get()) {
val lastModified = Path.of(file).toFile.lastModified()
- System.currentTimeMillis() <= lastModified + Constants.FileLifespan
+ System.currentTimeMillis() <= lastModified + SettingsState.getSettings(project).fileCacheTimeout * 1000
} else {
isAvailable.getAndSet(true)
}
@@ -326,8 +341,10 @@ object SbtDependencyAnalyzerContributor:
ideaModuleNamePaths: Map[String, String],
ideaModuleIdSbtModules: Map[String, String],
declared: List[UnifiedCoordinates]
- )(using ParserTypeEnum): JList[DependencyScopeNode] =
- val module = findModule(project, moduleData)
+ ): JList[DependencyScopeNode] =
+ val module = findModule(project, moduleData)
+ val moduleId = moduleData.getId.split(" ")(0)
+
if (DependencyUtils.canIgnoreModule(module)) return Collections.emptyList()
if (isNotifying.get() && SbtUtils.untilProjectReady(project)) {
@@ -340,9 +357,8 @@ object SbtDependencyAnalyzerContributor:
def executeCommandOrReadExistsFile(
scope: DependencyScopeEnum
): DependencyScopeNode =
- val moduleId = moduleData.getId.split(" ")(0)
val file = moduleData.getLinkedExternalProjectPath + analysisFilePath(scope, summon[ParserTypeEnum])
- val useCache = !isNotifying.get() && Files.exists(Path.of(file)) && isValidFile(file)
+ val useCache = !isNotifying.get() && Files.exists(Path.of(file)) && isValidFile(project, file)
// File cache for one hour
if (useCache) {
DependencyParserFactory
@@ -378,12 +394,20 @@ object SbtDependencyAnalyzerContributor:
val result = ListBuffer[DependencyScopeNode]()
import scala.util.control.Breaks.*
// break, no more commands will be executed
- breakable(
+ breakable {
+ val settings = SettingsState.getSettings(project)
for (scope <- DependencyScopeEnum.values) {
var node: DependencyScopeNode = null
try {
- node = executeCommandOrReadExistsFile(scope)
- result.append(node)
+
+ if (settings.disableAnalyzeProvided && scope == DependencyScopeEnum.Provided) {} else if (
+ settings.disableAnalyzeTest && scope == DependencyScopeEnum.Test
+ ) {} else if (settings.disableAnalyzeCompile && scope == DependencyScopeEnum.Compile) {} else {
+ node = executeCommandOrReadExistsFile(scope)
+ }
+ if (node != null) {
+ result.append(node)
+ }
} catch {
case _: AnalyzerCommandNotFoundException =>
if (isNotifying.compareAndSet(false, true)) {
@@ -397,7 +421,7 @@ object SbtDependencyAnalyzerContributor:
throw e
}
}
- )
+ }
result.toList.asJava
end loadDependencies
diff --git a/src/main/scala/bitlap/sbt/analyzer/SbtDependencyAnalyzerPanel.form b/src/main/scala/bitlap/sbt/analyzer/SbtDependencyAnalyzerPanel.form
new file mode 100644
index 0000000..0638bfa
--- /dev/null
+++ b/src/main/scala/bitlap/sbt/analyzer/SbtDependencyAnalyzerPanel.form
@@ -0,0 +1,103 @@
+
+
diff --git a/src/main/scala/bitlap/sbt/analyzer/SbtDependencyAnalyzerPanel.java b/src/main/scala/bitlap/sbt/analyzer/SbtDependencyAnalyzerPanel.java
new file mode 100644
index 0000000..21bf850
--- /dev/null
+++ b/src/main/scala/bitlap/sbt/analyzer/SbtDependencyAnalyzerPanel.java
@@ -0,0 +1,142 @@
+package bitlap.sbt.analyzer;
+
+import bitlap.sbt.analyzer.util.Notifications$;
+import com.intellij.openapi.project.Project;
+import com.intellij.uiDesigner.core.GridConstraints;
+import com.intellij.uiDesigner.core.GridLayoutManager;
+import com.intellij.uiDesigner.core.Spacer;
+
+import javax.swing.*;
+import java.awt.*;
+
+/**
+ * @author 梦境迷离
+ * @version 1.0, 2023/9/8
+ */
+@SuppressWarnings("unchecked")
+public class SbtDependencyAnalyzerPanel {
+ public JPanel mainPanel;
+
+ public JTextField organization;
+ public JCheckBox compileCheckBox;
+ public JCheckBox providedCheckBox;
+ public JCheckBox testCheckBox;
+ public JTextField fileCache;
+ private final SettingsState settings;
+ private final Project project;
+
+ public SbtDependencyAnalyzerPanel(Project project) {
+ this.project = project;
+ this.settings = SettingsState.getSettings(project);
+ }
+
+ boolean isModified() {
+ boolean disableAnalyzeCompile = settings.getDisableAnalyzeCompile() == compileCheckBox.isSelected();
+ boolean disableAnalyzeTest = settings.getDisableAnalyzeTest() == testCheckBox.isSelected();
+ boolean disableAnalyzeProvided = settings.getDisableAnalyzeProvided() == providedCheckBox.isSelected();
+ boolean fileCacheTimeout = String.valueOf(settings.fileCacheTimeout()).equals(fileCache.getText());
+ boolean org = settings.getOrganization() == null && organization.getText() == null ||
+ (organization.getText() != null && organization.getText().equals(settings.getOrganization()));
+
+ return !(org && fileCacheTimeout && disableAnalyzeCompile && disableAnalyzeTest && disableAnalyzeProvided);
+
+ }
+
+ void apply() {
+ // if data change, we publish a notification
+ boolean changed = false;
+ if (isModified()) {
+ changed = true;
+ }
+
+ settings.setOrganization(organization.getText());
+ settings.setDisableAnalyzeCompile(compileCheckBox.isSelected());
+ settings.setDisableAnalyzeTest(testCheckBox.isSelected());
+ settings.setDisableAnalyzeProvided(providedCheckBox.isSelected());
+ try {
+ int t = Integer.parseInt(fileCache.getText());
+ settings.setFileCacheTimeout(t);
+ } catch (Exception ignore) {
+ settings.setFileCacheTimeout(3600);
+ }
+ if (changed) {
+ Notifications$.MODULE$.notifySettingsChanged(project);
+ SettingsState.SettingsChangePublisher().onAnalyzerConfigurationChanged(this.project, settings);
+ }
+ }
+
+ void from() {
+ compileCheckBox.setSelected(settings.disableAnalyzeCompile());
+ providedCheckBox.setSelected(settings.disableAnalyzeProvided());
+ testCheckBox.setSelected(settings.disableAnalyzeTest());
+ organization.setText(settings.getOrganization());
+ fileCache.setText(String.valueOf(settings.fileCacheTimeout()));
+ }
+
+
+ {
+// GUI initializer generated by IntelliJ IDEA GUI Designer
+// >>> IMPORTANT!! <<<
+// DO NOT EDIT OR ADD ANY CODE HERE!
+ $$$setupUI$$$();
+ }
+
+ /**
+ * Method generated by IntelliJ IDEA GUI Designer
+ * >>> IMPORTANT!! <<<
+ * DO NOT edit this method OR call it in your code!
+ *
+ * @noinspection ALL
+ */
+ private void $$$setupUI$$$() {
+ mainPanel = new JPanel();
+ mainPanel.setLayout(new GridLayoutManager(4, 4, new Insets(0, 0, 0, 0), 0, 0, true, false));
+ mainPanel.setAlignmentX(0.0f);
+ mainPanel.setAlignmentY(0.0f);
+ mainPanel.setAutoscrolls(false);
+ mainPanel.setMaximumSize(new Dimension(-1, -1));
+ mainPanel.setMinimumSize(new Dimension(-1, -1));
+ mainPanel.setPreferredSize(new Dimension(600, 120));
+ final JLabel label1 = new JLabel();
+ label1.setText("Disable Scope:");
+ mainPanel.add(label1, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
+ final JLabel label2 = new JLabel();
+ label2.setText("Organization:");
+ mainPanel.add(label2, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
+ testCheckBox = new JCheckBox();
+ testCheckBox.setText("Test");
+ mainPanel.add(testCheckBox, new GridConstraints(2, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
+ compileCheckBox = new JCheckBox();
+ compileCheckBox.setText("Compile");
+ mainPanel.add(compileCheckBox, new GridConstraints(2, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
+ providedCheckBox = new JCheckBox();
+ providedCheckBox.setText("Provided");
+ mainPanel.add(providedCheckBox, new GridConstraints(2, 3, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
+ final JLabel label3 = new JLabel();
+ label3.setText("File Cache Timeout:");
+ mainPanel.add(label3, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
+ fileCache = new JTextField();
+ fileCache.setColumns(4);
+ fileCache.setHorizontalAlignment(2);
+ fileCache.setText("3600");
+ mainPanel.add(fileCache, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
+ organization = new JTextField();
+ organization.setColumns(12);
+ organization.setHorizontalAlignment(2);
+ organization.setText("");
+ mainPanel.add(organization, new GridConstraints(1, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
+ final JLabel label4 = new JLabel();
+ label4.setText("seconds");
+ mainPanel.add(label4, new GridConstraints(0, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
+ final Spacer spacer1 = new Spacer();
+ mainPanel.add(spacer1, new GridConstraints(3, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));
+ }
+
+ /**
+ * @noinspection ALL
+ */
+ public JComponent $$$getRootComponent$$$() {
+ return mainPanel;
+ }
+
+}
diff --git a/src/main/scala/bitlap/sbt/analyzer/SettingsState.scala b/src/main/scala/bitlap/sbt/analyzer/SettingsState.scala
new file mode 100644
index 0000000..5602f8b
--- /dev/null
+++ b/src/main/scala/bitlap/sbt/analyzer/SettingsState.scala
@@ -0,0 +1,77 @@
+package bitlap
+package sbt
+package analyzer
+
+import scala.beans.BeanProperty
+
+import org.jetbrains.sbt.project.settings.*
+
+import com.intellij.ide.util.PropertiesComponent
+import com.intellij.openapi.application.ApplicationManager
+import com.intellij.openapi.components.*
+import com.intellij.openapi.externalSystem.settings.*
+import com.intellij.openapi.project.Project
+import com.intellij.util.messages.Topic
+import com.intellij.util.xmlb.XmlSerializerUtil
+import com.intellij.util.xmlb.annotations.Transient
+
+import kotlin.jvm.Volatile
+
+/** @author
+ * 梦境迷离
+ * @version 1.0,2023/9/7
+ */
+@State(name = "SbtDependencyAnalyzer.Settings", storages = Array(new Storage("bitlap.sbt.dependency.analyzer.xml")))
+final class SettingsState extends PersistentStateComponent[SettingsState] {
+
+ import SettingsState.*
+
+ @BeanProperty
+ var disableAnalyzeCompile: Boolean = false
+
+ @BeanProperty
+ var disableAnalyzeProvided: Boolean = false
+
+ @BeanProperty
+ var disableAnalyzeTest: Boolean = false
+
+ @BeanProperty
+ var organization: String = ""
+
+ @BeanProperty
+ var fileCacheTimeout: Int = 3600
+
+ override def getState(): SettingsState = this
+
+ override def loadState(state: SettingsState): Unit = {
+ XmlSerializerUtil.copyBean(state, this)
+ }
+
+}
+
+object SettingsState {
+
+ def getSettings(project: Project): SettingsState = project.getService(classOf[SettingsState])
+
+ val _Topic: Topic[SettingsChangeListener] =
+ Topic.create("SbtDependencyAnalyzerSettingsChanged", classOf[SettingsChangeListener])
+
+ trait SettingsChangeListener:
+
+ def onAnalyzerConfigurationChanged(project: Project, settingsState: SettingsState): Unit
+
+ end SettingsChangeListener
+
+ /** *
+ * {{{
+ * ApplicationManager
+ * .getApplication()
+ * .messageBus
+ * .connect(this)
+ * .subscribe(SettingsChangeListener.TOPIC, this)
+ * }}}
+ */
+ val SettingsChangePublisher: SettingsChangeListener =
+ ApplicationManager.getApplication.getMessageBus.syncPublisher(_Topic)
+
+}
diff --git a/src/main/scala/bitlap/sbt/analyzer/action/SbtDependencyAnalyzerGoToAction.scala b/src/main/scala/bitlap/sbt/analyzer/action/SbtDependencyAnalyzerGoToAction.scala
index 391139f..9096c44 100644
--- a/src/main/scala/bitlap/sbt/analyzer/action/SbtDependencyAnalyzerGoToAction.scala
+++ b/src/main/scala/bitlap/sbt/analyzer/action/SbtDependencyAnalyzerGoToAction.scala
@@ -27,6 +27,7 @@ final class SbtDependencyAnalyzerGoToAction extends DependencyAnalyzerGoToAction
)
private val LOG = Logger.getInstance(classOf[SbtDependencyAnalyzerGoToAction])
+ private var declaredDependencies: List[DeclaredDependency] = _
override def getNavigatable(e: AnActionEvent): Navigatable =
Option(getDeclaredDependency(e)).flatMap { dependency =>
@@ -54,7 +55,12 @@ final class SbtDependencyAnalyzerGoToAction extends DependencyAnalyzerGoToAction
val module = getParentModule(project, dependency)
if (coordinates == null || module == null) return null
- val declared = DependencyUtils.getDeclaredDependency(module)
+ val declared =
+ if (declaredDependencies == null) {
+ declaredDependencies = DependencyUtils.getDeclaredDependency(module)
+ declaredDependencies
+ } else declaredDependencies
+
declared
.find(dc =>
if (
diff --git a/src/main/scala/bitlap/sbt/analyzer/util/Notifications.scala b/src/main/scala/bitlap/sbt/analyzer/util/Notifications.scala
index dcab18d..c4b01ed 100644
--- a/src/main/scala/bitlap/sbt/analyzer/util/Notifications.scala
+++ b/src/main/scala/bitlap/sbt/analyzer/util/Notifications.scala
@@ -61,9 +61,20 @@ object Notifications {
NotificationType.ERROR
)
.setIcon(SbtDependencyAnalyzerIcons.ICON)
+ .setImportant(true)
notification.notify(null)
}
+ def notifySettingsChanged(project: Project): Unit = {
+ val notification = NotificationGroup
+ .createNotification(
+ SbtDependencyAnalyzerBundle.message("analyzer.notification.setting.changed.title"),
+ NotificationType.INFORMATION
+ )
+ .setIcon(SbtDependencyAnalyzerIcons.ICON)
+ notification.notify(project)
+ }
+
def notifyUnknownError(project: Project, command: String, moduleId: String, scope: DependencyScopeEnum): Unit = {
// add notification
val notification = NotificationGroup
@@ -73,6 +84,7 @@ object Notifications {
NotificationType.ERROR
)
.setIcon(SbtDependencyAnalyzerIcons.ICON)
+ .setImportant(true)
notification.notify(project)
}
@@ -108,6 +120,7 @@ object Notifications {
SbtDependencyAnalyzerBundle.message("analyzer.notification.addSdap.text", pluginSbtFileName),
NotificationType.INFORMATION
)
+ .setImportant(true)
.setIcon(SbtDependencyAnalyzerIcons.ICON)
.addAction(
new NotificationAction(