Skip to content

fix: показывать информацию символа своего языка (BSL/OneScript) в ховере и подсказках#4064

Merged
nixel2007 merged 17 commits into
developfrom
fix/issue-4054
Jun 12, 2026
Merged

fix: показывать информацию символа своего языка (BSL/OneScript) в ховере и подсказках#4064
nixel2007 merged 17 commits into
developfrom
fix/issue-4054

Conversation

@nixel2007

@nixel2007 nixel2007 commented Jun 12, 2026

Copy link
Copy Markdown
Member

Closes #4054

Проблема

В .os-файле ховер по ПодробноеПредставлениеОшибки показывал BSL-вариант документации — с «устарела с 8.3.17» и рекомендацией ОбработкаОшибок.ПодробноеПредставлениеОшибки, не имеющими смысла для OneScript. Причина системная: BSL- и OneScript-наборы глобалов сливались в одну структуру по принципу «первый/последний победил», и для имён, существующих в обоих языках, один из вариантов молча терялся.

Что исправлено

  • Глобальные функцииGlobalScopeProvider хранит наборы каждого языка раздельно (Map<FileType, Loaded>); findFunction/getFunctions отдают дескриптор языка файла. Закрывает ховер, completion, signature help, вывод типов и семантические токены разом.
  • Двуязычные описания типовTypeRegistry.typeDescriptionsBilingual хранит описания списком со скоупом (по образцу descriptions/constructors); ховер Новый ТаблицаЗначений(...) и документация completion берут описание по языку файла. Определение типа файла по URI выделено в FileType.fromUri.
  • «Голые» глобальные имена (системные перечисления, глобальные свойства, имена классов) — GlobalSymbolScope хранит записи со скоупом и выбирает вариант по типу файла (точный скоуп приоритетнее BOTH); library-модули/классы OneScript регистрируются со скоупом OS.
  • Ключевые слова — описание в ховере (Пока, Выполнить) берётся из набора своего языка.

Члены типов, значения системных перечислений и конструкторы уже фильтровались по скоупу источника корректно — это зафиксировано регресс-тестами (TypeRegistryLanguageScopedMembersTest), чтобы не сломать.

Тесты

  • e2e на ховер в HoverProviderTest: функция / конструктор / перечисление / ключевое слово, в .bsl и .os;
  • юнит-тесты выбора варианта: GlobalScopeProviderLanguageVariantTest, TypeRegistryScopedDescriptionsTest, GlobalSymbolScopeTest;
  • полный набор тестов зелёный.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Documentation and hover content now adapt to the current file type (BSL vs OneScript), showing the appropriate bilingual descriptions and variants.
    • Completions and type-info reflect file-type-scoped platform/type visibility for more accurate results.
  • Bug Fixes

    • Hover text, constructor/tooltips and completion items no longer show OneScript-specific details in BSL files (and vice versa); file-type-specific deprecations and descriptions are shown correctly.

nixel2007 and others added 3 commits June 12, 2026 13:53
…ах (#4054)

Глобальные функции BSL и OneScript сливаются в одну мапу с приоритетом
BSL: для имён, существующих в обоих языках (ПодробноеПредставлениеОшибки
и т.п.), OneScript-дескриптор молча отбрасывался, и в .os-файлах ховер,
автодополнение и signature help показывали BSL-вариант с платформенными
метаданными (устаревание с 8.3.17, рекомендация ОбработкаОшибок.…).

OneScript-набор сохраняется отдельно (osFunctions); findFunction и
getFunctions для FileType.OS отдают OneScript-дескриптор.

Co-Authored-By: Claude Fable 5 <[email protected]>
Двуязычные описания типов хранились одной записью на TypeRef
(putIfAbsent — первый победил): для типов, существующих и в BSL, и в
OneScript (ТаблицаЗначений и т.п.), ховер конструктора «Новый Х(...)»
и документация completion показывали описание не того языка.

Описания хранятся списком со скоупом (по образцу descriptions/
constructors), добавлен getDescription(ref, language, fileType); тип
файла прокинут в ConstructorHoverBuilder и completion платформенных
классов. Определение FileType по URI выделено в FileType.fromUri.

Плюс регресс-тесты, фиксирующие уже корректную scope-фильтрацию членов
типов, значений системных перечислений и конструкторов.

Co-Authored-By: Claude Fable 5 <[email protected]>
…ать вариант по типу файла (#4054)

GlobalSymbolScope хранил одну запись на имя (последняя регистрация
побеждала): «голые» глобальные имена, существующие в обоих языках
(КодировкаТекста, имена классов), получали один символ с описанием
случайного языка. Записи теперь хранятся со скоупом (BSL/OS/BOTH), и
findEntry(name, fileType) выбирает вариант своего языка с приоритетом
точного скоупа над BOTH; library-модули и классы OneScript регистрируются
с явным скоупом OS.

GlobalScopeProvider вместо параллельных os*-мап хранит наборы каждого
языка как Map<FileType, Loaded>: функции, платформенные переменные и
перечисления, ключевые слова и их описания читаются из набора своего
языка напрямую, без scope-фильтрации merged-данных. Каждый язык
публикуется в GlobalSymbolScope со своим скоупом. Описание ключевого
слова в ховере выбирается по типу файла (Пока/Выполнить различаются
между BSL и OneScript).

Co-Authored-By: Claude Fable 5 <[email protected]>
@coderabbitai

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

The PR migrates language scoping from LanguageScope to FileType across TypeRegistry, GlobalScopeProvider, GlobalSymbolScope, providers (hover/completion/keyword), and tests, making lookups, descriptions, constructors, and registrations file-type aware and adding OS/BSL regression tests.

Changes

FileType scoping migration

Layer / File(s) Summary
FileType migration (all affected files)
src/main/java/..., src/test/java/...
Signatures, storage, and lookups were changed to accept/partition by FileType; hover/completion/keyword flows now pass FileType into description/constructor resolution and tests updated to assert OS vs BSL differences.

Sequence Diagram(s)

sequenceDiagram
  participant CompletionProvider
  participant ConstructorCallMarkupContentBuilder
  participant ConstructorHoverBuilder
  participant TypeService
  CompletionProvider->>TypeService: getDescription(ref, scriptVariant, fileType)
  ConstructorCallMarkupContentBuilder->>ConstructorHoverBuilder: build(..., fileType)
  ConstructorHoverBuilder->>TypeService: getDescription(ref, lang, fileType)
  TypeService-->>ConstructorHoverBuilder: FileType-specific description
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~90+ minutes

Possibly related PRs

Suggested reviewers

  • sfaqer

Poem

🐰 I hopped from scope to file type bright,
OneScript and BSL now sort just right.
Hovers and symbols in matching burrows lie,
With FileType ears up in the moonlit sky.

✨ 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 fix/issue-4054

…е FileType

По ревью #4064. Третье значение BOTH было нужно только как «не знаем» и
как эскалация при merge — оба применения устранены:

- TypeRegistry: typeScopes → typeFileTypes (Map<TypeRef, Set<FileType>>),
  регистрации аддитивны (registerFileType), видимость — isVisibleIn;
  отсутствие записи = видим везде (отсутствие знания, не значение enum).
  Scoped-записи источников членов, описаний и конструкторов несут FileType
  и фильтруются точным сравнением.
- GlobalSymbolScope: записи привязаны к конкретному FileType; сущность,
  видимая в обоих языках, регистрируется двумя вызовами. Конфликт
  «общая запись vs языко-специфичная» невозможен по построению.
- GlobalScopeProvider: Loaded без scope-карт; классы и ключевые слова
  отдаются статическими per-language списками; видимость переменных —
  по per-language индексу имён; merge упрощён до дедупликации.
- Провайдеры объявляют FileType (getFileType) вместо LanguageScope;
  пользовательские типы и library-сущности OneScript видимы только в OS,
  конфигурационные (mdclasses/bsl-context) — только в BSL, включая
  registerAsGlobalProperty в ConfigurationTypesProvider (был BOTH).
- Удалены мёртвые overload'ы с дефолтом BOTH (registerMemberSource,
  registerConstructorSource, registerUserType, registerPack,
  registerGlobalProperty без языка) — язык указывается явно.

Co-Authored-By: Claude Fable 5 <[email protected]>
@nixel2007

Copy link
Copy Markdown
Member Author

По итогам ревью добавлен d6f729c568: LanguageScope удалён полностью — все языковые данные хранятся и регистрируются в разрезе FileType.

  • BOTH исчез: «не знаем» выражается отсутствием записи (isVisibleIn для незарегистрированных типов — true), сущность обоих языков регистрируется двумя вызовами, merge-эскалаций нет.
  • Классы и пользовательские типы OneScript не видны в BSL и наоборот; конфигурационные сущности (mdclasses/bsl-context) — BSL-only, включая registerAsGlobalProperty в ConfigurationTypesProvider (раньше — BOTH).
  • Удалены overload'ы с дефолтным скоупом — язык всегда указывается явно.
  • Итог −790/+500 строк, полный набор тестов зелёный.

@Override
public MarkupContent getContent(Reference reference) {
var symbol = (ConstructorCallSymbol) reference.symbol();
var fileType = FileType.fromUri(reference.uri());

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

зачем? из Reference доступен from, а это SourceDefinedSymbol, у которого есть DocumentContext в виде owner

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Исправлено в b5c4444: reference.from().getOwner().getFileType(). Хелпер FileType.fromUri откачен целиком — единственный потребитель исчез, DocumentContext.computeFileType вернулся к приватной реализации.

nixel2007 and others added 3 commits June 12, 2026 15:54
… источник

По ревью #4064. merge(bsl, os) и merged-поля обслуживали только варианты
API без fileType, у которых не осталось ни одного боевого вызова — все
потребители (ховер, completion, signature help, инференсер, семантические
токены) передают язык файла.

- merge/mergeNames/mergeVariables и merged-поля удалены; Map<FileType, Loaded>
  byFileType — единственное хранилище загруженных глобалов;
- удалены варианты API без fileType (findFunction(String), getFunctions(),
  getClasses(), getKeywords(), findGlobalProperty/Enum(String),
  getGlobal*Names(), findGlobalContext(String), findGlobal(String),
  findKeywordDescription без языка) и null-ветки fileType — язык обязателен;
- findKeywordSnippet принимает FileType и читает набор своего языка;
- проверка видимости в findGlobal смотрит в оба per-language набора.

Co-Authored-By: Claude Fable 5 <[email protected]>
По ревью #4064: вместо Map<TypeRef, Set<FileType>> и записей с полем
fileType — разрезы по языку, где FileType ключ верхнего уровня:

- TypeRegistry: visibleTypes — Map<FileType, Set<TypeRef>>;
- GlobalScopeProvider: globalContextNames — Map<FileType, Set<String>>;
- GlobalSymbolScope: entries — Map<FileType, Map<String, Entry>>;
  ScopedEntry удалён, findEntry(name, fileType) — прямой get,
  повторная регистрация того же языка — обычный put-replace.

Тесты merged-эпохи переписаны под строгий разрез: library-модуль
OneScript видим только в OS, статический classes-список не расширяется
динамической регистрацией, generic-фильтрация bsl-context не
маскируется OS-набором.

Co-Authored-By: Claude Fable 5 <[email protected]>
…ссылки

По inline-ревью #4064: вместо разбора reference.uri() — готовый
documentContext через reference.from().getOwner(). Хелпер
FileType.fromUri откачен: единственный потребитель исчез,
DocumentContext.computeFileType вернулся к приватной реализации.

Co-Authored-By: Claude Fable 5 <[email protected]>

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (7)
src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/BuiltinOScriptPlatformTypesProvider.java (1)

37-40: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update the class JavaDoc to match the new FileType contract.

This comment still says language gating is handled elsewhere, but this provider now explicitly declares its visibility through getFileType() returning FileType.OS. Leaving the old wording behind is misleading during this migration.

As per coding guidelines, "Write JavaDoc for public APIs, include comments for complex logic, and keep documentation up to date with code changes."

🤖 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/registry/BuiltinOScriptPlatformTypesProvider.java`
around lines 37 - 40, Update the class JavaDoc for
BuiltinOScriptPlatformTypesProvider to reflect the new FileType contract: remove
the statement that language gating is handled elsewhere and explicitly document
that this provider declares its visibility by returning FileType.OS from
getFileType(), describe the effect/intent (only OS files), and note that it
still reuses the builtin-platform-types.json loader for resource behavior; keep
the doc concise and aligned with the public API contract.

Source: Coding guidelines

src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/KeywordMetadataBuilder.java (1)

40-44: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Remove the obsolete “+ scope” wording from the builder JavaDoc.

The builder no longer tracks or exports per-keyword scope, so this description is now inaccurate. It should describe only the keyword list, snippets, and descriptions that KeywordMetadata still contains.

As per coding guidelines, "Write JavaDoc for public APIs, include comments for complex logic, and keep documentation up to date with code changes."

🤖 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/registry/KeywordMetadataBuilder.java`
around lines 40 - 44, Update the JavaDoc on KeywordMetadataBuilder to remove the
obsolete "+ scope" phrase and make the description match current behavior: state
that it accumulates parsing of builtin-keywords.json into KeywordMetadata,
producing a flat list of names, snippets and descriptions (including
descriptionByParent), and that each name is added in both ru-canonical and
en-alias lower-cased. Edit the class-level comment in KeywordMetadataBuilder
(referencing KeywordMetadata) to remove any mention of per-keyword scope and
ensure the wording accurately reflects only the keyword list, snippets, and
descriptions exported.

Source: Coding guidelines

src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistry.java (3)

999-1005: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Drop constructor state when unregistering a user type.

unregisterUserType clears member sources, but it leaves constructors and constructorSources behind. For .os classes this leaks the old DocumentContext suppliers and duplicates constructor signatures when the same class name is registered again later.

Suggested fix
   public void unregisterUserType(String qualifiedName) {
     var ref = intern(TypeKind.USER, qualifiedName);
     types.remove(ref);
     memberSources.remove(ref);
+    constructors.remove(ref);
+    constructorSources.remove(ref);
     membersEpoch.incrementAndGet();
     visibleTypes.values().forEach(typed -> typed.remove(ref));
     aliasIndex.remove(qualifiedName.toLowerCase(Locale.ROOT));
   }
🤖 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/registry/TypeRegistry.java`
around lines 999 - 1005, unregisterUserType currently removes types and
memberSources but leaves constructor-related state, causing leaks and duplicate
constructor signatures; update unregisterUserType (the method that does
intern(TypeKind.USER, qualifiedName) and removes from types, memberSources,
visibleTypes and aliasIndex) to also remove any entries keyed by the same ref
from constructors and constructorSources and then update the constructorsEpoch
(or equivalent epoch/version used for constructor change notifications) to
reflect the mutation so suppliers are dropped and subsequent re-registration
won't duplicate constructors.

499-513: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Preserve additive visibility when a specialization already exists.

When specializedName is already present, this path reuses the existing TypeRef but skips registerFileType(...). That leaves visibleTypes unchanged, so the second language variant stays unresolved by resolve(name, fileType) even though you just registered scoped members for it.

Suggested fix
     if (existing == null) {
       // Регистрируем как полноценный тип того же kind, что и generic, чтобы
       // инференсер (резолвящий типы по имени через aliasIndex / по паре
       // (kind, name)) находил тот же TypeRef и member-source'ы доходили
       // до getMembers.
       types.put(specializedRef, hydrate(specializedRef));
       addAlias(specializedName, specializedRef);
-      registerFileType(specializedRef, fileType);
     }
+    registerFileType(specializedRef, fileType);
     registerSpecialization(specializedRef, genericRef, bindings, fileType);
🤖 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/registry/TypeRegistry.java`
around lines 499 - 513, The code reuses an existing TypeRef from
resolve(specializedName) but does not call registerFileType(...) for that
existing ref, so visibleTypes isn't updated and resolve(name, fileType) can fail
for the second variant; update the logic in the block around resolve/intern so
that when existing != null you still call registerFileType(existing, fileType)
(or always call registerFileType(specializedRef, fileType) after computing
specializedRef) before registerSpecialization, ensuring
types.put/hydrate/addAlias remain unchanged but visibility is preserved for the
file-scoped resolution.

555-572: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Thread fileType into generic-derived members.

Both specialization and member expansion currently read the source generic via unfiltered getMembers(genericRef). That reintroduces the BSL/OS mixing this PR is trying to remove: a BSL-only derived type can materialize OS members, and vice versa, whenever the generic exists in both slices.

Suggested direction
     MemberSource source = () -> {
-      var raw = getMembers(genericRef);
+      var raw = getMembers(genericRef, fileType);
       if (raw.isEmpty()) {
         return List.of();
       }
       var result = new ArrayList<MemberDescriptor>(raw.size());
     MemberSource source = () -> {
-      var materialized = expandGenericMembers(genericRef, safeTypeBindings, safeExpansions);
+      var materialized = expandGenericMembers(genericRef, safeTypeBindings, safeExpansions, fileType);
-  private List<MemberDescriptor> expandGenericMembers(TypeRef genericRef,
-                                                      Map<String, String> typeBindings,
-                                                      Map<String, List<String>> memberExpansions) {
-    var raw = getMembers(genericRef);
+  private List<MemberDescriptor> expandGenericMembers(TypeRef genericRef,
+                                                      Map<String, String> typeBindings,
+                                                      Map<String, List<String>> memberExpansions,
+                                                      FileType fileType) {
+    var raw = getMembers(genericRef, fileType);

Also applies to: 611-620, 662-676

🤖 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/registry/TypeRegistry.java`
around lines 555 - 572, The member expansion uses getMembers(genericRef) without
respecting the fileType, allowing OS/BSL members from the generic slice to leak
into specialized types; update the MemberSource logic used when creating
specializedRef (and the analogous locations ~611-620 and ~662-676) to only
iterate members filtered by the same fileType as the derived type—i.e., call the
fileType-aware member lookup (or add a fileType parameter to getMembers) instead
of plain getMembers(genericRef), then continue to specialize and index only
those members so member.specialize(safeBindings) and
memberMetadataIndex.index(specializedRef, specialized) operate on the correctly
filtered set before registerMemberSource(specializedRef, source, fileType).
src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/GlobalScopeProvider.java (2)

319-320: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Keep library handling scoped to the OS slice.

These paths still treat library names as global across both languages. In findGlobal, any OS library name collision suppresses the BSL symbol on the same name. In unregisterLibrarySymbol, findSymbol(name) returns the first slice match, so removing an OS library entry can unregister the BSL symbol instead.

Suggested direction
-    if (oScriptLibraryIndex != null && oScriptLibraryIndex.findByName(lc).isPresent()) {
-      return fileType == FileType.OS ? sym : Optional.empty();
-    }
   private void unregisterLibrarySymbol(String name) {
     if (name == null || name.isBlank()) {
       return;
     }
-    globalSymbolScope.findSymbol(name).ifPresent(globalSymbolScope::unregister);
+    globalSymbolScope.findEntry(name, FileType.OS)
+      .map(GlobalSymbolScope.Entry::symbol)
+      .ifPresent(globalSymbolScope::unregister);
   }

Also applies to: 731-735

🤖 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/registry/GlobalScopeProvider.java`
around lines 319 - 320, The library lookup and removal logic is incorrectly
treating OS libraries as global across slices; update the checks in findGlobal
and unregisterLibrarySymbol so library name resolution and unregistration only
consider the OS slice: in findGlobal, only consult
oScriptLibraryIndex.findByName(lc) when the current fileType equals FileType.OS
(keep the existing return sym only for OS and otherwise skip library hits), and
in unregisterLibrarySymbol avoid using the generic findSymbol(name) that returns
the first slice match—use a slice-aware lookup or filter by FileType.OS (or
explicitly target the OS slice index) so removing an OS library entry cannot
unregister a BSL symbol with the same name. Ensure references to
oScriptLibraryIndex, findGlobal, unregisterLibrarySymbol, findSymbol(name), and
FileType.OS are updated accordingly.

611-628: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

getGlobalContexts(FileType) is no longer filtering builtin/platform entries correctly.

matchesGlobalScope only consults globalContextNames, but that index is populated only by dynamic registerGlobalProperty(...) calls. Builtin platform globals, enums, and library modules are therefore treated as “not registered anywhere” and leak into both getGlobalContexts(fileType) and getGlobalContextNames(fileType).

Suggested direction
   public List<SyntheticSymbol> getGlobalContexts(FileType fileType) {
     return getGlobalContexts().stream()
-      .filter(s -> matchesGlobalScope(s.getName(), fileType))
+      .filter(s -> findGlobalEntry(s.getName(), fileType).isPresent())
       .toList();
   }

Also applies to: 652-661

🤖 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/registry/GlobalScopeProvider.java`
around lines 611 - 628, matchesGlobalScope currently checks only the dynamic
index (globalContextNames populated by registerGlobalProperty), so
builtin/platform globals and library-module symbols are missed; update
matchesGlobalScope to also consult the canonical names of built-in globals
(e.g., the canonical names from the existing builtins/enums/library-module
registry) or simply derive the allowed names from getGlobalContexts() instead of
only the globalContextNames field; ensure getGlobalContexts(FileType) and
getGlobalContextNames(FileType) then correctly filter by calling the updated
matchesGlobalScope so builtin/platform entries are excluded when they don't
match the fileType.
🧹 Nitpick comments (1)
src/test/java/com/github/_1c_syntax/bsl/languageserver/providers/HoverProviderTest.java (1)

238-243: ⚡ Quick win

Consider strengthening assertions for more reliable test coverage.

These tests wrap their assertions in if (optionalHover.isPresent()), which means they pass even when hover is absent. The corresponding OneScript tests (lines 263 and 313) unconditionally assert isPresent(), creating an inconsistency.

For more robust regression coverage, either:

  1. Assert isPresent() to ensure BSL-variant hover exists, then verify it doesn't contain OS-specific text, OR
  2. Document in a comment why hover might legitimately be absent for these symbols in BSL files.

The current pattern could mask bugs where hover should be available but isn't being generated.

💪 Proposed strengthening of assertions

For the global enum test (lines 238-243):

-    if (optionalHover.isPresent()) {
-      var markdown = optionalHover.get().getContents().getRight().getValue();
-      assertThat(markdown)
-        .as("hover глобального перечисления в .bsl не должен содержать OneScript-описание")
-        .doesNotContain("допустимых кодировок");
-    }
+    assertThat(optionalHover)
+      .as("hover должен быть доступен для глобального перечисления в .bsl")
+      .isPresent();
+    var markdown = optionalHover.get().getContents().getRight().getValue();
+    assertThat(markdown)
+      .as("hover глобального перечисления в .bsl не должен содержать OneScript-описание")
+      .doesNotContain("допустимых кодировок");

Apply the same pattern to the keyword test at lines 287-292.

Also applies to: 287-292

🤖 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/HoverProviderTest.java`
around lines 238 - 243, Replace the conditional guard that silently skips
assertions when hover is missing with an explicit presence assertion: in
HoverProviderTest change the "if (optionalHover.isPresent()) { ... }" blocks to
first assertThat(optionalHover).isPresent() and then retrieve the hover via
optionalHover.get() to assert the markdown does not contain OneScript-specific
text; apply this change for the global enum test (current optionalHover usage
around lines 238-243) and the keyword test (around lines 287-292) so tests fail
if hover is unexpectedly absent rather than silently passing.
🤖 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/registry/TypeRegistry.java`:
- Around line 474-477: registerMemberOverride mutates memberSources but doesn't
invalidate the memoized members; update it to bump the members cache epoch or
clear the cache so getMembers will recompute. Concretely, inside
registerMemberOverride (which currently computes list and adds new
ScopedMemberSource), after list.addFirst(...) either increment membersEpoch
(e.g., membersEpoch++) or call membersCache.clear()/invalidate() so that
getMembers will not return stale data; ensure you reference the same
membersEpoch/membersCache fields used by getMembers.

---

Outside diff comments:
In
`@src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/BuiltinOScriptPlatformTypesProvider.java`:
- Around line 37-40: Update the class JavaDoc for
BuiltinOScriptPlatformTypesProvider to reflect the new FileType contract: remove
the statement that language gating is handled elsewhere and explicitly document
that this provider declares its visibility by returning FileType.OS from
getFileType(), describe the effect/intent (only OS files), and note that it
still reuses the builtin-platform-types.json loader for resource behavior; keep
the doc concise and aligned with the public API contract.

In
`@src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/GlobalScopeProvider.java`:
- Around line 319-320: The library lookup and removal logic is incorrectly
treating OS libraries as global across slices; update the checks in findGlobal
and unregisterLibrarySymbol so library name resolution and unregistration only
consider the OS slice: in findGlobal, only consult
oScriptLibraryIndex.findByName(lc) when the current fileType equals FileType.OS
(keep the existing return sym only for OS and otherwise skip library hits), and
in unregisterLibrarySymbol avoid using the generic findSymbol(name) that returns
the first slice match—use a slice-aware lookup or filter by FileType.OS (or
explicitly target the OS slice index) so removing an OS library entry cannot
unregister a BSL symbol with the same name. Ensure references to
oScriptLibraryIndex, findGlobal, unregisterLibrarySymbol, findSymbol(name), and
FileType.OS are updated accordingly.
- Around line 611-628: matchesGlobalScope currently checks only the dynamic
index (globalContextNames populated by registerGlobalProperty), so
builtin/platform globals and library-module symbols are missed; update
matchesGlobalScope to also consult the canonical names of built-in globals
(e.g., the canonical names from the existing builtins/enums/library-module
registry) or simply derive the allowed names from getGlobalContexts() instead of
only the globalContextNames field; ensure getGlobalContexts(FileType) and
getGlobalContextNames(FileType) then correctly filter by calling the updated
matchesGlobalScope so builtin/platform entries are excluded when they don't
match the fileType.

In
`@src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/KeywordMetadataBuilder.java`:
- Around line 40-44: Update the JavaDoc on KeywordMetadataBuilder to remove the
obsolete "+ scope" phrase and make the description match current behavior: state
that it accumulates parsing of builtin-keywords.json into KeywordMetadata,
producing a flat list of names, snippets and descriptions (including
descriptionByParent), and that each name is added in both ru-canonical and
en-alias lower-cased. Edit the class-level comment in KeywordMetadataBuilder
(referencing KeywordMetadata) to remove any mention of per-keyword scope and
ensure the wording accurately reflects only the keyword list, snippets, and
descriptions exported.

In
`@src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistry.java`:
- Around line 999-1005: unregisterUserType currently removes types and
memberSources but leaves constructor-related state, causing leaks and duplicate
constructor signatures; update unregisterUserType (the method that does
intern(TypeKind.USER, qualifiedName) and removes from types, memberSources,
visibleTypes and aliasIndex) to also remove any entries keyed by the same ref
from constructors and constructorSources and then update the constructorsEpoch
(or equivalent epoch/version used for constructor change notifications) to
reflect the mutation so suppliers are dropped and subsequent re-registration
won't duplicate constructors.
- Around line 499-513: The code reuses an existing TypeRef from
resolve(specializedName) but does not call registerFileType(...) for that
existing ref, so visibleTypes isn't updated and resolve(name, fileType) can fail
for the second variant; update the logic in the block around resolve/intern so
that when existing != null you still call registerFileType(existing, fileType)
(or always call registerFileType(specializedRef, fileType) after computing
specializedRef) before registerSpecialization, ensuring
types.put/hydrate/addAlias remain unchanged but visibility is preserved for the
file-scoped resolution.
- Around line 555-572: The member expansion uses getMembers(genericRef) without
respecting the fileType, allowing OS/BSL members from the generic slice to leak
into specialized types; update the MemberSource logic used when creating
specializedRef (and the analogous locations ~611-620 and ~662-676) to only
iterate members filtered by the same fileType as the derived type—i.e., call the
fileType-aware member lookup (or add a fileType parameter to getMembers) instead
of plain getMembers(genericRef), then continue to specialize and index only
those members so member.specialize(safeBindings) and
memberMetadataIndex.index(specializedRef, specialized) operate on the correctly
filtered set before registerMemberSource(specializedRef, source, fileType).

---

Nitpick comments:
In
`@src/test/java/com/github/_1c_syntax/bsl/languageserver/providers/HoverProviderTest.java`:
- Around line 238-243: Replace the conditional guard that silently skips
assertions when hover is missing with an explicit presence assertion: in
HoverProviderTest change the "if (optionalHover.isPresent()) { ... }" blocks to
first assertThat(optionalHover).isPresent() and then retrieve the hover via
optionalHover.get() to assert the markdown does not contain OneScript-specific
text; apply this change for the global enum test (current optionalHover usage
around lines 238-243) and the keyword test (around lines 287-292) so tests fail
if hover is unexpectedly absent rather than silently passing.
🪄 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: 767ef1ee-d177-4c35-a46e-e34cce36857f

📥 Commits

Reviewing files that changed from the base of the PR and between c4a8470 and b5c4444.

📒 Files selected for processing (49)
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/hover/ConstructorCallMarkupContentBuilder.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/hover/ConstructorHoverBuilder.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/providers/CompletionProvider.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/references/KeywordReferenceFinder.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/TypeService.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/model/LanguageScope.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/OScriptModuleMembersProvider.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/BslContextPlatformTypesProvider.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/BuiltinOScriptPlatformTypesProvider.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/BuiltinPlatformTypesProvider.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/BuiltinTypesJsonLoader.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/ConfigurationGenericExpander.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/ConfigurationModuleMembersProvider.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/ConfigurationTypesProvider.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/GlobalScopeProvider.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/KeywordMetadata.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/KeywordMetadataBuilder.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/KeywordMetadataLoader.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/MetadataCollectionSpecializer.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/PlatformTypesProvider.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistry.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/scope/GlobalSymbolScope.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/hover/ConstructorHoverBuilderTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/providers/HoverProviderTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/ConfigurationManagerChainInferenceTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/GlobalEnumPropertyInferenceTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/model/LanguageScopeTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/OScriptModuleMembersProviderTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/BuiltinPlatformTypesProviderTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/ConfigurationModuleMembersProviderTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/ConfigurationTypesProviderHelpersTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/ConfigurationTypesProviderTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/GlobalScopeProviderBslContextTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/GlobalScopeProviderLanguageVariantTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/GlobalScopeProviderRegistrationTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/GlobalScopeProviderResourceTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/KeywordMetadataBuilderTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/KeywordMetadataLoaderTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/MetadataCollectionSpecializerHelpersTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/MetadataCollectionSpecializerUnitTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/MultiWorkspaceTypeRegistryTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/RegisterCommonLibraryExpansionTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistryExpandedMembersTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistryLanguageScopedMembersTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistryRegistrationTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistryScopedDescriptionsTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistryScopedSourcesTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistrySpecializationTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/scope/GlobalSymbolScopeTest.java
💤 Files with no reviewable changes (2)
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/model/LanguageScopeTest.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/model/LanguageScope.java

nixel2007 and others added 3 commits June 12, 2026 16:42
По ревью #4064: platformVariableNames — производный индекс от содержимого
набора (lowercased имена + алиасы переменных и перечислений для
O(1)-проверки видимости в findGlobal), принципиального отличия от
остальных данных Loaded у него нет — вычисляется вспомогательным
конструктором записи.

globalContextNames остаётся отдельным полем сознательно: это мутабельный
runtime-реестр registerGlobalProperty (общие модули конфигурации,
library-модули), а не часть иммутабельного снапшота загрузки —
различие зафиксировано в javadoc.

Co-Authored-By: Claude Fable 5 <[email protected]>
По ревью CodeRabbit в #4064: registerMemberOverride мутирует memberSources,
но не бампал membersEpoch — override, зарегистрированный после первого
чтения типа, не попадал в мемоизированный getMembers до следующей
инвалидации. Баг существовал и до миграции на FileType.

Co-Authored-By: Claude Fable 5 <[email protected]>
По ревью #4064: runtime-реестр имён глобальных свойств — такие же
per-language данные, как и снапшот загрузки; параллельная мапа рядом
с byFileType не нужна. Реестр стал компонентом записи (создаётся пустым
конструктором-от-снапшота, заполняется registerGlobalProperty в течение
жизни workspace). Запись Loaded переименована в LanguageData — она
больше не чистый снапшот загрузки.

Co-Authored-By: Claude Fable 5 <[email protected]>

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistry.java (2)

556-557: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Keep derived members scoped to the caller's FileType.

These paths still call getMembers(genericRef) without fileType, and that overload explicitly disables scoping. Once a generic template has different BSL/OS member sources, specialization and member expansion merge them back together, so derived types can leak wrong-language members into hover/completion again.

Proposed fix
   public void registerSpecialization(TypeRef specializedRef, TypeRef genericRef,
                                      Map<String, String> bindings, FileType fileType) {
@@
     registerSpecializedDisplayName(specializedRef, genericRef, safeBindings);
     MemberSource source = () -> {
-      var raw = getMembers(genericRef);
+      var raw = getMembers(genericRef, fileType);
       if (raw.isEmpty()) {
         return List.of();
       }
@@
   private List<MemberDescriptor> expandGenericMembers(TypeRef genericRef,
+                                                      FileType fileType,
                                                       Map<String, String> typeBindings,
                                                       Map<String, List<String>> memberExpansions) {
-    var raw = getMembers(genericRef);
+    var raw = getMembers(genericRef, fileType);
     if (raw.isEmpty()) {
       return List.of();
     }
     MemberSource source = () -> {
-      var materialized = expandGenericMembers(genericRef, safeTypeBindings, safeExpansions);
+      var materialized = expandGenericMembers(genericRef, fileType, safeTypeBindings, safeExpansions);
       // Индексируем как делает registerSpecialization: read-only/версионные
       // members проверяются через memberMetadataIndex.
       for (var member : materialized) {

Also applies to: 663-666

🤖 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/registry/TypeRegistry.java`
around lines 556 - 557, The MemberSource lambda currently calls
getMembers(genericRef) which uses the unscoped overload and thus can pull
members from the wrong language; update the MemberSource implementations to call
the file-scoped overload getMembers(genericRef, fileType) so derived/specialized
types inherit members limited to the caller's FileType; apply the same change to
the other occurrence(s) around the MemberSource creation (the similar block at
the later occurrence referenced in the review) to ensure derived members never
leak wrong-language members into hover/completion.

500-513: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Preserve additive visibility on repeated specialization registration.

Line 511 only records fileType when the specialized ref is created. If the same specialized name is later registered for the other language, resolve(name, otherFileType) still filters it out because visibleTypes was never updated for that second registration.

Proposed fix
     if (existing == null) {
       // Регистрируем как полноценный тип того же kind, что и generic, чтобы
       // инференсер (резолвящий типы по имени через aliasIndex / по паре
       // (kind, name)) находил тот же TypeRef и member-source'ы доходили
       // до getMembers.
       types.put(specializedRef, hydrate(specializedRef));
       addAlias(specializedName, specializedRef);
-      registerFileType(specializedRef, fileType);
     }
+    registerFileType(specializedRef, fileType);
     registerSpecialization(specializedRef, genericRef, bindings, fileType);
     return specializedRef;
🤖 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/registry/TypeRegistry.java`
around lines 500 - 513, The code only calls registerFileType(specializedRef,
fileType) when the specialized TypeRef is newly created, so repeated
registrations from another fileType miss updating visibleTypes; change the flow
so that registerFileType(specializedRef, fileType) is invoked for every
registration (whether existing != null or created), e.g., move or duplicate the
call so that after resolving/interning specializedRef you always call
registerFileType(specializedRef, fileType) before registerSpecialization(...),
keeping types.put/addAlias only for the new-creation branch and leaving resolve,
intern, types.put, addAlias and registerSpecialization behavior 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.

Outside diff comments:
In
`@src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistry.java`:
- Around line 556-557: The MemberSource lambda currently calls
getMembers(genericRef) which uses the unscoped overload and thus can pull
members from the wrong language; update the MemberSource implementations to call
the file-scoped overload getMembers(genericRef, fileType) so derived/specialized
types inherit members limited to the caller's FileType; apply the same change to
the other occurrence(s) around the MemberSource creation (the similar block at
the later occurrence referenced in the review) to ensure derived members never
leak wrong-language members into hover/completion.
- Around line 500-513: The code only calls registerFileType(specializedRef,
fileType) when the specialized TypeRef is newly created, so repeated
registrations from another fileType miss updating visibleTypes; change the flow
so that registerFileType(specializedRef, fileType) is invoked for every
registration (whether existing != null or created), e.g., move or duplicate the
call so that after resolving/interning specializedRef you always call
registerFileType(specializedRef, fileType) before registerSpecialization(...),
keeping types.put/addAlias only for the new-creation branch and leaving resolve,
intern, types.put, addAlias and registerSpecialization behavior unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 342e3f9d-4bad-4e3b-ae41-fc466f646554

📥 Commits

Reviewing files that changed from the base of the PR and between b5c4444 and e61bc03.

📒 Files selected for processing (3)
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/GlobalScopeProvider.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistry.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistryScopedSourcesTest.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/GlobalScopeProvider.java

nixel2007 and others added 3 commits June 12, 2026 17:14
По ревью #4064: symbolsByDescriptor нужен только для склейки ru/en-алиасов
одного дескриптора в один SyntheticSymbol (aliasesBySymbol/getEntries в
GlobalSymbolScope работают по identity). Межъязыковое переиспользование
символов для случайно идентичных по значению дескрипторов исключено по
построению: кэш создаётся заново на каждый язык.

Co-Authored-By: Claude Fable 5 <[email protected]>
…pe обязателен

По ревью #4064: memberSources, descriptions, typeDescriptionsBilingual,
constructors и constructorSources хранили списки Scoped-обёрток с полем
fileType — теперь это Map<FileType, Map<TypeRef, …>>, Scoped-records
удалены, фильтрация заменена прямым чтением разреза своего языка.

fileType стал обязательным: удалены overload'ы без языка (getMembers(ref),
getDescription(ref), getDescription(ref, Language), getConstructors(ref))
и null-ветки в resolve/getMembers; expandedMembers принимает FileType.
Конфигурационные потребители читают BSL-разрез, oscript-тесты — OS.

Co-Authored-By: Claude Fable 5 <[email protected]>
…верку видимости

По ревью #4064 («никакого legacy, FileType обязателен»):

- GlobalSymbolScope: удалены findSymbol/findEntry без языка; findSymbol,
  getNames, getEntries, streamSymbols требуют FileType;
- GlobalScopeProvider: удалены getGlobalContexts()/getGlobalContextNames()
  без языка; per-fileType варианты читают разрез напрямую;
- findGlobal(name, fileType) упрощён до findEntry разреза: после
  per-language entries категория-проверки видимости (globalContextNames,
  индекс variableNames, matchesGlobalScope, фильтр oScriptLibraryIndex
  вместе с polем и его cyclic-dependency-обходом) стали тавтологией —
  запись в разрезе существует ровно тогда, когда имя зарегистрировано
  для этого языка;
- LanguageData — снова чистый иммутабельный снапшот загрузки.

Co-Authored-By: Claude Fable 5 <[email protected]>

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistry.java (2)

942-949: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Clean up constructor registrations when a user type is removed.

unregisterUserType(...) drops types and memberSources, but any constructorSources already registered for the same interned TypeRef remain. Re-indexing a deleted/re-added .os class with the same name will then reuse stale suppliers and can duplicate or surface outdated constructor signatures.

Suggested fix
   public void unregisterUserType(String qualifiedName) {
     var ref = intern(TypeKind.USER, qualifiedName);
     types.remove(ref);
     memberSources.values().forEach(byRef -> byRef.remove(ref));
+    constructors.values().forEach(byRef -> byRef.remove(ref));
+    constructorSources.values().forEach(byRef -> byRef.remove(ref));
     membersEpoch.incrementAndGet();
     visibleTypes.values().forEach(typed -> typed.remove(ref));
     aliasIndex.remove(qualifiedName.toLowerCase(Locale.ROOT));
   }
🤖 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/registry/TypeRegistry.java`
around lines 942 - 949, unregisterUserType currently removes the type from
types, memberSources and visibleTypes but leaves any entries in
constructorSources, causing stale constructor suppliers to be reused; update
unregisterUserType to also remove the interned TypeRef (ref) from
constructorSources (and any nested collections / maps that store constructors)
and bump the constructors epoch/counter if one exists (e.g., constructorsEpoch)
so re-indexing a deleted/re-added user type cannot reuse stale constructor
suppliers or duplicate signatures.

467-480: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Register FileType visibility even when the specialization already exists.

If specializedName was first created from the other language pass, this path reuses the existing TypeRef but skips registerFileType(...). The new member source is added for fileType, yet resolve(name, fileType) still filters that type out via isVisibleIn(...), so shared BSL/OS specializations stay unreachable in the second language.

Suggested fix
     if (existing == null) {
       // Регистрируем как полноценный тип того же kind, что и generic, чтобы
       // инференсер (резолвящий типы по имени через aliasIndex / по паре
       // (kind, name)) находил тот же TypeRef и member-source'ы доходили
       // до getMembers.
       types.put(specializedRef, hydrate(specializedRef));
       addAlias(specializedName, specializedRef);
-      registerFileType(specializedRef, fileType);
     }
+    registerFileType(specializedRef, fileType);
     registerSpecialization(specializedRef, genericRef, bindings, fileType);
🤖 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/registry/TypeRegistry.java`
around lines 467 - 480, The code currently skips
registerFileType(specializedRef, fileType) when an existing TypeRef is reused,
causing visibility filtering to hide cross-language specializations; always
register the file visibility for the specialized TypeRef (call
registerFileType(specializedRef, fileType)) even when resolve(specializedName)
returns an existing entry. Concretely, ensure registerFileType is invoked for
specializedRef regardless of the existing==null branch (i.e., move or add
registerFileType(specializedRef, fileType) so it runs before
registerSpecialization), keeping the rest of the existing/intern, types.put,
addAlias, hydrate, and registerSpecialization logic 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.

Outside diff comments:
In
`@src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistry.java`:
- Around line 942-949: unregisterUserType currently removes the type from types,
memberSources and visibleTypes but leaves any entries in constructorSources,
causing stale constructor suppliers to be reused; update unregisterUserType to
also remove the interned TypeRef (ref) from constructorSources (and any nested
collections / maps that store constructors) and bump the constructors
epoch/counter if one exists (e.g., constructorsEpoch) so re-indexing a
deleted/re-added user type cannot reuse stale constructor suppliers or duplicate
signatures.
- Around line 467-480: The code currently skips registerFileType(specializedRef,
fileType) when an existing TypeRef is reused, causing visibility filtering to
hide cross-language specializations; always register the file visibility for the
specialized TypeRef (call registerFileType(specializedRef, fileType)) even when
resolve(specializedName) returns an existing entry. Concretely, ensure
registerFileType is invoked for specializedRef regardless of the existing==null
branch (i.e., move or add registerFileType(specializedRef, fileType) so it runs
before registerSpecialization), keeping the rest of the existing/intern,
types.put, addAlias, hydrate, and registerSpecialization logic unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 24ed88b7-0dfd-476a-9ad3-a325971cee0e

📥 Commits

Reviewing files that changed from the base of the PR and between e61bc03 and 9f4b2f3.

📒 Files selected for processing (26)
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/TypeService.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/ConfigurationGenericExpander.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/ConfigurationTypesProvider.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/GlobalScopeProvider.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/MetadataCollectionSpecializer.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistry.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/scope/GlobalSymbolScope.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/ConfigurationManagerChainInferenceTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/GlobalEnumPropertyInferenceTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/TypeServiceDelegationTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/ConventionalLibraryDiscoveryTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/OScriptLibraryIndexTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/ConfigurationModuleMembersProviderTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/ConfigurationTypesProviderTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/GlobalScopeProviderRegistrationTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/MetadataCollectionSpecializerTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/MetadataCollectionSpecializerUnitTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/MultiWorkspaceTypeRegistryTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/PlatformTypeDescriptionTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/RegisterCommonLibraryExpansionTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistryExpandedMembersTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistryRegistrationTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistryScopedDescriptionsTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistrySpecializationTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/scope/GlobalSymbolScopeTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/symbol/PlatformSymbolsTest.java
💤 Files with no reviewable changes (2)
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistryScopedDescriptionsTest.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/TypeService.java
🚧 Files skipped from review as they are similar to previous changes (13)
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/ConfigurationManagerChainInferenceTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/ConfigurationModuleMembersProviderTest.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/ConfigurationGenericExpander.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/GlobalEnumPropertyInferenceTest.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/MetadataCollectionSpecializer.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistryExpandedMembersTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistrySpecializationTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/MultiWorkspaceTypeRegistryTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/RegisterCommonLibraryExpansionTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/scope/GlobalSymbolScopeTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/GlobalScopeProviderRegistrationTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistryRegistrationTest.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/GlobalScopeProvider.java

Reliability (валили gate):
- S2583/S2589: мёртвые null-проверки удалены — ref в getMembers обязателен
  (как и fileType), Names.getName/getAlias из bsl-context non-null;
- S6411: ключи кэшей — Comparable: кэш символов функций по canonical-имени
  (String) вместо MemberDescriptor, дедуп записей разреза в GlobalSymbolScope
  через symbolKey вместо IdentityHashMap.

Maintainability:
- buildBslFromContext (CC 89) разрезан на addContextProperty/Enum/Keyword,
  keywordDescriptionOf, byParentDescriptions, putByNameAndAlias;
- registerPack (CC 20) — на registerPackAliases/Descriptions/Callables/
  CollectionTraits;
- SignatureDescriptor импортирован вместо FQN в типах полей (S103),
  perFileType() перенесён из середины блока полей (S1213), неиспользуемые
  импорты удалены (S1128), лямбда → method reference (S1612).

Co-Authored-By: Claude Fable 5 <[email protected]>

@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/registry/GlobalScopeProvider.java (2)

591-604: 💤 Low value

Stale Javadoc reference to removed method.

The Javadoc at line 593 references {@link #findGlobal(String)}, but that overload was removed. The correct method is findGlobal(String, FileType).

📝 Proposed fix
   /**
    * Зарегистрировать synthetic-symbol для библиотечного модуля OneScript
    * (записи {`@code` <module>} из {`@code` lib.config}). Symbol становится
-   * видимым через {`@link` `#findGlobal`(String)} с фильтрацией по {`@link` FileType}
+   * видимым через {`@link` `#findGlobal`(String, FileType)}
    * (через {`@link` com.github._1c_syntax.bsl.languageserver.types.oscript.OScriptLibraryIndex}).
🤖 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/registry/GlobalScopeProvider.java`
around lines 591 - 604, Update the stale Javadoc in GlobalScopeProvider for
registerLibraryModule: change the {`@link` `#findGlobal`(String)} reference to the
correct overload {`@link` `#findGlobal`(String, FileType)} and ensure any
surrounding text about filtering by FileType remains accurate; verify the tag
resolves to the findGlobal(String, FileType) method and adjust the Javadoc
import/fully-qualified mention if necessary so IDE/javadoc links are correct.

276-281: 💤 Low value

Redundant double-lookup in findGlobalEntry.

findGlobal already calls globalSymbolScope.findEntry(name, fileType) internally. Then findGlobalEntry calls findEntry again if the result is non-empty, performing the same lookup twice.

♻️ Proposed simplification
 public Optional<GlobalSymbolScope.Entry> findGlobalEntry(String name, FileType fileType) {
-  if (findGlobal(name, fileType).isEmpty()) {
-    return Optional.empty();
-  }
+  ensureGlobalsPublished();
   return globalSymbolScope.findEntry(name, fileType);
 }
🤖 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/registry/GlobalScopeProvider.java`
around lines 276 - 281, The method findGlobalEntry performs a redundant double
lookup by calling findGlobal(name, fileType) and then calling
globalSymbolScope.findEntry(name, fileType) again; replace the method body to
directly return the result of findGlobal(name, fileType) (i.e., return
findGlobal(name, fileType);) to avoid the duplicate lookup and keep logic
centralized in findGlobal while referencing findGlobalEntry and
globalSymbolScope.findEntry for locating the code.
🤖 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/registry/GlobalScopeProvider.java`:
- Around line 591-604: Update the stale Javadoc in GlobalScopeProvider for
registerLibraryModule: change the {`@link` `#findGlobal`(String)} reference to the
correct overload {`@link` `#findGlobal`(String, FileType)} and ensure any
surrounding text about filtering by FileType remains accurate; verify the tag
resolves to the findGlobal(String, FileType) method and adjust the Javadoc
import/fully-qualified mention if necessary so IDE/javadoc links are correct.
- Around line 276-281: The method findGlobalEntry performs a redundant double
lookup by calling findGlobal(name, fileType) and then calling
globalSymbolScope.findEntry(name, fileType) again; replace the method body to
directly return the result of findGlobal(name, fileType) (i.e., return
findGlobal(name, fileType);) to avoid the duplicate lookup and keep logic
centralized in findGlobal while referencing findGlobalEntry and
globalSymbolScope.findEntry for locating the code.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: fc9eef2f-a964-49c3-8c6f-053481f76036

📥 Commits

Reviewing files that changed from the base of the PR and between 9f4b2f3 and 8c65597.

📒 Files selected for processing (8)
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/GlobalScopeProvider.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistry.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/scope/GlobalSymbolScope.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/GlobalScopeProviderRegistrationTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/GlobalScopeProviderResourceTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/KeywordMetadataBuilderTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/KeywordMetadataLoaderTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistryRegistrationTest.java
💤 Files with no reviewable changes (3)
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/KeywordMetadataLoaderTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/GlobalScopeProviderResourceTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/KeywordMetadataBuilderTest.java
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/scope/GlobalSymbolScope.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/GlobalScopeProviderRegistrationTest.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistry.java

nixel2007 and others added 3 commits June 12, 2026 20:15
…olve

По ревью #4064: единственный боевой потребитель проверки видимости —
resolve(name, fileType); метод стал private, тесты переведены на resolve,
семантика «неизвестный тип видим везде» проверяется через alias без
языковой регистрации.

Co-Authored-By: Claude Fable 5 <[email protected]>
Merge develop принёс новый MCP-инструмент TypeInfoTool, написанный под
удалённый overload getDescription(ref, Language) — CI Analyse падал на
merge-ref компиляцией. У инструмента уже есть параметр fileType —
он и передаётся.

Co-Authored-By: Claude Fable 5 <[email protected]>

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistry.java (1)

513-537: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Register specialized refs in visibleTypes on every specialization call.

This overload adds a fileType-scoped member source, but it never calls registerFileType(specializedRef, fileType). If the same specialization is reused in a second language, resolve(name, secondFileType) still filters it out via isVisibleIn, so lookup-driven features keep missing it even though the members were registered for that fileType. A single registerFileType(specializedRef, fileType) here fixes both overload paths.

Suggested fix
 public void registerSpecialization(TypeRef specializedRef, TypeRef genericRef,
                                    Map<String, String> bindings, FileType fileType) {
   if (specializedRef == null || genericRef == null) {
     return;
   }
+  registerFileType(specializedRef, fileType);
   var safeBindings = Map.copyOf(bindings);
   registerSpecializedDisplayName(specializedRef, genericRef, safeBindings);
   MemberSource source = () -> {
🤖 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/registry/TypeRegistry.java`
around lines 513 - 537, The registerSpecialization(TypeRef specializedRef,
TypeRef genericRef, Map<String,String> bindings, FileType fileType) method
registers a fileType-scoped member source but never marks the specializedRef as
visible for that file type; call registerFileType(specializedRef, fileType) (the
same visibility registration used by the other overload) before or after
registerMemberSource so isVisibleIn checks will include this specializedRef
during resolve(name, fileType) lookups and avoid missing members; update the
method to invoke registerFileType for specializedRef and fileType.
🧹 Nitpick comments (1)
src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistry.java (1)

429-431: ⚡ Quick win

Update the JavaDoc links to the new FileType-aware overloads.

These comments still reference removed getMembers(TypeRef) / getConstructors(TypeRef) entry points, so the docs now point at nonexistent APIs and obscure the new mandatory fileType parameter.

As per coding guidelines, "Write JavaDoc for public APIs, include comments for complex logic, and keep documentation up to date with code changes."

Also applies to: 491-492, 899-902

🤖 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/registry/TypeRegistry.java`
around lines 429 - 431, Update the Javadoc links that reference the removed
overloads (e.g., getMembers(TypeRef) and getConstructors(TypeRef)) to point to
the new FileType-aware overloads (e.g., getMembers(TypeRef, FileType) and
getConstructors(TypeRef, FileType}); update any text that implies the old
no-fileType API (for example in the docs for registerMemberSource) to mention
the mandatory fileType parameter and its purpose (override returnType behavior),
and apply the same fix to the other affected blocks around registerMemberSource
and the lines noted (491-492, 899-902) so all public API docs correctly
reference the new signatures.

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.

Outside diff comments:
In
`@src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistry.java`:
- Around line 513-537: The registerSpecialization(TypeRef specializedRef,
TypeRef genericRef, Map<String,String> bindings, FileType fileType) method
registers a fileType-scoped member source but never marks the specializedRef as
visible for that file type; call registerFileType(specializedRef, fileType) (the
same visibility registration used by the other overload) before or after
registerMemberSource so isVisibleIn checks will include this specializedRef
during resolve(name, fileType) lookups and avoid missing members; update the
method to invoke registerFileType for specializedRef and fileType.

---

Nitpick comments:
In
`@src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistry.java`:
- Around line 429-431: Update the Javadoc links that reference the removed
overloads (e.g., getMembers(TypeRef) and getConstructors(TypeRef)) to point to
the new FileType-aware overloads (e.g., getMembers(TypeRef, FileType) and
getConstructors(TypeRef, FileType}); update any text that implies the old
no-fileType API (for example in the docs for registerMemberSource) to mention
the mandatory fileType parameter and its purpose (override returnType behavior),
and apply the same fix to the other affected blocks around registerMemberSource
and the lines noted (491-492, 899-902) so all public API docs correctly
reference the new signatures.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 38bc057e-d825-41e7-af72-1b55aa9ba9ed

📥 Commits

Reviewing files that changed from the base of the PR and between 8c65597 and 684711d.

📒 Files selected for processing (4)
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/mcp/tools/TypeInfoTool.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/providers/CompletionProvider.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistry.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistryRegistrationTest.java
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/providers/CompletionProvider.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistryRegistrationTest.java

@nixel2007
nixel2007 merged commit 40faee7 into develop Jun 12, 2026
19 checks passed
@nixel2007
nixel2007 deleted the fix/issue-4054 branch June 12, 2026 18:33
@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.

[BUG] В ховере и информации о символах в os-файле показывается информация от BSL-символа

1 participant