Skip to content

Commit 6ac91c9

Browse files
committed
reorganize first time plugin loaded persistence and event
1 parent 6e24c3c commit 6ac91c9

File tree

11 files changed

+58
-175
lines changed

11 files changed

+58
-175
lines changed
Lines changed: 40 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,29 @@
11
package org.digma.intellij.plugin.common;
22

3+
import com.intellij.openapi.components.Service;
34
import com.intellij.openapi.project.Project;
4-
import com.intellij.openapi.vfs.VirtualFile;
5-
import com.intellij.psi.*;
6-
import com.intellij.util.PlatformUtils;
7-
import org.digma.intellij.plugin.persistence.PersistenceService;
85
import org.digma.intellij.plugin.psi.*;
9-
import org.jetbrains.annotations.NotNull;
6+
import org.jetbrains.annotations.*;
107

11-
@SuppressWarnings("UnstableApiUsage")
12-
public class IDEUtilsService {
8+
@Service(Service.Level.PROJECT)
9+
public final class IDEUtilsService {
1310

14-
private final IsRider isRider;
15-
private final IsIdea isIdea;
11+
private final Idea idea;
12+
private final Rider rider;
13+
private final Pycharm pycharm;
1614

1715

1816
public IDEUtilsService(Project project) {
19-
isRider = new IsRider(project);
20-
isIdea = new IsIdea(project);
17+
idea = new Idea(project);
18+
rider = new Rider(project);
19+
pycharm = new Pycharm(project);
2120
}
2221

2322
public static IDEUtilsService getInstance(@NotNull Project project){
2423
return project.getService(IDEUtilsService.class);
2524
}
2625

2726

28-
public static boolean isAlreadyPassedInstallationWizard(){
29-
PersistenceService persistenceService = PersistenceService.getInstance();
30-
return IDEUtilsService.isIdeaIDE() && persistenceService.isAlreadyPassedTheInstallationWizardForIdeaIDE() ||
31-
IDEUtilsService.isRiderIDE() && persistenceService.isAlreadyPassedTheInstallationWizardForRiderIDE() ||
32-
IDEUtilsService.isPyCharmIDE() && persistenceService.isAlreadyPassedTheInstallationWizardForPyCharmIDE();
33-
}
34-
35-
36-
public static boolean shouldOpenWizard(){
37-
return !isAlreadyPassedInstallationWizard();
38-
}
39-
40-
4127
/*
4228
There is no easy way to know if a project is a java project. intellij doesn't have a project type. intellij projects
4329
have modules and each module has some nature. there may be a project that contains a java module and python module,
@@ -49,110 +35,74 @@ public static boolean shouldOpenWizard(){
4935
mean that its pycharm.
5036
*/
5137
public boolean isJavaProject() {
52-
return (PlatformUtils.isIdeaCommunity() || PlatformUtils.isIdeaUltimate()) && isIdea.isIdea();
38+
return idea.is();
5339
}
5440

5541
public boolean isCSharpProject() {
56-
return (PlatformUtils.isIdeaCommunity() || PlatformUtils.isIdeaUltimate()) && isRider.isRider();
42+
return rider.is();
5743
}
5844

5945

60-
public static boolean isIdeaIDE() {
61-
return PlatformUtils.isIdeaCommunity() || PlatformUtils.isIdeaUltimate();
46+
public boolean isIdeaIDE() {
47+
return idea.is();
6248
}
6349

64-
public static boolean isRiderIDE() {
65-
return PlatformUtils.isRider();
50+
public boolean isRiderIDE() {
51+
return rider.is();
6652
}
6753

68-
public static boolean isPyCharmIDE() {
69-
return PlatformUtils.isPyCharm() || PlatformUtils.isPyCharmCommunity() || PlatformUtils.isPyCharmEducational();
54+
public boolean isPyCharmIDE() {
55+
return pycharm.is();
7056
}
7157

72-
public boolean isRiderAndCSharpFile(@NotNull Project project, VirtualFile file) {
73-
74-
//it may be a C# file that was opened from vcs, it doesn't count as C# that CSharpLanguageService should handle
75-
if (!VfsUtilsKt.isValidVirtualFile(file)) {
76-
return false;
77-
}
78-
79-
if (isRider.isRider()) {
80-
LanguageService csharpLanguageService = isRider.getCSharpLanguageService();
81-
PsiFile psiFile = PsiAccessUtilsKt.runInReadAccessWithResult(() -> PsiManager.getInstance(project).findFile(file));
82-
if (!PsiUtils.isValidPsiFile(psiFile)) {
83-
return false;
84-
}
85-
return csharpLanguageService.isServiceFor(psiFile.getLanguage());
86-
}
87-
88-
return false;
89-
}
90-
91-
public boolean isRider() {
92-
return isRider.isRider();
93-
}
94-
95-
9658

97-
98-
private static class IsRider {
59+
private static abstract class IsIDE {
9960

10061
private LanguageService myLanguageService = null;
10162

102-
public IsRider(Project project) {
103-
init(project);
63+
private IsIDE(Project project, SupportedLanguages language) {
64+
init(project, language);
10465
}
10566

106-
@SuppressWarnings("unchecked")
107-
private void init(Project project) {
108-
Class<LanguageService> cshrpLanguageServiceClass;
67+
private void init(Project project, SupportedLanguages language) {
10968
try {
110-
cshrpLanguageServiceClass = (Class<LanguageService>) Class.forName(SupportedLanguages.CSHARP.getLanguageServiceClassName());
111-
myLanguageService = project.getService(cshrpLanguageServiceClass);
69+
@SuppressWarnings("unchecked") Class<LanguageService> languageServiceClass = (Class<LanguageService>) Class.forName(language.getLanguageServiceClassName());
70+
//noinspection IncorrectServiceRetrieving
71+
myLanguageService = project.getService(languageServiceClass);
11272
} catch (Throwable ignored) {
11373
//catch throwable and not exception because it may be Error like NoClassDefFound
11474
}
11575
}
11676

117-
public boolean isRider() {
77+
boolean is() {
11878
return myLanguageService != null;
11979
}
12080

121-
public LanguageService getCSharpLanguageService() {
81+
@Nullable
82+
LanguageService getLanguageService() {
12283
return myLanguageService;
12384
}
124-
}
125-
12685

86+
}
12787

128-
private static class IsIdea {
12988

130-
private LanguageService myLanguageService = null;
131-
132-
public IsIdea(Project project) {
133-
init(project);
134-
}
135-
136-
@SuppressWarnings("unchecked")
137-
private void init(Project project) {
138-
Class<LanguageService> javaLanguageServiceClass;
139-
try {
140-
javaLanguageServiceClass = (Class<LanguageService>) Class.forName(SupportedLanguages.JAVA.getLanguageServiceClassName());
141-
myLanguageService = project.getService(javaLanguageServiceClass);
142-
} catch (Throwable ignored) {
143-
//catch throwable and not exception because it may be Error like NoClassDefFound
144-
}
89+
private static class Rider extends IsIDE {
90+
private Rider(Project project) {
91+
super(project, SupportedLanguages.CSHARP);
14592
}
93+
}
14694

147-
public boolean isIdea() {
148-
return myLanguageService != null;
95+
private static class Idea extends IsIDE {
96+
private Idea(Project project) {
97+
super(project, SupportedLanguages.JAVA);
14998
}
99+
}
150100

151-
public LanguageService getJavaLanguageService() {
152-
return myLanguageService;
101+
private static class Pycharm extends IsIDE {
102+
private Pycharm(Project project) {
103+
super(project, SupportedLanguages.PYTHON);
153104
}
154105
}
155106

156107

157-
158108
}

ide-common/src/main/java/org/digma/intellij/plugin/common/StartupStartupActivity.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package org.digma.intellij.plugin.common;
22

3-
import com.intellij.ide.util.RunOnceUtil;
43
import com.intellij.openapi.project.*;
4+
import org.digma.intellij.plugin.persistence.PersistenceService;
55
import org.digma.intellij.plugin.posthog.ActivityMonitor;
66
import org.digma.intellij.plugin.session.SessionMetadataProperties;
77
import org.digma.intellij.plugin.startup.DigmaProjectActivity;
@@ -17,10 +17,14 @@ public class StartupStartupActivity extends DigmaProjectActivity {
1717

1818
@Override
1919
public void executeProjectStartup(@NotNull Project project) {
20-
RunOnceUtil.runOnceForApp(RUN_ONCE_ID, () -> {
20+
21+
//can't rely on intellij RunOnceUtil.runOnceForApp because it will run it again on ide upgrades
22+
if (PersistenceService.getInstance().isFirstTimePluginLoaded()) {
23+
PersistenceService.getInstance().setFirstTimePluginLoadedDone();
2124
ActivityMonitor.getInstance(project).registerFirstTimePluginLoaded();
2225
project.getService(DumbService.class).runWhenSmart(() -> EDT.ensureEDT(() -> ToolWindowShower.getInstance(project).showToolWindow()));
23-
});
26+
}
27+
2428
ActivityMonitor.getInstance(project).registerPluginLoaded();
2529
SessionMetadataProperties.getInstance().put(getPluginLoadedKey(project), true);
2630
}

ide-common/src/main/java/org/digma/intellij/plugin/ui/MainToolWindowCardsController.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import java.util.function.*;
2222

2323
import static org.digma.intellij.plugin.analytics.EnvUtilsKt.refreshEnvironmentsNowOnBackground;
24-
import static org.digma.intellij.plugin.persistence.PersistenceUtilsKt.updateInstallationWizardFlag;
2524
import static org.digma.intellij.plugin.scheduling.SchedulersKt.oneShotTask;
2625

2726
/**
@@ -106,7 +105,6 @@ public void connectionGained() {
106105
if (isCentralized()) {
107106
//do here everything that happens on INSTALLATION_WIZARD/FINISH message
108107
PersistenceService.getInstance().firstWizardLaunchDone();
109-
updateInstallationWizardFlag();
110108
EDT.ensureEDT(() -> {
111109
ToolWindowShower.getInstance(project).showToolWindow();
112110
project.getService(RecentActivityToolWindowShower.class).showToolWindow();
@@ -296,7 +294,7 @@ public void closeCoveringViewsIfNecessary() {
296294
//in case user finished new install but never clicked finish in the wizard, and clicks a link somewhere,
297295
// for example in recent activity, then close everything to show the main panel
298296
if (wizard.isOn()) {
299-
updateInstallationWizardFlag();
297+
PersistenceService.getInstance().firstWizardLaunchDone();
300298
}
301299
wizardFinished();
302300
troubleshootingFinished();

ide-common/src/main/kotlin/org/digma/intellij/plugin/persistence/PersistenceData.kt

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,6 @@ internal data class PersistenceData(
1919
// remove isAutoOtel after some versions, can remove in June 2024 when probably all users updated the plugin
2020
var isAutoOtel: Boolean = true,
2121
var isObservabilityEnabled: Boolean = true,
22-
var alreadyPassedTheInstallationWizardForIdeaIDE: Boolean = false,
23-
var alreadyPassedTheInstallationWizardForRiderIDE: Boolean = false,
24-
var alreadyPassedTheInstallationWizardForPyCharmIDE: Boolean = false,
2522
var firstWizardLaunch: Boolean = true,
2623

2724

@@ -64,8 +61,6 @@ internal data class PersistenceData(
6461
@OptionTag(converter = InstantConverter::class)
6562
var firstTimeRecentActivityReceivedTimestamp: Instant? = null,
6663

67-
//todo: remove isFirstTimePluginLoaded in May 2024
68-
var isFirstTimePluginLoaded: Boolean = false,
6964
@OptionTag(converter = InstantConverter::class)
7065
var firstTimePluginLoadedTimestamp: Instant? = null,
7166

ide-common/src/main/kotlin/org/digma/intellij/plugin/persistence/PersistenceService.kt

Lines changed: 2 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -72,15 +72,10 @@ class PersistenceService {
7272
}
7373

7474
fun isFirstTimePluginLoaded(): Boolean {
75-
//todo: backwards compatibility, remove state.isFirstTimePluginLoaded on May 2024
76-
if (state.isFirstTimePluginLoaded && state.firstTimePluginLoadedTimestamp == null) {
77-
state.firstTimePluginLoadedTimestamp = Instant.now()
78-
}
79-
80-
return state.firstTimePluginLoadedTimestamp != null
75+
return state.firstTimePluginLoadedTimestamp == null
8176
}
8277

83-
fun setFirstTimePluginLoaded() {
78+
fun setFirstTimePluginLoadedDone() {
8479
state.firstTimePluginLoadedTimestamp = Instant.now()
8580
}
8681

@@ -148,29 +143,6 @@ class PersistenceService {
148143
state.isAutoOtel = isObservabilityEnabled
149144
}
150145

151-
fun isAlreadyPassedTheInstallationWizardForIdeaIDE(): Boolean {
152-
return state.alreadyPassedTheInstallationWizardForIdeaIDE
153-
}
154-
155-
fun setAlreadyPassedTheInstallationWizardForIdeaIDE() {
156-
state.alreadyPassedTheInstallationWizardForIdeaIDE = true
157-
}
158-
159-
fun isAlreadyPassedTheInstallationWizardForRiderIDE(): Boolean {
160-
return state.alreadyPassedTheInstallationWizardForRiderIDE
161-
}
162-
163-
fun setAlreadyPassedTheInstallationWizardForRiderIDE() {
164-
state.alreadyPassedTheInstallationWizardForRiderIDE = true
165-
}
166-
167-
fun isAlreadyPassedTheInstallationWizardForPyCharmIDE(): Boolean {
168-
return state.alreadyPassedTheInstallationWizardForPyCharmIDE
169-
}
170-
171-
fun setAlreadyPassedTheInstallationWizardForPyCharmIDE() {
172-
state.alreadyPassedTheInstallationWizardForPyCharmIDE = true
173-
}
174146

175147

176148
fun isFirstTimeConnectionEstablished(): Boolean {

ide-common/src/main/kotlin/org/digma/intellij/plugin/persistence/PersistenceUtils.kt

Lines changed: 0 additions & 23 deletions
This file was deleted.

ide-common/src/main/kotlin/org/digma/intellij/plugin/posthog/ActivityMonitor.kt

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -646,12 +646,7 @@ class ActivityMonitor(private val project: Project, cs: CoroutineScope) : Dispos
646646
}
647647

648648

649-
//todo: remove at some point
650649
fun registerFirstTimePluginLoaded() {
651-
postHog?.capture(UniqueGeneratedUserId.userId, "plugin first-loaded")
652-
}
653-
654-
fun registerFirstTimePluginLoadedNew() {
655650
postHog?.capture(UniqueGeneratedUserId.userId, "plugin first-init")
656651
}
657652

src/main/java/org/digma/intellij/plugin/toolwindow/DigmaSidePaneToolWindowFactory.java

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import com.intellij.ui.content.ContentFactory;
99
import com.intellij.util.ui.JBUI;
1010
import org.digma.intellij.plugin.analytics.AnalyticsService;
11-
import org.digma.intellij.plugin.common.*;
11+
import org.digma.intellij.plugin.common.Backgroundable;
1212
import org.digma.intellij.plugin.log.Log;
1313
import org.digma.intellij.plugin.persistence.PersistenceService;
1414
import org.digma.intellij.plugin.posthog.ActivityMonitor;
@@ -32,7 +32,7 @@
3232
/**
3333
* The main Digma tool window on left panel
3434
*/
35-
public class DigmaSidePaneToolWindowFactory implements ToolWindowFactory {
35+
public final class DigmaSidePaneToolWindowFactory implements ToolWindowFactory {
3636

3737
private static final Logger LOGGER = Logger.getInstance(DigmaSidePaneToolWindowFactory.class);
3838
private static final String DIGMA_NAME = "DIGMA";
@@ -51,11 +51,6 @@ public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindo
5151
//initialize AnalyticsService early so the UI can detect the connection status when created
5252
AnalyticsService.getInstance(project);
5353

54-
if (!PersistenceService.getInstance().isFirstTimePluginLoaded()) {
55-
PersistenceService.getInstance().setFirstTimePluginLoaded();
56-
ActivityMonitor.getInstance(project).registerFirstTimePluginLoadedNew();
57-
}
58-
5954
Log.log(LOGGER::debug, "createToolWindowContent for project {}", project);
6055

6156
toolWindow.setTitle(DIGMA_NAME);
@@ -98,9 +93,9 @@ public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindo
9893
wizardPanelBuilder,
9994
troubleshootingPanelBuilder);
10095

101-
if (IDEUtilsService.shouldOpenWizard()) {
96+
if (PersistenceService.getInstance().isFirstWizardLaunch()) {
10297
ActivityMonitor.getInstance(project).registerCustomEvent("show-installation-wizard",
103-
Collections.singletonMap("reason", "show on startup,probably new installation"));
98+
Collections.singletonMap("reason", "show on startup,first wizard launch is true"));
10499
MainToolWindowCardsController.getInstance(project).showWizard(false);
105100
}
106101
else{

0 commit comments

Comments
 (0)