diff --git a/pkg/analysis_server/lib/src/lsp/client_configuration.dart b/pkg/analysis_server/lib/src/lsp/client_configuration.dart index 1b3ed6b3bd5..5e8d2af5711 100644 --- a/pkg/analysis_server/lib/src/lsp/client_configuration.dart +++ b/pkg/analysis_server/lib/src/lsp/client_configuration.dart @@ -38,11 +38,24 @@ class LspClientConfiguration { /// Returns the global configuration for the whole workspace. LspGlobalClientConfiguration get global => _globalSettings; + /// Returns whether or not the provided new configuration changes any values + /// that would affect analysis results. + bool affectsAnalysisResults(LspGlobalClientConfiguration otherConfig) { + // Check whether TODO settings have changed. + final oldFlag = _globalSettings.showAllTodos; + final newFlag = otherConfig.showAllTodos; + final oldTypes = _globalSettings.showTodoTypes; + final newTypes = otherConfig.showTodoTypes; + return newFlag != oldFlag || + !const SetEquality().equals(oldTypes, newTypes); + } + /// Returns whether or not the provided new configuration changes any values /// that would require analysis roots to be updated. bool affectsAnalysisRoots(LspGlobalClientConfiguration otherConfig) { - return _globalSettings.analysisExcludedFolders != - otherConfig.analysisExcludedFolders; + final oldExclusions = _globalSettings.analysisExcludedFolders; + final newExclusions = otherConfig.analysisExcludedFolders; + return !const ListEquality().equals(oldExclusions, newExclusions); } /// Returns config for a given resource. diff --git a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart index 17428de8508..f38a45cc503 100644 --- a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart +++ b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart @@ -272,6 +272,11 @@ class LspAnalysisServer extends AnalysisServer { if (clientConfiguration.affectsAnalysisRoots(oldGlobalConfig)) { await _refreshAnalysisRoots(); + } else if (clientConfiguration + .affectsAnalysisResults(oldGlobalConfig)) { + // Some settings affect analysis results and require re-analysis + // (such as showTodos). + await reanalyze(); } } } diff --git a/pkg/analysis_server/test/lsp/diagnostic_test.dart b/pkg/analysis_server/test/lsp/diagnostic_test.dart index 73424db8486..5c11923fd34 100644 --- a/pkg/analysis_server/test/lsp/diagnostic_test.dart +++ b/pkg/analysis_server/test/lsp/diagnostic_test.dart @@ -531,12 +531,24 @@ analyzer: // Ensure initial analysis completely finished before we continue. await initialAnalysis; - // Enable showTodos and update the file to ensure TODOs now come through. - final secondDiagnosticsUpdate = waitForDiagnostics(mainFileUri); + // Capture any diagnostic updates. We might get multiple, because during + // a reanalyze, all diagnostics are flushed (to empty) and then analysis + // occurs. + List? latestDiagnostics; + notificationsFromServer + .where((notification) => + notification.method == Method.textDocument_publishDiagnostics) + .map((notification) => PublishDiagnosticsParams.fromJson( + notification.params as Map)) + .where((diagnostics) => diagnostics.uri == mainFileUri) + .listen((diagnostics) { + latestDiagnostics = diagnostics.diagnostics; + }); + + final nextAnalysis = waitForAnalysisComplete(); await updateConfig({'showTodos': true}); - await replaceFile(222, mainFileUri, contents); - final updatedDiagnostics = await secondDiagnosticsUpdate; - expect(updatedDiagnostics, hasLength(1)); + await nextAnalysis; + expect(latestDiagnostics, hasLength(1)); } Future test_todos_specific() async {