[clangd] Expose FileStatus to LSP.

Summary:
Add an LSP extension "textDocument/clangd.fileStatus" to emit file-status information.

Reviewers: ilya-biryukov

Subscribers: javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits

Differential Revision: https://reviews.llvm.org/D55363

llvm-svn: 349768
diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp
index a9d1795..012302d 100644
--- a/clang-tools-extra/clangd/ClangdLSPServer.cpp
+++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp
@@ -294,7 +294,7 @@
   SupportsCodeAction = Params.capabilities.CodeActionStructure;
   SupportsHierarchicalDocumentSymbol =
       Params.capabilities.HierarchicalDocumentSymbol;
-
+  SupportFileStatus = Params.initializationOptions.FileStatus;
   Reply(json::Object{
       {{"capabilities",
         json::Object{
@@ -802,6 +802,19 @@
          });
 }
 
+void ClangdLSPServer::onFileUpdated(PathRef File, const TUStatus &Status) {
+  if (!SupportFileStatus)
+    return;
+  // FIXME: we don't emit "BuildingFile" and `RunningAction`, as these
+  // two statuses are running faster in practice, which leads the UI constantly
+  // changing, and doesn't provide much value. We may want to emit status at a
+  // reasonable time interval (e.g. 0.5s).
+  if (Status.Action.S == TUAction::BuildingFile ||
+      Status.Action.S == TUAction::RunningAction)
+    return;
+  notify("textDocument/clangd.fileStatus", Status.render(File));
+}
+
 void ClangdLSPServer::reparseOpenedFiles() {
   for (const Path &FilePath : DraftMgr.getActiveFiles())
     Server->addDocument(FilePath, *DraftMgr.getDraft(FilePath),