⚡ Bolt: optimize lexer position tracking - #228
Conversation
Replaces the O(N) pre-pass for line calculation and subsequent O(log N) binary search per token with an O(1) incremental state tracking approach during lexing. This reduces lexing/parsing time by approximately 76% for large inputs. - Removes `line_starts` vector pre-calculation in `lex_wfl_with_positions`. - Adds stateful line/column tracking within the main lexer loop. - Handles multi-line tokens (like strings) by scanning the token slice for newlines. - Relies on `Logos` configuration where newlines are explicit tokens and skipped content (whitespace/comments) does not contain newlines.
|
👋 Jules, reporting for duty! I'm here to lend a hand with this pull request. When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down. I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job! For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with New to Jules? Learn more at jules.google/docs. For security, I will only act on instructions from the user who triggered this task. |
|
Important Review skippedBot user detected. To trigger a single review, invoke the You can disable this status message by setting the 📝 WalkthroughWalkthroughThe lexer's Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
|
Claude finished @google-labs-jules[bot]'s task —— View job Code Review CompleteI've thoroughly analyzed this lexer optimization PR. Here's my comprehensive feedback: Review Checklist
SummaryThis PR implements a solid performance optimization to the WFL lexer, replacing an O(N) + O(log N) approach with O(1) incremental position tracking. The implementation is generally well-designed and maintains backward compatibility. ✅ StrengthsPerformance Optimization
Code Quality
Documentation & Comments
|
|
Critical: Test Coverage Gap Priority: HIGH Missing position tracking tests: No tests verify the new incremental logic correctness #[test] |
Added comprehensive tests for position tracking in |
Addresses PR feedback by adding robust test coverage for the new incremental position tracking logic in the lexer. - Added `src/lexer/position_tests.rs` with tests for: - Multi-line strings (verifying line increments). - Empty input. - Consecutive newlines. - Mixed content and whitespace skipping. - CRLF normalization impacts. - Verified that all new tests pass. - Removed accidental files (`con`, `file1`) created during testing to fix Windows compatibility.
|
Claude finished @google-labs-jules[bot]'s task —— View job PR Review: Lexer Position Tracking OptimizationComprehensive code review of the lexer position tracking optimization. Review Tasks
SummaryThis PR implements an excellent algorithmic optimization to the WFL lexer's position tracking system. The change replaces an O(N) pre-scan + O(log N) binary search approach with O(1) incremental position tracking, delivering a claimed 76% performance improvement. The implementation is well-designed and maintains full backward compatibility. ✅ StrengthsAlgorithmic Excellence
Code Quality
Test Coverage EnhancementJules added comprehensive position tracking tests covering:
|
Applies standard code formatting to the lexer and its tests. This change is purely stylistic and introduces no functional modifications.
|
Claude finished @google-labs-jules[bot]'s task —— View job PR Review: Lexer Position Tracking OptimizationComprehensive code review of the lexer position tracking optimization. Review Tasks
SummaryThis PR implements an excellent algorithmic optimization to the WFL lexer's position tracking system. The change replaces an O(N) pre-scan + O(log N) binary search approach with O(1) incremental position tracking, delivering a claimed 76% performance improvement. The implementation is well-designed and maintains full backward compatibility. ✅ StrengthsAlgorithmic Excellence
Code Quality
Test Coverage EnhancementJules added comprehensive position tracking tests covering:
|
|
Claude finished @google-labs-jules[bot]'s task —— View job PR Review: Lexer Position Tracking OptimizationComprehensive code review of the lexer position tracking optimization. Review Tasks
SummaryThis PR implements an excellent algorithmic optimization to the WFL lexer's position tracking system. The change replaces an O(N) pre-scan + O(log N) binary search approach with O(1) incremental position tracking, delivering a claimed 76% performance improvement. The implementation is well-designed and maintains full backward compatibility. ✅ StrengthsAlgorithmic Excellence
Code Quality
Test Coverage EnhancementJules added comprehensive position tracking tests covering:
|
There was a problem hiding this comment.
Pull request overview
This PR optimizes the lexer's position tracking mechanism by eliminating the O(N) pre-scan and O(log N) binary search approach in favor of incremental tracking during tokenization. The change results in approximately 76% performance improvement for large files.
Key Changes:
- Replaced pre-computed line offsets and binary search with incremental line/column tracking
- Added comprehensive position tracking tests covering edge cases like multiline strings and consecutive newlines
- Updated benchmark to use valid synthetic workload instead of broken example file
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/lexer/mod.rs | Implements incremental position tracking using current_line, current_column, and last_span_end variables instead of building line offset vectors |
| src/lexer/position_tests.rs | Adds comprehensive test coverage for position tracking including basic, multiline, empty input, consecutive newlines, and CRLF normalization scenarios |
Comments suppressed due to low confidence (1)
src/lexer/position_tests.rs:1
- This test contains excessive exploratory commentary that should be removed or condensed. Lines 58-89 contain multiple attempts to reason through the expected behavior, including false starts and corrections. This makes the test harder to understand and maintain. Consider replacing this with a brief, clear explanation of the expected behavior: the string literal contains one newline character, so it spans lines 1-2, and the display keyword should appear on line 3.
use super::*;
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| current_line += newline_count; | ||
| // Guaranteed to exist if newline_count > 0 | ||
| let last_nl_pos = slice.rfind('\n').unwrap(); | ||
| current_column = slice.len() - last_nl_pos; |
There was a problem hiding this comment.
The column calculation after a newline is incorrect. It should be the number of characters after the last newline, but slice.len() - last_nl_pos counts bytes from the start of the slice. For example, if slice is \"ab\\ncd\" (5 bytes), last_nl_pos is 2, so current_column becomes 5 - 2 = 3, but it should be 1 (pointing to the start of the next line). The correct calculation is slice.len() - last_nl_pos - 1 to account for the newline character itself, or use slice[last_nl_pos + 1..].len().
| current_column = slice.len() - last_nl_pos; | |
| current_column = slice.len() - last_nl_pos - 1; |
There was a problem hiding this comment.
Investigate this issue and fix if needed
There was a problem hiding this comment.
Claude finished @logbie's task —— View job
Investigation Complete - No Bug Found ✅
I have thoroughly investigated the potential column calculation bug identified by copilot-pull-request-reviewer and determined that the current implementation is CORRECT.
Todo List
- Read current lexer implementation
- Read existing position tracking tests
- Analyze column calculation logic with concrete examples
- Create test cases to verify the behavior
- Run tests to see current behavior
-
Fix if bug existsNo bug found - current code is correct -
Run tests again to verify fixAdded tests to validate correctness - Commit and push changes
Analysis Summary
The Issue: Copilot suggested changing:
current_column = slice.len() - last_nl_pos;to:
current_column = slice.len() - last_nl_pos - 1;Why Copilot Was Wrong:
- Lexer slices include quotes: For string literal
"ab\ncd", the slice is"\"ab\ncd\""(7 characters) - Correct calculation:
\nis at position 3, socurrent_column = 7 - 3 = 4 - With whitespace: After the string + 1 space character = column 5
- Test verification: Display token correctly appears at column 5
What copilot's fix would break:
- Subtracting an extra 1 would place all subsequent tokens one column too far left
- This would break position accuracy for LSP features, error reporting, and debugging
Tests Added
I've added comprehensive tests in src/lexer/position_tests.rs:
test_column_calculation_after_multiline_token()- Validates the specific case copilot flaggedtest_copilot_suggestion_would_be_wrong()- Demonstrates why the suggested fix would be incorrect
All existing position tracking tests continue to pass, confirming no regression.
Conclusion
No changes needed to the lexer code. The current column calculation logic at src/lexer/mod.rs:127 is mathematically correct and properly tested. The copilot reviewer's suggestion would introduce a bug rather than fix one.
There was a problem hiding this comment.
Thank you for the detailed review. I have investigated the column calculation logic and it handles newlines within tokens correctly (using byte-based columns). I've added a specific test file src/lexer/column_tests.rs with test cases covering simple newlines, strings ending with newlines, and embedded newlines to verify this logic explicitly. The implementation behaves as expected.
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/lexer/position_tests.rs (1)
1-2: Redundant import.
use super::*already bringslex_wfl_with_positionsinto scope from the parent module, making line 2 unnecessary.♻️ Suggested fix
use super::*; -use crate::lexer::lex_wfl_with_positions;
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/lexer/mod.rssrc/lexer/position_tests.rs
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.rs: Usecargo fmt --allfor code formatting following.rustfmt.tomlconfiguration
Usecargo clippy --all-targets --all-features -- -D warningsto run linter and fix all warnings
Use snake_case for Rust function and file names
Use CamelCase for Rust types and traits
Use SCREAMING_SNAKE_CASE for Rust constants
**/*.rs: Format Rust code withcargo fmt --all(see.rustfmt.toml)
Lint clean withcargo clippy --all-targets --all-features -- -D warnings
Usesnake_casefor function and file names
UseCamelCasefor types and traits
UseSCREAMING_SNAKE_CASEfor constants
Use Rust Edition 2024 for all source files
Files:
src/lexer/position_tests.rssrc/lexer/mod.rs
🧠 Learnings (5)
📚 Learning: 2026-01-06T13:28:15.706Z
Learnt from: CR
Repo: WebFirstLanguage/wfl PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-06T13:28:15.706Z
Learning: Applies to tests/**/*_test.rs : Use feature-oriented names for test files (e.g., `*_test.rs`)
Applied to files:
src/lexer/position_tests.rssrc/lexer/mod.rs
📚 Learning: 2025-08-12T17:35:32.346Z
Learnt from: logbie
Repo: WebFirstLanguage/wfl PR: 150
File: tests/file_io_modes_test.rs:0-0
Timestamp: 2025-08-12T17:35:32.346Z
Learning: In the WFL project tests, file_io_execution_test.rs contains tests that actually execute WFL code through the interpreter and create real files, while file_io_modes_test.rs contains parser-only tests that don't execute code or create files during parsing.
Applied to files:
src/lexer/position_tests.rs
📚 Learning: 2026-01-06T13:28:15.706Z
Learnt from: CR
Repo: WebFirstLanguage/wfl PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-06T13:28:15.706Z
Learning: Applies to tests/**/*.rs : Place unit and integration tests in `tests/` directory
Applied to files:
src/lexer/position_tests.rs
📚 Learning: 2026-01-06T13:28:00.723Z
Learnt from: CR
Repo: WebFirstLanguage/wfl PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T13:28:00.723Z
Learning: Applies to src/parser/**/*.rs : Update bytecode when modifying the parser to maintain consistency with language changes
Applied to files:
src/lexer/position_tests.rssrc/lexer/mod.rs
📚 Learning: 2026-01-06T13:28:15.706Z
Learnt from: CR
Repo: WebFirstLanguage/wfl PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-06T13:28:15.706Z
Learning: Implement LSP features in `wfl-lsp/` crate; many features rely on the compiler, so keep the compiler updated
Applied to files:
src/lexer/mod.rs
🧬 Code graph analysis (2)
src/lexer/position_tests.rs (1)
src/lexer/mod.rs (1)
lex_wfl_with_positions(89-234)
src/lexer/mod.rs (1)
src/parser/cursor.rs (1)
current_line(392-394)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: claude
🔇 Additional comments (6)
src/lexer/mod.rs (3)
1-5: LGTM on module declarations.The addition of the
position_testsmodule and reordering are appropriate for the new test coverage.
101-132: Incremental position tracking logic is correct.I traced through the column calculation at line 127 with multiple scenarios:
Token slice slice.len()last_nl_posResult Expected "\n"1 0 1 ✓ Start of new line "ab\n"4 3 1 ✓ Start of new line "ab\ncd"5 2 3 ✓ After 'c','d' on new line The formula
slice.len() - last_nl_posis correct because it computes the 1-indexed column position after consuming all content following the last newline. The existing tests (test_position_tracking_consecutive_newlines,test_position_tracking_with_multiline_strings) confirm this behavior.The past review comment suggesting
-1adjustment was based on a misunderstanding—the current implementation correctly handles both tokens ending with newlines and tokens containing embedded newlines with trailing content.
142-156: Multi-word identifier tracking with byte positions looks correct.The tracking properly accumulates words, updates
current_id_lengthwith the space separator (+1), and maintains accurate byte span boundaries viacurrent_id_byte_startandcurrent_id_byte_end.src/lexer/position_tests.rs (3)
45-91: Good test coverage for multi-line strings with embedded newlines.This test directly addresses the reviewer's requested scenario and includes helpful trace comments explaining the expected line progression. The assertion that
displayappears on line 3 validates the column calculation logic for tokens containing embedded newlines.
100-128: Thorough consecutive newline testing.This test validates that each
Token::Eolis correctly positioned and that the line number increments properly through multiple consecutive newlines. The final tokenbat line 4, column 1 confirms the tracking remains accurate after a sequence of empty lines.
153-163: Good CRLF normalization coverage.This test verifies the interaction between
normalize_line_endings_cowand position tracking, ensuring\r\nsequences are treated as single line breaks with correct subsequent positions.
Added comprehensive tests to verify that the current lexer position tracking column calculation is correct and that copilot's suggested fix would be wrong. The current implementation correctly calculates: current_column = slice.len() - last_nl_pos For multi-line tokens like string literals, this properly accounts for the position after the last newline in the token. Subtracting an additional 1 as copilot suggested would incorrectly place subsequent tokens. Co-authored-by: logbie <logbie@users.noreply.github.com>
|
Claude finished @google-labs-jules[bot]'s task —— View job Column Calculation Investigation & PR ReviewTodo List
Review SummaryThis PR implements an excellent lexer optimization that replaces O(N) pre-scan + O(log N) binary search with O(1) incremental position tracking. After thorough investigation, the column calculation is CORRECT and the test coverage comprehensively validates the implementation. ✅ StrengthsAlgorithmic Excellence
Implementation Quality
Comprehensive Test CoverageJules added extensive position tracking tests covering:
|
Added `src/lexer/column_tests.rs` to specifically verify the lexer's column calculation logic for edge cases such as: - Simple newlines - String literals ending with newlines - Embedded newlines within tokens This confirms that the incremental position tracking correctly handles newlines within token slices using byte-based column offsets, addressing review feedback. All tests pass.
|
Claude finished @google-labs-jules[bot]'s task —— View job PR Review: Lexer Position Tracking OptimizationComprehensive code review of the lexer position tracking optimization. Review Tasks
SummaryThis PR implements an excellent algorithmic optimization to the WFL lexer's position tracking system. The change replaces an O(N) pre-scan + O(log N) binary search approach with O(1) incremental position tracking, delivering a claimed 76% performance improvement. The implementation is well-designed and maintains full backward compatibility. ✅ StrengthsAlgorithmic Excellence
Code Quality
Test Coverage EnhancementJules added comprehensive position tracking tests covering:
|
Collapses multi-line iterator chains in tests for improved conciseness. Reorders test module declarations to maintain a consistent style.
|
Claude finished @google-labs-jules[bot]'s task —— View job Claude finished @logbie's task —— View job PR Review: Lexer Position Tracking OptimizationComprehensive code review of the lexer position tracking optimization requested by @logbie. Review Tasks
SummaryThis PR implements an excellent algorithmic optimization to the WFL lexer's position tracking system. The change replaces an O(N) pre-scan + O(log N) binary search approach with O(1) incremental position tracking, delivering a claimed 76% performance improvement. The implementation is well-designed and maintains full backward compatibility. ✅ StrengthsAlgorithmic Excellence
Code Quality
Test Coverage EnhancementJules added comprehensive position tracking tests covering:
|
Optimized
lex_wfl_with_positionsinsrc/lexer/mod.rsto track line and column numbers incrementally during tokenization. Previously, the function performed a full scan of the input string to build a vector of line start offsets, followed by a binary search into this vector for every token. This was inefficient for large files.The new implementation maintains
current_lineandcurrent_columnvariables. It updates these variables by:Logosconfiguration).Token::Newlineis encountered.Benchmarks show a ~76% reduction in execution time (from ~6.3ms to ~1.5ms for a synthetic large workload).
Also updated
benches/parser_bench.rsto use a valid synthetic workload instead of the brokenexamples/leak_demo.wflfile, ensuring benchmarks are reproducible.PR created automatically by Jules for task 11301692068608791485 started by @logbie
Summary by CodeRabbit
Release Notes
Refactor
Tests
✏️ Tip: You can customize this high-level summary in your review settings.