laburnum 1.17.1

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 {
  super::storage::{TestPartition, Test1Partition, TestPartitions},
  crate::{
    ContentHash, Ident, Uri,
    database::{
      PartitionKey,
      chunk::RecordWriter,
      partitions::{HasPartition, SpanIndex},
      storage::Partitions,
    },
  },
};

fn test_uri(path: &str) -> Uri {
  Uri::parse(path).expect("valid test URI")
}

#[test]
fn partition_store_span_index_round_trip() {
  let stores = TestPartitions::new_stores();
  let store = <
    <TestPartitions as Partitions>::Stores as HasPartition<TestPartition>
  >::store(&stores);

  let uri = test_uri("file:///test.gold");
  let hash_a = ContentHash::new(&[1, 0, 0, 0]);
  let hash_b = ContentHash::new(&[2, 0, 0, 0]);

  let index = SpanIndex::build(vec![
    (0, 10, hash_a),
    (20, 5, hash_b),
  ]);

  store.span_index_replace(uri.clone(), index);

  assert_eq!(store.span_index_query(&uri, 5), Some(hash_a));
  assert_eq!(store.span_index_query(&uri, 22), Some(hash_b));
  assert_eq!(store.span_index_query(&uri, 15), None);

  let other_uri = test_uri("file:///other.gold");
  assert_eq!(store.span_index_query(&other_uri, 5), None);
}

#[test]
fn partition_store_span_index_replace_overwrites() {
  let stores = TestPartitions::new_stores();
  let store = <
    <TestPartitions as Partitions>::Stores as HasPartition<TestPartition>
  >::store(&stores);

  let uri = test_uri("file:///test.gold");
  let hash_old = ContentHash::new(&[1, 0, 0, 0]);
  let hash_new = ContentHash::new(&[2, 0, 0, 0]);

  let index1 = SpanIndex::build(vec![(0, 10, hash_old)]);
  store.span_index_replace(uri.clone(), index1);
  assert_eq!(store.span_index_query(&uri, 5), Some(hash_old));

  let index2 = SpanIndex::build(vec![(0, 10, hash_new)]);
  store.span_index_replace(uri.clone(), index2);
  assert_eq!(store.span_index_query(&uri, 5), Some(hash_new));
}

#[test]
fn partition_store_span_index_remove() {
  let stores = TestPartitions::new_stores();
  let store = <
    <TestPartitions as Partitions>::Stores as HasPartition<TestPartition>
  >::store(&stores);

  let uri = test_uri("file:///test.gold");
  let hash = ContentHash::new(&[1, 0, 0, 0]);

  let index = SpanIndex::build(vec![(0, 10, hash)]);
  store.span_index_replace(uri.clone(), index);
  assert_eq!(store.span_index_query(&uri, 5), Some(hash));

  store.span_index_remove(&uri);
  assert_eq!(store.span_index_query(&uri, 5), None);
}

#[test]
fn record_writer_index_span_stages_per_partition() {
  let mut writer = RecordWriter::<TestPartitions>::new(Ident::new("task"));

  let span1 = crate::Span::new_inline(1, 0, 0, 10).unwrap();
  let span2 = crate::Span::new_inline(1, 0, 20, 5).unwrap();
  let span3 = crate::Span::new_inline(1, 0, 30, 5).unwrap();
  let hash1 = ContentHash::new(&[1, 0, 0, 0]);
  let hash2 = ContentHash::new(&[2, 0, 0, 0]);
  let hash3 = ContentHash::new(&[3, 0, 0, 0]);

  writer.index_span::<TestPartition>(span1, hash1);
  writer.index_span::<TestPartition>(span2, hash2);
  writer.index_span::<Test1Partition>(span3, hash3);

  let chunk = writer.build();

  let test_intervals = chunk.staged_intervals().get(&TestPartition::KEY);
  assert!(test_intervals.is_some());
  assert_eq!(test_intervals.map(|v| v.len()), Some(2));

  let test1_intervals = chunk.staged_intervals().get(&Test1Partition::KEY);
  assert!(test1_intervals.is_some());
  assert_eq!(test1_intervals.map(|v| v.len()), Some(1));
}

#[test]
fn partitions_trait_span_index_dispatch() {
  let stores = TestPartitions::new_stores();
  let uri = test_uri("file:///dispatch.gold");
  let hash = ContentHash::new(&[42, 0, 0, 0]);

  let index = SpanIndex::build(vec![(0, 10, hash)]);
  TestPartitions::span_index_replace(&stores, TestPartition::KEY, uri.clone(), index);

  let store = <
    <TestPartitions as Partitions>::Stores as HasPartition<TestPartition>
  >::store(&stores);
  assert_eq!(store.span_index_query(&uri, 5), Some(hash));

  TestPartitions::span_index_remove(&stores, TestPartition::KEY, &uri);
  assert_eq!(store.span_index_query(&uri, 5), None);
}