Repository: swc-project/swc
File: crates/swc_ecma_parser/src/parser/input.rs (Rust)

Code before:
    }

    pub fn scan_jsx_identifier(&mut self) {
        if !self.cur().is_word() {
            return;
        }
        let start = self.cur.span.lo;
        let cur = self.iter.scan_jsx_identifier(start);
        debug_assert!(cur.token == Token::JSXName);
        self.set_cur(cur);
    }

    pub fn scan_jsx_attribute_value(&mut self) {
        self.cur = self.iter.scan_jsx_attribute_value();
    }

    pub fn rescan_template_token(&mut self, start_with_back_tick: bool) {
        let start = self.cur_pos();
        self.cur = self.iter.rescan_template_token(start, start_with_back_tick);
    }
}

impl<I: Tokens> Buffer<I> {
    pub fn new(lexer: I) -> Self {
        let end_pos = lexer.end_pos();
        let prev_span = Span::new_with_checked(end_pos, end_pos);
        Buffer {
            iter: lexer,
            cur: TokenAndSpan::new(Token::Eof, prev_span, false),
            prev_span,
            next: None,
        }
    }

    #[inline(always)]
    pub fn set_cur(&mut self, token: TokenAndSpan) {
        self.cur = token
    }

    #[inline(always)]
    pub fn next(&self) -> Option<&NextTokenAndSpan> {
        self.next.as_ref()
    }

    #[inline(always)]
    pub fn set_next(&mut self, token: Option<NextTokenAndSpan>) {
        self.next = token;
    }

    #[inline(always)]
    pub fn next_mut(&mut self) -> &mut Option<NextTokenAndSpan> {

Review comment (suggestion):
The initialization logic has changed from using `start_pos` to `end_pos` for the initial span. While this makes sense conceptually (EOF position should be at the end), this is a significant behavioral change that affects all span calculations for empty files or comment-only files.

Please verify that this change is correct and that all tests pass with the updated span calculations. The changes to test output files suggest this is working as intended, but it represents a breaking change in the API behavior regarding span initialization.

Code after:

    pub fn rescan_jsx_token(&mut self, allow_multiline_jsx_text: bool) {
        let start = self.cur.span.lo;
        let t = self.iter.rescan_jsx_token(allow_multiline_jsx_text, start);
        self.set_cur(t);
    }

    pub fn scan_jsx_identifier(&mut self) {
        if !self.cur().is_word() {
            return;
        }
        let start = self.cur.span.lo;
        let cur = self.iter.scan_jsx_identifier(start);
        debug_assert!(cur.token == Token::JSXName);
        self.set_cur(cur);
    }

    pub fn scan_jsx_attribute_value(&mut self) {
        self.cur = self.iter.scan_jsx_attribute_value();
    }

    pub fn rescan_template_token(&mut self, start_with_back_tick: bool) {
        let start = self.cur_pos();
        self.cur = self.iter.rescan_template_token(start, start_with_back_tick);
    }
}

impl<I: Tokens> Buffer<I> {
    pub fn new(lexer: I) -> Self {
        let start_pos = lexer.start_pos();
        let prev_span = Span::new_with_checked(start_pos, start_pos);
        Buffer {
            iter: lexer,
            cur: TokenAndSpan::new(Token::Eof, prev_span, false),
            prev_span,
            next: None,
        }
    }

    #[inline(always)]
    pub fn set_cur(&mut self, token: TokenAndSpan) {
        self.cur = token
    }

    #[inline(always)]
    pub fn next(&self) -> Option<&NextTokenAndSpan> {
        self.next.as_ref()
    }

    #[inline(always)]
    pub fn set_next(&mut self, token: Option<NextTokenAndSpan>) {