Skip to content

perf(references): хелпер Positions и отказ от лишних Range при взятии позиции#4258

Merged
nixel2007 merged 3 commits into
developfrom
claude/perf-terminal-finder-position-alloc
Jul 10, 2026
Merged

perf(references): хелпер Positions и отказ от лишних Range при взятии позиции#4258
nixel2007 merged 3 commits into
developfrom
claude/perf-terminal-finder-position-alloc

Conversation

@nixel2007

@nixel2007 nixel2007 commented Jul 10, 2026

Copy link
Copy Markdown
Member

Описание

Часть общей оптимизации из #4248 (раздел «Лишние Position/Range в новом terminal SPI»): убираем аллокацию Range там, где нужна всего одна Position.

1. Терминальный ReferenceFinder

Дефолтный ReferenceFinder.findReference(uri, TerminalNode) вычислял стартовую позицию через Ranges.create(terminal).getStart() — создавал Range (две Position), брал одну и выбрасывал остальное. Оверлоуд не переопределён у самых частых finder'ов (ReferenceIndexReferenceFinder @Order(40), SourceDefinedSymbolDeclarationReferenceFinder, AnnotationReferenceFinder), поэтому каждый терминальный lookup сорсового символа (горячий путь инференсера и диагностик) аллоцировал на ровном месте — в конфигурации, чей heap и так доминируется Position/Range.

2. Утилити-класс Positions

Добавлен utils/Positions (по образцу Ranges) — сборка одной Position из координат / Token / TerminalNode / ParserRuleContext, плюс createEnd(Token/TerminalNode). Конвертация ANTLR→LSP (line - 1, charPositionInLine) теперь в одном месте.

3. Переезд остальных мест на Positions

Переведены все места, где Range строился только ради одного конца, и inline-конструирование позиции из токена:

  • Ranges.create(x).getStart()/.getEnd()Positions.create/createEnd: SelectionRangeProvider, LinkedEditingRangeProvider, ExtractStructureConstructorSupplier, VariableTypeInlayHintSupplier;
  • inline new Position(token.getLine()-1, token.getCharPositionInLine()): SignatureHelpProvider, PlatformMethodCallHintRenderer, PlatformMethodCallInlayHintCollector.

Поведение не меняется: createEnd повторяет арифметику конца из Ranges, а PositionsTest проверяет парити против Ranges.create(...).getStart()/.getEnd().

Границы эффекта: это снижение скорости аллокаций / нагрузки на GC (объекты транзиентные), а не пикового удержанного heap. Удержанные Position/Range из #4248 — это модель индекса ссылок, отдельная тема.

Связанные задачи

Пункт из архитектурного разбора #4248. Продолжение серии #4249#4257.

Closes

Чеклист

Общие

  • Ветка PR обновлена из develop
  • Отладочные, закомментированные и прочие, не имеющие смысла участки кода удалены
  • Изменения покрыты тестами (PositionsTest; парити подтверждён 119 тестами затронутых провайдеров/inlay-hint/code-action, а также ReferenceIndexTest/ReferencesProviderTest/DefinitionProviderTest/RenameProviderTest)

Дополнительно

Ranges не тронут (у него уже есть импорт org.eclipse.lsp4j.util.Positions — не стал смешивать имена внутри него). Место с нестандартной колонкой (PlatformMethodCallInlayHintCollector, центрирование по токену) намеренно оставлено на new Position.

Summary by CodeRabbit

  • Bug Fixes
    • Improved accuracy and consistency of cursor-to-language-element positioning across reference finding, selection/linked editing ranges, signature help, and inlay hints.
    • Standardized edit and hint alignment by using shared LSP position conversion (including proper start/end handling).
  • Tests
    • Added unit tests covering position conversion utilities for tokens, terminal nodes (including null-safe (0, 0)), parser contexts, and end-position calculation.

…ookup

The default ReferenceFinder.findReference(uri, TerminalNode) computed the
terminal's start position via Ranges.create(terminal).getStart(), allocating a
Range (two Position objects) only to keep one and discard the rest. The
non-overriding finders include the hottest one (ReferenceIndexReferenceFinder),
so every source-symbol terminal lookup allocated on that path — in a workspace
whose heap is already dominated by Position/Range objects (issue #4248).

Add a small Positions utility (mirroring Ranges) that builds a bare Position
from a Token/TerminalNode — the token->LSP-position conversion (line - 1,
charPositionInLine) previously inlined in several places — and use it in the
default overload. Result is identical to the previous start position (covered
by PositionsTest parity assertions against Ranges.create(...).getStart()).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01BSiRGLm633B4EmvG3vkk4V
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6d697920-8ebd-4583-b498-b1f895c37b88

📥 Commits

Reviewing files that changed from the base of the PR and between 6122551 and 6066138.

📒 Files selected for processing (1)
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/providers/LinkedEditingRangeProvider.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/providers/LinkedEditingRangeProvider.java

📝 Walkthrough

Walkthrough

Changes

Position conversion

Layer / File(s) Summary
Position utility and validation
src/main/java/.../utils/Positions.java, src/test/java/.../utils/PositionsTest.java
Adds coordinate, ANTLR token, parser-context, terminal-node, and end-position helpers with tests for line mapping, consistency, and null handling.
Reference finder position delegation
src/main/java/.../references/ReferenceFinder.java
Uses Positions.create(terminal) when delegating terminal-node reference searches.
Position helper adoption across providers
src/main/java/.../codeactions/..., src/main/java/.../inlayhints/..., src/main/java/.../providers/...
Replaces direct token and range position calculations with shared Positions helpers for code actions, inlay hints, signature help, linked editing, and selection ranges.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 36.36% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: introducing Positions and replacing unnecessary Range-based position handling.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/perf-terminal-finder-position-alloc

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.

@github-actions

github-actions Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Test Results

 3 612 files  + 6   3 612 suites  +6   1h 36m 9s ⏱️ - 11m 48s
 3 573 tests + 5   3 555 ✅ + 5   18 💤 ±0  0 ❌ ±0 
21 438 runs  +30  21 326 ✅ +30  112 💤 ±0  0 ❌ ±0 

Results for commit 38bb756. ± Comparison against base commit 1775382.

♻️ This comment has been updated with latest results.

Extend the Positions helper with create(ParserRuleContext) plus createEnd
(Token/TerminalNode), and route the remaining "build a Range only to take one
endpoint" and inline "new Position(token.getLine()-1, charPositionInLine)"
sites through it:

- Ranges.create(x).getStart()/.getEnd() -> Positions.create/createEnd in
  SelectionRangeProvider, LinkedEditingRangeProvider, ExtractStructure
  ConstructorSupplier, VariableTypeInlayHintSupplier;
- inline start-position construction in SignatureHelpProvider,
  PlatformMethodCallHintRenderer, PlatformMethodCallInlayHintCollector.

Behaviour is unchanged (createEnd mirrors Ranges' end math; PositionsTest adds
parity assertions against Ranges.create(...).getStart()/.getEnd()). Verified by
119 tests across the touched providers/inlay-hint/code-action suites.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01BSiRGLm633B4EmvG3vkk4V
@nixel2007 nixel2007 changed the title perf(references): не аллоцировать лишний Range в терминальном ReferenceFinder perf(references): хелпер Positions и отказ от лишних Range при взятии позиции Jul 10, 2026
Replace the terminal-node lambda with Positions::create (SonarCloud
java:S1612); the TerminalNode element resolves the overload unambiguously.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01BSiRGLm633B4EmvG3vkk4V
@nixel2007
nixel2007 merged commit 0bd6d38 into develop Jul 10, 2026
33 checks passed
@nixel2007
nixel2007 deleted the claude/perf-terminal-finder-position-alloc branch July 10, 2026 14:38
@sonarqubecloud

Copy link
Copy Markdown

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