laburnum 1.17.2

An LSP framework for building language servers and compilers, powered by an incremental query tree with content-addressed storage, task-based dataflow, and parallel queries.
Documentation
// Copyright Two Neutron Stars Incorporated and contributors
// SPDX-License-Identifier: BlueOak-1.0.0

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");
}
/// To write folding ranges, create a wrapper partition with
/// [`impl_partition_for_dyn!`]:
///
/// ```rust,ignore
/// use laburnum::{impl_partition_for_dyn, partitions::DocumentFoldingRange};
///
/// // Your record type must implement FoldingRangeRecord + Record
/// impl_partition_for_dyn!(MyFoldingRangePartition, DocumentFoldingRange, MyRange);
///
/// // Then write using the wrapper partition
/// let sort_key = FoldingRangeSortKey::Range {
///   source_key, start_line, end_line, start_character, end_character
/// };
/// writer.write::<MyFoldingRangePartition>(sort_key, range.into());
/// ```
///
/// [`impl_partition_for_dyn!`]: crate::impl_partition_for_dyn
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)
      },
    }
  }
}

// -- Sort key ordering (ADR0011) ----------------------------------------------

#[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;
}