Repository navigation
[flutter_tools] Fix hot reload for workspace member packages in lib/ (#190284) - #190540
Merged
Merged
Conversation
…lutter#190284) Fixes an issue where hot reload ignores file changes in pub workspace member packages located under the workspace root package's `lib/` directory (`Reloaded 0 of N libraries`). When translating file URIs to `package:` URIs for the resident frontend server during hot reload, `PackageConfig.toPackageUri` matches the first package whose `packageUriRoot` is a prefix of the file URI. If a workspace member package is located under the root package's `lib/` directory, the root package is matched first, causing `file:///.../lib/member/lib/foo.dart` to be incorrectly resolved to `package:root/member/lib/foo.dart` instead of `package:member/foo.dart`. This change introduces `PackageConfigWorkspaceExtension.toPackageUriForWorkspace`, which iterates through `PackageConfig.packages` to find the most specific package (longest matching `packageUriRoot` prefix) for a given file URI. Updates `ResidentCompiler` and web build/run targets to use `toPackageUriForWorkspace`. Issue: flutter#190284
Contributor
There was a problem hiding this comment.
Code Review
This pull request adds a toPackageUriForWorkspace extension method to PackageConfig to correctly resolve file URIs to package URIs in nested pub workspaces, updating the compiler and web runner targets accordingly. The review feedback suggests optimizing this new method by storing the matched root path during the loop to avoid redundant string computations.
Comment on lines
+146
to
+168
| final path = fileUri.toString(); | ||
| Package? bestMatch; | ||
| var bestMatchLength = -1; | ||
|
|
||
| for (final Package package in packages) { | ||
| final rootPath = package.packageUriRoot.toString(); | ||
| final rootPathWithSlash = rootPath.endsWith('/') ? rootPath : '$rootPath/'; | ||
| if (path.startsWith(rootPathWithSlash)) { | ||
| if (rootPathWithSlash.length > bestMatchLength) { | ||
| bestMatch = package; | ||
| bestMatchLength = rootPathWithSlash.length; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if (bestMatch == null) { | ||
| return null; | ||
| } | ||
|
|
||
| final rootPath = bestMatch.packageUriRoot.toString(); | ||
| final rootPathWithSlash = rootPath.endsWith('/') ? rootPath : '$rootPath/'; | ||
| final String rest = path.substring(rootPathWithSlash.length); | ||
| return Uri(scheme: 'package', path: '${bestMatch.name}/$rest'); |
Contributor
There was a problem hiding this comment.
The current implementation re-computes rootPathWithSlash for the bestMatch package after the loop finishes, which is redundant since it was already computed during the iteration. We can optimize this by storing the bestMatchRoot string directly, which also simplifies the code and improves readability.
final String path = fileUri.toString();
Package? bestMatch;
String? bestMatchRoot;
for (final Package package in packages) {
final String rootPath = package.packageUriRoot.toString();
final String rootPathWithSlash = rootPath.endsWith('/') ? rootPath : '$rootPath/';
if (path.startsWith(rootPathWithSlash)) {
if (bestMatchRoot == null || rootPathWithSlash.length > bestMatchRoot.length) {
bestMatch = package;
bestMatchRoot = rootPathWithSlash;
}
}
}
if (bestMatch == null || bestMatchRoot == null) {
return null;
}
final String rest = path.substring(bestMatchRoot.length);
return Uri(scheme: 'package', path: '${bestMatch.name}/$rest');References
- Suggest simplification and refactoring: Assess whether the code can be made simpler or refactored to enhance readability and maintainability. (link)
chingjun
approved these changes
Aug 7, 2026
This was referenced Aug 8, 2026
Merged
2 of 5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #190284
When a pub workspace member package is located under the workspace root package's
lib/directory (e.g.,workspace_root/lib/member_pkg/), standardPackageConfig.toPackageUri(fileUri)performs a prefix-tree lookup that matches shorter outer prefixes first (workspace_root). Modifyingworkspace_root/lib/member_pkg/lib/foo.dartresulted inpackage:workspace_root/member_pkg/lib/foo.dartinstead ofpackage:member_pkg/foo.dart. Because the incorrect URI does not exist in the active isolate's compilation graph,ResidentCompilerreportedReloaded 0 of N librariesand dropped the edit.This PR adds
PackageConfigWorkspaceExtension.toPackageUriForWorkspaceinpackage_map.dart, implementing longest-prefix matching across all configured packages so that nested workspace member packages resolve to their correctpackage:URIs.Testing
incremental compile sends correct package URI for pub workspace member package located under root lib/inpackages/flutter_tools/test/general.shard/compile_incremental_test.dart.packages/flutter_tools/test/general.shard/dart/package_map_test.dart.