Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(lsp): upgrade check on init and notification #21105

Merged
merged 12 commits into from
Nov 14, 2023
Merged
31 changes: 31 additions & 0 deletions cli/lsp/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,17 @@ impl Client {
});
}

pub fn send_did_upgrade_check_notification(
&self,
params: lsp_custom::DidUpgradeCheckNotificationParams,
) {
// do on a task in case the caller currently is in the lsp lock
let client = self.0.clone();
spawn(async move {
client.send_did_upgrade_check_notification(params).await;
});
}

pub fn show_message(
&self,
message_type: lsp::MessageType,
Expand Down Expand Up @@ -165,6 +176,10 @@ trait ClientTrait: Send + Sync {
&self,
params: lsp_custom::DidChangeDenoConfigurationNotificationParams,
);
async fn send_did_upgrade_check_notification(
&self,
params: lsp_custom::DidUpgradeCheckNotificationParams,
);
async fn workspace_configuration(
&self,
scopes: Vec<Option<lsp::Url>>,
Expand Down Expand Up @@ -249,6 +264,16 @@ impl ClientTrait for TowerClient {
.await
}

async fn send_did_upgrade_check_notification(
&self,
params: lsp_custom::DidUpgradeCheckNotificationParams,
) {
self
.0
.send_notification::<lsp_custom::DidUpgradeCheckNotification>(params)
.await
}

async fn workspace_configuration(
&self,
scopes: Vec<Option<lsp::Url>>,
Expand Down Expand Up @@ -350,6 +375,12 @@ impl ClientTrait for ReplClient {
) {
}

async fn send_did_upgrade_check_notification(
&self,
_params: lsp_custom::DidUpgradeCheckNotificationParams,
) {
}

async fn workspace_configuration(
&self,
scopes: Vec<Option<lsp::Url>>,
Expand Down
21 changes: 21 additions & 0 deletions cli/lsp/language_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ use crate::npm::CliNpmResolverManagedPackageJsonInstallerOption;
use crate::npm::CliNpmResolverManagedSnapshotOption;
use crate::tools::fmt::format_file;
use crate::tools::fmt::format_parsed_source;
use crate::tools::upgrade::check_for_upgrades_for_lsp;
use crate::tools::upgrade::upgrade_check_enabled;
use crate::util::fs::remove_dir_all_if_exists;
use crate::util::path::is_importable_ext;
use crate::util::path::specifier_to_file_path;
Expand Down Expand Up @@ -3189,6 +3191,25 @@ impl tower_lsp::LanguageServer for LanguageServer {
}

lsp_log!("Server ready.");

if upgrade_check_enabled() {
let http_client = self.0.read().await.http_client.clone();
match check_for_upgrades_for_lsp(http_client).await {
Ok(version_info) => {
client.send_did_upgrade_check_notification(
lsp_custom::DidUpgradeCheckNotificationParams {
upgrade_available: version_info.map(
|(latest_version, is_canary)| lsp_custom::UpgradeAvailable {
latest_version,
is_canary,
},
),
},
);
}
Err(err) => lsp_warn!("Failed to check for upgrades: {err}"),
}
}
}

async fn shutdown(&self) -> LspResult<()> {
Expand Down
12 changes: 7 additions & 5 deletions cli/lsp/logging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,13 @@ macro_rules! lsp_log {
/// for downgrading these logs to another log level in the REPL.
macro_rules! lsp_warn {
($($arg:tt)+) => (
let lsp_log_level = $crate::lsp::logging::lsp_warn_level();
if lsp_log_level == log::Level::Debug {
$crate::lsp::logging::lsp_debug!($($arg)+)
} else {
log::log!(lsp_log_level, $($arg)+)
{
let lsp_log_level = $crate::lsp::logging::lsp_warn_level();
if lsp_log_level == log::Level::Debug {
$crate::lsp::logging::lsp_debug!($($arg)+)
} else {
log::log!(lsp_log_level, $($arg)+)
}
}
)
}
Expand Down
21 changes: 21 additions & 0 deletions cli/lsp/lsp_custom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,27 @@ impl lsp::notification::Notification
const METHOD: &'static str = "deno/didChangeDenoConfiguration";
}

pub enum DidUpgradeCheckNotification {}

impl lsp::notification::Notification for DidUpgradeCheckNotification {
type Params = DidUpgradeCheckNotificationParams;

const METHOD: &'static str = "deno/didUpgradeCheck";
}

#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UpgradeAvailable {
pub latest_version: String,
pub is_canary: bool,
}

#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DidUpgradeCheckNotificationParams {
pub upgrade_available: Option<UpgradeAvailable>,
}

/// This notification is only sent for testing purposes
/// in order to know what the latest diagnostics are.
pub enum DiagnosticBatchNotification {}
Expand Down
61 changes: 50 additions & 11 deletions cli/tools/upgrade.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ impl UpdateCheckerEnvironment for RealUpdateCheckerEnvironment {
let http_client = self.http_client.clone();
async move {
if version::is_canary() {
get_latest_canary_version(&http_client).await
get_latest_canary_version(&http_client, false).await
} else {
get_latest_release_version(&http_client).await
get_latest_release_version(&http_client, false).await
}
}
.boxed()
Expand Down Expand Up @@ -186,11 +186,18 @@ fn print_release_notes(current_version: &str, new_version: &str) {
}
}

pub fn upgrade_check_enabled() -> bool {
matches!(
env::var("DENO_NO_UPDATE_CHECK"),
Err(env::VarError::NotPresent)
)
}

pub fn check_for_upgrades(
http_client: Arc<HttpClient>,
cache_file_path: PathBuf,
) {
if env::var("DENO_NO_UPDATE_CHECK").is_ok() {
if !upgrade_check_enabled() {
return;
}

Expand Down Expand Up @@ -239,6 +246,32 @@ pub fn check_for_upgrades(
}
}

pub async fn check_for_upgrades_for_lsp(
http_client: Arc<HttpClient>,
) -> Result<Option<(String, bool)>, AnyError> {
if !upgrade_check_enabled() {
return Ok(None);
}
let is_canary = version::is_canary();
let latest_version;
let mut is_upgrade;
if is_canary {
latest_version = get_latest_canary_version(&http_client, true).await?;
is_upgrade = latest_version != version::GIT_COMMIT_HASH;
} else {
latest_version = get_latest_release_version(&http_client, true).await?;
is_upgrade = true;
if let Ok(current) = Version::parse_standard(version::deno()) {
if let Ok(latest) = Version::parse_standard(&latest_version) {
if current >= latest {
is_upgrade = false;
}
}
}
};
Ok(is_upgrade.then_some((latest_version, is_canary)))
}

async fn fetch_and_store_latest_version<
TEnvironment: UpdateCheckerEnvironment,
>(
Expand Down Expand Up @@ -334,10 +367,10 @@ pub async fn upgrade(
None => {
let latest_version = if upgrade_flags.canary {
log::info!("Looking up latest canary version");
get_latest_canary_version(client).await?
get_latest_canary_version(client, false).await?
} else {
log::info!("Looking up latest version");
get_latest_release_version(client).await?
get_latest_release_version(client, false).await?
};

let current_is_most_recent = if upgrade_flags.canary {
Expand Down Expand Up @@ -448,20 +481,26 @@ pub async fn upgrade(

async fn get_latest_release_version(
client: &HttpClient,
for_lsp: bool,
) -> Result<String, AnyError> {
let text = client
.download_text("https://dl.deno.land/release-latest.txt")
.await?;
let mut url = "https://dl.deno.land/release-latest.txt".to_string();
if for_lsp {
url.push_str("?lsp");
}
let text = client.download_text(url).await?;
let version = text.trim().to_string();
Ok(version.replace('v', ""))
}

async fn get_latest_canary_version(
client: &HttpClient,
for_lsp: bool,
) -> Result<String, AnyError> {
let text = client
.download_text("https://dl.deno.land/canary-latest.txt")
.await?;
let mut url = "https://dl.deno.land/canary-latest.txt".to_string();
if for_lsp {
url.push_str("?lsp");
}
let text = client.download_text(url).await?;
let version = text.trim().to_string();
Ok(version)
}
Expand Down
1 change: 1 addition & 0 deletions test_util/src/lsp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,7 @@ impl LspClientBuilder {
"DENO_DONT_USE_INTERNAL_LSP_DIAGNOSTIC_SYNC_FLAG",
if self.use_diagnostic_sync { "1" } else { "" },
)
.env("DENO_NO_UPDATE_CHECK", "1")
.arg("lsp")
.stdin(Stdio::piped())
.stdout(Stdio::piped());
Expand Down