use crate::{
android::toolchain::{AndroidNdk, AndroidSdk, Java},
apple::toolchain::{AppleSdk, Xcode},
toolchain::Toolchain,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CheckStatus {
Ok,
Missing,
Skipped,
}
#[derive(Debug)]
pub struct DoctorItem {
pub name: &'static str,
pub status: CheckStatus,
pub message: Option<String>,
pub fixable: bool,
}
impl DoctorItem {
const fn ok(name: &'static str) -> Self {
Self {
name,
status: CheckStatus::Ok,
message: None,
fixable: false,
}
}
fn missing(name: &'static str, message: impl Into<String>) -> Self {
Self {
name,
status: CheckStatus::Missing,
message: Some(message.into()),
fixable: false,
}
}
const fn skipped(name: &'static str) -> Self {
Self {
name,
status: CheckStatus::Skipped,
message: None,
fixable: false,
}
}
}
pub async fn doctor() -> Vec<DoctorItem> {
let mut items = Vec::new();
if cfg!(target_os = "macos") {
match Xcode.check().await {
Ok(()) => items.push(DoctorItem::ok("Xcode")),
Err(e) => items.push(DoctorItem::missing("Xcode", e.to_string())),
}
match AppleSdk::Ios.check().await {
Ok(()) => items.push(DoctorItem::ok("iOS SDK")),
Err(e) => items.push(DoctorItem::missing("iOS SDK", e.to_string())),
}
match AppleSdk::Macos.check().await {
Ok(()) => items.push(DoctorItem::ok("macOS SDK")),
Err(e) => items.push(DoctorItem::missing("macOS SDK", e.to_string())),
}
} else {
items.push(DoctorItem::skipped("Xcode"));
items.push(DoctorItem::skipped("iOS SDK"));
items.push(DoctorItem::skipped("macOS SDK"));
}
match AndroidSdk.check().await {
Ok(()) => items.push(DoctorItem::ok("Android SDK")),
Err(e) => items.push(DoctorItem::missing("Android SDK", e.to_string())),
}
match AndroidNdk.check().await {
Ok(()) => items.push(DoctorItem::ok("Android NDK")),
Err(e) => items.push(DoctorItem::missing("Android NDK", e.to_string())),
}
match Java::detect_path().await {
Some(_) => items.push(DoctorItem::ok("Java")),
None => items.push(DoctorItem::missing(
"Java",
"Install JDK or set JAVA_HOME. Android Studio includes a bundled JDK.",
)),
}
items
}