Open lukehutch opened 1 year ago
@bwilkerson I thought this had come up before but I couldn't find any issues.
I think the server only watches files inside analysis roots (or with overlays), so if you have a path
dependency that isn't open in the workspace and you edit it outside of this server, the changes will not be noticed.
My recommendation for VS Code users is generally to have a single window with both sets of code open rather than having two different windows that overlap (which avoids this issue and avoids having multiple servers analyzing some of the same content). I don't know if there are good reasons not to do this though (@lukehutch I'm curious to know your reasons for using two windows), or whether that's alone is a reason this shouldn't be supported.
If this was supported, there's a question about whether it should only be for path
dependencies, or if the folders in pubcache should be watched too (my feeling is that those should be immutable and would result in a lot of watchers, although it feels slightly inconsistent for one to be watched and not the other).
We shouldn't need to watch the files in the pub cache, as you noted they're intended to be treated as read-only. And we don't need to know about new directories being added until they're actually referenced from a package_config.json
file.
The analysis server currently treats any files outside of the analysis roots as similarly being read-only. I'm not sure how difficult or expensive it would be to change that, though at the moment I don't think server has any special knowledge of the pub cache, and it might need to in order to support this.
@lukehutch I have a question to add to Danny's: Are these two (or more) directories part of a monorepo (in the sense of a directory containing two or more packages that are always expected to be kept in sync, versioned together, etc.)?
@DanTup I don't like the two window solution because I hit F12 an awful lot to jump into the dependency code. When a window opens in the dependency code, that file is analyzed to some degree (it seems that not all analyzer functionality is enabled, or something), but the entire project is not scanned.
@bwilkerson this is for a read/write project that has a dependency on another separate read/write project, where both projects are being actively edited on the local machine. (They may both be in the same git repo, they may be in separate git repos, but they are separate projects with separate roots from the POV of the analyzer.) In Dart, the equivalent of package_config.json
is pubspec.yaml
, and it is very easy to detect unversioned (potentially read/write) projects: they are included as dependencies by path, not by package/version, and not by git URL.
So what I'm proposing is that the analyzer detect these situations, and set up multiple analysis roots in one project.
I'm OK with running one analyzer per project root, in this case (resource constraints aren't an issue), as long as the results are all funneled into a single VS Code window.
@lukehutch
@DanTup I don't like the two window solution because
I may have misunderstood something - my suggestion is to not use two windows. My understanding was that you had a project open in VS Code and were editing some files (that its projects referenced via a path dependency and not in the workspace) outside of that VS Code window (which I assumed, was in a second VS Code window).
If you're not using two windows, can you clarify how the files which aren't in the workspace are being edited (and why you don't want to add that project to the same VS Code window). Thanks!
@DanTup sorry, I thought that was a typo. I forgot to mention one important detail: the most problematic code in question is generated code -- I am using Serverpod, and it generates client code from the definition of endpoints in a separate server project (which I do have open in another window, yes, but I am not directly editing the generated client code). The code generator can be run in watch mode, so the client project can be updated anytime. Dart-Code doesn't notice when the client code is updated in the Flutter project (which depends upon the client project by path).
I am using Serverpod, and it generates client code from the definition of endpoints in a separate server project (which I do have open in another window, yes, but I am not directly editing the generated client code).
Ah, gotcha. Whether the code is modified by a tool or manually in the other window doesn't change a lot here though. I guess my question is really why you don't add the server project to the original VS Code window. If you did this, it would automatically be watched (and it would reduce your resources because you don't need a second analysis server for that other VS Code window).
If the reason for this is that some things don't work correctly when you have them in the same workspace/window, I'd be very interested in knowing what those things are. If it's just that you want the code on another monitor or something, then I don't have a good reply to that currently 🙃
Honestly the reason is that I didn't even know it was possible to have two projects open in the same window! I thought the analysis root was defined by the directory you open VS Code in.
It sounds like I have a solution for my usecase (I'll try it out sometime today). I don't know whether it is worth pursuing further the request to automatically analyze unversioned dependencies, but that seems potentially worthwhile.
Honestly the reason is that I didn't even know it was possible to have two projects open in the same window! I thought the analysis root was defined by the directory you open VS Code in.
Early on, it was the case that VS Code could only open a single folder. It has been supported for some time though - they called it Multi-root Workspaces.
You can use File -> Add Folder to Workspace to add multiple, or multi-select folders from the Open Folder dialog (although they have to be siblings to do that).
When you have multiple folders open, you can click File -> Save Workspace As to save a .code-workspace
file. That file can contain not only a set of folders to open, but also workspace settings and launch configurations. I use this quite a lot when working in the Dart SDK so I can have just the relevant folders open, and have settings and launch configurations that suit me without having to commit them to the repository (or ignore them).
Please let us know how it feels when you try it out. While it would be nice to support what's requested here, if the most common reason to hit this issue is just not knowing that you can have multiple folders in a workspace, it might be better to try and improve discoverability or documentation of that instead (because it will reduce overall resource use by not having two analysis servers analyzing the same code).
@DanTup OK, so this is hilarious, but when I was reading your instructions, I was thinking "What platform is he talking about? There's no File menu on Linux"...
Turns out there is in fact a menu bar, and I have never even noticed it was there...
I think my brain just saw the menu bar as window chrome, and ignored it, especially since I'm using a dark theme, and the menu bar is light (doesn't match the theme).
As far as the docs, the docs are really good and really clear already, but I confess I have never gone and read the manual for VS Code. I suspect this is true for a lot of people. We want to figure it out as we go, without reading anything, and everything should be obvious.
Now that I tried multi-root workspaces, all my problems are solved -- thanks for explaining this in detail! I added the flutter, client, and server projects to a single workspace, started the Serverpod commandline generator tool in watch mode, and now changes I make actually affect all the projects at once, just as I needed.
So the final effect of enabling this is to make me realize that basically I was asking for something that already existed, although I asked for this sort of dependency tracking to be automatic, based on the unversioned dependencies of the project.
Maybe then what could be done is that if you add an unversioned dependency to the project, the project will be added to your multi-root workspace?
There are two changes I would love to see to how multi-root workspaces work:
code myproject.code-workspace
, not code .
, to open the multi-root workspace. I would strongly prefer VS Code to save multi-workspace information to .vscode/settings.json
rather than to a separate file like this, so that typing code .
would open the project with its previous state, whether that is single-root or multi-root. Currently that's how single-root projects work -- the exact state of the editor is restored when you open the same directory. This is not the case for multi-root workspaces.myproject.code-workspace
file, including deciding where to save it. I would like to see the saving of this file to happen automatically too -- either by saving the info to .vscode/settings.json
as recommended above, or by automatically saving the file to .vscode/project.code-workspace
or similar.So basically neither the loading nor the saving of .code-workspace
files should be manual.
Other issues I'm discovering with having multiple projects open:
(1) Launch configurations are listed in a per-project list:
however, these attempt to run the main method only from the project where you most recently opened a Dart file, not from the project selected in the list (click_flutter or click_server).
(2) Setting breakpoints no longer works properly with multiple projects open. The breakpoints are showing as unverified:
Maybe then what could be done is that if you add an unversioned dependency to the project, the project will be added to your multi-root workspace?
Adding the folder directly is a bit disruptive (it could trigger a full extension host restart) so I don't think we should do it automatically, but we could perhaps prompt ("Your workspace projects contain path
dependencies, add them to the workspace?"). The only niggle is is once you create a multi-root workspace, you're prompted to save it when you close, and this might also feel a little odd.
Still, if you file an issue for this at https://github.com/Dart-Code/Dart-Code, we can let it collect 👍 's to see if there's interest in it.
Currently you have to do code myproject.code-workspace, not code ., to open the multi-root workspace.
If you put your .code-workspace
file inside the folder, VS Code does prompt ("Did you want to open the code-workspace?") when you open the folder. But I agree this isn't perfect (esp. if you don't want to commit it). I have a terminal alias c
to open VS Code for the current directory and have some special cases because of this in my PowerShell profile:
function x-c($path) {
# Special-case folders where we want to open workspaces...
if ($PWD.Path -eq "C:\Dev\Google\devtools") {
$path ??= "C:\Dev\Code Workspaces\DevTools.code-workspace"
}
# ... (snip) ...
$path ??= "."
code $path
};
Set-Alias c x-c
While not ideal, you might be able to do something similar for bash.
I would strongly prefer VS Code to save multi-workspace information to .vscode/settings.json rather than to a separate file like this
How this works is all controlled by VS Code and not something we can influence, but I agree it'd be nice if there was an option to do this more easily. Note that there doesn't have to be a 1:1 mapping from folders to workspaces though - I have multiple code-workspace files for the same repos where I might work on different sets of packages.
It's also a pain to have to manually save the myproject.code-workspace file, including deciding where to save it. I would like to see the saving of this file to happen automatically too
I agree this could probably be more seamless with the concept of a default/preferred workspace for a folder. Again, it'd need to be built into VS Code though. FWIW I have a "Code Workspaces" folder which I have pinned to my favourites in the explorer window:
Again it's not perfect, but it works well for me (and keeps these files outside of the repos, since they contain launch configs and settings that might be specific to me that others aren't interested in).
(1) Launch configurations are listed in a per-project list: however, these attempt to run the main method only from the project where you most recently opened a Dart file, not from the project selected in the list (click_flutter or click_server).
This sounds like a bug - could you file at https://github.com/Dart-Code/Dart-Code and I'll take a look?
(2) Setting breakpoints no longer works properly with multiple projects open. The breakpoints are showing as unverified:
Are you sure this is related to multiple projects? There are some known issues about breakpoints appearing as unresolved until right before they're executed (because when using the new debug adapters, we support proper resolution but the VM only resolves them right before they execute them). There's an open issue about that at https://github.com/Dart-Code/Dart-Code/issues/4734. If that doesn't match what you're seeing, please open an additional Dart-Code issue and we can debug.
Thanks!
If you put your
.code-workspace
file inside the folder, VS Code does prompt ("Did you want to open the code-workspace?") when you open the folder.
I don't see that behavior on my end. I have a myproject.code-workspace
file in the current directory, but if I run code .
, I am not asked if I want to open the workspace. I have to manually open it with code myproject.code-workspace
to open the workspace.
(1) Launch configurations are listed in a per-project list: however, these attempt to run the main method only from the project where you most recently opened a Dart file, not from the project selected in the list (click_flutter or click_server).
This sounds like a bug - could you file at https://github.com/Dart-Code/Dart-Code and I'll take a look?
Let me first check -- the behavior I'm seeing is that when I hit F5 (Run), the first time I try to run a project, I have to run from the Dart file containing main
. Otherwise, the run configuration json file is opened by VS Code. After successfully running once, usually (but not always?) if I have some Dart file open, hitting F5 runs the same main
function. However, if I have something else open (like a YAML file), then when I hit F5, the json config file is opened again. I have not been able to figure out how to specify in the json file that a specific Dart file contains the main
to run every time, so that the editor does not open the json file rather than running the program.
(2) Setting breakpoints no longer works properly with multiple projects open. The breakpoints are showing as unverified:
Are you sure this is related to multiple projects?
It seems to be the same issue that you referenced, with unconfirmed breakpoints. Breakpoints appear to be more commonly unconfirmed for code that is outside the current workspace, i.e. in dependencies.
I don't see that behavior on my end. I have a myproject.code-workspace file in the current directory, but if I run code ., I am not asked if I want to open the workspace. I have to manually open it with code myproject.code-workspace to open the workspace.
That seems to be reported at https://github.com/microsoft/vscode/issues/185423 and based on https://github.com/microsoft/vscode/issues/125315#issuecomment-855584260 is apparently deliberate - the notification only shows the very first time and is otherwise hidden in the bell.
Let me first check -- the behavior I'm seeing is that when I hit F5 (Run), the first time I try to run a project, I have to run from the Dart file containing main. Otherwise, the run configuration json file is opened by VS Code. After successfully running once, usually (but not always?) if I have some Dart file open, hitting F5 runs the same main function.
I'm not sure if I complete understand the steps (so an issue with exact steps to repro might help), but the way this should work is:
program
specified in that launch config (which there won't be if one isn't defined in the launch config, or there was no launch config) we will run thatbin/
, tool/
, test/
or at lib/main.dart
) then we will try to run thatlib/main.dart
, bin/main.dart
) to see if we can find a likely entry point there.If you have a non-dart file open and press F5
:
So the way to ensure that pressing F5
always runs your app is to ensure you have a launch configuration (and it is selected) that has a program
field that points to a Dart script. If this doesn't work, please provide a small sample project and instructions so I can investigate.
Breakpoints appear to be more commonly unconfirmed for code that is outside the current workspace, i.e. in dependencies
I'm not aware of any issues that would cause these to behave differently - if you have good steps/an example to repro this, please file an additional issue for me to look at. Thanks!
Getting back to this issue, @lukehutch wrote
In Dart, the equivalent of package_config.json is pubspec.yaml, and it is very easy to detect unversioned (potentially read/write) projects: they are included as dependencies by path, not by package/version, and not by git URL.
So what I'm proposing is that the analyzer detect these situations, and set up multiple analysis roots in one project.
@bwilkerson @scheglov do you have thoughts here? I think I've been running into this while developing an analyzer plugin, referenced as a path dependency. Can we just watch the path of a non-versioned dependency, or do we need to add another analysis root, an analysis context...?
I can't think of any reason why it would be a problem for server to watch non-versioned dependencies, whether they're introduced as a path dependency directly or as a path-based dependency override.
I don't think we want to create a separate analysis context for such dependencies, though. That would add too much overhead and probably cause UX problems that we don't need to introduce.
We also encountered a similar issue in Android Studio. Here is my development environment:
IDE environment:
Android Studio Giraffe | 2022.3.1 Patch 1
Build #AI-223.8836.35.2231.10671973, built on August 17, 2023
Runtime version: 17.0.6+0-17.0.6b829.9-10027231 x86_64
VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o.
Flutter environment
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.10.0, on macOS 14.1.1 23B81 darwin-x64, locale zh-Hans-US)
[!] Android toolchain - develop for Android devices (Android SDK version 33.0.1)
✗ Android license status unknown.
Run `flutter doctor --android-licenses` to accept the SDK licenses.
See https://flutter.dev/docs/get-started/install/macos#android-setup for more details.
[✓] Xcode - develop for iOS and macOS (Xcode 14.2)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2021.3)
[✓] Android Studio (version 2022.3)
[✓] IntelliJ IDEA Ultimate Edition (version 2021.2.4)
[✓] VS Code (version 1.78.0)
[✓] Connected device (2 available)
Android Studio plugins version:
Flutter: 77.1.1
Dart: 223.8977
We have a Flutter application that depends on a component called foo
.
name: flutter_app_sample
...
dependencies:
foo: 1.0.0
When we develop the component foo
, in order to open only one IDE(Android Studio), we will rewrite the dependency to change the remote dependency to a local path dependency.
name: flutter_app_sample
...
dependencies:
foo: 1.0.0
dependency_overrides:
foo:
path: /Users/franticn/Projects/Samples/foo
Then run flutter pub get
. Later, we can see the locally dependent foo in the External Libraries
in Android Studio.
Since it is a local dependency, and it also is unversioned dependency. So we can directly develop the code of flutter_app_sample
and foo
in one project.
However, for foo
, Dart Analysis
is disabled for it. Editing the files directly in one IDE window in the above way will result in no code completion and reminders, but executing the command dart analyze
in the directory where foo
is located is possible.
At the same time, checking the checkbox Scope analysis to current package
in Dart Analysis Server Settings
does not work either.
In my understanding, Scope analysis to current package
is for this scenario?
I think this development method is also quite common, maybe. However, there is no good way to support it. Therefore, I submitted this comment in the hope of getting help from everyone.
@lukehutch
@DanTup I don't like the two window solution because
I may have misunderstood something - my suggestion is to not use two windows. My understanding was that you had a project open in VS Code and were editing some files (that its projects referenced via a path dependency and not in the workspace) outside of that VS Code window (which I assumed, was in a second VS Code window).
If you're not using two windows, can you clarify how the files which aren't in the workspace are being edited (and why you don't want to add that project to the same VS Code window). Thanks!
To address the question of "how the files which aren't in the workspace are being edited", if you depend on a component through a local dependency in VS Code, you can find your component in the VS Code EXPLORER -> DEPENDENCIES -> transitive dependencies after running pub get. However, Dart Analysis also does not work.
To address the question of "how the files which aren't in the workspace are being edited", if you depend on a component through a local dependency in VS Code, you can find your component in the VS Code EXPLORER -> DEPENDENCIES -> transitive dependencies after running pub get. However, Dart Analysis also does not work.
Got it, thanks. If you're going to be modifying files from a path dependency like this, I would recommend adding them to the workspace (File
-> Add Folder to Workspace
). There are many differences between dependencies that are just discovered as dependencies and folders that are explicitly in the workspace (for example when debugging, packages inside the workspace are considered "my code" and dependencies not inside the workspace are considered "external packages") and implementing the change requested here won't change all of those.
Filing here at the request of @DanTup -- https://github.com/Dart-Code/Dart-Code/issues/4725
In
pubspec.yaml
, it is possible to depend upon unversioned projects by path, e.g.:The files in a dependency like this are not monitored for changes by Dart-Code. Consequently, whenever you make changes in the dependency project, you have to go Ctrl+Shift+P > "Developer: Reload Window" and then wait for all the dependencies to be scanned.
All depended-upon files in
path:
dependencies should be watched for changes, just like files in the main project.dart info
)Linux
N/A