From ca156ffdb81381cbbca944479974fdf206fd4484 Mon Sep 17 00:00:00 2001 From: Ivan Karlo Date: Sun, 7 Jun 2026 12:30:02 +0300 Subject: [PATCH 1/2] =?UTF-8?q?feat(diagnostics):=20=D1=83=D0=BB=D1=83?= =?UTF-8?q?=D1=87=D1=88=D0=B5=D0=BD=D0=BE=20=D0=BE=D0=B1=D0=BD=D0=B0=D1=80?= =?UTF-8?q?=D1=83=D0=B6=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BD=D0=B5=D0=B8=D1=81?= =?UTF-8?q?=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D1=83=D0=B5=D0=BC=D1=8B=D1=85=20?= =?UTF-8?q?=D0=BB=D0=BE=D0=BA=D0=B0=D0=BB=D1=8C=D0=BD=D1=8B=D1=85=20=D0=BF?= =?UTF-8?q?=D0=B5=D1=80=D0=B5=D0=BC=D0=B5=D0=BD=D0=BD=D1=8B=D1=85=20=D0=B4?= =?UTF-8?q?=D0=BB=D1=8F=20=D1=81=D1=87=D0=B5=D1=82=D1=87=D0=B8=D0=BA=D0=BE?= =?UTF-8?q?=D0=B2=20=D1=86=D0=B8=D0=BA=D0=BB=D0=BE=D0=B2=20for?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Добавлена ​​функциональность в UnusedLocalVariableDiagnostic для исключения счетчиков циклов for из списка неиспользуемых. Введены методы для определения диапазонов счетчиков циклов for и проверки, является ли переменная счетчиком циклов for. Обновлены тестовые ресурсы. --- .../UnusedLocalVariableDiagnostic.java | 26 +++++++++++++++++++ .../UnusedLocalVariableDiagnostic.bsl | 8 ++++++ 2 files changed, 34 insertions(+) diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UnusedLocalVariableDiagnostic.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UnusedLocalVariableDiagnostic.java index a82b944db3f..178f635b9f7 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UnusedLocalVariableDiagnostic.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UnusedLocalVariableDiagnostic.java @@ -21,6 +21,7 @@ */ package com.github._1c_syntax.bsl.languageserver.diagnostics; +import com.github._1c_syntax.bsl.languageserver.context.symbol.VariableSymbol; import com.github._1c_syntax.bsl.languageserver.context.symbol.variable.VariableKind; import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticMetadata; import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticSeverity; @@ -28,11 +29,18 @@ import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticType; import com.github._1c_syntax.bsl.languageserver.references.ReferenceIndex; import com.github._1c_syntax.bsl.languageserver.references.model.OccurrenceType; +import com.github._1c_syntax.bsl.languageserver.utils.Ranges; +import com.github._1c_syntax.bsl.languageserver.utils.Trees; +import com.github._1c_syntax.bsl.parser.BSLParser; import com.github._1c_syntax.bsl.types.ModuleType; import lombok.RequiredArgsConstructor; +import org.eclipse.lsp4j.Range; +import java.util.Collection; import java.util.EnumSet; +import java.util.Objects; import java.util.Set; +import java.util.stream.Collectors; @DiagnosticMetadata( type = DiagnosticType.CODE_SMELL, @@ -63,9 +71,11 @@ public class UnusedLocalVariableDiagnostic extends AbstractDiagnostic { @Override public void check() { + Set forLoopCounterRanges = getForLoopCounterRanges(); documentContext.getSymbolTree().getVariables().stream() .filter(variable -> CHECKING_VARIABLE_KINDS.contains(variable.getKind())) .filter(variable -> !variable.isExport()) + .filter(variable -> !isForLoopCounter(variable, forLoopCounterRanges)) .filter(variable -> referenceIndex.getReferencesTo(variable).stream() .filter(ref -> ref.occurrenceType() == OccurrenceType.REFERENCE).findFirst().isEmpty() ) @@ -73,4 +83,20 @@ public void check() { variable.getSelectionRange(), info.getMessage(variable.getName())) ); } + + private Set getForLoopCounterRanges() { + return Trees.findAllRuleNodes(documentContext.getAst(), BSLParser.RULE_forStatement).stream() + .map(BSLParser.ForStatementContext.class::cast) + .map(BSLParser.ForStatementContext::IDENTIFIER) + .filter(Objects::nonNull) + .map(Ranges::create) + .collect(Collectors.toSet()); + } + + private boolean isForLoopCounter(VariableSymbol variable, + Collection forLoopCounterRanges) { + return referenceIndex.getReferencesTo(variable).stream() + .filter(ref -> ref.occurrenceType() == OccurrenceType.DEFINITION) + .anyMatch(ref -> forLoopCounterRanges.contains(ref.selectionRange())); + } } diff --git a/src/test/resources/diagnostics/UnusedLocalVariableDiagnostic.bsl b/src/test/resources/diagnostics/UnusedLocalVariableDiagnostic.bsl index b90f47627b3..65a66edf297 100644 --- a/src/test/resources/diagnostics/UnusedLocalVariableDiagnostic.bsl +++ b/src/test/resources/diagnostics/UnusedLocalVariableDiagnostic.bsl @@ -99,3 +99,11 @@ Сообщить(Комментарий); +Процедура ТестСчетчикаЦикла(КоличествоПопыток) + + Для НомерПопытки = 1 По КоличествоПопыток Цикл + ВыполнитьДействие(); + КонецЦикла; + +КонецПроцедуры + From dedbd7ccd0bcd1699f08db60e2b803260726e432 Mon Sep 17 00:00:00 2001 From: Ivan Karlo Date: Sun, 7 Jun 2026 15:28:17 +0300 Subject: [PATCH 2/2] =?UTF-8?q?docs(diagnostics):=20=D0=B4=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D1=82=D1=8C=20=D0=BA=D0=BE=D0=BC=D0=BC=D0=B5?= =?UTF-8?q?=D0=BD=D1=82=D0=B0=D1=80=D0=B8=D0=B8=20=D0=BA=20=D0=BC=D0=B5?= =?UTF-8?q?=D1=82=D0=BE=D0=B4=D0=B0=D0=BC=20=D0=B2=20UnusedLocalVariableDi?= =?UTF-8?q?agnostic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Добавлены Javadoc комментарии к методам класса UnusedLocalVariableDiagnostic, описывающие их функциональность и параметры. --- .../UnusedLocalVariableDiagnostic.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UnusedLocalVariableDiagnostic.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UnusedLocalVariableDiagnostic.java index 178f635b9f7..b71e37d686c 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UnusedLocalVariableDiagnostic.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UnusedLocalVariableDiagnostic.java @@ -42,6 +42,13 @@ import java.util.Set; import java.util.stream.Collectors; +/** + * Диагностика неиспользуемых локальных и модульных переменных. + * + * Срабатывает, если переменная объявлена, но к ней нет обращений по ссылке. + * Счётчик цикла {@code Для} не считается неиспользуемым, даже если он не + * упоминается в теле цикла. + */ @DiagnosticMetadata( type = DiagnosticType.CODE_SMELL, severity = DiagnosticSeverity.MAJOR, @@ -69,6 +76,9 @@ public class UnusedLocalVariableDiagnostic extends AbstractDiagnostic { VariableKind.DYNAMIC ); + /** + * Ищет объявленные, но неиспользуемые переменные модуля и метода. + */ @Override public void check() { Set forLoopCounterRanges = getForLoopCounterRanges(); @@ -84,6 +94,11 @@ public void check() { ); } + /** + * Возвращает диапазоны имён переменных-счётчиков в конструкциях {@code Для ... По ... Цикл}. + * + * @return множество диапазонов идентификаторов счётчиков цикла в текущем модуле + */ private Set getForLoopCounterRanges() { return Trees.findAllRuleNodes(documentContext.getAst(), BSLParser.RULE_forStatement).stream() .map(BSLParser.ForStatementContext.class::cast) @@ -93,6 +108,13 @@ private Set getForLoopCounterRanges() { .collect(Collectors.toSet()); } + /** + * Проверяет, что переменная объявлена как счётчик цикла {@code Для}. + * + * @param variable проверяемая переменная + * @param forLoopCounterRanges диапазоны имён счётчиков цикла + * @return {@code true}, если переменная определена в заголовке цикла {@code Для} + */ private boolean isForLoopCounter(VariableSymbol variable, Collection forLoopCounterRanges) { return referenceIndex.getReferencesTo(variable).stream()