From 8abed3bd78200fc5f7e3890fd853c17ce518d157 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matou=C5=A1=20Dzivjak?= <matousdzivjak@gmail.com>
Date: Fri, 9 Dec 2022 04:57:03 +0100
Subject: [PATCH] feat(lsp): pass client_info on initialization (#4904)

Pass client name ('helix') and client version (version / git hash)
to LSP server on initialization.
---
 Cargo.lock              |  1 +
 helix-loader/build.rs   | 20 ++++++++++++++++++++
 helix-loader/src/lib.rs |  2 ++
 helix-lsp/Cargo.toml    |  1 +
 helix-lsp/src/client.rs |  6 +++++-
 helix-term/build.rs     | 21 ---------------------
 helix-term/src/main.rs  |  5 +++--
 7 files changed, 32 insertions(+), 24 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 014834e4..b204214f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1187,6 +1187,7 @@ dependencies = [
  "futures-executor",
  "futures-util",
  "helix-core",
+ "helix-loader",
  "log",
  "lsp-types",
  "serde",
diff --git a/helix-loader/build.rs b/helix-loader/build.rs
index e0ebd1c4..c4b89e6b 100644
--- a/helix-loader/build.rs
+++ b/helix-loader/build.rs
@@ -1,6 +1,26 @@
+use std::borrow::Cow;
+use std::process::Command;
+
+const VERSION: &str = include_str!("../VERSION");
+
 fn main() {
+    let git_hash = Command::new("git")
+        .args(["rev-parse", "HEAD"])
+        .output()
+        .ok()
+        .filter(|output| output.status.success())
+        .and_then(|x| String::from_utf8(x.stdout).ok());
+
+    let version: Cow<_> = match git_hash {
+        Some(git_hash) => format!("{} ({})", VERSION, &git_hash[..8]).into(),
+        None => VERSION.into(),
+    };
+
     println!(
         "cargo:rustc-env=BUILD_TARGET={}",
         std::env::var("TARGET").unwrap()
     );
+
+    println!("cargo:rerun-if-changed=../VERSION");
+    println!("cargo:rustc-env=VERSION_AND_GIT_HASH={}", version);
 }
diff --git a/helix-loader/src/lib.rs b/helix-loader/src/lib.rs
index a02a59af..29a9f2e7 100644
--- a/helix-loader/src/lib.rs
+++ b/helix-loader/src/lib.rs
@@ -4,6 +4,8 @@ pub mod grammar;
 use etcetera::base_strategy::{choose_base_strategy, BaseStrategy};
 use std::path::PathBuf;
 
+pub const VERSION_AND_GIT_HASH: &str = env!("VERSION_AND_GIT_HASH");
+
 pub static RUNTIME_DIR: once_cell::sync::Lazy<PathBuf> = once_cell::sync::Lazy::new(runtime_dir);
 
 static CONFIG_FILE: once_cell::sync::OnceCell<PathBuf> = once_cell::sync::OnceCell::new();
diff --git a/helix-lsp/Cargo.toml b/helix-lsp/Cargo.toml
index 41884e73..05c5467e 100644
--- a/helix-lsp/Cargo.toml
+++ b/helix-lsp/Cargo.toml
@@ -13,6 +13,7 @@ homepage = "https://helix-editor.com"
 
 [dependencies]
 helix-core = { version = "0.6", path = "../helix-core" }
+helix-loader = { version = "0.6", path = "../helix-loader" }
 
 anyhow = "1.0"
 futures-executor = "0.3"
diff --git a/helix-lsp/src/client.rs b/helix-lsp/src/client.rs
index 2c2c7c88..90fd2f21 100644
--- a/helix-lsp/src/client.rs
+++ b/helix-lsp/src/client.rs
@@ -5,6 +5,7 @@ use crate::{
 };
 
 use helix_core::{find_root, ChangeSet, Rope};
+use helix_loader::{self, VERSION_AND_GIT_HASH};
 use lsp_types as lsp;
 use serde::Deserialize;
 use serde_json::Value;
@@ -376,7 +377,10 @@ impl Client {
                 ..Default::default()
             },
             trace: None,
-            client_info: None,
+            client_info: Some(lsp::ClientInfo {
+                name: String::from("helix"),
+                version: Some(String::from(VERSION_AND_GIT_HASH)),
+            }),
             locale: None, // TODO
         };
 
diff --git a/helix-term/build.rs b/helix-term/build.rs
index 719113ff..b47dae8e 100644
--- a/helix-term/build.rs
+++ b/helix-term/build.rs
@@ -1,30 +1,9 @@
 use helix_loader::grammar::{build_grammars, fetch_grammars};
-use std::borrow::Cow;
-use std::process::Command;
-
-const VERSION: &str = include_str!("../VERSION");
 
 fn main() {
-    let git_hash = Command::new("git")
-        .args(["rev-parse", "HEAD"])
-        .output()
-        .ok()
-        .filter(|output| output.status.success())
-        .and_then(|x| String::from_utf8(x.stdout).ok());
-
-    let version: Cow<_> = match git_hash {
-        Some(git_hash) => format!("{} ({})", VERSION, &git_hash[..8]).into(),
-        None => VERSION.into(),
-    };
-
     if std::env::var("HELIX_DISABLE_AUTO_GRAMMAR_BUILD").is_err() {
         fetch_grammars().expect("Failed to fetch tree-sitter grammars");
         build_grammars(Some(std::env::var("TARGET").unwrap()))
             .expect("Failed to compile tree-sitter grammars");
     }
-
-    println!("cargo:rerun-if-changed=../runtime/grammars/");
-    println!("cargo:rerun-if-changed=../VERSION");
-
-    println!("cargo:rustc-env=VERSION_AND_GIT_HASH={}", version);
 }
diff --git a/helix-term/src/main.rs b/helix-term/src/main.rs
index 96b695c6..aac5c537 100644
--- a/helix-term/src/main.rs
+++ b/helix-term/src/main.rs
@@ -1,5 +1,6 @@
 use anyhow::{Context, Error, Result};
 use crossterm::event::EventStream;
+use helix_loader::VERSION_AND_GIT_HASH;
 use helix_term::application::Application;
 use helix_term::args::Args;
 use helix_term::config::Config;
@@ -74,7 +75,7 @@ FLAGS:
     --hsplit                       Splits all given files horizontally into different windows
 ",
         env!("CARGO_PKG_NAME"),
-        env!("VERSION_AND_GIT_HASH"),
+        VERSION_AND_GIT_HASH,
         env!("CARGO_PKG_AUTHORS"),
         env!("CARGO_PKG_DESCRIPTION"),
         logpath.display(),
@@ -89,7 +90,7 @@ FLAGS:
     }
 
     if args.display_version {
-        println!("helix {}", env!("VERSION_AND_GIT_HASH"));
+        println!("helix {}", VERSION_AND_GIT_HASH);
         std::process::exit(0);
     }