use diagnostics::make_errors_for_mismatched_closing_delims;
use rustc_ast::ast::{self, AttrStyle};
use rustc_ast::token::{self, CommentKind, Delimiter, IdentIsRaw, Token, TokenKind};
use rustc_ast::tokenstream::TokenStream;
use rustc_ast::util::unicode::{TEXT_FLOW_CONTROL_CHARS, contains_text_flow_control_chars};
use rustc_errors::codes::*;
use rustc_errors::{Applicability, Diag, DiagCtxtHandle, StashKey};
use rustc_lexer::{
    Base, Cursor, DocStyle, FrontmatterAllowed, LiteralKind, RawStrError, is_horizontal_whitespace,
};
use rustc_literal_escaper::{EscapeError, Mode, check_for_errors};
use rustc_session::lint::BuiltinLintDiag;
use rustc_session::lint::builtin::{
    RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, RUST_2024_GUARDED_STRING_INCOMPATIBLE_SYNTAX,
    TEXT_DIRECTION_CODEPOINT_IN_COMMENT, TEXT_DIRECTION_CODEPOINT_IN_LITERAL,
};
use rustc_session::parse::ParseSess;
use rustc_span::{BytePos, Pos, Span, Symbol, sym};
use tracing::debug;

use crate::errors;
use crate::lexer::diagnostics::TokenTreeDiagInfo;
use crate::lexer::unicode_chars::UNICODE_ARRAY;

mod diagnostics;
mod tokentrees;
mod unescape_error_reporting;
mod unicode_chars;

use unescape_error_reporting::{emit_unescape_error, escaped_char};

// This type is used a lot. Make sure it doesn't unintentionally get bigger.
//
// This assertion is in this crate, rather than in `rustc_lexer`, because that
// crate cannot depend on `rustc_data_structures`.
#[cfg(target_pointer_width = "64")]
rustc_data_structures::static_assert_size!(rustc_lexer::Token, 12);

#[derive(Clone, Debug)]
pub(crate) struct UnmatchedDelim {
    pub found_delim: Option<Delimiter>,
    pub found_span: Span,
    pub unclosed_span: Option<Span>,
    pub candidate_span: Option<Span>,
}

/// Which tokens should be stripped before lexing the tokens.
pub enum StripTokens {
    /// Strip both shebang and frontmatter.
    ShebangAndFrontmatter,
    /// Strip the shebang but not frontmatter.
    ///
    /// That means that char sequences looking like frontmatter are simply
    /// interpreted as regular Rust lexemes.
    Shebang,
    /// Strip nothing.
    ///
    /// In other words, char sequences looking like a shebang or frontmatter
    /// are simply interpreted as regular Rust lexemes.
    Nothing,
}

pub(crate) fn lex_token_trees<'psess, 'src>(
    psess: &'psess ParseSess,
    mut src: &'src str,
    mut start_pos: BytePos,
    override_span: Option<Span>,
    strip_tokens: StripTokens,
) -> Result<TokenStream, Vec<Diag<'psess>>> {
    match strip_tokens {
        StripTokens::Shebang | StripTokens::ShebangAndFrontmatter => {
            if let Some(shebang_len) = rustc_lexer::strip_shebang(src) {
                src = &src[shebang_len..];
                start_pos = start_pos + BytePos::from_usize(shebang_len);
            }
        }
        StripTokens::Nothing => {}
    }

    let frontmatter_allowed = match strip_tokens {
        StripTokens::ShebangAndFrontmatter => FrontmatterAllowed::Yes,
        StripTokens::Shebang | StripTokens::Nothing => FrontmatterAllowed::No,
    };

    let cursor = Cursor::new(src, frontmatter_allowed);
    let mut lexer = Lexer {
        psess,
        start_pos,
        pos: start_pos,
        src,
        cursor,
        override_span,
        nbsp_is_whitespace: false,
        last_lifetime: None,
        token: Token::dummy(),
        diag_info: TokenTreeDiagInfo::default(),
    };
    let res = lexer.lex_token_trees(/* is_delimited */ false);

    let mut unmatched_closing_delims: Vec<_> =
        make_errors_for_mismatched_closing_delims(&lexer.diag_info.unmatched_delims, psess);

    match res {
        Ok((_open_spacing, stream)) => {
            if unmatched_closing_delims.is_empty() {
                Ok(stream)
            } else {
                // Return error if there are unmatched delimiters or unclosed delimiters.
                Err(unmatched_closing_delims)
            }
        }
        Err(errs) => {
            // We emit delimiter mismatch errors first, then emit the unclosing delimiter mismatch
            // because the delimiter mismatch is more likely to be the root cause of error
            unmatched_closing_delims.extend(errs);
            Err(unmatched_closing_delims)
        }
    }
}

struct Lexer<'psess, 'src> {
    psess: &'psess ParseSess,
    /// Initial position, read-only.
    start_pos: BytePos,
    /// The absolute offset within the source_map of the current character.
    pos: BytePos,
    /// Source text to tokenize.
    src: &'src str,
    /// Cursor for getting lexer tokens.
    cursor: Cursor<'src>,
    override_span: Option<Span>,
    /// When a "unknown start of token: \u{a0}" has already been emitted earlier
    /// in this file, it's safe to treat further occurrences of the non-breaking
    /// space character as whitespace.
    nbsp_is_whitespace: bool,

    /// Track the `Span` for the leading `'` of the last lifetime. Used for
    /// diagnostics to detect possible typo where `"` was meant.
    last_lifetime: Option<Span>,

    /// The current token.
    token: Token,

    diag_info: TokenTreeDiagInfo,
}

impl<'psess, 'src> Lexer<'psess, 'src> {
    fn dcx(&self) -> DiagCtxtHandle<'psess> {
        self.psess.dcx()
    }

    fn mk_sp(&self, lo: BytePos, hi: BytePos) -> Span {
        self.override_span.unwrap_or_else(|| Span::with_root_ctxt(lo, hi))
    }

    /// Returns the next token, paired with a bool indicating if the token was
    /// preceded by whitespace.
    fn next_token_from_cursor(&mut self) -> (Token, bool) {
        let mut preceded_by_whitespace = false;
        let mut swallow_next_invalid = 0;
        // Skip trivial (whitespace & comments) tokens
        loop {
            let str_before = self.cursor.as_str();
            let token = self.cursor.advance_token();
            let start = self.pos;
            self.pos = self.pos + BytePos(token.len);

            debug!("next_token: {:?}({:?})", token.kind, self.str_from(start));

            if let rustc_lexer::TokenKind::Semi
            | rustc_lexer::TokenKind::LineComment { .. }
            | rustc_lexer::TokenKind::BlockComment { .. }
            | rustc_lexer::TokenKind::CloseParen
            | rustc_lexer::TokenKind::CloseBrace
            | rustc_lexer::TokenKind::CloseBracket = token.kind
            {
                // Heuristic: we assume that it is unlikely we're dealing with an unterminated
                // string surrounded by single quotes.
                self.last_lifetime = None;
            }

            // Now "cook" the token, converting the simple `rustc_lexer::TokenKind` enum into a
            // rich `rustc_ast::TokenKind`. This turns strings into interned symbols and runs
            // additional validation.
            let kind = match token.kind {
                rustc_lexer::TokenKind::LineComment { doc_style } => {
                    // Skip non-doc comments
                    let Some(doc_style) = doc_style else {
                        self.lint_unicode_text_flow(start);
                        preceded_by_whitespace = true;
                        continue;
                    };

                    // Opening delimiter of the length 3 is not included into the symbol.
                    let content_start = start + BytePos(3);
                    let content = self.str_from(content_start);
                    self.lint_doc_comment_unicode_text_flow(start, content);
                    self.cook_doc_comment(content_start, content, CommentKind::Line, doc_style)
                }
                rustc_lexer::TokenKind::BlockComment { doc_style, terminated } => {
                    if !terminated {
                        self.report_unterminated_block_comment(start, doc_style);
                    }

                    // Skip non-doc comments
                    let Some(doc_style) = doc_style else {
                        self.lint_unicode_text_flow(start);
                        preceded_by_whitespace = true;
                        continue;
                    };

                    // Opening delimiter of the length 3 and closing delimiter of the length 2
                    // are not included into the symbol.
                    let content_start = start + BytePos(3);
                    let content_end = self.pos - BytePos(if terminated { 2 } else { 0 });
                    let content = self.str_from_to(content_start, content_end);
                    self.lint_doc_comment_unicode_text_flow(start, content);
                    self.cook_doc_comment(content_start, content, CommentKind::Block, doc_style)
                }
                rustc_lexer::TokenKind::Frontmatter { has_invalid_preceding_whitespace, invalid_infostring } => {
                    self.validate_frontmatter(start, has_invalid_preceding_whitespace, invalid_infostring);
                    preceded_by_whitespace = true;
                    continue;
                }
                rustc_lexer::TokenKind::Whitespace => {
                    preceded_by_whitespace = true;
                    continue;
                }
                rustc_lexer::TokenKind::Ident => self.ident(start),
                rustc_lexer::TokenKind::RawIdent => {
                    let sym = nfc_normalize(self.str_from(start + BytePos(2)));
                    let span = self.mk_sp(start, self.pos);
                    self.psess.symbol_gallery.insert(sym, span);
                    if !sym.can_be_raw() {
                        self.dcx().emit_err(errors::CannotBeRawIdent { span, ident: sym });
                    }
                    self.psess.raw_identifier_spans.push(span);
                    token::Ident(sym, IdentIsRaw::Yes)
                }
                rustc_lexer::TokenKind::UnknownPrefix => {
                    self.report_unknown_prefix(start);
                    self.ident(start)
                }
                rustc_lexer::TokenKind::UnknownPrefixLifetime => {
                    self.report_unknown_prefix(start);
                    // Include the leading `'` in the real identifier, for macro
                    // expansion purposes. See #12512 for the gory details of why
                    // this is necessary.
                    let lifetime_name = self.str_from(start);
                    self.last_lifetime = Some(self.mk_sp(start, start + BytePos(1)));
                    let ident = Symbol::intern(lifetime_name);
                    token::Lifetime(ident, IdentIsRaw::No)
                }
                rustc_lexer::TokenKind::InvalidIdent
                    // Do not recover an identifier with emoji if the codepoint is a confusable
                    // with a recoverable substitution token, like `➖`.
                    if !UNICODE_ARRAY.iter().any(|&(c, _, _)| {
                        let sym = self.str_from(start);
                        sym.chars().count() == 1 && c == sym.chars().next().unwrap()
                    }) =>
                {
                    let sym = nfc_normalize(self.str_from(start));
                    let span = self.mk_sp(start, self.pos);
                    self.psess
                        .bad_unicode_identifiers
                        .borrow_mut()
                        .entry(sym)
                        .or_default()
                        .push(span);
                    token::Ident(sym, IdentIsRaw::No)
                }
                // split up (raw) c string literals to an ident and a string literal when edition <
                // 2021.
                rustc_lexer::TokenKind::Literal {
                    kind: kind @ (LiteralKind::CStr { .. } | LiteralKind::RawCStr { .. }),
                    suffix_start: _,
                } if !self.mk_sp(start, self.pos).edition().at_least_rust_2021() => {
                    let prefix_len = match kind {
                        LiteralKind::CStr { .. } => 1,
                        LiteralKind::RawCStr { .. } => 2,
                        _ => unreachable!(),
                    };

                    // reset the state so that only the prefix ("c" or "cr")
                    // was consumed.
                    let lit_start = start + BytePos(prefix_len);
                    self.pos = lit_start;
                    self.cursor = Cursor::new(&str_before[prefix_len as usize..], FrontmatterAllowed::No);
                    self.report_unknown_prefix(start);
                    let prefix_span = self.mk_sp(start, lit_start);
                    return (Token::new(self.ident(start), prefix_span), preceded_by_whitespace);
                }
                rustc_lexer::TokenKind::GuardedStrPrefix => {
                    self.maybe_report_guarded_str(start, str_before)
                }
                rustc_lexer::TokenKind::Literal { kind, suffix_start } => {
                    let suffix_start = start + BytePos(suffix_start);
                    let (kind, symbol) = self.cook_lexer_literal(start, suffix_start, kind);
                    let suffix = if suffix_start < self.pos {
                        let string = self.str_from(suffix_start);
                        if string == "_" {
                            self.dcx().emit_err(errors::UnderscoreLiteralSuffix {
                                span: self.mk_sp(suffix_start, self.pos),
                            });
                            None
                        } else {
                            Some(Symbol::intern(string))
                        }
                    } else {
                        None
                    };
                    self.lint_literal_unicode_text_flow(symbol, kind, self.mk_sp(start, self.pos), "literal");
                    token::Literal(token::Lit { kind, symbol, suffix })
                }
                rustc_lexer::TokenKind::Lifetime { starts_with_number } => {
                    // Include the leading `'` in the real identifier, for macro
                    // expansion purposes. See #12512 for the gory details of why
                    // this is necessary.
                    let lifetime_name = self.str_from(start);
                    self.last_lifetime = Some(self.mk_sp(start, start + BytePos(1)));
                    if starts_with_number {
                        let span = self.mk_sp(start, self.pos);
                        self.dcx()
                            .struct_err("lifetimes cannot start with a number")
                            .with_span(span)
                            .stash(span, StashKey::LifetimeIsChar);
                    }
                    let ident = Symbol::intern(lifetime_name);
                    token::Lifetime(ident, IdentIsRaw::No)
                }
                rustc_lexer::TokenKind::RawLifetime => {
                    self.last_lifetime = Some(self.mk_sp(start, start + BytePos(1)));

                    let ident_start = start + BytePos(3);
                    let prefix_span = self.mk_sp(start, ident_start);

                    if prefix_span.at_least_rust_2021() {
                        // If the raw lifetime is followed by \' then treat it a normal
                        // lifetime followed by a \', which is to interpret it as a character
                        // literal. In this case, it's always an invalid character literal
                        // since the literal must necessarily have >3 characters (r#...) inside
                        // of it, which is invalid.
                        if self.cursor.as_str().starts_with('\'') {
                            let lit_span = self.mk_sp(start, self.pos + BytePos(1));
                            let contents = self.str_from_to(start + BytePos(1), self.pos);
                            emit_unescape_error(
                                self.dcx(),
                                contents,
                                lit_span,
                                lit_span,
                                Mode::Char,
                                0..contents.len(),
                                EscapeError::MoreThanOneChar,
                            )
                            .expect("expected error");
                        }

                        let span = self.mk_sp(start, self.pos);

                        let lifetime_name_without_tick =
                            Symbol::intern(&self.str_from(ident_start));
                        if !lifetime_name_without_tick.can_be_raw() {
                            self.dcx().emit_err(
                                errors::CannotBeRawLifetime {
                                    span,
                                    ident: lifetime_name_without_tick
                                }
                            );
                        }

                        // Put the `'` back onto the lifetime name.
                        let mut lifetime_name =
                            String::with_capacity(lifetime_name_without_tick.as_str().len() + 1);
                        lifetime_name.push('\'');
                        lifetime_name += lifetime_name_without_tick.as_str();
                        let sym = Symbol::intern(&lifetime_name);

                        // Make sure we mark this as a raw identifier.
                        self.psess.raw_identifier_spans.push(span);

                        token::Lifetime(sym, IdentIsRaw::Yes)
                    } else {
                        // Otherwise, this should be parsed like `'r`. Warn about it though.
                        self.psess.buffer_lint(
                            RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX,
                            prefix_span,
                            ast::CRATE_NODE_ID,
                            BuiltinLintDiag::RawPrefix(prefix_span),
                        );

                        // Reset the state so we just lex the `'r`.
                        let lt_start = start + BytePos(2);
                        self.pos = lt_start;
                        self.cursor = Cursor::new(&str_before[2 as usize..], FrontmatterAllowed::No);

                        let lifetime_name = self.str_from(start);
                        let ident = Symbol::intern(lifetime_name);
                        token::Lifetime(ident, IdentIsRaw::No)
                    }
                }
                rustc_lexer::TokenKind::Semi => token::Semi,
                rustc_lexer::TokenKind::Comma => token::Comma,
                rustc_lexer::TokenKind::Dot => token::Dot,
                rustc_lexer::TokenKind::OpenParen => token::OpenParen,
                rustc_lexer::TokenKind::CloseParen => token::CloseParen,
                rustc_lexer::TokenKind::OpenBrace => token::OpenBrace,
                rustc_lexer::TokenKind::CloseBrace => token::CloseBrace,
                rustc_lexer::TokenKind::OpenBracket => token::OpenBracket,
                rustc_lexer::TokenKind::CloseBracket => token::CloseBracket,
                rustc_lexer::TokenKind::At => token::At,
                rustc_lexer::TokenKind::Pound => token::Pound,
                rustc_lexer::TokenKind::Tilde => token::Tilde,
                rustc_lexer::TokenKind::Question => token::Question,
                rustc_lexer::TokenKind::Colon => token::Colon,
                rustc_lexer::TokenKind::Dollar => token::Dollar,
                rustc_lexer::TokenKind::Eq => token::Eq,
                rustc_lexer::TokenKind::Bang => token::Bang,
                rustc_lexer::TokenKind::Lt => token::Lt,
                rustc_lexer::TokenKind::Gt => token::Gt,
                rustc_lexer::TokenKind::Minus => token::Minus,
                rustc_lexer::TokenKind::And => token::And,
                rustc_lexer::TokenKind::Or => token::Or,
                rustc_lexer::TokenKind::Plus => token::Plus,
                rustc_lexer::TokenKind::Star => token::Star,
                rustc_lexer::TokenKind::Slash => token::Slash,
                rustc_lexer::TokenKind::Caret => token::Caret,
                rustc_lexer::TokenKind::Percent => token::Percent,

                rustc_lexer::TokenKind::Unknown | rustc_lexer::TokenKind::InvalidIdent => {
                    // Don't emit diagnostics for sequences of the same invalid token
                    if swallow_next_invalid > 0 {
                        swallow_next_invalid -= 1;
                        continue;
                    }
                    let mut it = self.str_from_to_end(start).chars();
                    let c = it.next().unwrap();
                    if c == '\u{00a0}' {
                        // If an error has already been reported on non-breaking
                        // space characters earlier in the file, treat all
                        // subsequent occurrences as whitespace.
                        if self.nbsp_is_whitespace {
                            preceded_by_whitespace = true;
                            continue;
                        }
                        self.nbsp_is_whitespace = true;
                    }
                    let repeats = it.take_while(|c1| *c1 == c).count();
                    // FIXME: the lexer could be used to turn the ASCII version of unicode
                    // homoglyphs, instead of keeping a table in `check_for_substitution`into the
                    // token. Ideally, this should be inside `rustc_lexer`. However, we should
                    // first remove compound tokens like `<<` from `rustc_lexer`, and then add
                    // fancier error recovery to it, as there will be less overall work to do this
                    // way.
                    let (token, sugg) =
                        unicode_chars::check_for_substitution(self, start, c, repeats + 1);
                    self.dcx().emit_err(errors::UnknownTokenStart {
                        span: self.mk_sp(start, self.pos + Pos::from_usize(repeats * c.len_utf8())),
                        escaped: escaped_char(c),
                        sugg,
                        null: if c == '\x00' { Some(errors::UnknownTokenNull) } else { None },
                        repeat: if repeats > 0 {
                            swallow_next_invalid = repeats;
                            Some(errors::UnknownTokenRepeat { repeats })
                        } else {
                            None
                        },
                    });

                    if let Some(token) = token {
                        token
                    } else {
                        preceded_by_whitespace = true;
                        continue;
                    }
                }
                rustc_lexer::TokenKind::Eof => token::Eof,
            };
            let span = self.mk_sp(start, self.pos);
            return (Token::new(kind, span), preceded_by_whitespace);
        }
    }

    fn ident(&self, start: BytePos) -> TokenKind {
        let sym = nfc_normalize(self.str_from(start));
        let span = self.mk_sp(start, self.pos);
        self.psess.symbol_gallery.insert(sym, span);
        token::Ident(sym, IdentIsRaw::No)
    }

    /// Detect usages of Unicode codepoints changing the direction of the text on screen and loudly
    /// complain about it.
    fn lint_unicode_text_flow(&self, start: BytePos) {
        // Opening delimiter of the length 2 is not included into the comment text.
        let content_start = start + BytePos(2);
        let content = self.str_from(content_start);
        if contains_text_flow_control_chars(content) {
            let span = self.mk_sp(start, self.pos);
            self.psess.buffer_lint(
                TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
                span,
                ast::CRATE_NODE_ID,
                BuiltinLintDiag::UnicodeTextFlow(span, content.to_string()),
            );
        }
    }

    fn lint_doc_comment_unicode_text_flow(&mut self, start: BytePos, content: &str) {
        if contains_text_flow_control_chars(content) {
            self.report_text_direction_codepoint(
                content,
                self.mk_sp(start, self.pos),
                0,
                false,
                "doc comment",
            );
        }
    }

    fn lint_literal_unicode_text_flow(
        &mut self,
        text: Symbol,
        lit_kind: token::LitKind,
        span: Span,
        label: &'static str,
    ) {
        if !contains_text_flow_control_chars(text.as_str()) {
            return;
        }
        let (padding, point_at_inner_spans) = match lit_kind {
            // account for `"` or `'`
            token::LitKind::Str | token::LitKind::Char => (1, true),
            // account for `c"`
            token::LitKind::CStr => (2, true),
            // account for `r###"`
            token::LitKind::StrRaw(n) => (n as u32 + 2, true),
            // account for `cr###"`
            token::LitKind::CStrRaw(n) => (n as u32 + 3, true),
            // suppress bad literals.
            token::LitKind::Err(_) => return,
            // Be conservative just in case new literals do support these.
            _ => (0, false),
        };
        self.report_text_direction_codepoint(
            text.as_str(),
            span,
            padding,
            point_at_inner_spans,
            label,
        );
    }

    fn report_text_direction_codepoint(
        &self,
        text: &str,
        span: Span,
        padding: u32,
        point_at_inner_spans: bool,
        label: &str,
    ) {
        // Obtain the `Span`s for each of the forbidden chars.
        let spans: Vec<_> = text
            .char_indices()
            .filter_map(|(i, c)| {
                TEXT_FLOW_CONTROL_CHARS.contains(&c).then(|| {
                    let lo = span.lo() + BytePos(i as u32 + padding);
                    (c, span.with_lo(lo).with_hi(lo + BytePos(c.len_utf8() as u32)))
                })
            })
            .collect();

        let label = label.to_string();
        let count = spans.len();
        let labels = point_at_inner_spans
            .then_some(errors::HiddenUnicodeCodepointsDiagLabels { spans: spans.clone() });
        let sub = if point_at_inner_spans && !spans.is_empty() {
            errors::HiddenUnicodeCodepointsDiagSub::Escape { spans }
        } else {
            errors::HiddenUnicodeCodepointsDiagSub::NoEscape { spans }
        };

        self.psess.buffer_lint(
            TEXT_DIRECTION_CODEPOINT_IN_LITERAL,
            span,
            ast::CRATE_NODE_ID,
            errors::HiddenUnicodeCodepointsDiag { label, count, span_label: span, labels, sub },
        );
    }

    fn validate_frontmatter(
        &self,
        start: BytePos,
        has_invalid_preceding_whitespace: bool,
        invalid_infostring: bool,
    ) {
        let s = self.str_from(start);
        let real_start = s.find("---").unwrap();
        let frontmatter_opening_pos = BytePos(real_start as u32) + start;
        let s_new = &s[real_start..];
        let within = s_new.trim_start_matches('-');
        let len_opening = s_new.len() - within.len();

        let frontmatter_opening_end_pos = frontmatter_opening_pos + BytePos(len_opening as u32);
        if has_invalid_preceding_whitespace {
            let line_start =
                BytePos(s[..real_start].rfind("\n").map_or(0, |i| i as u32 + 1)) + start;
            let span = self.mk_sp(line_start, frontmatter_opening_end_pos);
            let label_span = self.mk_sp(line_start, frontmatter_opening_pos);
            self.dcx().emit_err(errors::FrontmatterInvalidOpeningPrecedingWhitespace {
                span,
                note_span: label_span,
            });
        }

        if invalid_infostring {
            let line_end = s[real_start..].find('\n').unwrap_or(s[real_start..].len());
            let span = self.mk_sp(
                frontmatter_opening_end_pos,
                frontmatter_opening_pos + BytePos(line_end as u32),
            );
            self.dcx().emit_err(errors::FrontmatterInvalidInfostring { span });
        }

        let last_line_start = within.rfind('\n').map_or(0, |i| i + 1);
        let last_line = &within[last_line_start..];
        let last_line_trimmed = last_line.trim_start_matches(is_horizontal_whitespace);
        let last_line_start_pos = frontmatter_opening_end_pos + BytePos(last_line_start as u32);

        let frontmatter_span = self.mk_sp(frontmatter_opening_pos, self.pos);
        self.psess.gated_spans.gate(sym::frontmatter, frontmatter_span);

        if !last_line_trimmed.starts_with("---") {
            let label_span = self.mk_sp(frontmatter_opening_pos, frontmatter_opening_end_pos);
            self.dcx().emit_err(errors::FrontmatterUnclosed {
                span: frontmatter_span,
                note_span: label_span,
            });
            return;
        }

        if last_line_trimmed.len() != last_line.len() {
            let line_end = last_line_start_pos + BytePos(last_line.len() as u32);
            let span = self.mk_sp(last_line_start_pos, line_end);
            let whitespace_end =
                last_line_start_pos + BytePos((last_line.len() - last_line_trimmed.len()) as u32);
            let label_span = self.mk_sp(last_line_start_pos, whitespace_end);
            self.dcx().emit_err(errors::FrontmatterInvalidClosingPrecedingWhitespace {
                span,
                note_span: label_span,
            });
        }

        let rest = last_line_trimmed.trim_start_matches('-');
        let len_close = last_line_trimmed.len() - rest.len();
        if len_close != len_opening {
            let span = self.mk_sp(frontmatter_opening_pos, self.pos);
            let opening = self.mk_sp(frontmatter_opening_pos, frontmatter_opening_end_pos);
            let last_line_close_pos = last_line_start_pos + BytePos(len_close as u32);
            let close = self.mk_sp(last_line_start_pos, last_line_close_pos);
            self.dcx().emit_err(errors::FrontmatterLengthMismatch {
                span,
                opening,
                close,
                len_opening,
                len_close,
            });
        }

        if !rest.trim_matches(is_horizontal_whitespace).is_empty() {
            let span = self.mk_sp(last_line_start_pos, self.pos);
            self.dcx().emit_err(errors::FrontmatterExtraCharactersAfterClose { span });
        }
    }

    fn cook_doc_comment(
        &self,
        content_start: BytePos,
        content: &str,
        comment_kind: CommentKind,
        doc_style: DocStyle,
    ) -> TokenKind {
        if content.contains('\r') {
            for (idx, _) in content.char_indices().filter(|&(_, c)| c == '\r') {
                let span = self.mk_sp(
                    content_start + BytePos(idx as u32),
                    content_start + BytePos(idx as u32 + 1),
                );
                let block = matches!(comment_kind, CommentKind::Block);
                self.dcx().emit_err(errors::CrDocComment { span, block });
            }
        }

        let attr_style = match doc_style {
            DocStyle::Outer => AttrStyle::Outer,
            DocStyle::Inner => AttrStyle::Inner,
        };

        token::DocComment(comment_kind, attr_style, Symbol::intern(content))
    }

    fn cook_lexer_literal(
        &self,
        start: BytePos,
        end: BytePos,
        kind: rustc_lexer::LiteralKind,
    ) -> (token::LitKind, Symbol) {
        match kind {
            rustc_lexer::LiteralKind::Char { terminated } => {
                if !terminated {
                    let mut err = self
                        .dcx()
                        .struct_span_fatal(self.mk_sp(start, end), "unterminated character literal")
                        .with_code(E0762);
                    if let Some(lt_sp) = self.last_lifetime {
                        err.multipart_suggestion(
                            "if you meant to write a string literal, use double quotes",
                            vec![
                                (lt_sp, "\"".to_string()),
                                (self.mk_sp(start, start + BytePos(1)), "\"".to_string()),
                            ],
                            Applicability::MaybeIncorrect,
                        );
                    }
                    err.emit()
                }
                self.cook_quoted(token::Char, Mode::Char, start, end, 1, 1) // ' '
            }
            rustc_lexer::LiteralKind::Byte { terminated } => {
                if !terminated {
                    self.dcx()
                        .struct_span_fatal(
                            self.mk_sp(start + BytePos(1), end),
                            "unterminated byte constant",
                        )
                        .with_code(E0763)
                        .emit()
                }
                self.cook_quoted(token::Byte, Mode::Byte, start, end, 2, 1) // b' '
            }
            rustc_lexer::LiteralKind::Str { terminated } => {
                if !terminated {
                    self.dcx()
                        .struct_span_fatal(
                            self.mk_sp(start, end),
                            "unterminated double quote string",
                        )
                        .with_code(E0765)
                        .emit()
                }
                self.cook_quoted(token::Str, Mode::Str, start, end, 1, 1) // " "
            }
            rustc_lexer::LiteralKind::ByteStr { terminated } => {
                if !terminated {
                    self.dcx()
                        .struct_span_fatal(
                            self.mk_sp(start + BytePos(1), end),
                            "unterminated double quote byte string",
                        )
                        .with_code(E0766)
                        .emit()
                }
                self.cook_quoted(token::ByteStr, Mode::ByteStr, start, end, 2, 1)
                // b" "
            }
            rustc_lexer::LiteralKind::CStr { terminated } => {
                if !terminated {
                    self.dcx()
                        .struct_span_fatal(
                            self.mk_sp(start + BytePos(1), end),
                            "unterminated C string",
                        )
                        .with_code(E0767)
                        .emit()
                }
                self.cook_quoted(token::CStr, Mode::CStr, start, end, 2, 1) // c" "
            }
            rustc_lexer::LiteralKind::RawStr { n_hashes } => {
                if let Some(n_hashes) = n_hashes {
                    let n = u32::from(n_hashes);
                    let kind = token::StrRaw(n_hashes);
                    self.cook_quoted(kind, Mode::RawStr, start, end, 2 + n, 1 + n)
                // r##" "##
                } else {
                    self.report_raw_str_error(start, 1);
                }
            }
            rustc_lexer::LiteralKind::RawByteStr { n_hashes } => {
                if let Some(n_hashes) = n_hashes {
                    let n = u32::from(n_hashes);
                    let kind = token::ByteStrRaw(n_hashes);
                    self.cook_quoted(kind, Mode::RawByteStr, start, end, 3 + n, 1 + n)
                // br##" "##
                } else {
                    self.report_raw_str_error(start, 2);
                }
            }
            rustc_lexer::LiteralKind::RawCStr { n_hashes } => {
                if let Some(n_hashes) = n_hashes {
                    let n = u32::from(n_hashes);
                    let kind = token::CStrRaw(n_hashes);
                    self.cook_quoted(kind, Mode::RawCStr, start, end, 3 + n, 1 + n)
                // cr##" "##
                } else {
                    self.report_raw_str_error(start, 2);
                }
            }
            rustc_lexer::LiteralKind::Int { base, empty_int } => {
                let mut kind = token::Integer;
                if empty_int {
                    let span = self.mk_sp(start, end);
                    let guar = self.dcx().emit_err(errors::NoDigitsLiteral { span });
                    kind = token::Err(guar);
                } else if matches!(base, Base::Binary | Base::Octal) {
                    let base = base as u32;
                    let s = self.str_from_to(start + BytePos(2), end);
                    for (idx, c) in s.char_indices() {
                        let span = self.mk_sp(
                            start + BytePos::from_usize(2 + idx),
                            start + BytePos::from_usize(2 + idx + c.len_utf8()),
                        );
                        if c != '_' && c.to_digit(base).is_none() {
                            let guar =
                                self.dcx().emit_err(errors::InvalidDigitLiteral { span, base });
                            kind = token::Err(guar);
                        }
                    }
                }
                (kind, self.symbol_from_to(start, end))
            }
            rustc_lexer::LiteralKind::Float { base, empty_exponent } => {
                let mut kind = token::Float;
                if empty_exponent {
                    let span = self.mk_sp(start, self.pos);
                    let guar = self.dcx().emit_err(errors::EmptyExponentFloat { span });
                    kind = token::Err(guar);
                }
                let base = match base {
                    Base::Hexadecimal => Some("hexadecimal"),
                    Base::Octal => Some("octal"),
                    Base::Binary => Some("binary"),
                    _ => None,
                };
                if let Some(base) = base {
                    let span = self.mk_sp(start, end);
                    let guar =
                        self.dcx().emit_err(errors::FloatLiteralUnsupportedBase { span, base });
                    kind = token::Err(guar)
                }
                (kind, self.symbol_from_to(start, end))
            }
        }
    }

    #[inline]
    fn src_index(&self, pos: BytePos) -> usize {
        (pos - self.start_pos).to_usize()
    }

    /// Slice of the source text from `start` up to but excluding `self.pos`,
    /// meaning the slice does not include the character `self.ch`.
    fn str_from(&self, start: BytePos) -> &'src str {
        self.str_from_to(start, self.pos)
    }

    /// As symbol_from, with an explicit endpoint.
    fn symbol_from_to(&self, start: BytePos, end: BytePos) -> Symbol {
        debug!("taking an ident from {:?} to {:?}", start, end);
        Symbol::intern(self.str_from_to(start, end))
    }

    /// Slice of the source text spanning from `start` up to but excluding `end`.
    fn str_from_to(&self, start: BytePos, end: BytePos) -> &'src str {
        &self.src[self.src_index(start)..self.src_index(end)]
    }

    /// Slice of the source text spanning from `start` until the end
    fn str_from_to_end(&self, start: BytePos) -> &'src str {
        &self.src[self.src_index(start)..]
    }

    fn report_raw_str_error(&self, start: BytePos, prefix_len: u32) -> ! {
        match rustc_lexer::validate_raw_str(self.str_from(start), prefix_len) {
            Err(RawStrError::InvalidStarter { bad_char }) => {
                self.report_non_started_raw_string(start, bad_char)
            }
            Err(RawStrError::NoTerminator { expected, found, possible_terminator_offset }) => self
                .report_unterminated_raw_string(start, expected, possible_terminator_offset, found),
            Err(RawStrError::TooManyDelimiters { found }) => {
                self.report_too_many_hashes(start, found)
            }
            Ok(()) => panic!("no error found for supposedly invalid raw string literal"),
        }
    }

    fn report_non_started_raw_string(&self, start: BytePos, bad_char: char) -> ! {
        self.dcx()
            .struct_span_fatal(
                self.mk_sp(start, self.pos),
                format!(
                    "found invalid character; only `#` is allowed in raw string delimitation: {}",
                    escaped_char(bad_char)
                ),
            )
            .emit()
    }

    fn report_unterminated_raw_string(
        &self,
        start: BytePos,
        n_hashes: u32,
        possible_offset: Option<u32>,
        found_terminators: u32,
    ) -> ! {
        let mut err =
            self.dcx().struct_span_fatal(self.mk_sp(start, start), "unterminated raw string");
        err.code(E0748);
        err.span_label(self.mk_sp(start, start), "unterminated raw string");

        if n_hashes > 0 {
            err.note(format!(
                "this raw string should be terminated with `\"{}`",
                "#".repeat(n_hashes as usize)
            ));
        }

        if let Some(possible_offset) = possible_offset {
            let lo = start + BytePos(possible_offset);
            let hi = lo + BytePos(found_terminators);
            let span = self.mk_sp(lo, hi);
            err.span_suggestion(
                span,
                "consider terminating the string here",
                "#".repeat(n_hashes as usize),
                Applicability::MaybeIncorrect,
            );
        }

        err.emit()
    }

    fn report_unterminated_block_comment(&self, start: BytePos, doc_style: Option<DocStyle>) {
        let msg = match doc_style {
            Some(_) => "unterminated block doc-comment",
            None => "unterminated block comment",
        };
        let last_bpos = self.pos;
        let mut err = self.dcx().struct_span_fatal(self.mk_sp(start, last_bpos), msg);
        err.code(E0758);
        let mut nested_block_comment_open_idxs = vec![];
        let mut last_nested_block_comment_idxs = None;
        let mut content_chars = self.str_from(start).char_indices().peekable();

        while let Some((idx, current_char)) = content_chars.next() {
            match content_chars.peek() {
                Some((_, '*')) if current_char == '/' => {
                    nested_block_comment_open_idxs.push(idx);
                }
                Some((_, '/')) if current_char == '*' => {
                    last_nested_block_comment_idxs =
                        nested_block_comment_open_idxs.pop().map(|open_idx| (open_idx, idx));
                }
                _ => {}
            };
        }

        if let Some((nested_open_idx, nested_close_idx)) = last_nested_block_comment_idxs {
            err.span_label(self.mk_sp(start, start + BytePos(2)), msg)
                .span_label(
                    self.mk_sp(
                        start + BytePos(nested_open_idx as u32),
                        start + BytePos(nested_open_idx as u32 + 2),
                    ),
                    "...as last nested comment starts here, maybe you want to close this instead?",
                )
                .span_label(
                    self.mk_sp(
                        start + BytePos(nested_close_idx as u32),
                        start + BytePos(nested_close_idx as u32 + 2),
                    ),
                    "...and last nested comment terminates here.",
                );
        }

        err.emit();
    }

    // RFC 3101 introduced the idea of (reserved) prefixes. As of Rust 2021,
    // using a (unknown) prefix is an error. In earlier editions, however, they
    // only result in a (allowed by default) lint, and are treated as regular
    // identifier tokens.
    fn report_unknown_prefix(&self, start: BytePos) {
        let prefix_span = self.mk_sp(start, self.pos);
        let prefix = self.str_from_to(start, self.pos);
        let expn_data = prefix_span.ctxt().outer_expn_data();

        if expn_data.edition.at_least_rust_2021() {
            // In Rust 2021, this is a hard error.
            let sugg = if prefix == "rb" {
                Some(errors::UnknownPrefixSugg::UseBr(prefix_span))
            } else if prefix == "rc" {
                Some(errors::UnknownPrefixSugg::UseCr(prefix_span))
            } else if expn_data.is_root() {
                if self.cursor.first() == '\''
                    && let Some(start) = self.last_lifetime
                    && self.cursor.third() != '\''
                    && let end = self.mk_sp(self.pos, self.pos + BytePos(1))
                    && !self.psess.source_map().is_multiline(start.until(end))
                {
                    // FIXME: An "unclosed `char`" error will be emitted already in some cases,
                    // but it's hard to silence this error while not also silencing important cases
                    // too. We should use the error stashing machinery instead.
                    Some(errors::UnknownPrefixSugg::MeantStr { start, end })
                } else {
                    Some(errors::UnknownPrefixSugg::Whitespace(prefix_span.shrink_to_hi()))
                }
            } else {
                None
            };
            self.dcx().emit_err(errors::UnknownPrefix { span: prefix_span, prefix, sugg });
        } else {
            // Before Rust 2021, only emit a lint for migration.
            self.psess.buffer_lint(
                RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX,
                prefix_span,
                ast::CRATE_NODE_ID,
                BuiltinLintDiag::ReservedPrefix(prefix_span, prefix.to_string()),
            );
        }
    }

    /// Detect guarded string literal syntax
    ///
    /// RFC 3593 reserved this syntax for future use. As of Rust 2024,
    /// using this syntax produces an error. In earlier editions, however, it
    /// only results in an (allowed by default) lint, and is treated as
    /// separate tokens.
    fn maybe_report_guarded_str(&mut self, start: BytePos, str_before: &'src str) -> TokenKind {
        let span = self.mk_sp(start, self.pos);
        let edition2024 = span.edition().at_least_rust_2024();

        let space_pos = start + BytePos(1);
        let space_span = self.mk_sp(space_pos, space_pos);

        let mut cursor = Cursor::new(str_before, FrontmatterAllowed::No);

        let (is_string, span, unterminated) = match cursor.guarded_double_quoted_string() {
            Some(rustc_lexer::GuardedStr { n_hashes, terminated, token_len }) => {
                let end = start + BytePos(token_len);
                let span = self.mk_sp(start, end);
                let str_start = start + BytePos(n_hashes);

                if edition2024 {
                    self.cursor = cursor;
                    self.pos = end;
                }

                let unterminated = if terminated { None } else { Some(str_start) };

                (true, span, unterminated)
            }
            None => {
                // We should only get here in the `##+` case.
                debug_assert_eq!(self.str_from_to(start, start + BytePos(2)), "##");

                (false, span, None)
            }
        };
        if edition2024 {
            if let Some(str_start) = unterminated {
                // Only a fatal error if string is unterminated.
                self.dcx()
                    .struct_span_fatal(
                        self.mk_sp(str_start, self.pos),
                        "unterminated double quote string",
                    )
                    .with_code(E0765)
                    .emit()
            }

            let sugg = if span.from_expansion() {
                None
            } else {
                Some(errors::GuardedStringSugg(space_span))
            };

            // In Edition 2024 and later, emit a hard error.
            let err = if is_string {
                self.dcx().emit_err(errors::ReservedString { span, sugg })
            } else {
                self.dcx().emit_err(errors::ReservedMultihash { span, sugg })
            };

            token::Literal(token::Lit {
                kind: token::Err(err),
                symbol: self.symbol_from_to(start, self.pos),
                suffix: None,
            })
        } else {
            // Before Rust 2024, only emit a lint for migration.
            self.psess.buffer_lint(
                RUST_2024_GUARDED_STRING_INCOMPATIBLE_SYNTAX,
                span,
                ast::CRATE_NODE_ID,
                BuiltinLintDiag::ReservedString { is_string, suggestion: space_span },
            );

            // For backwards compatibility, roll back to after just the first `#`
            // and return the `Pound` token.
            self.pos = start + BytePos(1);
            self.cursor = Cursor::new(&str_before[1..], FrontmatterAllowed::No);
            token::Pound
        }
    }

    fn report_too_many_hashes(&self, start: BytePos, num: u32) -> ! {
        self.dcx().emit_fatal(errors::TooManyHashes { span: self.mk_sp(start, self.pos), num });
    }

    fn cook_quoted(
        &self,
        mut kind: token::LitKind,
        mode: Mode,
        start: BytePos,
        end: BytePos,
        prefix_len: u32,
        postfix_len: u32,
    ) -> (token::LitKind, Symbol) {
        let content_start = start + BytePos(prefix_len);
        let content_end = end - BytePos(postfix_len);
        let lit_content = self.str_from_to(content_start, content_end);
        check_for_errors(lit_content, mode, |range, err| {
            let span_with_quotes = self.mk_sp(start, end);
            let (start, end) = (range.start as u32, range.end as u32);
            let lo = content_start + BytePos(start);
            let hi = lo + BytePos(end - start);
            let span = self.mk_sp(lo, hi);
            let is_fatal = err.is_fatal();
            if let Some(guar) = emit_unescape_error(
                self.dcx(),
                lit_content,
                span_with_quotes,
                span,
                mode,
                range,
                err,
            ) {
                assert!(is_fatal);
                kind = token::Err(guar);
            }
        });

        // We normally exclude the quotes for the symbol, but for errors we
        // include it because it results in clearer error messages.
        let sym = if !matches!(kind, token::Err(_)) {
            Symbol::intern(lit_content)
        } else {
            self.symbol_from_to(start, end)
        };
        (kind, sym)
    }
}

pub fn nfc_normalize(string: &str) -> Symbol {
    use unicode_normalization::{IsNormalized, UnicodeNormalization, is_nfc_quick};
    match is_nfc_quick(string.chars()) {
        IsNormalized::Yes => Symbol::intern(string),
        _ => {
            let normalized_str: String = string.chars().nfc().collect();
            Symbol::intern(&normalized_str)
        }
    }
}
