From 138cb9fd8391bcc1cf979dc099505aeebdfd3b9b Mon Sep 17 00:00:00 2001 From: Maximov Valery Date: Thu, 12 Feb 2026 13:24:56 +0300 Subject: [PATCH 1/3] =?UTF-8?q?=D0=BF=D0=B0=D1=82=D1=87=D0=B8=20=D0=BF?= =?UTF-8?q?=D0=BE=D0=B4=20=D0=BD=D0=BE=D0=B2=D1=8B=D0=B9=20bsl=20parser?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ieldsFromJoinsWithoutIsNullDiagnostic.java | 6 +- .../FullOuterJoinQueryDiagnostic.java | 4 +- .../MultilineStringInQueryDiagnostic.java | 2 +- .../diagnostics/UnionAllDiagnostic.java | 2 +- .../SDBLJoinDocumentHighlightSupplier.java | 40 +++--- .../strings/SdblTokenTypes.java | 117 +++++++++--------- .../documenthighlight/AllKnownTokenTest.java | 94 ++++++++++++++ ...SDBLJoinDocumentHighlightSupplierTest.java | 15 +-- .../providers/SemanticTokensProviderTest.java | 6 +- 9 files changed, 188 insertions(+), 98 deletions(-) create mode 100644 src/test/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/AllKnownTokenTest.java diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/FieldsFromJoinsWithoutIsNullDiagnostic.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/FieldsFromJoinsWithoutIsNullDiagnostic.java index ac6251ce6cc..d480fa768f5 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/FieldsFromJoinsWithoutIsNullDiagnostic.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/FieldsFromJoinsWithoutIsNullDiagnostic.java @@ -108,11 +108,11 @@ private static Stream joinedTables(SDBLParser.JoinPartContext joinPartCt private static List joinedDataSourceContext(SDBLParser.JoinPartContext joinPartCtx) { final List result; - if (joinPartCtx.LEFT() != null) { + if (joinPartCtx.leftJoin() != null) { result = Collections.singletonList(joinPartCtx.dataSource()); - } else if (joinPartCtx.RIGHT() != null) { + } else if (joinPartCtx.rightJoin() != null) { result = Collections.singletonList(((SDBLParser.DataSourceContext) joinPartCtx.getParent())); - } else if (joinPartCtx.FULL() != null) { + } else if (joinPartCtx.fullJoin() != null) { result = Arrays.asList(((SDBLParser.DataSourceContext) joinPartCtx.getParent()), joinPartCtx.dataSource()); } else { diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/FullOuterJoinQueryDiagnostic.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/FullOuterJoinQueryDiagnostic.java index a4eba273b87..521d0e63a48 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/FullOuterJoinQueryDiagnostic.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/FullOuterJoinQueryDiagnostic.java @@ -45,8 +45,8 @@ public class FullOuterJoinQueryDiagnostic extends AbstractSDBLVisitorDiagnostic @Override public ParseTree visitJoinPart(SDBLParser.JoinPartContext ctx) { - if (ctx.FULL() != null && ctx.JOIN() != null) { - diagnosticStorage.addDiagnostic(ctx.FULL(), ctx.JOIN()); + if (ctx.fullJoin() != null) { + diagnosticStorage.addDiagnostic(ctx.fullJoin()); } return super.visitJoinPart(ctx); diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MultilineStringInQueryDiagnostic.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MultilineStringInQueryDiagnostic.java index 58e03b14bff..9cbf07b5491 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MultilineStringInQueryDiagnostic.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MultilineStringInQueryDiagnostic.java @@ -41,7 +41,7 @@ scope = DiagnosticScope.BSL ) public class MultilineStringInQueryDiagnostic extends AbstractSDBLVisitorDiagnostic { - private static final int MULTI_STRING_MIN_SIZE = 2; // see SDBLParser grammar + private static final int MULTI_STRING_MIN_SIZE = 1; // see SDBLParser grammar @Override public ParseTree visitMultiString(SDBLParser.MultiStringContext ctx) { diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UnionAllDiagnostic.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UnionAllDiagnostic.java index 3fb54d0fd0b..3095aa5c01d 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UnionAllDiagnostic.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UnionAllDiagnostic.java @@ -44,7 +44,7 @@ public class UnionAllDiagnostic extends AbstractSDBLVisitorDiagnostic { @Override public ParseTree visitUnion(SDBLParser.UnionContext ctx) { - if (ctx.UNION() != null && ctx.ALL() != null) { + if (ctx.UNION_ALL() != null) { return super.visitUnion(ctx); } diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/SDBLJoinDocumentHighlightSupplier.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/SDBLJoinDocumentHighlightSupplier.java index 1d26497fe22..3cf066eca12 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/SDBLJoinDocumentHighlightSupplier.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/SDBLJoinDocumentHighlightSupplier.java @@ -29,13 +29,13 @@ import org.eclipse.lsp4j.DocumentHighlight; import org.eclipse.lsp4j.DocumentHighlightParams; import org.eclipse.lsp4j.Position; -import java.util.Optional; import org.jspecify.annotations.Nullable; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Optional; /** * Поставщик подсветки для конструкций JOIN в SDBL-запросах. @@ -79,13 +79,14 @@ public List getDocumentHighlight( private boolean isJoinKeyword(int tokenType) { return tokenType == SDBLLexer.JOIN - || tokenType == SDBLLexer.LEFT - || tokenType == SDBLLexer.RIGHT - || tokenType == SDBLLexer.FULL - || tokenType == SDBLLexer.INNER - || tokenType == SDBLLexer.OUTER - || tokenType == SDBLLexer.ON_EN - || tokenType == SDBLLexer.PO_RU; + || tokenType == SDBLLexer.LEFT_JOIN + || tokenType == SDBLLexer.LEFT_OUTER_JOIN + || tokenType == SDBLLexer.RIGHT_JOIN + || tokenType == SDBLLexer.RIGHT_OUTER_JOIN + || tokenType == SDBLLexer.FULL_JOIN + || tokenType == SDBLLexer.FULL_OUTER_JOIN + || tokenType == SDBLLexer.INNER_JOIN + || tokenType == SDBLLexer.BY; } private SDBLParser.@Nullable JoinPartContext findJoinPartAtPosition( @@ -107,20 +108,17 @@ private List highlightJoinPart(SDBLParser.JoinPartContext joi List highlights = new ArrayList<>(); // LEFT/RIGHT/FULL/INNER - addTerminalHighlight(highlights, joinCtx.LEFT()); - addTerminalHighlight(highlights, joinCtx.RIGHT()); - addTerminalHighlight(highlights, joinCtx.FULL()); - addTerminalHighlight(highlights, joinCtx.INNER()); - - // OUTER (опционально после LEFT/RIGHT/FULL) - addTerminalHighlight(highlights, joinCtx.OUTER()); - - // JOIN - addTerminalHighlight(highlights, joinCtx.JOIN()); + if(joinCtx.leftJoin() != null) { + addTokenHighlight(highlights, joinCtx.leftJoin().keyword); + } else if(joinCtx.rightJoin() != null) { + addTokenHighlight(highlights, joinCtx.rightJoin().keyword); + } else if(joinCtx.fullJoin() != null) { + addTokenHighlight(highlights, joinCtx.fullJoin().keyword); + } else if(joinCtx.innerJoin() != null) { + addTokenHighlight(highlights, joinCtx.fullJoin().keyword); + } - // ON/ПО - addTerminalHighlight(highlights, joinCtx.ON_EN()); - addTerminalHighlight(highlights, joinCtx.PO_RU()); + addTerminalHighlight(highlights, joinCtx.BY()); return highlights; } diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/semantictokens/strings/SdblTokenTypes.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/semantictokens/strings/SdblTokenTypes.java index 9be931a7bd7..5a6103b1d9e 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/semantictokens/strings/SdblTokenTypes.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/semantictokens/strings/SdblTokenTypes.java @@ -96,14 +96,14 @@ public static SdblTokenTypeAndModifiers getTokenTypeAndModifiers(int tokenType) private static Set createSdblKeywords() { return Set.of( - SDBLLexer.ALL, SDBLLexer.ALLOWED, + SDBLLexer.ADD, SDBLLexer.AND, SDBLLexer.AS, SDBLLexer.ASC, SDBLLexer.AUTOORDER, SDBLLexer.BETWEEN, - SDBLLexer.BY_EN, + SDBLLexer.BY, SDBLLexer.CASE, SDBLLexer.CAST, SDBLLexer.DESC, @@ -112,53 +112,59 @@ private static Set createSdblKeywords() { SDBLLexer.ELSE, SDBLLexer.END, SDBLLexer.ESCAPE, - SDBLLexer.FOR, SDBLLexer.FROM, - SDBLLexer.FULL, - SDBLLexer.GROUP, SDBLLexer.HAVING, - SDBLLexer.HIERARCHY, - SDBLLexer.HIERARCHY_FOR_IN, - SDBLLexer.IN, - SDBLLexer.INDEX, - SDBLLexer.INNER, SDBLLexer.INTO, SDBLLexer.IS, - SDBLLexer.JOIN, - SDBLLexer.LEFT, SDBLLexer.LIKE, SDBLLexer.NOT, SDBLLexer.OF, - SDBLLexer.ONLY, - SDBLLexer.ON_EN, SDBLLexer.OR, - SDBLLexer.ORDER, SDBLLexer.OVERALL, - SDBLLexer.OUTER, - SDBLLexer.PERIODS, - SDBLLexer.PO_RU, - SDBLLexer.REFS, - SDBLLexer.RIGHT, SDBLLexer.SELECT, - SDBLLexer.SET, SDBLLexer.THEN, SDBLLexer.TOP, SDBLLexer.TOTALS, - SDBLLexer.UNION, - SDBLLexer.UPDATE, SDBLLexer.WHEN, SDBLLexer.WHERE, SDBLLexer.EMPTYREF, - SDBLLexer.GROUPEDBY, - SDBLLexer.GROUPING + SDBLLexer.UNIQUE, + SDBLLexer.PERIODS, + SDBLLexer.REFS, + SDBLLexer.INDEX_BY_SETS, + SDBLLexer.INDEX_BY, + SDBLLexer.GROUP_BY_GROUPING_SETS, + SDBLLexer.GROUP_BY, + SDBLLexer.ORDER_BY, + SDBLLexer.FOR_UPDATE, + SDBLLexer.RIGHT_OUTER_JOIN, + SDBLLexer.RIGHT_JOIN, + SDBLLexer.LEFT_OUTER_JOIN, + SDBLLexer.LEFT_JOIN, + SDBLLexer.FULL_OUTER_JOIN, + SDBLLexer.FULL_JOIN, + SDBLLexer.INNER_JOIN, + SDBLLexer.JOIN, + SDBLLexer.UNION_ALL, + SDBLLexer.UNION, + SDBLLexer.ONLY_HIERARCHY, + SDBLLexer.HIERARCHY, + SDBLLexer.IN_HIERARCHY, + SDBLLexer.IN, + SDBLLexer.GROUPEDBY ); } private static Set createSdblFunctions() { return Set.of( + SDBLLexer.ISNULL, + SDBLLexer.ACOS, + SDBLLexer.ASIN, + SDBLLexer.ATAN, SDBLLexer.AVG, SDBLLexer.BEGINOFPERIOD, SDBLLexer.BOOLEAN, + SDBLLexer.COS, SDBLLexer.COUNT, SDBLLexer.DATE, SDBLLexer.DATEADD, @@ -168,9 +174,14 @@ private static Set createSdblFunctions() { SDBLLexer.DAYOFYEAR, SDBLLexer.EMPTYTABLE, SDBLLexer.ENDOFPERIOD, + SDBLLexer.EXP, SDBLLexer.HALFYEAR, SDBLLexer.HOUR, - SDBLLexer.ISNULL, + SDBLLexer.INT, + SDBLLexer.LEFT, + SDBLLexer.LOG, + SDBLLexer.LOG10, + SDBLLexer.LOWER, SDBLLexer.MAX, SDBLLexer.MIN, SDBLLexer.MINUTE, @@ -180,40 +191,32 @@ private static Set createSdblFunctions() { SDBLLexer.PRESENTATION, SDBLLexer.RECORDAUTONUMBER, SDBLLexer.REFPRESENTATION, + SDBLLexer.POW, + SDBLLexer.RIGHT, + SDBLLexer.ROUND, SDBLLexer.SECOND, + SDBLLexer.SIN, + SDBLLexer.SQRT, + SDBLLexer.STOREDDATASIZE, SDBLLexer.STRING, + SDBLLexer.STRINGLENGTH, + SDBLLexer.STRFIND, + SDBLLexer.STRREPLACE, SDBLLexer.SUBSTRING, SDBLLexer.SUM, + SDBLLexer.TAN, SDBLLexer.TENDAYS, + SDBLLexer.TRIMALL, + SDBLLexer.TRIML, + SDBLLexer.TRIMR, SDBLLexer.TYPE, + SDBLLexer.UPPER, SDBLLexer.VALUE, SDBLLexer.VALUETYPE, SDBLLexer.WEEK, SDBLLexer.WEEKDAY, SDBLLexer.YEAR, - SDBLLexer.INT, - SDBLLexer.ACOS, - SDBLLexer.ASIN, - SDBLLexer.ATAN, - SDBLLexer.COS, - SDBLLexer.SIN, - SDBLLexer.TAN, - SDBLLexer.LOG, - SDBLLexer.LOG10, - SDBLLexer.EXP, - SDBLLexer.POW, - SDBLLexer.SQRT, - SDBLLexer.LOWER, - SDBLLexer.STRINGLENGTH, - SDBLLexer.TRIMALL, - SDBLLexer.TRIML, - SDBLLexer.TRIMR, - SDBLLexer.UPPER, - SDBLLexer.ROUND, - SDBLLexer.STOREDDATASIZE, - SDBLLexer.UUID, - SDBLLexer.STRFIND, - SDBLLexer.STRREPLACE + SDBLLexer.UUID ); } @@ -251,22 +254,22 @@ private static Set createSdblLiterals() { private static Set createSdblOperators() { return Set.of( - SDBLLexer.SEMICOLON, SDBLLexer.DOT, + SDBLLexer.SEMICOLON, + SDBLLexer.COMMA, + SDBLLexer.ASSIGN, SDBLLexer.PLUS, SDBLLexer.MINUS, - SDBLLexer.MUL, - SDBLLexer.QUOTIENT, - SDBLLexer.ASSIGN, SDBLLexer.LESS_OR_EQUAL, - SDBLLexer.LESS, SDBLLexer.NOT_EQUAL, + SDBLLexer.LESS, SDBLLexer.GREATER_OR_EQUAL, SDBLLexer.GREATER, - SDBLLexer.COMMA, + SDBLLexer.MUL, + SDBLLexer.QUOTIENT, + SDBLLexer.NUMBER_SIGH, SDBLLexer.BRACE, - SDBLLexer.BRACE_START, - SDBLLexer.NUMBER_SIGH + SDBLLexer.BRACE_START ); } } diff --git a/src/test/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/AllKnownTokenTest.java b/src/test/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/AllKnownTokenTest.java new file mode 100644 index 00000000000..a517b2e5e77 --- /dev/null +++ b/src/test/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/AllKnownTokenTest.java @@ -0,0 +1,94 @@ +/* + * This file is a part of BSL Language Server. + * + * Copyright (c) 2018-2026 + * Alexey Sosnoviy , Nikita Fedkin and contributors + * + * SPDX-License-Identifier: LGPL-3.0-or-later + * + * BSL Language Server is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * BSL Language Server is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with BSL Language Server. + */ +package com.github._1c_syntax.bsl.languageserver.documenthighlight; + +import com.github._1c_syntax.bsl.languageserver.semantictokens.strings.SdblTokenTypes; +import com.github._1c_syntax.bsl.parser.BSLLexer; +import com.github._1c_syntax.bsl.parser.SDBLLexer; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Тесты для проверки того, что обо всех токенах лексера было известно + */ +@SpringBootTest +public class AllKnownTokenTest { + + private static final Set skippedSdblToken = Set.of( + SDBLLexer.WHITE_SPACE, + SDBLLexer.LPAREN, + SDBLLexer.RPAREN, + SDBLLexer.AMPERSAND, + SDBLLexer.ROUTEPOINT_FIELD, + SDBLLexer.INCORRECT_IDENTIFIER, + SDBLLexer.IDENTIFIER, + SDBLLexer.UNKNOWN, + SDBLLexer.PARAMETER_IDENTIFIER, + SDBLLexer.ACTUAL_ACTION_PERIOD_VT, + SDBLLexer.BALANCE_VT, + SDBLLexer.BALANCE_AND_TURNOVERS_VT, + SDBLLexer.BOUNDARIES_VT, + SDBLLexer.DR_CR_TURNOVERS_VT, + SDBLLexer.EXT_DIMENSIONS_VT, + SDBLLexer.RECORDS_WITH_EXT_DIMENSIONS_VT, + SDBLLexer.SCHEDULE_DATA_VT, + SDBLLexer.SLICEFIRST_VT, + SDBLLexer.SLICELAST_VT, + SDBLLexer.TASK_BY_PERFORMER_VT, + SDBLLexer.TURNOVERS_VT, + SDBLLexer.BRACE_IDENTIFIER + ); + + @Test + void sdblTokens() { + List unknown = new ArrayList<>(); + // токены имею индекс от одного максимального + var endToken = SDBLLexer.VOCABULARY.getMaxTokenType(); + for (int i = 1; i <= endToken; i++) { + var type = SdblTokenTypes.getTokenTypeAndModifiers(i); + if (type == null) { + // проверим на исключения + if (!skippedSdblToken.contains(i)) { + unknown.add("Type=%s, name %s".formatted(i, SDBLLexer.VOCABULARY.getSymbolicName(i))); + } + } + } + + assertThat(unknown).isEmpty(); + } + + @Test + void bslTokens() { + List unknown = new ArrayList<>(); + // токены имею индекс от одного максимального + var endToken = BSLLexer.VOCABULARY.getMaxTokenType(); + // todo реализовать аналог для bsl lexer + + assertThat(unknown).isEmpty(); + } +} diff --git a/src/test/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/SDBLJoinDocumentHighlightSupplierTest.java b/src/test/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/SDBLJoinDocumentHighlightSupplierTest.java index 69b5a3def2c..5b6c837720f 100644 --- a/src/test/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/SDBLJoinDocumentHighlightSupplierTest.java +++ b/src/test/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/SDBLJoinDocumentHighlightSupplierTest.java @@ -60,11 +60,10 @@ void testLeftKeyword() { // then assertThat(highlights).isNotEmpty(); // Должны подсветиться: ЛЕВОЕ, СОЕДИНЕНИЕ, ПО (первого JOIN) - assertThat(highlights).hasSize(3); + assertThat(highlights).hasSize(2); // Проверяем точные позиции - assertHighlightRange(highlights, 10, 5, 10, 10); // ЛЕВОЕ - assertHighlightRange(highlights, 10, 11, 10, 21); // СОЕДИНЕНИЕ + assertHighlightRange(highlights, 10, 5, 10, 21); // ЛЕВОЕ СОЕДИНЕНИЕ assertHighlightRange(highlights, 11, 8, 11, 10); // ПО } @@ -83,11 +82,10 @@ void testJoinKeyword() { // then assertThat(highlights).isNotEmpty(); - assertThat(highlights).hasSize(3); + assertThat(highlights).hasSize(2); // Проверяем точные позиции - assertHighlightRange(highlights, 10, 5, 10, 10); // ЛЕВОЕ - assertHighlightRange(highlights, 10, 11, 10, 21); // СОЕДИНЕНИЕ + assertHighlightRange(highlights, 10, 5, 10, 21); // ЛЕВОЕ соединение assertHighlightRange(highlights, 11, 8, 11, 10); // ПО } @@ -106,11 +104,10 @@ void testOnKeyword() { // then assertThat(highlights).isNotEmpty(); - assertThat(highlights).hasSize(3); + assertThat(highlights).hasSize(2); // Проверяем точные позиции - assertHighlightRange(highlights, 10, 5, 10, 10); // ЛЕВОЕ - assertHighlightRange(highlights, 10, 11, 10, 21); // СОЕДИНЕНИЕ + assertHighlightRange(highlights, 10, 5, 10, 21); // ЛЕВОЕ СОЕДИНЕНИЕ assertHighlightRange(highlights, 11, 8, 11, 10); // ПО } diff --git a/src/test/java/com/github/_1c_syntax/bsl/languageserver/providers/SemanticTokensProviderTest.java b/src/test/java/com/github/_1c_syntax/bsl/languageserver/providers/SemanticTokensProviderTest.java index 329acf5e7ed..8ea92022395 100644 --- a/src/test/java/com/github/_1c_syntax/bsl/languageserver/providers/SemanticTokensProviderTest.java +++ b/src/test/java/com/github/_1c_syntax/bsl/languageserver/providers/SemanticTokensProviderTest.java @@ -928,8 +928,7 @@ void sdblQuery_complexQueryWithJoin() { new ExpectedToken(7, 56, 3, SemanticTokenTypes.Keyword, "КАК"), new ExpectedToken(7, 60, 5, SemanticTokenTypes.Variable, SemanticTokenModifiers.Declaration, "Курсы"), // Line 8: ИНДЕКСИРОВАТЬ ПО Валюта, Период - new ExpectedToken(8, 3, 13, SemanticTokenTypes.Keyword, "ИНДЕКСИРОВАТЬ"), - new ExpectedToken(8, 17, 2, SemanticTokenTypes.Keyword, "ПО"), + new ExpectedToken(8, 3, 16, SemanticTokenTypes.Keyword, "ИНДЕКСИРОВАТЬ ПО"), // Second query - line 10: ВЫБРАТЬ new ExpectedToken(10, 3, 7, SemanticTokenTypes.Keyword, "ВЫБРАТЬ"), // Line 14: ИЗ ВТ_Курсы КАК ВТ @@ -938,8 +937,7 @@ void sdblQuery_complexQueryWithJoin() { new ExpectedToken(14, 15, 3, SemanticTokenTypes.Keyword, "КАК"), new ExpectedToken(14, 19, 2, SemanticTokenTypes.Variable, SemanticTokenModifiers.Declaration, "ВТ"), // Line 15: ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Валюты КАК СпрВалюта - new ExpectedToken(15, 3, 5, SemanticTokenTypes.Keyword, "ЛЕВОЕ"), - new ExpectedToken(15, 9, 10, SemanticTokenTypes.Keyword, "СОЕДИНЕНИЕ"), + new ExpectedToken(15, 3, 16, SemanticTokenTypes.Keyword, "ЛЕВОЕ СОЕДИНЕНИЕ"), new ExpectedToken(15, 20, 10, SemanticTokenTypes.Namespace, "Справочник"), new ExpectedToken(15, 31, 6, SemanticTokenTypes.Class, "Валюты"), new ExpectedToken(15, 38, 3, SemanticTokenTypes.Keyword, "КАК"), From 98e64af161e530adefb5629c8f21c0ad2a598053 Mon Sep 17 00:00:00 2001 From: theshadowco Date: Thu, 12 Feb 2026 21:26:51 +0300 Subject: [PATCH 2/3] =?UTF-8?q?=D0=BD=D0=BE=D0=B2=D1=8B=D0=B9=20=D0=BF?= =?UTF-8?q?=D0=B0=D1=80=D1=81=D0=B5=D1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 6 +--- .../PermissionFilterBeforeSendCallback.java | 2 +- .../aop/sentry/SentryScopeConfigurer.java | 1 - .../cfg/CfgBuildingParseTreeVisitor.java | 10 +++--- .../ExtractStructureConstructorSupplier.java | 12 +++++-- .../semantictokens/SemanticTokensOptions.java | 1 - ...lFunctionPathMustHaveReturnDiagnostic.java | 2 +- .../AssignAliasFieldsInQueryDiagnostic.java | 5 +-- .../CreateQueryInCycleDiagnostic.java | 16 ++++----- .../DoubleNegativesDiagnostic.java | 13 ++++++-- .../IfElseDuplicatedCodeBlockDiagnostic.java | 5 +-- .../IncorrectUseOfStrTemplateDiagnostic.java | 16 +++++---- .../diagnostics/ParseErrorDiagnostic.java | 5 +-- .../diagnostics/RefOveruseDiagnostic.java | 4 +-- .../diagnostics/UnionAllDiagnostic.java | 3 +- .../UnsafeSafeModeMethodCallDiagnostic.java | 14 +++++--- .../UsingFindElementByStringDiagnostic.java | 25 +++++++++----- .../AbstractASTDocumentHighlightSupplier.java | 3 +- ...AbstractSDBLDocumentHighlightSupplier.java | 2 -- .../BracketDocumentHighlightSupplier.java | 3 ++ ...oopStatementDocumentHighlightSupplier.java | 15 ++++----- .../providers/SelectionRangeProvider.java | 5 ++- .../strings/SpecialContextVisitor.java | 6 +--- .../utils/DiagnosticHelper.java | 6 ++-- .../bsl/languageserver/utils/Ranges.java | 33 ++++++++++--------- .../ExpressionTreeBuildingVisitor.java | 24 +++++++------- .../expressiontree/TerminalSymbolNode.java | 7 ++-- .../documenthighlight/AllKnownTokenTest.java | 3 +- 28 files changed, 138 insertions(+), 109 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index db8340e4230..7c266ebc528 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -82,11 +82,7 @@ dependencies { api("org.eclipse.lsp4j", "org.eclipse.lsp4j.websocket.jakarta", "0.24.0") // 1c-syntax - api("io.github.1c-syntax", "bsl-parser", "0.30.0") { - exclude("com.ibm.icu", "*") - exclude("org.antlr", "ST4") - exclude("org.antlr", "antlr-runtime") - } + api("io.github.1c-syntax", "bsl-parser", "0.31.0-rc.1") api("io.github.1c-syntax", "utils", "0.6.9") api("io.github.1c-syntax", "mdclasses", "0.17.4") api("io.github.1c-syntax", "bsl-common-library", "0.9.2") diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/aop/sentry/PermissionFilterBeforeSendCallback.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/aop/sentry/PermissionFilterBeforeSendCallback.java index 7da56b48224..b11b7f7cd75 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/aop/sentry/PermissionFilterBeforeSendCallback.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/aop/sentry/PermissionFilterBeforeSendCallback.java @@ -131,7 +131,7 @@ private CompletableFuture askUserForPermission(LanguageClient return languageClient.showMessageRequest(requestParams); } - @Nullable private MessageActionItem waitForPermission(CompletableFuture sendQuestion) { + private @Nullable MessageActionItem waitForPermission(CompletableFuture<@Nullable MessageActionItem> sendQuestion) { try { return sendQuestion.get(); } catch (InterruptedException e) { diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/aop/sentry/SentryScopeConfigurer.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/aop/sentry/SentryScopeConfigurer.java index 53d28f11653..3350b1e8444 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/aop/sentry/SentryScopeConfigurer.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/aop/sentry/SentryScopeConfigurer.java @@ -28,7 +28,6 @@ import io.sentry.protocol.Geo; import io.sentry.protocol.User; import lombok.RequiredArgsConstructor; -import org.eclipse.lsp4j.ClientInfo; import org.eclipse.lsp4j.ServerInfo; import org.jspecify.annotations.Nullable; import org.springframework.boot.context.event.ApplicationReadyEvent; diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/cfg/CfgBuildingParseTreeVisitor.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/cfg/CfgBuildingParseTreeVisitor.java index 7533af65b4b..09453609d7d 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/cfg/CfgBuildingParseTreeVisitor.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/cfg/CfgBuildingParseTreeVisitor.java @@ -76,7 +76,7 @@ public ControlFlowGraph buildGraph(BSLParser.CodeBlockContext block) { // Если это тело модуля, то самую первую инструкцию препроцессора сожрет грамматика file // надо ее тоже посетить принудительно. var parent = block.getParent(); - if (parent instanceof BSLParser.FileCodeBlockContext fileBlock) { + if (parent instanceof BSLParser.FileCodeBlockContext fileBlock && fileBlock.getParent() != null) { var probablyPreprocessor = Trees.getPreviousNode(fileBlock.getParent(), fileBlock, BSLParser.RULE_preprocessor); @@ -210,15 +210,15 @@ public ParseTree visitElsifBranch(BSLParser.ElsifBranchContext ctx) { if (currentIfBlock == null) { throw new IllegalStateException( "Cannot process elsif branch: there is no active condition block. " + - "This may occur when preprocessor directives modify the block stack."); + "This may occur when preprocessor directives modify the block stack."); } var buildParts = currentIfBlock.getBuildParts(); if (buildParts.isEmpty()) { throw new IllegalStateException( "Cannot process elsif branch: build parts stack is empty. " + - "Expected previous condition on stack. " + - "This may occur when preprocessor conditions modify the stack inside if statement body."); + "Expected previous condition on stack. " + + "This may occur when preprocessor conditions modify the stack inside if statement body."); } var previousCondition = buildParts.pop(); @@ -256,7 +256,7 @@ public ParseTree visitElseBranch(BSLParser.ElseBranchContext ctx) { if (currentIfBlock == null) { throw new IllegalStateException( "Cannot process else branch: there is no active condition block. " + - "This may occur when preprocessor directives modify the block stack."); + "This may occur when preprocessor directives modify the block stack."); } var condition = currentIfBlock.getBuildParts().pop(); graph.addEdge(condition, block.begin(), CfgEdgeType.FALSE_BRANCH); diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/codeactions/ExtractStructureConstructorSupplier.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/codeactions/ExtractStructureConstructorSupplier.java index 1e96c9409bc..57e5a38b794 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/codeactions/ExtractStructureConstructorSupplier.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/codeactions/ExtractStructureConstructorSupplier.java @@ -46,6 +46,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.function.Predicate; /** @@ -85,7 +86,7 @@ public List getCodeActions(CodeActionParams params, DocumentContext var parameters = maybeDoCall .map(BSLParser.DoCallContext::callParamList) - .map(callParamListContext -> callParamListContext.children) + .map(ParserRuleContext::getChildren) .orElse(Collections.emptyList()) .stream() .filter(Predicate.not(TerminalNode.class::isInstance)) @@ -163,9 +164,14 @@ public List getCodeActions(CodeActionParams params, DocumentContext } private static boolean isParentAssignment(BSLParser.DoCallContext doCall, BSLParser.AssignmentContext assignment) { - return assignment.expression().member().stream() + var expression = assignment.expression(); + if (expression == null) { + return false; + } + return expression.member().stream() .map(BSLParser.MemberContext::complexIdentifier) - .map(BSLParser.ComplexIdentifierContext::newExpression) + .map(ctx -> ctx != null ? ctx.newExpression() : null) + .filter(Objects::nonNull) .filter(newExpressionContext -> newExpressionContext == doCall.getParent()) .findAny().isEmpty(); } diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/configuration/semantictokens/SemanticTokensOptions.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/configuration/semantictokens/SemanticTokensOptions.java index 1c5e0862a87..2e33e3be165 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/configuration/semantictokens/SemanticTokensOptions.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/configuration/semantictokens/SemanticTokensOptions.java @@ -33,7 +33,6 @@ import java.util.HashSet; import java.util.List; import java.util.Locale; -import java.util.Map; import java.util.Set; /** diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/AllFunctionPathMustHaveReturnDiagnostic.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/AllFunctionPathMustHaveReturnDiagnostic.java index 41cb5d2255d..ded94921c72 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/AllFunctionPathMustHaveReturnDiagnostic.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/AllFunctionPathMustHaveReturnDiagnostic.java @@ -151,7 +151,7 @@ private Optional checkElseIfClauseExitingNode(ConditionalVert var expression = v.getExpression(); if (expression.getParent() instanceof BSLParser.ElsifBranchContext elsifBranch && !ignoreMissingElseOnExit) { - return Optional.of(elsifBranch.getParent()); + return Optional.ofNullable(elsifBranch.getParent()); } return Optional.empty(); diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/AssignAliasFieldsInQueryDiagnostic.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/AssignAliasFieldsInQueryDiagnostic.java index 3fe8b3e7b7e..500750b3f33 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/AssignAliasFieldsInQueryDiagnostic.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/AssignAliasFieldsInQueryDiagnostic.java @@ -28,6 +28,7 @@ import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticType; import com.github._1c_syntax.bsl.parser.SDBLParser; import org.antlr.v4.runtime.tree.ParseTree; +import org.jspecify.annotations.Nullable; @DiagnosticMetadata( type = DiagnosticType.CODE_SMELL, @@ -44,9 +45,9 @@ public class AssignAliasFieldsInQueryDiagnostic extends AbstractSDBLVisitorDiagnostic { @Override - public ParseTree visitQuery(SDBLParser.QueryContext ctx) { + public @Nullable ParseTree visitQuery(SDBLParser.QueryContext ctx) { - if (ctx.getParent().getRuleIndex() != SDBLParser.RULE_subquery) { + if (ctx.getParent() != null && ctx.getParent().getRuleIndex() != SDBLParser.RULE_subquery) { return super.visitQuery(ctx); } diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/CreateQueryInCycleDiagnostic.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/CreateQueryInCycleDiagnostic.java index 1b0fc73eb02..cc1e9a51def 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/CreateQueryInCycleDiagnostic.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/CreateQueryInCycleDiagnostic.java @@ -145,7 +145,7 @@ private static String getComplexPathName( } @Override - public ParseTree visitFile(BSLParser.FileContext ctx) { + public @Nullable ParseTree visitFile(BSLParser.FileContext ctx) { currentScope = new VariableScope(); currentScope.enterScope(GLOBAL_SCOPE); ParseTree result = super.visitFile(ctx); @@ -154,7 +154,7 @@ public ParseTree visitFile(BSLParser.FileContext ctx) { } @Override - public ParseTree visitFileCodeBlock(BSLParser.FileCodeBlockContext ctx) { + public @Nullable ParseTree visitFileCodeBlock(BSLParser.FileCodeBlockContext ctx) { currentScope.enterScope(MODULE_SCOPE); ParseTree result = super.visitFileCodeBlock(ctx); currentScope.leaveScope(); @@ -162,7 +162,7 @@ public ParseTree visitFileCodeBlock(BSLParser.FileCodeBlockContext ctx) { } @Override - public ParseTree visitProcedure(BSLParser.ProcedureContext ctx) { + public @Nullable ParseTree visitProcedure(BSLParser.ProcedureContext ctx) { currentScope.enterScope(ctx.procDeclaration().subName().getText()); ParseTree result = super.visitProcedure(ctx); currentScope.leaveScope(); @@ -170,7 +170,7 @@ public ParseTree visitProcedure(BSLParser.ProcedureContext ctx) { } @Override - public ParseTree visitFunction(BSLParser.FunctionContext ctx) { + public @Nullable ParseTree visitFunction(BSLParser.FunctionContext ctx) { currentScope.enterScope(ctx.funcDeclaration().subName().getText()); ParseTree result = super.visitFunction(ctx); currentScope.leaveScope(); @@ -178,7 +178,7 @@ public ParseTree visitFunction(BSLParser.FunctionContext ctx) { } @Override - public ParseTree visitAssignment(AssignmentContext ctx) { + public @Nullable ParseTree visitAssignment(AssignmentContext ctx) { if (ctx.expression() == null) { return super.visitAssignment(ctx); } @@ -217,14 +217,14 @@ private Set getTypesFromComplexIdentifier(BSLParser.ComplexIdentifierCon private void visitDescendantCodeBlock(BSLParser.@Nullable CodeBlockContext ctx) { Optional.ofNullable(ctx) - .map(e -> e.children) + .map(ParserRuleContext::getChildren) .stream() .flatMap(Collection::stream) .forEach(t -> t.accept(this)); } @Override - public ParseTree visitAccessCall(BSLParser.AccessCallContext ctx) { + public @Nullable ParseTree visitAccessCall(BSLParser.AccessCallContext ctx) { if (!EXECUTE_CALL_PATTERN.matcher(ctx.methodCall().methodName().getText()).matches()) { return super.visitAccessCall(ctx); } @@ -273,7 +273,7 @@ public ParseTree visitForEachStatement(BSLParser.ForEachStatementContext ctx) { } @Override - public ParseTree visitWhileStatement(BSLParser.WhileStatementContext ctx) { + public @Nullable ParseTree visitWhileStatement(BSLParser.WhileStatementContext ctx) { currentScope.flowMode.push(CodeFlowType.CYCLE); ParseTree result = super.visitWhileStatement(ctx); currentScope.flowMode.pop(); diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/DoubleNegativesDiagnostic.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/DoubleNegativesDiagnostic.java index 392f4760705..73a25d3062d 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/DoubleNegativesDiagnostic.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/DoubleNegativesDiagnostic.java @@ -86,7 +86,12 @@ private static boolean isNegationOperator(BslExpression parent) { } private void addDiagnostic(BinaryOperationNode node) { - var startToken = Trees.getTokens(node.getParent().getRepresentingAst()) + var parent = node.getParent(); + if (parent == null) { + return; + } + + var startToken = Trees.getTokens(parent.getRepresentingAst()) .stream() .findFirst() .orElseThrow(); @@ -100,7 +105,11 @@ private void addDiagnostic(BinaryOperationNode node) { } private void addDiagnostic(UnaryOperationNode node) { - var startToken = Trees.getTokens(node.getParent().getRepresentingAst()) + var parent = node.getParent(); + if (parent == null) { + return; + } + var startToken = Trees.getTokens(parent.getRepresentingAst()) .stream() .findFirst() .orElseThrow(); diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/IfElseDuplicatedCodeBlockDiagnostic.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/IfElseDuplicatedCodeBlockDiagnostic.java index 7dfe34fe478..eed8245d243 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/IfElseDuplicatedCodeBlockDiagnostic.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/IfElseDuplicatedCodeBlockDiagnostic.java @@ -32,6 +32,7 @@ import jakarta.annotation.PostConstruct; import org.antlr.v4.runtime.tree.ParseTree; import org.eclipse.lsp4j.DiagnosticRelatedInformation; +import org.jspecify.annotations.Nullable; import java.util.ArrayList; import java.util.HashSet; @@ -61,7 +62,7 @@ public void init() { } @Override - public ParseTree visitIfStatement(BSLParser.IfStatementContext ctx) { + public @Nullable ParseTree visitIfStatement(BSLParser.IfStatementContext ctx) { checkedBlocks.clear(); List codeBlocks = new ArrayList<>(); @@ -96,7 +97,7 @@ private void checkCodeBlock(List codeBlockContexts, .skip(i) .filter(codeBlockContext -> !codeBlockContext.equals(currentCodeBlock) - && !(currentCodeBlock.children == null && codeBlockContext.children == null) + && !(currentCodeBlock.getChildren().isEmpty() && codeBlockContext.getChildren().isEmpty()) && DiagnosticHelper.equalNodes(currentCodeBlock, codeBlockContext)) .toList(); diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/IncorrectUseOfStrTemplateDiagnostic.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/IncorrectUseOfStrTemplateDiagnostic.java index 4ef6ff8b141..753028693e8 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/IncorrectUseOfStrTemplateDiagnostic.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/IncorrectUseOfStrTemplateDiagnostic.java @@ -145,7 +145,7 @@ private static Optional getConstValue(Optional calcStringForMemberContext(memberContext, isFullSearch)); } - private static Optional calcStringForMemberContext(BSLParser.MemberContext memberContext, + private static Optional calcStringForMemberContext(BSLParser.MemberContext memberContext, boolean isFullSearch) { final var constValue = memberContext.constValue(); if (constValue != null) { @@ -161,8 +161,8 @@ private static Optional calcStringForMemberContext( } private static Optional calcAssignedValueForIdentifier( - BSLParser.ComplexIdentifierContext complexIdentifier) { - + BSLParser.ComplexIdentifierContext complexIdentifier) { + final var identifier = complexIdentifier.IDENTIFIER(); if (identifier == null) { return Optional.empty(); @@ -172,9 +172,9 @@ private static Optional calcAssignedValueForIdentif var prevStatement = (BSLParser.StatementContext) Objects.requireNonNull(Trees.getRootParent(complexIdentifier, BSLParser.RULE_statement)); while (true) { - prevStatement = (BSLParser.StatementContext) getPreviousNode(Objects.requireNonNull(prevStatement), + prevStatement = (BSLParser.StatementContext) getPreviousNode(Objects.requireNonNull(prevStatement), BSLParser.RULE_statement); - + if (prevStatement == null) { break; } @@ -191,8 +191,12 @@ private static Optional calcAssignedValueForIdentif @Nullable private static ParserRuleContext getPreviousNode(ParserRuleContext node, int ruleStatement) { + var parent = node.getParent(); + if (parent == null) { + return null; + } - final var children = node.getParent().children; + final var children = parent.getChildren(); final var pos = children.indexOf(node); if (pos > 0) { for (int i = pos - 1; i >= 0; i--) { diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/ParseErrorDiagnostic.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/ParseErrorDiagnostic.java index 16f6691cc45..6bed54560fc 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/ParseErrorDiagnostic.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/ParseErrorDiagnostic.java @@ -31,6 +31,7 @@ import com.github._1c_syntax.bsl.parser.BSLParser; import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.tree.ErrorNode; +import org.jspecify.annotations.Nullable; import java.util.StringJoiner; import java.util.stream.IntStream; @@ -87,8 +88,8 @@ public void enterFile(BSLParser.FileContext ctx) { }); } - private static String getTokenName(int tokenType) { - String value = BSLLexer.VOCABULARY.getLiteralName(tokenType); + private static @Nullable String getTokenName(int tokenType) { + var value = BSLLexer.VOCABULARY.getLiteralName(tokenType); if (value == null) { value = BSLLexer.VOCABULARY.getSymbolicName(tokenType); } diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/RefOveruseDiagnostic.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/RefOveruseDiagnostic.java index 04dc9880c08..5255fd58355 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/RefOveruseDiagnostic.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/RefOveruseDiagnostic.java @@ -107,7 +107,7 @@ public ParseTree visitQueryPackage(SDBLParser.QueryPackageContext ctx) { } @Override - public ParseTree visitQuery(SDBLParser.QueryContext ctx) { + public @Nullable ParseTree visitQuery(SDBLParser.QueryContext ctx) { checkQuery(ctx).forEach(diagnosticStorage::addDiagnostic); return super.visitQuery(ctx); } @@ -312,7 +312,7 @@ private static int findLastRef(List children) { private static List extractFirstMetadataTypeName(SDBLParser.ColumnContext ctx) { final var mdoName = ctx.mdoName; - final var children = ctx.children; + final var children = ctx.getChildren(); if (mdoName == null || children.size() < COUNT_OF_TABLE_DOT_REF_DOT_REF || !METADATA_TYPES.contains(mdoName.getStart().getType())) { return children; diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UnionAllDiagnostic.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UnionAllDiagnostic.java index 3095aa5c01d..d7de0876073 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UnionAllDiagnostic.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UnionAllDiagnostic.java @@ -28,6 +28,7 @@ import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticType; import com.github._1c_syntax.bsl.parser.SDBLParser; import org.antlr.v4.runtime.tree.ParseTree; +import org.jspecify.annotations.Nullable; @DiagnosticMetadata( type = DiagnosticType.CODE_SMELL, @@ -43,7 +44,7 @@ public class UnionAllDiagnostic extends AbstractSDBLVisitorDiagnostic { @Override - public ParseTree visitUnion(SDBLParser.UnionContext ctx) { + public @Nullable ParseTree visitUnion(SDBLParser.UnionContext ctx) { if (ctx.UNION_ALL() != null) { return super.visitUnion(ctx); } diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UnsafeSafeModeMethodCallDiagnostic.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UnsafeSafeModeMethodCallDiagnostic.java index 606f13c4ca1..a690a4f3de1 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UnsafeSafeModeMethodCallDiagnostic.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UnsafeSafeModeMethodCallDiagnostic.java @@ -87,12 +87,16 @@ private static boolean nonValidExpression(BSLParser.MemberContext currentRootMem return true; } - ParserRuleContext rootExpressionNode = currentRootMember.getParent(); + var rootExpressionNode = currentRootMember.getParent(); + if (rootExpressionNode == null) { + return false; + } - ParserRuleContext rootIfNode = Trees.getRootParent(rootExpressionNode, ROOT_LIST); + var rootIfNode = Trees.getRootParent(rootExpressionNode, ROOT_LIST); if (rootIfNode == null || rootIfNode.getRuleIndex() == BSLParser.RULE_codeBlock) { return false; } + if (rootExpressionNode.getChildCount() == 1 && IF_BRANCHES.contains(rootIfNode.getRuleIndex())) { return true; } @@ -103,9 +107,9 @@ private static boolean nonValidExpression(BSLParser.MemberContext currentRootMem private static boolean haveNeighboorBooleanOperator(ParserRuleContext currentRootMember, ParserRuleContext rootExpressionNode) { var haveNeighbourBoolOperation = false; - int indexOfCurrentMemberNode = rootExpressionNode.children.indexOf(currentRootMember); + int indexOfCurrentMemberNode = rootExpressionNode.getChildren().indexOf(currentRootMember); if (indexOfCurrentMemberNode > 0) { - var prev = (ParserRuleContext) rootExpressionNode.children.get(indexOfCurrentMemberNode - 1); + var prev = (ParserRuleContext) rootExpressionNode.getChildren().get(indexOfCurrentMemberNode - 1); if (Trees.nodeContains(prev, BSLParser.RULE_compareOperation)) { return false; } @@ -113,7 +117,7 @@ private static boolean haveNeighboorBooleanOperator(ParserRuleContext currentRoo } if (indexOfCurrentMemberNode < rootExpressionNode.getChildCount() - 1) { - var next = (ParserRuleContext) rootExpressionNode.children.get(indexOfCurrentMemberNode + 1); + var next = (ParserRuleContext) rootExpressionNode.getChildren().get(indexOfCurrentMemberNode + 1); if (Trees.nodeContains(next, BSLParser.RULE_compareOperation)) { return false; } diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UsingFindElementByStringDiagnostic.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UsingFindElementByStringDiagnostic.java index 6fffacd2782..18025d77add 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UsingFindElementByStringDiagnostic.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UsingFindElementByStringDiagnostic.java @@ -29,7 +29,9 @@ import com.github._1c_syntax.bsl.parser.BSLParser; import com.github._1c_syntax.utils.CaseInsensitivePattern; import org.antlr.v4.runtime.tree.ParseTree; +import org.jspecify.annotations.Nullable; +import java.util.Optional; import java.util.regex.Pattern; @DiagnosticMetadata( @@ -51,14 +53,21 @@ public class UsingFindElementByStringDiagnostic extends AbstractVisitorDiagnosti ); @Override - public ParseTree visitMethodCall(BSLParser.MethodCallContext ctx) { - var matcher = pattern.matcher(ctx.methodName().getText()); - if (matcher.matches()) { - BSLParser.CallParamContext param = ctx.doCall().callParamList().callParam().get(0); - if (param.children == null || - param.getStart().getType() == BSLParser.STRING || - param.getStart().getType() == BSLParser.DECIMAL) { - diagnosticStorage.addDiagnostic(ctx, info.getMessage(matcher.group(0))); + public @Nullable ParseTree visitMethodCall(BSLParser.MethodCallContext ctx) { + var methodName = ctx.methodName(); + if (methodName != null) { + var matcher = pattern.matcher(methodName.getText()); + if (matcher.matches()) { + Optional.ofNullable(ctx.doCall()) + .map(BSLParser.DoCallContext::callParamList) + .ifPresent(callParamList -> { + var param = callParamList.callParam().get(0); + if (param.getChildren().isEmpty() || + param.getStart().getType() == BSLParser.STRING || + param.getStart().getType() == BSLParser.DECIMAL) { + diagnosticStorage.addDiagnostic(ctx, info.getMessage(matcher.group(0))); + } + }); } } return super.visitMethodCall(ctx); diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/AbstractASTDocumentHighlightSupplier.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/AbstractASTDocumentHighlightSupplier.java index b0ef1381ca6..1c5745a65e5 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/AbstractASTDocumentHighlightSupplier.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/AbstractASTDocumentHighlightSupplier.java @@ -24,7 +24,6 @@ import com.github._1c_syntax.bsl.languageserver.utils.Ranges; import org.antlr.v4.runtime.tree.TerminalNode; import org.eclipse.lsp4j.DocumentHighlight; -import java.util.Optional; import org.jspecify.annotations.Nullable; import java.util.List; @@ -41,7 +40,7 @@ public abstract class AbstractASTDocumentHighlightSupplier implements DocumentHi *

* Используется для прямого доступа к токенам через геттеры ANTLR-контекста. * - * @param highlights Список подсветок, в который будет добавлена подсветка токена + * @param highlights Список подсветок, в который будет добавлена подсветка токена * @param terminalNode Терминальный узел с токеном (может быть null) */ protected void addTokenHighlight(List highlights, @Nullable TerminalNode terminalNode) { diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/AbstractSDBLDocumentHighlightSupplier.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/AbstractSDBLDocumentHighlightSupplier.java index 03d5ac69c6e..af5ce3a25ba 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/AbstractSDBLDocumentHighlightSupplier.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/AbstractSDBLDocumentHighlightSupplier.java @@ -28,12 +28,10 @@ import org.antlr.v4.runtime.tree.TerminalNode; import org.eclipse.lsp4j.DocumentHighlight; import org.eclipse.lsp4j.Position; -import java.util.Optional; import org.jspecify.annotations.Nullable; import java.util.List; import java.util.Optional; -import org.jspecify.annotations.Nullable; /** * Базовый класс для поставщиков подсветки в SDBL-запросах. diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/BracketDocumentHighlightSupplier.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/BracketDocumentHighlightSupplier.java index db66d702c9a..0e48f5d9763 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/BracketDocumentHighlightSupplier.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/BracketDocumentHighlightSupplier.java @@ -28,6 +28,8 @@ import org.eclipse.lsp4j.DocumentHighlight; import org.eclipse.lsp4j.DocumentHighlightParams; import java.util.Optional; + +import org.jspecify.annotations.Nullable; import org.springframework.stereotype.Component; import java.util.ArrayList; @@ -111,6 +113,7 @@ private List highlightMatchingBracket(Token token, DocumentCo return highlights; } + @Nullable private Token findMatchingBracket(Token token, List allTokens, int openType, int closeType, boolean isOpening) { int tokenIndex = token.getTokenIndex(); int depth = 1; diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/LoopStatementDocumentHighlightSupplier.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/LoopStatementDocumentHighlightSupplier.java index 04992731d22..6c59913ffa8 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/LoopStatementDocumentHighlightSupplier.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/LoopStatementDocumentHighlightSupplier.java @@ -26,13 +26,13 @@ import org.antlr.v4.runtime.ParserRuleContext; import org.eclipse.lsp4j.DocumentHighlight; import org.eclipse.lsp4j.DocumentHighlightParams; -import java.util.Optional; import org.jspecify.annotations.Nullable; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Optional; /** * Поставщик подсветки для циклов (For/While/Do/EndDo). @@ -96,12 +96,11 @@ private ParserRuleContext findNearestLoopStatement(ParserRuleContext context) { while (current != null) { var ruleIndex = current.getRuleIndex(); if (ruleIndex == BSLParser.RULE_whileStatement - || ruleIndex == BSLParser.RULE_forStatement - || ruleIndex == BSLParser.RULE_forEachStatement) { + || ruleIndex == BSLParser.RULE_forStatement + || ruleIndex == BSLParser.RULE_forEachStatement) { return current; } - var parent = current.getParent(); - current = parent instanceof ParserRuleContext ? (ParserRuleContext) parent : null; + current = current.getParent(); } return null; } @@ -170,7 +169,7 @@ private List highlightForEachStatement(ParserRuleContext forE * Добавляет подсветку для break и continue внутри блока кода цикла. * Ищет только на первом уровне вложенности - не заходит во вложенные циклы. */ - private void addBreakAndContinueHighlights(List highlights, BSLParser.CodeBlockContext codeBlock) { + private void addBreakAndContinueHighlights(List highlights, BSLParser.@Nullable CodeBlockContext codeBlock) { if (codeBlock == null) { return; } @@ -210,7 +209,7 @@ private void addBreakAndContinueHighlights(List highlights, B * Ищет break/continue в if-блоках. */ private void addBreakAndContinueFromIfStatement(List highlights, - BSLParser.IfStatementContext ifStatement) { + BSLParser.IfStatementContext ifStatement) { var ifBranch = ifStatement.ifBranch(); if (ifBranch != null) { addBreakAndContinueHighlights(highlights, ifBranch.codeBlock()); @@ -230,7 +229,7 @@ private void addBreakAndContinueFromIfStatement(List highligh * Ищет break/continue в try-блоках. */ private void addBreakAndContinueFromTryStatement(List highlights, - BSLParser.TryStatementContext tryStatement) { + BSLParser.TryStatementContext tryStatement) { addBreakAndContinueHighlights(highlights, tryStatement.tryCodeBlock().codeBlock()); addBreakAndContinueHighlights(highlights, tryStatement.exceptCodeBlock().codeBlock()); } diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/providers/SelectionRangeProvider.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/providers/SelectionRangeProvider.java index 5e56eeadb8f..6db1014e0a9 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/providers/SelectionRangeProvider.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/providers/SelectionRangeProvider.java @@ -180,8 +180,7 @@ private static ParserRuleContext getStatementParent(BSLParser.StatementContext s if (!nearbyStatements.isEmpty() && (nearbyStatements.size() + 1 != children.size())) { - var statementsBlock = new ParserRuleContext(); - statementsBlock.setParent(parent); + var statementsBlock = new ParserRuleContext(parent, -1); // todo стоит переделать nearbyStatements.add(statement); nearbyStatements.sort(Comparator.comparing(ruleContext -> ruleContext.getStart().getLine())); @@ -207,6 +206,6 @@ private static boolean ifBranchMatchesIfStatement(ParserRuleContext ctx) { } var ifStatement = (BSLParser.IfStatementContext) ifBranch.getParent(); - return ifStatement.elseBranch() == null && ifStatement.elsifBranch().isEmpty(); + return ifStatement != null && ifStatement.elseBranch() == null && ifStatement.elsifBranch().isEmpty(); } } diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/semantictokens/strings/SpecialContextVisitor.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/semantictokens/strings/SpecialContextVisitor.java index e641b3755f6..a0c583b8dd2 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/semantictokens/strings/SpecialContextVisitor.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/semantictokens/strings/SpecialContextVisitor.java @@ -273,11 +273,7 @@ private String extractVariableName(BSLParser.CallParamContext callParam) { return null; } - var children = parent.children; - if (children == null) { - return null; - } - + var children = parent.getChildren(); int pos = children.indexOf(statement); for (int i = pos - 1; i >= 0; i--) { var child = children.get(i); diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/utils/DiagnosticHelper.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/utils/DiagnosticHelper.java index 19cda7b17e9..839bc9faad8 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/utils/DiagnosticHelper.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/utils/DiagnosticHelper.java @@ -56,8 +56,10 @@ public final class DiagnosticHelper { * @param rightNode Второй узел для сравнения * @return true, если узлы эквивалентны */ - public static boolean equalNodes(Tree leftNode, Tree rightNode) { - + public static boolean equalNodes(@Nullable Tree leftNode, @Nullable Tree rightNode) { + if (leftNode == null || rightNode == null) { + return false; + } if (leftNode.getChildCount() != rightNode.getChildCount() || !leftNode.getClass().equals(rightNode.getClass())) { return false; diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/utils/Ranges.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/utils/Ranges.java index 4688df0140c..5a947d167c9 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/utils/Ranges.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/utils/Ranges.java @@ -21,8 +21,6 @@ */ package com.github._1c_syntax.bsl.languageserver.utils; -import com.github._1c_syntax.bsl.languageserver.context.symbol.ModuleSymbol; -import com.github._1c_syntax.bsl.parser.BSLLexer; import lombok.experimental.UtilityClass; import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.Token; @@ -34,9 +32,7 @@ import org.eclipse.lsp4j.util.Positions; import org.jspecify.annotations.Nullable; -import java.util.Collection; import java.util.List; -import java.util.Optional; /** * Набор методов для удобства работы с областями текста (ренджами) @@ -68,8 +64,8 @@ public Range create() { * * @param startLine Начальная строка * @param startChar Начальный символ - * @param endLine Конечная строка - * @param endChar Конечный символ + * @param endLine Конечная строка + * @param endChar Конечный символ * @return Созданный диапазон */ public Range create(int startLine, int startChar, int endLine, int endChar) { @@ -94,7 +90,10 @@ public Range create(int lineNo, int startChar, int endChar) { * @param ruleContext Контекст правила * @return Диапазон, покрывающий весь контекст */ - public Range create(ParserRuleContext ruleContext) { + public Range create(@Nullable ParserRuleContext ruleContext) { + if (ruleContext == null) { + return create(); + } return create(ruleContext.getStart(), ruleContext.getStop()); } @@ -102,7 +101,7 @@ public Range create(ParserRuleContext ruleContext) { * Создать диапазон от начала одного контекста до конца другого. * * @param startCtx Начальный контекст - * @param endCtx Конечный контекст + * @param endCtx Конечный контекст * @return Диапазон между контекстами */ public Range create(ParserRuleContext startCtx, ParserRuleContext endCtx) { @@ -113,7 +112,7 @@ public Range create(ParserRuleContext startCtx, ParserRuleContext endCtx) { * Создать диапазон из токенов. * * @param startToken Начальный токен - * @param endToken Конечный токен + * @param endToken Конечный токен * @return Диапазон между токенами */ public Range create(Token startToken, @Nullable Token endToken) { @@ -153,7 +152,10 @@ public Range create(List tokens) { * @param terminalNode Терминальный узел * @return Диапазон узла */ - public Range create(TerminalNode terminalNode) { + public Range create(@Nullable TerminalNode terminalNode) { + if (terminalNode == null) { + return create(); + } return create(terminalNode.getSymbol()); } @@ -161,7 +163,7 @@ public Range create(TerminalNode terminalNode) { * Создать диапазон между двумя терминальными узлами. * * @param startTerminalNode Начальный узел - * @param stopTerminalNode Конечный узел + * @param stopTerminalNode Конечный узел * @return Диапазон между узлами */ public Range create(TerminalNode startTerminalNode, TerminalNode stopTerminalNode) { @@ -210,7 +212,7 @@ public boolean containsPosition(Range range, Position position) { Preconditions.checkNotNull(position, "position"); return range.getStart().equals(position) || (Positions.isBefore(range.getStart(), position) - && Positions.isBefore(position, range.getEnd())); + && Positions.isBefore(position, range.getEnd())); } /** @@ -275,7 +277,6 @@ private boolean isBefore(int line1, int character1, int line2, int character2) { } - /** * Натуральный порядок сравнения Range * @@ -284,11 +285,11 @@ private boolean isBefore(int line1, int character1, int line2, int character2) { * @return 0 - равно, 1 - больше, -1 - меньше */ public int compare(Range o1, Range o2) { - if (o1.equals(o2)){ + if (o1.equals(o2)) { return 0; } final var startCompare = compare(o1.getStart(), o2.getStart()); - if (startCompare != 0){ + if (startCompare != 0) { return startCompare; } return compare(o1.getEnd(), o2.getEnd()); @@ -302,7 +303,7 @@ public int compare(Range o1, Range o2) { * @return 0 - равно, 1 - больше, -1 - меньше */ public int compare(Position pos1, Position pos2) { - if (pos1.equals(pos2)){ + if (pos1.equals(pos2)) { return 0; } diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/utils/expressiontree/ExpressionTreeBuildingVisitor.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/utils/expressiontree/ExpressionTreeBuildingVisitor.java index bfab6875415..2b2aa3cc404 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/utils/expressiontree/ExpressionTreeBuildingVisitor.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/utils/expressiontree/ExpressionTreeBuildingVisitor.java @@ -92,7 +92,7 @@ public ParseTree visitExpression(BSLParser.ExpressionContext ctx) { var nestingCount = operatorsInFly.size(); recursionLevel++; - if (Trees.nodeContainsErrors(ctx) || (ctx.getChildCount() == 0 || ctx.children.stream().anyMatch(ErrorNode.class::isInstance))) { + if (Trees.nodeContainsErrors(ctx) || (ctx.getChildCount() == 0 || ctx.getChildren().stream().anyMatch(ErrorNode.class::isInstance))) { var errorExpressionNode = new ErrorExpressionNode(ctx); if (recursionLevel > 0) { operands.push(errorExpressionNode); @@ -147,10 +147,10 @@ public ParseTree visitExpression(BSLParser.ExpressionContext ctx) { } @Override - public ParseTree visitMember(BSLParser.MemberContext ctx) { + public @Nullable ParseTree visitMember(BSLParser.MemberContext ctx) { // В случае ошибки парсинга member может быть пустой. - if (Trees.nodeContainsErrors(ctx) || ctx.getChildCount() == 0 || ctx.children.stream().anyMatch(ErrorNode.class::isInstance)) { + if (Trees.nodeContainsErrors(ctx) || ctx.getChildCount() == 0 || ctx.getChildren().stream().anyMatch(ErrorNode.class::isInstance)) { operands.push(new ErrorExpressionNode(ctx)); return ctx; } @@ -168,7 +168,7 @@ public ParseTree visitMember(BSLParser.MemberContext ctx) { if (unaryModifier != null) { visitUnaryModifier(unaryModifier); - childIndex = ctx.children.indexOf(unaryModifier) + 1; + childIndex = ctx.getChildren().indexOf(unaryModifier) + 1; } if (ctx.waitExpression() != null) { @@ -299,7 +299,7 @@ public ParseTree visitConstValue(BSLParser.ConstValueContext ctx) { @Override public ParseTree visitUnaryModifier(BSLParser.UnaryModifierContext ctx) { var child = (TerminalNode) ctx.getChild(0); - var token = (child).getSymbol().getType(); + var token = child.getSymbol().getType(); var operator = switch (token) { case BSLLexer.PLUS -> BslOperator.UNARY_PLUS; @@ -318,7 +318,7 @@ public ParseTree visitComplexIdentifier(BSLParser.ComplexIdentifierContext ctx) if (ctx.IDENTIFIER() != null) { operands.push(TerminalSymbolNode.identifier(ctx.IDENTIFIER())); } else { - var childVariant = ctx.children.get(0); + var childVariant = ctx.getChildren().get(0); childVariant.accept(this); } @@ -413,10 +413,12 @@ public ParseTree visitAccessIndex(BSLParser.AccessIndexContext ctx) { public ParseTree visitAccessCall(BSLParser.AccessCallContext ctx) { var target = operands.pop(); var methodCall = ctx.methodCall(); - var callNode = MethodCallNode.create(methodCall.methodName().IDENTIFIER()); - addCallArguments(callNode, methodCall.doCall().callParamList().callParam()); - var operation = BinaryOperationNode.create(BslOperator.DEREFERENCE, target, callNode, ctx); - operands.push(operation); + if (methodCall != null) { + var callNode = MethodCallNode.create(methodCall.methodName().IDENTIFIER()); + addCallArguments(callNode, methodCall.doCall().callParamList().callParam()); + var operation = BinaryOperationNode.create(BslOperator.DEREFERENCE, target, callNode, ctx); + operands.push(operation); + } return ctx; } @@ -442,7 +444,7 @@ public ParseTree visitTernaryOperator(BSLParser.TernaryOperatorContext ctx) { return ctx; } - private static @Nullable BslExpression makeSubexpression(BSLParser.ExpressionContext ctx) { + private static @Nullable BslExpression makeSubexpression(BSLParser.@Nullable ExpressionContext ctx) { return buildExpressionTree(ctx); } diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/utils/expressiontree/TerminalSymbolNode.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/utils/expressiontree/TerminalSymbolNode.java index 296cddac19d..6beaf196879 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/utils/expressiontree/TerminalSymbolNode.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/utils/expressiontree/TerminalSymbolNode.java @@ -24,6 +24,7 @@ import com.github._1c_syntax.bsl.parser.BSLParser; import org.antlr.v4.runtime.tree.ParseTree; import org.antlr.v4.runtime.tree.TerminalNode; +import org.jspecify.annotations.Nullable; /** * Терминальный узел дерева выражений. @@ -32,7 +33,7 @@ * числа, строки, булевы значения, Неопределено, имена переменных. */ public class TerminalSymbolNode extends BslExpression { - private TerminalSymbolNode(ExpressionNodeType type, ParseTree representingAst) { + private TerminalSymbolNode(ExpressionNodeType type, @Nullable ParseTree representingAst) { super(type, representingAst, null); } @@ -48,7 +49,7 @@ public static TerminalSymbolNode literal(BSLParser.ConstValueContext constant) { * @param constant константа * @return терминал константы */ - public static TerminalSymbolNode literal(TerminalNode constant) { + public static TerminalSymbolNode literal(@Nullable TerminalNode constant) { return new TerminalSymbolNode(ExpressionNodeType.LITERAL, constant); } @@ -56,7 +57,7 @@ public static TerminalSymbolNode literal(TerminalNode constant) { * @param identifier идентификатор * @return терминал идентификатора */ - public static TerminalSymbolNode identifier(TerminalNode identifier) { + public static TerminalSymbolNode identifier(@Nullable TerminalNode identifier) { return new TerminalSymbolNode(ExpressionNodeType.IDENTIFIER, identifier); } } diff --git a/src/test/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/AllKnownTokenTest.java b/src/test/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/AllKnownTokenTest.java index a517b2e5e77..0c7560c460a 100644 --- a/src/test/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/AllKnownTokenTest.java +++ b/src/test/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/AllKnownTokenTest.java @@ -60,8 +60,7 @@ public class AllKnownTokenTest { SDBLLexer.SLICEFIRST_VT, SDBLLexer.SLICELAST_VT, SDBLLexer.TASK_BY_PERFORMER_VT, - SDBLLexer.TURNOVERS_VT, - SDBLLexer.BRACE_IDENTIFIER + SDBLLexer.TURNOVERS_VT ); @Test From 5a11395b5edf6b5a16dd48c76d8eea9536e16c34 Mon Sep 17 00:00:00 2001 From: theshadowco Date: Fri, 13 Feb 2026 08:05:05 +0300 Subject: [PATCH 3/3] sq fixes --- .../PermissionFilterBeforeSendCallback.java | 2 +- .../diagnostics/ParseErrorDiagnostic.java | 7 +++++-- .../UsingFindElementByStringDiagnostic.java | 4 ++-- ...oopStatementDocumentHighlightSupplier.java | 6 ++++-- .../SDBLJoinDocumentHighlightSupplier.java | 20 ++++++++++--------- .../bsl/languageserver/utils/Ranges.java | 2 ++ ...singFindElementByStringDiagnosticTest.java | 1 - .../documenthighlight/AllKnownTokenTest.java | 6 ++---- 8 files changed, 27 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/aop/sentry/PermissionFilterBeforeSendCallback.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/aop/sentry/PermissionFilterBeforeSendCallback.java index b11b7f7cd75..2107b6369d8 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/aop/sentry/PermissionFilterBeforeSendCallback.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/aop/sentry/PermissionFilterBeforeSendCallback.java @@ -131,7 +131,7 @@ private CompletableFuture askUserForPermission(LanguageClient return languageClient.showMessageRequest(requestParams); } - private @Nullable MessageActionItem waitForPermission(CompletableFuture<@Nullable MessageActionItem> sendQuestion) { + private @Nullable MessageActionItem waitForPermission(CompletableFuture sendQuestion) { try { return sendQuestion.get(); } catch (InterruptedException e) { diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/ParseErrorDiagnostic.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/ParseErrorDiagnostic.java index 6bed54560fc..1f559082308 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/ParseErrorDiagnostic.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/ParseErrorDiagnostic.java @@ -31,7 +31,6 @@ import com.github._1c_syntax.bsl.parser.BSLParser; import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.tree.ErrorNode; -import org.jspecify.annotations.Nullable; import java.util.StringJoiner; import java.util.stream.IntStream; @@ -88,12 +87,16 @@ public void enterFile(BSLParser.FileContext ctx) { }); } - private static @Nullable String getTokenName(int tokenType) { + private static String getTokenName(int tokenType) { var value = BSLLexer.VOCABULARY.getLiteralName(tokenType); if (value == null) { value = BSLLexer.VOCABULARY.getSymbolicName(tokenType); } + if (value == null) { // вероятность равна нолю + value = ""; + } + return value; } } diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UsingFindElementByStringDiagnostic.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UsingFindElementByStringDiagnostic.java index 18025d77add..eebb0ce8dea 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UsingFindElementByStringDiagnostic.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UsingFindElementByStringDiagnostic.java @@ -61,8 +61,8 @@ public class UsingFindElementByStringDiagnostic extends AbstractVisitorDiagnosti Optional.ofNullable(ctx.doCall()) .map(BSLParser.DoCallContext::callParamList) .ifPresent(callParamList -> { - var param = callParamList.callParam().get(0); - if (param.getChildren().isEmpty() || + var param = callParamList.callParam(0); + if (param == null || param.getChildren().isEmpty() || param.getStart().getType() == BSLParser.STRING || param.getStart().getType() == BSLParser.DECIMAL) { diagnosticStorage.addDiagnostic(ctx, info.getMessage(matcher.group(0))); diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/LoopStatementDocumentHighlightSupplier.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/LoopStatementDocumentHighlightSupplier.java index 6c59913ffa8..314f38bd120 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/LoopStatementDocumentHighlightSupplier.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/LoopStatementDocumentHighlightSupplier.java @@ -230,7 +230,9 @@ private void addBreakAndContinueFromIfStatement(List highligh */ private void addBreakAndContinueFromTryStatement(List highlights, BSLParser.TryStatementContext tryStatement) { - addBreakAndContinueHighlights(highlights, tryStatement.tryCodeBlock().codeBlock()); - addBreakAndContinueHighlights(highlights, tryStatement.exceptCodeBlock().codeBlock()); + Optional.ofNullable(tryStatement.tryCodeBlock()) + .ifPresent(block -> addBreakAndContinueHighlights(highlights, block.codeBlock())); + Optional.ofNullable(tryStatement.exceptCodeBlock()) + .ifPresent(block -> addBreakAndContinueHighlights(highlights, block.codeBlock())); } } diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/SDBLJoinDocumentHighlightSupplier.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/SDBLJoinDocumentHighlightSupplier.java index 3cf066eca12..ba1b154e6d3 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/SDBLJoinDocumentHighlightSupplier.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/SDBLJoinDocumentHighlightSupplier.java @@ -108,15 +108,17 @@ private List highlightJoinPart(SDBLParser.JoinPartContext joi List highlights = new ArrayList<>(); // LEFT/RIGHT/FULL/INNER - if(joinCtx.leftJoin() != null) { - addTokenHighlight(highlights, joinCtx.leftJoin().keyword); - } else if(joinCtx.rightJoin() != null) { - addTokenHighlight(highlights, joinCtx.rightJoin().keyword); - } else if(joinCtx.fullJoin() != null) { - addTokenHighlight(highlights, joinCtx.fullJoin().keyword); - } else if(joinCtx.innerJoin() != null) { - addTokenHighlight(highlights, joinCtx.fullJoin().keyword); - } + Optional.ofNullable(joinCtx.leftJoin()) + .ifPresent(join -> addTokenHighlight(highlights, join.keyword)); + + Optional.ofNullable(joinCtx.rightJoin()) + .ifPresent(join -> addTokenHighlight(highlights, join.keyword)); + + Optional.ofNullable(joinCtx.fullJoin()) + .ifPresent(join -> addTokenHighlight(highlights, join.keyword)); + + Optional.ofNullable(joinCtx.innerJoin()) + .ifPresent(join -> addTokenHighlight(highlights, join.keyword)); addTerminalHighlight(highlights, joinCtx.BY()); diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/utils/Ranges.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/utils/Ranges.java index 5a947d167c9..0645b5ae23f 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/utils/Ranges.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/utils/Ranges.java @@ -30,6 +30,7 @@ import org.eclipse.lsp4j.Range; import org.eclipse.lsp4j.jsonrpc.util.Preconditions; import org.eclipse.lsp4j.util.Positions; +import org.jspecify.annotations.NullMarked; import org.jspecify.annotations.Nullable; import java.util.List; @@ -38,6 +39,7 @@ * Набор методов для удобства работы с областями текста (ренджами) */ @UtilityClass +@NullMarked public final class Ranges { /** diff --git a/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UsingFindElementByStringDiagnosticTest.java b/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UsingFindElementByStringDiagnosticTest.java index 17057f4e1cc..55d60194cb2 100644 --- a/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UsingFindElementByStringDiagnosticTest.java +++ b/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UsingFindElementByStringDiagnosticTest.java @@ -28,7 +28,6 @@ import static com.github._1c_syntax.bsl.languageserver.util.Assertions.assertThat; - class UsingFindElementByStringDiagnosticTest extends AbstractDiagnosticTest { UsingFindElementByStringDiagnosticTest() { diff --git a/src/test/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/AllKnownTokenTest.java b/src/test/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/AllKnownTokenTest.java index 0c7560c460a..18efeed93be 100644 --- a/src/test/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/AllKnownTokenTest.java +++ b/src/test/java/com/github/_1c_syntax/bsl/languageserver/documenthighlight/AllKnownTokenTest.java @@ -24,8 +24,8 @@ import com.github._1c_syntax.bsl.languageserver.semantictokens.strings.SdblTokenTypes; import com.github._1c_syntax.bsl.parser.BSLLexer; import com.github._1c_syntax.bsl.parser.SDBLLexer; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; import java.util.ArrayList; import java.util.List; @@ -36,7 +36,6 @@ /** * Тесты для проверки того, что обо всех токенах лексера было известно */ -@SpringBootTest public class AllKnownTokenTest { private static final Set skippedSdblToken = Set.of( @@ -82,12 +81,11 @@ void sdblTokens() { } @Test + @Disabled("Заготовка. Надо реализовать аналог для bsl lexer") void bslTokens() { List unknown = new ArrayList<>(); // токены имею индекс от одного максимального var endToken = BSLLexer.VOCABULARY.getMaxTokenType(); - // todo реализовать аналог для bsl lexer - assertThat(unknown).isEmpty(); } }