Skip to content

Commit 2e70e33

Browse files
authored
Fix broken devtools inspector source navigation (#8058)
Restores source navigation from the embedded devtools inspector. Fixes: #8041 ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read the [Flutter Style Guide] _recently_, and have followed its advice. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/master/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/master/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/master/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/master/docs/contributing/Style-guide-for-Flutter-repo.md [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/master/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/master/docs/contributing/Chat.md
1 parent fe07d80 commit 2e70e33

File tree

2 files changed

+100
-1
lines changed

2 files changed

+100
-1
lines changed

flutter-idea/src/io/flutter/devtools/DevToolsUtils.java

+90-1
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,32 @@
55
*/
66
package io.flutter.devtools;
77

8+
import com.intellij.openapi.application.Application;
89
import com.intellij.openapi.editor.colors.EditorColorsManager;
10+
import com.intellij.openapi.vfs.VirtualFile;
911
import com.intellij.ui.ColorUtil;
1012
import com.intellij.ui.JBColor;
1113
import com.intellij.util.ui.UIUtil;
14+
import org.dartlang.vm.service.VmService;
15+
import org.dartlang.vm.service.VmServiceListener;
1216
import org.jetbrains.annotations.NotNull;
1317

18+
import org.dartlang.vm.service.element.Event;
19+
20+
import com.google.gson.JsonObject;
21+
import com.intellij.openapi.application.ApplicationManager;
22+
import com.intellij.openapi.vfs.LocalFileSystem;
23+
import com.intellij.xdebugger.impl.XSourcePositionImpl;
24+
import io.flutter.run.daemon.FlutterApp;
25+
import io.flutter.utils.JsonUtils;
26+
import org.dartlang.vm.service.element.*;
27+
import org.jetbrains.annotations.Nullable;
28+
29+
import java.net.MalformedURLException;
30+
import java.net.URI;
31+
import java.net.URISyntaxException;
32+
import java.util.*;
33+
1434
public class DevToolsUtils {
1535
public static String findWidgetId(String url) {
1636
final String searchFor = "inspectorRef=";
@@ -23,6 +43,75 @@ public static String findWidgetId(String url) {
2343
return null;
2444
}
2545

46+
/**
47+
* Register a VM listener that listens for devtools "ToolEvent"s.
48+
* @param app the associated app
49+
*/
50+
public static void registerDevToolsVmServiceListener(@NotNull FlutterApp app) {
51+
// This functionality lived originally in the `FlutterInspectorService` introduced in:
52+
// https://github.com/flutter/flutter-intellij/pull/6881
53+
//
54+
// It was mistakenly removed in: https://github.com/flutter/flutter-intellij/pull/7867
55+
//
56+
// TODO(pq): some follow-ups:
57+
// * consider a better long-term home for this utility
58+
// * do we need to de-register?
59+
60+
VmService vmService = app.getVmService();
61+
if (vmService == null) return;
62+
63+
vmService.addVmServiceListener(new VmServiceListener() {
64+
@Override
65+
public void connectionOpened() { }
66+
67+
@Override
68+
public void received(String streamId, Event event) {
69+
if (streamId != null) {
70+
onVmServiceReceived(app, streamId, event);
71+
}
72+
}
73+
74+
@Override
75+
public void connectionClosed() { }
76+
});
77+
}
78+
79+
private static void onVmServiceReceived(@NotNull FlutterApp app, @NotNull String streamId, @Nullable Event event) {
80+
Application application = ApplicationManager.getApplication();
81+
if (application == null) return;
82+
83+
if (streamId.equals("ToolEvent")) {
84+
Optional<Event> eventOrNull = Optional.ofNullable(event);
85+
if ("navigate".equals(eventOrNull.map(Event::getExtensionKind).orElse(null))) {
86+
JsonObject json = eventOrNull.map(Event::getExtensionData).map(ExtensionData::getJson).orElse(null);
87+
if (json == null) return;
88+
89+
String fileUri = JsonUtils.getStringMember(json, "fileUri");
90+
if (fileUri == null) return;
91+
92+
String path = null;
93+
try {
94+
path = new URI(fileUri).toURL().getFile();
95+
}
96+
catch (MalformedURLException | URISyntaxException e) {
97+
// A null path will cause an early return.
98+
}
99+
if (path == null) return;
100+
101+
VirtualFile file = LocalFileSystem.getInstance().findFileByPath(path);
102+
int line = JsonUtils.getIntMember(json, "line");
103+
int column = JsonUtils.getIntMember(json, "column");
104+
105+
application.invokeLater(() -> {
106+
if (file != null && line >= 0 && column >= 0) {
107+
XSourcePositionImpl position = XSourcePositionImpl.create(file, line - 1, column - 1);
108+
position.createNavigatable(app.getProject()).navigate(false);
109+
}
110+
});
111+
}
112+
}
113+
}
114+
26115
public String getColorHexCode() {
27116
return ColorUtil.toHex(UIUtil.getEditorPaneBackground());
28117
}
@@ -37,6 +126,6 @@ public Boolean getIsBackgroundBright() {
37126
// Return the default normal font size if editor manager is not found.
38127
return UIUtil.getFontSize(UIUtil.FontSize.NORMAL);
39128
}
40-
return (float) manager.getGlobalScheme().getEditorFontSize();
129+
return (float)manager.getGlobalScheme().getEditorFontSize();
41130
}
42131
}

flutter-idea/src/io/flutter/view/FlutterView.java

+10
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import io.flutter.bazel.WorkspaceCache;
3434
import io.flutter.devtools.DevToolsIdeFeature;
3535
import io.flutter.devtools.DevToolsUrl;
36+
import io.flutter.devtools.DevToolsUtils;
3637
import io.flutter.jxbrowser.FailureType;
3738
import io.flutter.jxbrowser.InstallationFailedReason;
3839
import io.flutter.jxbrowser.JxBrowserManager;
@@ -49,6 +50,7 @@
4950
import io.flutter.utils.EventStream;
5051
import io.flutter.utils.JxBrowserUtils;
5152
import io.flutter.utils.LabelInput;
53+
import org.dartlang.vm.service.VmService;
5254
import org.jetbrains.annotations.NotNull;
5355

5456
import javax.swing.*;
@@ -161,6 +163,14 @@ private void addBrowserInspectorViewContent(FlutterApp app,
161163
FlutterSdk flutterSdk = FlutterSdk.getFlutterSdk(app.getProject());
162164
FlutterSdkVersion flutterSdkVersion = flutterSdk == null ? null : flutterSdk.getVersion();
163165

166+
167+
// Register for devtools events (required for inspector->editor source linking)
168+
// See: https://github.com/flutter/flutter-intellij/issues/8041
169+
VmService vmService = app.getVmService();
170+
if (vmService != null) {
171+
DevToolsUtils.registerDevToolsVmServiceListener(app);
172+
}
173+
164174
if (isEmbedded) {
165175
final DevToolsUrl devToolsUrl = new DevToolsUrl.Builder()
166176
.setDevToolsHost(devToolsInstance.host())

0 commit comments

Comments
 (0)