use tower_lsp::lsp_types::Url;
pub(crate) const HARN_LANGUAGE_ID: &str = "harn";
pub(crate) const PROMPT_LANGUAGE_ID: &str = "harn-prompt";
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum DocumentKind {
Harn,
Prompt,
Other,
}
impl DocumentKind {
pub(crate) fn classify(uri: &Url, language_id: &str) -> Self {
let path = uri.path();
if path.ends_with(".prompt") {
return Self::Prompt;
}
match language_id {
HARN_LANGUAGE_ID => Self::Harn,
PROMPT_LANGUAGE_ID => Self::Prompt,
_ if path.ends_with(".harn") => Self::Harn,
_ => Self::Other,
}
}
pub(crate) fn is_harn(self) -> bool {
self == Self::Harn
}
}
#[cfg(test)]
mod tests {
use super::DocumentKind;
use tower_lsp::lsp_types::Url;
fn classify(path: &str, language_id: &str) -> DocumentKind {
DocumentKind::classify(
&Url::parse(&format!("file:///w/{path}")).unwrap(),
language_id,
)
}
#[test]
fn language_id_decides_when_the_client_knows_harn() {
assert_eq!(classify("main.harn", "harn"), DocumentKind::Harn);
assert_eq!(
classify("greet.harn.prompt", "harn-prompt"),
DocumentKind::Prompt
);
}
#[test]
fn file_name_decides_when_the_client_does_not() {
assert_eq!(
classify("greet.harn.prompt", "plaintext"),
DocumentKind::Prompt
);
assert_eq!(classify("greet.prompt", ""), DocumentKind::Prompt);
assert_eq!(classify("main.harn", ""), DocumentKind::Harn);
}
#[test]
fn unrelated_documents_are_neither() {
assert_eq!(classify("main.ts", "typescript"), DocumentKind::Other);
assert_eq!(classify("README.md", "markdown"), DocumentKind::Other);
}
#[test]
fn a_declared_prompt_is_never_parsed_as_harn() {
assert!(!classify("greet.prompt", "harn-prompt").is_harn());
assert!(!classify("greet.harn.prompt", "harn").is_harn());
}
}