Skip to content

Commit 6293002

Browse files
scheglovCommit Queue
authored andcommitted
Macro. Support for macro generated files in getFilesReferencingName()
Change-Id: Ie3fe2f10780d7f5b8a119ed35ef4de9c25f5eabd Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/348767 Reviewed-by: Brian Wilkerson <[email protected]> Reviewed-by: Phil Quitslund <[email protected]> Commit-Queue: Konstantin Shcheglov <[email protected]>
1 parent 36e4bf1 commit 6293002

File tree

4 files changed

+231
-153
lines changed

4 files changed

+231
-153
lines changed

pkg/analyzer/lib/src/dart/analysis/driver.dart

Lines changed: 84 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -192,8 +192,12 @@ class AnalysisDriver {
192192
/// Set to `true` after first [discoverAvailableFiles].
193193
bool _hasAvailableFilesDiscovered = false;
194194

195-
/// The list of tasks to compute files referencing a name.
196-
final _referencingNameTasks = <_FilesReferencingNameTask>[];
195+
/// The requests to compute files defining a class member with the name.
196+
final _definingClassMemberNameRequests =
197+
<_GetFilesDefiningClassMemberNameRequest>[];
198+
199+
/// The requests to compute files referencing a name.
200+
final _referencingNameRequests = <_GetFilesReferencingNameRequest>[];
197201

198202
/// The mapping from the files for which errors were requested using
199203
/// [getErrors] to the [Completer]s to report the result.
@@ -437,7 +441,10 @@ class AnalysisDriver {
437441
if (_requestedLibraries.isNotEmpty) {
438442
return AnalysisDriverPriority.interactive;
439443
}
440-
if (_referencingNameTasks.isNotEmpty) {
444+
if (_definingClassMemberNameRequests.isNotEmpty) {
445+
return AnalysisDriverPriority.interactive;
446+
}
447+
if (_referencingNameRequests.isNotEmpty) {
441448
return AnalysisDriverPriority.interactive;
442449
}
443450
if (_errorsRequestedFiles.isNotEmpty) {
@@ -488,7 +495,8 @@ class AnalysisDriver {
488495
_requestedLibraries.isNotEmpty ||
489496
_requestedFiles.isNotEmpty ||
490497
_errorsRequestedFiles.isNotEmpty ||
491-
_referencingNameTasks.isNotEmpty ||
498+
_definingClassMemberNameRequests.isNotEmpty ||
499+
_referencingNameRequests.isNotEmpty ||
492500
_indexRequestedFiles.isNotEmpty ||
493501
_unitElementRequestedFiles.isNotEmpty ||
494502
_disposeRequests.isNotEmpty;
@@ -783,36 +791,19 @@ class AnalysisDriver {
783791
/// Completes with files that define a class member with the [name].
784792
Future<List<FileState>> getFilesDefiningClassMemberName(String name) async {
785793
await discoverAvailableFiles();
786-
787-
// Get library elements, so macro generated files are added.
788-
for (var file in knownFiles.toList()) {
789-
await getLibraryByUri(file.uriStr);
790-
}
791-
792-
var definingFiles = <FileState>[];
793-
for (var file in knownFiles) {
794-
if (file.definedClassMemberNames.contains(name)) {
795-
definingFiles.add(file);
796-
}
797-
}
798-
799-
return definingFiles;
800-
}
801-
802-
/// Return a [Future] that completes with the list of known files that
803-
/// reference the given external [name].
804-
Future<List<String>> getFilesReferencingName(String name) {
805-
discoverAvailableFiles();
806-
var task = _FilesReferencingNameTask(this, name);
807-
_referencingNameTasks.add(task);
794+
var request = _GetFilesDefiningClassMemberNameRequest(name);
795+
_definingClassMemberNameRequests.add(request);
808796
_scheduler.notify();
809-
return task.completer.future;
797+
return request.completer.future;
810798
}
811799

812-
/// See [getFilesReferencingName].
813-
Future<List<File>> getFilesReferencingName2(String name) async {
814-
final pathList = await getFilesReferencingName(name);
815-
return pathList.map((path) => resourceProvider.getFile(path)).toList();
800+
/// Completes with files that reference the given external [name].
801+
Future<List<FileState>> getFilesReferencingName(String name) async {
802+
await discoverAvailableFiles();
803+
var request = _GetFilesReferencingNameRequest(name);
804+
_referencingNameRequests.add(request);
805+
_scheduler.notify();
806+
return request.completer.future;
816807
}
817808

818809
/// Return the [FileResult] for the Dart file with the given [path].
@@ -1223,12 +1214,15 @@ class AnalysisDriver {
12231214
return;
12241215
}
12251216

1217+
// Compute files defining a class member.
1218+
if (_definingClassMemberNameRequests.removeLastOrNull() case var request?) {
1219+
await _getFilesDefiningClassMemberName(request);
1220+
return;
1221+
}
1222+
12261223
// Compute files referencing a name.
1227-
if (_referencingNameTasks.firstOrNull case var task?) {
1228-
bool isDone = task.perform();
1229-
if (isDone) {
1230-
_referencingNameTasks.remove(task);
1231-
}
1224+
if (_referencingNameRequests.removeLastOrNull() case var request?) {
1225+
await _getFilesReferencingName(request);
12321226
return;
12331227
}
12341228

@@ -1637,6 +1631,24 @@ class AnalysisDriver {
16371631
}
16381632
}
16391633

1634+
Future<void> _ensureMacroGeneratedFiles() async {
1635+
for (var file in knownFiles.toList()) {
1636+
if (file.kind case LibraryFileKind libraryKind) {
1637+
var libraryCycle = libraryKind.libraryCycle;
1638+
if (libraryCycle.importsMacroClass) {
1639+
if (!libraryCycle.hasMacroFilesCreated) {
1640+
libraryCycle.hasMacroFilesCreated = true;
1641+
// We create macro-generated FileState(s) when load bundles.
1642+
await libraryContext.load(
1643+
targetLibrary: libraryKind,
1644+
performance: OperationPerformanceImpl('<root>'),
1645+
);
1646+
}
1647+
}
1648+
}
1649+
}
1650+
}
1651+
16401652
void _fillSalt() {
16411653
_fillSaltForUnlinked();
16421654
_fillSaltForElements();
@@ -1707,6 +1719,34 @@ class AnalysisDriver {
17071719
return errors;
17081720
}
17091721

1722+
Future<void> _getFilesDefiningClassMemberName(
1723+
_GetFilesDefiningClassMemberNameRequest request,
1724+
) async {
1725+
await _ensureMacroGeneratedFiles();
1726+
1727+
var result = <FileState>[];
1728+
for (var file in knownFiles) {
1729+
if (file.definedClassMemberNames.contains(request.name)) {
1730+
result.add(file);
1731+
}
1732+
}
1733+
request.completer.complete(result);
1734+
}
1735+
1736+
Future<void> _getFilesReferencingName(
1737+
_GetFilesReferencingNameRequest request,
1738+
) async {
1739+
await _ensureMacroGeneratedFiles();
1740+
1741+
var result = <FileState>[];
1742+
for (var file in knownFiles) {
1743+
if (file.referencedNames.contains(request.name)) {
1744+
result.add(file);
1745+
}
1746+
}
1747+
request.completer.complete(result);
1748+
}
1749+
17101750
Future<void> _getIndex(String path) async {
17111751
final file = _fsState.getFileForPath(path);
17121752

@@ -2518,62 +2558,18 @@ class _FileChange {
25182558

25192559
enum _FileChangeKind { add, change, remove }
25202560

2521-
/// Task that computes the list of files that were added to the driver and
2522-
/// have at least one reference to an identifier [name] defined outside of the
2523-
/// file.
2524-
class _FilesReferencingNameTask {
2525-
static const int _WORK_FILES = 100;
2526-
static const int _MS_WORK_INTERVAL = 5;
2527-
2528-
final AnalysisDriver driver;
2561+
class _GetFilesDefiningClassMemberNameRequest {
25292562
final String name;
2530-
final Completer<List<String>> completer = Completer<List<String>>();
2563+
final completer = Completer<List<FileState>>();
25312564

2532-
int fileStamp = -1;
2533-
List<FileState>? filesToCheck;
2534-
int filesToCheckIndex = -1;
2535-
2536-
final List<String> referencingFiles = <String>[];
2537-
2538-
_FilesReferencingNameTask(this.driver, this.name);
2539-
2540-
/// Perform work for a fixed length of time, and complete the [completer] to
2541-
/// either return `true` to indicate that the task is done, or return `false`
2542-
/// to indicate that the task should continue to be run.
2543-
///
2544-
/// Each invocation of an asynchronous method has overhead, which looks as
2545-
/// `_SyncCompleter.complete` invocation, we see as much as 62% in some
2546-
/// scenarios. Instead we use a fixed length of time, so we can spend less time
2547-
/// overall and keep quick enough response time.
2548-
bool perform() {
2549-
if (driver._fsState.fileStamp != fileStamp) {
2550-
filesToCheck = null;
2551-
referencingFiles.clear();
2552-
}
2553-
2554-
// Prepare files to check.
2555-
if (filesToCheck == null) {
2556-
fileStamp = driver._fsState.fileStamp;
2557-
filesToCheck = driver._fsState.knownFiles.toList();
2558-
filesToCheckIndex = 0;
2559-
}
2565+
_GetFilesDefiningClassMemberNameRequest(this.name);
2566+
}
25602567

2561-
Stopwatch timer = Stopwatch()..start();
2562-
while (filesToCheckIndex < filesToCheck!.length) {
2563-
if (filesToCheckIndex % _WORK_FILES == 0 &&
2564-
timer.elapsedMilliseconds > _MS_WORK_INTERVAL) {
2565-
return false;
2566-
}
2567-
FileState file = filesToCheck![filesToCheckIndex++];
2568-
if (file.referencedNames.contains(name)) {
2569-
referencingFiles.add(file.path);
2570-
}
2571-
}
2568+
class _GetFilesReferencingNameRequest {
2569+
final String name;
2570+
final completer = Completer<List<FileState>>();
25722571

2573-
// If no more files to check, complete and done.
2574-
completer.complete(referencingFiles);
2575-
return true;
2576-
}
2572+
_GetFilesReferencingNameRequest(this.name);
25772573
}
25782574

25792575
class _ResolveForCompletionRequest {

pkg/analyzer/lib/src/dart/analysis/library_graph.dart

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class LibraryCycle {
5555
/// include [implSignature] of the macro defining library.
5656
String implSignature;
5757

58-
late final bool hasMacroClass = () {
58+
late final bool declaresMacroClass = () {
5959
for (final library in libraries) {
6060
for (final file in library.files) {
6161
if (file.unlinked2.macroClasses.isNotEmpty) {
@@ -71,6 +71,21 @@ class LibraryCycle {
7171
/// imported into a cycle that declares one.
7272
bool mightBeExecutedByMacroClass = false;
7373

74+
/// If a cycle imports a library that declares a macro, then it can have
75+
/// macro applications, and so macro-generated files.
76+
late final bool importsMacroClass = () {
77+
for (final dependency in directDependencies) {
78+
if (dependency.declaresMacroClass) {
79+
return true;
80+
}
81+
}
82+
return false;
83+
}();
84+
85+
/// Set to `true` if this library cycle [importsMacroClass], and we have
86+
/// already created macro generated [FileState]s.
87+
bool hasMacroFilesCreated = false;
88+
7489
LibraryCycle({
7590
required this.libraries,
7691
required this.directDependencies,
@@ -229,7 +244,7 @@ class _LibraryWalker extends graph.DependencyWalker<_LibraryNode> {
229244
implSignature: implSignature.toHex(),
230245
);
231246

232-
if (cycle.hasMacroClass) {
247+
if (cycle.declaresMacroClass) {
233248
cycle.markMightBeExecutedByMacroClass();
234249
}
235250

@@ -259,7 +274,7 @@ class _LibraryWalker extends graph.DependencyWalker<_LibraryNode> {
259274

260275
if (directDependencies.add(referencedCycle)) {
261276
apiSignature.addString(
262-
referencedCycle.hasMacroClass
277+
referencedCycle.declaresMacroClass
263278
? referencedCycle.implSignature
264279
: referencedCycle.apiSignature,
265280
);

pkg/analyzer/lib/src/dart/analysis/search.dart

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -495,13 +495,13 @@ class Search {
495495
}
496496

497497
// Prepare the list of files that reference the name.
498-
List<String> files = await _driver.getFilesReferencingName(name);
498+
var files = await _driver.getFilesReferencingName(name);
499499

500500
// Check the index of every file that references the element name.
501501
List<SearchResult> results = [];
502-
for (String file in files) {
503-
if (searchedFiles.add(file, this)) {
504-
var index = await _driver.getIndex(file);
502+
for (var file in files) {
503+
if (searchedFiles.add(file.path, this)) {
504+
var index = await _driver.getIndex(file.path);
505505
if (index != null) {
506506
_IndexRequest request = _IndexRequest(index);
507507
var fileResults = await request.getUnresolvedMemberReferences(
@@ -512,7 +512,7 @@ class Search {
512512
IndexRelationKind.IS_READ_WRITTEN_BY: SearchResultKind.READ_WRITE,
513513
IndexRelationKind.IS_INVOKED_BY: SearchResultKind.INVOCATION
514514
},
515-
() => _getUnitElement(file),
515+
() => _getUnitElement(file.path),
516516
);
517517
results.addAll(fileResults);
518518
}
@@ -534,18 +534,23 @@ class Search {
534534
name = element.enclosingElement.displayName;
535535
}
536536

537+
var elementPath = element.source!.fullName;
538+
var elementFile = _driver.fsState.getExistingFromPath(elementPath);
539+
if (elementFile == null) {
540+
return;
541+
}
542+
537543
// Prepare the list of files that reference the element name.
538-
List<String> files = <String>[];
539-
String path = element.source!.fullName;
544+
var files = <FileState>[];
540545
if (name.startsWith('_')) {
541546
String libraryPath = element.library!.source.fullName;
542547
if (searchedFiles.add(libraryPath, this)) {
543548
final libraryFile = _driver.fsState.getFileForPath(libraryPath);
544549
final libraryKind = libraryFile.kind;
545550
if (libraryKind is LibraryFileKind) {
546551
for (final file in libraryKind.files) {
547-
if (file.path == path || file.referencedNames.contains(name)) {
548-
files.add(file.path);
552+
if (file == elementFile || file.referencedNames.contains(name)) {
553+
files.add(file);
549554
}
550555
}
551556
}
@@ -554,21 +559,24 @@ class Search {
554559
if (filesToCheck != null) {
555560
for (FileState file in filesToCheck) {
556561
if (file.referencedNames.contains(name)) {
557-
files.add(file.path);
562+
files.add(file);
558563
}
559564
}
560565
} else {
561566
files = await _driver.getFilesReferencingName(name);
562567
}
563-
if (searchedFiles.add(path, this) && !files.contains(path)) {
564-
files.add(path);
568+
if (searchedFiles.add(elementFile.path, this)) {
569+
if (!files.contains(elementFile)) {
570+
files.add(elementFile);
571+
}
565572
}
566573
}
567574

568575
// Check the index of every file that references the element name.
569-
for (String file in files) {
570-
if (searchedFiles.add(file, this)) {
571-
await _addResultsInFile(results, element, relationToResultKind, file);
576+
for (var file in files) {
577+
if (searchedFiles.add(file.path, this)) {
578+
await _addResultsInFile(
579+
results, element, relationToResultKind, file.path);
572580
}
573581
}
574582
}

0 commit comments

Comments
 (0)