55import 'package:async/async.dart' ;
66import 'package:dwds/src/config/tool_configuration.dart' ;
77import 'package:dwds/src/debugging/debugger.dart' ;
8+ import 'package:dwds/src/debugging/metadata/provider.dart' ;
89import 'package:dwds/src/utilities/dart_uri.dart' ;
910import 'package:logging/logging.dart' ;
1011
@@ -16,6 +17,9 @@ class Modules {
1617 // The Dart server path to containing module.
1718 final _sourceToModule = < String , String > {};
1819
20+ // Module to Dart server paths.
21+ final _moduleToSources = < String , Set <String >> {};
22+
1923 // The Dart server path to library import uri
2024 final _sourceToLibrary = < String , Uri > {};
2125 var _moduleMemoizer = AsyncMemoizer <void >();
@@ -31,9 +35,13 @@ class Modules {
3135 /// Intended to be called multiple times throughout the development workflow,
3236 /// e.g. after a hot-reload.
3337 void initialize (String entrypoint) {
34- // We only clear the source to module mapping as script IDs may persist
35- // across hot reloads.
38+ // TODO(srujzs): Can we do better and only invalidate the sources/modules
39+ // that were deleted/reloaded? This would require removing the
40+ // deleted/reloaded libraries/sources/modules from the following maps and
41+ // then only processing that set in `_initializeMapping`. It's doable, but
42+ // these calculations are also not that expensive.
3643 _sourceToModule.clear ();
44+ _moduleToSources.clear ();
3745 _sourceToLibrary.clear ();
3846 _libraryToModule.clear ();
3947 _moduleMemoizer = AsyncMemoizer ();
@@ -46,6 +54,12 @@ class Modules {
4654 return _sourceToModule[serverPath];
4755 }
4856
57+ /// Returns the Dart server paths for the provided module.
58+ Future <Set <String >?> sourcesForModule (String module) async {
59+ await _moduleMemoizer.runOnce (_initializeMapping);
60+ return _moduleToSources[module];
61+ }
62+
4963 /// Returns the containing library importUri for the provided Dart server path.
5064 Future <Uri ?> libraryForSource (String serverPath) async {
5165 await _moduleMemoizer.runOnce (_initializeMapping);
@@ -69,11 +83,15 @@ class Modules {
6983 ) async {
7084 final serverPath = await globalToolConfiguration.loadStrategy
7185 .serverPathForModule (entrypoint, module);
86+ // TODO(srujzs): We should wait until all scripts are parsed before
87+ // accessing.
7288 return chromePathToRuntimeScriptId[serverPath];
7389 }
7490
75- /// Initializes [_sourceToModule] and [_sourceToLibrary] .
76- Future <void > _initializeMapping () async {
91+ /// Initializes [_sourceToModule] , [_moduleToSources] , and [_sourceToLibrary] .
92+ Future <void > _initializeMapping ([
93+ InvalidatedModuleReport ? invalidatedModuleReport,
94+ ]) async {
7795 final provider = globalToolConfiguration.loadStrategy.metadataProviderFor (
7896 _entrypoint,
7997 );
@@ -92,6 +110,7 @@ class Modules {
92110 final module = scriptToModule[library]! ;
93111
94112 _sourceToModule[libraryServerPath] = module;
113+ _moduleToSources.putIfAbsent (module, () => {}).add (libraryServerPath);
95114 _sourceToLibrary[libraryServerPath] = Uri .parse (library);
96115 _libraryToModule[library] = module;
97116
@@ -102,6 +121,7 @@ class Modules {
102121 : DartUri (script, _root).serverPath;
103122
104123 _sourceToModule[scriptServerPath] = module;
124+ _moduleToSources[module]! .add (scriptServerPath);
105125 _sourceToLibrary[scriptServerPath] = Uri .parse (library);
106126 }
107127 } else {
0 commit comments