use crate::{
Ident,
SourceKey,
Uri,
database::{
DynPartition,
PartitionKey,
},
protocol::lsp::SymbolKind,
};
pub struct WorkspaceSymbols;
impl PartitionKey for WorkspaceSymbols {
const KEY: Ident = Ident::new("laburnum::workspace_symbols");
}
impl DynPartition for WorkspaceSymbols {
type DynSortKey = WorkspaceSymbolSortKey;
type RecordConstraint = dyn WorkspaceSymbolRecord;
}
impl<R: WorkspaceSymbolRecord + crate::record::Record>
crate::database::DynPartitionRecord<WorkspaceSymbols> for R
{
}
#[derive(Debug, Clone)]
pub enum WorkspaceSymbolSortKey {
Symbol {
name_lowercase: String,
kind: SymbolKind,
source_key: SourceKey,
},
All,
NamePrefix {
name_lowercase: String,
},
}
impl std::fmt::Display for WorkspaceSymbolSortKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
| WorkspaceSymbolSortKey::Symbol {
name_lowercase,
kind,
source_key,
} => write!(f, "{}|{}|{}", name_lowercase, kind, source_key),
| WorkspaceSymbolSortKey::All => Ok(()),
| WorkspaceSymbolSortKey::NamePrefix { name_lowercase } => {
write!(f, "{}", name_lowercase)
},
}
}
}
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
enum WsSymToken {
Name(String),
Kind(SymbolKind),
Source(SourceKey),
}
impl WorkspaceSymbolSortKey {
fn tokens(&self) -> Vec<WsSymToken> {
match self {
| WorkspaceSymbolSortKey::All => Vec::new(),
| WorkspaceSymbolSortKey::NamePrefix { name_lowercase } => {
vec![WsSymToken::Name(name_lowercase.clone())]
},
| WorkspaceSymbolSortKey::Symbol {
name_lowercase,
kind,
source_key,
} => vec![
WsSymToken::Name(name_lowercase.clone()),
WsSymToken::Kind(*kind),
WsSymToken::Source(*source_key),
],
}
}
fn name(&self) -> Option<&str> {
match self {
| WorkspaceSymbolSortKey::Symbol { name_lowercase, .. }
| WorkspaceSymbolSortKey::NamePrefix { name_lowercase } => {
Some(name_lowercase.as_str())
},
| WorkspaceSymbolSortKey::All => None,
}
}
}
impl PartialEq for WorkspaceSymbolSortKey {
fn eq(&self, other: &Self) -> bool {
self.tokens() == other.tokens()
}
}
impl Eq for WorkspaceSymbolSortKey {}
impl std::hash::Hash for WorkspaceSymbolSortKey {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.tokens().hash(state);
}
}
impl PartialOrd for WorkspaceSymbolSortKey {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for WorkspaceSymbolSortKey {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.tokens().cmp(&other.tokens())
}
}
impl crate::database::PartitionSortKey for WorkspaceSymbolSortKey {
fn is_prefix_of(&self, other: &Self) -> bool {
match self {
| WorkspaceSymbolSortKey::All => true,
| WorkspaceSymbolSortKey::NamePrefix { name_lowercase } => {
other.name().is_some_and(|n| n.starts_with(name_lowercase.as_str()))
},
| WorkspaceSymbolSortKey::Symbol { .. } => self == other,
}
}
fn resolve(&self, _resolver: &dyn crate::SourceResolver) -> String {
self.to_string()
}
}
pub trait WorkspaceSymbolRecord: Send + Sync + std::fmt::Debug {
fn name(&self) -> &str;
fn kind(&self) -> SymbolKind;
fn uri(&self) -> &Uri;
fn source_key(&self) -> SourceKey;
fn range(&self) -> crate::protocol::lsp::Range;
fn container_name(&self) -> Option<&str>;
}