[analysis_server/lsp] Don't send Flutter outlines for non-Flutter projects

Fixes https://github.com/dart-lang/sdk/issues/44628.

Change-Id: I38e6a9d336f1b90c0030a16b2897557053a7d469
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/275942
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
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 920aa8f..28f15d7 100644
--- a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
+++ b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
@@ -31,6 +31,7 @@
 import 'package:analysis_server/src/server/error_notifier.dart';
 import 'package:analysis_server/src/server/performance.dart';
 import 'package:analysis_server/src/services/refactoring/legacy/refactoring.dart';
+import 'package:analysis_server/src/utilities/flutter.dart';
 import 'package:analysis_server/src/utilities/process.dart';
 import 'package:analyzer/dart/analysis/context_locator.dart';
 import 'package:analyzer/dart/analysis/results.dart';
@@ -722,7 +723,9 @@
   /// given absolute path.
   bool shouldSendFlutterOutlineFor(String file) {
     // Outlines should only be sent for open (priority) files in the workspace.
-    return initializationOptions.flutterOutline && priorityFiles.contains(file);
+    return initializationOptions.flutterOutline &&
+        priorityFiles.contains(file) &&
+        _isInFlutterProject(file);
   }
 
   /// Returns `true` if outlines should be sent for [file] with the given
@@ -862,6 +865,16 @@
     }
   }
 
+  /// Checks whether [file] is in a project that can resolve 'package:flutter'
+  /// libraries.
+  bool _isInFlutterProject(String file) =>
+      contextManager
+          .getDriverFor(file)
+          ?.currentSession
+          .uriConverter
+          .uriToPath(Uri.parse(Flutter.instance.widgetsUri)) !=
+      null;
+
   void _notifyPluginsOverlayChanged(
       String path, plugin.HasToJson changeForPlugins) {
     if (AnalysisServer.supportsPlugins) {
diff --git a/pkg/analysis_server/test/lsp/flutter_outline_test.dart b/pkg/analysis_server/test/lsp/flutter_outline_test.dart
index 3c5fa75..34ba063 100644
--- a/pkg/analysis_server/test/lsp/flutter_outline_test.dart
+++ b/pkg/analysis_server/test/lsp/flutter_outline_test.dart
@@ -11,10 +11,40 @@
 void main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(FlutterOutlineTest);
+    defineReflectiveTests(FlutterOutlineNonFlutterProjectTest);
   });
 }
 
 @reflectiveTest
+class FlutterOutlineNonFlutterProjectTest
+    extends AbstractLspAnalysisServerTest {
+  /// In a project that doesn't reference Flutter, no Flutter outlines should
+  /// be sent.
+  Future<void> test_noOutline() async {
+    final content = 'void f() {}';
+    await initialize(initializationOptions: {'flutterOutline': true});
+
+    // Wait up to 1sec to ensure no error/log notifications were sent back.
+    var didTimeout = false;
+    final outlineNotification = waitForFlutterOutline(mainFileUri)
+        // ignore: unnecessary_cast
+        .then((outline) => outline as FlutterOutline?)
+        .timeout(
+      const Duration(seconds: 1),
+      onTimeout: () {
+        didTimeout = true;
+        return null;
+      },
+    );
+    // Only open files trigger outline notifications.
+    await openFile(mainFileUri, content);
+
+    expect(await outlineNotification, isNull);
+    expect(didTimeout, isTrue);
+  }
+}
+
+@reflectiveTest
 class FlutterOutlineTest extends AbstractLspAnalysisServerTest {
   @override
   void setUp() {