pub mod database;
pub mod error;
pub mod extractor;
pub mod harvester;
pub mod query;
pub use database::TypeDatabase;
pub use error::{KnowledgeError, Result};
pub use extractor::Extractor;
pub use harvester::{HarvestResult, Harvester};
pub use query::TypeQuery;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum TypeFactKind {
Function,
Class,
Method,
Attribute,
}
impl std::fmt::Display for TypeFactKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Function => write!(f, "function"),
Self::Class => write!(f, "class"),
Self::Method => write!(f, "method"),
Self::Attribute => write!(f, "attribute"),
}
}
}
impl std::str::FromStr for TypeFactKind {
type Err = KnowledgeError;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
match s {
"function" => Ok(Self::Function),
"class" => Ok(Self::Class),
"method" => Ok(Self::Method),
"attribute" => Ok(Self::Attribute),
_ => Err(KnowledgeError::InvalidKind(s.to_string())),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct TypeFact {
pub module: String,
pub symbol: String,
pub kind: TypeFactKind,
pub signature: String,
pub return_type: String,
}
impl TypeFact {
pub fn function(module: &str, symbol: &str, signature: &str, return_type: &str) -> Self {
Self {
module: module.to_string(),
symbol: symbol.to_string(),
kind: TypeFactKind::Function,
signature: signature.to_string(),
return_type: return_type.to_string(),
}
}
pub fn class(module: &str, symbol: &str) -> Self {
Self {
module: module.to_string(),
symbol: symbol.to_string(),
kind: TypeFactKind::Class,
signature: String::new(),
return_type: format!("{module}.{symbol}"),
}
}
pub fn method(
module: &str,
class: &str,
method: &str,
signature: &str,
return_type: &str,
) -> Self {
Self {
module: module.to_string(),
symbol: format!("{class}.{method}"),
kind: TypeFactKind::Method,
signature: signature.to_string(),
return_type: return_type.to_string(),
}
}
pub fn fqn(&self) -> String {
format!("{}.{}", self.module, self.symbol)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_type_fact_function() {
let fact = TypeFact::function(
"requests",
"get",
"(url: str, **kwargs) -> Response",
"requests.models.Response",
);
assert_eq!(fact.module, "requests");
assert_eq!(fact.symbol, "get");
assert_eq!(fact.kind, TypeFactKind::Function);
assert_eq!(fact.fqn(), "requests.get");
}
#[test]
fn test_type_fact_class() {
let fact = TypeFact::class("requests.models", "Response");
assert_eq!(fact.kind, TypeFactKind::Class);
assert_eq!(fact.return_type, "requests.models.Response");
}
#[test]
fn test_type_fact_method() {
let fact = TypeFact::method(
"requests.models",
"Response",
"json",
"(self) -> dict",
"dict",
);
assert_eq!(fact.symbol, "Response.json");
assert_eq!(fact.kind, TypeFactKind::Method);
}
#[test]
fn test_type_fact_kind_display() {
assert_eq!(TypeFactKind::Function.to_string(), "function");
assert_eq!(TypeFactKind::Class.to_string(), "class");
assert_eq!(TypeFactKind::Method.to_string(), "method");
assert_eq!(TypeFactKind::Attribute.to_string(), "attribute");
}
#[test]
fn test_type_fact_kind_from_str() {
assert_eq!(
"function".parse::<TypeFactKind>().unwrap(),
TypeFactKind::Function
);
assert_eq!(
"class".parse::<TypeFactKind>().unwrap(),
TypeFactKind::Class
);
assert!("invalid".parse::<TypeFactKind>().is_err());
}
}