Skip to content

Commit

Permalink
[analysis_server] Skip analysis work when overlays are created if con…
Browse files Browse the repository at this point in the history
…tent matches previous content-

May prevent #48051 from occurring since we will no longer call driver.changeFile() for SDK libraries being opened, although it does not resolve the underlying issue.

Change-Id: I5ca53a04842348a584ccc824aaf90ba7f230c002
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/251980
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
  • Loading branch information
DanTup authored and Commit Bot committed Jul 20, 2022
1 parent 188d473 commit 0add39a
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,6 @@ class TextDocumentOpenHandler
);
server.onOverlayCreated(path, doc.text);

// If the file did not exist, and is "overlay only", it still should be
// analyzed. Add it to driver to which it should have been added.
server.contextManager.getDriverFor(path)?.addFile(path);

await server.addPriorityFile(path);

return success(null);
Expand Down
36 changes: 32 additions & 4 deletions pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
Original file line number Diff line number Diff line change
Expand Up @@ -497,10 +497,33 @@ class LspAnalysisServer extends AbstractAnalysisServer {
}

void onOverlayCreated(String path, String content) {
final currentFile = resourceProvider.getFile(path);
String? currentContent;

try {
currentContent = currentFile.readAsStringSync();
} on FileSystemException {
// It's possible we're creating an overlay for a file that doesn't yet
// exist on disk so must handle missing file exceptions. Checking for
// exists first would introduce a race.
}

resourceProvider.setOverlay(path,
content: content, modificationStamp: overlayModificationStamp++);

_afterOverlayChanged(path, plugin.AddContentOverlay(content));
// If the overlay is exactly the same as the previous content we can skip
// notifying drivers which avoids re-analyzing the same content.
if (content != currentContent) {
_afterOverlayChanged(path, plugin.AddContentOverlay(content));

// If the file did not exist, and is "overlay only", it still should be
// analyzed. Add it to driver to which it should have been added.
contextManager.getDriverFor(path)?.addFile(path);
} else {
// If we skip the work above, we still need to ensure plugins are notified
// of the new overlay (which usually happens in `_afterOverlayChanged`).
_notifyPluginsOverlayChanged(path, plugin.AddContentOverlay(content));
}
}

void onOverlayDestroyed(String path) {
Expand Down Expand Up @@ -772,9 +795,7 @@ class LspAnalysisServer extends AbstractAnalysisServer {
for (var driver in driverMap.values) {
driver.changeFile(path);
}
pluginManager.setAnalysisUpdateContentParams(
plugin.AnalysisUpdateContentParams({path: changeForPlugins}),
);
_notifyPluginsOverlayChanged(path, changeForPlugins);

notifyDeclarationsTracker(path);
notifyFlutterWidgetDescriptions(path);
Expand Down Expand Up @@ -834,6 +855,13 @@ class LspAnalysisServer extends AbstractAnalysisServer {
}
}

void _notifyPluginsOverlayChanged(
String path, plugin.HasToJson changeForPlugins) {
pluginManager.setAnalysisUpdateContentParams(
plugin.AnalysisUpdateContentParams({path: changeForPlugins}),
);
}

void _onPluginsChanged() {
capabilitiesComputer.performDynamicRegistration();
}
Expand Down
43 changes: 43 additions & 0 deletions pkg/analysis_server/test/lsp/document_changes_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,49 @@ class Bar {
expect(driverForInside.addedFiles, isNot(contains(fileOutsideRootPath)));
}

Future<void> test_documentOpen_contentChanged_analysis() async {
const content = '// original content';
const newContent = '// new content';
newFile(mainFilePath, content);

// Wait for initial analysis to provide diagnostics for the file.
await Future.wait([
waitForDiagnostics(mainFileUri),
initialize(),
]);

// Capture any further diagnostics sent after we open the file.
List<Diagnostic>? diagnostics;
unawaited(waitForDiagnostics(mainFileUri).then((d) => diagnostics = d));
await openFile(mainFileUri, newContent);
await pumpEventQueue(times: 5000);

// Expect diagnostics, because changing the content will have triggered
// analysis.
expect(diagnostics, isNotNull);
}

Future<void> test_documentOpen_contentUnchanged_noAnalysis() async {
const content = '// original content';
newFile(mainFilePath, content);

// Wait for initial analysis to provide diagnostics for the file.
await Future.wait([
waitForDiagnostics(mainFileUri),
initialize(),
]);

// Capture any further diagnostics sent after we open the file.
List<Diagnostic>? diagnostics;
unawaited(waitForDiagnostics(mainFileUri).then((d) => diagnostics = d));
await openFile(mainFileUri, content);
await pumpEventQueue(times: 5000);

// Expect no diagnostics because the file didn't actually change content
// when the overlay was created, so it should not have triggered analysis.
expect(diagnostics, isNull);
}

Future<void> test_documentOpen_createsOverlay() async {
await _initializeAndOpen();

Expand Down

0 comments on commit 0add39a

Please sign in to comment.