Skip to content

[ls] Refactor textDocument/documentHighlight implementation#157

Merged
purefunctor merged 5 commits into
mainfrom
justin/pr-156
Jun 3, 2026
Merged

[ls] Refactor textDocument/documentHighlight implementation#157
purefunctor merged 5 commits into
mainfrom
justin/pr-156

Conversation

@purefunctor

Copy link
Copy Markdown
Owner

Closes #156

@coderabbitai

coderabbitai Bot commented Jun 3, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: dcafc10b-48ab-414b-a097-a37701b3b821

📥 Commits

Reviewing files that changed from the base of the PR and between 840ba38 and ea61922.

⛔ Files ignored due to path filters (1)
  • tests-integration/fixtures/lsp/1780504560_document_highlight_types_and_imports/Main.snap is excluded by !**/*.snap
📒 Files selected for processing (4)
  • compiler-lsp/analyzer/src/document_highlight.rs
  • compiler-lsp/analyzer/src/position.rs
  • tests-integration/fixtures/lsp/1780504560_document_highlight_types_and_imports/Lib.purs
  • tests-integration/fixtures/lsp/1780504560_document_highlight_types_and_imports/Main.purs
🚧 Files skipped from review as they are similar to previous changes (4)
  • tests-integration/fixtures/lsp/1780504560_document_highlight_types_and_imports/Lib.purs
  • compiler-lsp/analyzer/src/position.rs
  • tests-integration/fixtures/lsp/1780504560_document_highlight_types_and_imports/Main.purs
  • compiler-lsp/analyzer/src/document_highlight.rs

Confidence 4/5 - "Large refactor with good test coverage; watch for rare resolution edge-cases"

Summary

This PR refactors textDocument/documentHighlight to fully support local bindings (named binders, let-bindings, and record puns) by porting the resolution-and-scan pattern used in references.rs into document_highlight.rs. It expands locate dispatching to cover imports, term/type operators, let-bindings, binder and expression record-puns, and definition occurrences for terms and types. Position helpers for UTF‑8 ranges were added to improve range accuracy for a variety of CST/AST name/operator tokens.

Key implementations

  • Dispatcher expanded to handle: ImportItem, Binder, Expression, Type, TermItem, TypeItem, LetBinding, BinderPun, ExpressionPun, TermOperator, TypeOperator.
  • Imports:
    • Introduced HighlightTarget and import_target resolution that maps an import’s stabilised AST node to exported term/type/class targets (trimming parentheses) and drives highlight_import to add both target highlights and the import token highlight.
  • Binder / Let / Pun handling:
    • highlight_binder: rewritten to use locate::id_range-based occurrence collection; early constructor-binder path delegates to file-term highlights; scans lowered variable resolutions and expression-pun entries resolving to the binder id.
    • highlight_let: accumulates let signature/equation highlights and extends with locate::id_range for lowered variable resolutions and matching expression-puns.
    • highlight_binder_pun and highlight_expression_pun: new flows to highlight record-pun definitions and all occurrences—including expression-puns and variable resolutions—referencing the same pun id.
    • highlight_expression now routes RecordPun resolution to the new pun highlight paths.
  • File-level and definition mapping:
    • highlight_file_term / highlight_file_type refactored to consistently collect occurrences via locate::id_range across lowered expression/binder/operator/pun info and to add definition-name highlights for items defined in the current file.
    • Added generic push_name_highlight helper used by term_item_highlights / type_item_highlights; removed older push_document_highlight/document_highlights helpers.
  • Operators and types:
    • Added handling for term and type operators in the dispatcher and used new position helpers to compute operator ranges.
  • Misc:
    • Removed previous value-equation specific expansion in favour of unified locate-based occurrence collection.
    • Improved import-item computed ranges (range-accuracy adjustments).

Position helpers

  • Added public UTF‑8 range helpers in compiler-lsp/analyzer/src/position.rs:
    • import_item_name_range
    • declaration_name_range
    • data_constructor_name_range
    • class_member_name_range
    • instance_declaration_name_range
    • infix_operator_range
  • Tests added to verify UTF‑8 protocol round-tripping and PositionEncoding mapping to LSP kinds.

Tests and fixtures

  • Integration fixtures and snapshots added/updated to cover binder/let/pun and import/type/operator flows:
    • 1780118760_binder_local
    • 1780119540_let_local
    • 1780123440_pun_local
    • 1780504560_document_highlight_types_and_imports
    • 1780512780_document_highlight_uncovered_cases
    • Additional fixture updates for record-pun cases
  • Tests exercise imports, type/operator highlights, and various pun/let/binder patterns.

Code size & effort

  • Large but focused refactor: ~+523/-117 lines across document_highlight and position helpers.
  • Estimated review effort: High.

Risks / open points

  • The broad dispatch and multiple new flows increase the chance of subtle cross-file or complex-resolution edge cases (deeply nested puns, unusual import aliasing, or complex operator/type-alias combinations). Existing fixtures cover many scenarios, but additional CI runs and manual review of edge-case interactions are recommended.
  • Review attention suggested on:
    • Correctness of import_target mapping (parentheses trimming and target resolution).
    • Accuracy of ranges produced by new position helpers across various CST shapes.
    • Record-pun flows (binder_pun vs expression_pun) for complex nested records or cross-module references.

Files of interest (non-exhaustive)

  • compiler-lsp/analyzer/src/document_highlight.rs — primary refactor (new dispatch flows and occurrence collection)
  • compiler-lsp/analyzer/src/position.rs — new exported UTF‑8 range helpers
  • tests-integration/fixtures/lsp/* — added/updated fixtures and snapshots for document-highlight scenarios

Walkthrough

Document highlighting now routes locate::Located results through an expanded dispatcher, adds CST-backed UTF‑8 range helpers, and implements highlight paths for imports, binders, let-bindings, record-puns, and term/type operators, plus integration fixtures exercising these flows.

Changes

Local bindings document highlighting

Layer / File(s) Summary
Position range extraction helpers
compiler-lsp/analyzer/src/position.rs
New public functions declaration_name_range, data_constructor_name_range, class_member_name_range, instance_declaration_name_range, and infix_operator_range extract name/operator token ranges from CST nodes as UTF‑8 ranges; tests added for UTF‑8 position behaviour.
Dispatcher refactor and import target resolution
compiler-lsp/analyzer/src/document_highlight.rs
Refactor implementation to compute current file and UTF‑8 position and dispatch locate::Located variants; add HighlightTarget, highlight_import, and import_target to resolve imported term/type/class names (trimming parentheses and consulting exports).
Binder / let / pun highlight paths
compiler-lsp/analyzer/src/document_highlight.rs
highlight_binder rewritten to use locate::id_range, special-case constructor binders, and scan lowered resolver entries; highlight_let extended to include lowered variable and expression-pun occurrences; highlight_binder_pun and highlight_expression_pun added for record-pun flows.
File-term / type highlights and helpers
compiler-lsp/analyzer/src/document_highlight.rs
highlight_expression/highlight_type/highlight_file_term/highlight_file_type refactored to consistently use locate::id_range, remove prior value-equation expansion, and extend with term_item_highlights/type_item_highlights; introduce push_name_highlight helper and macros for item-kind driven definition highlights.
Integration test fixtures
tests-integration/fixtures/lsp/*
Update existing record-pun fixture and add fixtures for types/imports and uncovered cases to validate imports, type/operator aliases, local operators, and record-pun highlighting.

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The PR description only states 'Closes #156' without detailing the actual changes made to the codebase. Consider adding a more detailed description explaining the refactoring work, key changes to document_highlight.rs, and any notable implementation decisions.
✅ Passed checks (2 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR successfully addresses all coding requirements from issue #156: binder/let/pun-bound local bindings are now handled, matching the references.rs pattern with proper dispatch and occurrence collection.
Out of Scope Changes check ✅ Passed All changes are scoped to document_highlight implementation and related helper functions in position.rs. Integration test fixtures are appropriately added to validate the implementation.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov

codecov Bot commented Jun 3, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 79.82262% with 91 lines in your changes missing coverage. Please review.
✅ Project coverage is 83.25%. Comparing base (0a1cd82) to head (ea61922).

Files with missing lines Patch % Lines
compiler-lsp/analyzer/src/document_highlight.rs 81.42% 2 Missing and 66 partials ⚠️
compiler-lsp/analyzer/src/position.rs 72.94% 1 Missing and 22 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #157      +/-   ##
==========================================
- Coverage   83.25%   83.25%   -0.01%     
==========================================
  Files         134      134              
  Lines       24772    25121     +349     
  Branches    24772    25121     +349     
==========================================
+ Hits        20624    20914     +290     
+ Misses       2263     2257       -6     
- Partials     1885     1950      +65     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
tests-integration/fixtures/lsp/1780504560_document_highlight_types_and_imports/Main.purs (2)

33-33: ⚡ Quick win

Add type signature for consistency.

The plus function is missing a type signature, which is inconsistent with other top-level definitions in this module. Type signatures improve clarity and enable better type checking.

📝 Proposed fix to add type signature
+plus :: Local -> Local -> Local
 plus left right = left
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@tests-integration/fixtures/lsp/1780504560_document_highlight_types_and_imports/Main.purs`
at line 33, The top-level function `plus` lacks an explicit type signature; add
a type signature for `plus` above its definition (the `plus` function)
consistent with other top-level declarations in the module so it explicitly
declares the argument and return types used by `plus` and satisfies the module's
style and compiler checks; ensure the signature matches how `plus` is used (same
type variables/constraints as other functions) and place it immediately before
the `plus left right = left` definition.

31-31: ⚡ Quick win

Parameter name shadows imported binding.

The parameter value in the localMember implementation shadows the imported value from Lib (line 3). Whilst syntactically valid, this reduces clarity and could cause confusion when reasoning about which value is being used.

♻️ Proposed fix to rename parameter
-  localMember value = value
+  localMember x = x
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@tests-integration/fixtures/lsp/1780504560_document_highlight_types_and_imports/Main.purs`
at line 31, The parameter name `value` in the function `localMember` is
shadowing the imported `value` from `Lib`; rename the parameter (e.g., to
`localValue` or `v`) in the `localMember` definition and update all references
inside `localMember`'s body to use the new name so the imported `value` remains
unshadowed and intent is clear; ensure any related pattern matches or type
annotations in `localMember` are adjusted to the new parameter name.
tests-integration/fixtures/lsp/1780504560_document_highlight_types_and_imports/Lib.purs (1)

15-15: ⚡ Quick win

Add type signature for consistency.

The append function is missing a type signature, which is inconsistent with other top-level definitions like value (lines 12-13). Even in test fixtures, type signatures improve clarity and type safety.

📝 Proposed fix to add type signature
+append :: Box -> Box -> Box
 append left right = left
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@tests-integration/fixtures/lsp/1780504560_document_highlight_types_and_imports/Lib.purs`
at line 15, Add an explicit polymorphic type signature for the top-level
function append to match the style of nearby definitions (e.g., value) and the
implementation append left right = left; for example declare append with two
arguments returning the first (e.g., append :: forall a b. a -> b -> a) so the
signature matches the function name append and its behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@compiler-lsp/analyzer/src/document_highlight.rs`:
- Around line 794-795: The code calls highlights.extend(highlight.into_iter())
which is redundant; change the call to highlights.extend(highlight) so
Vec::extend uses the IntoIterator impl directly. Locate the variable named
highlight created via range.and_then(|range| document_highlight(content,
encoding, range)) and update the extend call to pass highlight without
.into_iter() (in the scope where highlights is extended).

---

Nitpick comments:
In
`@tests-integration/fixtures/lsp/1780504560_document_highlight_types_and_imports/Lib.purs`:
- Line 15: Add an explicit polymorphic type signature for the top-level function
append to match the style of nearby definitions (e.g., value) and the
implementation append left right = left; for example declare append with two
arguments returning the first (e.g., append :: forall a b. a -> b -> a) so the
signature matches the function name append and its behavior.

In
`@tests-integration/fixtures/lsp/1780504560_document_highlight_types_and_imports/Main.purs`:
- Line 33: The top-level function `plus` lacks an explicit type signature; add a
type signature for `plus` above its definition (the `plus` function) consistent
with other top-level declarations in the module so it explicitly declares the
argument and return types used by `plus` and satisfies the module's style and
compiler checks; ensure the signature matches how `plus` is used (same type
variables/constraints as other functions) and place it immediately before the
`plus left right = left` definition.
- Line 31: The parameter name `value` in the function `localMember` is shadowing
the imported `value` from `Lib`; rename the parameter (e.g., to `localValue` or
`v`) in the `localMember` definition and update all references inside
`localMember`'s body to use the new name so the imported `value` remains
unshadowed and intent is clear; ensure any related pattern matches or type
annotations in `localMember` are adjusted to the new parameter name.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: fb7b1731-5936-4b94-8e71-6ef5725bdf12

📥 Commits

Reviewing files that changed from the base of the PR and between 0a1cd82 and 2e68004.

⛔ Files ignored due to path filters (5)
  • tests-integration/fixtures/lsp/1778600460_document_highlight_cross_file/Main.snap is excluded by !**/*.snap
  • tests-integration/fixtures/lsp/1778600760_document_highlight_constructor_binder/Main.snap is excluded by !**/*.snap
  • tests-integration/fixtures/lsp/1778600820_document_highlight_record_pun/Main.snap is excluded by !**/*.snap
  • tests-integration/fixtures/lsp/1778600940_document_highlight_constructor_declaration/Main.snap is excluded by !**/*.snap
  • tests-integration/fixtures/lsp/1780504560_document_highlight_types_and_imports/Main.snap is excluded by !**/*.snap
📒 Files selected for processing (5)
  • compiler-lsp/analyzer/src/document_highlight.rs
  • compiler-lsp/analyzer/src/position.rs
  • tests-integration/fixtures/lsp/1778600820_document_highlight_record_pun/Main.purs
  • tests-integration/fixtures/lsp/1780504560_document_highlight_types_and_imports/Lib.purs
  • tests-integration/fixtures/lsp/1780504560_document_highlight_types_and_imports/Main.purs

Comment thread compiler-lsp/analyzer/src/document_highlight.rs Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@compiler-lsp/analyzer/src/document_highlight.rs`:
- Around line 87-94: The current code passes the full ImportItem range from
locate::id_range(import_id) to document_highlight, which highlights
keywords/parentheses for forms like `type Foo` or operator imports; instead, add
a small helper (e.g., import_item_name_range) that takes a cst::ImportItem node
(reuse the same variant handling as import_target) and returns the token-only
name range, then change the pipeline: call
locate::id_range(&content,&parsed,&stabilized, import_id), map that ImportItem
range through import_item_name_range to extract the symbol-only range, and pass
that resulting range into document_highlight (keeping context.encoding). Ensure
import_item_name_range covers all ImportItem variants
(type/class/operator/alias) so only the symbol token is highlighted.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6d745d61-abea-4fc1-b03e-fc885f1ba676

📥 Commits

Reviewing files that changed from the base of the PR and between 2e68004 and 7a11f98.

⛔ Files ignored due to path filters (6)
  • tests-integration/fixtures/lsp/1778600460_document_highlight_cross_file/Main.snap is excluded by !**/*.snap
  • tests-integration/fixtures/lsp/1778600760_document_highlight_constructor_binder/Main.snap is excluded by !**/*.snap
  • tests-integration/fixtures/lsp/1778600820_document_highlight_record_pun/Main.snap is excluded by !**/*.snap
  • tests-integration/fixtures/lsp/1778600940_document_highlight_constructor_declaration/Main.snap is excluded by !**/*.snap
  • tests-integration/fixtures/lsp/1780504560_document_highlight_types_and_imports/Main.snap is excluded by !**/*.snap
  • tests-integration/fixtures/lsp/1780512780_document_highlight_uncovered_cases/Main.snap is excluded by !**/*.snap
📒 Files selected for processing (6)
  • compiler-lsp/analyzer/src/document_highlight.rs
  • compiler-lsp/analyzer/src/position.rs
  • tests-integration/fixtures/lsp/1778600820_document_highlight_record_pun/Main.purs
  • tests-integration/fixtures/lsp/1780504560_document_highlight_types_and_imports/Lib.purs
  • tests-integration/fixtures/lsp/1780504560_document_highlight_types_and_imports/Main.purs
  • tests-integration/fixtures/lsp/1780512780_document_highlight_uncovered_cases/Main.purs
🚧 Files skipped from review as they are similar to previous changes (3)
  • tests-integration/fixtures/lsp/1780504560_document_highlight_types_and_imports/Main.purs
  • tests-integration/fixtures/lsp/1780504560_document_highlight_types_and_imports/Lib.purs
  • compiler-lsp/analyzer/src/position.rs

Comment thread compiler-lsp/analyzer/src/document_highlight.rs
@purefunctor purefunctor merged commit bf1bf60 into main Jun 3, 2026
11 of 13 checks passed
@purefunctor purefunctor deleted the justin/pr-156 branch June 3, 2026 21:07
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.

[ls] Implement document_highlight for local bindings

1 participant