symbolique 0.1.0

Symbol table pipeline for language servers — parse, link, merge, and resolve symbols across files, built on the laburnum LSP framework.
// Copyright Two Neutron Stars Incorporated and contributors
// SPDX-License-Identifier: BlueOak-1.0.0

//! Resolution partition.
//!
//! Stage 4 of the symbolique pipeline. Resolution maps references to their
//! target definitions:
//!
//! - **SymbolResolution**: Index-only partition with `ResolutionEntry` entries
//!   pointing to target definitions in the shared `Symbols` partition
//!
//! Resolution algorithms are user-defined - symbolique provides the partition
//! for storing results. No new shapes are created; resolution links existing
//! Reference/Import shapes to existing Definition shapes.

use {
  super::records::ResolutionEntry,
  crate::core::{Ident, SymbolPath, SymbolSortKey, Value},
  laburnum::{
    Ident as LaburnumIdent,
    database::{Partition, PartitionKey},
  },
  std::marker::PhantomData,
};

/// Symbol resolution partition (index-only).
///
/// Stores only index entries that reference target definitions in the shared
/// `Symbols` partition. Each entry contains the target path and a handle to
/// the target symbol shape.
pub struct SymbolResolution<V, I, P>(PhantomData<(V, I, P)>);

impl<V, I, P> Default for SymbolResolution<V, I, P> {
  fn default() -> Self {
    Self(PhantomData)
  }
}

impl<V, I, P> Clone for SymbolResolution<V, I, P> {
  fn clone(&self) -> Self {
    *self
  }
}

impl<V, I, P> Copy for SymbolResolution<V, I, P> {}

impl<V, I, P> std::fmt::Debug for SymbolResolution<V, I, P> {
  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    f.debug_struct("SymbolResolution").finish()
  }
}

impl<V, I, P> PartitionKey for SymbolResolution<V, I, P>
where
  V: Value<I>,
  I: Ident,
  P: SymbolPath,
{
  const KEY: LaburnumIdent = LaburnumIdent::new("symbolique::resolution");
}

impl<V, I, P> Partition for SymbolResolution<V, I, P>
where
  V: Value<I>,
  I: Ident,
  P: SymbolPath,
{
  type Record = (); // Index-only
  type IndexEntry = ResolutionEntry<V, I, P>;
  type SortKey = SymbolSortKey;
}

#[cfg(test)]
mod tests {
  use super::*;

  #[derive(Debug, Clone, Hash, PartialEq, Eq)]
  struct TestPath(String);

  impl crate::core::SymbolPath for TestPath {
    fn sort_key(&self) -> String {
      self.0.clone()
    }
  }

  #[test]
  fn symbol_resolution_partition_key() {
    use crate::core::{DefaultValue, StringIdent};

    let _key = SymbolResolution::<DefaultValue, StringIdent, TestPath>::KEY;
  }

  #[test]
  fn symbol_resolution_is_index_only() {
    use crate::core::{DefaultValue, StringIdent};

    fn assert_record_is_unit<P: Partition<Record = ()>>() {}

    assert_record_is_unit::<
      SymbolResolution<DefaultValue, StringIdent, TestPath>,
    >();
  }
}