use crate::{
Ident,
SourceKey,
database::{
DynPartition,
PartitionKey,
},
protocol::lsp::FoldingRange,
};
pub struct DocumentFoldingRange;
impl PartitionKey for DocumentFoldingRange {
const KEY: Ident = Ident::new("laburnum::document_folding_range");
}
impl DynPartition for DocumentFoldingRange {
type DynSortKey = FoldingRangeSortKey;
type RecordConstraint = dyn FoldingRangeRecord;
}
impl<R: FoldingRangeRecord + crate::record::Record>
crate::database::DynPartitionRecord<DocumentFoldingRange> for R
{
}
#[derive(Debug, Clone)]
pub enum FoldingRangeSortKey {
Range {
source_key: SourceKey,
start_line: u32,
end_line: u32,
start_character: u32,
end_character: u32,
},
All,
FilePrefix {
source_key: SourceKey,
},
}
impl std::fmt::Display for FoldingRangeSortKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
| FoldingRangeSortKey::Range {
source_key,
start_line,
end_line,
start_character,
end_character,
} => {
write!(
f,
"{}|{:010}|{:010}|{:010}|{:010}",
source_key, start_line, end_line, start_character, end_character
)
},
| FoldingRangeSortKey::All => Ok(()),
| FoldingRangeSortKey::FilePrefix { source_key } => {
write!(f, "{}", source_key)
},
}
}
}
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
enum FoldToken {
Source(SourceKey),
StartLine(u32),
EndLine(u32),
StartChar(u32),
EndChar(u32),
}
impl FoldingRangeSortKey {
fn tokens(&self) -> Vec<FoldToken> {
match self {
| FoldingRangeSortKey::All => Vec::new(),
| FoldingRangeSortKey::FilePrefix { source_key } => {
vec![FoldToken::Source(*source_key)]
},
| FoldingRangeSortKey::Range {
source_key,
start_line,
end_line,
start_character,
end_character,
} => vec![
FoldToken::Source(*source_key),
FoldToken::StartLine(*start_line),
FoldToken::EndLine(*end_line),
FoldToken::StartChar(*start_character),
FoldToken::EndChar(*end_character),
],
}
}
}
impl PartialEq for FoldingRangeSortKey {
fn eq(&self, other: &Self) -> bool {
self.tokens() == other.tokens()
}
}
impl Eq for FoldingRangeSortKey {}
impl std::hash::Hash for FoldingRangeSortKey {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.tokens().hash(state);
}
}
impl PartialOrd for FoldingRangeSortKey {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for FoldingRangeSortKey {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.tokens().cmp(&other.tokens())
}
}
impl crate::database::PartitionSortKey for FoldingRangeSortKey {
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 FoldingRangeRecord: Send + Sync + std::fmt::Debug {
fn source_key(&self) -> SourceKey;
fn to_folding_range(&self) -> FoldingRange;
}