use crate::{
Ident,
SourceKey,
protocol::lsp::PositionEncodingKind,
source::Span,
};
crate::define_dyn_partition!(
TextDocumentReferences,
crate::partitions::known_keys::SYMBOL_REFERENCES,
TextDocumentReferenceSortKey,
TextDocumentReferenceRecord
);
#[derive(Debug, Clone)]
pub enum TextDocumentReferenceSortKey {
Reference {
source_key: SourceKey,
ident: Ident,
span: Span,
},
All,
SourcePrefix {
source_key: SourceKey,
},
SymbolPrefix {
source_key: SourceKey,
ident: Ident,
},
}
impl std::fmt::Display for TextDocumentReferenceSortKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
| TextDocumentReferenceSortKey::Reference {
source_key,
ident,
span,
} => write!(f, "{}|{}|>{:?}", source_key, ident, span),
| TextDocumentReferenceSortKey::All => Ok(()),
| TextDocumentReferenceSortKey::SourcePrefix { source_key } => {
write!(f, "{}|", source_key)
},
| TextDocumentReferenceSortKey::SymbolPrefix { source_key, ident } => {
write!(f, "{}|{}|>", source_key, ident)
},
}
}
}
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
enum RefToken {
Source(SourceKey),
Ident(Ident),
Span(Span),
}
impl TextDocumentReferenceSortKey {
fn tokens(&self) -> Vec<RefToken> {
match self {
| TextDocumentReferenceSortKey::All => Vec::new(),
| TextDocumentReferenceSortKey::SourcePrefix { source_key } => {
vec![RefToken::Source(*source_key)]
},
| TextDocumentReferenceSortKey::SymbolPrefix { source_key, ident } => {
vec![RefToken::Source(*source_key), RefToken::Ident(*ident)]
},
| TextDocumentReferenceSortKey::Reference {
source_key,
ident,
span,
} => vec![
RefToken::Source(*source_key),
RefToken::Ident(*ident),
RefToken::Span(*span),
],
}
}
}
impl PartialEq for TextDocumentReferenceSortKey {
fn eq(&self, other: &Self) -> bool {
self.tokens() == other.tokens()
}
}
impl Eq for TextDocumentReferenceSortKey {}
impl std::hash::Hash for TextDocumentReferenceSortKey {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.tokens().hash(state);
}
}
impl PartialOrd for TextDocumentReferenceSortKey {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for TextDocumentReferenceSortKey {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.tokens().cmp(&other.tokens())
}
}
impl bluegum::Bluegum for TextDocumentReferenceSortKey {
fn node(&self, b: &mut bluegum::Builder) {
b.name("TextDocumentReferenceSortKey");
}
}
impl bluegum::BluegumWithState<dyn crate::SourceResolver>
for TextDocumentReferenceSortKey
{
fn node_with_state(
&self,
b: &mut bluegum::Builder,
resolver: &(dyn crate::SourceResolver + 'static),
) {
b.name("TextDocumentReferenceSortKey")
.alt(crate::database::PartitionSortKey::resolve(self, resolver));
}
}
impl crate::database::PartitionSortKey for TextDocumentReferenceSortKey {
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()
}
}
pub trait TextDocumentReferenceRecord: Send + Sync + std::fmt::Debug {
fn reference_source_key(&self) -> SourceKey;
fn reference_span(&self) -> Span;
fn target_source_key(&self) -> SourceKey;
fn target_ident(&self) -> Ident;
fn location(
&self,
source_cache: &crate::source::cache::reporter::SourceCacheReader,
encoding: &PositionEncodingKind,
) -> Option<crate::protocol::lsp::Location> {
let source = source_cache.get_source(self.reference_source_key())?;
let uri = source.uri().clone();
let span_cache = source.span_cache();
let range = self
.reference_span()
.to_lsp_range(span_cache, &*source, encoding)?;
Some(crate::protocol::lsp::Location { uri, range })
}
}