[analysis_server] Don't use Dart analysis driver to obtain LineInfos for non-Dart files

Change-Id: I80eead30caecf855385b5cc6c2cd7995de8a9349
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/223880
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
index 10e4cf9..d2bd74d 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
@@ -65,8 +65,9 @@
     final unit = await path.mapResult(requireResolvedUnit);
 
     final lineInfo = await unit.map(
-      // If we don't have a unit, we can still try to obtain the line info for
-      // plugin contributors.
+      // If we don't have a unit, we can still try to obtain the line info from
+      // the server (this could be because the file is non-Dart, such as YAML or
+      // another handled by a plugin).
       (error) => path.mapResult(getLineInfo),
       (unit) => success(unit.lineInfo),
     );
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 55a9da8..e4e8d17 100644
--- a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
+++ b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
@@ -261,12 +261,23 @@
     capabilitiesComputer.performDynamicRegistration();
   }
 
-  /// Return the LineInfo for the file with the given [path]. The file is
-  /// analyzed in one of the analysis drivers to which the file was added,
-  /// otherwise in the first driver, otherwise `null` is returned.
+  /// Return a [LineInfo] for the file with the given [path].
+  ///
+  /// If the file does not exist or cannot be read, returns `null`.
+  ///
+  /// This method supports non-Dart files but uses the current content of the
+  /// file which may not be the latest analyzed version of the file if it was
+  /// recently modified, so using the lineInfo from an analyzed result may be
+  /// preferable.
   LineInfo? getLineInfo(String path) {
-    var result = getAnalysisDriver(path)?.getFileSync(path);
-    return result is FileResult ? result.lineInfo : null;
+    try {
+      final content = resourceProvider.getFile(path).readAsStringSync();
+      return LineInfo.fromContent(content);
+    } on FileSystemException {
+      // If the file does not exist or cannot be read, return null to allow
+      // the caller to decide how to handle this.
+      return null;
+    }
   }
 
   /// Gets the version of a document known to the server, returning a
diff --git a/pkg/analysis_server/lib/src/lsp/mapping.dart b/pkg/analysis_server/lib/src/lsp/mapping.dart
index ffabd19..8a26c20 100644
--- a/pkg/analysis_server/lib/src/lsp/mapping.dart
+++ b/pkg/analysis_server/lib/src/lsp/mapping.dart
@@ -23,6 +23,7 @@
 import 'package:analyzer/dart/analysis/results.dart' as server;
 import 'package:analyzer/error/error.dart' as server;
 import 'package:analyzer/source/line_info.dart' as server;
+import 'package:analyzer/source/line_info.dart';
 import 'package:analyzer/source/source_range.dart' as server;
 import 'package:analyzer/src/dart/analysis/search.dart' as server
     show DeclarationKind;
@@ -123,8 +124,11 @@
       edits
           .map((e) => FileEditInformation(
                 server.getVersionedDocumentIdentifier(e.file),
-                // We should never produce edits for a file with no LineInfo.
-                server.getLineInfo(e.file)!,
+                // If we expect to create the file, server.getLineInfo() won't
+                // provide a LineInfo so create one from empty contents.
+                e.fileStamp == -1
+                    ? LineInfo.fromContent('')
+                    : server.getLineInfo(e.file)!,
                 e.edits,
                 // fileStamp == 1 is used by the server to indicate the file needs creating.
                 newFile: e.fileStamp == -1,