use crate::{
ContentHash,
Ident,
SourceKey,
database::{
DynPartition,
PartitionKey,
},
protocol::lsp::Position,
};
pub struct TextDocumentPosition;
impl PartitionKey for TextDocumentPosition {
const KEY: crate::SpannedIdent =
crate::partitions::known_keys::TEXT_DOCUMENT_POSITION_INDEX;
}
impl DynPartition for TextDocumentPosition {
type DynSortKey = TextDocumentPositionSortKey;
type RecordConstraint = dyn TextDocumentPositionRecord;
}
impl<R: TextDocumentPositionRecord + crate::record::Record>
crate::database::DynPartitionRecord<TextDocumentPosition> for R
{
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(u8)]
pub enum PositionKind {
Unknown = 0,
Ident = 1,
Symbol = 2,
Reference = 3,
}
#[derive(Debug, Clone)]
pub enum TextDocumentPositionSortKey {
Position {
source_key: SourceKey,
line: u32,
character: u32,
kind: PositionKind,
},
All,
FilePrefix {
source_key: SourceKey,
},
}
impl std::fmt::Display for TextDocumentPositionSortKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
| TextDocumentPositionSortKey::Position {
source_key,
line,
character,
kind,
} => {
write!(
f,
"{}|{:010}|{:010}|{}",
source_key, line, character, *kind as u8
)
},
| TextDocumentPositionSortKey::All => Ok(()),
| TextDocumentPositionSortKey::FilePrefix { source_key } => {
write!(f, "{}", source_key)
},
}
}
}
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
enum PosToken {
Source(SourceKey),
Line(u32),
Char(u32),
Kind(u8),
}
impl TextDocumentPositionSortKey {
fn tokens(&self) -> Vec<PosToken> {
match self {
| TextDocumentPositionSortKey::All => Vec::new(),
| TextDocumentPositionSortKey::FilePrefix { source_key } => {
vec![PosToken::Source(*source_key)]
},
| TextDocumentPositionSortKey::Position {
source_key,
line,
character,
kind,
} => vec![
PosToken::Source(*source_key),
PosToken::Line(*line),
PosToken::Char(*character),
PosToken::Kind(*kind as u8),
],
}
}
}
impl PartialEq for TextDocumentPositionSortKey {
fn eq(&self, other: &Self) -> bool {
self.tokens() == other.tokens()
}
}
impl Eq for TextDocumentPositionSortKey {}
impl std::hash::Hash for TextDocumentPositionSortKey {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.tokens().hash(state);
}
}
impl PartialOrd for TextDocumentPositionSortKey {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for TextDocumentPositionSortKey {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.tokens().cmp(&other.tokens())
}
}
impl bluegum::Bluegum for TextDocumentPositionSortKey {
fn node(&self, b: &mut bluegum::Builder) {
b.name("TextDocumentPositionSortKey");
}
}
impl bluegum::BluegumWithState<dyn crate::SourceResolver>
for TextDocumentPositionSortKey
{
fn node_with_state(
&self,
b: &mut bluegum::Builder,
resolver: &(dyn crate::SourceResolver + 'static),
) {
b.name("TextDocumentPositionSortKey")
.alt(crate::database::PartitionSortKey::resolve(self, resolver));
}
}
impl crate::database::PartitionSortKey for TextDocumentPositionSortKey {
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 TextDocumentPositionRecord: Send + Sync + std::fmt::Debug {
fn source_key(&self) -> SourceKey;
fn position(&self) -> Position;
fn kind(&self) -> PositionKind;
fn symbol_hash(&self) -> ContentHash;
fn symbol_ident(&self) -> Ident;
}