blues-lsp 0.1.3

LSP language server for the Bluespec SystemVerilog language
Documentation
use std::{fmt::Display, path::PathBuf, sync::Arc};

use arcstr::Substr;

use crate::{bsc::args::BscArgs, project::Project};

use super::{FileHandle, PkgHandle, bo_for_source};

pub struct Package {
    pub file: FileHandle,
    pub cli: Arc<BscArgs>,
    pub bo_path: Option<PathBuf>,
    pub name: Option<Substr>,
}

impl Display for Package {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        if let Some(bo) = &self.bo_path {
            write!(f, "'{}'", bo.display())
        } else {
            write!(f, "<anonymous pacakge for {:?}>", self.file)
        }
    }
}

impl Package {
    pub fn new(file: FileHandle, cli: Arc<BscArgs>, bo_path: Option<PathBuf>) -> Self {
        let name = bo_path
            .as_deref()
            .and_then(|bo| bo.file_stem().and_then(|s| s.to_str()).map(str::to_owned))
            .map(Substr::from);
        Package {
            file,
            cli,
            bo_path,
            name,
        }
    }

    pub fn resolve_import(&self, proj: &Project, name: &str) -> Option<PkgHandle> {
        let search_paths = |ext: &str| {
            for dir in &self.cli.include_dirs {
                let path = dir.join(name).with_extension(ext);
                if path.is_file() {
                    return Some(path);
                }
            }
            None
        };

        if let Some(bsv) = search_paths("bsv") {
            return bo_for_source(bsv, self.cli.bdir.as_deref())
                .and_then(|bo| proj.pkg_for_bo(&bo));
        }

        if let Some(bs) = search_paths("bs") {
            return bo_for_source(bs, self.cli.bdir.as_deref()).and_then(|bo| proj.pkg_for_bo(&bo));
        }

        if let Some(bo) = search_paths("bo") {
            return proj.pkg_for_bo(&bo);
        }

        None
    }
}