use std::{cmp::Ordering, ops::Range};
use sway_ast::{
attribute::Annotated,
brackets::{Parens, SquareBrackets},
keywords::{
AddToken, ColonToken, CommaToken, ForToken, ForwardSlashToken, RightArrowToken,
SemicolonToken,
},
Braces, TypeField,
};
use sway_parse::Parse;
use sway_types::{Ident, Span, Spanned};
pub(crate) const STARTING_BYTE_SPAN: ByteSpan = ByteSpan { start: 0, end: 0 };
#[derive(Eq, PartialEq, Debug, Clone, Default)]
pub struct ByteSpan {
pub start: usize,
pub end: usize,
}
impl From<Span> for ByteSpan {
fn from(span: Span) -> Self {
ByteSpan {
start: span.start(),
end: span.end(),
}
}
}
impl ByteSpan {
pub fn len(&self) -> usize {
self.end - self.start
}
pub fn contained_within(&self, range: &Range<usize>) -> bool {
range.start <= self.start && self.end <= range.end
}
}
impl Ord for ByteSpan {
fn cmp(&self, other: &Self) -> Ordering {
match self.start.cmp(&other.start) {
Ordering::Equal => other.end.cmp(&self.end),
ord => ord,
}
}
}
impl PartialOrd for ByteSpan {
fn partial_cmp(&self, other: &ByteSpan) -> Option<Ordering> {
Some(self.cmp(other))
}
}
pub trait LeafSpans {
fn leaf_spans(&self) -> Vec<ByteSpan>;
}
impl<T> LeafSpans for Braces<T>
where
T: LeafSpans + Clone,
{
fn leaf_spans(&self) -> Vec<ByteSpan> {
let mut collected_spans = Vec::new();
let mut opening_brace_span = ByteSpan::from(self.span());
opening_brace_span.end = opening_brace_span.start + 1;
collected_spans.push(opening_brace_span);
collected_spans.append(&mut self.clone().into_inner().leaf_spans());
let mut closing_brace_span = ByteSpan::from(self.span());
closing_brace_span.start = closing_brace_span.end - 1;
collected_spans.push(closing_brace_span);
collected_spans
}
}
impl<T> LeafSpans for Parens<T>
where
T: LeafSpans + Clone,
{
fn leaf_spans(&self) -> Vec<ByteSpan> {
let mut collected_spans = Vec::new();
let mut opening_paren_span = ByteSpan::from(self.span());
opening_paren_span.end = opening_paren_span.start + 1;
collected_spans.push(opening_paren_span);
collected_spans.append(&mut self.clone().into_inner().leaf_spans());
let mut closing_paren_span = ByteSpan::from(self.span());
closing_paren_span.start = closing_paren_span.end - 1;
collected_spans.push(closing_paren_span);
collected_spans
}
}
impl<T> LeafSpans for SquareBrackets<T>
where
T: LeafSpans + Clone,
{
fn leaf_spans(&self) -> Vec<ByteSpan> {
let mut collected_spans = Vec::new();
let mut opening_bracket_span = ByteSpan::from(self.span());
opening_bracket_span.end = opening_bracket_span.start + 1;
collected_spans.push(opening_bracket_span);
collected_spans.append(&mut self.clone().into_inner().leaf_spans());
let mut closing_bracket_span = ByteSpan::from(self.span());
closing_bracket_span.start = closing_bracket_span.end - 1;
collected_spans.push(closing_bracket_span);
collected_spans
}
}
impl<T, P> LeafSpans for (T, P)
where
T: LeafSpans,
P: LeafSpans,
{
fn leaf_spans(&self) -> Vec<ByteSpan> {
let mut collected_spans = self.0.leaf_spans();
collected_spans.append(&mut self.1.leaf_spans());
collected_spans
}
}
impl<T> LeafSpans for Vec<T>
where
T: LeafSpans,
{
fn leaf_spans(&self) -> Vec<ByteSpan> {
let mut collected_spans = Vec::new();
for t in self {
collected_spans.append(&mut t.leaf_spans());
}
collected_spans
}
}
impl<T> LeafSpans for Annotated<T>
where
T: LeafSpans + Parse,
{
fn leaf_spans(&self) -> Vec<ByteSpan> {
let mut collected_spans = self.attribute_list.leaf_spans();
collected_spans.append(&mut self.value.leaf_spans());
collected_spans
}
}
impl LeafSpans for Ident {
fn leaf_spans(&self) -> Vec<ByteSpan> {
vec![ByteSpan::from(self.span())]
}
}
impl LeafSpans for CommaToken {
fn leaf_spans(&self) -> Vec<ByteSpan> {
vec![(ByteSpan::from(self.span()))]
}
}
impl LeafSpans for TypeField {
fn leaf_spans(&self) -> Vec<ByteSpan> {
let mut collected_spans = Vec::new();
if let Some(visibility) = &self.visibility {
collected_spans.push(ByteSpan::from(visibility.span()));
}
collected_spans.push(ByteSpan::from(self.name.span()));
collected_spans.push(ByteSpan::from(self.colon_token.span()));
collected_spans.append(&mut self.ty.leaf_spans());
collected_spans
}
}
impl LeafSpans for AddToken {
fn leaf_spans(&self) -> Vec<ByteSpan> {
vec![ByteSpan::from(self.span())]
}
}
impl LeafSpans for SemicolonToken {
fn leaf_spans(&self) -> Vec<ByteSpan> {
vec![ByteSpan::from(self.span())]
}
}
impl LeafSpans for ColonToken {
fn leaf_spans(&self) -> Vec<ByteSpan> {
vec![ByteSpan::from(self.span())]
}
}
impl LeafSpans for RightArrowToken {
fn leaf_spans(&self) -> Vec<ByteSpan> {
vec![ByteSpan::from(self.span())]
}
}
impl LeafSpans for ForToken {
fn leaf_spans(&self) -> Vec<ByteSpan> {
vec![ByteSpan::from(self.span())]
}
}
impl LeafSpans for ForwardSlashToken {
fn leaf_spans(&self) -> Vec<ByteSpan> {
vec![ByteSpan::from(self.span())]
}
}
#[cfg(test)]
mod tests {
use super::ByteSpan;
#[test]
fn test_byte_span_ordering() {
let first_span = ByteSpan { start: 2, end: 6 };
let second_span = ByteSpan { start: 2, end: 4 };
let third_span = ByteSpan { start: 4, end: 7 };
let mut vec = [second_span.clone(), third_span.clone(), first_span.clone()];
vec.sort();
assert_eq!(vec[0], first_span);
assert_eq!(vec[1], second_span);
assert_eq!(vec[2], third_span);
}
}