shape/
location.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
use apollo_compiler::parser::FileId;
use std::fmt::Display;
use std::ops::Range;
use std::sync::Arc;

/// Some identifier of the source text that a [`Location`] refers to.
/// The content only matters to the caller, who will need to be able to use this to give
/// diagnostics to users.
///
/// This might be a file name, reference to an editor panel, or a unique identifier for a
/// sub-slice of a larger text. It could also be the string content itself.
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub enum SourceId {
    /// A key into [`apollo_compiler::Schema`] sources.
    GraphQL(FileId),
    /// An arbitrary source identifier from a consumer.
    Other(Arc<str>),
}

impl SourceId {
    pub fn new(id: impl Into<Arc<str>>) -> Self {
        Self::Other(id.into())
    }

    /// Create a new [`Location`] within this source text.
    #[must_use]
    pub fn location(&self, span: Range<usize>) -> Location {
        Location {
            source_id: self.clone(),
            span,
        }
    }
}

/// The location of a [`crate::Shape`] within the source text that produced it.
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct Location {
    /// Some identifier correlating `span` to a string the caller controls
    pub source_id: SourceId,
    /// The character offset within the source text. 0-indexed, end is exclusive.
    pub span: Range<usize>,
}

/// Used to track the location of a thing.
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct Located<T> {
    pub value: T,
    pub locations: Vec<Location>,
}

impl<T> Located<T> {
    pub fn new(value: T, locations: impl IntoIterator<Item = Location>) -> Self {
        Self {
            value,
            locations: locations.into_iter().collect(),
        }
    }
}

impl<T: Display> Display for Located<T> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.value)
    }
}