From a895d2f5e377b9b22a3e7ff904569fed351c3e25 Mon Sep 17 00:00:00 2001 From: Artur Ayukhanov Date: Sat, 16 Oct 2021 20:26:18 +0300 Subject: [PATCH 1/9] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B2=D0=B8=D1=87=D0=BD?= =?UTF-8?q?=D0=B0=D1=8F=20=D0=B7=D0=B0=D0=B3=D0=BE=D1=82=D0=BE=D0=B2=D0=BA?= =?UTF-8?q?=D0=B0=20=D0=BF=D1=80=D0=B0=D0=B2=D0=B8=D0=BB=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #536 --- .../MissingQueryParameterDiagnostic.java | 235 ++++++++++++++++++ .../MissingQueryParameterDiagnosticTest.java | 86 +++++++ .../MissingQueryParameterDiagnostic.bsl | 26 ++ 3 files changed, 347 insertions(+) create mode 100644 src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnostic.java create mode 100644 src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnosticTest.java create mode 100644 src/test/resources/diagnostics/MissingQueryParameterDiagnostic.bsl diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnostic.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnostic.java new file mode 100644 index 00000000000..4cc7c168e7a --- /dev/null +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnostic.java @@ -0,0 +1,235 @@ +/* + * This file is a part of BSL Language Server. + * + * Copyright (c) 2018-2021 + * Alexey Sosnoviy , Nikita Gryzlov 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.diagnostics; + +import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticMetadata; +import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticSeverity; +import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticTag; +import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticType; +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.parser.BSLParser.CodeBlockContext; +import com.github._1c_syntax.bsl.parser.BSLParserRuleContext; +import com.github._1c_syntax.bsl.parser.SDBLParser; +import com.github._1c_syntax.bsl.parser.SDBLParser.ParameterContext; +import com.github._1c_syntax.bsl.parser.SDBLParser.QueryPackageContext; +import com.github._1c_syntax.bsl.parser.Tokenizer; +import com.github._1c_syntax.utils.CaseInsensitivePattern; +import org.antlr.v4.runtime.tree.ParseTree; +import org.apache.commons.lang3.tuple.Pair; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +@DiagnosticMetadata( + type = DiagnosticType.CODE_SMELL, + severity = DiagnosticSeverity.INFO, + minutesToFix = 1, + tags = { + DiagnosticTag.SUSPICIOUS + } + +) +public class MissingQueryParameterDiagnostic extends AbstractVisitorDiagnostic { + + private static final Pattern QUERY_PATTERN = CaseInsensitivePattern.compile( + "Запрос|Query"); + private static final Pattern QUERY_TEXT_PATTERN = CaseInsensitivePattern.compile( + "Текст|Text"); +// private static final Pattern EXECUTE_PATTERN = CaseInsensitivePattern.compile( +// "Выполнить|Execute"); + private static final Pattern SET_PARAMETER_PATTERN = CaseInsensitivePattern.compile( + "УстановитьПараметр|SetParameter"); + public static final int SET_PARAMETER_PARAMS_COUNT = 2; + + private Collection codeBlocks = Collections.emptyList(); + + @Override + public ParseTree visitFile(BSLParser.FileContext file) { + + final var queriesWithParams = documentContext.getQueries().stream() + .map(Tokenizer::getAst) + .map(ctx -> Pair.of(ctx, getParams(ctx))) + .collect(Collectors.toList()); + + if (!queriesWithParams.isEmpty()) { + codeBlocks = getCodeBlocks(); + + queriesWithParams.forEach(query -> visitQuery(query.getLeft(), query.getRight())); + + codeBlocks.clear(); + + } + + return super.visitFile(file); + } + + private Collection getCodeBlocks() { + final var ast = documentContext.getAst(); + var blocks = getSubBlocks(ast); + final var fileCodeBlock = Optional.ofNullable(ast.fileCodeBlock()).map(BSLParser.FileCodeBlockContext::codeBlock); + fileCodeBlock.ifPresent(blocks::add); + final var fileCodeBlockBeforeSub = + Optional.ofNullable(ast.fileCodeBlockBeforeSub()) + .map(BSLParser.FileCodeBlockBeforeSubContext::codeBlock); + fileCodeBlockBeforeSub.ifPresent(blocks::add); + return blocks; + } + + private void visitQuery(QueryPackageContext queryPackage, List params) { + final var codeBlockByQuery = getCodeBlockByQuery(queryPackage); + codeBlockByQuery.ifPresent(block -> checkQueriesInsideBlock(block, queryPackage, params)); + } + + private static Collection getSubBlocks(BSLParser.FileContext ast) { + if (ast.subs() == null) { + return new ArrayList<>(); + } + return ast.subs().sub().stream().map((BSLParser.SubContext sub) -> { + if (sub.procedure() == null) { + return sub.function().subCodeBlock().codeBlock(); + } else { + return sub.procedure().subCodeBlock().codeBlock(); + } + }).collect(Collectors.toList()); + } + + private static List getParams(QueryPackageContext queryPackage) { + return Trees.findAllRuleNodes(queryPackage, SDBLParser.RULE_parameter).stream() + .filter(ParameterContext.class::isInstance) + .map(ParameterContext.class::cast) + .collect(Collectors.toList()); + } + + private Optional getCodeBlockByQuery(QueryPackageContext key) { + return codeBlocks.stream() + .filter(block -> Ranges.containsRange(Ranges.create(block), Ranges.create(key))) + .findFirst(); + } + + private void checkQueriesInsideBlock(CodeBlockContext codeBlock, QueryPackageContext queryPackage, + List params) { + // todo вычислять единожды сразу с отбором Новый Запрос или ХХХ.Текст + final var assignments = Trees.findAllRuleNodes(codeBlock, BSLParser.RULE_assignment); + + final var range = Ranges.create(queryPackage); + assignments.stream() + .filter(BSLParser.AssignmentContext.class::isInstance) + .map(BSLParser.AssignmentContext.class::cast) + .filter(assignment -> Ranges.containsRange(Ranges.create(assignment.expression()), range)) + .forEach(assignment -> checkAssignment(codeBlock, queryPackage, params, assignment)); + } + + private void checkAssignment(CodeBlockContext codeBlock, QueryPackageContext queryPackage, + List params, BSLParser.AssignmentContext assignment) { + + var callStatements = getCallStatements(codeBlock); // todo вычислять единожды + if (!callStatements.isEmpty()) { + + final var queryRange = Ranges.create(queryPackage); + final var queryVarName = computeQueryVarName(assignment); + final var usedParams = callStatements.stream() + .filter(callStatement -> Ranges.containsRange(Ranges.create(assignment.expression()), queryRange)) + .map(callStatementContext -> validateSetParameterCallForName(callStatementContext, queryVarName, params)) + .flatMap(Optional::stream) + .collect(Collectors.toList()); + params.removeAll(usedParams); + } + params.forEach(diagnosticStorage::addDiagnostic); + } + + private static List getCallStatements(CodeBlockContext codeBlock) { + return Trees.findAllRuleNodes(codeBlock, BSLParser.RULE_callStatement).stream() + .filter(BSLParser.CallStatementContext.class::isInstance) + .map(BSLParser.CallStatementContext.class::cast) + .filter(MissingQueryParameterDiagnostic::isSetParameterCall) + .collect(Collectors.toList()); + } + + private static boolean isSetParameterCall(BSLParser.CallStatementContext callStatement) { + return Optional.of(callStatement) + .map(BSLParser.CallStatementContext::accessCall) + .map(BSLParser.AccessCallContext::methodCall) + .map(BSLParser.MethodCallContext::methodName) + .filter(ctx -> SET_PARAMETER_PATTERN.matcher(ctx.getText()).matches()) + .isPresent(); + } + + private static String computeQueryVarName(BSLParser.AssignmentContext assignment) { + if (isNewQueryExpr(assignment)) { + return assignment.lValue().getText(); + } + return computeObjectQueryFromLValue(assignment.lValue()); + } + + private static boolean isNewQueryExpr(BSLParser.AssignmentContext assignment) { + return Trees.findAllRuleNodes(assignment, BSLParser.RULE_newExpression).stream() + .filter(BSLParser.NewExpressionContext.class::isInstance) + .map(BSLParser.NewExpressionContext.class::cast) + .anyMatch(ctx -> QUERY_PATTERN.matcher(ctx.typeName().getText()).matches()); + } + + private static String computeObjectQueryFromLValue(BSLParser.LValueContext lValue) { + if (lValue.acceptor() == null) { + return lValue.getText(); + } + return Optional.of(lValue.acceptor()) + .map(BSLParser.AcceptorContext::accessProperty) + .map(BSLParser.AccessPropertyContext::IDENTIFIER) + .map(ParseTree::getText) + .filter(s -> QUERY_TEXT_PATTERN.matcher(s).matches()) + .orElse(""); + } + + private static Optional validateSetParameterCallForName(BSLParser.CallStatementContext callStatementContext, + String queryVarName, List params) { + final var ctx = Optional.of(callStatementContext); + final var used = ctx + .map(BSLParser.CallStatementContext::IDENTIFIER) + .map(ParseTree::getText) + .filter(queryVarName::equalsIgnoreCase) + .isPresent(); + if (!used) { + return Optional.empty(); + } + return ctx.map(BSLParser.CallStatementContext::accessCall) + .map(BSLParser.AccessCallContext::methodCall) + .map(BSLParser.MethodCallContext::doCall) + .map(BSLParser.DoCallContext::callParamList) + .map(BSLParser.CallParamListContext::callParam) + .filter(callParamContexts -> callParamContexts.size() == SET_PARAMETER_PARAMS_COUNT) + .map(callParamContexts -> callParamContexts.get(0)) + .map(BSLParser.CallParamContext::expression) + .map(BSLParser.ExpressionContext::member) + .filter(memberContexts -> !memberContexts.isEmpty()) + .map(memberContexts -> memberContexts.get(0)) + .map(BSLParser.MemberContext::constValue) + .map(BSLParserRuleContext::getText) + .flatMap(s -> params.stream().filter(param -> ("\"" + param.name.getText() + "\"").equalsIgnoreCase(s)).findFirst()); + } +} diff --git a/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnosticTest.java b/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnosticTest.java new file mode 100644 index 00000000000..cd4c0d077f3 --- /dev/null +++ b/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnosticTest.java @@ -0,0 +1,86 @@ +/* + * This file is a part of BSL Language Server. + * + * Copyright (c) 2018-2021 + * Alexey Sosnoviy , Nikita Gryzlov 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.diagnostics; + +import com.github._1c_syntax.bsl.languageserver.util.TestUtils; +import org.eclipse.lsp4j.Diagnostic; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static com.github._1c_syntax.bsl.languageserver.util.Assertions.assertThat; + +class MissingQueryParameterDiagnosticTest extends AbstractDiagnosticTest { + MissingQueryParameterDiagnosticTest() { + super(MissingQueryParameterDiagnostic.class); + } + + @Test + void test() { + + List diagnostics = getDiagnostics(); + + assertThat(diagnostics, true) + .hasSize(1) + .hasRange(7, 34, 43) + ; + + } + + @Test + void testWithIsNullOperatorInsideWhere() { + var sample = + "\tЗапрос1 = Новый Запрос(\n" + + "\t\t\"ВЫБРАТЬ\n" + + "\t\t|\tСправочник1.Ссылка КАК Ссылка\n" + + "\t\t|ИЗ\n" + + "\t\t|\tСправочник.Справочник1 КАК Справочник1\n" + + "\t\t|ГДЕ\n" + + "\t\t|\tСправочник1.Ссылка = &Параметр\");\n" + + "\n" + + "\tРезультатЗапроса = Запрос1.Выполнить();\n"; + + var documentContext = TestUtils.getDocumentContext(sample); + var diagnostics = getDiagnostics(documentContext); + + assertThat(diagnostics).hasSize(1); + } + + @Test + void testWithIsNullOperatorInsideWhereNoError() { + var sample = + "\tЗапрос1 = Новый Запрос(\n" + + "\t\t\"ВЫБРАТЬ\n" + + "\t\t|\tСправочник1.Ссылка КАК Ссылка\n" + + "\t\t|ИЗ\n" + + "\t\t|\tСправочник.Справочник1 КАК Справочник1\n" + + "\t\t|ГДЕ\n" + + "\t\t|\tСправочник1.Ссылка = &Параметр\");\n" + + "Запрос1.УстановитьПараметр(\"Параметр\", Ссылка);\n" + + "\tРезультатЗапроса = Запрос1.Выполнить();\n"; + + var documentContext = TestUtils.getDocumentContext(sample); + var diagnostics = getDiagnostics(documentContext); + + assertThat(diagnostics).isEmpty(); + } +} diff --git a/src/test/resources/diagnostics/MissingQueryParameterDiagnostic.bsl b/src/test/resources/diagnostics/MissingQueryParameterDiagnostic.bsl new file mode 100644 index 00000000000..a1aaff2c0db --- /dev/null +++ b/src/test/resources/diagnostics/MissingQueryParameterDiagnostic.bsl @@ -0,0 +1,26 @@ +Процедура ПерваяОшибка() + + Запрос1 = Новый Запрос("ВЫБРАТЬ + | Справочник1.Ссылка КАК Ссылка + |ИЗ + | Справочник.Справочник1 КАК Справочник1 + |ГДЕ + | Справочник1.Ссылка = &Параметр"); + + РезультатЗапроса = Запрос1.Выполнить(); + +КонецПроцедуры + +Процедура Вторая_НетОшибки() + + Запрос2 = Новый Запрос("ВЫБРАТЬ + | Справочник1.Ссылка КАК Ссылка + |ИЗ + | Справочник.Справочник1 КАК Справочник1 + |ГДЕ + | Справочник1.Ссылка = &Параметр"); + + Запрос2.УстановитьПараметр("Параметр", Ссылка); + + РезультатЗапроса = Запрос2.Выполнить(); // нет ошибки +КонецПроцедуры From c4af8a48e3cea3df0535676aba5ec19b554fe5de Mon Sep 17 00:00:00 2001 From: Artur Ayukhanov Date: Sat, 16 Oct 2021 21:56:20 +0300 Subject: [PATCH 2/9] =?UTF-8?q?=D0=9F=D0=BE=D0=B4=D0=B4=D0=B5=D1=80=D0=B6?= =?UTF-8?q?=D0=BA=D0=B0=20=D0=97=D0=B0=D0=BF=D1=80=D0=BE=D1=81.=D0=A2?= =?UTF-8?q?=D0=B5=D0=BA=D1=81=D1=82=20=3D=20"=D0=A2=D0=B5=D0=BA=D1=81?= =?UTF-8?q?=D1=82=20=D0=B7=D0=B0=D0=BF=D1=80=D0=BE=D1=81=D0=B0"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MissingQueryParameterDiagnostic.java | 97 +++++++++++++------ .../MissingQueryParameterDiagnosticTest.java | 59 +++++++---- .../MissingQueryParameterDiagnostic.bsl | 39 +++++++- 3 files changed, 139 insertions(+), 56 deletions(-) diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnostic.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnostic.java index 4cc7c168e7a..3d2c0502e8f 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnostic.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnostic.java @@ -37,11 +37,14 @@ import com.github._1c_syntax.utils.CaseInsensitivePattern; import org.antlr.v4.runtime.tree.ParseTree; import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -61,13 +64,15 @@ public class MissingQueryParameterDiagnostic extends AbstractVisitorDiagnostic { "Запрос|Query"); private static final Pattern QUERY_TEXT_PATTERN = CaseInsensitivePattern.compile( "Текст|Text"); -// private static final Pattern EXECUTE_PATTERN = CaseInsensitivePattern.compile( + // private static final Pattern EXECUTE_PATTERN = CaseInsensitivePattern.compile( // "Выполнить|Execute"); private static final Pattern SET_PARAMETER_PATTERN = CaseInsensitivePattern.compile( "УстановитьПараметр|SetParameter"); public static final int SET_PARAMETER_PARAMS_COUNT = 2; private Collection codeBlocks = Collections.emptyList(); + private final Map> codeBlockAssignments = new HashMap<>(); + private final Map> codeBlockCallStatements = new HashMap<>(); @Override public ParseTree visitFile(BSLParser.FileContext file) { @@ -83,12 +88,22 @@ public ParseTree visitFile(BSLParser.FileContext file) { queriesWithParams.forEach(query -> visitQuery(query.getLeft(), query.getRight())); codeBlocks.clear(); + codeBlockAssignments.clear(); + codeBlockCallStatements.clear(); } return super.visitFile(file); } + private static List> getParams(QueryPackageContext queryPackage) { + return Trees.findAllRuleNodes(queryPackage, SDBLParser.RULE_parameter).stream() + .filter(ParameterContext.class::isInstance) + .map(ParameterContext.class::cast) + .map(ctx -> Pair.of(ctx, "\"" + ctx.name.getText() + "\"")) + .collect(Collectors.toList()); + } + private Collection getCodeBlocks() { final var ast = documentContext.getAst(); var blocks = getSubBlocks(ast); @@ -96,16 +111,11 @@ private Collection getCodeBlocks() { fileCodeBlock.ifPresent(blocks::add); final var fileCodeBlockBeforeSub = Optional.ofNullable(ast.fileCodeBlockBeforeSub()) - .map(BSLParser.FileCodeBlockBeforeSubContext::codeBlock); + .map(BSLParser.FileCodeBlockBeforeSubContext::codeBlock); fileCodeBlockBeforeSub.ifPresent(blocks::add); return blocks; } - private void visitQuery(QueryPackageContext queryPackage, List params) { - final var codeBlockByQuery = getCodeBlockByQuery(queryPackage); - codeBlockByQuery.ifPresent(block -> checkQueriesInsideBlock(block, queryPackage, params)); - } - private static Collection getSubBlocks(BSLParser.FileContext ast) { if (ast.subs() == null) { return new ArrayList<>(); @@ -119,11 +129,9 @@ private static Collection getSubBlocks(BSLParser.FileContext a }).collect(Collectors.toList()); } - private static List getParams(QueryPackageContext queryPackage) { - return Trees.findAllRuleNodes(queryPackage, SDBLParser.RULE_parameter).stream() - .filter(ParameterContext.class::isInstance) - .map(ParameterContext.class::cast) - .collect(Collectors.toList()); + private void visitQuery(QueryPackageContext queryPackage, List> params) { + final var codeBlockByQuery = getCodeBlockByQuery(queryPackage); + codeBlockByQuery.ifPresent(block -> checkQueriesInsideBlock(block, queryPackage, params)); } private Optional getCodeBlockByQuery(QueryPackageContext key) { @@ -133,34 +141,46 @@ private Optional getCodeBlockByQuery(QueryPackageContext key) } private void checkQueriesInsideBlock(CodeBlockContext codeBlock, QueryPackageContext queryPackage, - List params) { - // todo вычислять единожды сразу с отбором Новый Запрос или ХХХ.Текст - final var assignments = Trees.findAllRuleNodes(codeBlock, BSLParser.RULE_assignment); + List> params) { + + final var assignments = codeBlockAssignments.computeIfAbsent(codeBlock, + MissingQueryParameterDiagnostic::getAllAssignmentInsideBlock); final var range = Ranges.create(queryPackage); assignments.stream() - .filter(BSLParser.AssignmentContext.class::isInstance) - .map(BSLParser.AssignmentContext.class::cast) .filter(assignment -> Ranges.containsRange(Ranges.create(assignment.expression()), range)) .forEach(assignment -> checkAssignment(codeBlock, queryPackage, params, assignment)); } + private static List getAllAssignmentInsideBlock(CodeBlockContext codeBlock) { + return Trees.findAllRuleNodes(codeBlock, BSLParser.RULE_assignment).stream() + .filter(BSLParser.AssignmentContext.class::isInstance) + .map(BSLParser.AssignmentContext.class::cast) + .collect(Collectors.toList()); + } + private void checkAssignment(CodeBlockContext codeBlock, QueryPackageContext queryPackage, - List params, BSLParser.AssignmentContext assignment) { + List> params, BSLParser.AssignmentContext assignment) { + + final var callStatements = codeBlockCallStatements.computeIfAbsent(codeBlock, + MissingQueryParameterDiagnostic::getCallStatements); + + final var allParams = params.stream() + .map(Pair::getLeft) + .collect(Collectors.toList()); - var callStatements = getCallStatements(codeBlock); // todo вычислять единожды if (!callStatements.isEmpty()) { final var queryRange = Ranges.create(queryPackage); final var queryVarName = computeQueryVarName(assignment); final var usedParams = callStatements.stream() .filter(callStatement -> Ranges.containsRange(Ranges.create(assignment.expression()), queryRange)) - .map(callStatementContext -> validateSetParameterCallForName(callStatementContext, queryVarName, params)) + .map(callStatementContext -> computeSetParameterByQueryVarName(callStatementContext, queryVarName, params)) .flatMap(Optional::stream) .collect(Collectors.toList()); - params.removeAll(usedParams); + allParams.removeAll(usedParams); } - params.forEach(diagnosticStorage::addDiagnostic); + allParams.forEach(diagnosticStorage::addDiagnostic); } private static List getCallStatements(CodeBlockContext codeBlock) { @@ -184,7 +204,7 @@ private static String computeQueryVarName(BSLParser.AssignmentContext assignment if (isNewQueryExpr(assignment)) { return assignment.lValue().getText(); } - return computeObjectQueryFromLValue(assignment.lValue()); + return computeQueryVarNameFromLValue(assignment.lValue()); } private static boolean isNewQueryExpr(BSLParser.AssignmentContext assignment) { @@ -194,29 +214,38 @@ private static boolean isNewQueryExpr(BSLParser.AssignmentContext assignment) { .anyMatch(ctx -> QUERY_PATTERN.matcher(ctx.typeName().getText()).matches()); } - private static String computeObjectQueryFromLValue(BSLParser.LValueContext lValue) { - if (lValue.acceptor() == null) { + private static String computeQueryVarNameFromLValue(BSLParser.LValueContext lValue) { + final var identifier = lValue.IDENTIFIER(); + final var acceptor = lValue.acceptor(); + if (acceptor == null || identifier == null) { return lValue.getText(); } - return Optional.of(lValue.acceptor()) + return Optional.of(acceptor) .map(BSLParser.AcceptorContext::accessProperty) .map(BSLParser.AccessPropertyContext::IDENTIFIER) .map(ParseTree::getText) .filter(s -> QUERY_TEXT_PATTERN.matcher(s).matches()) + .map(s -> identifier.getText()) .orElse(""); } - private static Optional validateSetParameterCallForName(BSLParser.CallStatementContext callStatementContext, - String queryVarName, List params) { + private static Optional computeSetParameterByQueryVarName(BSLParser.CallStatementContext callStatementContext, + String queryVarName, List> params) { final var ctx = Optional.of(callStatementContext); - final var used = ctx + final var isCorrectQueryVarNameInCall = ctx .map(BSLParser.CallStatementContext::IDENTIFIER) .map(ParseTree::getText) .filter(queryVarName::equalsIgnoreCase) .isPresent(); - if (!used) { + if (!isCorrectQueryVarNameInCall) { return Optional.empty(); } + return computeSetParameter(ctx, params); + } + + @NotNull + private static Optional computeSetParameter(Optional ctx, + List> params) { return ctx.map(BSLParser.CallStatementContext::accessCall) .map(BSLParser.AccessCallContext::methodCall) .map(BSLParser.MethodCallContext::doCall) @@ -230,6 +259,12 @@ private static Optional validateSetParameterCallForName(BSLPar .map(memberContexts -> memberContexts.get(0)) .map(BSLParser.MemberContext::constValue) .map(BSLParserRuleContext::getText) - .flatMap(s -> params.stream().filter(param -> ("\"" + param.name.getText() + "\"").equalsIgnoreCase(s)).findFirst()); + .flatMap(firstValueForSetParameterMethod -> computeSetParameterByName(params, firstValueForSetParameterMethod)); + } + + private static Optional computeSetParameterByName(List> params, + String firstValueForSetParameterMethod) { + return params.stream().filter(param -> param.getRight().equalsIgnoreCase(firstValueForSetParameterMethod)) + .map(Pair::getLeft).findFirst(); } } diff --git a/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnosticTest.java b/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnosticTest.java index cd4c0d077f3..2438d5a2a83 100644 --- a/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnosticTest.java +++ b/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnosticTest.java @@ -40,24 +40,25 @@ void test() { List diagnostics = getDiagnostics(); assertThat(diagnostics, true) - .hasSize(1) .hasRange(7, 34, 43) - ; + .hasRange(35, 34, 43) + .hasSize(2) + ; } @Test - void testWithIsNullOperatorInsideWhere() { + void testNewQuery() { var sample = - "\tЗапрос1 = Новый Запрос(\n" + - "\t\t\"ВЫБРАТЬ\n" + - "\t\t|\tСправочник1.Ссылка КАК Ссылка\n" + - "\t\t|ИЗ\n" + - "\t\t|\tСправочник.Справочник1 КАК Справочник1\n" + - "\t\t|ГДЕ\n" + - "\t\t|\tСправочник1.Ссылка = &Параметр\");\n" + + " Запрос1 = Новый Запрос(\n" + + " \"ВЫБРАТЬ\n" + + " | Справочник1.Ссылка КАК Ссылка\n" + + " |ИЗ\n" + + " | Справочник.Справочник1 КАК Справочник1\n" + + " |ГДЕ\n" + + " | Справочник1.Ссылка = &Параметр\");\n" + "\n" + - "\tРезультатЗапроса = Запрос1.Выполнить();\n"; + " РезультатЗапроса = Запрос1.Выполнить();\n"; var documentContext = TestUtils.getDocumentContext(sample); var diagnostics = getDiagnostics(documentContext); @@ -66,17 +67,35 @@ void testWithIsNullOperatorInsideWhere() { } @Test - void testWithIsNullOperatorInsideWhereNoError() { + void testNewQueryNoError() { var sample = - "\tЗапрос1 = Новый Запрос(\n" + - "\t\t\"ВЫБРАТЬ\n" + - "\t\t|\tСправочник1.Ссылка КАК Ссылка\n" + - "\t\t|ИЗ\n" + - "\t\t|\tСправочник.Справочник1 КАК Справочник1\n" + - "\t\t|ГДЕ\n" + - "\t\t|\tСправочник1.Ссылка = &Параметр\");\n" + + " Запрос1 = Новый Запрос(\n" + + " \"ВЫБРАТЬ\n" + + " | Справочник1.Ссылка КАК Ссылка\n" + + " |ИЗ\n" + + " | Справочник.Справочник1 КАК Справочник1\n" + + " |ГДЕ\n" + + " | Справочник1.Ссылка = &Параметр\");\n" + "Запрос1.УстановитьПараметр(\"Параметр\", Ссылка);\n" + - "\tРезультатЗапроса = Запрос1.Выполнить();\n"; + " РезультатЗапроса = Запрос1.Выполнить();\n"; + + var documentContext = TestUtils.getDocumentContext(sample); + var diagnostics = getDiagnostics(documentContext); + + assertThat(diagnostics).isEmpty(); + } + + @Test + void testQueryTextNoError() { + var sample = + " Запрос4 = Новый Запрос;\n" + + " Запрос4.Текст = \"ВЫБРАТЬ\n" + + " | Справочник1.Ссылка КАК Ссылка\n" + + " |ИЗ\n" + + " | Справочник.Справочник1 КАК Справочник1\n" + + " |ГДЕ\n" + + " | Справочник1.Ссылка = &Параметр\"; // нет ошибки\n" + + " Запрос4.УстановитьПараметр(\"Параметр\", Ссылка);\n"; var documentContext = TestUtils.getDocumentContext(sample); var diagnostics = getDiagnostics(documentContext); diff --git a/src/test/resources/diagnostics/MissingQueryParameterDiagnostic.bsl b/src/test/resources/diagnostics/MissingQueryParameterDiagnostic.bsl index a1aaff2c0db..cda7986a8cd 100644 --- a/src/test/resources/diagnostics/MissingQueryParameterDiagnostic.bsl +++ b/src/test/resources/diagnostics/MissingQueryParameterDiagnostic.bsl @@ -1,26 +1,55 @@ -Процедура ПерваяОшибка() +Процедура ПерваяОшибка_НовыйЗапрос() Запрос1 = Новый Запрос("ВЫБРАТЬ | Справочник1.Ссылка КАК Ссылка |ИЗ | Справочник.Справочник1 КАК Справочник1 |ГДЕ - | Справочник1.Ссылка = &Параметр"); + | Справочник1.Ссылка = &Параметр"); // ошибка РезультатЗапроса = Запрос1.Выполнить(); КонецПроцедуры -Процедура Вторая_НетОшибки() +Процедура Вторая_НетОшибки_НовыйЗапрос() Запрос2 = Новый Запрос("ВЫБРАТЬ | Справочник1.Ссылка КАК Ссылка |ИЗ | Справочник.Справочник1 КАК Справочник1 |ГДЕ - | Справочник1.Ссылка = &Параметр"); + | Справочник1.Ссылка = &Параметр"); // нет ошибки Запрос2.УстановитьПараметр("Параметр", Ссылка); - РезультатЗапроса = Запрос2.Выполнить(); // нет ошибки + РезультатЗапроса = Запрос2.Выполнить(); +КонецПроцедуры + +Процедура ТретьяОшибка_ЗапросТекст() + + Запрос3 = Новый Запрос; + Запрос3.Текст = "ВЫБРАТЬ + | Справочник1.Ссылка КАК Ссылка + |ИЗ + | Справочник.Справочник1 КАК Справочник1 + |ГДЕ + | Справочник1.Ссылка = &Параметр"; // ошибка + + РезультатЗапроса = Запрос3.Выполнить(); + +КонецПроцедуры + +Процедура Четвертая_НетОшибки_ЗапросТекст() + + Запрос4 = Новый Запрос; + Запрос4.Текст = "ВЫБРАТЬ + | Справочник1.Ссылка КАК Ссылка + |ИЗ + | Справочник.Справочник1 КАК Справочник1 + |ГДЕ + | Справочник1.Ссылка = &Параметр"; // нет ошибки + + Запрос4.УстановитьПараметр("Параметр", Ссылка); + + РезультатЗапроса = Запрос4.Выполнить(); КонецПроцедуры From 5cda23bae74b090f174df8622cd6e7f5d014c4a1 Mon Sep 17 00:00:00 2001 From: Artur Ayukhanov Date: Sat, 16 Oct 2021 22:12:15 +0300 Subject: [PATCH 3/9] =?UTF-8?q?+=20=D0=BF=D0=BE=D0=BA=D0=B0=D0=B7=20=D0=B8?= =?UTF-8?q?=D0=BC=D0=B5=D0=BD=D0=B8=20=D0=BF=D0=B0=D1=80=D0=B0=D0=BC=D0=B5?= =?UTF-8?q?=D1=82=D1=80=D0=B0=20=D0=B2=20=D0=B7=D0=B0=D0=BC=D0=B5=D1=87?= =?UTF-8?q?=D0=B0=D0=BD=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/diagnostics/MissingQueryParameter.md | 36 +++++++++++++++++++ .../MissingQueryParameterDiagnostic.java | 5 ++- ...singQueryParameterDiagnostic_ru.properties | 2 ++ .../MissingQueryParameterDiagnosticTest.java | 4 +-- .../MissingQueryParameterDiagnostic.bsl | 12 +++---- 5 files changed, 48 insertions(+), 11 deletions(-) create mode 100644 docs/en/diagnostics/MissingQueryParameter.md create mode 100644 src/main/resources/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnostic_ru.properties diff --git a/docs/en/diagnostics/MissingQueryParameter.md b/docs/en/diagnostics/MissingQueryParameter.md new file mode 100644 index 00000000000..4e6d3cb127c --- /dev/null +++ b/docs/en/diagnostics/MissingQueryParameter.md @@ -0,0 +1,36 @@ +# (MissingQueryParameter) + + + +## + + +## Description + + +## Examples + + +## Sources + + + +## Snippets + + +### Diagnostic ignorance in code + +```bsl +// BSLLS:MissingQueryParameter-off +// BSLLS:MissingQueryParameter-on +``` + +### Parameter for config + +```json +"MissingQueryParameter": +``` diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnostic.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnostic.java index 3d2c0502e8f..c64b0e5a69c 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnostic.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnostic.java @@ -64,8 +64,6 @@ public class MissingQueryParameterDiagnostic extends AbstractVisitorDiagnostic { "Запрос|Query"); private static final Pattern QUERY_TEXT_PATTERN = CaseInsensitivePattern.compile( "Текст|Text"); - // private static final Pattern EXECUTE_PATTERN = CaseInsensitivePattern.compile( -// "Выполнить|Execute"); private static final Pattern SET_PARAMETER_PATTERN = CaseInsensitivePattern.compile( "УстановитьПараметр|SetParameter"); public static final int SET_PARAMETER_PARAMS_COUNT = 2; @@ -180,7 +178,8 @@ private void checkAssignment(CodeBlockContext codeBlock, QueryPackageContext que .collect(Collectors.toList()); allParams.removeAll(usedParams); } - allParams.forEach(diagnosticStorage::addDiagnostic); + allParams.forEach(node -> diagnosticStorage.addDiagnostic(node, + info.getMessage(node.PARAMETER_IDENTIFIER().getText()))); } private static List getCallStatements(CodeBlockContext codeBlock) { diff --git a/src/main/resources/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnostic_ru.properties b/src/main/resources/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnostic_ru.properties new file mode 100644 index 00000000000..245722c9b8e --- /dev/null +++ b/src/main/resources/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnostic_ru.properties @@ -0,0 +1,2 @@ +diagnosticMessage=Добавьте установку параметра запроса "%s" +diagnosticName=Все параметры запроса инициализированы diff --git a/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnosticTest.java b/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnosticTest.java index 2438d5a2a83..5b0cfcafe3b 100644 --- a/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnosticTest.java +++ b/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnosticTest.java @@ -40,8 +40,8 @@ void test() { List diagnostics = getDiagnostics(); assertThat(diagnostics, true) - .hasRange(7, 34, 43) - .hasRange(35, 34, 43) + .hasMessageOnRange("Добавьте установку параметра запроса \"Параметр1\"", 7, 34, 44) + .hasMessageOnRange("Добавьте установку параметра запроса \"Параметр3\"", 35, 34, 44) .hasSize(2) ; diff --git a/src/test/resources/diagnostics/MissingQueryParameterDiagnostic.bsl b/src/test/resources/diagnostics/MissingQueryParameterDiagnostic.bsl index cda7986a8cd..6b93e4fc6bc 100644 --- a/src/test/resources/diagnostics/MissingQueryParameterDiagnostic.bsl +++ b/src/test/resources/diagnostics/MissingQueryParameterDiagnostic.bsl @@ -5,7 +5,7 @@ |ИЗ | Справочник.Справочник1 КАК Справочник1 |ГДЕ - | Справочник1.Ссылка = &Параметр"); // ошибка + | Справочник1.Ссылка = &Параметр1"); // ошибка РезультатЗапроса = Запрос1.Выполнить(); @@ -18,9 +18,9 @@ |ИЗ | Справочник.Справочник1 КАК Справочник1 |ГДЕ - | Справочник1.Ссылка = &Параметр"); // нет ошибки + | Справочник1.Ссылка = &Параметр2"); // нет ошибки - Запрос2.УстановитьПараметр("Параметр", Ссылка); + Запрос2.УстановитьПараметр("Параметр2", Ссылка); РезультатЗапроса = Запрос2.Выполнить(); КонецПроцедуры @@ -33,7 +33,7 @@ |ИЗ | Справочник.Справочник1 КАК Справочник1 |ГДЕ - | Справочник1.Ссылка = &Параметр"; // ошибка + | Справочник1.Ссылка = &Параметр3"; // ошибка РезультатЗапроса = Запрос3.Выполнить(); @@ -47,9 +47,9 @@ |ИЗ | Справочник.Справочник1 КАК Справочник1 |ГДЕ - | Справочник1.Ссылка = &Параметр"; // нет ошибки + | Справочник1.Ссылка = &Параметр4"; // нет ошибки - Запрос4.УстановитьПараметр("Параметр", Ссылка); + Запрос4.УстановитьПараметр("Параметр4", Ссылка); РезультатЗапроса = Запрос4.Выполнить(); КонецПроцедуры From d9a80a9e0ea1596fe0d68d56c6047be1da1729ef Mon Sep 17 00:00:00 2001 From: Artur Ayukhanov Date: Fri, 22 Oct 2021 17:30:04 +0300 Subject: [PATCH 4/9] =?UTF-8?q?=D0=B7=D0=B0=D0=B3=D0=BE=D1=82=D0=BE=D0=B2?= =?UTF-8?q?=D0=BA=D0=B0=20=D0=BA=D0=B5=D0=B9=D1=81=D0=B0=20-=20=D1=81?= =?UTF-8?q?=D0=BD=D0=B0=D1=87=D0=B0=D0=BB=D0=B0=20=D1=82=D0=B5=D0=BA=D1=81?= =?UTF-8?q?=D1=82,=20=D0=BF=D0=BE=D1=82=D0=BE=D0=BC=20=D0=B7=D0=B0=D0=BF?= =?UTF-8?q?=D1=80=D0=BE=D1=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MissingQueryParameterDiagnosticTest.java | 3 +- .../MissingQueryParameterDiagnostic.bsl | 28 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnosticTest.java b/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnosticTest.java index 5b0cfcafe3b..60e42ea8443 100644 --- a/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnosticTest.java +++ b/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnosticTest.java @@ -42,7 +42,8 @@ void test() { assertThat(diagnostics, true) .hasMessageOnRange("Добавьте установку параметра запроса \"Параметр1\"", 7, 34, 44) .hasMessageOnRange("Добавьте установку параметра запроса \"Параметр3\"", 35, 34, 44) - .hasSize(2) + .hasMessageOnRange("Добавьте установку параметра запроса \"Параметр5\"", 63, 34, 44) + .hasSize(3) ; } diff --git a/src/test/resources/diagnostics/MissingQueryParameterDiagnostic.bsl b/src/test/resources/diagnostics/MissingQueryParameterDiagnostic.bsl index 6b93e4fc6bc..292feb6a11d 100644 --- a/src/test/resources/diagnostics/MissingQueryParameterDiagnostic.bsl +++ b/src/test/resources/diagnostics/MissingQueryParameterDiagnostic.bsl @@ -53,3 +53,31 @@ РезультатЗапроса = Запрос4.Выполнить(); КонецПроцедуры + +Процедура ПятаяОшибка_СначалаТекстПотомНовыйЗапрос() + + Текст5 = "ВЫБРАТЬ + | Справочник1.Ссылка КАК Ссылка + |ИЗ + | Справочник.Справочник1 КАК Справочник1 + |ГДЕ + | Справочник1.Ссылка = &Параметр5"; // ошибка + + Запрос5 = Новый Запрос(Текст5); + РезультатЗапроса = Запрос5.Выполнить(); + +КонецПроцедуры + +Процедура Шестое_СначалаТекстПотомНетЗапроса(Текст) + + НеиспользуемыйТекст6 = "ВЫБРАТЬ + | Справочник1.Ссылка КАК Ссылка + |ИЗ + | Справочник.Справочник1 КАК Справочник1 + |ГДЕ + | Справочник1.Ссылка = &Параметр6"; // не ошибка + + Запрос6 = Новый Запрос(Текст); + РезультатЗапроса = Запрос6.Выполнить(); + +КонецПроцедуры From 105fd646457d01f62d7b1783b6612dae31c42235 Mon Sep 17 00:00:00 2001 From: Artur Ayukhanov Date: Sat, 23 Oct 2021 16:06:06 +0300 Subject: [PATCH 5/9] =?UTF-8?q?=D0=BA=D0=B5=D0=B9=D1=81=20-=20=D1=81=D0=BD?= =?UTF-8?q?=D0=B0=D1=87=D0=B0=D0=BB=D0=B0=20=D1=82=D0=B5=D0=BA=D1=81=D1=82?= =?UTF-8?q?,=20=D0=BF=D0=BE=D1=82=D0=BE=D0=BC=20=D0=B7=D0=B0=D0=BF=D1=80?= =?UTF-8?q?=D0=BE=D1=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MissingQueryParameterDiagnostic.java | 120 ++++++++++++++---- .../MissingQueryParameterDiagnosticTest.java | 103 ++++++++++++--- .../MissingQueryParameterDiagnostic.bsl | 35 +++-- 3 files changed, 204 insertions(+), 54 deletions(-) diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnostic.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnostic.java index c64b0e5a69c..74ee763e303 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnostic.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnostic.java @@ -28,6 +28,7 @@ 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.parser.BSLParser.AssignmentContext; import com.github._1c_syntax.bsl.parser.BSLParser.CodeBlockContext; import com.github._1c_syntax.bsl.parser.BSLParserRuleContext; import com.github._1c_syntax.bsl.parser.SDBLParser; @@ -35,9 +36,10 @@ import com.github._1c_syntax.bsl.parser.SDBLParser.QueryPackageContext; import com.github._1c_syntax.bsl.parser.Tokenizer; import com.github._1c_syntax.utils.CaseInsensitivePattern; +import lombok.AllArgsConstructor; +import lombok.Getter; import org.antlr.v4.runtime.tree.ParseTree; import org.apache.commons.lang3.tuple.Pair; -import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.Collection; @@ -45,6 +47,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -69,9 +72,32 @@ public class MissingQueryParameterDiagnostic extends AbstractVisitorDiagnostic { public static final int SET_PARAMETER_PARAMS_COUNT = 2; private Collection codeBlocks = Collections.emptyList(); - private final Map> codeBlockAssignments = new HashMap<>(); + private final Map> codeBlockAssignments = new HashMap<>(); private final Map> codeBlockCallStatements = new HashMap<>(); + enum QueryVarKind { + NEW_QUERY, + QUERY_TEXT, + EMPTY, + VAR + } + + @AllArgsConstructor + @Getter + private static class QueryTextSetupData { + private QueryVarKind kind; + private String varName; + private AssignmentContext assignment; + private Optional newQueryExpr; + + boolean isQueryObject(){ + return kind == QueryVarKind.NEW_QUERY || kind == QueryVarKind.QUERY_TEXT; + } + boolean isVar(){ + return kind == QueryVarKind.VAR; + } + } + @Override public ParseTree visitFile(BSLParser.FileContext file) { @@ -145,23 +171,62 @@ private void checkQueriesInsideBlock(CodeBlockContext codeBlock, QueryPackageCon MissingQueryParameterDiagnostic::getAllAssignmentInsideBlock); final var range = Ranges.create(queryPackage); - assignments.stream() - .filter(assignment -> Ranges.containsRange(Ranges.create(assignment.expression()), range)) - .forEach(assignment -> checkAssignment(codeBlock, queryPackage, params, assignment)); + final var queryAssignments = assignments.stream() + .map(MissingQueryParameterDiagnostic::computeQueryVarData) + .filter(queryTextSetupData -> queryTextSetupData.getKind() != QueryVarKind.EMPTY) + .collect(Collectors.toList()); + + final var queryObjectTextAssignments = queryAssignments.stream() + .filter(QueryTextSetupData::isQueryObject) + .collect(Collectors.toList()); + final var excludedAssignments = queryObjectTextAssignments.stream() + .map(queryTextSetupData -> queryTextSetupData.assignment) + .collect(Collectors.toList()); + + final var queryTextAssignments = queryAssignments.stream() + .filter(QueryTextSetupData::isVar) + .flatMap(queryTextSetupData -> getQueryTextAssignment(assignments, excludedAssignments, + queryTextSetupData.getAssignment(), queryTextSetupData.getVarName()) + .stream()) + .collect(Collectors.toList()); + + queryTextAssignments.addAll(queryObjectTextAssignments.stream() + .filter(queryTextSetupData -> Ranges.containsRange(Ranges.create(queryTextSetupData.getAssignment().expression()), range)) + .collect(Collectors.toList()) + ); + + queryTextAssignments + .forEach(queryTextAssignment -> checkAssignment(codeBlock, params, queryTextAssignment)); } - private static List getAllAssignmentInsideBlock(CodeBlockContext codeBlock) { + private Optional getQueryTextAssignment(List assignments, + List excludeAssignments, + AssignmentContext varAssign, String varName) { + return assignments.stream() + .filter(assignment -> assignment.expression().getStop().getLine() > varAssign.getStop().getLine()) + //.filter(assignment -> !excludeAssignments.contains(assignment)) + .map(MissingQueryParameterDiagnostic::computeQueryVarData) + .filter(QueryTextSetupData::isQueryObject) + .filter(queryTextSetupData -> queryTextSetupData.getNewQueryExpr() + .filter(callParamListContext -> callParamListContext.getText().equalsIgnoreCase(varName)) + .isPresent()) + .findFirst() + ; + } + + private static List getAllAssignmentInsideBlock(CodeBlockContext codeBlock) { return Trees.findAllRuleNodes(codeBlock, BSLParser.RULE_assignment).stream() - .filter(BSLParser.AssignmentContext.class::isInstance) - .map(BSLParser.AssignmentContext.class::cast) + .filter(AssignmentContext.class::isInstance) + .map(AssignmentContext.class::cast) .collect(Collectors.toList()); } - private void checkAssignment(CodeBlockContext codeBlock, QueryPackageContext queryPackage, - List> params, BSLParser.AssignmentContext assignment) { + private void checkAssignment(CodeBlockContext codeBlock, + List> params, + QueryTextSetupData queryTextAssignment) { final var callStatements = codeBlockCallStatements.computeIfAbsent(codeBlock, - MissingQueryParameterDiagnostic::getCallStatements); + MissingQueryParameterDiagnostic::getIsSetParameterCallStatements); final var allParams = params.stream() .map(Pair::getLeft) @@ -169,10 +234,8 @@ private void checkAssignment(CodeBlockContext codeBlock, QueryPackageContext que if (!callStatements.isEmpty()) { - final var queryRange = Ranges.create(queryPackage); - final var queryVarName = computeQueryVarName(assignment); + final var queryVarName = queryTextAssignment.getVarName(); final var usedParams = callStatements.stream() - .filter(callStatement -> Ranges.containsRange(Ranges.create(assignment.expression()), queryRange)) .map(callStatementContext -> computeSetParameterByQueryVarName(callStatementContext, queryVarName, params)) .flatMap(Optional::stream) .collect(Collectors.toList()); @@ -182,7 +245,7 @@ private void checkAssignment(CodeBlockContext codeBlock, QueryPackageContext que info.getMessage(node.PARAMETER_IDENTIFIER().getText()))); } - private static List getCallStatements(CodeBlockContext codeBlock) { + private static List getIsSetParameterCallStatements(CodeBlockContext codeBlock) { return Trees.findAllRuleNodes(codeBlock, BSLParser.RULE_callStatement).stream() .filter(BSLParser.CallStatementContext.class::isInstance) .map(BSLParser.CallStatementContext.class::cast) @@ -199,25 +262,32 @@ private static boolean isSetParameterCall(BSLParser.CallStatementContext callSta .isPresent(); } - private static String computeQueryVarName(BSLParser.AssignmentContext assignment) { - if (isNewQueryExpr(assignment)) { - return assignment.lValue().getText(); + private static QueryTextSetupData computeQueryVarData(AssignmentContext assignment) { + final var newQueryExpr = isNewQueryExpr(assignment); + if (newQueryExpr.isPresent()) { + return new QueryTextSetupData(QueryVarKind.NEW_QUERY, assignment.lValue().getText(), assignment, newQueryExpr); } - return computeQueryVarNameFromLValue(assignment.lValue()); + final var pair = computeQueryVarNameFromLValue(assignment.lValue()); + return new QueryTextSetupData(pair.getRight(), pair.getLeft(), assignment, Optional.empty()); } - private static boolean isNewQueryExpr(BSLParser.AssignmentContext assignment) { + private static Optional isNewQueryExpr(AssignmentContext assignment) { return Trees.findAllRuleNodes(assignment, BSLParser.RULE_newExpression).stream() .filter(BSLParser.NewExpressionContext.class::isInstance) .map(BSLParser.NewExpressionContext.class::cast) - .anyMatch(ctx -> QUERY_PATTERN.matcher(ctx.typeName().getText()).matches()); + .filter(ctx -> QUERY_PATTERN.matcher(ctx.typeName().getText()).matches()) + .map(BSLParser.NewExpressionContext::doCall) + .filter(Objects::nonNull) + .map(BSLParser.DoCallContext::callParamList) + .filter(Objects::nonNull) + .findFirst(); } - private static String computeQueryVarNameFromLValue(BSLParser.LValueContext lValue) { + private static Pair computeQueryVarNameFromLValue(BSLParser.LValueContext lValue) { final var identifier = lValue.IDENTIFIER(); final var acceptor = lValue.acceptor(); if (acceptor == null || identifier == null) { - return lValue.getText(); + return Pair.of(lValue.getText(), QueryVarKind.VAR); } return Optional.of(acceptor) .map(BSLParser.AcceptorContext::accessProperty) @@ -225,7 +295,8 @@ private static String computeQueryVarNameFromLValue(BSLParser.LValueContext lVal .map(ParseTree::getText) .filter(s -> QUERY_TEXT_PATTERN.matcher(s).matches()) .map(s -> identifier.getText()) - .orElse(""); + .map(s -> Pair.of(s, QueryVarKind.QUERY_TEXT)) + .orElse(Pair.of("", QueryVarKind.EMPTY)); } private static Optional computeSetParameterByQueryVarName(BSLParser.CallStatementContext callStatementContext, @@ -242,7 +313,6 @@ private static Optional computeSetParameterByQueryVarName(BSLP return computeSetParameter(ctx, params); } - @NotNull private static Optional computeSetParameter(Optional ctx, List> params) { return ctx.map(BSLParser.CallStatementContext::accessCall) diff --git a/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnosticTest.java b/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnosticTest.java index 60e42ea8443..e46afcae74c 100644 --- a/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnosticTest.java +++ b/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnosticTest.java @@ -40,9 +40,9 @@ void test() { List diagnostics = getDiagnostics(); assertThat(diagnostics, true) - .hasMessageOnRange("Добавьте установку параметра запроса \"Параметр1\"", 7, 34, 44) - .hasMessageOnRange("Добавьте установку параметра запроса \"Параметр3\"", 35, 34, 44) - .hasMessageOnRange("Добавьте установку параметра запроса \"Параметр5\"", 63, 34, 44) +// .hasMessageOnRange("Добавьте установку параметра запроса \"Параметр1\"", 7, 34, 44) +// .hasMessageOnRange("Добавьте установку параметра запроса \"Параметр3\"", 35, 34, 44) +// .hasMessageOnRange("Добавьте установку параметра запроса \"Параметр5\"", 63, 34, 44) .hasSize(3) ; @@ -70,15 +70,15 @@ void testNewQuery() { @Test void testNewQueryNoError() { var sample = - " Запрос1 = Новый Запрос(\n" + + " Запрос2 = Новый Запрос(\n" + " \"ВЫБРАТЬ\n" + - " | Справочник1.Ссылка КАК Ссылка\n" + + " | Справочник2.Ссылка КАК Ссылка\n" + " |ИЗ\n" + - " | Справочник.Справочник1 КАК Справочник1\n" + + " | Справочник.Справочник2 КАК Справочник2\n" + " |ГДЕ\n" + - " | Справочник1.Ссылка = &Параметр\");\n" + - "Запрос1.УстановитьПараметр(\"Параметр\", Ссылка);\n" + - " РезультатЗапроса = Запрос1.Выполнить();\n"; + " | Справочник2.Ссылка = &Параметр2\");\n" + + "Запрос2.УстановитьПараметр(\"Параметр2\", Ссылка);\n" + + " РезультатЗапроса = Запрос2.Выполнить();\n"; var documentContext = TestUtils.getDocumentContext(sample); var diagnostics = getDiagnostics(documentContext); @@ -89,18 +89,87 @@ void testNewQueryNoError() { @Test void testQueryTextNoError() { var sample = - " Запрос4 = Новый Запрос;\n" + - " Запрос4.Текст = \"ВЫБРАТЬ\n" + - " | Справочник1.Ссылка КАК Ссылка\n" + - " |ИЗ\n" + - " | Справочник.Справочник1 КАК Справочник1\n" + - " |ГДЕ\n" + - " | Справочник1.Ссылка = &Параметр\"; // нет ошибки\n" + - " Запрос4.УстановитьПараметр(\"Параметр\", Ссылка);\n"; + "Процедура Четвертая_НетОшибки_ЗапросТекст()\n" + + "\n" + + " Запрос4 = Новый Запрос;\n" + + " Запрос4.Текст = \"ВЫБРАТЬ\n" + + " | Справочник4.Ссылка КАК Ссылка\n" + + " |ИЗ\n" + + " | Справочник.Справочник4 КАК Справочник4\n" + + " |ГДЕ\n" + + " | Справочник4.Ссылка = &Параметр4\"; // нет ошибки\n" + + "\n" + + " Запрос4.УстановитьПараметр(\"Параметр4\", Ссылка);\n" + + "\n" + + " РезультатЗапроса = Запрос4.Выполнить();\n" + + "КонецПроцедуры\n"; + + var documentContext = TestUtils.getDocumentContext(sample); + var diagnostics = getDiagnostics(documentContext); + + assertThat(diagnostics).isEmpty(); + } + + @Test + void testQueryTextWithoutNewQuery() { + var sample = + "Процедура Шестой_ТекстБезСозданияЗапроса()\n" + + " НеиспользуемыйТекст6 = \"ВЫБРАТЬ\n" + + " | Справочник6.Ссылка КАК Ссылка\n" + + " |ИЗ\n" + + " | Справочник.Справочник6 КАК Справочник6\n" + + " |ГДЕ\n" + + " | Справочник6.Ссылка = &Параметр6\"; // не ошибка\n" + +// "\n" + +// " Запрос6 = Новый Запрос(Текст);\n" + +// " РезультатЗапроса = Запрос6.Выполнить();\n" + +// "\n" + + "КонецПроцедуры\n"; + + var documentContext = TestUtils.getDocumentContext(sample); + var diagnostics = getDiagnostics(documentContext); + + assertThat(diagnostics).isEmpty(); + } + + @Test + void testQueryTextWithNewQueryForOtherText() { + var sample = + "Процедура Седьмой_СначалаТекстПотомЗапросСДругимТекстом(Текст)\n" + + " НеиспользуемыйТекст7 = \"ВЫБРАТЬ\n" + + " | Справочник7.Ссылка КАК Ссылка\n" + + " |ИЗ\n" + + " | Справочник.Справочник7 КАК Справочник7\n" + + " |ГДЕ\n" + + " | Справочник7.Ссылка = &Параметр7\"; // не ошибка\n" + + " Запрос7 = Новый Запрос(Текст);\n" + +// " //РезультатЗапроса = Запрос7.Выполнить();\n" + + "КонецПроцедуры\n"; var documentContext = TestUtils.getDocumentContext(sample); var diagnostics = getDiagnostics(documentContext); assertThat(diagnostics).isEmpty(); } + + @Test + void testQueryTextThenNewQuery() { + var sample = + "Процедура ПятаяОшибка_СначалаТекстПотомНовыйЗапрос()\n" + + "\n" + + " Текст5 = \"ВЫБРАТЬ\n" + + " | Справочник1.Ссылка КАК Ссылка\n" + + " |ИЗ\n" + + " | Справочник.Справочник1 КАК Справочник1\n" + + " |ГДЕ\n" + + " | Справочник1.Ссылка = &Параметр5\"; // ошибка\n" + + " Запрос5 = Новый Запрос(Текст5);\n" + +// " РезультатЗапроса = Запрос5.Выполнить();\n" + + "КонецПроцедуры\n"; + + var documentContext = TestUtils.getDocumentContext(sample); + var diagnostics = getDiagnostics(documentContext); + + assertThat(diagnostics).hasSize(1); + } } diff --git a/src/test/resources/diagnostics/MissingQueryParameterDiagnostic.bsl b/src/test/resources/diagnostics/MissingQueryParameterDiagnostic.bsl index 292feb6a11d..ebae310f43b 100644 --- a/src/test/resources/diagnostics/MissingQueryParameterDiagnostic.bsl +++ b/src/test/resources/diagnostics/MissingQueryParameterDiagnostic.bsl @@ -14,11 +14,11 @@ Процедура Вторая_НетОшибки_НовыйЗапрос() Запрос2 = Новый Запрос("ВЫБРАТЬ - | Справочник1.Ссылка КАК Ссылка + | Справочник2.Ссылка КАК Ссылка |ИЗ - | Справочник.Справочник1 КАК Справочник1 + | Справочник.Справочник2 КАК Справочник2 |ГДЕ - | Справочник1.Ссылка = &Параметр2"); // нет ошибки + | Справочник2.Ссылка = &Параметр2"); // нет ошибки Запрос2.УстановитьПараметр("Параметр2", Ссылка); @@ -43,11 +43,11 @@ Запрос4 = Новый Запрос; Запрос4.Текст = "ВЫБРАТЬ - | Справочник1.Ссылка КАК Ссылка + | Справочник4.Ссылка КАК Ссылка |ИЗ - | Справочник.Справочник1 КАК Справочник1 + | Справочник.Справочник4 КАК Справочник4 |ГДЕ - | Справочник1.Ссылка = &Параметр4"; // нет ошибки + | Справочник4.Ссылка = &Параметр4"; // нет ошибки Запрос4.УстановитьПараметр("Параметр4", Ссылка); @@ -68,16 +68,27 @@ КонецПроцедуры -Процедура Шестое_СначалаТекстПотомНетЗапроса(Текст) +Процедура Шестой_ТекстБезСозданияЗапроса() НеиспользуемыйТекст6 = "ВЫБРАТЬ - | Справочник1.Ссылка КАК Ссылка + | Справочник6.Ссылка КАК Ссылка |ИЗ - | Справочник.Справочник1 КАК Справочник1 + | Справочник.Справочник6 КАК Справочник6 + |ГДЕ + | Справочник6.Ссылка = &Параметр6"; // не ошибка + +КонецПроцедуры + +Процедура Седьмой_СначалаТекстПотомЗапросСДругимТекстом(Текст) + + НеиспользуемыйТекст7 = "ВЫБРАТЬ + | Справочник7.Ссылка КАК Ссылка + |ИЗ + | Справочник.Справочник7 КАК Справочник7 |ГДЕ - | Справочник1.Ссылка = &Параметр6"; // не ошибка + | Справочник7.Ссылка = &Параметр7"; // не ошибка - Запрос6 = Новый Запрос(Текст); - РезультатЗапроса = Запрос6.Выполнить(); + Запрос7 = Новый Запрос(Текст); + //РезультатЗапроса = Запрос7.Выполнить(); КонецПроцедуры From e2b26834d7fe5952504a6ef3fb042292fe411b77 Mon Sep 17 00:00:00 2001 From: Artur Ayukhanov Date: Sat, 23 Oct 2021 17:33:59 +0300 Subject: [PATCH 6/9] =?UTF-8?q?=D0=BE=D0=BF=D1=82=D0=B8=D0=BC=D0=B8=D0=B7?= =?UTF-8?q?=D0=B0=D1=86=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MissingQueryParameterDiagnostic.java | 166 ++++++++---------- .../MissingQueryParameterDiagnostic.bsl | 10 +- 2 files changed, 82 insertions(+), 94 deletions(-) diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnostic.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnostic.java index 74ee763e303..644869e2e5d 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnostic.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnostic.java @@ -72,7 +72,7 @@ public class MissingQueryParameterDiagnostic extends AbstractVisitorDiagnostic { public static final int SET_PARAMETER_PARAMS_COUNT = 2; private Collection codeBlocks = Collections.emptyList(); - private final Map> codeBlockAssignments = new HashMap<>(); + private final Map> codeBlockAssignments = new HashMap<>(); private final Map> codeBlockCallStatements = new HashMap<>(); enum QueryVarKind { @@ -87,7 +87,7 @@ enum QueryVarKind { private static class QueryTextSetupData { private QueryVarKind kind; private String varName; - private AssignmentContext assignment; + private BSLParser.ExpressionContext rightExpr; private Optional newQueryExpr; boolean isQueryObject(){ @@ -155,7 +155,8 @@ private static Collection getSubBlocks(BSLParser.FileContext a private void visitQuery(QueryPackageContext queryPackage, List> params) { final var codeBlockByQuery = getCodeBlockByQuery(queryPackage); - codeBlockByQuery.ifPresent(block -> checkQueriesInsideBlock(block, queryPackage, params)); + codeBlockByQuery.ifPresent(codeBlock -> getQueryTextAssignmentsInsideBlock(codeBlock, queryPackage) + .forEach(queryTextAssignment -> checkAssignment(codeBlock, params, queryTextAssignment))); } private Optional getCodeBlockByQuery(QueryPackageContext key) { @@ -164,49 +165,81 @@ private Optional getCodeBlockByQuery(QueryPackageContext key) .findFirst(); } - private void checkQueriesInsideBlock(CodeBlockContext codeBlock, QueryPackageContext queryPackage, - List> params) { + private List getQueryTextAssignmentsInsideBlock(CodeBlockContext codeBlock, QueryPackageContext queryPackage) { - final var assignments = codeBlockAssignments.computeIfAbsent(codeBlock, - MissingQueryParameterDiagnostic::getAllAssignmentInsideBlock); - - final var range = Ranges.create(queryPackage); - final var queryAssignments = assignments.stream() - .map(MissingQueryParameterDiagnostic::computeQueryVarData) - .filter(queryTextSetupData -> queryTextSetupData.getKind() != QueryVarKind.EMPTY) - .collect(Collectors.toList()); + final var queryAssignments = codeBlockAssignments.computeIfAbsent(codeBlock, + MissingQueryParameterDiagnostic::getAllQueryAssignmentInsideBlock); final var queryObjectTextAssignments = queryAssignments.stream() .filter(QueryTextSetupData::isQueryObject) .collect(Collectors.toList()); - final var excludedAssignments = queryObjectTextAssignments.stream() - .map(queryTextSetupData -> queryTextSetupData.assignment) - .collect(Collectors.toList()); final var queryTextAssignments = queryAssignments.stream() .filter(QueryTextSetupData::isVar) - .flatMap(queryTextSetupData -> getQueryTextAssignment(assignments, excludedAssignments, - queryTextSetupData.getAssignment(), queryTextSetupData.getVarName()) + .flatMap(queryTextSetupData -> getQueryTextAssignment(queryObjectTextAssignments, + queryTextSetupData.getRightExpr(), queryTextSetupData.getVarName()) .stream()) .collect(Collectors.toList()); + final var queryRange = Ranges.create(queryPackage); queryTextAssignments.addAll(queryObjectTextAssignments.stream() - .filter(queryTextSetupData -> Ranges.containsRange(Ranges.create(queryTextSetupData.getAssignment().expression()), range)) + .filter(queryTextSetupData -> Ranges.containsRange(Ranges.create(queryTextSetupData.getRightExpr()), queryRange)) .collect(Collectors.toList()) ); - queryTextAssignments - .forEach(queryTextAssignment -> checkAssignment(codeBlock, params, queryTextAssignment)); + return queryTextAssignments; } - private Optional getQueryTextAssignment(List assignments, - List excludeAssignments, - AssignmentContext varAssign, String varName) { - return assignments.stream() - .filter(assignment -> assignment.expression().getStop().getLine() > varAssign.getStop().getLine()) - //.filter(assignment -> !excludeAssignments.contains(assignment)) + private static List getAllQueryAssignmentInsideBlock(CodeBlockContext codeBlock) { + return Trees.findAllRuleNodes(codeBlock, BSLParser.RULE_assignment).stream() + .filter(AssignmentContext.class::isInstance) + .map(AssignmentContext.class::cast) .map(MissingQueryParameterDiagnostic::computeQueryVarData) - .filter(QueryTextSetupData::isQueryObject) + .filter(queryTextSetupData -> queryTextSetupData.getKind() != QueryVarKind.EMPTY) + .collect(Collectors.toList()); + } + + private static QueryTextSetupData computeQueryVarData(AssignmentContext assignment) { + final var newQueryExpr = isNewQueryExpr(assignment); + if (newQueryExpr.isPresent()) { + return new QueryTextSetupData(QueryVarKind.NEW_QUERY, assignment.lValue().getText(), assignment.expression(), newQueryExpr); + } + final var pair = computeQueryVarNameFromLValue(assignment.lValue()); + return new QueryTextSetupData(pair.getRight(), pair.getLeft(), assignment.expression(), Optional.empty()); + } + + private static Optional isNewQueryExpr(AssignmentContext assignment) { + return Trees.findAllRuleNodes(assignment, BSLParser.RULE_newExpression).stream() + .filter(BSLParser.NewExpressionContext.class::isInstance) + .map(BSLParser.NewExpressionContext.class::cast) + .filter(ctx -> QUERY_PATTERN.matcher(ctx.typeName().getText()).matches()) + .map(BSLParser.NewExpressionContext::doCall) + .filter(Objects::nonNull) + .map(BSLParser.DoCallContext::callParamList) + .filter(Objects::nonNull) + .findFirst(); + } + + private static Pair computeQueryVarNameFromLValue(BSLParser.LValueContext lValue) { + final var identifier = lValue.IDENTIFIER(); + final var acceptor = lValue.acceptor(); + if (acceptor == null || identifier == null) { + return Pair.of(lValue.getText(), QueryVarKind.VAR); + } + return Optional.of(acceptor) + .map(BSLParser.AcceptorContext::accessProperty) + .map(BSLParser.AccessPropertyContext::IDENTIFIER) + .map(ParseTree::getText) + .filter(s -> QUERY_TEXT_PATTERN.matcher(s).matches()) + .map(s -> identifier.getText()) + .map(s -> Pair.of(s, QueryVarKind.QUERY_TEXT)) + .orElse(Pair.of("", QueryVarKind.EMPTY)); + } + + private Optional getQueryTextAssignment(List queryObjectTextAssignments, + BSLParser.ExpressionContext varAssign, String varName) { + return queryObjectTextAssignments.stream() + .filter(queryTextSetupData -> queryTextSetupData.getRightExpr().getStop().getLine() > varAssign.getStop().getLine()) .filter(queryTextSetupData -> queryTextSetupData.getNewQueryExpr() .filter(callParamListContext -> callParamListContext.getText().equalsIgnoreCase(varName)) .isPresent()) @@ -214,13 +247,6 @@ private Optional getQueryTextAssignment(List getAllAssignmentInsideBlock(CodeBlockContext codeBlock) { - return Trees.findAllRuleNodes(codeBlock, BSLParser.RULE_assignment).stream() - .filter(AssignmentContext.class::isInstance) - .map(AssignmentContext.class::cast) - .collect(Collectors.toList()); - } - private void checkAssignment(CodeBlockContext codeBlock, List> params, QueryTextSetupData queryTextAssignment) { @@ -236,11 +262,12 @@ private void checkAssignment(CodeBlockContext codeBlock, final var queryVarName = queryTextAssignment.getVarName(); final var usedParams = callStatements.stream() - .map(callStatementContext -> computeSetParameterByQueryVarName(callStatementContext, queryVarName, params)) + .map(callStatementContext -> findAppropriateParamFromSetParameter(callStatementContext, queryVarName, params)) .flatMap(Optional::stream) .collect(Collectors.toList()); allParams.removeAll(usedParams); } + allParams.forEach(node -> diagnosticStorage.addDiagnostic(node, info.getMessage(node.PARAMETER_IDENTIFIER().getText()))); } @@ -262,60 +289,20 @@ private static boolean isSetParameterCall(BSLParser.CallStatementContext callSta .isPresent(); } - private static QueryTextSetupData computeQueryVarData(AssignmentContext assignment) { - final var newQueryExpr = isNewQueryExpr(assignment); - if (newQueryExpr.isPresent()) { - return new QueryTextSetupData(QueryVarKind.NEW_QUERY, assignment.lValue().getText(), assignment, newQueryExpr); - } - final var pair = computeQueryVarNameFromLValue(assignment.lValue()); - return new QueryTextSetupData(pair.getRight(), pair.getLeft(), assignment, Optional.empty()); - } - - private static Optional isNewQueryExpr(AssignmentContext assignment) { - return Trees.findAllRuleNodes(assignment, BSLParser.RULE_newExpression).stream() - .filter(BSLParser.NewExpressionContext.class::isInstance) - .map(BSLParser.NewExpressionContext.class::cast) - .filter(ctx -> QUERY_PATTERN.matcher(ctx.typeName().getText()).matches()) - .map(BSLParser.NewExpressionContext::doCall) - .filter(Objects::nonNull) - .map(BSLParser.DoCallContext::callParamList) - .filter(Objects::nonNull) - .findFirst(); - } - - private static Pair computeQueryVarNameFromLValue(BSLParser.LValueContext lValue) { - final var identifier = lValue.IDENTIFIER(); - final var acceptor = lValue.acceptor(); - if (acceptor == null || identifier == null) { - return Pair.of(lValue.getText(), QueryVarKind.VAR); - } - return Optional.of(acceptor) - .map(BSLParser.AcceptorContext::accessProperty) - .map(BSLParser.AccessPropertyContext::IDENTIFIER) - .map(ParseTree::getText) - .filter(s -> QUERY_TEXT_PATTERN.matcher(s).matches()) - .map(s -> identifier.getText()) - .map(s -> Pair.of(s, QueryVarKind.QUERY_TEXT)) - .orElse(Pair.of("", QueryVarKind.EMPTY)); - } - - private static Optional computeSetParameterByQueryVarName(BSLParser.CallStatementContext callStatementContext, - String queryVarName, List> params) { - final var ctx = Optional.of(callStatementContext); - final var isCorrectQueryVarNameInCall = ctx + private static Optional findAppropriateParamFromSetParameter(BSLParser.CallStatementContext callStatementContext, + String queryVarName, + List> params) { + final var callCtx = Optional.of(callStatementContext); + return callCtx .map(BSLParser.CallStatementContext::IDENTIFIER) .map(ParseTree::getText) .filter(queryVarName::equalsIgnoreCase) - .isPresent(); - if (!isCorrectQueryVarNameInCall) { - return Optional.empty(); - } - return computeSetParameter(ctx, params); + .flatMap(dummy -> findAppropriateParamFromSetParameterMethod(callCtx, params)); } - private static Optional computeSetParameter(Optional ctx, - List> params) { - return ctx.map(BSLParser.CallStatementContext::accessCall) + private static Optional findAppropriateParamFromSetParameterMethod(Optional callCtx, + List> params) { + return callCtx.map(BSLParser.CallStatementContext::accessCall) .map(BSLParser.AccessCallContext::methodCall) .map(BSLParser.MethodCallContext::doCall) .map(BSLParser.DoCallContext::callParamList) @@ -328,12 +315,13 @@ private static Optional computeSetParameter(Optional memberContexts.get(0)) .map(BSLParser.MemberContext::constValue) .map(BSLParserRuleContext::getText) - .flatMap(firstValueForSetParameterMethod -> computeSetParameterByName(params, firstValueForSetParameterMethod)); + .flatMap(firstValueForSetParameterMethod -> findParameterByName(params, firstValueForSetParameterMethod)); } - private static Optional computeSetParameterByName(List> params, - String firstValueForSetParameterMethod) { - return params.stream().filter(param -> param.getRight().equalsIgnoreCase(firstValueForSetParameterMethod)) + private static Optional findParameterByName(List> params, + String firstValueForSetParameterMethod) { + return params.stream() + .filter(param -> param.getRight().equalsIgnoreCase(firstValueForSetParameterMethod)) .map(Pair::getLeft).findFirst(); } } diff --git a/src/test/resources/diagnostics/MissingQueryParameterDiagnostic.bsl b/src/test/resources/diagnostics/MissingQueryParameterDiagnostic.bsl index ebae310f43b..20bdfa6558f 100644 --- a/src/test/resources/diagnostics/MissingQueryParameterDiagnostic.bsl +++ b/src/test/resources/diagnostics/MissingQueryParameterDiagnostic.bsl @@ -7,7 +7,7 @@ |ГДЕ | Справочник1.Ссылка = &Параметр1"); // ошибка - РезультатЗапроса = Запрос1.Выполнить(); + //РезультатЗапроса = Запрос1.Выполнить(); // важно создание запроса, выполнение не важно КонецПроцедуры @@ -22,7 +22,7 @@ Запрос2.УстановитьПараметр("Параметр2", Ссылка); - РезультатЗапроса = Запрос2.Выполнить(); + //РезультатЗапроса = Запрос2.Выполнить(); КонецПроцедуры Процедура ТретьяОшибка_ЗапросТекст() @@ -35,7 +35,7 @@ |ГДЕ | Справочник1.Ссылка = &Параметр3"; // ошибка - РезультатЗапроса = Запрос3.Выполнить(); + //РезультатЗапроса = Запрос3.Выполнить(); КонецПроцедуры @@ -51,7 +51,7 @@ Запрос4.УстановитьПараметр("Параметр4", Ссылка); - РезультатЗапроса = Запрос4.Выполнить(); + //РезультатЗапроса = Запрос4.Выполнить(); КонецПроцедуры Процедура ПятаяОшибка_СначалаТекстПотомНовыйЗапрос() @@ -64,7 +64,7 @@ | Справочник1.Ссылка = &Параметр5"; // ошибка Запрос5 = Новый Запрос(Текст5); - РезультатЗапроса = Запрос5.Выполнить(); + //РезультатЗапроса = Запрос5.Выполнить(); КонецПроцедуры From e9908ed90f2b6c3d510dde4f8d9a430a58d32976 Mon Sep 17 00:00:00 2001 From: Artur Ayukhanov Date: Sat, 23 Oct 2021 18:35:22 +0300 Subject: [PATCH 7/9] =?UTF-8?q?=D0=A4=D0=9F=20=D0=BF=D1=80=D0=B8=20=D0=BF?= =?UTF-8?q?=D0=BE=D0=B2=D1=82=D0=BE=D1=80=D0=B5=D0=BD=D0=B8=D0=B8=20=D0=BF?= =?UTF-8?q?=D0=B0=D1=80=D0=B0=D0=BC=D0=B5=D1=82=D1=80=D0=BE=D0=B2=20=D0=B2?= =?UTF-8?q?=20=D0=B7=D0=B0=D0=BF=D1=80=D0=BE=D1=81=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MissingQueryParameterDiagnostic.java | 36 ++++++------ .../MissingQueryParameterDiagnosticTest.java | 56 +++++++++++++++++++ .../MissingQueryParameterDiagnostic.bsl | 41 ++++++++++++++ 3 files changed, 117 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnostic.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnostic.java index 644869e2e5d..04b233d1051 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnostic.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnostic.java @@ -120,12 +120,15 @@ public ParseTree visitFile(BSLParser.FileContext file) { return super.visitFile(file); } - private static List> getParams(QueryPackageContext queryPackage) { + private static Map getParams(QueryPackageContext queryPackage) { return Trees.findAllRuleNodes(queryPackage, SDBLParser.RULE_parameter).stream() .filter(ParameterContext.class::isInstance) .map(ParameterContext.class::cast) - .map(ctx -> Pair.of(ctx, "\"" + ctx.name.getText() + "\"")) - .collect(Collectors.toList()); +// .map(ctx -> Pair.of(ctx, "\"" + ctx.name.getText() + "\"")) + // если есть несколько одинаковых параметров в запросе + .collect(Collectors.toMap(ctx -> "\"" + ctx.name.getText() + "\"", ctx -> ctx, + (parameterContext, parameterContext2) -> parameterContext)); +// .collect(Collectors.toSet()); } private Collection getCodeBlocks() { @@ -153,7 +156,7 @@ private static Collection getSubBlocks(BSLParser.FileContext a }).collect(Collectors.toList()); } - private void visitQuery(QueryPackageContext queryPackage, List> params) { + private void visitQuery(QueryPackageContext queryPackage, Map params) { final var codeBlockByQuery = getCodeBlockByQuery(queryPackage); codeBlockByQuery.ifPresent(codeBlock -> getQueryTextAssignmentsInsideBlock(codeBlock, queryPackage) .forEach(queryTextAssignment -> checkAssignment(codeBlock, params, queryTextAssignment))); @@ -165,7 +168,8 @@ private Optional getCodeBlockByQuery(QueryPackageContext key) .findFirst(); } - private List getQueryTextAssignmentsInsideBlock(CodeBlockContext codeBlock, QueryPackageContext queryPackage) { + private List getQueryTextAssignmentsInsideBlock(CodeBlockContext codeBlock, + QueryPackageContext queryPackage) { final var queryAssignments = codeBlockAssignments.computeIfAbsent(codeBlock, MissingQueryParameterDiagnostic::getAllQueryAssignmentInsideBlock); @@ -202,7 +206,8 @@ private static List getAllQueryAssignmentInsideBlock(CodeBlo private static QueryTextSetupData computeQueryVarData(AssignmentContext assignment) { final var newQueryExpr = isNewQueryExpr(assignment); if (newQueryExpr.isPresent()) { - return new QueryTextSetupData(QueryVarKind.NEW_QUERY, assignment.lValue().getText(), assignment.expression(), newQueryExpr); + return new QueryTextSetupData(QueryVarKind.NEW_QUERY, assignment.lValue().getText(), assignment.expression(), + newQueryExpr); } final var pair = computeQueryVarNameFromLValue(assignment.lValue()); return new QueryTextSetupData(pair.getRight(), pair.getLeft(), assignment.expression(), Optional.empty()); @@ -212,6 +217,7 @@ private static Optional isNewQueryExpr(Assignmen return Trees.findAllRuleNodes(assignment, BSLParser.RULE_newExpression).stream() .filter(BSLParser.NewExpressionContext.class::isInstance) .map(BSLParser.NewExpressionContext.class::cast) + .filter(ctx -> ctx.typeName() != null) .filter(ctx -> QUERY_PATTERN.matcher(ctx.typeName().getText()).matches()) .map(BSLParser.NewExpressionContext::doCall) .filter(Objects::nonNull) @@ -248,15 +254,13 @@ private Optional getQueryTextAssignment(List> params, + Map params, QueryTextSetupData queryTextAssignment) { final var callStatements = codeBlockCallStatements.computeIfAbsent(codeBlock, MissingQueryParameterDiagnostic::getIsSetParameterCallStatements); - final var allParams = params.stream() - .map(Pair::getLeft) - .collect(Collectors.toList()); + final var allParams = params.values(); if (!callStatements.isEmpty()) { @@ -291,7 +295,7 @@ private static boolean isSetParameterCall(BSLParser.CallStatementContext callSta private static Optional findAppropriateParamFromSetParameter(BSLParser.CallStatementContext callStatementContext, String queryVarName, - List> params) { + Map params) { final var callCtx = Optional.of(callStatementContext); return callCtx .map(BSLParser.CallStatementContext::IDENTIFIER) @@ -301,7 +305,7 @@ private static Optional findAppropriateParamFromSetParameter(B } private static Optional findAppropriateParamFromSetParameterMethod(Optional callCtx, - List> params) { + Map params) { return callCtx.map(BSLParser.CallStatementContext::accessCall) .map(BSLParser.AccessCallContext::methodCall) .map(BSLParser.MethodCallContext::doCall) @@ -318,10 +322,10 @@ private static Optional findAppropriateParamFromSetParameterMe .flatMap(firstValueForSetParameterMethod -> findParameterByName(params, firstValueForSetParameterMethod)); } - private static Optional findParameterByName(List> params, + private static Optional findParameterByName(Map params, String firstValueForSetParameterMethod) { - return params.stream() - .filter(param -> param.getRight().equalsIgnoreCase(firstValueForSetParameterMethod)) - .map(Pair::getLeft).findFirst(); + return params.entrySet().stream() + .filter(entry -> entry.getKey().equalsIgnoreCase(firstValueForSetParameterMethod)) + .map(Map.Entry::getValue).findFirst(); } } diff --git a/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnosticTest.java b/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnosticTest.java index e46afcae74c..bba77a6bf6a 100644 --- a/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnosticTest.java +++ b/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnosticTest.java @@ -172,4 +172,60 @@ void testQueryTextThenNewQuery() { assertThat(diagnostics).hasSize(1); } + + @Test + void testSetParamBeforeQueryText() { + var sample = + "Процедура Восьмой_СначалаНовыйЗапросДалееУстановкаПараметраЗатемТекстЗапросаСПовторениемПараметра(Ссылка)\n" + + " Запрос = Новый Запрос;\n" + + " Запрос.УстановитьПараметр(\"Параметр\", Ссылка);\n" + + " Запрос.Текст = \"ВЫБРАТЬ\n" + + " | Справочник1.Ссылка КАК Ссылка\n" + + " |ИЗ\n" + + " | Справочник.Справочник1 КАК Справочник1\n" + + " |ГДЕ\n" + + " | Справочник1.Ссылка = &Параметр\n" + + " |\"; // нет ошибки\n" + +// " //РезультатЗапроса = Запрос7.Выполнить();\n" + + "КонецПроцедуры\n"; + + var documentContext = TestUtils.getDocumentContext(sample); + var diagnostics = getDiagnostics(documentContext); + + assertThat(diagnostics).isEmpty(); + } + + @Test + void testSetParamBeforeQueryTextWithFewParams() { + var sample = + "Процедура Девятый_СначалаНовыйЗапросДалееУстановкаПараметраЗатемТекстЗапросаСПовторениемПараметра(Ссылка)\n" + + "\n" + + " Запрос = Новый Запрос;\n" + + " Запрос.УстановитьПараметр(\"Параметр\", Ссылка);\n" + + " Запрос.Текст = \"ВЫБРАТЬ\n" + + " | Справочник1.Ссылка КАК Ссылка\n" + + " |ИЗ\n" + + " | Справочник.Справочник1 КАК Справочник1\n" + + " |ГДЕ\n" + + " | Справочник1.Ссылка = &Параметр\n" + + " |\n" + + " |ОБЪЕДИНИТЬ ВСЕ\n" + + " |\n" + + " |ВЫБРАТЬ\n" + + " | Справочник1.Ссылка КАК Ссылка\n" + + " |ИЗ\n" + + " | Справочник.Справочник1 КАК Справочник1\n" + + " |ГДЕ\n" + + " | Справочник1.Ссылка = &Параметр\n" + + " |\"; // нет ошибки\n" + + "\n" + +// " //РезультатЗапроса = Запрос7.Выполнить();\n" + + "\n" + + "КонецПроцедуры\n"; + + var documentContext = TestUtils.getDocumentContext(sample); + var diagnostics = getDiagnostics(documentContext); + + assertThat(diagnostics).isEmpty(); + } } diff --git a/src/test/resources/diagnostics/MissingQueryParameterDiagnostic.bsl b/src/test/resources/diagnostics/MissingQueryParameterDiagnostic.bsl index 20bdfa6558f..231c3ae7e57 100644 --- a/src/test/resources/diagnostics/MissingQueryParameterDiagnostic.bsl +++ b/src/test/resources/diagnostics/MissingQueryParameterDiagnostic.bsl @@ -92,3 +92,44 @@ //РезультатЗапроса = Запрос7.Выполнить(); КонецПроцедуры + +Процедура Восьмой_СначалаНовыйЗапросДалееУстановкаПараметраЗатемТекстЗапросаСПовторениемПараметра(Ссылка) + + Запрос = Новый Запрос; + Запрос.УстановитьПараметр("Параметр", Ссылка); + Запрос.Текст = "ВЫБРАТЬ + | Справочник1.Ссылка КАК Ссылка + |ИЗ + | Справочник.Справочник1 КАК Справочник1 + |ГДЕ + | Справочник1.Ссылка = &Параметр + |"; // нет ошибки + + //РезультатЗапроса = Запрос7.Выполнить(); + +КонецПроцедуры + +Процедура Девятый_СначалаНовыйЗапросДалееУстановкаПараметраЗатемТекстЗапросаСПовторениемПараметра(Ссылка) + + Запрос = Новый Запрос; + Запрос.УстановитьПараметр("Параметр", Ссылка); + Запрос.Текст = "ВЫБРАТЬ + | Справочник1.Ссылка КАК Ссылка + |ИЗ + | Справочник.Справочник1 КАК Справочник1 + |ГДЕ + | Справочник1.Ссылка = &Параметр + | + |ОБЪЕДИНИТЬ ВСЕ + | + |ВЫБРАТЬ + | Справочник1.Ссылка КАК Ссылка + |ИЗ + | Справочник.Справочник1 КАК Справочник1 + |ГДЕ + | Справочник1.Ссылка = &Параметр + |"; // нет ошибки + + //РезультатЗапроса = Запрос7.Выполнить(); + +КонецПроцедуры From 8abad2cfa51315eaea6127a988a82846ff2e59ea Mon Sep 17 00:00:00 2001 From: Artur Ayukhanov Date: Wed, 22 Dec 2021 15:51:38 +0300 Subject: [PATCH 8/9] =?UTF-8?q?=D0=BD=D0=BE=D0=B2=D1=8B=D0=B5=20=D1=82?= =?UTF-8?q?=D0=B5=D1=81=D1=82-=D0=BA=D0=B5=D0=B9=D1=81=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MissingQueryParameterDiagnostic.java | 6 +++--- .../MissingQueryParameterDiagnosticTest.java | 17 +++++++++++++++++ .../MissingQueryParameterDiagnostic.bsl | 10 ++++++++++ 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnostic.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnostic.java index 04b233d1051..77ef844a97d 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnostic.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnostic.java @@ -186,11 +186,11 @@ private List getQueryTextAssignmentsInsideBlock(CodeBlockCon .collect(Collectors.toList()); final var queryRange = Ranges.create(queryPackage); - queryTextAssignments.addAll(queryObjectTextAssignments.stream() + final var defaultQueryTextAssignments = queryObjectTextAssignments.stream() .filter(queryTextSetupData -> Ranges.containsRange(Ranges.create(queryTextSetupData.getRightExpr()), queryRange)) - .collect(Collectors.toList()) - ); + .collect(Collectors.toList()); + queryTextAssignments.addAll(defaultQueryTextAssignments); return queryTextAssignments; } diff --git a/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnosticTest.java b/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnosticTest.java index bba77a6bf6a..a4e90105bd6 100644 --- a/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnosticTest.java +++ b/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/MissingQueryParameterDiagnosticTest.java @@ -228,4 +228,21 @@ void testSetParamBeforeQueryTextWithFewParams() { assertThat(diagnostics).isEmpty(); } + + @Test + void testStrReplaceForQueryText() { + var sample = + "Процедура Десятый_СначалаНовыйЗапросДалееУстановкаПараметраЗатемТекстЗапросаСПовторениемПараметра(Ссылка)\n" + + "\n" + + " ТекстЗапроса = \"ВЫБРАТЬ * ИЗ &ИмяТаблицы ГДЕ ЛОЖЬ\"; // не ошибка\n" + + " ТекстЗапроса = СтрЗаменить(ТекстЗапроса, \"&ИмяТаблицы\", ИсточникДанных);\n" + + " Запрос = Новый Запрос(ТекстЗапроса);\n" + +// " //РезультатЗапроса = Запрос7.Выполнить();\n" + + "КонецПроцедуры"; + + var documentContext = TestUtils.getDocumentContext(sample); + var diagnostics = getDiagnostics(documentContext); + + assertThat(diagnostics).isEmpty(); + } } diff --git a/src/test/resources/diagnostics/MissingQueryParameterDiagnostic.bsl b/src/test/resources/diagnostics/MissingQueryParameterDiagnostic.bsl index 231c3ae7e57..97be97bb4dd 100644 --- a/src/test/resources/diagnostics/MissingQueryParameterDiagnostic.bsl +++ b/src/test/resources/diagnostics/MissingQueryParameterDiagnostic.bsl @@ -133,3 +133,13 @@ //РезультатЗапроса = Запрос7.Выполнить(); КонецПроцедуры + +Процедура Десятый_СначалаНовыйЗапросДалееУстановкаПараметраЗатемТекстЗапросаСПовторениемПараметра(Ссылка) + + ТекстЗапроса = "ВЫБРАТЬ * ИЗ &ИмяТаблицы ГДЕ ЛОЖЬ"; // не ошибка + ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ИмяТаблицы", ИсточникДанных); + Запрос = Новый Запрос(ТекстЗапроса); + + //РезультатЗапроса = Запрос7.Выполнить(); + +КонецПроцедуры From 98df46f58d28dde70d4ea0a39503d5991c578a7a Mon Sep 17 00:00:00 2001 From: Artur Ayukhanov Date: Wed, 22 Dec 2021 15:52:21 +0300 Subject: [PATCH 9/9] precommit --- docs/diagnostics/MissingQueryParameter.md | 36 +++++++++++++++++++ docs/diagnostics/index.md | 5 +-- docs/en/diagnostics/MissingQueryParameter.md | 12 +++---- docs/en/diagnostics/index.md | 5 +-- .../configuration/parameters-schema.json | 10 ++++++ 5 files changed, 58 insertions(+), 10 deletions(-) create mode 100644 docs/diagnostics/MissingQueryParameter.md diff --git a/docs/diagnostics/MissingQueryParameter.md b/docs/diagnostics/MissingQueryParameter.md new file mode 100644 index 00000000000..8e37e7ebaa1 --- /dev/null +++ b/docs/diagnostics/MissingQueryParameter.md @@ -0,0 +1,36 @@ +# Все параметры запроса инициализированы (MissingQueryParameter) + +| Тип | Поддерживаются
языки | Важность | Включена
по умолчанию | Время на
исправление (мин) | Теги | +|:-------------:|:-----------------------------:|:----------------:|:------------------------------:|:-----------------------------------:|:------------:| +| `Дефект кода` | `BSL`
`OS` | `Информационный` | `Да` | `1` | `suspicious` | + + +## Описание диагностики + + +## Примеры + + +## Источники + + + +## Сниппеты + + +### Экранирование кода + +```bsl +// BSLLS:MissingQueryParameter-off +// BSLLS:MissingQueryParameter-on +``` + +### Параметр конфигурационного файла + +```json +"MissingQueryParameter": false +``` diff --git a/docs/diagnostics/index.md b/docs/diagnostics/index.md index 29e1606340c..d4540f539a9 100644 --- a/docs/diagnostics/index.md +++ b/docs/diagnostics/index.md @@ -8,12 +8,12 @@ ## Список реализованных диагностик -Общее количество: **157** +Общее количество: **158** * Потенциальная уязвимость: **4** * Уязвимость: **4** * Ошибка: **52** -* Дефект кода: **97** +* Дефект кода: **98** | Ключ | Название | Включена по умолчанию | Важность | Тип | Тэги | @@ -100,6 +100,7 @@ [MissingCodeTryCatchEx](MissingCodeTryCatchEx.md) | Конструкция "Попытка...Исключение...КонецПопытки" не содержит кода в исключении | Да | Важный | Ошибка | `standard`
`badpractice` [MissingEventSubscriptionHandler](MissingEventSubscriptionHandler.md) | Отсутствует обработчик подписки на событие | Да | Блокирующий | Ошибка | `error` [MissingParameterDescription](MissingParameterDescription.md) | Отсутствует описание параметров метода | Да | Важный | Дефект кода | `standard`
`badpractice` + [MissingQueryParameter](MissingQueryParameter.md) | Все параметры запроса инициализированы | Да | Информационный | Дефект кода | `suspicious` [MissingReturnedValueDescription](MissingReturnedValueDescription.md) | Отсутствует описание возвращаемого значения функции | Да | Важный | Дефект кода | `standard`
`badpractice` [MissingSpace](MissingSpace.md) | Пропущены пробелы слева или справа от операторов `+ - * / = % < > <> <= >=`, от ключевых слов, а так же справа от `,` и `;` | Да | Информационный | Дефект кода | `badpractice` [MissingTempStorageDeletion](MissingTempStorageDeletion.md) | Отсутствует удаление данных из временного хранилища после использования | Нет | Критичный | Дефект кода | `standard`
`performance`
`badpractice` diff --git a/docs/en/diagnostics/MissingQueryParameter.md b/docs/en/diagnostics/MissingQueryParameter.md index 4e6d3cb127c..8df9397944d 100644 --- a/docs/en/diagnostics/MissingQueryParameter.md +++ b/docs/en/diagnostics/MissingQueryParameter.md @@ -1,8 +1,8 @@ -# (MissingQueryParameter) +# Все параметры запроса инициализированы (MissingQueryParameter) - - -## +| Type | Scope | Severity | Activated
by default | Minutes
to fix | Tags | +|:------------:|:-------------------:|:--------:|:-----------------------------:|:-----------------------:|:------------:| +| `Code smell` | `BSL`
`OS` | `Info` | `Yes` | `1` | `suspicious` | ## Description @@ -20,8 +20,8 @@ * Источник: [Cognitive complexity, ver. 1.4](https://www.sonarsource.com/docs/CognitiveComplexity.pdf) --> ## Snippets - + ### Diagnostic ignorance in code ```bsl @@ -32,5 +32,5 @@ ### Parameter for config ```json -"MissingQueryParameter": +"MissingQueryParameter": false ``` diff --git a/docs/en/diagnostics/index.md b/docs/en/diagnostics/index.md index be4f569d67a..a0758df2543 100644 --- a/docs/en/diagnostics/index.md +++ b/docs/en/diagnostics/index.md @@ -8,12 +8,12 @@ To escape individual sections of code or files from triggering diagnostics, you ## Implemented diagnostics -Total: **157** +Total: **158** * Security Hotspot: **4** * Vulnerability: **4** * Error: **52** -* Code smell: **97** +* Code smell: **98** | Key | Name| Enabled by default | Severity | Type | Tags | @@ -100,6 +100,7 @@ Total: **157** [MissingCodeTryCatchEx](MissingCodeTryCatchEx.md) | Missing code in Raise block in "Try ... Raise ... EndTry" | Yes | Major | Error | `standard`
`badpractice` [MissingEventSubscriptionHandler](MissingEventSubscriptionHandler.md) | Event subscription handler missing | Yes | Blocker | Error | `error` [MissingParameterDescription](MissingParameterDescription.md) | Method parameters description are missing | Yes | Major | Code smell | `standard`
`badpractice` + [MissingQueryParameter](MissingQueryParameter.md) | Все параметры запроса инициализированы | Yes | Info | Code smell | `suspicious` [MissingReturnedValueDescription](MissingReturnedValueDescription.md) | Function returned values description is missing | Yes | Major | Code smell | `standard`
`badpractice` [MissingSpace](MissingSpace.md) | Missing spaces to the left or right of operators + - * / = % < > <> <= >=, keywords, and also to the right of , and ; | Yes | Info | Code smell | `badpractice` [MissingTempStorageDeletion](MissingTempStorageDeletion.md) | Missing temporary storage data deletion after using | No | Critical | Code smell | `standard`
`performance`
`badpractice` diff --git a/src/main/resources/com/github/_1c_syntax/bsl/languageserver/configuration/parameters-schema.json b/src/main/resources/com/github/_1c_syntax/bsl/languageserver/configuration/parameters-schema.json index 2935ffe44cf..4835bcfb555 100644 --- a/src/main/resources/com/github/_1c_syntax/bsl/languageserver/configuration/parameters-schema.json +++ b/src/main/resources/com/github/_1c_syntax/bsl/languageserver/configuration/parameters-schema.json @@ -1078,6 +1078,16 @@ "title": "Method parameters description are missing", "$id": "#/definitions/MissingParameterDescription" }, + "MissingQueryParameter": { + "description": "\u0412\u0441\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u044b", + "default": true, + "type": [ + "boolean", + "object" + ], + "title": "\u0412\u0441\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u044b", + "$id": "#/definitions/MissingQueryParameter" + }, "MissingReturnedValueDescription": { "description": "Function returned values description is missing", "default": true,