diff --git a/docs/contributing/DiagnosticStructure.md b/docs/contributing/DiagnosticStructure.md index a312a01d2a2..f98512c41f9 100644 --- a/docs/contributing/DiagnosticStructure.md +++ b/docs/contributing/DiagnosticStructure.md @@ -45,11 +45,13 @@ - Тип диагностики `type` и ее важность `severity`, для каждой диагностики обязательно их определение. Для того, чтобы правильно выбрать тип и важность диагностики, можно обратиться к [статье](DiagnosticTypeAndSeverity.md). - Время на исправление замечания `minutesToFix` (по умолчанию 0). Данное значение используется при расчете общего техдолга проекта в трудозатрах на исправление всех замечаний (сумма времени на исправление по всем обнаруженным замечаниям). Стоит указывать время, максимально реалистичное, которое разработчик должен потратить на исправление. +- С помощью параметра `extraMinForComplexity` можно динамически увеличивать время на исправление замечания для диагностик, в которых учитывается несколько нарушающих правило мест, например при расчете сложности метода. - Набор тэгов `tag` диагностики, указывающих группы, к котором она относится. Подробнее о тэга в [статье](DiagnosticTag.md). - Границы применимости `scope` (по умолчанию `ALL`, т.е. без ограничения). BSL LS поддерживает несколько языков (oscript и bsl) и диагностики могут применяться как к одному конкретному языку, так и ко всем сразу. - Активность правила по-умолчанию `activatedByDefault` (по умолчанию `Истина`). При разработке экспериментальных, спорных либо не применимых в большинстве проектов, стоит по умолчанию отключать диагностику, активацию выполнит конечный пользователь решения. - Режим совместимости `compatibilityMode`, по которому фильтруются диагностики при использовании метаданных. По умолчанию `UNDEFINED`. - +- Список типов модулей `modules` для возможности ограничить анализируемую диагностикой область +- Признак возможности установить замечания на весь проект `canLocateOnProject`. Используется для диагностик не связанных с модулем исходного кода. На данный момент опция воспринимается только SonarQube, остальные инструменты игнорируют. Последние два могут быть опущены. Пример аннотации @@ -64,8 +66,14 @@ compatibilityMode = DiagnosticCompatibilityMode.COMPATIBILITY_MODE_8_3_3, // Режим проверки совместимости с 8.3.3 tags = { DiagnosticTag.STANDARD // Относится к диагностикам нарушения стандарта 1С - } + }, + modules = { + ModuleType.CommonModule // Анализируются только общие модули + }, + canLocateOnProject = false, // Замечание будет размещено только в привязке к модулю + extraMinForComplexity = 1 // За каждую дополнительную позицию замечания (`DiagnosticRelatedInformation`) будет добавлено по одной минуте ) + ``` Класс должен реализовывать интерфейс `BSLDiagnostic`. Если диагностика основывается на AST дереве, то класс реализации должен быть унаследован от одного из классов ниже, реализующих `BSLDiagnostic`: diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/CognitiveComplexityDiagnostic.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/CognitiveComplexityDiagnostic.java index fadb587011d..f7d9bd1bfc9 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/CognitiveComplexityDiagnostic.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/CognitiveComplexityDiagnostic.java @@ -46,7 +46,8 @@ minutesToFix = 15, tags = { DiagnosticTag.BRAINOVERLOAD - } + }, + extraMinForComplexity = 1 ) public class CognitiveComplexityDiagnostic extends AbstractVisitorDiagnostic { @@ -99,28 +100,6 @@ public ParseTree visitSub(BSLParser.SubContext ctx) { Integer methodComplexity = documentContext.getCognitiveComplexityData().getMethodsComplexity().get(methodSymbol); if (methodComplexity > complexityThreshold) { - - List relatedInformation = new ArrayList<>(); - - relatedInformation.add(RelatedInformation.create( - documentContext.getUri(), - methodSymbol.getSubNameRange(), - info.getMessage(methodSymbol.getName(), methodComplexity, complexityThreshold) - )); - - List secondaryLocations = - documentContext.getCognitiveComplexityData().getMethodsComplexitySecondaryLocations().get(methodSymbol); - - secondaryLocations.stream() - .map((ComplexitySecondaryLocation secondaryLocation) -> - RelatedInformation.create( - documentContext.getUri(), - secondaryLocation.getRange(), - secondaryLocation.getMessage() - ) - ) - .collect(Collectors.toCollection(() -> relatedInformation)); - diagnosticStorage.addDiagnostic( methodSymbol.getSubNameRange(), info.getMessage(methodSymbol.getName(), methodComplexity, complexityThreshold), diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/CyclomaticComplexityDiagnostic.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/CyclomaticComplexityDiagnostic.java index f9454294a40..569d96ddbb9 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/CyclomaticComplexityDiagnostic.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/CyclomaticComplexityDiagnostic.java @@ -46,7 +46,8 @@ minutesToFix = 25, tags = { DiagnosticTag.BRAINOVERLOAD - } + }, + extraMinForComplexity = 1 ) public class CyclomaticComplexityDiagnostic extends AbstractVisitorDiagnostic { private static final int COMPLEXITY_THRESHOLD = 20; diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/DiagnosticStorage.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/DiagnosticStorage.java index e0650d657ca..34f7f982e84 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/DiagnosticStorage.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/DiagnosticStorage.java @@ -209,10 +209,10 @@ public void addDiagnostic( } public void addDiagnostic(ParseTree tree) { - if (tree instanceof BSLParserRuleContext) { - addDiagnostic((BSLParserRuleContext) tree); - } else if (tree instanceof TerminalNode) { - addDiagnostic((TerminalNode) tree); + if (tree instanceof BSLParserRuleContext parserRuleContext) { + addDiagnostic(parserRuleContext); + } else if (tree instanceof TerminalNode terminalNode) { + addDiagnostic(terminalNode); } else { throw new IllegalArgumentException("Unsupported parameter type " + tree); } @@ -253,5 +253,4 @@ private static Diagnostic createDiagnostic( } return diagnostic; } - } diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/TransferringParametersBetweenClientAndServerDiagnostic.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/TransferringParametersBetweenClientAndServerDiagnostic.java index 8997f5bbf6a..0faad5af051 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/TransferringParametersBetweenClientAndServerDiagnostic.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/TransferringParametersBetweenClientAndServerDiagnostic.java @@ -106,10 +106,11 @@ private List calcNotAssignedParams(MethodSymbol method) { return calcNotAssignedParams(method, parameterDefinitions); } - private List calcNotAssignedParams(MethodSymbol method, List parameterDefinitions) { + private List calcNotAssignedParams(MethodSymbol method, + List parameterDefinitions) { return parameterDefinitions.stream() .filter(parameterDefinition -> isAssignedParam(method, parameterDefinition)) - .collect(Collectors.toUnmodifiableList()); + .toList(); } private boolean isAssignedParam(MethodSymbol method, ParameterDefinition parameterDefinition) { @@ -118,7 +119,8 @@ private boolean isAssignedParam(MethodSymbol method, ParameterDefinition paramet .anyMatch(ref -> ref.getOccurrenceType() == OccurrenceType.DEFINITION)); } - private static Stream getVariableByParameter(MethodSymbol method, ParameterDefinition parameterDefinition) { + private static Stream getVariableByParameter(MethodSymbol method, + ParameterDefinition parameterDefinition) { return method.getChildren().stream() // в будущем могут появиться и другие символы, подчиненные методам .filter(sourceDefinedSymbol -> sourceDefinedSymbol.getSymbolKind() == SymbolKind.Variable) @@ -159,7 +161,7 @@ private static boolean isEqualCompilerDirective(MethodSymbol method) { private static List getMethodParamsByRef(MethodSymbol methodSymbol) { return methodSymbol.getParameters().stream() .filter(parameterDefinition -> !parameterDefinition.isByValue()) - .collect(Collectors.toUnmodifiableList()); + .toList(); } private static List getRelatedInformation(List references) { diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/metadata/DiagnosticInfo.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/metadata/DiagnosticInfo.java index 49960d4cb61..85b36f0d3f5 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/metadata/DiagnosticInfo.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/metadata/DiagnosticInfo.java @@ -198,6 +198,10 @@ public boolean canLocateOnProject() { return diagnosticMetadata.canLocateOnProject(); } + public double getExtraMinForComplexity() { + return diagnosticMetadata.extraMinForComplexity(); + } + public Map getDefaultConfiguration() { return diagnosticParameters.stream() .collect(Collectors.toMap(DiagnosticParameterInfo::getName, DiagnosticParameterInfo::getDefaultValue)); diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/metadata/DiagnosticMetadata.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/metadata/DiagnosticMetadata.java index 934d7aac59b..ad4c2979aa3 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/metadata/DiagnosticMetadata.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/metadata/DiagnosticMetadata.java @@ -83,4 +83,9 @@ * Замечания диагностики могут быть прикреплены на уровень анализируемого проекта (в частности в SonarQube) */ boolean canLocateOnProject() default false; + + /** + * Надбавка ко времени исправления замечания за повышенную сложность + */ + double extraMinForComplexity() default 0; } diff --git a/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/CyclomaticComplexityDiagnosticTest.java b/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/CyclomaticComplexityDiagnosticTest.java index a035a178b84..7f7673f2ea5 100644 --- a/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/CyclomaticComplexityDiagnosticTest.java +++ b/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/CyclomaticComplexityDiagnosticTest.java @@ -37,6 +37,8 @@ class CyclomaticComplexityDiagnosticTest extends AbstractDiagnosticTest diagnostics = getDiagnostics(); @@ -45,7 +47,6 @@ void test() { assertThat(diagnostics, true) .hasRange(0, 8, 0, 32); assertThat(diagnostics.get(0).getRelatedInformation()).hasSize(21); - } @Test diff --git a/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/SmokyTest.java b/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/SmokyTest.java index a60b36b3fe2..f2c792b75a6 100644 --- a/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/SmokyTest.java +++ b/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/SmokyTest.java @@ -143,4 +143,13 @@ void testIAllDiagnostics() { assertThat(diagnosticErrors).isEmpty(); } + @Test + void testExtraMinForComplexity() { + // нельзя ставить отрицательное значение + diagnosticInfos.forEach(diagnosticInfo -> + assertThat(diagnosticInfo.getExtraMinForComplexity()) + .as(diagnosticInfo.getCode().getStringValue()) + .isNotNegative() + ); + } } diff --git a/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/metadata/DiagnosticInfoTest.java b/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/metadata/DiagnosticInfoTest.java index ad7c945b9a3..be97c5ec967 100644 --- a/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/metadata/DiagnosticInfoTest.java +++ b/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/metadata/DiagnosticInfoTest.java @@ -155,6 +155,7 @@ void testCanLocateOnProject() { Assertions.assertThat(diagnosticInfo.isActivatedByDefault()).isTrue(); Assertions.assertThat(diagnosticInfo.getTags()).isNotEmpty(); Assertions.assertThat(diagnosticInfo.canLocateOnProject()).isTrue(); + Assertions.assertThat(diagnosticInfo.getExtraMinForComplexity()).isZero(); } @Test