You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Breakpoints in SDK code don't work for framework code (found from Go-to-Definition) #27189
Breakpoints only work if I use the debugger to step into dart: libraries and add breakpoints, but not if I set them by navigating into the code using Go-to-Definition (via the analyzer).
If I go-to-definition on print I will be taken to the implementation of print that lives inside my SDK folder (this path comes back from the analyzer):
If I add a breakpoint in the definition of print then when I run the application, it's never hit. Here's what the addBreakpointWithScriptUri call looks like:
I was under the impression this was expected, but @a-siva suggests maybe not. I think the issue is that the breakpoint I'm setting is in package:sky_engine/core/print.dart but if I step into print with the debugger the URI is dart:code/print.dart.
This may not be specific to Flutter - while reviewing my skipped tests I noticed that this also doesn't work outside of Flutter (Dart CLI apps). I F12'd into Uri.parse() and added a breakpoint, but it doesn't get hit either.
I'm adding it with a file:/// URI, since in VS Code I don't have a mapping of fs->URIs for the SDK:
For setting breakpoints within dart:* libraries, you'll want to pass a URI with the org-dartlang-sdk:// scheme. For example, to set a breakpoint for print in dart:core you would use the following for the scriptUri: org-dartlang-sdk:///sdk/lib/core/print.dart. Can you give that a shot and let me know if that works?
Also, as an aside, is there any way to get the output from the VM when running through VSCode? I'll admit I haven't tried very hard to find it, so I could be missing something obvious :)
The complicated bit here is that we don't really know what's a dart: library. In the editor the user just invokes "Go to definition" and the analysis server gives us a filepath back. It may be in the SDK, it might not. Is there any possibility of supporting the file paths in the debugger?
It's possible I could just look for file paths the start with the SDK folder we're running from, but it feels a little fragile.
Also, as an aside, is there any way to get the output from the VM when running through VSCode?
Do you mean the VM service JSON? There are two ways:
Set the dart.observatoryLogFile setting - this will log the JSON on every debug session (overwriting the file each time). I leave this enabled all the time, so if I spot a bug I can grab it and not have to worry about reproducing it again.
Run the Dart: Capture Logs command and tick Observatory. This will start logging to a temp file, which will be opened when you click the Stop Logging button (which may collapse into the bell icon after a while).
In both cases, you might want to also increase the dart.maxLogLineLength setting to reduce truncation of long messages (default is 2k characters).
The complicated bit here is that we don't really know what's a dart: library. In the editor the user just invokes "Go to definition" and the analysis server gives us a filepath back. It may be in the SDK, it might not. Is there any possibility of supporting the file paths in the debugger?
It's possible I could just look for file paths the start with the SDK folder we're running from, but it feels a little fragile.
Oh that's unfortunate. We don't have the dart:* sources mapped to file URIs as they're part of the platform kernel which is linked into the VM. Basically, since the files for these sources aren't actually on the filesystem in a typical sense, the platform kernel uses URIs with the org-dartlang-sdk:// scheme. Unfortunately, you'll probably have to hack at the path a bit to get to the desired URI but I can't think of any way to get around it.
Also, as an aside, is there any way to get the output from the VM when running through VSCode?
Do you mean the VM service JSON? There are two ways:
Set the dart.observatoryLogFile setting - this will log the JSON on every debug session (overwriting the file each time). I leave this enabled all the time, so if I spot a bug I can grab it and not have to worry about reproducing it again.
Run the Dart: Capture Logs command and tick Observatory. This will start logging to a temp file, which will be opened when you click the Stop Logging button (which may collapse into the bell icon after a while).
In both cases, you might want to also increase the dart.maxLogLineLength setting to reduce truncation of long messages (default is 2k characters).
There are two places where the user can add breakpoints for SDK sources:
At editor time - no debugger is running. They invoke Go-to-Definition on a built-in method/class and it takes them to the source code - this works by the analysis server returning us the path on disk to the SDK's lib folder (the last item in the lists above).
At debug time - the user is debugging, they Step into an SDK source and the URI and source code is provided via the VM service, but we are not provided the real path on disk.
Right now these appear in VS Code as two completely different files (even though to the user they are logically the same). It seems like I need to be able to map them to the same thing in order for this to work as the user would expect.
As a potential complication, is it guaranteed that the source downloaded from the VM service matches what's in the SDK lib folder on disk for the VM that's executing the code? (assuming the user hasn't explicitly modified it or something daft). For ex., if we stopped downloading source code from the VM and always used the one on disk, could anything bad happen?
Ah, sorry for the delay! Must have slipped through my emails... anyway, the path segments aren't the same exactly. For example, org-dartlang-sdk:///sdk/lib/async/stream_impl.dart is the same as dart:async/stream_impl.dart, org-darglang-sdk:///runtime/lib/async_patch.dart is the same as dart:async-patch/async_patch.dart (note the dart:async-patch, which is rather strange), etc.
As for whether the files on disk match those provided by the VM service, they should match overall except for patch files. I'm not sure how we apply them or pull them in for the actual SDK release since they're not packaged with the SDK like the rest of the core library files, but I assume they're just linked into the VM itself.
The example you gave still looks computable by me (eg. if there's no subfolder, then foo.dart becomes foo/foo.dart). What concerns me more is org-dartlang-sdk:///sdk/ versus org-dartlang-sdk:///runtime/, since I'm not sure why that's different.
If we can reliably convert a file system path to a VM URI with some basic code (eg. not requiring special knowledge from the VM) then I think we can make this work. I'm not worried about patch files, since I don't think the user could Go-to-Definition to them in the first place.
If the mapping from FS -> sdk URIs is not consistent (eg. it requires a big mapping) then that seems like a blocker since we'd need some mapping table. If that's the case, I wonder if we should build it into the SDK and let the analysis server provide it (to avoid duplicating it in each IDE)? (@bwilkerson I presume the server doesn't already have this, but I don't know for sure that that's true).
@bkonyi not urgent, but I saw you resolve a comment about this in a doc. I'm still not sure whether the mapping from FS to URI is something we can compute in the editor (with some rules), or if they're arbitrary and would require us to include a big mapping (which is probably not feasible) - see last comment above.
The example you gave still looks computable by me (eg. if there's no subfolder, then foo.dart becomes foo/foo.dart). What concerns me more is org-dartlang-sdk:///sdk/ versus org-dartlang-sdk:///runtime/, since I'm not sure why that's different.
If we can reliably convert a file system path to a VM URI with some basic code (eg. not requiring special knowledge from the VM) then I think we can make this work. I'm not worried about patch files, since I don't think the user could Go-to-Definition to them in the first place.
If the mapping from FS -> sdk URIs is not consistent (eg. it requires a big mapping) then that seems like a blocker since we'd need some mapping table. If that's the case, I wonder if we should build it into the SDK and let the analysis server provide it (to avoid duplicating it in each IDE)? (@bwilkerson I presume the server doesn't already have this, but I don't know for sure that that's true).
The reason why we have both org-dartlang-sdk:///sdk/ versus org-dartlang-sdk:///runtime/ is that the *_patch.dart files are located in the VM's runtime directory as they often contain native method invocations. AFAIK, the vast majority of the Dart files in the runtime directory are patch files, with only a few which aren't.
Ok, but if the pattern is consistent (anything ending _patch.dart goes into runtime, everything else into sdk) that still seems computable.
I'm trying to understand if I can write a function that given an SDK file path can compute the correct URI to put a breakpoint there (or vice versa).
Is there a way I can get a list of all the org-dartlang-sdk scripts loaded? Maybe the easier thing is for me to take a list and see if I can write such a function, and confirm all the files I map to exist on disk?
Also, iirc sky_engine is package that contains subset of dart sdk relevant for flutter (specified in _embedder.yaml). I don't think it should be present at all if you run CLI app against regular dart SDK.
So I tried a rather trivial approach of checking whether file is within dart SDK, and if it is replacing SDK path with org-dartlang-sdk:///sdk/, and also replacing dart: prefix with actual location stackTraceRequest and I was able to debug code within the SDK. Even something as simple as this would be significant improvement.
It wouldn't, but I'd like to just fix it once and it work everywhere. sky_engine is the current complication, since that's where I end up when I hit F12 on print in a Flutter project, but the debugger still maps it to the base Dart SDK.
I'd like to know how sky_engine is treated differently, and whether it's the only package that is (in which case, I should be able to map that similarly).
@bkonyi is this something you know, or is there someone else I could ping? Thanks!
I assume, that's because of _embedder.yaml present it in sky_engine/lib. It might be necessary to parse _embedder.yaml for all packages where it is present. However another complication seems to be, that embedder for example only maps "dart:async" to "async/async.dart, which in turns includes all files from async folder.
This is getting rather hairy. It does seem like the proper place for mapping between org-dartlang-sdk and filesystem is in the analyzer, as it already knows about packages that embed sdk.
To save you reading the whole thread, the analyzer and the debugger have different ideas about URIs for SDK libraries (eg. analyzer gives file system paths, which for the SDK in flutter we end up mapping to package:sky_engine based on the .packages file, and for the SDK we just don't map). The debugger wants URIs for the SDK in specific formats (org-dartlang-sdk:///sdk/...).
It doesn't seem like there's a great way for the editors to match these up. For example if you press Go-to-Definition on print when not debugging, and then also "step into" it during debugging, these two files are considered different by the editor. Each have their own set of breakpoints, one of which is never hit. This makes it really awkward to put breakpoints inside SDK files since you can only do it if you step into them first, not via Go-to-Definition.
It would be great to support this, but I don't know where it should be fixed. My preference (biased entirely by the work I have to do in VS Code!) would be for the VM to handle file system paths for everything (including the SDK) since it already feels awkward for the editor to be doing its own parsing of .packages and mapping things to URIs, however it sounds like it doesn't have the information to do this.
(I presume we must have this limitation in IntelliJ/Android Studio too?)
For reference, patch I'm using right now to get breakpoints working. Obviously this only works with dart SDK and doesn't handle embedded SDKs in any way.
Reacted by Danny Tuppeny, chunli, akatriel and ipcjs
@knopp thanks! Depending on what a potential future solution might be, I might run with something like this as a workaround in the meantime (probably special-casing sky_engine too, if that's the only one).
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.
Activity
DanTup commentedon Mar 20, 2019
This may not be specific to Flutter - while reviewing my skipped tests I noticed that this also doesn't work outside of Flutter (Dart CLI apps). I F12'd into
Uri.parse()and added a breakpoint, but it doesn't get hit either.I'm adding it with a
file:///URI, since in VS Code I don't have a mapping of fs->URIs for the SDK:(fyi @bkonyi :-))
bkonyi commentedon Mar 26, 2019
For setting breakpoints within dart:* libraries, you'll want to pass a URI with the
org-dartlang-sdk://scheme. For example, to set a breakpoint forprintindart:coreyou would use the following for the scriptUri:org-dartlang-sdk:///sdk/lib/core/print.dart. Can you give that a shot and let me know if that works?Also, as an aside, is there any way to get the output from the VM when running through VSCode? I'll admit I haven't tried very hard to find it, so I could be missing something obvious :)
DanTup commentedon Mar 26, 2019
The complicated bit here is that we don't really know what's a
dart:library. In the editor the user just invokes "Go to definition" and the analysis server gives us a filepath back. It may be in the SDK, it might not. Is there any possibility of supporting the file paths in the debugger?It's possible I could just look for file paths the start with the SDK folder we're running from, but it feels a little fragile.
Do you mean the VM service JSON? There are two ways:
Set the
dart.observatoryLogFilesetting - this will log the JSON on every debug session (overwriting the file each time). I leave this enabled all the time, so if I spot a bug I can grab it and not have to worry about reproducing it again.Run the Dart: Capture Logs command and tick Observatory. This will start logging to a temp file, which will be opened when you click the Stop Logging button (which may collapse into the bell icon after a while).
In both cases, you might want to also increase the
dart.maxLogLineLengthsetting to reduce truncation of long messages (default is 2k characters).bkonyi commentedon Mar 26, 2019
Oh that's unfortunate. We don't have the
dart:*sources mapped to file URIs as they're part of the platform kernel which is linked into the VM. Basically, since the files for these sources aren't actually on the filesystem in a typical sense, the platform kernel uses URIs with theorg-dartlang-sdk://scheme. Unfortunately, you'll probably have to hack at the path a bit to get to the desired URI but I can't think of any way to get around it.Perfect, thanks! :)
DanTup commentedon Mar 28, 2019
Just to clarify, are the path segments for
dart:,org-dartlang-sdk:and the path in the local SDK folder all the same?For example:
There are two places where the user can add breakpoints for SDK sources:
Right now these appear in VS Code as two completely different files (even though to the user they are logically the same). It seems like I need to be able to map them to the same thing in order for this to work as the user would expect.
As a potential complication, is it guaranteed that the source downloaded from the VM service matches what's in the SDK lib folder on disk for the VM that's executing the code? (assuming the user hasn't explicitly modified it or something daft). For ex., if we stopped downloading source code from the VM and always used the one on disk, could anything bad happen?
DanTup commentedon Apr 8, 2019
@bkonyi any thoughts on the above? Thanks!
bkonyi commentedon Apr 8, 2019
Ah, sorry for the delay! Must have slipped through my emails... anyway, the path segments aren't the same exactly. For example,
org-dartlang-sdk:///sdk/lib/async/stream_impl.dartis the same asdart:async/stream_impl.dart,org-darglang-sdk:///runtime/lib/async_patch.dartis the same asdart:async-patch/async_patch.dart(note thedart:async-patch, which is rather strange), etc.As for whether the files on disk match those provided by the VM service, they should match overall except for patch files. I'm not sure how we apply them or pull them in for the actual SDK release since they're not packaged with the SDK like the rest of the core library files, but I assume they're just linked into the VM itself.
DanTup commentedon Apr 10, 2019
The example you gave still looks computable by me (eg. if there's no subfolder, then
foo.dartbecomesfoo/foo.dart). What concerns me more isorg-dartlang-sdk:///sdk/versusorg-dartlang-sdk:///runtime/, since I'm not sure why that's different.If we can reliably convert a file system path to a VM URI with some basic code (eg. not requiring special knowledge from the VM) then I think we can make this work. I'm not worried about patch files, since I don't think the user could Go-to-Definition to them in the first place.
If the mapping from FS -> sdk URIs is not consistent (eg. it requires a big mapping) then that seems like a blocker since we'd need some mapping table. If that's the case, I wonder if we should build it into the SDK and let the analysis server provide it (to avoid duplicating it in each IDE)? (@bwilkerson I presume the server doesn't already have this, but I don't know for sure that that's true).
DanTup commentedon Apr 30, 2019
@bkonyi not urgent, but I saw you resolve a comment about this in a doc. I'm still not sure whether the mapping from FS to URI is something we can compute in the editor (with some rules), or if they're arbitrary and would require us to include a big mapping (which is probably not feasible) - see last comment above.
bkonyi commentedon May 22, 2019
The reason why we have both
org-dartlang-sdk:///sdk/versusorg-dartlang-sdk:///runtime/is that the*_patch.dartfiles are located in the VM's runtime directory as they often contain native method invocations. AFAIK, the vast majority of the Dart files in the runtime directory are patch files, with only a few which aren't.DanTup commentedon May 23, 2019
Ok, but if the pattern is consistent (anything ending
_patch.dartgoes into runtime, everything else into sdk) that still seems computable.I'm trying to understand if I can write a function that given an SDK file path can compute the correct URI to put a breakpoint there (or vice versa).
Is there a way I can get a list of all the
org-dartlang-sdkscripts loaded? Maybe the easier thing is for me to take a list and see if I can write such a function, and confirm all the files I map to exist on disk?2 remaining items
DanTup commentedon Jun 5, 2019
Wait a minute :( Going back to the sample right at the top here, it has:
package:sky_engine\/core\/print.dartWhat is the relationship between
package:sky_engineand the SDK? (And if it's special, is it the only special one?)knopp commentedon Jun 11, 2019
Any progress on this? Not being able to place breakpoint in dart SDK has caught me very much by surprise. This is a fundamental thing that's broken.
knopp commentedon Jun 12, 2019
Also, iirc sky_engine is package that contains subset of dart sdk relevant for flutter (specified in _embedder.yaml). I don't think it should be present at all if you run CLI app against regular dart SDK.
knopp commentedon Jun 12, 2019
So I tried a rather trivial approach of checking whether file is within dart SDK, and if it is replacing SDK path with org-dartlang-sdk:///sdk/, and also replacing dart: prefix with actual location stackTraceRequest and I was able to debug code within the SDK. Even something as simple as this would be significant improvement.
DanTup commentedon Jun 12, 2019
It wouldn't, but I'd like to just fix it once and it work everywhere. sky_engine is the current complication, since that's where I end up when I hit F12 on
printin a Flutter project, but the debugger still maps it to the base Dart SDK.I'd like to know how sky_engine is treated differently, and whether it's the only package that is (in which case, I should be able to map that similarly).
@bkonyi is this something you know, or is there someone else I could ping? Thanks!
knopp commentedon Jun 12, 2019
I assume, that's because of _embedder.yaml present it in sky_engine/lib. It might be necessary to parse _embedder.yaml for all packages where it is present. However another complication seems to be, that embedder for example only maps "dart:async" to "async/async.dart, which in turns includes all files from async folder.
I.e. this is what analyzer does
This is getting rather hairy. It does seem like the proper place for mapping between org-dartlang-sdk and filesystem is in the analyzer, as it already knows about packages that embed sdk.
DanTup commentedon Jun 12, 2019
Aha, that's how it works.
Yeah, it doesn't feel like this logic should exist in the editor, it seems like a pretty specific implementation detail and not some public API.
@bwilkerson @devoncarew FYI..
To save you reading the whole thread, the analyzer and the debugger have different ideas about URIs for SDK libraries (eg. analyzer gives file system paths, which for the SDK in flutter we end up mapping to
package:sky_enginebased on the.packagesfile, and for the SDK we just don't map). The debugger wants URIs for the SDK in specific formats (org-dartlang-sdk:///sdk/...).It doesn't seem like there's a great way for the editors to match these up. For example if you press Go-to-Definition on
printwhen not debugging, and then also "step into" it during debugging, these two files are considered different by the editor. Each have their own set of breakpoints, one of which is never hit. This makes it really awkward to put breakpoints inside SDK files since you can only do it if you step into them first, not via Go-to-Definition.It would be great to support this, but I don't know where it should be fixed. My preference (biased entirely by the work I have to do in VS Code!) would be for the VM to handle file system paths for everything (including the SDK) since it already feels awkward for the editor to be doing its own parsing of .packages and mapping things to URIs, however it sounds like it doesn't have the information to do this.
(I presume we must have this limitation in IntelliJ/Android Studio too?)
knopp commentedon Jun 12, 2019
For reference, patch I'm using right now to get breakpoints working. Obviously this only works with dart SDK and doesn't handle embedded SDKs in any way.
DanTup commentedon Jun 12, 2019
@knopp thanks! Depending on what a potential future solution might be, I might run with something like this as a workaround in the meantime (probably special-casing sky_engine too, if that's the only one).
bkonyi commentedon Nov 1, 2021
This should be resolved by using the new RPCs landed in this CL. Closing, but feel free to reopen if you want to track that work here.
github-actions commentedon Nov 16, 2021
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of
flutter doctor -vand a minimal reproduction of the issue.