Skip to content

feat(providers): иерархия типов для OneScript-классов библиотеки extends#4014

Merged
nixel2007 merged 34 commits into
developfrom
claude/os-files-type-hierarchy-HzJ5n
Jun 11, 2026
Merged

feat(providers): иерархия типов для OneScript-классов библиотеки extends#4014
nixel2007 merged 34 commits into
developfrom
claude/os-files-type-hierarchy-HzJ5n

Conversation

@nixel2007

@nixel2007 nixel2007 commented Jun 7, 2026

Copy link
Copy Markdown
Member

Поддержка библиотеки наследования OneScript nixel2007/extends (autumn-library/extends) — как в системе типов, так и в LSP-фичах.

Возможности

  • Иерархия типов (textDocument/prepareTypeHierarchy, typeHierarchy/supertypes, typeHierarchy/subtypes) для .os-классов: супер- и подтипы по &Расширяет. Работает и для иерархии интерфейсов (интерфейс &Расширяет интерфейс). prepareTypeHierarchy возвращает пусто для файлов, не участвующих в иерархии.
  • Переход к реализациям (textDocument/implementation) для интерфейсов (&Интерфейс): на экспортном методе → одноимённые методы реализующих классов; в теле файла-интерфейса → сами классы. Транзитивно по двум измерениям:
    • наследование классов (абстрактный родитель &Реализует, наследник &Расширяет);
    • иерархия интерфейсов (реализатор производного интерфейса — реализатор и базового).
  • Автодополнение/hover/переход унаследованных членов: класс получает экспортные члены супер-класса (транзитивно), переопределённые выигрывают. Реализовано через единый источник членов в системе типов, поэтому работает во всех фичах, читающих TypeRegistry.getMembers.
  • Типизация поля-родителя: явного (&Родитель) и неявного (_ОбъектРодитель) — типом становится супер-класс (только если класс объявляет &Расширяет).
  • Мета-аннотации «ОСени»: наследование распознаётся и через производные аннотации (например, &ХранилищеСущностей из autumn-data), а не только прямой &Расширяет.

Модель extends (аннотации)

  • &Расширяет("Имя") / &Extends("Имя") — наследование класса от класса либо интерфейса от интерфейса.
  • &Реализует("Имя") — класс реализует интерфейс (повторяемая).
  • &Интерфейс — маркер интерфейса.
  • &Родитель / _ОбъектРодитель — держатель экземпляра родителя.

Имя резолвится так же, как в Новый Имя: qualifiedName из lib.config (OScriptLibraryIndex) либо basename файла.

Архитектура

Понятие наследования вынесено в отдельную сущность системы типов — TypeRelationIndex: единая точка истины об отношениях &Расширяет/&Реализует и единственное место транзитивных обходов и защиты от циклов. Раньше обходы и cycle-guard были бы продублированы в трёх местах (унаследованные члены, иерархия типов, переход к реализациям) — теперь все три делегируют в индекс.

  • TypeRegistry не изменён: унаследованные члены подмешиваются ленивым MemberSource, делегирующим индексу (хук-функция); override-дедуп — штатный first-wins в getMembers.
  • TypeRelationIndex зависит только от OScriptExtends (разбор аннотаций); разрешение имён в документы/типы передаётся функциями — граф бинов остаётся ацикличным.
  • OScriptExtends (аннотации) и OScriptClassResolver (имена ↔ документы) — низкоуровневые адаптеры.
  • Отношения читаются вживую из аннотаций при каждом запросе → бесплатный hot-reload.

Тесты

Покрыты: иерархия типов (корень/лист/супер-/подтипы), переход к реализациям (интерфейс, абстрактный класс, иерархия интерфейсов), наследование членов (транзитивно, override, отсечение не-экспортных), типизация явного и неявного поля-родителя, autumn-data, юнит-тесты TypeRelationIndex (в т.ч. обрыв циклов в обоих измерениях), маршрутизация в BSLTextDocumentService и регистрация capabilities в BSLLanguageServer.

https://claude.ai/code/session_0181QDW1r8NYKkWybSgcjyPv

Summary by CodeRabbit

  • New Features

    • Type Hierarchy: view hierarchy and navigate supertypes/subtypes for OneScript classes using the extends library; prepare may return null for non-hierarchy files.
    • Go to Implementation: find implementations for OneScript interfaces (method- and class-level), including interface-to-interface hierarchies.
    • Completions: inherited members included for extends-based classes, covering explicit and implicit parent-field receivers.
  • Documentation

    • Protocol docs now mark implementation and type-hierarchy operations as supported for extends-based OneScript classes.
  • Tests

    • Added/expanded tests covering type-hierarchy, implementations, inheritance resolution, and completion behaviors.

Summary by CodeRabbit

  • New Features

    • Type-hierarchy navigation for OneScript classes (extends library), including prepare/supertypes/subtypes flows
    • Implementation search for OneScript interfaces, including method-level resolution
    • Completion now surfaces inherited members from parent classes
  • Documentation

    • Protocol operations table updated to show support for implementation and type-hierarchy operations (OneScript/extends-only)

@coderabbitai

coderabbitai Bot commented Jun 7, 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

Adds OneScript extends/interface annotation discovery, a TypeRelationIndex for supertype/subtype/interface relations (cycle-guarded), LSP providers for implementations and type hierarchy, inference updates for parent fields, inherited-member registration, docs updates, and extensive tests.

Changes

OneScript Type Hierarchy and Inheritance

Layer / File(s) Summary
OScript extends/interface annotation introspection
src/main/java/.../types/oscript/OScriptExtends.java, src/main/java/.../types/inferencer/autumn/AutumnMetaAnnotationResolver.java, src/test/java/.../types/oscript/OScriptExtendsTest.java
New OScriptExtends component and public annotation-definition check expose parent/interface/parent-holder detection and extraction of parent/interface names; tests cover Russian/English annotation forms and parent-holder detection.
Library class and document resolution
src/main/java/.../types/oscript/OScriptLibraryIndex.java, src/test/java/.../types/oscript/OScriptLibraryIndexTest.java
Adds classNames(DocumentContext) and isLibraryClass(DocumentContext) to resolve class qualified names from library entries or fall back to URI basename; tests validate library vs non-library behavior.
Type relation index with cycle guards
src/main/java/.../types/oscript/TypeRelationIndex.java, src/test/java/.../types/oscript/TypeRelationIndexTest.java
TypeRelationIndex resolves supertype name/document, finds subtypes, matches interface implementations via hierarchy traversal, and computes transitive inherited members with a ThreadLocal recursion guard; tests cover direct, transitive, annotation-suppressed, and cyclic cases.
Type hierarchy navigation
src/main/java/.../providers/TypeHierarchyProvider.java, src/test/java/.../providers/TypeHierarchyProviderTest.java
New TypeHierarchyProvider builds TypeHierarchyItems (selection ranges, SymbolKind.Class, detail), implements prepareTypeHierarchy, supertypes, and subtypes with deterministic sorting and participation rules.
Interface implementation discovery
src/main/java/.../providers/ImplementationProvider.java, src/test/java/.../providers/ImplementationProviderTest.java, src/test/java/.../providers/ImplementationAbstractClassTest.java, src/test/java/.../providers/ImplementationInterfaceHierarchyTest.java
ImplementationProvider finds OneScript implementors for interfaces, returning method Locations when on an interface method or class selection ranges otherwise; tests validate base behavior, abstract-class chains, and interface-hierarchy resolution.
LSP server wiring and protocol documentation
src/main/java/.../BSLLanguageServer.java, src/main/java/.../BSLTextDocumentService.java, src/test/java/.../BSLLanguageServerTest.java, src/test/java/.../BSLTextDocumentServiceTest.java, docs/en/index.md, docs/index.md
Registers implementationProvider and typeHierarchyProvider capabilities, adds text-document handlers for prepareTypeHierarchy/supertypes/subtypes with null/empty fallbacks, adjusts implementation missing-document Either side, and documents supported operations.
Inheritance-aware type inference for parent fields
src/main/java/.../types/inferencer/ExpressionTypeInferencer.java
Inference now recognizes implicit/explicit parent-holder fields in OS modules and resolves their types from parent class names via OScriptExtends and TypeRegistry (FileType.OS), unioning parent-field types during variable inference and fast-pathing identifier inference.
Inherited member source registration
src/main/java/.../types/oscript/OScriptModuleMembersProvider.java, src/test/java/.../types/oscript/OScriptModuleMembersProviderTest.java
Registers lazy inherited-member sources for library CLASS entries and OScriptClass modules delegating to TypeRelationIndex.inheritedMembers; test adjusted to construct provider with new dependencies.
Parent-field and inherited-member completion
src/test/java/.../providers/CompletionInheritedMembersTest.java, src/test/java/.../providers/CompletionParentFieldTest.java
Tests ensure instance and parent-field completions include inherited superclass members when extends is declared and exclude them otherwise.
Transitive inheritance and member deduplication
src/test/java/.../types/oscript/OScriptInheritanceMembersTest.java, src/test/java/.../types/oscript/AutumnDataInheritanceTest.java
Validates transitive inherited members, exclusion of non-exported parent members, overridden-member deduplication preserving override descriptions, and meta-annotation inheritance behavior.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

Suggested labels

hacktoberfest-accepted

Suggested reviewers

  • sfaqer

Poem

🐰 I hop through classes, find parents and names,
Interfaces echo, and children reclaim,
Members inherited, locations aligned,
A forest of types — neatly defined!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.42% 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 PR title accurately and specifically describes the main feature: type hierarchy support for OneScript classes in the extends library.
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.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/os-files-type-hierarchy-HzJ5n

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.

@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/providers/ImplementationProvider.java (1)

201-201: ⚡ Quick win

Prefer toLowerCase(Locale.ROOT) for case-insensitive comparison.

For consistency with interface name matching (lines 91, 134) and to avoid locale-dependent behavior, replace equalsIgnoreCase with explicit toLowerCase(Locale.ROOT) comparison.

♻️ Proposed refactor
     for (var candidate : serverContext.getDocuments().values()) {
       if (candidate.getFileType() == FileType.OS
-        && FilenameUtils.getBaseName(candidate.getUri().getPath()).equalsIgnoreCase(name)) {
+        && FilenameUtils.getBaseName(candidate.getUri().getPath()).toLowerCase(Locale.ROOT).equals(name.toLowerCase(Locale.ROOT))) {
         return Optional.of(candidate);
       }
     }
🤖 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/providers/ImplementationProvider.java`
at line 201, The comparison using
FilenameUtils.getBaseName(candidate.getUri().getPath()).equalsIgnoreCase(name)
in ImplementationProvider should be made locale-safe and consistent with other
matches: replace the equalsIgnoreCase call with explicit
toLowerCase(Locale.ROOT) on both sides (e.g.,
FilenameUtils.getBaseName(candidate.getUri().getPath()).toLowerCase(Locale.ROOT).equals(name.toLowerCase(Locale.ROOT)))
and add the java.util.Locale import if missing; this change should be applied
where the base name is compared to name in the ImplementationProvider class to
match the approach used at lines 91 and 134.
src/main/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/OScriptExtends.java (1)

118-132: ⚡ Quick win

Return immutable collection for consistency.

The method returns List.of() (immutable) at line 121 but returns the mutable ArrayList at line 131. This inconsistency means callers cannot rely on a consistent mutability contract. Utility methods should return immutable collections to prevent accidental modification and ensure defensive programming.

🛡️ Proposed fix
-    return result;
+    return List.copyOf(result);
🤖 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/oscript/OScriptExtends.java`
around lines 118 - 132, The method implementedInterfaceNames in OScriptExtends
returns an immutable List.of() in the early-exit branch but a mutable ArrayList
in the normal path; change the normal path to return an immutable copy (e.g.,
wrap the result with List.copyOf(result) or return
Collections.unmodifiableList(result)) before returning so callers always get an
immutable collection; update the return of result in implementedInterfaceNames
to use that immutable wrapper while keeping the rest of the logic
(DocumentContext, metaResolver, and result accumulation) unchanged.
🤖 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/providers/ImplementationProvider.java`:
- Line 201: The comparison using
FilenameUtils.getBaseName(candidate.getUri().getPath()).equalsIgnoreCase(name)
in ImplementationProvider should be made locale-safe and consistent with other
matches: replace the equalsIgnoreCase call with explicit
toLowerCase(Locale.ROOT) on both sides (e.g.,
FilenameUtils.getBaseName(candidate.getUri().getPath()).toLowerCase(Locale.ROOT).equals(name.toLowerCase(Locale.ROOT)))
and add the java.util.Locale import if missing; this change should be applied
where the base name is compared to name in the ImplementationProvider class to
match the approach used at lines 91 and 134.

In
`@src/main/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/OScriptExtends.java`:
- Around line 118-132: The method implementedInterfaceNames in OScriptExtends
returns an immutable List.of() in the early-exit branch but a mutable ArrayList
in the normal path; change the normal path to return an immutable copy (e.g.,
wrap the result with List.copyOf(result) or return
Collections.unmodifiableList(result)) before returning so callers always get an
immutable collection; update the return of result in implementedInterfaceNames
to use that immutable wrapper while keeping the rest of the logic
(DocumentContext, metaResolver, and result accumulation) unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0bd027fb-03a6-4726-af49-e9c8ceba21b9

📥 Commits

Reviewing files that changed from the base of the PR and between 95748db and 5668b36.

⛔ Files ignored due to path filters (9)
  • src/test/resources/oscript-libraries/interface-abstract-lib/lib.config is excluded by !src/test/resources/**
  • src/test/resources/oscript-libraries/interface-abstract-lib/src/АбстрактноеХранилище.os is excluded by !src/test/resources/**
  • src/test/resources/oscript-libraries/interface-abstract-lib/src/ИнтерфейсХранилища.os is excluded by !src/test/resources/**
  • src/test/resources/oscript-libraries/interface-abstract-lib/src/КонкретноеХранилище.os is excluded by !src/test/resources/**
  • src/test/resources/oscript-libraries/interface-lib/lib.config is excluded by !src/test/resources/**
  • src/test/resources/oscript-libraries/interface-lib/src/МойИнтерфейс.os is excluded by !src/test/resources/**
  • src/test/resources/oscript-libraries/interface-lib/src/НеРеализация.os is excluded by !src/test/resources/**
  • src/test/resources/oscript-libraries/interface-lib/src/Реализация1.os is excluded by !src/test/resources/**
  • src/test/resources/oscript-libraries/interface-lib/src/Реализация2.os is excluded by !src/test/resources/**
📒 Files selected for processing (9)
  • docs/en/index.md
  • docs/index.md
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/BSLLanguageServer.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/BSLTextDocumentService.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/providers/ImplementationProvider.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/OScriptExtends.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/BSLTextDocumentServiceTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/providers/ImplementationAbstractClassTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/providers/ImplementationProviderTest.java
✅ Files skipped from review due to trivial changes (2)
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/providers/ImplementationAbstractClassTest.java
  • docs/index.md
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/BSLTextDocumentServiceTest.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/BSLTextDocumentService.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/BSLLanguageServer.java

@github-actions

github-actions Bot commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

Test Results

 3 192 files  + 66   3 192 suites  +66   1h 37m 52s ⏱️ + 4m 24s
 3 035 tests + 74   3 020 ✅ + 74  15 💤 ±0  0 ❌ ±0 
18 210 runs  +444  18 120 ✅ +444  90 💤 ±0  0 ❌ ±0 

Results for commit 66a58ea. ± Comparison against base commit 1fc87d0.

This pull request removes 117 and adds 191 tests. Note that renamed tests count towards both.
com.github._1c_syntax.bsl.languageserver.types.inferencer.autumn.AutumnBeanIndexTest ‑ componentBeanNamesForUriExcludesFactoryBeans()
com.github._1c_syntax.bsl.languageserver.types.inferencer.autumn.AutumnBeanIndexTest ‑ componentBeanNamesForUriReturnsComponentNamesWithQualifier()
com.github._1c_syntax.bsl.languageserver.types.inferencer.autumn.AutumnBeanIndexTest ‑ factoryMethodBeansForUriEmptyForComponentOnlyFile()
com.github._1c_syntax.bsl.languageserver.types.inferencer.autumn.AutumnBeanIndexTest ‑ factoryMethodBeansForUriReturnsMethodsOfFile()
com.github._1c_syntax.bsl.languageserver.types.inferencer.autumn.AutumnBeanIndexTest ‑ ignoresBslDocumentChange()
com.github._1c_syntax.bsl.languageserver.types.inferencer.autumn.AutumnBeanIndexTest ‑ ignoresChangeOfNonClassDocument()
com.github._1c_syntax.bsl.languageserver.types.inferencer.autumn.AutumnBeanIndexTest ‑ prefersPrimaryOnConflict()
com.github._1c_syntax.bsl.languageserver.types.inferencer.autumn.AutumnBeanIndexTest ‑ rebuildsContributionOfChangedDocument()
com.github._1c_syntax.bsl.languageserver.types.inferencer.autumn.AutumnBeanIndexTest ‑ rebuildsEntireIndexWhenAnnotationDefinitionChanges()
com.github._1c_syntax.bsl.languageserver.types.inferencer.autumn.AutumnBeanIndexTest ‑ registersComponentByDefaultName()
…
com.github._1c_syntax.bsl.languageserver.BSLTextDocumentServiceTest ‑ implementationRoutesForOsInterface()
com.github._1c_syntax.bsl.languageserver.BSLTextDocumentServiceTest ‑ prepareTypeHierarchyReturnsNullForNonHierarchyOsFile()
com.github._1c_syntax.bsl.languageserver.BSLTextDocumentServiceTest ‑ prepareTypeHierarchyRoutesForOsClass()
com.github._1c_syntax.bsl.languageserver.BSLTextDocumentServiceTest ‑ prepareTypeHierarchyUnknownFile()
com.github._1c_syntax.bsl.languageserver.BSLTextDocumentServiceTest ‑ typeHierarchySubtypesUnknownFile()
com.github._1c_syntax.bsl.languageserver.BSLTextDocumentServiceTest ‑ typeHierarchySupertypesUnknownFile()
com.github._1c_syntax.bsl.languageserver.providers.CompletionInheritedMembersTest ‑ instanceCompletionIncludesInheritedMembers()
com.github._1c_syntax.bsl.languageserver.providers.CompletionParentFieldTest ‑ explicitParentFieldExposesSuperclassMembers()
com.github._1c_syntax.bsl.languageserver.providers.CompletionParentFieldTest ‑ implicitParentFieldExposesSuperclassMembers()
com.github._1c_syntax.bsl.languageserver.providers.CompletionParentFieldTest ‑ parentFieldHasNoSuperclassMembersWithoutExtends()
…

♻️ This comment has been updated with latest results.

@nixel2007

Copy link
Copy Markdown
Member Author

/buildJar

@github-actions

github-actions Bot commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

✅ Собраны JAR-файлы для этого PR по команде /buildJar.

Артефакт: 7464512744

Файлы внутри:

  • bsl-language-server-claude-os-files-type-hierarchy-HzJ5n-5668b36-exec.jar

@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

🧹 Nitpick comments (1)
src/test/java/com/github/_1c_syntax/bsl/languageserver/BSLTextDocumentServiceTest.java (1)

646-648: ⚡ Quick win

Strengthen routing assertions to validate non-empty success paths.

At Line 646 and Line 647, and again at Line 670–672, assertions only check non-null / isLeft(). These tests can pass even if hierarchy/implementation results are empty. Add minimal content checks so routing regressions are caught.

Suggested assertion hardening
-    assertThat(supertypes).isNotNull();
-    assertThat(subtypes).isNotNull();
+    assertThat(supertypes).isNotNull().isNotEmpty();
+    assertThat(subtypes).isNotNull().isNotEmpty();
...
-    assertThat(result).isNotNull();
-    assertThat(result.isLeft()).isTrue();
+    assertThat(result).isNotNull();
+    assertThat(result.isLeft()).isTrue();
+    assertThat(result.getLeft()).isNotEmpty();

Also applies to: 670-672

🤖 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/test/java/com/github/_1c_syntax/bsl/languageserver/BSLTextDocumentServiceTest.java`
around lines 646 - 648, The current assertions in BSLTextDocumentServiceTest
only verify that supertypes and subtypes are not null (and similar isLeft()
checks later) which allows empty results to pass; update the assertions around
variables supertypes and subtypes (and the corresponding isLeft() checks at the
other block) to also assert they are non-empty (e.g., size > 0 or
hasSizeGreaterThan(0)) and/or contain an expected sample element to ensure
routing returns at least one success path; locate the checks in the test methods
referencing supertypes, subtypes and the isLeft() result and strengthen them to
validate minimal content rather than just non-null.
🤖 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/oscript/OScriptClassResolver.java`:
- Around line 97-103: The current loop in OScriptClassResolver that iterates
serverContext.getDocuments().values() to find an .os by basename is
non-deterministic when multiple files share the same base name; change the logic
in the method containing that loop to collect all matches (where
candidate.getFileType() == FileType.OS and
FilenameUtils.getBaseName(candidate.getUri().getPath()).equalsIgnoreCase(name)),
sort the matches deterministically (for example by candidate.getUri().getPath()
or candidate.getUri().toString()), and then return Optional.of(firstSortedMatch)
or Optional.empty() if none — this ensures OScriptClassResolver picks a stable
file when duplicate basenames exist.

---

Nitpick comments:
In
`@src/test/java/com/github/_1c_syntax/bsl/languageserver/BSLTextDocumentServiceTest.java`:
- Around line 646-648: The current assertions in BSLTextDocumentServiceTest only
verify that supertypes and subtypes are not null (and similar isLeft() checks
later) which allows empty results to pass; update the assertions around
variables supertypes and subtypes (and the corresponding isLeft() checks at the
other block) to also assert they are non-empty (e.g., size > 0 or
hasSizeGreaterThan(0)) and/or contain an expected sample element to ensure
routing returns at least one success path; locate the checks in the test methods
referencing supertypes, subtypes and the isLeft() result and strengthen them to
validate minimal content rather than just non-null.
🪄 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: b94d957f-8dba-46de-966a-3effbafab892

📥 Commits

Reviewing files that changed from the base of the PR and between 5668b36 and ef154c2.

⛔ Files ignored due to path filters (1)
  • src/test/resources/standalone-class.os is excluded by !src/test/resources/**
📒 Files selected for processing (11)
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/providers/ImplementationProvider.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/providers/TypeHierarchyProvider.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/OScriptClassResolver.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/OScriptExtends.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/BSLLanguageServerTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/BSLTextDocumentServiceTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/providers/CompletionParentFieldTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/providers/TypeHierarchyProviderTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/OScriptClassResolverTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/OScriptExtendsTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/OScriptInheritanceMembersTest.java
✅ Files skipped from review due to trivial changes (1)
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/BSLLanguageServerTest.java
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/OScriptInheritanceMembersTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/providers/CompletionParentFieldTest.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/providers/TypeHierarchyProvider.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/OScriptExtends.java

@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 (1)
src/test/java/com/github/_1c_syntax/bsl/languageserver/providers/CompletionParentFieldTest.java (1)

134-134: ⚡ Quick win

Add import for java.util.List.

The method signature uses the fully qualified name java.util.List<String> instead of importing the type. As per coding guidelines, imports should be optimized before committing. Adding the import improves readability and follows standard Java style.

📦 Proposed fix

Add the import at the top of the file:

 import java.nio.file.Path;
+import java.util.List;
 
 import static org.assertj.core.api.Assertions.assertThat;

Then update the method signature:

-  private java.util.List<String> labelsAfterDot(String content, String receiver) {
+  private List<String> labelsAfterDot(String content, String receiver) {
🤖 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/test/java/com/github/_1c_syntax/bsl/languageserver/providers/CompletionParentFieldTest.java`
at line 134, The method labelsAfterDot currently uses the fully-qualified type
java.util.List<String>; add an import statement for java.util.List at the top of
the file and change the method signature to use List<String> (i.e., private
List<String> labelsAfterDot(String content, String receiver)); run your IDE's
optimize/imports to ensure imports are formatted and unused imports removed;
make sure the change is applied to the method declaration named labelsAfterDot.

Source: Coding guidelines

🤖 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/test/java/com/github/_1c_syntax/bsl/languageserver/providers/CompletionParentFieldTest.java`:
- Line 134: The method labelsAfterDot currently uses the fully-qualified type
java.util.List<String>; add an import statement for java.util.List at the top of
the file and change the method signature to use List<String> (i.e., private
List<String> labelsAfterDot(String content, String receiver)); run your IDE's
optimize/imports to ensure imports are formatted and unused imports removed;
make sure the change is applied to the method declaration named labelsAfterDot.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 235421c8-4ac4-46c0-9d31-6a81637b3f9e

📥 Commits

Reviewing files that changed from the base of the PR and between ef154c2 and b56c8bc.

📒 Files selected for processing (11)
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/providers/ImplementationProvider.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/providers/TypeHierarchyProvider.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/OScriptClassResolver.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/OScriptExtends.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/OScriptModuleMembersProvider.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/BSLTextDocumentServiceTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/providers/CompletionInheritedMembersTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/providers/CompletionParentFieldTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/providers/TypeHierarchyProviderTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/OScriptExtendsTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/OScriptInheritanceMembersTest.java
💤 Files with no reviewable changes (1)
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/providers/TypeHierarchyProviderTest.java
🚧 Files skipped from review as they are similar to previous changes (9)
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/providers/CompletionInheritedMembersTest.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/OScriptClassResolver.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/OScriptExtendsTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/BSLTextDocumentServiceTest.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/OScriptModuleMembersProvider.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/providers/ImplementationProvider.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/OScriptInheritanceMembersTest.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/OScriptExtends.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/providers/TypeHierarchyProvider.java

@nixel2007

Copy link
Copy Markdown
Member Author

/buildJar

@github-actions

github-actions Bot commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

✅ Собраны JAR-файлы для этого PR по команде /buildJar.

Артефакт: 7466203611

Файлы внутри:

  • bsl-language-server-claude-os-files-type-hierarchy-HzJ5n-f17a2df-exec.jar

@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 (1)
src/main/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/OScriptLibraryIndex.java (1)

254-254: 💤 Low value

Consider defensive handling of URI path extraction.

While .os documents typically have file: URIs with non-null paths, uri.getPath() can return null for opaque URIs. FilenameUtils.getBaseName(null) returns an empty string, which would produce List.of("") — a non-empty list containing a blank class name. This could confuse downstream consumers expecting valid identifiers.

Consider either:

  • Adding a null-safe fallback (e.g., Optional.ofNullable(uri.getPath()).map(FilenameUtils::getBaseName).filter(s -> !s.isBlank()).map(List::of).orElse(List.of())), or
  • Documenting the assumption that .os URIs are always hierarchical file URIs with non-null paths.
🤖 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/oscript/OScriptLibraryIndex.java`
at line 254, The current return uses FilenameUtils.getBaseName(uri.getPath())
and can produce List.of("") when uri.getPath() is null/blank; in
OScriptLibraryIndex replace that direct call with a null/blank-safe check (e.g.,
check uri.getPath() != null && !uri.getPath().isBlank() or use
Optional.ofNullable(uri.getPath())...) and only return
List.of(FilenameUtils.getBaseName(...)) when the result is a non-blank name;
otherwise return an empty list so downstream consumers never receive a blank
identifier. Ensure you reference uri.getPath(), FilenameUtils.getBaseName, and
the method in OScriptLibraryIndex where this return occurs.
🤖 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/types/oscript/OScriptLibraryIndex.java`:
- Line 254: The current return uses FilenameUtils.getBaseName(uri.getPath()) and
can produce List.of("") when uri.getPath() is null/blank; in OScriptLibraryIndex
replace that direct call with a null/blank-safe check (e.g., check uri.getPath()
!= null && !uri.getPath().isBlank() or use
Optional.ofNullable(uri.getPath())...) and only return
List.of(FilenameUtils.getBaseName(...)) when the result is a non-blank name;
otherwise return an empty list so downstream consumers never receive a blank
identifier. Ensure you reference uri.getPath(), FilenameUtils.getBaseName, and
the method in OScriptLibraryIndex where this return occurs.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c26e7ae3-25fc-4b9e-9ea7-f4981031810d

📥 Commits

Reviewing files that changed from the base of the PR and between 69821e9 and d6bcccb.

⛔ Files ignored due to path filters (6)
  • src/test/resources/oscript-libraries/cycle-lib/lib.config is excluded by !src/test/resources/**
  • src/test/resources/oscript-libraries/cycle-lib/src/ИнтерфейсЦиклА.os is excluded by !src/test/resources/**
  • src/test/resources/oscript-libraries/cycle-lib/src/ИнтерфейсЦиклБ.os is excluded by !src/test/resources/**
  • src/test/resources/oscript-libraries/cycle-lib/src/РеализаторЦикла.os is excluded by !src/test/resources/**
  • src/test/resources/oscript-libraries/cycle-lib/src/ЦиклА.os is excluded by !src/test/resources/**
  • src/test/resources/oscript-libraries/cycle-lib/src/ЦиклБ.os is excluded by !src/test/resources/**
📒 Files selected for processing (7)
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/providers/ImplementationProvider.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/providers/TypeHierarchyProvider.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/OScriptLibraryIndex.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/OScriptModuleMembersProvider.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/TypeRelationIndex.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/OScriptLibraryIndexTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/TypeRelationIndexTest.java

@nixel2007

Copy link
Copy Markdown
Member Author

@claude review

@claude

claude Bot commented Jun 8, 2026

Copy link
Copy Markdown

Claude finished @nixel2007's task in 3m 17s —— View job


Code Review

Большой и хорошо структурированный PR. Архитектурное решение централизовать всё наследование в TypeRelationIndex — правильное: без него логика cycle-guard и транзитивных обходов была бы продублирована как минимум в трёх местах. Javadoc полный и информативный. Тестовое покрытие (~95% по SonarQube) высокое, включая нетривиальные случаи (циклы, мета-аннотации, иерархии интерфейсов).

Ниже — замечания, сгруппированные по приоритету.


Потенциальный NPE / NoSuchElementException

TypeHierarchyProvider.toItem()names.iterator().next() без guard-а

TypeHierarchyProvider.java:155 — вызов names.iterator().next() падает с NoSuchElementException, если classNames() вернёт пустой список. По документации classNames() возвращает «непустой список», но это только комментарий — в крайнем случае (опаковый URI, uri.getPath() == null) FilenameUtils.getBaseName(null) возвращает "", и List.of("") формально непустой, но содержит пустую строку. Для надёжности лучше:

var primaryName = names.isEmpty() ? "" : names.iterator().next();
var item = new TypeHierarchyItem(primaryName, SymbolKind.Class, ...);

ImplementationProvider.classSelectionRange() — нет null-guard для getSelectionRange()

ImplementationProvider.java:131module.getSelectionRange() может вернуть null (поле в ModuleSymbol без @NonNull). В TypeHierarchyProvider.selectionRange() для аналогичной ситуации есть явная защита:

var range = module.getSelectionRange();
return range != null ? range : Ranges.create(0, 0, 0, 0);

ImplementationProvider должен содержать аналогичный fallback для согласованности и защиты от NPE. Fix this →


Производительность (дизайн-трейдофф, упомянутый в PR)

TypeHierarchyProvider.participatesInHierarchy() — двойной обход документов

TypeHierarchyProvider.java:136-140 — вызов !subtypeDocuments(documentContext).isEmpty() уже обходит все документы workspace. Результат сразу выбрасывается — используется только булев флаг. Для больших проектов это заметно: на каждый prepareTypeHierarchy (например, при наведении в IDE) делается полный O(n) скан, и результат нигде не кэшируется.

PR явно выбирает «живое» чтение для hot-reload — это приемлемо для малых проектов. Для будущей оптимизации можно рассмотреть обратный индекс parent → [children] в TypeRelationIndex, сбрасываемый при изменении документа.

ImplementationProvider.getImplementations() — O(n) по документам на каждый запрос

ImplementationProvider.java:95 — аналогично, перебор всех документов при каждом goto-implementation. Это O(n × m), где m — длина цепочки &Расширяет у кандидата. Опять же, это осознанный трейдофф, но стоит учесть при росте проектов.


Нарушение контракта иммутабельности

OScriptExtends.implementedInterfaceNames() — мутабельный возврат vs иммутабельный ранний выход

OScriptExtends.java:122-135 — ранний возврат (List.of()) иммутабелен, основной путь возвращает мутабельный ArrayList. Вызывающий код не должен полагаться на изменяемость, но неконсистентность может удивить. Простое исправление:

return List.copyOf(result);

(Это уже отмечал CodeRabbit, приводим для полноты.)


Минорные замечания

TypeHierarchyProvider.itemComparator — можно сделать static

TypeHierarchyProvider.java:67 — компаратор не зависит от состояния бина, его можно объявить private static final. Для singleton Spring-бина это не критично, но читаемее.

OScriptExtends.parentClassName() — ищет аннотацию на любом методе, не только на конструкторе

OScriptExtends.java:200-208 — по документации аннотация &Расширяет ставится над ПриСозданииОбъекта, но код проверяет все методы. Это расширенная интерпретация, которая может дать ложные срабатывания (например, вспомогательный метод с &Расширяет("X") из другой библиотеки). Если семантика extends это допускает — ок; если нет — стоит добавить фильтр по isConstructor().


Что сделано хорошо

  • TypeRelationIndex как единая точка истины — правильная централизация.
  • ThreadLocal cycle-guard с явным remove() в finally — корректно решает утечку на пуловых потоках (Sonar S5164).
  • Детерминированная сортировка в ImplementationProvider и TypeHierarchyProvider — важно для воспроизводимого поведения IDE.
  • Комментарий в BSLTextDocumentService о VSCode-краше при пустом списке (null vs []) — полезный артефакт для будущих разработчиков.
  • Широкий набор тест-фикстур: циклы, иерархии интерфейсов, мета-аннотации, standalone-классы.
  • Тест prepareTypeHierarchyReturnsNullForNonHierarchyOsFile проверяет именно VSCode-corner-case.

Copy link
Copy Markdown
Member Author

Code review (at d6bcccbd)

Overview

Adds OneScript extends-library type-hierarchy & inheritance support:

  • Relations: OScriptExtends (annotation parsing) + TypeRelationIndex (single source of truth for &Расширяет/&Реализует traversals and cycle guards).
  • LSP: TypeHierarchyProvider (prepare/supertypes/subtypes) + ImplementationProvider (go-to-implementation), wired into BSLTextDocumentService and server capabilities.
  • Typing: inheritance-aware members via a lazy MemberSource, plus implicit/explicit parent-field (_ОбъектРодитель / &Родитель) inference.

Strengths

  • Clean layering, each layer depends only downward: OScriptExtendsOScriptLibraryIndex (name↔doc) → TypeRelationIndex (relations) → TypeRegistry (members). The traversal/cycle-guard logic that used to be triplicated now lives in one place.
  • Name resolution unified on the canonical type-system path (TypeRegistry.resolve → UserType → owning document, same as Новый Имя), with the library catalog as a deterministic fast-path — no parallel resolver to drift.
  • Cycle protection is thorough: ThreadLocal guard for recursive member assembly (with S5164 cleanup of the empty set), visited-URI guard for the class chain, visited-name guard for the interface closure. Backed by cycle-lib fixtures.
  • Override semantics correct: the inherited source is registered after the class's own source, so own/overridden members win during dedup in getMembers.
  • Meta-annotation correctness: &Аннotация class-definitions carry &Расширяет as a template, not real inheritance — excluded from supertype/subtype/members (annotation→annotation kept).
  • Hot-reload for free: relations are read live from annotations, lazy member source re-resolves the parent without re-registration.
  • Protocol nuance: prepareTypeHierarchy returns null (not empty) to avoid the VSCode crash.
  • Test coverage is excellent — 95% on new code, unit + integration, covering abstract/transitive, interface-hierarchy, override and cycle cases.

Minor suggestions (all non-blocking)

  1. Per-request workspace scans. subtypes, implementsAny (via getImplementations) iterate getDocuments().values() on each call — O(N) over the workspace. Fine for on-demand navigation; if it ever shows up on very large workspaces, a reverse parent→children index would amortize it.
  2. OScriptLibraryIndex.classNames (line 254): FilenameUtils.getBaseName(uri.getPath()) yields List.of("") if getPath() is ever null (opaque URI). In practice .os docs are always hierarchical file: URIs so this can't happen — worth either a one-line guard or a comment documenting the assumption (the method's contract promises a non-empty list). CodeRabbit flagged the same; genuinely low value.

Risks

None significant. Live (uncached) relation reads are an intentional trade for hot-reload; pooled-thread ThreadLocals are cleaned up. No security surface.

Overall this is well-structured and well-tested. 👍


Generated by Claude Code

nixel2007 added a commit that referenced this pull request Jun 8, 2026
- TypeHierarchyProvider.toItem: guard на пустой classNames перед
  names.iterator().next() (NoSuchElementException на опаковом URI).
- ImplementationProvider.classSelectionRange: fallback на Ranges.create(0,0,0,0),
  если module.getSelectionRange() == null — согласованно с
  TypeHierarchyProvider.selectionRange.
- OScriptLibraryIndex.classNames: guard от опакового URI (getPath()==null),
  чтобы не вернуть List.of("").
- TypeHierarchyProvider.ITEM_COMPARATOR: сделан private static final (не зависит
  от состояния бина).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
nixel2007 added a commit that referenced this pull request Jun 8, 2026
…уктора

По ревью PR #4014: аннотации наследования библиотеки extends объявляются на
конструкторе ПриСозданииОбъекта. Раньше parentClassName/isInterface/
implementedInterfaceNames сканировали ВСЕ методы — вспомогательный метод с
&Расширяет("X") (например, из другой библиотеки) давал ложное наследование.

Теперь читаем аннотации только с метода-конструктора. Конструктор ищется по
имени через Methods.isOscriptClassConstructorName (ПриСозданииОбъекта/
OnObjectCreate), а НЕ через SymbolTree.getConstructor(): ConstructorSymbol
создаётся лишь для классифицированных OScript-классов, а наследование работает
и для обычных .os-файлов (basename-резолв) — иначе ломается иерархия plain-.os.

Заодно implementedInterfaceNames возвращает List.copyOf (иммутабельно, как и
ранний выход List.of()).

Тесты: аннотация на вспомогательном методе не считается наследованием/
реализацией.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
nixel2007 added a commit that referenced this pull request Jun 10, 2026
- TypeHierarchyProvider.toItem: guard на пустой classNames перед
  names.iterator().next() (NoSuchElementException на опаковом URI).
- ImplementationProvider.classSelectionRange: fallback на Ranges.create(0,0,0,0),
  если module.getSelectionRange() == null — согласованно с
  TypeHierarchyProvider.selectionRange.
- OScriptLibraryIndex.classNames: guard от опакового URI (getPath()==null),
  чтобы не вернуть List.of("").
- TypeHierarchyProvider.ITEM_COMPARATOR: сделан private static final (не зависит
  от состояния бина).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
nixel2007 added a commit that referenced this pull request Jun 10, 2026
…уктора

По ревью PR #4014: аннотации наследования библиотеки extends объявляются на
конструкторе ПриСозданииОбъекта. Раньше parentClassName/isInterface/
implementedInterfaceNames сканировали ВСЕ методы — вспомогательный метод с
&Расширяет("X") (например, из другой библиотеки) давал ложное наследование.

Теперь читаем аннотации только с метода-конструктора. Конструктор ищется по
имени через Methods.isOscriptClassConstructorName (ПриСозданииОбъекта/
OnObjectCreate), а НЕ через SymbolTree.getConstructor(): ConstructorSymbol
создаётся лишь для классифицированных OScript-классов, а наследование работает
и для обычных .os-файлов (basename-резолв) — иначе ломается иерархия plain-.os.

Заодно implementedInterfaceNames возвращает List.copyOf (иммутабельно, как и
ранний выход List.of()).

Тесты: аннотация на вспомогательном методе не считается наследованием/
реализацией.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
@nixel2007
nixel2007 force-pushed the claude/os-files-type-hierarchy-HzJ5n branch from 2781c78 to d9dfb95 Compare June 10, 2026 14:52
claude added 11 commits June 10, 2026 23:33
Добавлена поддержка LSP-запросов textDocument/prepareTypeHierarchy,
typeHierarchy/supertypes и typeHierarchy/subtypes для .os-файлов,
использующих библиотеку наследования nixel2007/extends.

Наследование определяется по аннотации &Расширяет("Родитель")
(и английскому псевдониму &Extends) над конструктором
ПриСозданииОбъекта. Имя родителя резолвится так же, как в
Новый Родитель: через каталог library-классов (OScriptLibraryIndex)
либо по basename файла.

https://claude.ai/code/session_0181QDW1r8NYKkWybSgcjyPv
Класс-наследник (&Расширяет/&Extends) теперь получает экспортные члены
родителя во всей системе типов: автодополнение после точки, hover,
signature help, переход к определению, семантические токены и вывод типов.

Реализовано через ленивый MemberSource на типе наследника, который тянет
члены родителя из TypeRegistry.getMembers — тот же приём, что и
специализация generic-типов. Это даёт «бесплатно»:
- транзитивное наследование (родитель тянет своего родителя);
- переопределение (собственные члены выигрывают дедупликацию по имени);
- hot-reload смены &Расширяет (источник ленивый);
- корректный go-to-definition (унаследованный член хранит sourceSymbol
  метода родителя).

Добавлена защита от циклов наследования (ThreadLocal-гард).
Извлечение родителя вынесено в общий util OScriptExtends (DRY с
TypeHierarchyProvider).

https://claude.ai/code/session_0181QDW1r8NYKkWybSgcjyPv
…ностей)

Распознавание родителя переключено с прямого имени &Расширяет на роль
"Расширяет" через AutumnMetaAnnotationResolver. Это покрывает мета-аннотации
фреймворка «ОСень»: класс, помеченный пользовательской аннотацией, чьё
определение несёт &Расширяет (как &ХранилищеСущностей в autumn-data),
наследует методы супер-класса (ПолучитьОдно, Получить, Сохранить и т.п.).

Прямое &Расширяет("X") по-прежнему работает (роль распознаётся и без
класса-определения), английский &Extends — через явный fallback.

Добавлен fixture по образцу autumn-data и тест AutumnDataInheritanceTest.

https://claude.ai/code/session_0181QDW1r8NYKkWybSgcjyPv
…тель)

Поле, хранящее экземпляр родителя, типизируется родительским классом, что
даёт автодополнение/hover по членам супер-класса при обращении к родителю:
- явный держатель — поле модуля с аннотацией &Родитель (имя произвольное);
- неявный — поле _ОбъектРодитель, которое библиотека extends создаёт в
  собранном объекте (в исходниках наследника не объявлено) — типизируется
  фолбэком в inferIdentifier.

Тип выводится ТОЛЬКО если класс объявляет наследование (&Расширяет напрямую
или через мета-аннотацию): источник типа — OScriptExtends.parentClassName,
который пуст без наследования (покрыто негативным тестом).

https://claude.ai/code/session_0181QDW1r8NYKkWybSgcjyPv
…ует)

Реализован textDocument/implementation (ранее возвращал пусто) для библиотеки
extends: интерфейс — класс с &Интерфейс, класс реализует его через &Реализует.
- курсор на экспортном методе интерфейса → одноимённые методы реализующих классов;
- курсор в файле-интерфейсе → сами реализующие классы.

Поддержан сложный случай из документации extends (комбинирование наследования
и интерфейсов): абстрактный родитель объявляет &Реализует("Интерфейс"), а
реализация — в наследнике. Реализация интерфейса определяется транзитивно по
цепочке &Расширяет, поэтому наследники абстрактного класса тоже считаются
реализациями.

Capability setImplementationProvider зарегистрирован. Детектирование интерфейса
и &Реализует учитывает мета-аннотации «ОСени» (через AutumnMetaAnnotationResolver).

https://claude.ai/code/session_0181QDW1r8NYKkWybSgcjyPv
- fix(javadoc): экранировать & в примере autumn-data (doclint html)
- refactor: общий OScriptClassResolver (classNames/resolveClassDocument/
  isLibraryClass) вместо дублирования в TypeHierarchyProvider и
  ImplementationProvider (устранение дублей для Sonar)
- test: OScriptExtendsTest, OScriptClassResolverTest, маршрутизация
  type hierarchy/implementation в BSLTextDocumentServiceTest, проверки
  capability в BSLLanguageServerTest, non-OS prepare

https://claude.ai/code/session_0181QDW1r8NYKkWybSgcjyPv
…entationProvider

- ImplementationProvider: сортировка локаций по URI (он уникален в результатах),
  убран мёртвый guard на пустые имена, упрощён methodNameAt (конструктор
  отсекается фильтром экспортности) — меньше мёртвого кода для Sonar.
- Тесты: ветки non-OS/без-наследования/без-аргумента, basename-резолв,
  плоское поле (не родитель), null-prepare, базовый класс без наследуемых
  членов; маршрутизация в сервисе и capability в сервере.

https://claude.ai/code/session_0181QDW1r8NYKkWybSgcjyPv
…solver

TypeHierarchyProvider больше не импортирует OScriptLibraryIndex (перешёл на
OScriptClassResolver), из-за чего {@link OScriptLibraryIndex} в javadoc
ломал сборку build-javadoc. Ссылка обновлена на OScriptClassResolver.

https://claude.ai/code/session_0181QDW1r8NYKkWybSgcjyPv
…ng-тестов

По ревью CodeRabbit:
- OScriptClassResolver.resolveClassDocument: при совпадении basename у
  нескольких .os выбираем минимальный по URI (порядок getDocuments() не
  гарантирован) — детерминированный результат.
- BSLTextDocumentServiceTest: routing-тесты type hierarchy/implementation
  теперь открывают связанные документы и проверяют непустой результат
  (super/subtypes и список реализаций), а не только non-null.

https://claude.ai/code/session_0181QDW1r8NYKkWybSgcjyPv
- ImplementationProvider.methodNameAt помечен @nullable: пакет @NullMarked,
  метод может вернуть null. Чинит S2637 (возврат null) и S2583 (проверка
  methodName != null больше не «всегда true»).
- OScriptModuleMembersProvider: ThreadLocal INHERITANCE_IN_PROGRESS очищается
  через remove(), когда набор пуст — не держим пустой Set на пуловых потоках (S5164).
- OScriptInheritanceMembersTest: assertion doesNotContain дополнен contains,
  чтобы не проходить вхолостую на пустом списке (S5841).

https://claude.ai/code/session_0181QDW1r8NYKkWybSgcjyPv
- OScriptExtends.parentClassName: вынесен parentFromAnnotations, логика на
  стримах — снижены cognitive complexity (S3776 17→<15) и вложенность (S134).
- ImplementationProvider: цикл сведён к одному continue (S135).
- OScriptModuleMembersProvider: static-поле INHERITANCE_IN_PROGRESS поднято к
  началу класса (S1213); java.util.Set → Set (S1942).
- Тесты: многострочные фикстуры переведены на text blocks (S6126),
  убран неиспользуемый импорт java.util.List (S1128).

https://claude.ai/code/session_0181QDW1r8NYKkWybSgcjyPv
nixel2007 added a commit that referenced this pull request Jun 11, 2026
- ссылка на библиотеку extends ведёт на github.com/nixel2007/extends (4 javadoc);
- classNames: убран фолбэк для нерезолвящихся URI — .os-документы всегда
  иерархические file:-URI, basename обязан разрешаться (нерезолв — ошибка в коде);
- тест переименован под фактическое поведение, убраны FQN в пользу импорта.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
nixel2007 and others added 5 commits June 11, 2026 09:00
…ана документов

По ревью архитектуры: subtypes() и поиск реализаторов сканировали все документы
workspace на каждый запрос. Теперь прямые отношения хранятся в TypeRelationIndex —
ленивом обратном индексе «имя родителя → URI наследников» и «имя интерфейса → URI
реализаторов» (только сырые имена, lowercase; разрешение имён и транзитивность —
по-прежнему на момент запроса). Инкрементальная инвалидация: правка/добавление/
удаление .os-документа меняет вклад точечно, правка класса-определения аннотации,
переиндексация библиотек и перепопуляция контекста сбрасывают индекс на ленивую
пересборку.

Прежний live-класс переименован в TypeRelations (он не хранилище): supertype/
inheritedMembers без изменений, subtypes() — лукап по индексу, implementsAny
заменён на implementors(интерфейс) — поиск «вниз» (замыкание производных
интерфейсов + поддеревья наследников реализаторов) без перебора кандидатов;
ImplementationProvider больше не сканирует документы. Общий classSelectionRange
вынесен в TypeRelations (дубль в двух провайдерах), мёртвый guard и прокси-метод
в TypeHierarchyProvider убраны.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
- S1905: убран лишний каст — у ServerContextDocumentAddedEvent типизированный getSource;
- S2211: явные типы параметров лямбд в TypeRelationIndex;
- S3776/S1541: implementors разложен на interfaceClosureNames и expandImplementors;
- S1213: статический компаратор выше инстанс-полей в TypeHierarchyProvider;
- S2325: constructorAnnotations в OScriptExtends стал static;
- S5976: четыре однотипных parentClassName-теста сведены в параметризованный;
- S125×2: переформулированы русские комментарии, похожие на код; убран
  провенанс-комментарий про ревью;
- S1128: удалён неиспользуемый импорт в TypeRelationsTest.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
… по ревью

По ревью PR #4014:
- ссылки в javadoc указывают на github.com/nixel2007/extends (канонический
  репозиторий) вместо oscript-library/extends — в OScriptExtends,
  ImplementationProvider, TypeHierarchyProvider, TypeRelations;
- «опакового» → «непрозрачного» (несуществующее слово) в комментарии
  OScriptLibraryIndex.classNames.

https://claude.ai/code/session_0181QDW1r8NYKkWybSgcjyPv
- ссылка на библиотеку extends ведёт на github.com/nixel2007/extends (4 javadoc);
- classNames: убран фолбэк для нерезолвящихся URI — .os-документы всегда
  иерархические file:-URI, basename обязан разрешаться (нерезолв — ошибка в коде);
- тест переименован под фактическое поведение, убраны FQN в пользу импорта.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
@nixel2007
nixel2007 force-pushed the claude/os-files-type-hierarchy-HzJ5n branch from 1e0218e to d803fdc Compare June 11, 2026 07:00
Comment thread src/main/java/com/github/_1c_syntax/bsl/languageserver/BSLLanguageServer.java Outdated
nixel2007 and others added 9 commits June 11, 2026 09:13
OScriptMetaAnnotationResolver не зависит от экосистемы ОСени: это движок
пользовательских аннотаций autumn-library/annotations. Константы движка
(&Аннотация, &ПсевдонимДля, Значение) выделены в класс-константник
OScriptAnnotations, методы чтения аннотаций (find, stringParameter,
isAnnotationDefinition) — методы компонента-резолвера. AutumnAnnotations
остался константником имён аннотаций ОСени.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
…tends

Проверка «класс — определение аннотации» — ответственность резолвера
мета-аннотаций; потребители обращаются к нему напрямую.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
…actOScriptLazyIndex

Барьер первичной сборки, инвалидация по OScriptLibraryIndexedEvent,
точечная переиндексация на правку и сброс при изменении класса-определения
аннотации — общие для autumn-индексов и TypeRelationIndex; теперь они
наследуют одну базу. AbstractAutumnLibraryIndex оставил себе лишь источник
пересборки из записей-классов библиотек.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
…nds_

OScriptExtends, TypeRelations и TypeRelationIndex — поддержка библиотеки
наследования extends; выделены в подпакет types.oscript.extends_
(extends — зарезервированное слово Java).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Класс-константник по образцу AutumnAnnotations (имена аннотаций ОСени) и
OScriptAnnotations (служебные имена движка аннотаций): &Расширяет, &Реализует,
&Интерфейс, &Родитель и неявное поле _ОбъектРодитель — в ExtendsAnnotations.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
…индекса

Basename-фолбэк снесён: имя класса берётся из qualifiedName записей
OScriptLibraryIndex, для незарегистрированного файла список пуст.
TypeHierarchyProvider не строит элементы для незарегистрированных
документов; фикстура type-hierarchy оформлена библиотекой с lib.config.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
…bilities

Вместо setImplementationProvider(Boolean.TRUE) — ImplementationRegistrationOptions
по образцу соседних провайдеров.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
types.inferencer.annotations → types.oscript.annotations,
types.inferencer.autumn → types.oscript.autumn: всё oscript-зависимое — в
пакете oscript, библиотеко-специфичное — в его подпакетах (annotations,
autumn, extends_); зависимости между пакетами прослеживаются по импортам.
У каждого пакета package-info.java с javadoc и @NullMarked.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
…ionResolver

Явные типы лямбд (S2211), константа вместо магического числа (S109),
переформулированы комментарии, похожие на код (S125), убран импорт
класса своего пакета (S1128).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
@sonarqubecloud

Copy link
Copy Markdown

@nixel2007
nixel2007 merged commit 960671e into develop Jun 11, 2026
37 checks passed
@nixel2007
nixel2007 deleted the claude/os-files-type-hierarchy-HzJ5n branch June 11, 2026 11: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.

2 participants