Skip to content

refactor(types): глобальная область видимости — члены синтетического типа ГлобальныйКонтекст#4135

Merged
nixel2007 merged 39 commits into
developfrom
fix/typeregistry-implicit-bootstrap
Jun 18, 2026
Merged

refactor(types): глобальная область видимости — члены синтетического типа ГлобальныйКонтекст#4135
nixel2007 merged 39 commits into
developfrom
fix/typeregistry-implicit-bootstrap

Conversation

@nixel2007

@nixel2007 nixel2007 commented Jun 16, 2026

Copy link
Copy Markdown
Member

Проблема (issue #3994)

TypeRegistry (@WorkspaceScope) в @PostConstruct bootstrap() push-моделью наполнял другой бин — GlobalScopeProvider (платформенные классы для Новый, системные перечисления, глобальные свойства/функции). Потребители читали из GlobalScopeProvider, но его чтение не материализовало TypeRegistry → в свежем workspace-scope первый запрос видел пустой скоуп. Костыль: потребители дёргали typeRegistry.resolve("") ради побочного эффекта bootstrap.

Решение: глобальная область = члены синтетического типа

Глобальная область видимости моделируется как члены синтетического типа ГлобальныйКонтекст в TypeRegistry. Знание «эта сущность видна без префикса» — метаданные источника (bsl-context / встроенный JSON / конфигурация), а не флаг на конкретном типе.

  • Поставщики членов глобального контекста читают источник и регистрируют члены GLOBAL_CONTEXT штатным TypeDecl/registerMemberSource:
    • GlobalContextTypesProvider (BSL) и GlobalContextOScriptTypesProvider (OS) — глобальные функции (методы-члены), свойства, системные перечисления (свойства-члены с valueType = сам тип);
    • ConfigurationTypesProvider — коллекции-namespace (Справочники, Перечисления…);
    • ConfigurationModuleMembersProvider / OScriptModuleMembersProvider — общие/library-модули.
  • TypeRegistry не эмитит ничего в глобальную область — он лишь хранит тип с именем ГлобальныйКонтекст. Цикл TypeRegistry ↔ GlobalScopeProvider разорван (направление только GlobalScopeProvider → TypeRegistry, read).
  • Костыль exposedAsGlobal снят с TypeDecl — признак читается из источника при сборке GLOBAL_CONTEXT. Удалены registerAsGlobalProperty/registerAsPlatformClass и мёртвый global-symbol API GlobalScopeProvider.

Доступ к глобальной области — отдельная абстракция

TypeRegistry — хранилище типов; резолв глобальных функций/свойств — не его ответственность. API живёт в GlobalScopeProvider:

  • globalMember(name, ft), типизированные globalFunction(...) / globalProperty(...) (вместо россыпи globalMember().filter(kind==…) у потребителей), плюс перечисление globalProperties(ft)/globalFunctions(ft);
  • делегирует в typeRegistry.getMembers(GLOBAL_CONTEXT), эпоха-кэш через TypeRegistry.membersEpoch();
  • TypeRegistry.globalMember() удалён. Константа GLOBAL_CONTEXTpackage-private в TypeRegistry; доступ потребителей только через геттеры GlobalScopeProvider.

Сохранённые инварианты

  • Семантическая раскраска различает глобальное свойство и системное перечисление — из valueType члена (isEnumType), а не из отдельного флага; собственные реквизиты/методы конфигурации не красятся как defaultLibrary.
  • Имена типов для Новый (Массив, Структура) — отдельная ось (проекция «типы с конструктором»), не члены контекста.
  • Ключевые слова — лексика, вне TypeRegistry.

Исправленный баг шадоуинга коллекций

Платформенный глобальный контекст (bsl-context) сам отдаёт свойства-менеджеры коллекций (Справочники → СправочникиМенеджер, Перечисления → ПеречисленияМенеджер). Они регистрировались на bootstrap'е раньше одноимённых коллекций конфигурации; computeMembers берёт первый источник (putIfAbsent), и платформенное свойство без MD-объектов затеняло конфигурационную коллекцию → Справочники.<Каталог> / Перечисления.<Перечисление> не резолвились (видно только с платформой/HBK, поэтому CI/юнит-тесты не ловили). Фикс: коллекции конфигурации регистрируются как registerMemberOverride (в начало списка) — конфигурация выигрывает (суперсет: наследует методы менеджера + MD-объекты).

Сопутствующая чистка реестра типов

  • Единый фасад. Семь потребителей тянули одновременно TypeRegistry и TypeService, хотя лезли в реестр за мелочами. В TypeService добавлены делегаты (isEnumType, isVersionedMemberName, hasAnyReadOnlyMember, supportsForEach, supportsIndexAccess, getForEachDescription, getIndexAccessDescription); потребители (CompletionProvider, SignatureHelpProvider, ConstructorHoverBuilder, CollectionHoverHints, AssignToReadOnlyPropertyDiagnostic, PlatformMemberCalls + Unavailable/DeprecatedMemberCall) больше не зависят от TypeRegistry. Мёртвое поле в SignatureHelpProvider удалено.
  • Интернер. Самописная Map<TypeRef,TypeRef> заменена на GenericInterner<TypeRef> из utils.
  • Баг: признаки коллекций/перечислений не были разрезаны по языку. enumTypes, supportsForEach, supportsIndexAccess и их описания сидели на голом TypeRef без разреза по fileType (а члены и описания типа уже per-fileType). Одно и то же имя в BSL и OneScript — разные типы с разной природой, поэтому признак одного языка протекал в другой. Хранение переведено на Map<FileType, …>, в геттеры добавлен параметр fileType. Идентичность TypeRef осталась языко-независимой; всё языко-зависимое наполнение типа теперь консистентно per-fileType.

Тесты

  • GlobalContextCollectionShadowingTest — воспроизводит шадоуинг без платформы (red→green).
  • TypeRegistryCollectionTraitsPerLanguageTest — признаки коллекций/перечислений, заявленные для BSL, не видны в OS (red→green).
  • GlobalContextMembersTest, GlobalContextTypesProviderTest (bsl-context-путь через синтетический PlatformContextProvider), CompletionCommonModuleMembersTest (члены общего модуля), миграция читателей на GlobalScopeProvider и фасад TypeService.

Refs #3994

@coderabbitai

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

TypeRegistry adds GLOBAL_CONTEXT constant, ensureInitialized() entry point, enum tracking, and globalMember() lookup with epoch-bound caching. GlobalScopeProvider implements lazy bootstrap via ObjectProvider and CAS-guarded ensureBootstrapped() called at read entry points, plus JSON fallback member loading. GlobalContextTypesProvider synthesizes the type from optional BslContextHolder or built-in platform declarations. OScriptModuleMembersProvider, ConfigurationModuleMembersProvider, and ConfigurationTypesProvider register dynamic GLOBAL_CONTEXT member sources. Bootstrap triggers consolidate to TypeService.expressionTypesAt(), and CompareWithBooleanDiagnostic removes its TypeRegistry dependency. Five consumer providers (signature help, semantic tokens, type inference) migrate to TypeRegistry.globalMember() for global-member resolution. Integration tests validate auto-materialization and context membership.

Changes

TypeRegistry Bootstrap and Global Context Type

Layer / File(s) Summary
TypeRegistry core: GLOBAL_CONTEXT type and bootstrap contract
src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistry.java
Adds GLOBAL_CONTEXT constant, ensureInitialized() no-op method, isEnumType() read projection, and globalMember() lookup with epoch-bound index caching. Populates enum set during pack registration.
GlobalScopeProvider lazy bootstrap via ObjectProvider
src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/GlobalScopeProvider.java
Injects optional TypeRegistry via ObjectProvider, adds CAS-guarded bootstrapped flag, and ensureBootstrapped() called at start of findGlobal() and getGlobalContexts(). Adds globalContextMembers() JSON fallback loader for method/property descriptors.
Global context synthetic type provider
src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/GlobalContextTypesProvider.java
New component builds GLOBAL_CONTEXT type from optional BslContextHolder or JSON fallback (built-in platform declarations marked exposedAsGlobal, excluding generics). Exposes context members/enums as properties; returns empty when no members exist.
Platform modules/collections exposed as global context members
src/main/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/OScriptModuleMembersProvider.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
Each provider tracks platform entities (library modules, common modules, collections) in concurrent maps and registers a single guarded GLOBAL_CONTEXT member source that dynamically rebuilds members from current state on each epoch invalidation.
Bootstrap trigger consolidation and TypeRegistry cleanup
src/main/java/com/github/_1c_syntax/bsl/languageserver/types/TypeService.java, src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/CompareWithBooleanDiagnostic.java
TypeService.expressionTypesAt() centralizes single resolve("") call; resolveBareName() removes per-name call and switches to globalMember() filtering by MemberKind. CompareWithBooleanDiagnostic removes TypeRegistry field, import, and resolve("") call.
Bootstrap and global context integration tests
src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/GlobalScopeProviderBootstrapTest.java, src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/GlobalContextMembersTest.java, src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/ConfigurationModuleMembersProviderTest.java
Tests verify auto-materialization of TypeRegistry on first global read, presence of exposedAsGlobal enums and functions in GLOBAL_CONTEXT, correct member kind classification, enum-type detection, and registration of common modules as properties.
Global-member consumer migration to TypeRegistry
src/main/java/com/github/_1c_syntax/bsl/languageserver/providers/SignatureHelpProvider.java, src/main/java/com/github/_1c_syntax/bsl/languageserver/semantictokens/PlatformGlobalMethodSemanticTokensSupplier.java, src/main/java/com/github/_1c_syntax/bsl/languageserver/semantictokens/PlatformMemberPropertyAccessSemanticTokensSupplier.java, src/main/java/com/github/_1c_syntax/bsl/languageserver/semantictokens/GlobalScopeSemanticTokensSupplier.java, src/main/java/com/github/_1c_syntax/bsl/languageserver/types/inferencer/ExpressionTypeInferencer.java
Five consumer providers switch from GlobalScopeProvider to TypeRegistry.globalMember() for global-method/property resolution. Each filters by MemberKind (METHOD or PROPERTY), returns types, and classifies result types (enum, module namespace, or class). Semantic suppliers remove synthetic-kind checks and derive token types from inferred value types.

Sequence Diagram(s)

sequenceDiagram
  participant Client as Caller
  participant Provider as Consumer<br/>(e.g., SignatureHelp,<br/>SemanticTokens,<br/>TypeInference)
  participant TypeRegistry
  participant GlobalScopeProvider
  participant GlobalContext as GLOBAL_CONTEXT<br/>Member Source

  Client->>Provider: Query global member
  Provider->>TypeRegistry: globalMember(name, fileType)
  alt first access or epoch invalidated
    TypeRegistry->>TypeRegistry: Build GlobalIndex
    TypeRegistry->>GlobalContext: Fetch GLOBAL_CONTEXT members
    GlobalContext->>GlobalScopeProvider: ensureBootstrapped() [CAS]
    alt first bootstrap
      GlobalScopeProvider->>TypeRegistry: ensureInitialized()
      Note over TypeRegistry: `@PostConstruct` bootstrap() runs
    end
    GlobalContext-->>TypeRegistry: Members populated
    TypeRegistry->>TypeRegistry: Cache index in AtomicReference
  end
  TypeRegistry-->>Provider: Optional<MemberDescriptor>
  Provider->>Provider: Filter by MemberKind
  Provider-->>Client: Resolved type/token/signature
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related issues

Possibly related PRs

  • 1c-syntax/bsl-language-server#3952: Both PRs modify semantic-token suppliers' global-method handling (e.g., PlatformGlobalMethodSemanticTokensSupplier) with overlapping code paths for async-aware modifier selection and global-member resolution.
  • 1c-syntax/bsl-language-server#3993: Direct overlap on TypeService's positional/type inference flow, especially expressionTypesAt() and global-member resolution around TypeRegistry and member/type APIs.
  • 1c-syntax/bsl-language-server#4064: Both modify TypeService.resolveBareName() to make description/type resolution file-type aware using typeRegistry.getDescription(ref, fileType).

Poem

🐇 Bootstrap lazy, no more side effects to chase,
The registry now materializes in its own space!
A CAS guard keeps that first call tight,
Global context blooms—modules, enums in sight,
Platform members flow as properties, oh delight,
Type definitions complete, the system takes flight! 🌿

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 35.29% 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
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.
Title check ✅ Passed The title accurately summarizes the main architectural change: refactoring global scope visibility to use members of a synthetic GlobalContext type, which is the core focus of this substantial type system refactor.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ 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 fix/typeregistry-implicit-bootstrap

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.

Actionable comments posted: 1

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

Inline comments:
In
`@src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/GlobalScopeProvider.java`:
- Around line 283-304: The bootstrapped flag is being set to true before the
actual initialization occurs, creating a race condition where concurrent threads
can skip the bootstrap step thinking it's already complete. In the
ensureBootstrapped method, move the compareAndSet call to after the
ensureInitialized() call completes, so the flag only gets set once
initialization actually finishes. This ensures other threads waiting to
bootstrap will not proceed until the initialization is genuinely complete.
🪄 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: d324bf7d-9fa3-488a-8a45-e0e99c2824b6

📥 Commits

Reviewing files that changed from the base of the PR and between 3dd3a91 and 2c70d42.

📒 Files selected for processing (5)
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/CompareWithBooleanDiagnostic.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/TypeService.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/TypeRegistry.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/GlobalScopeProviderBootstrapTest.java
💤 Files with no reviewable changes (2)
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/TypeService.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/CompareWithBooleanDiagnostic.java

@github-actions

github-actions Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Test Results

 3 474 files  +  6   3 474 suites  +6   1h 43m 50s ⏱️ + 8m 14s
 3 409 tests  -  73   3 391 ✅  -  73   18 💤 ±0  0 ❌ ±0 
20 454 runs   - 438  20 342 ✅  - 438  112 💤 ±0  0 ❌ ±0 

Results for commit a199f6c. ± Comparison against base commit 6c985d8.

This pull request removes 86 and adds 13 tests. Note that renamed tests count towards both.
com.github._1c_syntax.bsl.languageserver.hover.CollectionHoverHintsTest ‑ appendIsNoOpForNullArgs()
com.github._1c_syntax.bsl.languageserver.hover.SyntheticSymbolMarkupContentBuilderTest ‑ getContentForGlobalPropertyIncludesNameRoleAndDescription()
com.github._1c_syntax.bsl.languageserver.hover.SyntheticSymbolMarkupContentBuilderTest ‑ getContentForLibraryModuleShowsRoleAndName()
com.github._1c_syntax.bsl.languageserver.hover.SyntheticSymbolMarkupContentBuilderTest ‑ getContentForTypeNameMarksAsTypeName()
com.github._1c_syntax.bsl.languageserver.hover.SyntheticSymbolMarkupContentBuilderTest ‑ getContentOmitsEmptyDescription()
com.github._1c_syntax.bsl.languageserver.hover.SyntheticSymbolMarkupContentBuilderTest ‑ getContentSkipsValueTypeWhenUnknown()
com.github._1c_syntax.bsl.languageserver.hover.SyntheticSymbolMarkupContentBuilderTest ‑ getSymbolClassReturnsSyntheticSymbol()
com.github._1c_syntax.bsl.languageserver.types.TypeServiceDelegationTest ‑ findTypesByReferenceForSyntheticSymbolUsesValueType()
com.github._1c_syntax.bsl.languageserver.types.TypeServiceDelegationTest ‑ findTypesByReferenceWithUnknownSyntheticValueReturnsEmpty()
com.github._1c_syntax.bsl.languageserver.types.registry.BslContextPlatformTypesProviderTest ‑ exposedAsGlobalHeuristicTriggersOnGenericProperty()
…
com.github._1c_syntax.bsl.languageserver.aop.sentry.SentryScopeConfigurerOptionsTest ‑ resolvesFeatureEnvironmentWhenServerVersionIsNull()
com.github._1c_syntax.bsl.languageserver.providers.CompletionCommonModuleMembersTest ‑ completionAfterCommonModuleDotOffersExportedMethods()
com.github._1c_syntax.bsl.languageserver.providers.DiagnosticProviderTest ‑ testServerContextPopulatedClearsCachedDiagnosticsForPullClient()
com.github._1c_syntax.bsl.languageserver.types.registry.ConfigurationModuleMembersProviderTest ‑ registersCommonModuleAsGlobalContextMember()
com.github._1c_syntax.bsl.languageserver.types.registry.GlobalContextCollectionShadowingTest ‑ configurationCollectionWinsOverPlatformGlobalProperty()
com.github._1c_syntax.bsl.languageserver.types.registry.GlobalContextMembersTest ‑ exposedGlobalEnumBecomesPropertyMemberOfGlobalContext()
com.github._1c_syntax.bsl.languageserver.types.registry.GlobalContextMembersTest ‑ globalFunctionBecomesMethodMemberOfGlobalContext()
com.github._1c_syntax.bsl.languageserver.types.registry.GlobalContextMembersTest ‑ globalMemberResolvesAndProjectionsClassify()
com.github._1c_syntax.bsl.languageserver.types.registry.GlobalContextMembersTest ‑ oscriptGlobalFunctionResolvesForOsFileType()
com.github._1c_syntax.bsl.languageserver.types.registry.GlobalContextTypesProviderTest ‑ globalContextMethodsPropertiesAndEnumsBecomeMembers()
…

♻️ This comment has been updated with latest results.

* не инжектится и остаётся {@code null} — bootstrap там не нужен.
*/
@Autowired(required = false)
private @Nullable ObjectProvider<TypeRegistry> typeRegistryProvider;

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.

final

@nixel2007

Copy link
Copy Markdown
Member Author

Развязка связей: кто/зачем/откуда пишет и читает, и как порвать цикл по-настоящему

Согласен, что текущий PR — это перенос «магии» из потребителей в GlobalScopeProvider, а не развязка. Ниже полная карта потоков данных (всё проверено по коду, с file:line) и предложение убрать цикл целиком, без ObjectProvider/ensureInitialized/resolve("").

1. Слои хранения

Три workspace-scoped бина:

Бин Роль
GlobalSymbolScope (types/scope/GlobalSymbolScope.java) сам стор глобальных символов (entries/displayNames/aliasesBySymbol). Лист графа: ни от кого не зависит, единственный внешний пользователь — GlobalScopeProvider (никто больше его инстанс не трогает).
GlobalScopeProvider (GSP) фасад над GlobalSymbolScope + собственный снапшот byFileType (функции/keyword'ы/переменные/перечисления), загружаемый в конструкторе из bsl-context/JSON.
TypeRegistry центральный стор типов (члены, конструкторы, алиасы, описания).

2. Граф зависимостей (конструкторные рёбра)

TypeRegistry ──▶ GlobalScopeProvider ──▶ GlobalSymbolScope
     ▲                   ┊
     └┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┘  ObjectProvider<TypeRegistry> (этот PR — cycle-breaker)
  • TypeRegistry → GlobalScopeProvider — жёсткое ребро (TypeRegistry.java:87), нужно, чтобы пушить платформенный глобальный скоуп во время bootstrap.
  • GlobalScopeProvider ┄▶ TypeRegistry — ленивое ребро, добавлено этим PR, только чтобы дёрнуть @PostConstruct bootstrap() при первом чтении.

То есть цикл целиком существует ради одной вещи: наполнение глобального скоупа — побочный эффект @PostConstruct TypeRegistry, а чтение GlobalScopeProvider его не триггерит.

3. Писатели

Bootstrap-time (платформа, статично, без конфигурации) — единственная точка: TypeRegistry.bootstrap() (TypeRegistry.java:196) пул-итерирует List<PlatformTypesProvider> (Builtin*/BslContext*) и на каждый TypeDecl в registerPackCallables (:1010) пушит в GSP:

  • registerAsPlatformClass (:1013, когда есть constructors) → имя класса для Новый как Role.TYPE_NAME;
  • registerAsGlobalProperty (:1023, когда exposedAsGlobal) → системные перечисления/глобальные свойства как Role.VALUE.

Indexing-time (конфигурация/oscript) — пишут в оба бина по событиям индексации:

  • ConfigurationTypesProvider — MD-типы, registerAsGlobalProperty для коллекций (:331), registerConfigurationQualifiedName (:302,308);
  • ConfigurationModuleMembersProvider — общие модули: registerAsGlobalProperty (:161) + indexModuleType (:127,150);
  • OScriptModuleMembersProviderregisterLibraryModule/registerLibraryClass/indexModuleType напрямую в GSP (:137,143,144), registerUserType в TypeRegistry.

Важно: писатели конфигурации/oscript опираются на состояние TypeRegistry (алиасы из aliasIndex, описание из getDescription) — для них TypeRegistry.registerAsGlobalProperty это настоящее переиспользование, не побочный эффект.

4. Читатели GSP (по фичам)

Фича Метод GSP Нужен ли bootstrap?
Инференс (ExpressionTypeInferencer:158/258/514) moduleTypeByUri, findGlobalEntry, findFunction findGlobalEntry — да; но инференсер и так зовёт TypeRegistry напрямую (getMembers/resolve/...)
TypeService (:286/375/380) moduleUriByType, findFunction, findGlobalEntry тоже зовёт TypeRegistry напрямую
Completion (CompletionProvider:199/547/576/594/617/658) findGlobal, getGlobalContexts, getClasses, getFunctions, getKeywords, getConfigurationQualifiedNames только getGlobalContexts/findGlobal (читают стор); getClasses/getKeywords/getFunctions читают byFileType (конструктор!)
Semantic tokens (GlobalScopeSemanticTokensSupplier:118, PlatformMemberPropertyAccessSemanticTokensSupplier:113, PlatformGlobalMethodSemanticTokensSupplier:84) findGlobalEntry, findFunction findGlobalEntry — да; findFunction — нет
Signature help (SignatureHelpProvider:413), hover keyword'ов (KeywordReferenceFinder:93) findFunction, findKeywordDescription нет (всё из byFileType)

Ключевой вывод: bootstrap реально нужен только читателям стора (findGlobalEntry/getGlobalContexts/findGlobal). И почти все тяжёлые из них (инференсер, TypeService, GlobalScopeSemanticTokensSupplier) уже инжектят и зовут TypeRegistry напрямую — bootstrap у них и так отрабатывает. «Только-через-GSP-и-нужен-bootstrap» остаются буквально CompletionProvider.getGlobalContexts/findGlobal и PlatformMemberPropertyAccessSemanticTokensSupplier.findGlobalEntry.

5. Инсайт для развязки

Наполнение платформенного глобального скоупа — чистая функция от platformProviders.getTypes(): TYPE_NAMEdecl.constructors() непуст, VALUEdecl.exposedAsGlobal(); имена и описание берутся из самого TypeDecl (qualifiedName + name.ru/en + description). Сканирование aliasIndex/getDescription в registerAsGlobalProperty для платформенных decl возвращает ровно алиасы этого же decl — то есть состояние TypeRegistry тут не требуется. А platformProviders зависят только от BslContextHolder — ребро GSP → platformProviders ацикличное.

6. Предложение — вариант 3 (push → pull)

  1. GSP сам публикует платформенный скоуп. Внедрить в GSP List<PlatformTypesProvider> и в ensureGlobalsPublished() (рядом с уже существующей публикацией функций/enum'ов из byFileType) пройти provider.getTypes() и зарегистрировать в GlobalSymbolScope платформенные классы (TYPE_NAME) и exposedAsGlobal-типы (VALUE) — прямо из TypeDecl.
  2. TypeRegistry.registerPackCallables перестаёт пушить в GSP (убрать registerAsPlatformClass/registerAsGlobalProperty для bootstrap-пути; registerConstructors/registerMemberSource остаются — это работа реестра).
  3. GSP больше не зависит от TypeRegistry → ленивое ребро удаляется вместе с ObjectProvider/ensureInitialized/ensureBootstrapped. Чтения GSP самодостаточны.
  4. Конфигурация/oscript остаются как есть: TypeRegistry.registerAsGlobalProperty сохраняется как helper для indexing-time писателей (он законно использует aliasIndex/getDescription). Ребро TypeRegistry → GSP остаётся односторонним — цикла нет.

Итог графа:

TypeRegistry ──▶ GlobalScopeProvider ──▶ GlobalSymbolScope
                       └──▶ List<PlatformTypesProvider>   (новое, ацикличное)

Никакого цикла, никакого resolve(""), никакой неявной связанности «дёрни реестр перед чтением».

7. Риски / на что смотреть

  • Дубль источников платформенных классов: getClasses() отдаёт byFileType.classes (грузится в конструкторе своим лоадером), а TYPE_NAME-записи сейчас идут из registerAsPlatformClass. Это уже два источника — вариант 3 не ухудшает, но просится последующая унификация лоадеров.
  • Порядок: indexing-time registerAsGlobalProperty должен видеть опубликованный платформенный скоуп — гейт ensureGlobalsPublished() уже дергается и на read, и на register*, надо лишь добавить туда платформенную публикацию.
  • Один ref от нескольких decl: для платформы пересечений нет (BuiltinPlatformTypesProvider.getTypes() пуст при наличии bsl-context; BSL/OS — разные fileType).
  • Тесты-стражи: hover/completion/semantic-tokens по платформенному классу (Структура, ТаблицаЗначений), системному перечислению и exposedAsGlobal в свежем workspace-scope без обращения к TypeRegistry. Текущий GlobalScopeProviderBootstrapTest остаётся валидным стражем и для варианта 3.

8. Что делать с этим PR

Вариант 1 здесь — безопасный интерим (зелёный, страж-тест есть). Предлагаю либо переписать эту ветку на вариант 3, либо смержить как промежуточный и сделать вариант 3 отдельным PR. Если ок — берусь за вариант 3 по плану выше.

@nixel2007 куда двигаемся — переписать ветку или отдельный PR поверх?

…gistry

Наполнение GlobalScopeProvider платформенным глобальным скоупом — побочный
эффект @PostConstruct bootstrap() workspace-scoped TypeRegistry. Чтение
GlobalScopeProvider сам этот bootstrap не триггерило, поэтому потребители
(инференсер, резолв голых имён, CompareWithBooleanDiagnostic) вынуждены были
вручную дёргать typeRegistry.resolve("") ради побочного эффекта — неявная
связанность, которую легко забыть в новом потребителе (тихий пустой скоуп в
свежем workspace-scope, не ловится под @SpringBootTest).

Вариант 1 из issue: GlobalScopeProvider.ensureBootstrapped() в начале
read-методов (findGlobal, getGlobalContexts) лениво материализует TypeRegistry
через ObjectProvider (разрывает конструкторный цикл). TypeRegistry — scoped
proxy, поэтому его target/bootstrap создаётся только при вызове МЕТОДА: добавлен
явный самодокументированный TypeRegistry.ensureInitialized() вместо загадочного
resolve(""). Все три ручных resolve("") у потребителей удалены.

Red-тест: чтение GlobalScopeProvider в свежем workspace-scope (без ручного
bootstrap) теперь само находит платформенный класс.

Refs #3994

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@nixel2007
nixel2007 force-pushed the fix/typeregistry-implicit-bootstrap branch from 2c70d42 to 5f39be3 Compare June 16, 2026 21:11
@nixel2007

Copy link
Copy Markdown
Member Author

Согласованный целевой дизайн (зафиксировано)

Глобальная область перестаёт быть отдельным push-наполняемым стором. Моделируется как члены синтетического типа ГлобальныйКонтекст в TypeRegistry + одна отдельная ось «имена типов». Источник — тот же bsl-context, который уже отдаёт глобальный контекст как сущность с .methods() и .properties() (GlobalScopeProvider.java:787,807).

Сущности и куда едут:

  1. Глобальные методы (Сообщить…) → методы-члены ГлобальногоКонтекста.
  2. Глобальные свойства (СправочникиСправочникиМенеджер, БиблиотекаКартинок…) → свойства-члены, valueType = соответствующий тип.
  3. Системные перечисления (КодировкаТекста) → синтезируются как свойства-члены ГлобальногоКонтекста (valueType = enum-тип). Важно (требование): член обязан нести дискриминатор «свойство-неймспейс / свойство-перечисление», чтобы semantic highlight сохранил текущее различие PLATFORM_GLOBAL_PROPERTY vs PLATFORM_GLOBAL_ENUM (GlobalScopeSemanticTokensSupplier:118 сейчас красит по SyntheticKind). То есть member-уровневый kind (свойство-неймспейс / свойство-перечисление / метод / library-модуль) должен переживать резолв и доезжать до семантик-сапплаеров без потери.
  4. Имена типов для Новый (Массив, Структура) → отдельная сущность, НЕ свойства контекста. Проекция TypeRegistry «типы с конструктором / именуемые типы». Сохраняется семантика Role.TYPE_NAME; инференсер по-прежнему отсекает их из value-резолва (ExpressionTypeInferencer:258-259).
  5. Keyword'ы — лексика, вне TypeRegistry, остаются как есть.

Разрешение голого имени в глобальной области = getMembers(ГлобальныйКонтекст) + проверка type-name-проекции (для Новый/имени типа). registerAsGlobalProperty/registerAsPlatformClass, зависимость TypeRegistry → GlobalScopeProvider и весь цикл (ObjectProvider/ensureInitialized/ensureBootstrapped) удаляются. GlobalScopeProvider/GlobalSymbolScope сжимаются до тонкого индекса (имя→член/type-name) либо растворяются.

Конфиг/oscript: общие модули и library-модули — те же свойства-члены контекста (valueType = тип модуля), через ту же member-машинерию, без отдельного «register global property».

Направление зависимостей: namespace/scope → TypeRegistry (read), никогда обратно.

План (пофазно, каждая фаза = коммит с тестами-стражами)

  • Фаза 1. Ввести синтетический тип ГлобальныйКонтекст, наполнить его членами (методы + свойства + enum-как-свойства, с member-kind дискриминатором) из тех же провайдеров. Стражи: hover/semantic/completion по Сообщить/Справочники/КодировкаТекста — типы и токены не деградируют.
  • Фаза 2. Мигрировать читателей (ExpressionTypeInferencer.findGlobalEntry/findFunction, CompletionProvider, семантик-сапплаеры, TypeService) на резолв через члены ГлобальногоКонтекста + type-name-проекцию.
  • Фаза 3. Удалить registerAsGlobalProperty/registerAsPlatformClass, ребро TypeRegistry → GlobalScopeProvider, схлопнуть GlobalScopeProvider/GlobalSymbolScope. Цикл уходит окончательно.

Текущий вариант-1-коммит в этой ветке заменяется новым дизайном (rebase/переписывание ветки).

nixel2007 and others added 5 commits June 17, 2026 06:33
Первый шаг развязки глобальной области (issue #3994): глобальная область
моделируется как члены синтетического типа TypeRegistry.GLOBAL_CONTEXT.

GlobalContextTypesProvider — composer: читает источник (bsl-context либо
встроенный JSON) и собирает члены GLOBAL_CONTEXT (глобальные методы/свойства,
системные перечисления как свойства-члены с valueType = сам тип). registerPack
штатно регистрирует члены этого типа — реестр типов ничего не эмитит в
глобальную область, а конкретный тип (КодировкаТекста) не знает о своём
глобальном отражении.

Старый push-путь (registerAsGlobalProperty/GlobalScopeProvider) пока живёт
параллельно — снос в последующих шагах cutover'а.

Refs #3994

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
…текста

Composer наполняет GLOBAL_CONTEXT и в builtin-fallback: функции из
builtin-globals.json → методы-члены, переменные → свойства-члены (двуязычное
имя из name+alias, сигнатуры/async/metadata сохраняются). bsl-context-путь
уже покрывал методы/свойства глобального контекста.

Парсинг builtin-globals.json временно переиспользуется через мост
GlobalScopeProvider.globalContextMembers — переедет в выделенный loader при
схлопывании GSP.

Refs #3994

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
ConfigurationModuleMembersProvider регистрирует общий модуль ещё и как
свойство-член GLOBAL_CONTEXT: единый динамический member-источник пересобирает
члены из карты URI→DocumentContext, поэтому добавление/смена модуля
отражаются после ближайшей инвалидации members-кэша (бампается на каждом
изменении документа), а sourceSymbol всегда берётся из актуального SymbolTree.

Старый registerAsGlobalProperty пока сохранён параллельно (снос в шаге E).
Тест: общий модуль присутствует среди членов GLOBAL_CONTEXT.

Refs #3994

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
…Контекста

Завершает миграцию динамических писателей глобальной области (issue #3994):
- ConfigurationTypesProvider: коллекции-namespace (Справочники/Документы) →
  свойства-члены GLOBAL_CONTEXT (карта пересоздаётся каждый проход — переживает
  перезагрузку конфигурации без дублей);
- OScriptModuleMembersProvider: library-модули OneScript → свойства-члены
  GLOBAL_CONTEXT для FileType.OS, с дерегистрацией по имени в unregister.

Старые registerAsGlobalProperty/registerLibraryModule пока сохранены
параллельно (снос в шаге E). Теперь все глобалы (платформа + конфигурация +
oscript) присутствуют как члены GLOBAL_CONTEXT — можно мигрировать читателей.

Refs #3994

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Подготовка к миграции читателей (issue #3994):
- globalMember(name, fileType) — резолв безпрефиксного имени в член
  GLOBAL_CONTEXT через быстрый name-индекс, пересобираемый по membersEpoch;
- isEnumType(ref) — классификация типа-значения (enum vs property) для
  раскраски, на основе сохранённого TypeDecl.isEnum;
- isConstructibleTypeName(name, fileType) — ось type-name (Структура для
  Новый) отдельно от членов GLOBAL_CONTEXT.

Направление зависимостей чистое: проекции читаются из TypeRegistry.

Refs #3994

Co-Authored-By: Claude Opus 4.8 (1M context) <[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 (1)
src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistry.java (1)

406-450: 💤 Low value

Benign race in global index caching.

Two concurrent callers may both compute the index when the epoch changes, and one overwrites the other's result. This is functionally correct (both compute the same data for the same epoch) but wastes CPU. Consider using compareAndSet or updateAndGet if this hot path sees contention, though the current approach is acceptable for typical usage patterns.

🤖 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 406 - 450, The globalMember method has a benign race condition
where multiple concurrent threads compute the same GlobalIndex when the epoch
changes and all overwrite each other's result via the unconditional
globalIndexRef.set() call. Replace the set() call with compareAndSet() to ensure
only the first computed GlobalIndex is stored, or alternatively use
updateAndGet() to perform the epoch check and index computation atomically in a
single operation, eliminating wasted CPU from redundant calculations while
maintaining functional correctness.
🤖 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/TypeRegistry.java`:
- Around line 406-450: The globalMember method has a benign race condition where
multiple concurrent threads compute the same GlobalIndex when the epoch changes
and all overwrite each other's result via the unconditional globalIndexRef.set()
call. Replace the set() call with compareAndSet() to ensure only the first
computed GlobalIndex is stored, or alternatively use updateAndGet() to perform
the epoch check and index computation atomically in a single operation,
eliminating wasted CPU from redundant calculations while maintaining functional
correctness.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0a8267bd-0689-4fd5-9132-e236ebb661f5

📥 Commits

Reviewing files that changed from the base of the PR and between 8f1a2e8 and 49e157c.

📒 Files selected for processing (8)
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/OScriptModuleMembersProvider.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/GlobalContextTypesProvider.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/TypeRegistry.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/GlobalContextMembersTest.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/GlobalContextTypesProvider.java

nixel2007 and others added 2 commits June 17, 2026 07:12
…GLOBAL_CONTEXT

Миграция читателей (issue #3994), часть 1:
- ExpressionTypeInferencer: bare-идентификатор и возвращаемый тип глобальной
  функции — через typeRegistry.globalMember (PROPERTY → valueType, METHOD →
  returnTypes), вместо findGlobalEntry/findFunction;
- GlobalScopeSemanticTokensSupplier: 4-сторонняя раскраска выводится из
  типа-значения члена — isEnumType → Enum, модульный тип (URI-индекс) →
  Namespace, иначе → Class+DefaultLibrary; убран SyntheticKind-switch и
  isCommonModuleBacked.

Старый путь (GSP) ещё используется остальными читателями — мигрируются следом.

Refs #3994

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
…з GLOBAL_CONTEXT

Миграция читателей (issue #3994), часть 2:
- PlatformGlobalMethodSemanticTokensSupplier: глоб-функция → globalMember(METHOD);
- PlatformMemberPropertyAccessSemanticTokensSupplier: база цепочки → globalMember(PROPERTY);
- SignatureHelpProvider: fallback глоб-функции → globalMember(METHOD);
- TypeService.resolveBareName: голое имя → globalMember (METHOD/PROPERTY),
  убраны findFunction/findGlobalEntry и SyntheticKind/GlobalSymbolScope-импорты.

Остался один читатель — CompletionProvider (list-проекции глобалов). Затем
снос старого пути и схлопывание GSP.

Refs #3994

Co-Authored-By: Claude Opus 4.8 (1M context) <[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: 3

🤖 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/semantictokens/GlobalScopeSemanticTokensSupplier.java`:
- Around line 123-131: The valueType assignment in the stream operation at the
beginning of the conditional block does not filter out UNKNOWN types before
selecting the first element. If TypeRef.UNKNOWN appears first in the stream, it
will be selected and cause misclassification of the semantic token. Add a filter
to the stream chain to exclude UNKNOWN types before calling findFirst() on
member.get().returnTypes().refs().stream() to ensure a concrete type is selected
when available.

In
`@src/main/java/com/github/_1c_syntax/bsl/languageserver/types/inferencer/ExpressionTypeInferencer.java`:
- Around line 256-260: The current filter in the return statement of the global
property type resolution only verifies that at least one concrete ref exists,
but returns the complete TypeSet which may contain UNKNOWN values. Modify the
code to filter out UNKNOWN refs from the TypeSet after the filter that checks
for their existence, ensuring that only concrete types are returned. This
prevents UNKNOWN from being leaked into the result even when concrete
global-property types are available. The fix involves transforming the filtered
TypeSet to exclude any refs that equal TypeRef.UNKNOWN before returning it.

In
`@src/main/java/com/github/_1c_syntax/bsl/languageserver/types/TypeService.java`:
- Around line 405-409: In the map operation that creates the TypedMember for
global properties, the MemberDescriptor.property call is incorrectly setting the
owner to `ref`. According to the TypedMember contract, global properties must
have owner == null to avoid misclassification. Change the second parameter
passed to MemberDescriptor.property from `ref` to `null` to ensure the owner
field remains null for these global properties.
🪄 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: f51c46fe-3ff0-4812-98f0-d234839da4b2

📥 Commits

Reviewing files that changed from the base of the PR and between 49e157c and 5e623d0.

📒 Files selected for processing (6)
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/providers/SignatureHelpProvider.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/semantictokens/GlobalScopeSemanticTokensSupplier.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/semantictokens/PlatformGlobalMethodSemanticTokensSupplier.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/semantictokens/PlatformMemberPropertyAccessSemanticTokensSupplier.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/TypeService.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/inferencer/ExpressionTypeInferencer.java

Comment thread src/main/java/com/github/_1c_syntax/bsl/languageserver/types/TypeService.java Outdated
nixel2007 and others added 7 commits June 17, 2026 09:03
Завершает миграцию читателей (issue #3994):
- getGlobalContexts → PROPERTY-члены GLOBAL_CONTEXT; иконка выводится из
  типа-значения (перечисление→Enum, library-модуль в OS→Module, иначе→Variable);
- getFunctions → METHOD-члены GLOBAL_CONTEXT;
- findGlobal (дедуп ru/en) → ключ по члену GLOBAL_CONTEXT либо resolve() для
  имён типов;
- resolveCompletionItem → globalMember(METHOD).

getClasses/getKeywords/getConfigurationQualifiedNames остаются собственными
данными GlobalScopeProvider (грузятся в конструкторе, не push-путь). Теперь у
GlobalSymbolScope-методов GSP не осталось читателей — снос в шаге E.

Refs #3994

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Последний читатель глобальной области (issue #3994): MCP-инструмент
global_member_info теперь использует typeRegistry.globalMember + isEnumType
вместо findFunction/findGlobalProperty/findGlobalEnum/findGlobalEntry. Канон-имя
и описание берутся из члена напрямую.

Все читатели глобалов мигрированы — GlobalSymbolScope-методы GSP без читателей.

Refs #3994

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Снят старый push-путь глобальной области (issue #3994):
- registerPackCallables больше не эмитит классы/exposedAsGlobal в GSP;
- registerAsGlobalProperty/registerAsPlatformClass удалены из TypeRegistry
  вместе с зависимостью на GlobalScopeProvider — ребро цикла разорвано;
- config/oscript-писатели больше не зовут registerAsGlobalProperty/
  registerLibraryModule/registerLibraryClass (всё через члены GLOBAL_CONTEXT);
- последний читатель GSP-read API (GlobalMemberInfoTool) переведён на globalMember;
- тесты, проверявшие через findGlobalContext/getGlobalContextNames, мигрированы
  на globalMember/getMembers(GLOBAL_CONTEXT); вариант-1 страж-тест удалён.

Направление зависимостей теперь одностороннее: scope/потребители → TypeRegistry.
Мёртвый код GSP (findGlobal*/register*/GlobalSymbolScope/ObjectProvider) и
exposedAsGlobal на TypeDecl снимаются следующим коммитом.

Refs #3994

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
…-symbol API

После миграции всех читателей на GLOBAL_CONTEXT (issue #3994) у GSP-методов
глобального символьного фронта не осталось вызовов. Удалены:
- findGlobal/findGlobalEntry/findGlobalContext/findGlobalProperty/findGlobalEnum,
  getGlobalContexts/getGlobalContextNames/getGlobalPropertyNames/getGlobalEnumNames,
  getFunctions/findFunction;
- registerGlobalProperty(×4)/registerPlatformClass/registerLibraryModule/
  registerLibraryClass/unregisterLibrary*;
- publishGlobals/ensureGlobalsPublished/registerFunctionSymbol/publishPlatformGlobals;
- вариант-1: поле ObjectProvider<TypeRegistry> + ensureBootstrapped + флаги
  bootstrapped/globalsPublished, зависимость на GlobalSymbolScope (ctor-параметр).

GSP остался слим-фасадом: классы для `Новый` (getClasses), keyword'ы
(getKeywords/findKeyword*), URI-индекс модулей (indexModuleType/moduleTypeByUri),
configuration-qualified-имена. Obsolete-тесты register*/find* удалены/обрезаны
до валидных (class/keyword) кейсов.

Refs #3994

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
…источника

Завершает развязку (issue #3994): «видно в глобальной области» больше не
поле нашего типа. exposedAsGlobal удалён из TypeDecl (record + оба конструктора);
признак читается из источника там, где собирается глобальный контекст:
- BuiltinTypesJsonLoader.globalContextProperties(resource) — читает JSON-флаг
  exposedAsGlobal и отдаёт свойства-члены GLOBAL_CONTEXT напрямую;
- BslContextPlatformTypesProvider — убрана эвристика isExposedAsGlobal;
- composer (GlobalContextTypesProvider) берёт exposed-свойства из лоадера.

Конкретный тип (КодировкаТекста) больше не знает о своём глобальном отражении;
TypeRegistry/TypeDecl чисты от namespace-концепции. Obsolete-тесты флага
удалены/обрезаны.

Refs #3994

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
CI поймал регрессию: GLOBAL_CONTEXT наполнялся только для BSL
(GlobalContextTypesProvider), а OneScript-глобалы (функции/переменные/
перечисления) выпали — резолв глобалов в .os-файлах ломался (hover глоб-функции/
перечисления, global_member_info для OS).

Добавлен GlobalContextOScriptTypesProvider (FileType.OS): члены GLOBAL_CONTEXT из
builtin-oscript-globals.json (функции/переменные) + exposed-перечисления из
builtin-oscript-platform-types.json. Зеркалит BSL-composer; OneScript всегда из
ресурсов (bsl-context не применяется). globalContextDecl переиспользован.

Чинит: HoverProviderTest.hoverOnGlobal{Function,Enum}InOsFile*,
HoverProviderTypeAwareTest.hoverOn{CurrentDate,StrReplace}*, McpToolsTest.
globalMemberInfoAcceptsOscriptFileType. Добавлен страж globalMember(OS).

Refs #3994

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Платформенный глобальный контекст (bsl-context) отдаёт свойства-менеджеры
коллекций (Справочники → СправочникиМенеджер, Перечисления →
ПеречисленияМенеджер, Документы → ДокументыМенеджер). GlobalContextTypesProvider
кладёт их членами GLOBAL_CONTEXT на bootstrap'е — раньше, чем
ConfigurationTypesProvider зарегистрирует одноимённые коллекции-namespace
конфигурации (с членами-MD-объектами).

computeMembers резолвит член GLOBAL_CONTEXT через putIfAbsent по имени
(первый источник побеждает), поэтому платформенное свойство — без MD-объектов —
затеняло конфигурационную коллекцию: Справочники.<Каталог> и
Перечисления.<Перечисление> не резолвились, completion членов менеджера был пуст.
Видно только с платформой (HBK), поэтому CI/юнит-тесты этого не ловили.

Регистрируем коллекции конфигурации как registerMemberOverride (в начало
списка источников): конфигурация выигрывает, т.к. она суперсет (наследует
методы менеджера через registerInheritedMembers + добавляет MD-объекты).

Red-тест GlobalContextCollectionShadowingTest воспроизводит затенение без
платформы (имитирует платформенное свойство, зарегистрированное раньше config).

Refs #3994

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@nixel2007

Copy link
Copy Markdown
Member Author

Регрессия: пустой completion членов менеджера коллекций/перечислений (с платформой)

Нашёл и починил регрессию, которая воспроизводилась только с подключённой платформой (HBK) — поэтому CI и юнит-тесты её не ловили.

Симптом

Справочники.<Каталог>. и Перечисления.<Перечисление>. — пустой список автодополнения (на стенде GIF: comp-09, comp-17). На develop — богатый список (методы менеджера + предопределённые/значения перечисления).

Root cause

Платформенный ГлобальныйКонтекст (bsl-context) сам отдаёт свойства-менеджеры коллекций — подтверждено дампом из bsl-context:

  • Справочники → СправочникиМенеджер, Перечисления → ПеречисленияМенеджер, Документы → ДокументыМенеджер.

GlobalContextTypesProvider кладёт их членами GLOBAL_CONTEXT на bootstrap'е — раньше, чем ConfigurationTypesProvider зарегистрирует одноимённые коллекции-namespace конфигурации (на ServerContextPopulatedEvent). computeMembers резолвит член через putIfAbsent по имени (первый источник побеждает), поэтому платформенное свойство без MD-объектов затеняло конфигурационную коллекцию → receiver Справочники/Перечисления резолвился в пустой платформенный менеджер → второй хоп пуст.

Без платформы (CI/тесты/host) у bsl-context этих свойств нет → конфигурация выигрывала → зелено.

Фикс

ConfigurationTypesProvider.ensureGlobalContextCollectionsSource регистрирует коллекции конфигурации как registerMemberOverride (в начало списка источников), а не append. Конфигурация выигрывает корректно: её namespace — суперсет (наследует методы менеджера через registerInheritedMembers + добавляет MD-объекты).

Тест

GlobalContextCollectionShadowingTest воспроизводит затенение без платформы: имитирует платформенное свойство Справочники, зарегистрированное раньше конфигурации (initServerContext(root, false) + ручной registerMemberSource + populateContext()), и проверяет, что безпрефиксное Справочники резолвится в config-коллекцию с членом-каталогом. Красный до фикса, зелёный после.

Валидация гифками

Перезаписал globalscope-ssl: comp-09 (Перечисления.ВажностьПроблемыУчета.) и comp-17 (Справочники.ВидыКонтактнойИнформации.) снова показывают полный список (значения перечисления/предопределённые + методы менеджера) — как на develop. Зелёные пакеты: types.*, hover.*, providers.*, semantictokens.*.

Коммит: 98f785a.

nixel2007 and others added 4 commits June 17, 2026 14:08
Путь membersFromContext (методы/свойства глобального контекста + системные
перечисления как свойства-члены GLOBAL_CONTEXT) исполняется только при
подключённой платформе (HBK), поэтому не покрывался в CI — крупнейший пробел
new-code coverage PR'а и та же зона, где жила регрессия затенения коллекций.

Покрываем синтетическим PlatformContextProvider по образцу
BslContextPlatformTypesProviderTest (без реальной платформы): метод → метод-член,
свойство → свойство-член, top-level ContextEnum → свойство-член с valueType.

Refs #3994

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
TypeRegistry — хранилище ТИПОВ; резолв глобальных функций/свойств — не его
ответственность. Переносим API в GlobalScopeProvider (абстракцию доступа к
контексту), TypeRegistry оставляем чистым storage (issue #3994).

- GlobalScopeProvider получает globalMember/globalFunction/globalProperty
  (типизированные аксессоры вместо россыпи globalMember().filter(kind==…)) и
  эпоха-кэшированный name-индекс; делегирует в typeRegistry.getMembers(GLOBAL_CONTEXT).
  Направление GlobalScopeProvider → TypeRegistry (read), без цикла.
- TypeRegistry.globalMember удалён; добавлен membersEpoch() как ключ инвалидации
  кэшей потребителей. GLOBAL_CONTEXT (идентичность типа) остаётся на TypeRegistry —
  он используется композерами как цель регистрации членов.
- 11 потребителей (TypeService, ExpressionTypeInferencer, CompletionProvider,
  SignatureHelpProvider, semantic-сапплаеры, GlobalMemberInfoTool) переключены на
  globalScopeProvider.global*(); тесты — на GlobalScopeProvider.

Refs #3994

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
После переноса globalMember в GlobalScopeProvider у сапплаера удалён импорт
TypeRegistry (поле заменено на GlobalScopeProvider), но в javadoc класса осталась
ссылка {@link TypeRegistry#GLOBAL_CONTEXT} — кросс-пакетная, без импорта →
"reference not found", падал таск :javadoc. Сапплаер теперь резолвит глобальную
функцию через GlobalScopeProvider#globalFunction — обновляем ссылку на неё.

Refs #3994

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
ОбщегоНазначения.Знач → экспортный метод модуля (ЗначениеВМассиве). Страж пути,
который задел перенос globalMember в GlobalScopeProvider (резолв ресивера-модуля
через globalProperty + раскраска). На designer-фикстуре логика completion общих
модулей исправна; пустой comp-07 на стенде GIF — следствие неполной индексации
большого SSL-конфига, не логики.

Refs #3994

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@nixel2007 nixel2007 changed the title refactor(types): GlobalScopeProvider сам гарантирует bootstrap TypeRegistry refactor(types): глобальная область видимости — члены синтетического типа ГлобальныйКонтекст Jun 17, 2026
nixel2007 and others added 4 commits June 17, 2026 15:43
filterNamesByLanguage обслуживал три разные сущности (классы, составные имена
конфигурации, кейворды) одним catch-all ключом globalMember?:resolve?:bareKey —
причём ветка globalMember для этих вызовов мертва (голых глобал-значений в
списках нет), а кейворды всё равно уходили в bareKey (не группируются).

Разносим:
- filterTypeNamesByLanguage(names, language) — для имён типов (классы для Новый +
  составные имена MD-объектов): ключ = интернированный TypeRef (resolve), ru/en
  одного типа группируются, остаётся написание под язык. fileType больше не нужен
  (resolve по имени, без языка).
- кейворды — прямая итерация getKeywords: общей идентичности ru/en у них нет,
  фильтр был no-op; поведение сохранено, намерение явно в комментарии.

Refs #3994

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
CompletionProvider перечислял глобальные свойства и функции прямым чтением
typeRegistry.getMembers(GLOBAL_CONTEXT) + фильтром по kind — обход абстракции
(by-name доступ уже шёл через GlobalScopeProvider). Получалось два способа
доступа к глобальной области.

Добавляем перечисляющие аналоги by-name аксессоров:
- GlobalScopeProvider.globalProperties(fileType)
- GlobalScopeProvider.globalFunctions(fileType)

Оба цикла completion идут через них. Поле typeRegistry в CompletionProvider
остаётся только для resolve(name) и isEnumType(valueType) — запросы к хранилищу
ТИПОВ (имя→тип, признак типа), не к глобальной области. Прямых обращений к
TypeRegistry.GLOBAL_CONTEXT в потребителях больше нет.

Refs #3994

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
После переноса глобальной области в члены GLOBAL_CONTEXT синтетик-символы больше
не создаются (new SyntheticSymbol отсутствует), а резолв/hover платформенных
глобалов идёт через PlatformMemberSymbol (несёт MemberDescriptor) — тот же путь,
что и для остальных платформенных членов. Параллельный Symbol-фронт осиротел.

Удалено:
- SyntheticSymbol, SyntheticKind, GlobalSymbolScope (пустой @Component-бин),
  SyntheticSymbolMarkupContentBuilder (никогда не диспетчеризовался);
- мёртвые ветки instanceof SyntheticSymbol в TypeService.typesAt и
  ExpressionTypeInferencer (никогда не матчили — таких символов нет);
- тесты на удалённые классы; synthetic-методы TypeServiceDelegationTest;
- устаревшие javadoc-ссылки на удалённые классы (чинит сборку javadoc).

Классификация property-vs-enum у потребителей — из типа-значения
(TypeRegistry.isEnumType), как и было после рефактора.

Refs #3994

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Симметрия с BSL-общими модулями: GLOBAL_CONTEXT(OS)-член library-модуля теперь
несёт sourceSymbol (ModuleSymbol) — для навигации/раскраски/hover, как
ConfigurationModuleMembersProvider в BSL.

libraryModuleGlobals ключуется по URI (а не по имени) и хранит тип + DocumentContext;
member пересобирается с withSourceSymbol(doc.getSymbolTree().getModule()) лениво
(rebuild-safe). unregister(URI) убирает запись по URI.

Refs #3994

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
nixel2007 and others added 16 commits June 17, 2026 18:01
… провайдерах

Динамическое членство глобальной области (коллекции, общие/library-модули)
хранилось картами прямо в трёх провайдерах (collectionGlobalMembers,
commonModuleDocs, libraryModuleGlobals) — дублируя то, что уже есть в TypeRegistry
(интернированный ref, а для UserType — declaration-символ), и удерживая
DocumentContext сильной ссылкой (анти-паттерн, ср. 325636f).

Централизуем в TypeRegistry (как enumTypes):
- маркер-множество globalPropertyTypes (per FileType) + опциональный
  globalPropertySymbols (WeakReference) для типов без собственного declaration
  (конфигурационные общие модули — ConfigurationType его не несёт);
- registerGlobalPropertyType(ref, ft, declaration) / unregisterGlobalPropertyType;
- единый override-source на GLOBAL_CONTEXT (per язык, в bootstrap): собирает
  property(name/bilingual из displayName, value-type=ref, sourceSymbol из
  UserType.declaration либо globalPropertySymbols). Override сохраняет фикс
  шадоуинга (config-коллекции перекрывают платформенные свойства).

Провайдеры теперь только помечают тип глобальным:
- ConfigurationTypesProvider/ConfigurationModuleMembersProvider/
  OScriptModuleMembersProvider — registerGlobalPropertyType(...), карты удалены.

Символ захватывается eager на DocumentContextContentChangedEvent (после rebuild,
как SymbolTypeIndex/WorkspaceSymbolIndex), а getMembers(GLOBAL_CONTEXT) делает
лишь WeakReference.get() — без доступа к SymbolTree под чужими локами (раньше
ленивый getSymbolTree() в source'е был рискованнее по локам).

Refs #3994

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
CodeRabbit (валидные):
- TypeService.resolveBareName: owner=null для глобального свойства (контракт
  TypedMember — глобалы без owner; глоб-функция уже была null);
- GlobalScopeSemanticTokensSupplier: фильтр UNKNOWN перед классификацией токена.

SonarCloud:
- удалены unused-импорты/dead-code: TypeRegistry (LinkedHashSet),
  GlobalContextTypesProvider (EnAttachments), GlobalScopeProviderBslContextTest
  (8 импортов + мёртвый method()), GlobalContextTypesProviderTest (MemberDescriptor),
  ConfigurationTypesProviderHelpersTest (unused globalScope);
- GlobalMemberInfoTool.globalValueResult → static; убрана мёртвая проверка
  description==null (S2589, @nonnull в @NullMarked);
- BuiltinTypesJsonLoader.globalContextProperties: один guard-continue + вынос
  firstAlias (снижение вложенности S134/S135);
- GlobalScopeProvider.globalContextMembers: вынос functionMember/variableMember
  (сложность S3776/S1541), константы RETURN_TYPE_FIELD/ALIASES_FIELD (дубль S1192);
- тест-нитпики: lambda→MemberDescriptor::name, объединение assertThat-цепочки.

Refs #3994

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
…раметра

Никаких null в публичном API: вместо registerGlobalPropertyType(ref, ft, null)
два перегруза —
- registerGlobalPropertyType(ref, ft) — без source-символа (коллекции;
  library-модули OneScript несут declaration в UserType);
- registerGlobalPropertyType(ref, ft, declaration) — с явным non-null символом
  (конфигурационные общие модули, ConfigurationType его не хранит).

Вызовы коллекций и library-модулей переведены на 2-арг.

Refs #3994

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
- registerGlobalPropertyType и соседние комментарии TypeRegistry больше не
  называют домены-вызывающие (коллекции, общие/library-модули, bsl-context):
  хранилище описывается в своих терминах (тип-глобал-свойство, source-символ,
  override над другими источниками GLOBAL_CONTEXT);
- удалены ссылки "issue #3994"/"PR #4135" из javadoc и комментариев (трекинг —
  в git/PR, не в коде).

Refs #3994

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Javadoc описывает «что есть», а не «как было раньше»:
- ensureInitialized: убрано «push-моделью наполняет GlobalScopeProvider»,
  ссылка на удалённый ensureBootstrapped и «заменяет прежний resolve("")» —
  оставлено описание текущего поведения (материализация scope + bootstrap);
- globalContextMembers: убран «временный мост на время cutover'а»;
- GlobalContextMembersTest: убрана «Фаза 1 рефактора … push-механизм»;
- registerPackCallables: убран комментарий «глобальная видимость больше не
  эмитится отсюда».

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
…lScopeProvider

Константа GLOBAL_CONTEXT больше не public: её видимость пакетная, доступ
у потребителей — только через геттеры GlobalScopeProvider
(globalFunction/globalProperty/globalProperties/…). Из комментариев
потребителей убрано упоминание внутреннего устройства реестра.

Заодно вычищены комментарии: убран выдуманный термин «composer»
(нет такого типа/интерфейса в bsl-ls) и внешнее знание (стенд GIF),
не относящееся к кодовой базе.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
…ль-зависимость от TypeRegistry

Семь потребителей инжектили одновременно TypeService и TypeRegistry, хотя
лезли в реестр лишь за мелочами, которые фасад не реэкспортировал.

- В TypeService добавлены делегаты: isEnumType, isVersionedMemberName,
  hasAnyReadOnlyMember, supportsForEach, supportsIndexAccess,
  getForEachDescription, getIndexAccessDescription.
- CompletionProvider, SignatureHelpProvider, ConstructorHoverBuilder,
  CollectionHoverHints, AssignToReadOnlyPropertyDiagnostic,
  PlatformMemberCalls (+ Unavailable/DeprecatedMemberCall) больше не
  зависят от TypeRegistry — всё через TypeService.
- SignatureHelpProvider: удалено мёртвое поле typeRegistry.
- PlatformMemberCalls.collect: убран параметр typeRegistry.
- CompletionProvider.filterTypeNamesByLanguage резолвит ключ-идентичность
  через resolve(name, fileType): безфильтровый resolve(name) — внутренний
  примитив слоя типов и на фасаде не выставляется.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Самописная карта internedRefs (Map<TypeRef,TypeRef> + putIfAbsent) — это
ровно GenericInterner<T> из utils; заменено на него.

У GenericInterner нет read-API (только intern/clear), поэтому
resolve(TypeKind, qualifiedName) больше не может делать чистый lookup по
интернеру. Метод перенесён на хранилище types: он возвращает ссылку только
для ЗАРЕГИСТРИРОВАННОГО типа (kind-точно), а не для просто интернированного
полуфабриката без Type/членов. Прод-вызовов у метода нет; тест обновлён под
новый контракт.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
… файла

enumTypes, supportsForEach, supportsIndexAccess и их описания
(forEach/indexAccessDescriptions) хранились на голом TypeRef без разреза по
fileType, хотя члены и описания типа уже per-fileType. Одно и то же имя в BSL
и OneScript — разные типы с разной природой, поэтому признак, выставленный
источником одного языка, протекал в другой (последний регистратор побеждал).

Хранение переведено на Map<FileType, …>; в isEnumType/supportsForEach/
supportsIndexAccess и геттеры описаний добавлен параметр fileType. Рябь
проброшена через фасад TypeService и вызывающих (CompletionProvider,
GlobalScopeSemanticTokensSupplier, GlobalMemberInfoTool, CollectionHoverHints,
ConstructorHoverBuilder) — у всех fileType под рукой.

Red-test: TypeRegistryCollectionTraitsPerLanguageTest — признаки, заявленные
для BSL, не видны в OS.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
…кет @NullMarked

Пакет hover помечен @NullMarked, параметры append non-null по контракту, а
единственный вызывающий передаёт non-null. Защитная проверка на null
противоречила контракту (подразумевала возможность null) — удалена вместе с
тестом, дёргавшим append с null (запрещённый контрактом ввод).

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
…не параметр

TypeService прокидывался в append параметром (рудимент от прежней передачи
workspace-scoped TypeRegistry). Spring отдаёт scoped-proxy, поэтому
TypeService инжектится полем — как уже сделано в ConstructorHoverBuilder.
append теперь принимает только (sb, ref, fileType).

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
…bal и двойной парс

JSON-fallback глобальной области строил enum-свойства повторным парсом
platform-types.json с фильтром по флагу exposedAsGlobal — это и двойной разбор
того же файла, и рассинхрон с платформенным путём (там enum-глобалы выводятся
структурно из ContextEnum, без флага).

Теперь enum-глобалы выводятся из ENUM-типов уже загруженного пака
(BuiltinTypesJsonLoader.enumGlobalProperties), load() мемоизирован по ресурсу —
один парс на JVM. globalContextProperties + firstAlias удалены.

Данные приведены к источнику (живой движок OneScript + OneScript.StandardLibrary
+ oscriptStdLib):
- 7 XS-типов (ЗавершенностьСхемыXS и пр.) — это системные перечисления
  (EnumXSSchemaFinal), исправлен kind TYPE→ENUM;
- Символы — класс (ТипЗнч=Chars), а не перечисление: kind ENUM→TYPE; его
  глобальность идёт из builtin-oscript-globals.json/variables;
- поле exposedAsGlobal удалено из обоих platform-types.json (больше не читается).

Генератор (OneScriptDocumenter/HBK-grabber) должен впредь отдавать
Enumeration*/[SystemEnum]-типы как ENUM и не эмитить exposedAsGlobal.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
… Символы

Глобальная переменная Символы (класс набора системных символов) не имела
поля type → value-type UNKNOWN, обращение Символы.ПС не резолвилось. Задан
type "Символы" — значением переменной становится класс Символы, его члены
(ПС/ВК/Таб/…) подтягиваются.

Red-test: GlobalContextMembersTest.oscriptGlobalVariableCharsResolvesItsMembers.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
…адер чистый

enumGlobalProperties жил в BuiltinTypesJsonLoader и дублировал enumAsProperty
провайдера: сборка членов GLOBAL_CONTEXT — домен провайдера, а лоадер должен
лишь парсить JSON в TypeDecl. Маппинг «перечисление → глобальное свойство»
сведён в один общий статик GlobalContextTypesProvider.enumGlobalProperties
(зовут и BSL-, и OScript-провайдер), переиспользующий enumAsProperty
платформенного пути. Типы берутся из мемоизированного load() — без повторного
парса. Метод удалён из лоадера.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
- 3 BUG (always-false): убраны мёртвые `if (ref == null)` в
  registerGlobalPropertyType/unregisterGlobalPropertyType — пакет @NullMarked,
  параметр non-null по контракту.
- FQN: `new java.lang.ref.WeakReference<>` → `WeakReference` (импорт есть).
- S1213: LOAD_CACHE перенесён в начало BuiltinTypesJsonLoader (поле до методов);
  заодно починена битая @link на удалённый enumGlobalProperties.
- S125 (FP): переформулирован прозаический комментарий в
  GlobalScopeProviderBslContextTest, чтобы не выглядел закомментированным кодом.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
…ямбды

- CompletionProvider.filterTypeNamesByLanguage: Object-ключ (с new Object()
  для не-типов) заменён на TypeRef-ключ (Comparable); не-типы собираются прямо
  в результат. Порядок не важен — итоговую сортировку задаёт sortText.
- TypeService: явный тип параметра лямбды `(TypeRef ref)`.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@nixel2007
nixel2007 merged commit ac39cbd into develop Jun 18, 2026
33 checks passed
@nixel2007
nixel2007 deleted the fix/typeregistry-implicit-bootstrap branch June 18, 2026 05:44
@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.

1 participant