harper-comments 2.0.0

The language checker for developers.
Documentation
use harper_core::Lrc;
use harper_core::Span;
use harper_core::Token;
use harper_core::parsers::{Markdown, MarkdownOptions, Parser};

use super::without_initiators;

#[derive(Clone)]
pub struct Lua {
    inner: Lrc<dyn Parser>,
}

impl Lua {
    pub fn new(parser: Lrc<dyn Parser>) -> Self {
        Self { inner: parser }
    }

    pub fn new_markdown(markdown_options: MarkdownOptions) -> Self {
        Self::new(Lrc::new(Markdown::new(markdown_options)))
    }
}

impl Parser for Lua {
    fn parse(&self, source: &[char]) -> Vec<Token> {
        let mut tokens = Vec::new();

        let mut chars_traversed = 0;

        for line in source.split(|c| *c == '\n') {
            if starts_with_prefix(line) {
                tokens.push(Token::new(
                    Span::empty(chars_traversed),
                    harper_core::TokenKind::Newline(2),
                ));
                chars_traversed += line.len() + 1;
                continue;
            }

            let mut new_tokens = parse_line(line, self.inner.clone());

            if chars_traversed + line.len() < source.len() {
                new_tokens.push(Token::new(
                    Span::new_with_len(line.len(), 1),
                    harper_core::TokenKind::Newline(1),
                ));
            }

            new_tokens
                .iter_mut()
                .for_each(|t| t.span.push_by(chars_traversed));

            chars_traversed += line.len() + 1;
            tokens.append(&mut new_tokens);
        }

        tokens
    }
}

fn starts_with_prefix(source: &[char]) -> bool {
    let actual = without_initiators(source);
    let actual_chars = actual.get_content(source);

    matches!(actual_chars, ['@', ..])
}

fn parse_line(source: &[char], parser: Lrc<dyn Parser>) -> Vec<Token> {
    let actual = without_initiators(source);

    if actual.is_empty() {
        return Vec::new();
    }

    let source = actual.get_content(source);

    let mut new_tokens = parser.parse(source);

    new_tokens
        .iter_mut()
        .for_each(|t| t.span.push_by(actual.start));

    new_tokens
}