Skip to content

feat: new diagnostic InsertionWithoutChangeAndValidate - #4397

Open
pravets wants to merge 1 commit into
1c-syntax:developfrom
pravets:feat/new-diagnostic-insertion-without-change-and-validate
Open

feat: new diagnostic InsertionWithoutChangeAndValidate#4397
pravets wants to merge 1 commit into
1c-syntax:developfrom
pravets:feat/new-diagnostic-insertion-without-change-and-validate

Conversation

@pravets

@pravets pravets commented Aug 3, 2026

Copy link
Copy Markdown

Описание

Новая диагностика InsertionWithoutChangeAndValidate — находит использование директив #Вставка / #КонецВставки внутри методов без аннотации &ИзменениеИКонтроль.

Без этой аннотации платформа 1С не может скомпилировать модуль — вставка кода расширения разрешена только в методах, явно объявленных как изменяющие.

Closes #3815

Метаданные

Параметр Значение
Тип Ошибка (ERROR)
Важность Критическая (CRITICAL)
Время исправления 1 минута
Тэги ERROR
scope BSL
Активирована по умолчанию Да

Как работает

  1. Обходит все методы модуля через symbol tree
  2. Пропускает методы с аннотацией &ИзменениеИКонтроль
  3. Ищет токены PREPROC_INSERT / PREPROC_ENDINSERT в теле метода
  4. Если есть вставка без аннотации — выдаёт diagnostic на имени метода

Состав PR

  • Java-класс диагностики
  • _ru.properties / _en.properties
  • Документация (ru + en)
  • Тест + фикстура

Чеклист

  • Тесты проходят локально
  • Архитектурные тесты (ArchUnit) проходят
  • Документация на русском и английском

Summary by CodeRabbit

  • New Features

    • Added a new diagnostic that flags insertion directives used without the required change-and-validate annotation.
    • Added localized diagnostic messages in English and Russian.
  • Documentation

    • Added usage guidance with incorrect and correct examples, plus a reference to the applicable module structure standard.
  • Tests

    • Added coverage verifying detection and source highlighting for the diagnostic.

Detects #Insert / #EndInsert directives used inside a method
without &ChangeAndValidate annotation, which causes compilation
error in 1C:Enterprise configuration extensions.

- Diagnostic type: ERROR, severity: CRITICAL, minutesToFix: 1
- Checks all PREPROC_INSERT / PREPROC_ENDINSERT tokens within
  method bodies
- Skips methods with CHANGEANDVALIDATE annotation
- RU/EN messages, docs, and test fixture included
@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The change adds a critical diagnostic for #Вставка/#Insert directives used in methods without &ИзменениеИКонтроль/&ChangeAndValidate. It includes localized messages, documentation in two languages, and a focused Java test.

Changes

Insertion directive diagnostic

Layer / File(s) Summary
Diagnostic detection and localization
src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/InsertionWithoutChangeAndValidateDiagnostic.java, src/main/resources/.../InsertionWithoutChangeAndValidateDiagnostic_*.properties
The new diagnostic scans methods without the required annotation, detects insertion directives, and reports the method name range with localized messages.
Documentation and test validation
src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/InsertionWithoutChangeAndValidateDiagnosticTest.java, docs/diagnostics/InsertionWithoutChangeAndValidate.md, docs/en/diagnostics/InsertionWithoutChangeAndValidate.md
The test verifies one diagnostic at the expected range. Russian and English documentation describe incorrect and correct method examples and reference Standard 455.

Estimated code review effort: 2 (Simple) | ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the primary change: adding the InsertionWithoutChangeAndValidate diagnostic.
Linked Issues check ✅ Passed The implementation detects both insertion directives without the required annotation and includes the requested severity, tag, fix estimate, documentation, and tests.
Out of Scope Changes check ✅ Passed The implementation, localization, documentation, and tests directly support the linked diagnostic objective.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

🧹 Nitpick comments (3)
src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/InsertionWithoutChangeAndValidateDiagnostic.java (2)

54-55: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Keep the diagnostic lifecycle hook protected.

The base diagnostic lifecycle initializes documentContext, clears diagnostics, and then calls check(). This override widens the hook to public, so callers can invoke it without that lifecycle and trigger a null context or stale diagnostics. Use protected void check() to match the base contract. The repository base class currently declares this hook as protected. (raw.githubusercontent.com)

Proposed fix
   `@Override`
-  public void check() {
+  protected void check() {
🤖 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/diagnostics/InsertionWithoutChangeAndValidateDiagnostic.java`
around lines 54 - 55, Change the check() override in
InsertionWithoutChangeAndValidateDiagnostic from public to protected so it
matches AbstractDiagnostic’s lifecycle hook visibility and cannot be called
outside the initialized diagnostic flow.

Source: MCP tools


56-69: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Avoid rescanning all tokens for every method.

The inner stream scans the complete token list for each unannotated method. This can make the diagnostic scale as O(methods × tokens). Filter insertion positions once and return early when the document has no insertion directives.

Proposed refactor
   var tokens = documentContext.getTokens();
+  var insertionPositions = tokens.stream()
+    .filter(token -> token.getType() == BSLLexer.PREPROC_INSERT
+      || token.getType() == BSLLexer.PREPROC_ENDINSERT)
+    .map(token -> new Position(token.getLine() - 1, 0))
+    .toList();
+  if (insertionPositions.isEmpty()) {
+    return;
+  }

   documentContext.getSymbolTree().getMethods()
...
-      .filter(method -> tokens.stream()
-        .filter(token -> token.getType() == BSLLexer.PREPROC_INSERT
-          || token.getType() == BSLLexer.PREPROC_ENDINSERT)
-        .anyMatch(token -> {
-          var tokenPosition = new Position(token.getLine() - 1, 0);
-          return Ranges.containsPosition(method.getRange(), tokenPosition);
-        }))
+      .filter(method -> insertionPositions.stream()
+        .anyMatch(position -> Ranges.containsPosition(method.getRange(), position)))
🤖 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/diagnostics/InsertionWithoutChangeAndValidateDiagnostic.java`
around lines 56 - 69, Update the diagnostic flow around the symbol-tree method
stream to precompute insertion and end-insertion token positions once, return
immediately when none exist, and have each method check only those filtered
positions instead of rescanning the complete tokens list. Preserve the existing
CHANGEANDVALIDATE annotation exclusion and range-matching behavior.
src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/InsertionWithoutChangeAndValidateDiagnosticTest.java (1)

38-47: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add coverage for the #КонецВставки directive form.

INSERTION_WITHOUT_CHANGE_AND_VALIDATE currently asserts only one aggregate diagnostic and one #Вставка range. Since the diagnostic accepts both PREPROC_INSERT and PREPROC_ENDINSERT, add a separate annotated procedure/function that contains only #КонецВставки and assert its diagnostic/range instead of relying on the existing aggregate case.

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

In
`@src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/InsertionWithoutChangeAndValidateDiagnosticTest.java`
around lines 38 - 47, Extend the test fixture and test method test() to include
a separate annotated procedure or function containing only `#КонецВставки`, then
assert its diagnostic and exact range independently. Keep the existing `#Вставка`
coverage and aggregate diagnostic assertions, ensuring both PREPROC_INSERT and
PREPROC_ENDINSERT forms are validated.

Source: Coding guidelines

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

Nitpick comments:
In
`@src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/InsertionWithoutChangeAndValidateDiagnostic.java`:
- Around line 54-55: Change the check() override in
InsertionWithoutChangeAndValidateDiagnostic from public to protected so it
matches AbstractDiagnostic’s lifecycle hook visibility and cannot be called
outside the initialized diagnostic flow.
- Around line 56-69: Update the diagnostic flow around the symbol-tree method
stream to precompute insertion and end-insertion token positions once, return
immediately when none exist, and have each method check only those filtered
positions instead of rescanning the complete tokens list. Preserve the existing
CHANGEANDVALIDATE annotation exclusion and range-matching behavior.

In
`@src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/InsertionWithoutChangeAndValidateDiagnosticTest.java`:
- Around line 38-47: Extend the test fixture and test method test() to include a
separate annotated procedure or function containing only `#КонецВставки`, then
assert its diagnostic and exact range independently. Keep the existing `#Вставка`
coverage and aggregate diagnostic assertions, ensuring both PREPROC_INSERT and
PREPROC_ENDINSERT forms are validated.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 7a632a1b-5457-43f9-bf76-856b74935730

📥 Commits

Reviewing files that changed from the base of the PR and between 0b45e3b and 913dd5b.

⛔ Files ignored due to path filters (1)
  • src/test/resources/diagnostics/InsertionWithoutChangeAndValidateDiagnostic.bsl is excluded by !src/test/resources/**
📒 Files selected for processing (6)
  • docs/diagnostics/InsertionWithoutChangeAndValidate.md
  • docs/en/diagnostics/InsertionWithoutChangeAndValidate.md
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/InsertionWithoutChangeAndValidateDiagnostic.java
  • src/main/resources/com/github/_1c_syntax/bsl/languageserver/diagnostics/InsertionWithoutChangeAndValidateDiagnostic_en.properties
  • src/main/resources/com/github/_1c_syntax/bsl/languageserver/diagnostics/InsertionWithoutChangeAndValidateDiagnostic_ru.properties
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/InsertionWithoutChangeAndValidateDiagnosticTest.java

.filter(method -> method.getAnnotations().stream()
.map(Annotation::getKind)
.noneMatch(kind -> kind == AnnotationKind.CHANGEANDVALIDATE))
.filter(method -> tokens.stream()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Вот тут точно не прокатит. Это n*m поиск (токены в документе, количество методов).
Кажется, дешевле будет подписаться на узлы preproc insert/end и проверить что метод не имеет нужной директивы

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.

[NEW] Использование #Вставка #КонецВставки в процедуре без #ИзменениеИКонтроль

2 participants