From 93ab97f274de5daec48f8d55744ee2377413e6fd Mon Sep 17 00:00:00 2001 From: Alan Zimmerman Date: Thu, 22 Aug 2024 09:28:33 -0700 Subject: [PATCH] Disable eqwalizer for OTP < 26 (#48) Summary: Pull Request resolved: https://github.com/WhatsApp/erlang-language-platform/pull/48 OSS users want to use ELP with OTP < 26. But eqwalizer does not support this. So disable eqwalizer diagnostics in this case. Reviewed By: robertoaloi Differential Revision: D61660600 fbshipit-source-id: 0c1188f60f784b3fb278c05cb4922d4ae24a4bc2 --- crates/base_db/src/fixture.rs | 34 ++------------------ crates/ide_db/src/eqwalizer.rs | 11 +++++++ crates/project_model/src/otp.rs | 55 +++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 32 deletions(-) diff --git a/crates/base_db/src/fixture.rs b/crates/base_db/src/fixture.rs index a8b5841a5..8f36c205b 100644 --- a/crates/base_db/src/fixture.rs +++ b/crates/base_db/src/fixture.rs @@ -19,12 +19,13 @@ use std::fs; use std::fs::File; use std::io::Write; use std::path::Path; -use std::path::PathBuf; use std::sync::Arc; use elp_project_model::buck::BuckQueryConfig; use elp_project_model::json::JsonConfig; use elp_project_model::otp::Otp; +use elp_project_model::otp::OTP_ERLANG_APP; +use elp_project_model::otp::OTP_ERLANG_MODULE; use elp_project_model::rebar::RebarProject; use elp_project_model::temp_dir::TempDir; use elp_project_model::test_fixture::DiagnosticsEnabled; @@ -41,7 +42,6 @@ use fxhash::FxHashMap; use lazy_static::lazy_static; use paths::AbsPathBuf; use paths::Utf8Path; -use paths::Utf8PathBuf; use regex::Regex; use vfs::file_set::FileSet; use vfs::FileId; @@ -402,36 +402,6 @@ fn inc_file_id(file_id: &mut FileId) { *file_id = FileId::from_raw(file_id.index() + 1); } -lazy_static! { - pub static ref OTP_ROOT: Utf8PathBuf = - Otp::find_otp().expect("tests should always be able to find OTP"); - pub static ref OTP_ERTS_DIR: AbsPathBuf = get_erts_dir(); - pub static ref OTP_ERLANG_MODULE: (PathBuf, String) = get_erlang_module(); - pub static ref OTP_ERLANG_APP: ProjectAppData = ProjectAppData::fixture_app_data( - AppName("erts".to_string()), - OTP_ERTS_DIR.clone(), - Vec::default(), - vec![OTP_ERTS_DIR.join("src")], - Vec::default(), - ); -} - -fn get_erts_dir() -> AbsPathBuf { - let (_otp, apps) = Otp::discover(OTP_ROOT.to_path_buf()); - for app in apps { - if app.name == AppName("erts".to_string()) { - return app.dir; - } - } - panic!() -} - -fn get_erlang_module() -> (PathBuf, String) { - let erlang_path = OTP_ERTS_DIR.join("src/erlang.erl"); - let contents = std::fs::read_to_string(&erlang_path).unwrap(); - (erlang_path.into(), contents) -} - #[derive(Debug, Clone, Default)] pub struct AppMap { app_map: FxHashMap, diff --git a/crates/ide_db/src/eqwalizer.rs b/crates/ide_db/src/eqwalizer.rs index d20fe026f..77533db1e 100644 --- a/crates/ide_db/src/eqwalizer.rs +++ b/crates/ide_db/src/eqwalizer.rs @@ -28,6 +28,7 @@ use elp_eqwalizer::ipc::IpcHandle; use elp_eqwalizer::EqwalizerDiagnostic; use elp_eqwalizer::EqwalizerDiagnostics; use elp_eqwalizer::EqwalizerDiagnosticsDatabase; +use elp_project_model::otp::OTP_VERSION; use elp_syntax::ast; use elp_syntax::SmolStr; use elp_types_db::eqwalizer; @@ -154,6 +155,9 @@ fn is_eqwalizer_enabled( file_id: FileId, include_generated: bool, ) -> bool { + if !otp_supported_by_eqwalizer() { + return false; + } if !include_generated && db.is_generated(file_id) { return false; } @@ -178,6 +182,13 @@ fn is_eqwalizer_enabled( opt_in && !ignored } +fn otp_supported_by_eqwalizer() -> bool { + OTP_VERSION + .as_ref() + .and_then(|v| Some(v.as_str() > "25")) + .unwrap_or(true) +} + fn has_eqwalizer_app_marker(db: &dyn EqwalizerDatabase, source_root_id: SourceRootId) -> bool { if let Some(app_data) = db.app_data(source_root_id) { let source_root = db.source_root(source_root_id); diff --git a/crates/project_model/src/otp.rs b/crates/project_model/src/otp.rs index 3388a4428..0527617d5 100644 --- a/crates/project_model/src/otp.rs +++ b/crates/project_model/src/otp.rs @@ -8,6 +8,7 @@ */ use std::fs; +use std::path::PathBuf; use std::process::Command; use std::sync::RwLock; @@ -19,6 +20,7 @@ use paths::AbsPathBuf; use paths::Utf8Path; use paths::Utf8PathBuf; +use crate::AppName; use crate::ProjectAppData; #[derive(Debug, Clone, PartialEq, Eq)] @@ -30,6 +32,37 @@ lazy_static! { pub static ref ERL: RwLock = RwLock::new("erl".to_string()); } +lazy_static! { + pub static ref OTP_ROOT: Utf8PathBuf = + Otp::find_otp().expect("tests should always be able to find OTP"); + pub static ref OTP_ERTS_DIR: AbsPathBuf = get_erts_dir(); + pub static ref OTP_ERLANG_MODULE: (PathBuf, String) = get_erlang_module(); + pub static ref OTP_ERLANG_APP: ProjectAppData = ProjectAppData::fixture_app_data( + AppName("erts".to_string()), + OTP_ERTS_DIR.clone(), + Vec::default(), + vec![OTP_ERTS_DIR.join("src")], + Vec::default(), + ); + pub static ref OTP_VERSION: Option = Otp::otp_version().ok(); +} + +fn get_erts_dir() -> AbsPathBuf { + let (_otp, apps) = Otp::discover(OTP_ROOT.to_path_buf()); + for app in apps { + if app.name == AppName("erts".to_string()) { + return app.dir; + } + } + panic!() +} + +fn get_erlang_module() -> (PathBuf, String) { + let erlang_path = OTP_ERTS_DIR.join("src/erlang.erl"); + let contents = std::fs::read_to_string(&erlang_path).unwrap(); + (erlang_path.into(), contents) +} + impl Otp { pub fn find_otp() -> Result { let _timer = timeit!("find otp"); @@ -55,6 +88,28 @@ impl Otp { let result = fs::canonicalize(result)?; Ok(Utf8PathBuf::from_path_buf(result).expect("Could not create Utf8PathBuf")) } + pub fn otp_version() -> Result { + let _timer = timeit!("otp_version"); + let erl = ERL.read().unwrap(); + let output = Command::new(&*erl) + .arg("-noshell") + .arg("-eval") + .arg("io:format('~s', [erlang:system_info(otp_release)])") + .arg("-s") + .arg("erlang") + .arg("halt") + .output()?; + + if !output.status.success() { + bail!( + "Failed to get OTP version, error code: {:?}, stderr: {:?}", + output.status.code(), + String::from_utf8(output.stderr) + ); + } + let val = String::from_utf8(output.stdout)?; + Ok(val) + } pub fn discover(path: Utf8PathBuf) -> (Otp, Vec) { let apps = Self::discover_otp_apps(&path);