Skip to content

Commit

Permalink
Новая диагностика - кривой запрос
Browse files Browse the repository at this point in the history
  • Loading branch information
theshadowco committed Oct 4, 2021
1 parent a9ac745 commit 09032f7
Show file tree
Hide file tree
Showing 11 changed files with 262 additions and 11 deletions.
66 changes: 66 additions & 0 deletions docs/diagnostics/BrokenQuery.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Ошибка разбора текста запроса (BrokenQuery)

| Тип | Поддерживаются<br>языки | Важность | Включена<br>по умолчанию | Время на<br>исправление (мин) | Теги |
|:-------------:|:-----------------------------:|:--------:|:------------------------------:|:-----------------------------------:|:------------------------------------------------:|
| `Дефект кода` | `BSL` | `Важный` | `Да` | `5` | `standard`<br>`sql`<br>`badpractice` |

<!-- Блоки выше заполняются автоматически, не трогать -->
## Описание диагностики
<!-- Описание диагностики заполняется вручную. Необходимо понятным языком описать смысл и схему работу -->

При написании текста запроса необходимо следовать следующему правилу: текст запроса должен быть написан таким образом, что бы он мог быть открыт конструктором запросов.

Следование этому правилу позволяет осуществлять быструю проверку корректности синтаксиса запроса, а также доработку и сопровождение.

## Примеры
<!-- В данном разделе приводятся примеры, на которые диагностика срабатывает, а также можно привести пример, как можно исправить ситуацию -->

Неправильно

```bsl
ТекстЗапроса = "ВЫБРАТЬ
| Номенклатура.Наименование КАК Наименование ,
| Номенклатура. " + ИмяПоляКод + " КАК КодАртикул
|ИЗ
| Справочник.Номенклатура КАК Номенклатура";
```

Правильно

```bsl
ТекстЗапроса = "ВЫБРАТЬ
| Номенклатура.Наименование КАК Наименование ,
| &ИмяПоляЗапроса КАК КодАртикул
|ИЗ
| Справочник.Номенклатура КАК Номенклатура";
ТекстЗапроса = СтрЗаменить(ТекстЗапроса,
"&ИмяПоляКод",
"Номенклатура." + ИмяПоляКод);
```

## Источники
<!-- Необходимо указывать ссылки на все источники, из которых почерпнута информация для создания диагностики -->
<!-- Примеры источников
* Источник: [Стандарт: Тексты модулей](https://its.1c.ru/db/v8std#content:456:hdoc)
* Полезная информация: [Отказ от использования модальных окон](https://its.1c.ru/db/metod8dev#content:5272:hdoc)
* Источник: [Cognitive complexity, ver. 1.4](https://www.sonarsource.com/docs/CognitiveComplexity.pdf) -->

* [Стандарт: Работа с запросами. Оформление текстов запросов](https://its.1c.ru/db/v8std#content:437:hdoc)

## Сниппеты

<!-- Блоки ниже заполняются автоматически, не трогать -->
### Экранирование кода

```bsl
// BSLLS:BrokenQuery-off
// BSLLS:BrokenQuery-on
```

### Параметр конфигурационного файла

```json
"BrokenQuery": false
```
5 changes: 3 additions & 2 deletions docs/diagnostics/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,20 @@

## Список реализованных диагностик

Общее количество: **145**
Общее количество: **146**

* Потенциальная уязвимость: **4**
* Уязвимость: **4**
* Ошибка: **44**
* Дефект кода: **93**
* Дефект кода: **94**


| Ключ | Название | Включена по умолчанию | Важность | Тип | Тэги |
| --- | --- | :-: | --- | --- | --- |
[AllFunctionPathMustHaveReturn](AllFunctionPathMustHaveReturn.md) | Все возможные пути выполнения функции должны содержать оператор Возврат | Да | Важный | Дефект кода | `unpredictable`<br>`badpractice`<br>`suspicious`
[AssignAliasFieldsInQuery](AssignAliasFieldsInQuery.md) | Назначение псевдонимов выбранным полям в запросе | Да | Важный | Дефект кода | `standard`<br>`sql`<br>`badpractice`
[BeginTransactionBeforeTryCatch](BeginTransactionBeforeTryCatch.md) | Нарушение правил работы с транзакциями для метода 'НачатьТранзакцию' | Да | Важный | Ошибка | `standard`
[BrokenQuery](BrokenQuery.md) | Ошибка разбора текста запроса | Да | Важный | Дефект кода | `standard`<br>`sql`<br>`badpractice`
[CachedPublic](CachedPublic.md) | Кеширование программного интерфейса | Да | Важный | Дефект кода | `standard`<br>`design`
[CanonicalSpellingKeywords](CanonicalSpellingKeywords.md) | Каноническое написание ключевых слов | Да | Информационный | Дефект кода | `standard`
[CodeAfterAsyncCall](CodeAfterAsyncCall.md) | После вызова асинхронного метода есть строки кода | Нет | Важный | Дефект кода | `suspicious`
Expand Down
36 changes: 36 additions & 0 deletions docs/en/diagnostics/BrokenQuery.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Query text parsing error (BrokenQuery)

| Type | Scope | Severity | Activated<br>by default | Minutes<br>to fix | Tags |
|:------------:|:-----:|:--------:|:-----------------------------:|:-----------------------:|:------------------------------------------------:|
| `Code smell` | `BSL` | `Major` | `Yes` | `5` | `standard`<br>`sql`<br>`badpractice` |

<!-- Блоки выше заполняются автоматически, не трогать -->
## Description
<!-- Описание диагностики заполняется вручную. Необходимо понятным языком описать смысл и схему работу -->

## Examples
<!-- В данном разделе приводятся примеры, на которые диагностика срабатывает, а также можно привести пример, как можно исправить ситуацию -->

## Sources
<!-- Необходимо указывать ссылки на все источники, из которых почерпнута информация для создания диагностики -->
<!-- Примеры источников
* Источник: [Стандарт: Тексты модулей](https://its.1c.ru/db/v8std#content:456:hdoc)
* Полезная информация: [Отказ от использования модальных окон](https://its.1c.ru/db/metod8dev#content:5272:hdoc)
* Источник: [Cognitive complexity, ver. 1.4](https://www.sonarsource.com/docs/CognitiveComplexity.pdf) -->

## Snippets

<!-- Блоки ниже заполняются автоматически, не трогать -->
### Diagnostic ignorance in code

```bsl
// BSLLS:BrokenQuery-off
// BSLLS:BrokenQuery-on
```

### Parameter for config

```json
"BrokenQuery": false
```
5 changes: 3 additions & 2 deletions docs/en/diagnostics/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,20 @@ To escape individual sections of code or files from triggering diagnostics, you

## Implemented diagnostics

Total: **145**
Total: **146**

* Security Hotspot: **4**
* Vulnerability: **4**
* Error: **44**
* Code smell: **93**
* Code smell: **94**


| Key | Name| Enabled by default | Severity | Type | Tags |
| --- | --- | :-: | --- | --- | --- |
[AllFunctionPathMustHaveReturn](AllFunctionPathMustHaveReturn.md) | All execution paths of a function must have a Return statement | Yes | Major | Code smell | `unpredictable`<br>`badpractice`<br>`suspicious`
[AssignAliasFieldsInQuery](AssignAliasFieldsInQuery.md) | Assigning aliases to selected fields in a query | Yes | Major | Code smell | `standard`<br>`sql`<br>`badpractice`
[BeginTransactionBeforeTryCatch](BeginTransactionBeforeTryCatch.md) | Violating transaction rules for the 'BeginTransaction' method | Yes | Major | Error | `standard`
[BrokenQuery](BrokenQuery.md) | Query text parsing error | Yes | Major | Code smell | `standard`<br>`sql`<br>`badpractice`
[CachedPublic](CachedPublic.md) | Cached public methods | Yes | Major | Code smell | `standard`<br>`design`
[CanonicalSpellingKeywords](CanonicalSpellingKeywords.md) | Canonical keyword writing | Yes | Info | Code smell | `standard`
[CodeAfterAsyncCall](CodeAfterAsyncCall.md) | Lines of code after the asynchronous method call | No | Major | Code smell | `suspicious`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,6 @@

public class QueryComputer extends BSLParserBaseVisitor<ParseTree> implements Computer<List<SDBLTokenizer>> {

private final DocumentContext documentContext;
private final List<SDBLTokenizer> queries = new ArrayList<>();

/**
* Ключевые слова для поиска потенциально запросных строк
*/
Expand All @@ -66,6 +63,9 @@ public class QueryComputer extends BSLParserBaseVisitor<ParseTree> implements Co
private static final Pattern FIRST_QUOTE_PATTERN = CaseInsensitivePattern.compile(
"^\\s*(\")");

private final DocumentContext documentContext;
private final List<SDBLTokenizer> queries = new ArrayList<>();

public QueryComputer(DocumentContext documentContext) {
this.documentContext = documentContext;
}
Expand All @@ -85,18 +85,18 @@ public ParseTree visitString(BSLParser.StringContext ctx) {
return ctx;
}

int startLine = 0;
var startLine = 0;
var startEmptyLines = "";
if (!ctx.getTokens().isEmpty()) {
startLine = ctx.getTokens().get(0).getLine();
startEmptyLines = "\n".repeat(startLine - 1);
}

boolean isQuery = false;
var isQuery = false;

// конкатенация строк в одну
int prevTokenLine = -1;
String partString = "";
var partString = "";
var strings = new StringJoiner("\n");
for (Token token : ctx.getTokens()) {

Expand All @@ -109,7 +109,7 @@ public ParseTree visitString(BSLParser.StringContext ctx) {

// если новый токен строки находится на той же строке файла, что и предыдущий, то добавляем его к ней
if (token.getLine() == prevTokenLine && prevTokenLine != -1) {
String newString = getString(startLine, token);
var newString = getString(startLine, token);
partString = newString.substring(partString.length());
} else {
partString = getString(startLine, token);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* This file is a part of BSL Language Server.
*
* Copyright (c) 2018-2021
* Alexey Sosnoviy <labotamy@gmail.com>, Nikita Gryzlov <nixel2007@gmail.com> 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.DiagnosticScope;
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.Trees;
import com.github._1c_syntax.bsl.parser.SDBLParser;
import org.antlr.v4.runtime.tree.ParseTree;

@DiagnosticMetadata(
type = DiagnosticType.CODE_SMELL,
severity = DiagnosticSeverity.MAJOR,
minutesToFix = 5,
tags = {
DiagnosticTag.STANDARD,
DiagnosticTag.SQL,
DiagnosticTag.BADPRACTICE
},
scope = DiagnosticScope.BSL
)
public class BrokenQueryDiagnostic extends AbstractSDBLVisitorDiagnostic {

@Override
// анализируем каждый запрос пакета
public ParseTree visitQueries(SDBLParser.QueriesContext ctx) {
if (Trees.treeContainsErrors(ctx)) {
diagnosticStorage.addDiagnostic(ctx);
}
return ctx;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@
"title": "Violating transaction rules for the 'BeginTransaction' method",
"$id": "#/definitions/BeginTransactionBeforeTryCatch"
},
"BrokenQuery": {
"description": "Query text parsing error",
"default": true,
"type": [
"boolean",
"object"
],
"title": "Query text parsing error",
"$id": "#/definitions/BrokenQuery"
},
"CachedPublic": {
"description": "Cached public methods",
"default": true,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
diagnosticMessage=Query text must be correct
diagnosticName=Query text parsing error
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
diagnosticMessage=Текст запроса должен быть корректным и открываться конструктором запросов
diagnosticName=Ошибка разбора текста запроса
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* This file is a part of BSL Language Server.
*
* Copyright (c) 2018-2021
* Alexey Sosnoviy <labotamy@gmail.com>, Nikita Gryzlov <nixel2007@gmail.com> 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 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 BrokenQueryDiagnosticTest extends AbstractDiagnosticTest<BrokenQueryDiagnostic> {
BrokenQueryDiagnosticTest() {
super(BrokenQueryDiagnostic.class);
}

@Test
void test() {

List<Diagnostic> diagnostics = getDiagnostics();

assertThat(diagnostics).hasSize(4);
assertThat(diagnostics, true)
.hasRange(5, 1, 6, 26)
.hasRange(9, 1, 10, 59)
.hasRange(14, 1, 19, 11)
.hasRange(27, 1, 28, 3)
;
}
}
30 changes: 30 additions & 0 deletions src/test/resources/diagnostics/BrokenQueryDiagnostic.bsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
ТекстЗапроса =
"ВЫБРАТЬ ССЫЛКА
|ИЗ Справочник.Контрагенты";

ТекстЗапросаОшибка1 =
"ВЫБРАТЬ
|ИЗ Справочник.Контрагенты";

ТекстЗапросаОшибка2 =
"ВЫБРАТЬ Поле
|ИЗ Справочник.Контрагенты КАК Контрагенты ЛЕВОЕ СОЕДИНЕНИЕ "
+ "Документ.Накладная ПО Контрагенты.Ссылка = Покупатель";

ТекстЗапросаОшибка3 =
"ВЫБРАТЬ Поле
|ИЗ Справочник.Контрагенты КАК Контрагенты
|ЛЕВОЕ СОЕДИНЕНИЕ
|Документ.Накладная ПО Контрагенты.Ссылка = Покупатель
|ГДЕ
| Условие >";

ТекстЗапросаОшибка4 =
"ВЫБРАТЬ Поле
|ИЗ Справочник.Контрагенты КАК Контрагенты
|ЛЕВОЕ СОЕДИНЕНИЕ
|Документ.Накладная ПО Контрагенты.Ссылка = Покупатель
|;
|ВЫБРАТЬ Поле
|ИЗ
|";

0 comments on commit 09032f7

Please sign in to comment.