Skip to content

Commit 2be1a3f

Browse files
authored
Merge pull request #2396 from digma-ai/fix-some-posthog-events
reorganize first time plugin loaded persistence and event Closes #2391
2 parents 1626326 + 81a5aa6 commit 2be1a3f

File tree

11 files changed

+70
-175
lines changed

11 files changed

+70
-175
lines changed
Lines changed: 52 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,39 @@
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+
/*
9+
This class is not perfect but it does serve our needs.
10+
see the comments in com.intellij.util.PlatformUtils, PlatformUtils is marked internal API so its better not to user it.
11+
for what we need its probably ok:
12+
isIdeaIDE() is for sure Idea if we have JavaLanguageService installed.
13+
isRiderIDE() is for sure rider if we have CHarpLanguageService installed.
14+
isPyCharmIDE() is for sure pycharm if we have PythonLanguageService installed and it's not Idea.
15+
if we need more capabilities here we need to explore the technics suggested in com.intellij.util.PlatformUtils
16+
*/
1317

14-
private final IsRider isRider;
15-
private final IsIdea isIdea;
18+
@Service(Service.Level.PROJECT)
19+
public final class IDEUtilsService {
20+
21+
private final Idea idea;
22+
private final Rider rider;
23+
private final Pycharm pycharm;
1624

1725

1826
public IDEUtilsService(Project project) {
19-
isRider = new IsRider(project);
20-
isIdea = new IsIdea(project);
27+
idea = new Idea(project);
28+
rider = new Rider(project);
29+
pycharm = new Pycharm(project);
2130
}
2231

2332
public static IDEUtilsService getInstance(@NotNull Project project){
2433
return project.getService(IDEUtilsService.class);
2534
}
2635

2736

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-
4137
/*
4238
There is no easy way to know if a project is a java project. intellij doesn't have a project type. intellij projects
4339
have modules and each module has some nature. there may be a project that contains a java module and python module,
@@ -49,110 +45,76 @@ public static boolean shouldOpenWizard(){
4945
mean that its pycharm.
5046
*/
5147
public boolean isJavaProject() {
52-
return (PlatformUtils.isIdeaCommunity() || PlatformUtils.isIdeaUltimate()) && isIdea.isIdea();
48+
return idea.is();
5349
}
5450

51+
//this is not accurate, it may be rider but not a C# project
5552
public boolean isCSharpProject() {
56-
return (PlatformUtils.isIdeaCommunity() || PlatformUtils.isIdeaUltimate()) && isRider.isRider();
57-
}
58-
59-
60-
public static boolean isIdeaIDE() {
61-
return PlatformUtils.isIdeaCommunity() || PlatformUtils.isIdeaUltimate();
53+
return rider.is();
6254
}
6355

64-
public static boolean isRiderIDE() {
65-
return PlatformUtils.isRider();
66-
}
6756

68-
public static boolean isPyCharmIDE() {
69-
return PlatformUtils.isPyCharm() || PlatformUtils.isPyCharmCommunity() || PlatformUtils.isPyCharmEducational();
57+
public boolean isIdeaIDE() {
58+
return idea.is();
7059
}
7160

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;
61+
public boolean isRiderIDE() {
62+
return rider.is();
8963
}
9064

91-
public boolean isRider() {
92-
return isRider.isRider();
65+
public boolean isPyCharmIDE() {
66+
//python plugin may also be installed on Idea
67+
return pycharm.is() && !idea.is();
9368
}
9469

9570

96-
97-
98-
private static class IsRider {
71+
private static abstract class IsIDE {
9972

10073
private LanguageService myLanguageService = null;
10174

102-
public IsRider(Project project) {
103-
init(project);
75+
private IsIDE(Project project, SupportedLanguages language) {
76+
init(project, language);
10477
}
10578

106-
@SuppressWarnings("unchecked")
107-
private void init(Project project) {
108-
Class<LanguageService> cshrpLanguageServiceClass;
79+
private void init(Project project, SupportedLanguages language) {
10980
try {
110-
cshrpLanguageServiceClass = (Class<LanguageService>) Class.forName(SupportedLanguages.CSHARP.getLanguageServiceClassName());
111-
myLanguageService = project.getService(cshrpLanguageServiceClass);
81+
@SuppressWarnings("unchecked") Class<LanguageService> languageServiceClass = (Class<LanguageService>) Class.forName(language.getLanguageServiceClassName());
82+
//noinspection IncorrectServiceRetrieving
83+
myLanguageService = project.getService(languageServiceClass);
11284
} catch (Throwable ignored) {
11385
//catch throwable and not exception because it may be Error like NoClassDefFound
11486
}
11587
}
11688

117-
public boolean isRider() {
89+
boolean is() {
11890
return myLanguageService != null;
11991
}
12092

121-
public LanguageService getCSharpLanguageService() {
93+
@Nullable
94+
LanguageService getLanguageService() {
12295
return myLanguageService;
12396
}
124-
}
125-
12697

98+
}
12799

128-
private static class IsIdea {
129100

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-
}
101+
private static class Rider extends IsIDE {
102+
private Rider(Project project) {
103+
super(project, SupportedLanguages.CSHARP);
145104
}
105+
}
146106

147-
public boolean isIdea() {
148-
return myLanguageService != null;
107+
private static class Idea extends IsIDE {
108+
private Idea(Project project) {
109+
super(project, SupportedLanguages.JAVA);
149110
}
111+
}
150112

151-
public LanguageService getJavaLanguageService() {
152-
return myLanguageService;
113+
private static class Pycharm extends IsIDE {
114+
private Pycharm(Project project) {
115+
super(project, SupportedLanguages.PYTHON);
153116
}
154117
}
155118

156119

157-
158120
}

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

0 commit comments

Comments
 (0)