Skip to content

feat(types): «Перем» без сведений — «Неопределено», единый резолвер висячих комментариев - #4348

Closed
nixel2007 wants to merge 14 commits into
developfrom
feat/typification-spec-conformance
Closed

feat(types): «Перем» без сведений — «Неопределено», единый резолвер висячих комментариев#4348
nixel2007 wants to merge 14 commits into
developfrom
feat/typification-spec-conformance

Conversation

@nixel2007

@nixel2007 nixel2007 commented Aug 1, 2026

Copy link
Copy Markdown
Member

Что сделано

Правки системы типов, закрывающие расхождения с методической рекомендацией «Типизация кода»,
и тесты на них в компонентах системы типов. Сверка ведётся на тестовом полигоне (#4345);
сюда вынесены только код и тесты — полигона в ветке нет.

1. Значение переменной, объявленной записью Перем

По рекомендации переменная, объявленная через Перем и без иных сведений о типе, содержит
Неопределено — это её значение, а не отсутствие сведений.

Перем А;
Если Ложь Тогда
    А = Истина;
КонецЕсли;
// здесь А — Неопределено | Булево

Исключения, где Неопределено от объявления наблюдать неоткуда:

  • присваивание в теле модуля — оно отрабатывает раньше любой процедуры;
  • присваивание в ПриСозданииОбъекта — конструктор выполняется при создании объекта,
    до обращения к его полям.

2. Один резолвер висячих комментариев вместо двух

MemberTypeFromCommentResolver (типизирующий комментарий члена) и
VariableCommentTypeResolver (типизирующий комментарий переменной) разбирали один и тот же
вид комментария и разошлись в возможностях: ссылку // см. Функция умел только первый.
Объединены в TrailingCommentTypeResolver; ссылка // см. … теперь работает и в объявлении
переменной, и в строке присваивания — как в описании члена.

3. Приведение ссылок после структурной специализации

Шаблон СправочникСсылка.<Имя справочника> приходит из синтакс-помощника платформенным, а
конфигурационные типы регистрируются своим видом. Специализация сохраняла вид шаблона, из-за
чего за одним именем оказывались две ссылки, различающиеся только видом, и объединение
наборов их не схлопывало — тип показывался дважды. Ссылки специализированных членов
приводятся к зарегистрированным в реестре.

Тесты

Новые: PeremTypeCommentInferenceTest, ModuleVariableFlowTest, ModuleBodyFlowTest,
FlowSensitiveVariableTypeTest, InlineTypeCommentInferenceTest,
TypeRegistrySpecializationTest.

Обновлены под новое поведение: ExpressionTypeInferencerSelfPropertyFallbackTest,
AutumnDependencyInjectionInferenceTest, VariableSymbolMarkupContentBuilderTest
Перем без сведений hover теперь показывает Тип: Неопределено).

🤖 Generated with Claude Code

https://claude.ai/code/session_01MnWpDdNSEFohPZHG6voe6y

Summary by CodeRabbit

  • New Features

    • Improved type inference from trailing comments in BSL and OneScript, including referenced types and assignment comments.
    • Added more accurate flow-sensitive inference before and after assignments or constructor initialization.
    • Preserved structured fields for collections, value-table rows, trees, and correspondence elements.
    • Specialized types now consistently reuse canonical type definitions.
  • Bug Fixes

    • Variables without enough information now correctly display Неопределено instead of an empty type.
    • Improved hover information and type unions for unassigned, conditionally assigned, and unresolved variables.

@coderabbitai

coderabbitai Bot commented Aug 1, 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 change replaces comment-based type resolvers with TrailingCommentTypeResolver, preserves Неопределено during flow analysis, canonicalizes specialized type references, and propagates fields for collection element types.

Changes

Type inference updates

Layer / File(s) Summary
Trailing-comment resolver and integrations
src/main/java/.../types/TrailingCommentTypeResolver.java, src/main/java/.../types/{oscript,registry}/*, src/test/java/.../types/*
Trailing comments resolve direct types, см. references, qualified links, and assignment comments. Providers and inference tests use the new resolver.
Undefined-variable and assignment flow
src/main/java/.../types/inferencer/ExpressionTypeInferencer.java, src/test/java/.../types/*, src/test/java/.../hover/*
Unassigned Перем variables retain Неопределено until a guaranteed assignment. Constructor, module-body, conditional, and hover behavior are covered by tests.
Canonical generic types and collection fields
src/main/java/.../types/model/*, src/main/java/.../types/registry/*, src/main/java/.../types/index/SymbolTypeIndex.java, src/test/java/.../types/model/*, src/test/java/.../types/ValueTableColumnsFieldsInferenceTest.java
Specialized references are canonicalized through TypeRegistry. TypeSet.mapRefs preserves merged decorations. Collection fields attach to resolved element types.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Variable
  participant ExpressionTypeInferencer
  participant TrailingCommentTypeResolver
  participant TypeRegistry
  participant SymbolTypeIndex
  Variable->>ExpressionTypeInferencer: infer declaration or assignment type
  ExpressionTypeInferencer->>TrailingCommentTypeResolver: resolve trailing comment
  TrailingCommentTypeResolver->>TypeRegistry: resolve direct type
  TrailingCommentTypeResolver->>SymbolTypeIndex: resolve см. reference
  SymbolTypeIndex-->>TrailingCommentTypeResolver: return referenced type
  TrailingCommentTypeResolver-->>ExpressionTypeInferencer: return TypeSet
  ExpressionTypeInferencer-->>Variable: merge inferred types and Неопределено
Loading

Possibly related PRs

Suggested reviewers: claude

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 13.16% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Заголовок точно отражает основные изменения: вывод «Неопределено» для «Перем» без сведений и объединение резолверов висячих комментариев.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/typification-spec-conformance

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.

@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/types/inferencer/ExpressionTypeInferencer.java`:
- Around line 960-1008: Update the documentation for the type-inference behavior
implemented by declaredByPerem and assignedBeforeAnyUse, covering Перем
variables, module initialization, and ПриСозданииОбъекта; add equivalent
explanations to both localized documentation trees, docs/ and docs/en/, using
the existing documentation structure and terminology.
- Around line 993-1005: Replace the unconditional success logic in
assignedBeforeAnyUse with control-flow analysis that verifies a module variable
assignment dominates and reaches every use, including module-level reads and all
constructor branches; return true only when no use can observe an unassigned
value. Add tests covering a read before a later module assignment and an
assignment confined to a conditional ПриСозданииОбъекта branch.

In
`@src/main/java/com/github/_1c_syntax/bsl/languageserver/types/model/TypeRef.java`:
- Around line 190-203: Update TypeSet.map to preserve all decorations when
rebuilding mapped references: remap element types, local fields, and lazy
decorations using each source ref’s mapped ref, and merge decoration entries
when multiple refs canonicalize to the same target. Keep returning the original
typeSet when no references change, while ensuring changed results retain the
complete decorated TypeSet structure rather than calling TypeSet.of(rebuilt)
alone.
🪄 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 Plus

Run ID: e9ae7415-8f80-46a1-a7db-18f71fbdc5fc

📥 Commits

Reviewing files that changed from the base of the PR and between 6fb9c39 and 16ce68b.

⛔ Files ignored due to path filters (5)
  • src/test/resources/types/FlowSensitiveVariableTypes.bsl is excluded by !src/test/resources/**
  • src/test/resources/types/InlineTypeComment.bsl is excluded by !src/test/resources/**
  • src/test/resources/types/ModuleBodyFlow.os is excluded by !src/test/resources/**
  • src/test/resources/types/ModuleVariableFlow.bsl is excluded by !src/test/resources/**
  • src/test/resources/types/PeremTypeComment.bsl is excluded by !src/test/resources/**
📒 Files selected for processing (21)
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/CLAUDE.md
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/MemberTypeFromCommentResolver.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/TrailingCommentTypeResolver.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/index/SymbolTypeIndex.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/inferencer/ExpressionTypeInferencer.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/inferencer/VariableCommentTypeResolver.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/model/MemberDescriptor.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/model/TypeRef.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/ConfigurationModuleMembersProvider.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistry.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/hover/VariableSymbolMarkupContentBuilderTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/ExpressionTypeInferencerSelfPropertyFallbackTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/FlowSensitiveVariableTypeTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/InlineTypeCommentInferenceTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/ModuleBodyFlowTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/ModuleVariableFlowTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/PeremTypeCommentInferenceTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/OScriptModuleMembersProviderTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/autumn/AutumnDependencyInjectionInferenceTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistrySpecializationTest.java
💤 Files with no reviewable changes (2)
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/MemberTypeFromCommentResolver.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/inferencer/VariableCommentTypeResolver.java

Comment thread src/main/java/com/github/_1c_syntax/bsl/languageserver/types/model/TypeRef.java Outdated

@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/model/TypeSet.java`:
- Around line 214-230: Update TypeSet.mapRefs to recursively apply the mapper to
nested TypeSet values in elementTypes and the types held by LocalField, and
include those nested results when determining whether to return this. Preserve
unchanged nested values where possible, while ensuring canonicalized element and
field references are returned even when the parent refs are unchanged; add
coverage for both nested cases.
🪄 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 Plus

Run ID: abcf29ae-ee8d-426d-b329-5c43c5d13b81

📥 Commits

Reviewing files that changed from the base of the PR and between 16ce68b and 9a729e1.

⛔ Files ignored due to path filters (1)
  • src/test/resources/types/ModuleBodyFlowEnglishConstructor.os is excluded by !src/test/resources/**
📒 Files selected for processing (4)
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/inferencer/ExpressionTypeInferencer.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/model/MemberDescriptor.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/model/TypeSet.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/ModuleBodyFlowTest.java
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/model/MemberDescriptor.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/inferencer/ExpressionTypeInferencer.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/ModuleBodyFlowTest.java

Comment thread src/main/java/com/github/_1c_syntax/bsl/languageserver/types/model/TypeSet.java Outdated

Copilot AI 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.

Pull request overview

This PR updates the types subsystem to better match the “Типизация кода” recommendation: variables declared via Перем without additional type info now infer as Неопределено, trailing type comments are resolved by a single shared resolver, and type specializations canonicalize TypeRefs to avoid duplicate refs for the same qualified name.

Changes:

  • Treat Перем-declared variables with no other type signals as having value/type Неопределено, with flow-sensitive handling for module-body / constructor assignments.
  • Replace two overlapping trailing-comment resolvers with TrailingCommentTypeResolver and extend // см. … support to assignment-line comments too.
  • Canonicalize refs after structural specialization (incl. decorations) so unions don’t show the same type twice.

Reviewed changes

Copilot reviewed 32 out of 32 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/main/java/com/github/_1c_syntax/bsl/languageserver/types/TrailingCommentTypeResolver.java New unified resolver for trailing type comments and // см. … references (declaration + assignment-line).
src/main/java/com/github/_1c_syntax/bsl/languageserver/types/MemberTypeFromCommentResolver.java Removed (merged into TrailingCommentTypeResolver).
src/main/java/com/github/_1c_syntax/bsl/languageserver/types/inferencer/VariableCommentTypeResolver.java Removed (merged into TrailingCommentTypeResolver).
src/main/java/com/github/_1c_syntax/bsl/languageserver/types/inferencer/ExpressionTypeInferencer.java Adds Неопределено for Перем without other info; uses unified trailing resolver; adds “assigned before any use” logic.
src/main/java/com/github/_1c_syntax/bsl/languageserver/types/model/TypeSet.java Adds mapRefs to canonicalize refs (incl. decorations) after specialization.
src/main/java/com/github/_1c_syntax/bsl/languageserver/types/model/MemberDescriptor.java Specialization now accepts a canonicalizer and applies it to return/parameter refs (incl. decorations).
src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistry.java Passes canonicalizer during specialization and adds canonicalRef helper.
src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/RegisterTypesRegistrar.java Uses canonicalizer when specializing register-based members.
src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/PlaceholderBinder.java Uses canonicalizer when binding placeholders into members.
src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/ConfigurationModuleMembersProvider.java Switches module member typing from removed resolver to TrailingCommentTypeResolver.
src/main/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/OScriptModuleMembersProvider.java Switches property typing from removed resolver to TrailingCommentTypeResolver.
src/main/java/com/github/_1c_syntax/bsl/languageserver/types/index/SymbolTypeIndex.java Updates documentation reference to the new unified trailing resolver.
src/main/java/com/github/_1c_syntax/bsl/languageserver/types/CLAUDE.md Updates subsystem documentation to reflect the new resolver name/responsibilities.
src/test/java/com/github/_1c_syntax/bsl/languageserver/types/PeremTypeCommentInferenceTest.java New assertions: Перем without other info → Неопределено; // см. … on Перем resolves constructor-return structure fields.
src/test/java/com/github/_1c_syntax/bsl/languageserver/types/ModuleVariableFlowTest.java Flow tests updated for Неопределено baseline + new cases for module-body initialization behavior.
src/test/java/com/github/_1c_syntax/bsl/languageserver/types/ModuleBodyFlowTest.java Adds constructor/module-body assignment scenarios that eliminate or preserve Неопределено depending on unconditionality.
src/test/java/com/github/_1c_syntax/bsl/languageserver/types/FlowSensitiveVariableTypeTest.java Adds merge behavior test: branch-only assignment must preserve Неопределено path.
src/test/java/com/github/_1c_syntax/bsl/languageserver/types/InlineTypeCommentInferenceTest.java Adds support tests for // см. … on assignment-line (local + cross-module).
src/test/java/com/github/_1c_syntax/bsl/languageserver/types/ExpressionTypeInferencerSelfPropertyFallbackTest.java Updates expectation: unassigned Перем now yields Неопределено (not empty).
src/test/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/OScriptModuleMembersProviderTest.java Updates mocks/imports to use TrailingCommentTypeResolver.
src/test/java/com/github/_1c_syntax/bsl/languageserver/types/oscript/autumn/AutumnDependencyInjectionInferenceTest.java Adjusts expectations: “not injected” now leaves Неопределено instead of empty.
src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistrySpecializationTest.java Adds regression test: specialized members must use canonical TypeRef from registry.
src/test/java/com/github/_1c_syntax/bsl/languageserver/types/model/TypeSetTest.java Adds tests for mapRefs moving/merging decorations and returning this when no changes.
src/test/java/com/github/_1c_syntax/bsl/languageserver/types/model/MemberDescriptorSpecializeTest.java Updates to new specialize(bindings, canonicalizer) signature.
src/test/java/com/github/_1c_syntax/bsl/languageserver/types/model/MemberDescriptorFactoryTest.java Updates to new specialize(bindings, canonicalizer) signature.
src/test/java/com/github/_1c_syntax/bsl/languageserver/hover/VariableSymbolMarkupContentBuilderTest.java Updates hover content expectations: module/local vars show Тип: Неопределено.
src/test/resources/types/PeremTypeComment.bsl Adds fixtures for no-comment Перем and // см. … reference in Перем declaration.
src/test/resources/types/InlineTypeComment.bsl Adds fixtures for assignment-line // см. … references.
src/test/resources/types/ModuleVariableFlow.bsl Adds fixtures for module-body initialization (unconditional vs conditional).
src/test/resources/types/ModuleBodyFlow.os Adds fixtures for constructor initialization paths and “no assignment” behavior.
src/test/resources/types/ModuleBodyFlowEnglishConstructor.os New fixture: English-named constructor OnObjectCreate() path.
src/test/resources/types/FlowSensitiveVariableTypes.bsl Adds fixture for “declared, assigned only in branch” merge behavior.

Comment on lines +236 to +239
// Ленивые декорации приводятся при вычислении: заглядывать в них здесь означало бы
// считать то, ради отсрочки чего они и заведены.
mapKeys(lazyElements, mapper, LazyTypeSet::combine, UnaryOperator.identity()),
mapNestedKeys(lazyFields, mapper, LazyField::merge, UnaryOperator.identity())

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.

Верно, комментарий врал. Поправил в 565ad0becc: ленивая декорация теперь оборачивается — new LazyTypeSet(lazy.key(), () -> lazy.get().mapRefs(mapper)). Форсить источник для этого не нужно, приведение применяется к тому, что он вернёт при чтении, а ключ у обёртки прежний, поэтому равенство и combine не меняются. Набор с ленивыми декорациями теперь пересобирается всегда: изменилось ли их содержимое, сравнением по ключу не узнать.

Тест TypeSetTest.mapRefsAppliesToLazyDecorationOnRead проверяет обе стороны: при приведении источник не вычисляется, а при чтении ссылка приходит канонической.

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.

@coderabbitai проверь адекватность и корректность решения

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.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

type_set_test="$(fd '^TypeSetTest\.java$' src test 2>/dev/null | head -n1 || true)"
lazy_type_set="$(fd '^LazyTypeSet\.java$' src 2>/dev/null | head -n1 || true)"
lazy_field="$(fd '^LazyField\.java$' src 2>/dev/null | head -n1 || true)"

printf '%s\n' '=== outlines ==='
for file in "$lazy_type_set" "$lazy_field" "$type_set_test"; do
  if [ -n "$file" ]; then
    printf '%s\n' "--- $file"
    ast-grep outline "$file" --items all
  fi
done

printf '%s\n' '=== target test and lazy contracts ==='
rg -n -A90 -B15 'mapRefsAppliesToLazyDecorationOnRead|class LazyTypeSet|record LazyField|combine\(|equals\(|hashCode\(' \
  "$lazy_type_set" "$lazy_field" "$type_set_test" 2>/dev/null || true

Length of output: 24826


@nixel2007, решение адекватно и корректно.

mapLazy не вычисляет исходный LazyTypeSet. Он создаёт обёртку с тем же key() и применяет mapRefs(mapper) только после вызова get().

Сохранение key() корректно. LazyTypeSet.equals, hashCode и combine используют ключ. Поэтому объединение ленивых источников сохраняет прежнюю семантику.

Принудительная пересборка TypeSet при наличии ленивых декораций также корректна. Равенство LazyTypeSet не включает resolver, поэтому сравнение карт не может обнаружить изменение результата, которое создаёт обёртка.

Тест mapRefsAppliesToLazyDecorationOnRead проверяет два необходимых свойства: mapRefs не форсит источник, а результат чтения содержит каноническую ссылку. Отдельный тест для lazyFields мог бы сделать покрытие симметричным, но текущая реализация использует тот же mapLazy; это не является дефектом.

You are interacting with an AI system.

Copilot AI 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.

Pull request overview

Copilot reviewed 32 out of 32 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/main/java/com/github/_1c_syntax/bsl/languageserver/types/model/TypeSet.java:216

  • Javadoc для mapRefs говорит, что метод вернёт исходный набор, если «ни одна не изменилась», но реализация всегда пересобирает набор при наличии lazyElements/lazyFields (даже если все уже известные ссылки/ключи не изменились), чтобы обернуть ленивые декорации. Лучше уточнить контракт в @return, чтобы он соответствовал фактическому поведению.
   * @param mapper преобразование ссылки.
   * @return набор с преобразованными ссылками; исходный, если ни одна не изменилась.
   */

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

149-159: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Resolve defined types through resolveSet.

Defined types are resolved by TypeRegistry.resolveSet(String), not resolve(String, FileType), and the current accumulation collects only TypeRef values. Accumulate the resolved TypeSet directly and preserve its metadata.

🤖 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/TrailingCommentTypeResolver.java`
around lines 149 - 159, Update the defined-type resolution logic in
TrailingCommentTypeResolver to use TypeRegistry.resolveSet(String) instead of
resolve(String, FileType). Accumulate the returned TypeSet values directly,
combining them into the result while preserving their metadata; do not collect
TypeRef values or reconstruct the set with TypeSet.of.

Source: Learnings

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

62-64: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add contract Javadoc for TrailingCommentTypeResolver.

Add class-level Javadoc that describes the supported trailing comments, the TypeSet.EMPTY result for unresolved input, and mutation behavior.

As per coding guidelines, public Java APIs require contract Javadoc.

Suggested Javadoc
+/**
+ * Resolves types declared in trailing comments on variable declarations and assignments.
+ *
+ * <p>Returns {`@link` TypeSet#EMPTY} when no declared type or link resolves.
+ */
 `@Component`
 `@RequiredArgsConstructor`
 public class TrailingCommentTypeResolver implements VariableTypeSource {
🤖 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/TrailingCommentTypeResolver.java`
around lines 62 - 64, Add class-level contract Javadoc to
TrailingCommentTypeResolver describing the supported trailing comments, that
unresolved input returns TypeSet.EMPTY, and the resolver’s mutation behavior.
Keep the existing annotations and VariableTypeSource implementation unchanged.

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/TrailingCommentTypeResolver.java`:
- Around line 149-159: Update the defined-type resolution logic in
TrailingCommentTypeResolver to use TypeRegistry.resolveSet(String) instead of
resolve(String, FileType). Accumulate the returned TypeSet values directly,
combining them into the result while preserving their metadata; do not collect
TypeRef values or reconstruct the set with TypeSet.of.

---

Nitpick comments:
In
`@src/main/java/com/github/_1c_syntax/bsl/languageserver/types/TrailingCommentTypeResolver.java`:
- Around line 62-64: Add class-level contract Javadoc to
TrailingCommentTypeResolver describing the supported trailing comments, that
unresolved input returns TypeSet.EMPTY, and the resolver’s mutation behavior.
Keep the existing annotations and VariableTypeSource implementation unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 61723773-21dd-4337-8566-55dc2c707b6f

📥 Commits

Reviewing files that changed from the base of the PR and between 9a729e1 and 52304b9.

⛔ Files ignored due to path filters (2)
  • src/test/resources/types/ModuleBodyFlow.os is excluded by !src/test/resources/**
  • src/test/resources/types/ModuleVariableFlow.bsl is excluded by !src/test/resources/**
📒 Files selected for processing (14)
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/TrailingCommentTypeResolver.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/inferencer/ExpressionTypeInferencer.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/model/MemberDescriptor.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/model/TypeSet.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/PlaceholderBinder.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/RegisterTypesRegistrar.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/TypeRegistry.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/InlineTypeCommentInferenceTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/ModuleBodyFlowTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/ModuleVariableFlowTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/PeremTypeCommentInferenceTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/model/MemberDescriptorFactoryTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/model/MemberDescriptorSpecializeTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/model/TypeSetTest.java
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/PeremTypeCommentInferenceTest.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/inferencer/ExpressionTypeInferencer.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/InlineTypeCommentInferenceTest.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/ModuleBodyFlowTest.java

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Test Results

 3 936 files  ±  0   3 936 suites  ±0   1h 7m 32s ⏱️ + 2m 4s
 4 075 tests + 22   4 009 ✅ + 22   66 💤 ±0  0 ❌ ±0 
24 450 runs  +132  24 050 ✅ +132  400 💤 ±0  0 ❌ ±0 

Results for commit e96ce6d. ± Comparison against base commit 50d66d6.

This pull request removes 1 and adds 23 tests. Note that renamed tests count towards both.
com.github._1c_syntax.bsl.languageserver.types.oscript.autumn.AutumnDependencyInjectionInferenceTest ‑ returnsEmptyForUnknownCollectionName()
com.github._1c_syntax.bsl.languageserver.types.FlowSensitiveVariableTypeTest ‑ undefinedFromDeclarationSurvivesMergeWithBranchAssignment()
com.github._1c_syntax.bsl.languageserver.types.InlineTypeCommentInferenceTest ‑ seeRefToAnotherModuleFunction()
com.github._1c_syntax.bsl.languageserver.types.InlineTypeCommentInferenceTest ‑ seeRefToLocalConstructor()
com.github._1c_syntax.bsl.languageserver.types.ModuleBodyFlowTest ‑ assignmentInConstructorLeavesNoUndefined()
com.github._1c_syntax.bsl.languageserver.types.ModuleBodyFlowTest ‑ assignmentInEnglishNamedConstructorLeavesNoUndefined()
com.github._1c_syntax.bsl.languageserver.types.ModuleBodyFlowTest ‑ assignmentUnderConditionInConstructorLeavesUndefined()
com.github._1c_syntax.bsl.languageserver.types.ModuleBodyFlowTest ‑ fieldWithoutAssignmentsIsUndefined()
com.github._1c_syntax.bsl.languageserver.types.ModuleVariableFlowTest ‑ initializationInModuleBodyLeavesNoUndefined()
com.github._1c_syntax.bsl.languageserver.types.ModuleVariableFlowTest ‑ initializationUnderConditionInModuleBodyLeavesUndefined()
com.github._1c_syntax.bsl.languageserver.types.PeremTypeCommentInferenceTest ‑ localPeremWithoutCommentIsUndefined()
…

♻️ This comment has been updated with latest results.

@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/index/SymbolTypeIndex.java (1)

485-521: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Update the stale Javadoc for applyFields.

The Javadoc at Line 486 still states that fields are attached "на головной {@link TypeRef}" (onto the head TypeRef). The code below it no longer does this unconditionally: Lines 498-503 redirect field attachment to collectionElement(headRef, ...) when the head type is a collection, and only fall back to headRef for structure-like types. Line 519 confirms this by wrapping the result through base.withElement(headRef, result) for the collection case.

Update the Javadoc to describe the current contract: fields go to the collection's resolved element type when one exists, and to the head type only when it is structure-like or has no known element.

📝 Proposed Javadoc update
   /**
    * Если у описания типа есть {`@link` TypeDescription#fields() поля}
    * (декларация структуры/ТЗ ключами через {`@code` * Поле - Тип}),
-   * навесить их на головной {`@link` TypeRef}. Поле, типизированное см.-ссылкой
+   * навесить их на элемент коллекции (строку таблицы/дерева, пару «ключ-значение»
+   * и т.п.), полученный через {`@link` `#collectionElement`}, либо на головной
+   * {`@link` TypeRef} для структуроподобных типов. Поле, типизированное см.-ссылкой
    * на локальную функцию, навешивается лениво ({`@link` TypeSet#withLazyField}) —
    * для поддержки рекурсивных структур.
    */

As per coding guidelines, "Javadoc классов и методов должен описывать контракт: параметры, результат, инварианты и побочные эффекты" and general Java guideline to "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/index/SymbolTypeIndex.java`
around lines 485 - 521, Update the Javadoc for applyFields to describe that
fields attach to the resolved collection element type when collectionElement
returns one, while falling back to the head TypeRef for structure-like types or
types without a known element; retain the notes about lazy local-function
references and recursive structures.

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/index/SymbolTypeIndex.java`:
- Around line 485-521: Update the Javadoc for applyFields to describe that
fields attach to the resolved collection element type when collectionElement
returns one, while falling back to the head TypeRef for structure-like types or
types without a known element; retain the notes about lazy local-function
references and recursive structures.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 72397369-8216-4f2b-a2ed-129ad310d018

📥 Commits

Reviewing files that changed from the base of the PR and between 44c6ac3 and b6c733d.

⛔ Files ignored due to path filters (1)
  • src/test/resources/types/ValueTableColumnsFields.bsl is excluded by !src/test/resources/**
📒 Files selected for processing (3)
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/index/SymbolTypeIndex.java
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/inferencer/ExpressionTypeInferencer.java
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/ValueTableColumnsFieldsInferenceTest.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/types/inferencer/ExpressionTypeInferencer.java

* @param variable переменная.
* @return {@code true}, если переменная объявлена записью {@code Перем}.
*/
private static boolean declaredByPerem(VariableSymbol variable) {

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.

byVar

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.

Переименовал в declaredByVar — смеси языков в идентификаторе больше нет.

*/
private static boolean declaredByPerem(VariableSymbol variable) {
var kind = variable.getKind();
return kind == VariableKind.LOCAL || kind == VariableKind.MODULE;

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.

Global тоже объявляется через Перем

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.

Верно, добавил VariableKind.GLOBAL в предикат. Сейчас этот вид, правда, нигде не проставляется — в VariableSymbolComputer переменная уровня модуля получает MODULE, а GLOBAL только проверяется (WorkspaceSymbolIndex, DocumentSymbolProvider, UseLessForEachDiagnostic). Но правило от этого не зависит: объявлена записью «Перем» — значит до присваивания там «Неопределено».

var enclosingMethod = enclosingMethod(symbolTree, position);
var runsBeforeAnyUse = enclosingMethod.isEmpty()
|| Methods.isOscriptClassConstructorName(enclosingMethod.get().getName());
if (runsBeforeAnyUse && unconditional(owner, position)) {

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.

А по cfg нет смысла собрать? Как это делают другие части инференсера

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.

Смысл есть, и точность выше. Сейчас проверка синтаксическая — обход предков узла до Если/Пока/Для/Попытка, — и она консервативна: случай, где присваивание есть в обеих ветках,

Если Условие Тогда
    Кэш = Новый Соответствие;
Иначе
    Кэш = Новый Массив;
КонецЕсли;

она считает условным, хотя после КонецЕсли значение присвоено на любом пути. На графе это ровно доминирование выхода, и такой случай разбирался бы правильно.

Инфраструктура рядом: VariableFlowAnalyzer и FlowLayout уже работают поверх ControlFlowGraphIndex, у FlowLayout есть отображение позиции в оператор и его вершину. Загвоздка в том, что declaredTypes отвечает про переменную без привязки к телу и вызывается до расчёта по потоку, поэтому граф нужного тела придётся доставать отдельно (тело мы и так находим — это либо метод, либо тело модуля).

Делать в этом PR или отдельной задачей? PR уже довольно широкий, а правка заметная — она меняет и место, откуда берётся ответ, и стоимость: на каждую переменную модуля без объявленных типов добавится обращение к индексу графов.

*/
@Component
@RequiredArgsConstructor
public class TrailingCommentTypeResolver implements VariableTypeSource {

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.

А почему вообще только trailing комментарий разбирается? Что не так с комментарием над самой переменной?

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.

Ничего не так — просто не разбирался. Сделал, и заодно выяснилась причина, по которой само оно не работало: комментарий, дописанный в конце предыдущей строки кода, парсер отдаёт и как описание следующего объявления — по строкам он ведь стоит выше. На фикстуре это сразу поймал тест:

Перем ПараметрыВызова; // Булево
Перем БезКомментария;      // ← получал тип Булево от соседа

Отличить можно по началу описания: своё начинается со своей строки, чужое висячее — после кода. С этой проверкой оба случая работают, висячий комментарий остаётся приоритетнее. Класс переименован в CommentTypeResolver — он больше не только про висячий комментарий. Тест PeremTypeCommentInferenceTest.moduleVarWithTypeCommentAboveDeclaration.

nixel2007 and others added 6 commits August 2, 2026 08:13
Шаблон вида «СправочникСсылка.<Имя справочника>» приходит из синтакс-помощника
платформенным, а конфигурационные типы регистрируются своим видом. Структурная
специализация сохраняла вид шаблона, поэтому за одним именем оказывались две
ссылки, различающиеся только видом: объединение наборов их не схлопывало и тип
показывался дважды.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MnWpDdNSEFohPZHG6voe6y
…елено»

По методической рекомендации «Типизация кода» переменная, объявленная записью
«Перем» и без иных сведений о типе, содержит «Неопределено» — это её значение,
а не отсутствие сведений. В точке слияния путей оно остаётся, если хотя бы один
путь до присваивания не дошёл. Исключения, где это состояние наблюдать неоткуда:
присваивание в теле модуля (оно отрабатывает раньше любой процедуры) и в
«ПриСозданииОбъекта» (конструктор выполняется при создании объекта).

Заодно два резолвера висячих комментариев — у члена и у переменной — объединены
в «TrailingCommentTypeResolver»: они разбирали один и тот же вид комментария и
разошлись в возможностях, ссылку «// см. Функция» умел только первый. Теперь она
работает и в объявлении переменной, и в строке присваивания.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MnWpDdNSEFohPZHG6voe6y
Сборка результата через «TypeSet.of» оставляла одни ссылки: поля объекта и типы
элементов коллекции отбрасывались. Приведение переехало в «TypeSet.mapRefs»,
который переносит декорации на новую ссылку, а если несколько исходных ссылок
сходятся в одну каноническую — сливает их.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MnWpDdNSEFohPZHG6voe6y
Сравнение со строкой «ПриСозданииОбъекта» не видело английского написания.
Используется общая проверка «Methods.isOscriptClassConstructorName», а метод в
позиции присваивания ищется спуском по дереву символов, а не перебором методов.

Объявленное о переменной расчёт по потоку спрашивает многократно за один запрос,
а у переменной модуля за ответом стоит обход индекса ссылок — ответ запоминается
на время запроса, как это уже сделано для операторов-мутаторов.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MnWpDdNSEFohPZHG6voe6y
…еским

Перегруз без приведения оставлял дверь, через которую в members попадали
неканонические ссылки: подстановка сохраняет вид шаблона, поэтому платформенный
шаблон давал платформенную ссылку и на конфигурационный тип. Приведение получили
и остальные места специализации — разворачивание generic-членов, регистры и
подстановка единственного плейсхолдера.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MnWpDdNSEFohPZHG6voe6y
Присваивание внутри условия, цикла или попытки может не выполниться, поэтому
доказательством того, что состояние от объявления наблюдать неоткуда, оно не
является — ни в теле модуля, ни в конструкторе.

Приведение ссылок к каноническим заодно заходит внутрь декораций: типы элементов
коллекции и типы полей объекта приводятся тем же преобразованием.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MnWpDdNSEFohPZHG6voe6y
nixel2007 and others added 8 commits August 2, 2026 08:13
Ленивая декорация оборачивается: преобразование применяется к тому, что её
источник вернёт при чтении, форсить его для этого не нужно. Ключ у обёртки
прежний, поэтому равенство и слияние ленивых ссылок не меняются.

Заодно замечания статического анализа: объявления рядом с использованием, явные
типы параметров лямбд, ссылки на методы вместо лямбд.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MnWpDdNSEFohPZHG6voe6y
Колонки, объявленные звёздочками в описании возвращаемого значения
(«ТаблицаЗначений: * Колонка - Тип»), навешивались на саму таблицу. Обращения
«Таблица.Колонка» в 1С нет — колонки видны у строки, поэтому строка, полученная
из «Добавить()» или обходом «Для Каждого», о них не знала и каждое обращение к
колонке становилось находкой «нет метода или свойства».

Описанные колонки навешиваются на тип элемента таблицы — так же, как это уже
делает разбор «Колонки.Добавить» рядом с кодом.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MnWpDdNSEFohPZHG6voe6y
Правило распространено с таблицы значений на все коллекции: собственные свойства
бывают только у структуроподобных типов, у остальных звёздочки в описании
описывают элемент. Так работают дерево значений, табличная часть, коллекции
формы и соответствие, у которого «Ключ» и «Значение» — свойства пары, а не
самого соответствия; обращения к нему через точку в 1С нет.

Дерево значений само не обходится, его строки лежат в отдельной коллекции
«Строки» — уточнение строки переезжает внутрь неё.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MnWpDdNSEFohPZHG6voe6y
Правило «поля описания принадлежат элементу» сплошным быть не может: у коллекции
элементов формы и у выборки из результата запроса обращение по имени свойства к
ним самим законное, и перенос ломал его. Список типов, у которых собственных
свойств нет, задан явно: таблица и дерево значений, табличная часть, коллекции
формы, соответствие.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MnWpDdNSEFohPZHG6voe6y
Новые места специализации из типов форм переведены на единственную сигнатуру
с приведением — как и все остальные.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MnWpDdNSEFohPZHG6voe6y
Разбирался только висячий комментарий, хотя парсер отдаёт типы и у описания над
записью «Перем». Причина, по которой это не работало само собой: комментарий,
дописанный в конце предыдущей строки кода, парсер отдаёт и как описание
следующего объявления — по строкам он стоит выше. Отличается по началу: своё
описание начинается со своей строки, чужое висячее — после кода.

Висячий комментарий остаётся приоритетнее: он стоит вплотную к объявлению.
Класс переименован — он больше не только про висячий комментарий.

Заодно по замечаниям ревью: глобальная переменная тоже объявляется записью
«Перем», поэтому попадает под то же правило, а предикат назван без смеси языков.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MnWpDdNSEFohPZHG6voe6y
Компенсация была нужна, пока комментарий предыдущей строки попадал в описание
следующего символа. Утечка исправлена в сборе комментариев (#4360), и различать
своё описание по началу строки больше не требуется.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MnWpDdNSEFohPZHG6voe6y
@nixel2007

Copy link
Copy Markdown
Member Author

Разнёс на стек из трёх независимых правок — так их проще смотреть и вливать по одной:

Конечное состояние стека посимвольно совпадает с тем, что было здесь.

@nixel2007 nixel2007 closed this Aug 2, 2026
@sonarqubecloud

sonarqubecloud Bot commented Aug 2, 2026

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.

3 participants