Skip to content

⚡ perf(mq-lsp): integrate incremental CST parser into LSP server#1446

Open
harehare wants to merge 5 commits intomainfrom
feat/lsp-incremental-parser
Open

⚡ perf(mq-lsp): integrate incremental CST parser into LSP server#1446
harehare wants to merge 5 commits intomainfrom
feat/lsp-incremental-parser

Conversation

@harehare
Copy link
Copy Markdown
Owner

  • Enable cst feature for mq-lang in mq-lsp to expose IncrementalParser
  • Add incremental_parser_map to Backend to cache per-file IncrementalParser state
  • Replace full re-parse on every change with IncrementalParser::update(), reusing unchanged top-level CST nodes (O(log n) edits via ropey Rope)
  • Remove error_map and split concerns: syntax errors derived on-demand from incremental_parser_map; type errors cached separately in type_error_map
  • Update formatting() and range_formatting() to check syntax errors via incremental_parser_map.result().1.has_errors()
  • Update diagnostics() to pull syntax errors from incremental_parser_map and type errors from type_error_map
  • Add #[derive(Debug)] to IncrementalParser to satisfy Backend's Debug bound

Copilot AI review requested due to automatic review settings March 13, 2026 13:18
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Integrates mq_lang’s incremental CST parsing into mq-lsp to avoid full re-parses on document changes, while separating syntax vs. type diagnostic caching.

Changes:

  • Enable mq-lang’s cst feature in mq-lsp and cache an IncrementalParser per open document.
  • Replace error_map with incremental_parser_map (syntax) + type_error_map (type), and update formatting/diagnostics to consult these.
  • Add Debug support for IncrementalParser to satisfy Backend: Debug.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
crates/mq-lsp/src/server.rs Adds per-file incremental parser caching; reworks syntax/type diagnostics and formatting gating logic.
crates/mq-lsp/Cargo.toml Enables mq-lang’s cst feature so LSP can use IncrementalParser.
crates/mq-lang/src/cst/incremental.rs Derives Debug for IncrementalParser to support storing it in Backend.

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq bot commented Mar 13, 2026

Merging this PR will not alter performance

✅ 29 untouched benchmarks


Comparing feat/lsp-incremental-parser (518d15f) with main (2359c4b)1

Open in CodSpeed

Footnotes

  1. No successful run was found on main (3de5c71) during the generation of this report, so 2359c4b was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

Copilot AI review requested due to automatic review settings March 14, 2026 02:32
@harehare harehare force-pushed the feat/lsp-incremental-parser branch from 5a224da to 650e25d Compare March 14, 2026 02:32
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Integrates mq_lang::IncrementalParser into the mq-lsp backend so the LSP server can reuse CST state across edits and derive syntax diagnostics from the cached parser state.

Changes:

  • Enable mq-lang’s cst feature in mq-lsp and add Debug to IncrementalParser.
  • Replace per-file text_map/error_map with incremental_parser_map and type_error_map.
  • Update formatting and diagnostics paths to consult the incremental parser’s current parse result.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
crates/mq-lsp/src/server.rs Stores per-URI incremental parsers, splits syntax vs type errors, and updates formatting/diagnostics to use the cached parse state.
crates/mq-lsp/Cargo.toml Enables mq-lang’s cst feature so the LSP can use IncrementalParser.
crates/mq-lang/src/cst/incremental.rs Adds #[derive(Debug)] to satisfy Backend: Debug bounds.

@harehare harehare force-pushed the feat/lsp-incremental-parser branch from 650e25d to 83ad347 Compare March 14, 2026 04:47
Copilot AI review requested due to automatic review settings March 14, 2026 12:35
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Integrates mq-lang’s incremental CST parser into the mq-lsp backend so the LSP can reuse parse state across edits (instead of full re-parses), and refactors diagnostics/formatting to derive syntax errors from the incremental parser while caching type-check results separately.

Changes:

  • Enable mq-lang’s cst feature in mq-lsp and cache per-document IncrementalParser state in the LSP backend.
  • Refactor LSP error caching: syntax errors are derived on-demand from the incremental parser; type errors + TypeEnv are cached together.
  • Extend CST parsing metadata to include per-top-level-group node index ranges, and update incremental splicing logic accordingly (plus new property tests).

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
crates/mq-lsp/src/server.rs Adds incremental_parser_map + type_map, switches formatting/diagnostics/type-checking flow to use incremental parsing and split type vs syntax concerns.
crates/mq-lsp/Cargo.toml Enables mq-lang’s cst feature so IncrementalParser is available to the LSP.
crates/mq-lang/src/cst/parser.rs Introduces ParseWithRangesResult so parsing can return both token ranges and node index ranges per top-level group.
crates/mq-lang/src/cst/incremental.rs Uses node index ranges for correct node splicing, fixes prefix/suffix overlap handling, derives Debug, and adds proptest coverage.

Comment on lines +350 to +356
let entry = self.incremental_parser_map.entry(uri_string.clone());
let parser = entry
.and_modify(|p| {
p.update(&text);
})
.or_insert_with(|| mq_lang::IncrementalParser::new(&text));
let (nodes, errors) = parser.result();
Copilot AI review requested due to automatic review settings March 14, 2026 14:04
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Integrates mq-lang’s incremental CST parser into mq-lsp to avoid full re-parses on each document change, and restructures LSP-side error caching to separate syntax vs. type diagnostics.

Changes:

  • Cache a per-document mq_lang::IncrementalParser in the LSP backend and update it on changes.
  • Replace the old error_map/text_map approach with on-demand syntax diagnostics from the incremental parser and cached type-check results.
  • Extend the CST parser/incremental machinery to track node index ranges per top-level group to support correct splicing during incremental updates.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.

File Description
crates/mq-lsp/src/server.rs Switches LSP state to incremental parsing + refactors syntax/type diagnostics and formatting gating.
crates/mq-lsp/Cargo.toml Enables mq-lang’s cst feature so IncrementalParser is available in mq-lsp.
crates/mq-lang/src/cst/parser.rs Introduces ParseWithRangesResult and adds node index ranges alongside token ranges for top-level groups.
crates/mq-lang/src/cst/incremental.rs Updates incremental splicing logic to use node index ranges and adds extensive proptests.

Comment on lines +346 to 349
let (nodes, cst_errors) = if text.is_empty() {
self.incremental_parser_map.remove(&uri_string);
(Vec::new(), mq_lang::CstErrorReporter::default())
} else {
Comment on lines +214 to +218
let uri_str = params.text_document.uri.to_string();
let text = match self.incremental_parser_map.get(&uri_str) {
Some(parser) if !parser.result().1.has_errors() => parser.source(),
_ => return Ok(None),
};
@harehare harehare force-pushed the feat/lsp-incremental-parser branch from 6111c77 to fabffb3 Compare March 15, 2026 12:36
Copilot AI review requested due to automatic review settings March 16, 2026 13:44
@harehare harehare force-pushed the feat/lsp-incremental-parser branch from fabffb3 to 5178b0f Compare March 16, 2026 13:44
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Integrates mq-lang’s incremental CST parsing into mq-lsp so the LSP backend can reuse parse state per file, reducing reparse work on edits and simplifying how syntax/type diagnostics are sourced and cached.

Changes:

  • Enable mq-lang’s cst feature in mq-lsp and cache IncrementalParser per URI in the backend.
  • Refactor LSP state from text_map/error_map/type_env_map into incremental_parser_map plus a combined type_map for type env + type errors.
  • Extend CST parsing internals to return both token ranges and node index ranges to support safer incremental splicing.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
crates/mq-lsp/src/server.rs Backend now caches IncrementalParser per file; diagnostics/formatting pull syntax errors and text from the incremental parser; type info stored in type_map.
crates/mq-lsp/Cargo.toml Enables mq-lang cst feature to access IncrementalParser from the LSP crate.
crates/mq-lang/src/cst/parser.rs Changes parse_with_ranges to return a struct with node/token ranges (supports incremental parsing needs).
crates/mq-lang/src/cst/incremental.rs Updates incremental logic to use node index ranges and reparses suffix for correctness; adds regression + property tests; derives Debug.

/// - `token_ranges[i]` is the half-open token index range `[start, end)` for group `i`.
/// - `node_ranges[i]` is the half-open node index range `[start, end)` for group `i`,
/// allowing callers to know exactly which entries in `nodes` belong to each group.
pub fn parse_with_ranges(&mut self) -> ParseWithRangesResult {
Comment on lines +409 to +418
let text = parser.source();
let syntax_diagnostics: Vec<ls_types::Diagnostic> = cst_errors
.error_ranges(&text)
.into_iter()
.map(|(message, range)| {
let lsp_error = LspError::SyntaxError((message, range));
ls_types::Diagnostic::from(&lsp_error)
})
.collect();
diagnostics.extend(syntax_diagnostics);

// Exercise the full diagnostics pipeline: on_change should parse, type check,
// and populate error_map with type errors when there are no parse errors.
// and populate type_error_map with type errors when there are no parse errors.
@harehare harehare force-pushed the feat/lsp-incremental-parser branch from 6a236e5 to 76018d7 Compare March 29, 2026 14:53
- Enable `cst` feature for mq-lang in mq-lsp to expose IncrementalParser
- Add `incremental_parser_map` to Backend to cache per-file IncrementalParser state
- Replace full re-parse on every change with IncrementalParser::update(), reusing
  unchanged top-level CST nodes (O(log n) edits via ropey Rope)
- Remove `error_map` and split concerns: syntax errors derived on-demand from
  incremental_parser_map; type errors cached separately in `type_error_map`
- Update formatting() and range_formatting() to check syntax errors via
  incremental_parser_map.result().1.has_errors()
- Update diagnostics() to pull syntax errors from incremental_parser_map and
  type errors from type_error_map
- Add #[derive(Debug)] to IncrementalParser to satisfy Backend's Debug bound
@harehare harehare force-pushed the feat/lsp-incremental-parser branch from 76018d7 to 518d15f Compare April 12, 2026 13:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants