Skip to content

Commit ee64a06

Browse files
authored
Между "НачатьТранзакцию()" и "Попытка" есть исполняемый код (#1063)
1 parent a48f5b8 commit ee64a06

File tree

12 files changed

+275
-2
lines changed

12 files changed

+275
-2
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@
3737
2. Отсутствует вызов "НачатьТранзакцию()", хотя вызываются "ОтменитьТранзакцию()"
3838
3. Для вызова "НачатьТранзакцию()" отсутствует парный вызов "ЗафиксироватьТранзакцию()"
3939
4. Mежду "Исключение" и "ОтменитьТранзакцию()" есть исполняемый код, который может вызвать исключение
40+
- Проверка нарушения схемы работы с транзакциями связанной с началом транзакции:
41+
1. Mежду "НачатьТранзакцию()" и "Попытка" есть исполняемый код, который может вызвать исключение
42+
2. Не найден оператор "Попытка" после вызова "НачатьТранзакцию()"
4043
- Отсутствует удаление временного файла после использования.
4144

4245
#### Запросы
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# There is no Try-Exception block after the start of the transaction
2+
3+
There should be no executable code between begin transaction and try,
4+
the try operator was not found after calling begin transaction
5+
6+
## Noncompliant Code Example
7+
8+
```bsl
9+
BeginTransaction();
10+
CommitTransaction();
11+
```
12+
13+
## Compliant Solution
14+
15+
```bsl
16+
BeginTransaction();
17+
Try
18+
// ...
19+
CommitTransaction();
20+
Except
21+
// ...
22+
RollbackTransaction();
23+
// ...
24+
Raise;
25+
EndTry;
26+
```
27+
28+
## See
29+
30+
- [Catching exceptions in code](https://support.1ci.com/hc/en-us/articles/360011002440-Catching-exceptions-in-code)
31+
- [Transactions: rules of use](https://support.1ci.com/hc/en-us/articles/360011121239-Transactions-rules-of-use)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# После начала транзакции отсуствует блок Попытка-Исключение
2+
3+
Mежду "НачатьТранзакцию()" и "Попытка" есть исполняемый код, который может вызвать исключение,
4+
после "НачатьТранзакцию()" не найден оператор "Попытка"
5+
6+
## Неправильно
7+
8+
```bsl
9+
НачатьТранзакцию();
10+
ЗафиксироватьТранзакцию();
11+
```
12+
13+
## Правильно
14+
15+
```bsl
16+
НачатьТранзакцию();
17+
Попытка
18+
// ...
19+
ЗафиксироватьТранзакцию();
20+
Исключение
21+
// ...
22+
ОтменитьТранзакцию();
23+
// ...
24+
ВызватьИсключение;
25+
КонецПопытки;
26+
```
27+
28+
## См.
29+
30+
- [Перехват исключений в коде](https://its.1c.ru/db/v8std#content:499:hdoc:3.6)
31+
- [Транзакции: правила использования](https://its.1c.ru/db/v8std#content:783:hdoc:1.3)

bundles/com.e1c.v8codestyle.bsl/plugin.xml

+4
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,10 @@
267267
category="com.e1c.v8codestyle.bsl"
268268
class="com.e1c.v8codestyle.bsl.check.RollbackTransactionCheck">
269269
</check>
270+
<check
271+
category="com.e1c.v8codestyle.bsl"
272+
class="com.e1c.v8codestyle.bsl.check.BeginTransactionCheck">
273+
</check>
270274
</extension>
271275
<extension
272276
point="org.eclipse.core.runtime.preferences">
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*******************************************************************************
2+
* Copyright (C) 2022, 1C-Soft LLC and others.
3+
*
4+
* This program and the accompanying materials are made
5+
* available under the terms of the Eclipse Public License 2.0
6+
* which is available at https://www.eclipse.org/legal/epl-2.0/
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
*
10+
* Contributors:
11+
* 1C-Soft LLC - initial API and implementation
12+
*******************************************************************************/
13+
package com.e1c.v8codestyle.bsl.check;
14+
15+
import static com._1c.g5.v8.dt.bsl.model.BslPackage.Literals.INVOCATION;
16+
17+
import org.eclipse.core.runtime.IProgressMonitor;
18+
19+
import com._1c.g5.v8.dt.bsl.model.FeatureAccess;
20+
import com._1c.g5.v8.dt.bsl.model.Invocation;
21+
import com._1c.g5.v8.dt.bsl.model.Statement;
22+
import com._1c.g5.v8.dt.bsl.model.StaticFeatureAccess;
23+
import com._1c.g5.v8.dt.bsl.model.TryExceptStatement;
24+
import com.e1c.g5.v8.dt.check.CheckComplexity;
25+
import com.e1c.g5.v8.dt.check.ICheckParameters;
26+
import com.e1c.g5.v8.dt.check.settings.IssueSeverity;
27+
import com.e1c.g5.v8.dt.check.settings.IssueType;
28+
29+
/**
30+
* The try operator was not found after calling begin transaction,
31+
* there should be no executable code between begin transaction and try,
32+
*
33+
* @author Artem Iliukhin
34+
*/
35+
public final class BeginTransactionCheck
36+
extends AbstractTransactionCheck
37+
{
38+
39+
private static final String CHECK_ID = "begin-transaction"; //$NON-NLS-1$
40+
41+
@Override
42+
public String getCheckId()
43+
{
44+
return CHECK_ID;
45+
}
46+
47+
@Override
48+
protected void configureCheck(CheckConfigurer builder)
49+
{
50+
builder.title(Messages.BeginTransactionCheck_Begin_transaction_is_incorrect)
51+
.description(Messages.BeginTransactionCheck_Try_must_be_after_begin)
52+
.complexity(CheckComplexity.NORMAL)
53+
.severity(IssueSeverity.MINOR)
54+
.issueType(IssueType.WARNING)
55+
.disable()
56+
.module()
57+
.checkedObjectType(INVOCATION);
58+
}
59+
60+
@Override
61+
protected void check(Object object, ResultAcceptor resultAceptor, ICheckParameters parameters,
62+
IProgressMonitor monitor)
63+
{
64+
Invocation inv = (Invocation)object;
65+
FeatureAccess featureAccess = inv.getMethodAccess();
66+
if (featureAccess instanceof StaticFeatureAccess)
67+
{
68+
if (monitor.isCanceled())
69+
{
70+
return;
71+
}
72+
73+
String nameFeature = featureAccess.getName();
74+
if (!(BEGIN_TRANSACTION_RU.equalsIgnoreCase(nameFeature)
75+
|| BEGIN_TRANSACTION.equalsIgnoreCase(nameFeature)))
76+
{
77+
return;
78+
}
79+
80+
Statement statement = getStatementFromInvoc(inv);
81+
if (statement != null)
82+
{
83+
statement = getNextStatement(statement);
84+
if (statement == null)
85+
{
86+
resultAceptor.addIssue(Messages.BeginTransactionCheck_Try_was_not_found_after_calling_begin, inv);
87+
}
88+
else if (!(statement instanceof TryExceptStatement))
89+
{
90+
resultAceptor.addIssue(
91+
Messages.BeginTransactionCheck_Executable_code_between_begin_transaction_and_try, inv);
92+
}
93+
}
94+
}
95+
}
96+
}

bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/Messages.java

+8
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,20 @@ final class Messages
6060

6161
public static String RollbackTransactionCheck_Should_be_no_executable_code_between_exception_and_rollback;
6262

63+
public static String BeginTransactionCheck_Executable_code_between_begin_transaction_and_try;
64+
6365
public static String CommitTransactionCheck_Transaction_contains_empty_except;
6466

6567
public static String CommitTransactionCheck_Transactions_is_broken;
6668

6769
public static String CommitTransactionCheck_Transactions_is_broken_des;
6870

71+
public static String BeginTransactionCheck_Begin_transaction_is_incorrect;
72+
73+
public static String BeginTransactionCheck_Try_must_be_after_begin;
74+
75+
public static String BeginTransactionCheck_Try_was_not_found_after_calling_begin;
76+
6977
public static String CommonModuleNamedSelfReferenceCheck_description;
7078

7179
public static String CommonModuleNamedSelfReferenceCheck_issue;

bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages.properties

+8
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,20 @@ CommitTransactionCheck_Should_be_no_executable_code_between_commit_and_exception
5454

5555
RollbackTransactionCheck_Should_be_no_executable_code_between_exception_and_rollback=There should be no executable code between exception and rollback transaction
5656

57+
BeginTransactionCheck_Executable_code_between_begin_transaction_and_try=There should be no executable code between begin transaction and try
58+
5759
CommitTransactionCheck_Transaction_contains_empty_except=The transaction contains an empty exception block
5860

5961
CommitTransactionCheck_Transactions_is_broken=Commit transaction is incorrect
6062

6163
CommitTransactionCheck_Transactions_is_broken_des=Commit transaction must be in a try-catch, there should be no executable code between commit transaction and exception, there is no begin transaction for commit transaction, there is no rollback transaction for begin transaction.
6264

65+
BeginTransactionCheck_Begin_transaction_is_incorrect=Begin transaction is incorrect
66+
67+
BeginTransactionCheck_Try_must_be_after_begin=Try-catch must be after begin transaction
68+
69+
BeginTransactionCheck_Try_was_not_found_after_calling_begin=The try operator was not found after calling begin transaction
70+
6371
CommonModuleNamedSelfReferenceCheck_description=Excessive named self reference
6472

6573
CommonModuleNamedSelfReferenceCheck_issue=Excessive named self reference

bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages_ru.properties

+8-2
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,20 @@ CommitTransactionCheck_No_begin_transaction_for_commit_transaction=Отсутс
4646

4747
CommitTransactionCheck_No_begin_transaction_for_rollback_transaction=Отсутствует вызов "НачатьТранзакцию()", хотя вызываются "ОтменитьТранзакцию()"
4848

49-
CommitTransactionCheck_No_commit_transaction_for_begin_transaction=Для вызова "НачатьТранзакцию()" отсутствует парный вызов "ЗафиксироватьТранзакцию()"
50-
5149
CommitTransactionCheck_No_rollback_transaction_for_begin_transaction=Для вызова "НачатьТранзакцию()" отсутствует парный вызов "ОтменитьТранзакцию()"
5250

5351
CommitTransactionCheck_Should_be_no_executable_code_between_commit_and_exception=Mежду "ЗафиксироватьТранзакцию()" и "Исключение" есть исполняемый код, который может вызвать исключение
5452

5553
CommitTransactionCheck_Should_be_no_executable_code_between_exception_and_rollback=Mежду "Исключение" и "ОтменитьТранзакцию()" есть исполняемый код, который может вызвать исключение
5654

55+
BeginTransactionCheck_Executable_code_between_begin_transaction_and_try=Между "НачатьТранзакцию()" и "Попытка" есть исполняемый код
56+
57+
BeginTransactionCheck_Try_was_not_found_after_calling_begin=Не найден оператор "Попытка" после вызова "НачатьТранзакцию()"
58+
59+
BeginTransactionCheck_Begin_transaction_is_incorrect=Нарушена схема работы с "НачатьТранзакцию()"
60+
61+
BeginTransactionCheck_Try_must_be_after_begin=После начала транзакции не найден оператор "Попытка"
62+
5763
CommitTransactionCheck_Transaction_contains_empty_except=Транзакция содержит пустой блок Исключение
5864

5965
CommitTransactionCheck_Transactions_is_broken=Нарушена схема работы с "ЗафиксироватьТранзакцию()"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Процедура Тест()
2+
3+
НачатьТранзакцию();
4+
5+
КонецПроцедуры
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
Процедура Тест()
2+
3+
НачатьТранзакцию();
4+
Тест = 1;
5+
Попытка
6+
// 2. Вся логика блокировки и обработки данных размещается в блоке Попытка-Исключение
7+
// 3. В самом конце обработки данных выполняется попытка зафиксировать транзакцию
8+
ЗафиксироватьТранзакцию();
9+
Исключение
10+
// 4. В случае любых проблем с СУБД, транзакция сначала отменяется...
11+
ОтменитьТранзакцию();
12+
// 5. ...затем проблема фиксируется в журнале регистрации...
13+
// 6. ... после чего, проблема передается дальше вызывающему коду.
14+
ВызватьИсключение;
15+
КонецПопытки;
16+
17+
КонецПроцедуры
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*******************************************************************************
2+
* Copyright (C) 2022, 1C-Soft LLC and others.
3+
*
4+
* This program and the accompanying materials are made
5+
* available under the terms of the Eclipse Public License 2.0
6+
* which is available at https://www.eclipse.org/legal/epl-2.0/
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
*
10+
* Contributors:
11+
* 1C-Soft LLC - initial API and implementation
12+
*******************************************************************************/
13+
package com.e1c.v8codestyle.bsl.check.itests;
14+
15+
import static org.junit.Assert.assertEquals;
16+
17+
import java.util.List;
18+
19+
import org.junit.Test;
20+
21+
import com._1c.g5.v8.dt.validation.marker.Marker;
22+
import com.e1c.v8codestyle.bsl.check.BeginTransactionCheck;
23+
24+
/**
25+
* Tests for {@link BeginTransactionCheck} check.
26+
*
27+
* @author Artem Iliukhin
28+
*/
29+
public class BeginTransactionCheckTest
30+
extends AbstractSingleModuleTestBase
31+
{
32+
33+
/**
34+
* Instantiates a new commit transaction check test.
35+
*/
36+
public BeginTransactionCheckTest()
37+
{
38+
super(BeginTransactionCheck.class);
39+
}
40+
41+
42+
@Test
43+
public void testNotFoundTryAfterBegin() throws Exception
44+
{
45+
updateModule(FOLDER_RESOURCE + "not-found-try-after-begin.bsl");
46+
47+
List<Marker> markers = getModuleMarkers();
48+
assertEquals(1, markers.size());
49+
Marker marker = markers.get(0);
50+
assertEquals("The try operator was not found after calling begin transaction", marker.getMessage());
51+
}
52+
53+
@Test
54+
public void testShouldBeNoExecutableCodebetweenBeginAndTry() throws Exception
55+
{
56+
updateModule(FOLDER_RESOURCE + "should-be-no-executable-code-between-begin-and-try.bsl");
57+
58+
List<Marker> markers = getModuleMarkers();
59+
assertEquals(1, markers.size());
60+
Marker marker = markers.get(0);
61+
assertEquals("There should be no executable code between begin transaction and try", marker.getMessage());
62+
}
63+
}

tests/com.e1c.v8codestyle.bsl.itests/src/com/e1c/v8codestyle/bsl/check/itests/CommitTransactionCheckTest.java

+1
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,5 @@ public void testShouldBeNoExecutableCodebetweenCommitAndException() throws Excep
8282
assertEquals("There should be no executable code between commit transaction and exception",
8383
marker.getMessage());
8484
}
85+
8586
}

0 commit comments

Comments
 (0)