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 = nfc_normalize(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);
                    }
                    token::Lifetime(lifetime_name, 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 = nfc_normalize(&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 = nfc_normalize(self.str_from(start));
                        token::Lifetime(lifetime_name, 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,
            });
        }

        // Only up to 255 `-`s are allowed in code fences
        if u8::try_from(len_opening).is_err() {
            self.dcx().emit_err(errors::FrontmatterTooManyDashes { len_opening });
        }

        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)
        }
    }
}
