Skip to content

Commit f99f8cc

Browse files
authored
[PERF] migrate Project parentDisposables to Services (#8178)
Using a `Project` as a parent disposable can lead to plugins not being unloaded correctly leading to memory leaks. This follows the advice given in the Jetbrains [disposer docs](https://plugins.jetbrains.com/docs/intellij/disposers.html?from=IncorrectParentDisposable#choosing-a-disposable-parent) and is (I think) consistent with the Dart plugin (@alexander-doroshko?). This gets us *most* of the way to fixing #8107 with an open question about `AndroidModuleLibraryManager`. (Question posed there 👍 .) --- - [x] I’ve reviewed the contributor guide and applied the relevant portions to this PR. <details> <summary>Contribution guidelines:</summary><br> - See our [contributor guide]([https://github.com/dart-lang/sdk/blob/main/CONTRIBUTING.md](https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview) for general expectations for PRs. - Larger or significant changes should be discussed in an issue before creating a PR. - Dart contributions to our repos should follow the [Dart style guide](https://dart.dev/guides/language/effective-dart) and use `dart format`. - Java and Kotlin contributions should strive to follow Java and Kotlin best practices ([discussion](#8098)). </details>
1 parent 9102f9c commit f99f8cc

File tree

9 files changed

+33
-22
lines changed

9 files changed

+33
-22
lines changed

flutter-idea/src/io/flutter/bazel/WorkspaceCache.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ private WorkspaceCache(@NotNull final Project project) {
6161
FileWatch nextWatch = null;
6262
if (next != null) {
6363
nextWatch = FileWatch.subscribe(next.getRoot(), next.getDependencies(), this::scheduleRefresh);
64-
nextWatch.setDisposeParent(project);
64+
nextWatch.setDisposeParent(FlutterDartAnalysisServer.getInstance(project));
6565
}
6666

6767
final FileWatch prevWatch = fileWatch.getAndSet(nextWatch);

flutter-idea/src/io/flutter/dart/FlutterDartAnalysisServer.java

-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
import com.intellij.openapi.application.Application;
1717
import com.intellij.openapi.application.ApplicationManager;
1818
import com.intellij.openapi.project.Project;
19-
import com.intellij.openapi.util.Disposer;
2019
import com.intellij.util.Consumer;
2120
import com.jetbrains.lang.dart.analyzer.DartAnalysisServerService;
2221
import io.flutter.utils.JsonUtils;
@@ -100,7 +99,6 @@ public void computedErrors(String file, List<AnalysisError> errors) {
10099
super.computedErrors(file, errors);
101100
}
102101
});
103-
Disposer.register(project, this);
104102
}
105103

106104
public void addOutlineListener(@NotNull final String filePath, @NotNull final FlutterOutlineListener listener) {

flutter-idea/src/io/flutter/run/FlutterReloadManager.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
import io.flutter.actions.ReloadFlutterApp;
5959
import io.flutter.bazel.Workspace;
6060
import io.flutter.bazel.WorkspaceCache;
61+
import io.flutter.dart.FlutterDartAnalysisServer;
6162
import io.flutter.run.common.RunMode;
6263
import io.flutter.run.daemon.FlutterApp;
6364
import io.flutter.settings.FlutterSettings;
@@ -127,7 +128,8 @@ public static FlutterReloadManager getInstance(@NotNull Project project) {
127128
private FlutterReloadManager(@NotNull Project project) {
128129
this.myProject = project;
129130

130-
final MessageBusConnection connection = ApplicationManager.getApplication().getMessageBus().connect(project);
131+
final MessageBusConnection connection =
132+
ApplicationManager.getApplication().getMessageBus().connect(FlutterDartAnalysisServer.getInstance(project));
131133
connection.subscribe(AnActionListener.TOPIC, new AnActionListener() {
132134
private @Nullable Project eventProject;
133135
private @Nullable Editor eventEditor;

flutter-idea/src/io/flutter/run/common/CommonTestConfigUtils.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import com.jetbrains.lang.dart.psi.DartCallExpression;
1717
import com.jetbrains.lang.dart.psi.DartStringLiteralExpression;
1818
import io.flutter.dart.DartSyntax;
19+
import io.flutter.dart.FlutterDartAnalysisServer;
1920
import io.flutter.editor.ActiveEditorsOutlineService;
2021
import io.flutter.utils.OpenApiUtils;
2122
import org.dartlang.analysis.server.protocol.ElementKind;
@@ -173,7 +174,8 @@ private LineMarkerUpdatingListener getListenerForFile(@NotNull final PsiFile fil
173174
final ActiveEditorsOutlineService service = getActiveEditorsOutlineService(file.getProject());
174175
if (!listenerCache.containsKey(path) && service != null) {
175176
listenerCache.put(path, new LineMarkerUpdatingListener(this, file.getProject(), service));
176-
Disposer.register(file.getProject(), () -> {
177+
var disposableParent = FlutterDartAnalysisServer.getInstance(file.getProject());
178+
Disposer.register(disposableParent, () -> {
177179
listenerCache.remove(path);
178180
});
179181
}

flutter-idea/src/io/flutter/run/daemon/DeviceService.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import io.flutter.FlutterMessages;
2121
import io.flutter.FlutterUtils;
2222
import io.flutter.bazel.WorkspaceCache;
23+
import io.flutter.dart.FlutterDartAnalysisServer;
2324
import io.flutter.run.FlutterDevice;
2425
import io.flutter.sdk.AndroidEmulatorManager;
2526
import io.flutter.sdk.FlutterSdkManager;
@@ -63,7 +64,7 @@ public static DeviceService getInstance(@NotNull final Project project) {
6364
private DeviceService(@NotNull final Project project) {
6465
this.project = project;
6566

66-
deviceDaemon.setDisposeParent(project);
67+
deviceDaemon.setDisposeParent(FlutterDartAnalysisServer.getInstance(project));
6768
deviceDaemon.subscribe(this::refreshDeviceSelection);
6869
refreshDeviceDaemon();
6970

@@ -80,7 +81,8 @@ public void flutterSdkRemoved() {
8081
}
8182
};
8283
FlutterSdkManager.getInstance(project).addListener(sdkListener);
83-
Disposer.register(project, () -> FlutterSdkManager.getInstance(project).removeListener(sdkListener));
84+
Disposer.register(FlutterDartAnalysisServer.getInstance(project),
85+
() -> FlutterSdkManager.getInstance(project).removeListener(sdkListener));
8486

8587
// Watch for Bazel workspace changes.
8688
WorkspaceCache.getInstance(project).subscribe(this::refreshDeviceDaemon);

flutter-idea/src/io/flutter/run/daemon/FlutterApp.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import io.flutter.ObservatoryConnector;
3434
import io.flutter.bazel.Workspace;
3535
import io.flutter.bazel.WorkspaceCache;
36+
import io.flutter.dart.FlutterDartAnalysisServer;
3637
import io.flutter.logging.FlutterConsoleLogManager;
3738
import io.flutter.pub.PubRoot;
3839
import io.flutter.pub.PubRoots;
@@ -260,7 +261,7 @@ public static FlutterApp start(@NotNull ExecutionEnvironment env,
260261
}
261262

262263
final ProcessHandler process = new MostlySilentColoredProcessHandler(command, onTextAvailable);
263-
Disposer.register(project, process::destroyProcess);
264+
Disposer.register(FlutterDartAnalysisServer.getInstance(project), process::destroyProcess);
264265

265266
final DaemonApi api = new DaemonApi(process);
266267
final FlutterApp app = new FlutterApp(project, module, mode, device, process, env, api, command);

flutter-idea/src/io/flutter/sdk/FlutterPluginsLibraryManager.java

+6-3
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
import io.flutter.pub.PubRoots;
2222
import org.jetbrains.annotations.NotNull;
2323

24-
import java.util.*;
24+
import java.util.HashSet;
25+
import java.util.List;
26+
import java.util.Set;
2527
import java.util.concurrent.atomic.AtomicBoolean;
2628

2729
import static com.jetbrains.lang.dart.util.PubspecYamlUtil.PUBSPEC_YAML;
@@ -42,6 +44,7 @@ public FlutterPluginsLibraryManager(@NotNull Project project) {
4244
}
4345

4446
public void startWatching() {
47+
var project = getProject();
4548
VirtualFileManager.getInstance().addVirtualFileListener(new VirtualFileContentsChangedAdapter() {
4649
@Override
4750
protected void onFileChange(@NotNull VirtualFile file) {
@@ -51,9 +54,9 @@ protected void onFileChange(@NotNull VirtualFile file) {
5154
@Override
5255
protected void onBeforeFileChange(@NotNull VirtualFile file) {
5356
}
54-
}, getProject());
57+
}, FlutterDartAnalysisServer.getInstance(project));
5558

56-
getProject().getMessageBus().connect().subscribe(ModuleRootListener.TOPIC, new ModuleRootListener() {
59+
project.getMessageBus().connect().subscribe(ModuleRootListener.TOPIC, new ModuleRootListener() {
5760
@Override
5861
public void rootsChanged(@NotNull ModuleRootEvent event) {
5962
scheduleUpdate();

flutter-idea/src/io/flutter/sdk/FlutterSdkManager.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import com.intellij.openapi.roots.libraries.LibraryTable;
1414
import com.intellij.openapi.util.Disposer;
1515
import com.intellij.util.EventDispatcher;
16+
import io.flutter.dart.FlutterDartAnalysisServer;
1617
import io.flutter.utils.OpenApiUtils;
1718
import org.jetbrains.annotations.NotNull;
1819
import org.jetbrains.annotations.Nullable;
@@ -48,7 +49,7 @@ private FlutterSdkManager(@NotNull Project project) {
4849
final ScheduledFuture timer = JobScheduler.getScheduler().scheduleWithFixedDelay(
4950
this::checkForFlutterSdkChange, 1, 1, TimeUnit.SECONDS);
5051

51-
Disposer.register(project, () -> {
52+
Disposer.register(FlutterDartAnalysisServer.getInstance(project), () -> {
5253
libraryTable.removeListener(libraryTableListener);
5354
timer.cancel(false);
5455
});

flutter-studio/src/io/flutter/utils/AddToAppUtils.java

+12-10
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,6 @@
77

88
//import static com.android.tools.idea.gradle.project.importing.GradleProjectImporter.ANDROID_PROJECT_TYPE;
99

10-
import static com.intellij.util.ReflectionUtil.findAssignableField;
11-
import static io.flutter.actions.AttachDebuggerAction.ATTACH_IS_ACTIVE;
12-
import static io.flutter.actions.AttachDebuggerAction.findRunConfig;
13-
1410
import com.android.tools.idea.gradle.project.sync.GradleSyncListener;
1511
import com.android.tools.idea.gradle.project.sync.GradleSyncState;
1612
import com.intellij.debugger.engine.DebugProcess;
@@ -22,25 +18,32 @@
2218
import com.intellij.openapi.application.Application;
2319
import com.intellij.openapi.application.ApplicationManager;
2420
import com.intellij.openapi.module.Module;
25-
import com.intellij.openapi.project.*;
21+
import com.intellij.openapi.project.ModuleListener;
22+
import com.intellij.openapi.project.Project;
23+
import com.intellij.openapi.project.ProjectType;
24+
import com.intellij.openapi.project.ProjectTypeService;
2625
import com.intellij.util.ThreeState;
2726
import com.intellij.util.concurrency.AppExecutorUtil;
2827
import com.intellij.util.messages.MessageBusConnection;
2928
import com.intellij.util.messages.Topic;
3029
import io.flutter.FlutterUtils;
3130
import io.flutter.actions.AttachDebuggerAction;
31+
import io.flutter.dart.FlutterDartAnalysisServer;
3232
import io.flutter.pub.PubRoot;
3333
import io.flutter.run.SdkAttachConfig;
3434
import io.flutter.sdk.FlutterSdk;
35+
import org.jetbrains.annotations.NonNls;
36+
import org.jetbrains.annotations.NotNull;
37+
import org.jetbrains.annotations.Nullable;
3538

3639
import java.lang.reflect.Field;
3740
import java.lang.reflect.Modifier;
3841
import java.util.Collection;
3942
import java.util.List;
4043

41-
import org.jetbrains.annotations.NonNls;
42-
import org.jetbrains.annotations.NotNull;
43-
import org.jetbrains.annotations.Nullable;
44+
import static com.intellij.util.ReflectionUtil.findAssignableField;
45+
import static io.flutter.actions.AttachDebuggerAction.ATTACH_IS_ACTIVE;
46+
import static io.flutter.actions.AttachDebuggerAction.findRunConfig;
4447

4548
public class AddToAppUtils {
4649
//private static final Logger LOG = Logger.getInstance(AddToAppUtils.class);
@@ -49,7 +52,7 @@ private AddToAppUtils() {
4952
}
5053

5154
public static boolean initializeAndDetectFlutter(@NotNull Project project) {
52-
MessageBusConnection connection = project.getMessageBus().connect(project);
55+
MessageBusConnection connection = project.getMessageBus().connect(FlutterDartAnalysisServer.getInstance(project));
5356
// GRADLE_SYNC_TOPIC is not public in Android Studio 3.5. It is in 3.6. It isn't defined in 3.4.
5457
//noinspection unchecked
5558
Topic<GradleSyncListener> topic = getStaticFieldValue(GradleSyncState.class, Topic.class, "GRADLE_SYNC_TOPIC");
@@ -71,7 +74,6 @@ public void modulesAdded(@NotNull Project proj, @NotNull List<? extends Module>
7174
});
7275
}
7376
}
74-
7577
}
7678
});
7779
return false;

0 commit comments

Comments
 (0)