Skip to content

feat(types): резолв См.-ссылок в определение через type service + кликабельные ссылки в hover#4209

Merged
nixel2007 merged 11 commits into
developfrom
claude/hover-see-reference-link
Jul 3, 2026
Merged

feat(types): резолв См.-ссылок в определение через type service + кликабельные ссылки в hover#4209
nixel2007 merged 11 commits into
developfrom
claude/hover-see-reference-link

Conversation

@nixel2007

@nixel2007 nixel2007 commented Jun 25, 2026

Copy link
Copy Markdown
Member

Продолжение #4196 / #4207 (#4204). Делает См.-ссылки навигируемыми и вводит
переиспользуемый резолв ссылки в определение через type service (корректно по
общим модулям, модулям менеджеров и прочим типам).

Компоненты (нейтральные, без зависимости hover↔documentlink)

  • TypeService.resolveSeeReference(reference, context): Optional<SourceDefinedSymbol>
    единая точка резолва См.-ссылки в символ-определение:
    • неквалифицированная (Метод) — среди методов того же модуля;
    • квалифицированная (Модуль.Метод, Справочники.X.Метод,
      СправочникМенеджер.X.Метод и т.п.) — через реестр типов
      (SymbolTypeIndex.resolveReferenceSymbol): идём по членам и берём
      source-символ найденного члена (MemberDescriptor.getSourceSymbol).
  • utils/SourceSymbolLinks.navigationTarget(symbol) — общий формат таргета
    uri#L<line>,<col> (используют и documentlink, и hover).

Применение

  • DocumentLink (SeeReferenceDocumentLinkSupplier) переведён с findCommonModule
    на TypeService.resolveSeeReference. Прежний путь видел только общие модули и не
    доставал, например, методы модулей менеджеров; теперь резолв единообразен.
    DocumentLink больше не зависит от пакета hover.
  • Hover (SeeReferenceHyperlinks.toMarkdownLink) делает метки обрыва
    рекурсивных см.-цепочек кликабельными: См. КоробкаСм. [Коробка](…)
    (источник метки — MethodSymbol, резолв не нужен). Утилита и резолвер готовы к
    применению при доработке представления см.-ссылок в подсказках (это уже
    вопрос UX/«п.1» [BUG] Ошибка в определении последнего типа в ховере рекурсивных типов #4204 — в этот PR не входит).

Почему не DereferenceMemberMatcher

Он резолвит приёмник.член по узлам AST в позиции курсора
(matchAt(TerminalNode, …, Position)), а См.-ссылка — строка из
doc-комментария без AST. Поэтому используется обход по реестру типов
(findMember/resolveReferenceSymbol), параллельный существующему
resolveHyperlink.walkMembers (но возвращающий символ члена, без параметрического
fallback, нужного только для типов).

Тесты

  • SeeReferenceDocumentLinkSupplierTest (same-module + общий модуль) проходит уже
    через type-service путь — он же включает резолв модулей менеджеров.
  • ReporterScenariosSeeRefTest / RecursiveSeeRefInferenceTest обновлены на
    проверку markdown-гиперссылки См. [Имя](uri#L<line>,<col>) (RU) и See [Имя](…) (EN).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • “См.” references in hover and document-link views are now rendered as clickable markdown links, including correct navigation anchors.
    • Qualified “См.” targets can resolve directly to referenced symbols, including nested member paths.
  • Bug Fixes
    • Improved resolution for manager-module-style links and tighter handling of recursive/mutual “См.” hover rendering and formatting.
    • Hover “См.” source aggregation is now sorted for more consistent output.
  • Tests
    • Expanded and adjusted hover/link/reference resolution tests to validate link formatting and anchor targets.

@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR replaces Location-based "См."/"See" reference resolution with TypeService/SymbolTypeIndex-driven symbol lookup, then uses those targets to build document-link URIs and markdown hover links.

Changes

See-reference links

Layer / File(s) Summary
Symbol target resolution
utils/NavigationLinks.java, types/TypeService.java, types/index/SymbolTypeIndex.java, types/index/SymbolTypeIndexHyperlinkTest.java
Adds NavigationLinks.toTarget(URI, Range), TypeService.resolveSeeReference(...), and SymbolTypeIndex.resolveReferenceSymbol(...) with shared chain-walking logic; tests cover blank, direct, nested, and missing references.
DocumentLink wiring
documentlink/SeeReferenceDocumentLinkSupplier.java, documentlink/SeeReferenceDocumentLinkSupplierTest.java
SeeReferenceDocumentLinkSupplier now resolves references through TypeService and builds DocumentLink targets from the resolved symbol URI/range; a manager-module case is covered by test.
Hover markdown links
hover/SeeReferenceHyperlinks.java, hover/VariableSymbolMarkupContentBuilder.java, types/RecursiveSeeRefInferenceTest.java, types/ReporterScenariosSeeRefTest.java, architecture/ArchitectureTest.java
Hover labels now render См./See targets as markdown links, with sorted/deduplicated source labels and updated hover expectations plus the widened Hover→Utils architecture rule.

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

Possibly related PRs

Suggested reviewers: theshadowco

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 43.33% 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 summarizes the main change: resolving "См." links via type service and making hover links clickable.
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 unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/hover-see-reference-link

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.

@nixel2007 nixel2007 changed the title feat(hover): кликабельные См.-ссылки на определения (обрыв рекурсии) feat(types): резолв См.-ссылок в определение через type service + кликабельные ссылки в hover Jun 25, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
src/main/java/com/github/_1c_syntax/bsl/languageserver/types/index/SymbolTypeIndex.java (1)

154-198: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoff

Дублирование с resolveHyperlink/walkMembers.

resolveReferenceSymbol повторяет структуру перебора префиксов из resolveHyperlink, а walkToMember — обход сегментов из walkMembers. Различие лишь в возвращаемом результате (символ-источник vs TypeSet/обработка параметра-последнего-сегмента). Можно выделить общий обход сегментов, чтобы поведение резолва не разъезжалось при будущих правках.

🤖 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
`@src/main/java/com/github/_1c_syntax/bsl/languageserver/types/index/SymbolTypeIndex.java`
around lines 154 - 198, `resolveReferenceSymbol` and `walkToMember` duplicate
the same prefix/member traversal logic already used by `resolveHyperlink` and
`walkMembers`; extract the shared segment-walking behavior in `SymbolTypeIndex`
into a common helper so all resolvers use the same path resolution flow. Keep
the existing return differences by having the shared traversal return the
resolved chain/member and let `resolveReferenceSymbol`, `resolveHyperlink`, and
`walkMembers` map that result to `SourceDefinedSymbol`, `TypeSet`, or parameter
handling as needed.
src/main/java/com/github/_1c_syntax/bsl/languageserver/hover/VariableSymbolMarkupContentBuilder.java (1)

295-303: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Недетерминированный порядок при нескольких источниках.

sources приходит как Set<Object>fieldExpansionSources это HashSet ключей элементов), поэтому при наличии более одного источника порядок в результате joining(" | ") нестабилен между запусками. Для одиночного источника не проявляется, но при множественных «См.» метках вывод hover может «прыгать». Стоит зафиксировать порядок (например, sorted() по тексту ссылки) для стабильного рендеринга.

🤖 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
`@src/main/java/com/github/_1c_syntax/bsl/languageserver/hover/VariableSymbolMarkupContentBuilder.java`
around lines 295 - 303, The seeReferenceLabel method builds the hover “See/См.”
string from a Set, so the joined source links can appear in a different order
between runs. Update seeReferenceLabel in VariableSymbolMarkupContentBuilder to
make the output deterministic by sorting the mapped source links before joining
them, while keeping the existing blank-link filtering and distinct handling
intact.
🤖 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.

Nitpick comments:
In
`@src/main/java/com/github/_1c_syntax/bsl/languageserver/hover/VariableSymbolMarkupContentBuilder.java`:
- Around line 295-303: The seeReferenceLabel method builds the hover “See/См.”
string from a Set, so the joined source links can appear in a different order
between runs. Update seeReferenceLabel in VariableSymbolMarkupContentBuilder to
make the output deterministic by sorting the mapped source links before joining
them, while keeping the existing blank-link filtering and distinct handling
intact.

In
`@src/main/java/com/github/_1c_syntax/bsl/languageserver/types/index/SymbolTypeIndex.java`:
- Around line 154-198: `resolveReferenceSymbol` and `walkToMember` duplicate the
same prefix/member traversal logic already used by `resolveHyperlink` and
`walkMembers`; extract the shared segment-walking behavior in `SymbolTypeIndex`
into a common helper so all resolvers use the same path resolution flow. Keep
the existing return differences by having the shared traversal return the
resolved chain/member and let `resolveReferenceSymbol`, `resolveHyperlink`, and
`walkMembers` map that result to `SourceDefinedSymbol`, `TypeSet`, or parameter
handling as needed.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 58461998-b87d-41f0-9f3f-86a9ef4e42dc

📥 Commits

Reviewing files that changed from the base of the PR and between 287be25 and afc7eac.

📒 Files selected for processing (9)
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/documentlink/SeeReferenceDocumentLinkSupplier.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/hover/SeeReferenceHyperlinks.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/hover/VariableSymbolMarkupContentBuilder.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/TypeService.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/index/SymbolTypeIndex.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/utils/SourceSymbolLinks.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/documentlink/SeeReferenceDocumentLinkSupplierTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/RecursiveSeeRefInferenceTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/ReporterScenariosSeeRefTest.java

@github-actions

github-actions Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Test Results

 3 588 files   3 588 suites   1h 52m 11s ⏱️
 3 548 tests  3 530 ✅  18 💤 0 ❌
21 288 runs  21 176 ✅ 112 💤 0 ❌

Results for commit ffefd69.

♻️ This comment has been updated with latest results.

claude added 6 commits July 1, 2026 06:38
Добавлена переиспользуемая утилита SeeReferenceHyperlinks.toMarkdownLink(text,
target): строит markdown-ссылку [text](uri#L<line>,<col>) на определение символа.
Формат таргета совпадает с SeeReferenceDocumentLinkSupplier, поэтому переход и
позиционирование работают в клиентах, поддерживающих такие ссылки (VS Code и
совместимые).

Сейчас применяется к меткам обрыва рекурсивных см.-цепочек: `См. Коробка` →
`См. [Коробка](…)` с переходом к функции-конструктору. Утилита вынесена отдельно,
чтобы переиспользовать её при доработке представления см.-ссылок в подсказках.

Тесты (Reporter/Recursive SeeRef) обновлены на проверку markdown-ссылки.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QcYuuctkrfWkmGqXaUmx5S
Добавлен переиспользуемый резолвер ссылки в символ-определение, не привязанный
к hover/documentlink:
- TypeService.resolveSeeReference(reference, context): Optional<SourceDefinedSymbol>
  — неквалифицированная ссылка ищется в методах того же модуля, квалифицированная
  (Модуль.Метод, Справочники.X.Метод, СправочникМенеджер.X.Метод и т.п.) —
  через реестр типов (SymbolTypeIndex.resolveReferenceSymbol), единообразно для
  общих модулей, модулей менеджеров и прочих типов; берётся source-символ
  найденного члена (MemberDescriptor.getSourceSymbol);
- utils/SourceSymbolLinks.navigationTarget(symbol) — общий формат таргета
  uri#L<line>,<col>.

SeeReferenceDocumentLinkSupplier переведён на TypeService.resolveSeeReference +
SourceSymbolLinks вместо findCommonModule (тот видел только общие модули и не
доставал, например, методы модулей менеджеров). DocumentLink больше не зависит
от пакета hover.

hover/SeeReferenceHyperlinks.toMarkdownLink использует тот же SourceSymbolLinks.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QcYuuctkrfWkmGqXaUmx5S
Прямой тест мотивирующего случая: `См. СправочникМенеджер.СправочникСМенеджером.МетодМенеджера`
теперь даёт document link на определение метода в модуле менеджера справочника —
то, что старый findCommonModule не доставал.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QcYuuctkrfWkmGqXaUmx5S
… См.-ссылок

- юнит-тесты SymbolTypeIndex.resolveReferenceSymbol/walkToMember: пустая/
  неквалифицированная ссылка, наличие/отсутствие source-символа, ненайденный
  член, обход вложенных сегментов. Покрытие нового кода поднято выше порога
  Quality Gate (предыдущий прогон Sonar был на устаревшем коммите без этих
  методов и их тестов);
- seeReferenceLabel: добавлен sorted() перед join — детерминированный порядок
  при нескольких источниках (замечание CodeRabbit). Замечание про дублирование
  walkToMember/walkMembers осознанно не правлю: обходы расходятся (параметрический
  fallback нужен только для типов, извлечение source-символа — только для
  определений), общая абстракция добавила бы больше сложности, чем убирает.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QcYuuctkrfWkmGqXaUmx5S
- S1448: TypeService больше не растёт (36 методов) — резолв См.-ссылки убран из
  фасада: SeeReferenceDocumentLinkSupplier теперь сам диспетчеризует (метод того
  же модуля — по дереву символов, квалифицированная ссылка — через
  SymbolTypeIndex.resolveReferenceSymbol). DocumentLink зависит от слоя типов,
  не от hover;
- S109: магическая 2 вынесена в константу MIN_QUALIFIED_SEGMENTS;
- S2589: убрана всегда-ложная проверка next == null (returnType() не-null под
  @NullMarked).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QcYuuctkrfWkmGqXaUmx5S
…edSymbolLinks

utils/ — листовой пакет и не должен зависеть от доменных типов (context.symbol),
поэтому хелпер построения таргета uri#L<line>,<col> переехал из
utils.SourceSymbolLinks в context.symbol.SourceDefinedSymbolLinks и снова
принимает SourceDefinedSymbol (чистый однопараметрический API). Вызовы в hover
(SeeReferenceHyperlinks) и documentlink (SeeReferenceDocumentLinkSupplier)
обновлены.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QcYuuctkrfWkmGqXaUmx5S
@nixel2007
nixel2007 force-pushed the claude/hover-see-reference-link branch from 86dc8a3 to 3bb9f32 Compare July 1, 2026 06:46
…ылок

Исправляет смешение ответственностей, возникшее из-за попытки обойти смелл S1448:

- дублирование убрано: resolveHyperlink (тип по строке) и резолв См.-ссылки в
  символ используют один обход resolveChain; из результата первый берёт тип
  возврата, второй — getSourceSymbol(). Удалены параллельные walkMembers/walkToMember;
- слой типов: резолв См.-ссылки снова на фасаде TypeService.resolveSeeReference
  (диспетч «тот же модуль / квалифицированная» внутри фасада); DocumentLink-саплаер
  ходит через фасад, а не напрямую в SymbolTypeIndex. Ценой известного смелла
  S1448 (TypeService большой; дробление — отдельно);
- presentation вынесен из домена: форматтер uri#L<line>,<col> переехал из
  context.symbol в доменно-независимый utils.NavigationLinks(URI, Range); им
  пользуются и hover, и documentlink.

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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
`@src/main/java/com/github/_1c_syntax/bsl/languageserver/types/index/SymbolTypeIndex.java`:
- Around line 192-224: The parameter fallback in resolveChain is unreachable
when an intermediate MemberDescriptor has TypeKind.UNKNOWN, so
Модуль.Процедура.Параметр references fail before the trailing-parameter lookup
runs. Update SymbolTypeIndex.resolveChain to attempt the last-segment parameter
resolution via parameterFromMember(lastMethod, name) before returning null on an
unknown return type, and make sure lastMethod is set for method/procedure
members even when their returnType is unknown. Add a test covering a См.-style
reference to a procedure parameter to verify this path.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 2f4c36b1-36f5-4175-b6bc-7251b7e2f4ed

📥 Commits

Reviewing files that changed from the base of the PR and between 3bb9f32 and 8afc05a.

📒 Files selected for processing (5)
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/documentlink/SeeReferenceDocumentLinkSupplier.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/hover/SeeReferenceHyperlinks.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/TypeService.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/index/SymbolTypeIndex.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/utils/NavigationLinks.java

…лой Hover→Utils

resolveChain не доходил до фолбэка на параметр (Модуль.Метод.Параметр),
если у промежуточного метода тип возврата UNKNOWN — а у процедур и
недокументированных функций он всегда такой. Теперь на последнем сегменте
пробуем разрешить его как имя параметра метода до выхода по UNKNOWN.

Также ArchitectureTest: Hover теперь легитимно зависит от Utils
(hover.SeeReferenceHyperlinks использует utils.NavigationLinks) — как и
прочие фичевые пакеты (Color, DocumentLink, Folding, InlayHints,
SemanticTokens).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QcYuuctkrfWkmGqXaUmx5S
claude added 3 commits July 2, 2026 19:55
…ания

Отдельный компонент ради однострочного построения markdown-ссылки избыточен —
формирование ссылки перенесено прямо в VariableSymbolMarkupContentBuilder.sourceLink.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QcYuuctkrfWkmGqXaUmx5S
Резолв не привязан к «См.»: разрешает имя/квалифицированную ссылку в
определяющий символ — метод, общий модуль, менеджер справочника/документа,
любой тип с модульным отражением. Имя метода фасада отражает это, а не «см.».
Ветка имени типа целиком добавлена явно (resolve + definingSymbol), покрыта
тестом на ссылку в тип менеджера.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QcYuuctkrfWkmGqXaUmx5S
…34/S1142/S109)

Добавленный фолбэк на параметр раздул resolveChain до когнитивной сложности 32.
Дублированные блоки «последний сегмент — имя параметра метода» вынесены в
parameterChain(); убраны лишние вложенность, возвраты и magic number 2.
Поведение не изменилось (покрыто SymbolTypeIndexHyperlinkTest).

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

sonarqubecloud Bot commented Jul 2, 2026

Copy link
Copy Markdown

@nixel2007
nixel2007 merged commit 1f79c76 into develop Jul 3, 2026
37 checks passed
@nixel2007
nixel2007 deleted the claude/hover-see-reference-link branch July 3, 2026 06:14
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