use crate::{
Ident,
SourceKey,
database::{
DynPartition,
PartitionKey,
},
protocol::lsp::SymbolKind,
};
pub struct DocumentSymbols;
impl PartitionKey for DocumentSymbols {
const KEY: crate::SpannedIdent =
crate::partitions::known_keys::DOCUMENT_SYMBOLS;
}
impl DynPartition for DocumentSymbols {
type DynSortKey = DocumentSymbolSortKey;
type RecordConstraint = dyn DocumentSymbolRecord;
}
impl<R: DocumentSymbolRecord + crate::record::Record>
crate::database::DynPartitionRecord<DocumentSymbols> for R
{
}
#[derive(Debug, Clone)]
pub enum DocumentSymbolSortKey {
Symbol {
source_key: SourceKey,
symbol_kind: SymbolKind,
ident: Ident,
},
All,
FilePrefix {
source_key: SourceKey,
},
}
impl std::fmt::Display for DocumentSymbolSortKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
| DocumentSymbolSortKey::Symbol {
source_key,
symbol_kind,
ident,
} => write!(f, "{}|{}|{}", source_key, symbol_kind, ident),
| DocumentSymbolSortKey::All => Ok(()),
| DocumentSymbolSortKey::FilePrefix { source_key } => {
write!(f, "{}", source_key)
},
}
}
}
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
enum DocSymToken {
Source(SourceKey),
Kind(SymbolKind),
Ident(Ident),
}
impl DocumentSymbolSortKey {
fn tokens(&self) -> Vec<DocSymToken> {
match self {
| DocumentSymbolSortKey::All => Vec::new(),
| DocumentSymbolSortKey::FilePrefix { source_key } => {
vec![DocSymToken::Source(*source_key)]
},
| DocumentSymbolSortKey::Symbol {
source_key,
symbol_kind,
ident,
} => vec![
DocSymToken::Source(*source_key),
DocSymToken::Kind(*symbol_kind),
DocSymToken::Ident(*ident),
],
}
}
}
impl PartialEq for DocumentSymbolSortKey {
fn eq(&self, other: &Self) -> bool {
self.tokens() == other.tokens()
}
}
impl Eq for DocumentSymbolSortKey {}
impl std::hash::Hash for DocumentSymbolSortKey {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.tokens().hash(state);
}
}
impl PartialOrd for DocumentSymbolSortKey {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for DocumentSymbolSortKey {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.tokens().cmp(&other.tokens())
}
}
impl bluegum::Bluegum for DocumentSymbolSortKey {
fn node(&self, b: &mut bluegum::Builder) {
b.name("DocumentSymbolSortKey");
}
}
impl bluegum::BluegumWithState<dyn crate::SourceResolver>
for DocumentSymbolSortKey
{
fn node_with_state(
&self,
b: &mut bluegum::Builder,
resolver: &(dyn crate::SourceResolver + 'static),
) {
b.name("DocumentSymbolSortKey")
.alt(crate::database::PartitionSortKey::resolve(self, resolver));
}
}
impl crate::database::PartitionSortKey for DocumentSymbolSortKey {
fn is_prefix_of(&self, other: &Self) -> bool {
other.tokens().starts_with(&self.tokens())
}
fn resolve(&self, _resolver: &dyn crate::SourceResolver) -> String {
self.to_string()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SymbolKindVariant {
Symbol,
Reference,
}
pub trait DocumentSymbolRecord: Send + Sync + std::fmt::Debug {
fn get_ident(&self) -> Ident;
fn get_ident_path(&self) -> Vec<Ident>;
fn get_ident_range(&self) -> crate::protocol::lsp::Range;
fn source_key(&self) -> SourceKey;
fn span(&self) -> crate::source::Span;
fn symbol_kind(&self) -> SymbolKind;
fn target_source_key(&self) -> Option<SourceKey> {
None
}
fn symbol_kind_variant(&self) -> SymbolKindVariant {
SymbolKindVariant::Symbol
}
fn to_document_symbol(
&self,
source_cache: &crate::source::cache::reporter::SourceCacheReader,
encoding: &crate::protocol::lsp::PositionEncodingKind,
) -> crate::protocol::lsp::DocumentSymbol;
fn definition_location(
&self,
_source_cache: &crate::source::cache::reporter::SourceCacheReader,
_encoding: &crate::protocol::lsp::PositionEncodingKind,
) -> Option<crate::protocol::lsp::Location> {
None
}
fn hover_info(
&self,
_source_cache: &crate::source::cache::reporter::SourceCacheReader,
_encoding: &crate::protocol::lsp::PositionEncodingKind,
) -> Option<crate::protocol::lsp::Hover> {
None
}
fn rename_range(
&self,
_source_cache: &crate::source::cache::reporter::SourceCacheReader,
_encoding: &crate::protocol::lsp::PositionEncodingKind,
) -> Option<crate::protocol::lsp::Range> {
None
}
}