1
0
mirror of https://github.com/1C-Company/v8-code-style.git synced 2024-11-28 09:33:06 +02:00

Нарушена схема работы с транзакциями (#922)

This commit is contained in:
Artem Iliukhin 2022-07-05 10:00:15 +03:00 committed by GitHub
parent 5b2036df3a
commit ccf546d290
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 1168 additions and 0 deletions

View File

@ -25,6 +25,16 @@
#### Код модулей
- Избыточное обращение внутри модуля через его имя или псевдоним ЭтотОбъект (к методу, свойству или реквизиту)
- Проверка нарушения схемы работы с транзакциями связанной с фиксацией транзакции:
1. Вызов "ЗафиксироватьТранзакцию()" находится вне конструкции "Попытка... Исключение"
2. Отсутствует вызов "НачатьТранзакцию()", хотя вызываются "ЗафиксироватьТранзакцию()"
3. Для вызова "НачатьТранзакцию()" отсутствует парный вызов "ОтменитьТранзакцию()"
4. Mежду "ЗафиксироватьТранзакцию()" и "Исключение" есть исполняемый код, который может вызвать исключение
- Проверка нарушения схемы работы с транзакциями связанной с отменой транзакции:
1. Вызов "ОтменитьТранзакцию()" находится вне конструкции "Попытка... Исключение"
2. Отсутствует вызов "НачатьТранзакцию()", хотя вызываются "ОтменитьТранзакцию()"
3. Для вызова "НачатьТранзакцию()" отсутствует парный вызов "ЗафиксироватьТранзакцию()"
4. Mежду "Исключение" и "ОтменитьТранзакцию()" есть исполняемый код, который может вызвать исключение
- Отсутствует удаление временного файла после использования.
#### Запросы

View File

@ -0,0 +1,41 @@
# The scheme of working with transactions is broken
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.
## Noncompliant Code Example
```bsl
BeginTransaction();
CommitTransaction();
Try
// ...
Except
// ...
RollbackTransaction();
// ...
Raise;
EndTry;
```
## Compliant Solution
```bsl
BeginTransaction();
Try
// ...
CommitTransaction();
Except
// ...
RollbackTransaction();
// ...
Raise;
EndTry;
```
## See
- [Catching exceptions in code](https://support.1ci.com/hc/en-us/articles/360011002440-Catching-exceptions-in-code)
- [Transactions: rules of use](https://support.1ci.com/hc/en-us/articles/360011121239-Transactions-rules-of-use)

View File

@ -0,0 +1,40 @@
# The scheme of working with transactions is broken
Rollback transaction must be in a try-catch,
there should be no executable code between exception and rollback transaction,
there is no begin transaction for rollback transaction,
there is no commit transaction for begin transaction.
## Noncompliant Code Example
```bsl
BeginTransaction();
Try
// ...
CommitTransaction();
Except
// ...
Raise;
EndTry;
RollbackTransaction();
```
## Compliant Solution
```bsl
BeginTransaction();
Try
// ...
CommitTransaction();
Except
// ...
RollbackTransaction();
// ...
Raise;
EndTry;
```
## See
- [Catching exceptions in code](https://support.1ci.com/hc/en-us/articles/360011002440-Catching-exceptions-in-code)
- [Transactions: rules of use](https://support.1ci.com/hc/en-us/articles/360011121239-Transactions-rules-of-use)

View File

@ -0,0 +1,41 @@
# Проверка нарушения схемы работы с транзакциями
Вызов "ЗафиксироватьТранзакцию()" находится вне конструкции "Попытка... Исключение"
Отсутствует вызов "НачатьТранзакцию()", хотя вызываются "ЗафиксироватьТранзакцию()"
Для вызова "НачатьТранзакцию()" отсутствует парный вызов "ОтменитьТранзакцию()"
Mежду "ЗафиксироватьТранзакцию()" и "Исключение" есть исполняемый код, который может вызвать исключение
## Неправильно
```bsl
НачатьТранзакцию();
ЗафиксироватьТранзакцию();
Попытка
// ...
Исключение
// ...
ОтменитьТранзакцию();
// ...
ВызватьИсключение;
КонецПопытки;
```
## Правильно
```bsl
НачатьТранзакцию();
Попытка
// ...
ЗафиксироватьТранзакцию();
Исключение
// ...
ОтменитьТранзакцию();
// ...
ВызватьИсключение;
КонецПопытки;
```
## См.
- [Перехват исключений в коде](https://its.1c.ru/db/v8std#content:499:hdoc:3.6)
- [Транзакции: правила использования](https://its.1c.ru/db/v8std#content:783:hdoc:1.3)

View File

@ -0,0 +1,40 @@
# Проверка нарушения схемы работы с транзакциями
Вызов "ОтменитьТранзакцию()" находится вне конструкции "Попытка... Исключение"
Отсутствует вызов "НачатьТранзакцию()", хотя вызываются "ОтменитьТранзакцию()"
Для вызова "НачатьТранзакцию()" отсутствует парный вызов "ЗафиксироватьТранзакцию()"
Mежду "Исключение" и "ОтменитьТранзакцию()" есть исполняемый код, который может вызвать исключение
## Неправильно
```bsl
НачатьТранзакцию();
Попытка
// ...
ЗафиксироватьТранзакцию();
Исключение
// ...
ВызватьИсключение;
КонецПопытки;
ОтменитьТранзакцию();
```
## Правильно
```bsl
НачатьТранзакцию();
Попытка
// ...
ЗафиксироватьТранзакцию();
Исключение
// ...
ОтменитьТранзакцию();
// ...
ВызватьИсключение;
КонецПопытки;
```
## См.
- [Перехват исключений в коде](https://its.1c.ru/db/v8std#content:499:hdoc:3.6)
- [Транзакции: правила использования](https://its.1c.ru/db/v8std#content:783:hdoc:1.3)

View File

@ -259,6 +259,14 @@
category="com.e1c.v8codestyle.bsl"
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.check.ManagerModuleNamedSelfReferenceCheck">
</check>
<check
category="com.e1c.v8codestyle.bsl"
class="com.e1c.v8codestyle.bsl.check.CommitTransactionCheck">
</check>
<check
category="com.e1c.v8codestyle.bsl"
class="com.e1c.v8codestyle.bsl.check.RollbackTransactionCheck">
</check>
</extension>
<extension
point="org.eclipse.core.runtime.preferences">

View File

@ -0,0 +1,222 @@
/*******************************************************************************
* Copyright (C) 2022, 1C-Soft LLC and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* 1C-Soft LLC - initial API and implementation
*******************************************************************************/
package com.e1c.v8codestyle.bsl.check;
import java.util.Iterator;
import java.util.List;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.EcoreUtil2;
import com._1c.g5.v8.dt.bsl.model.BslPackage;
import com._1c.g5.v8.dt.bsl.model.Conditional;
import com._1c.g5.v8.dt.bsl.model.EmptyStatement;
import com._1c.g5.v8.dt.bsl.model.IfStatement;
import com._1c.g5.v8.dt.bsl.model.Invocation;
import com._1c.g5.v8.dt.bsl.model.LoopStatement;
import com._1c.g5.v8.dt.bsl.model.PreprocessorItem;
import com._1c.g5.v8.dt.bsl.model.PreprocessorItemStatements;
import com._1c.g5.v8.dt.bsl.model.RegionPreprocessor;
import com._1c.g5.v8.dt.bsl.model.SimpleStatement;
import com._1c.g5.v8.dt.bsl.model.Statement;
import com._1c.g5.v8.dt.bsl.model.TryExceptStatement;
import com.e1c.g5.v8.dt.check.components.BasicCheck;
import com.google.common.collect.Lists;
/**
* Common functionality for transaction analysis.
*
* @author Artem Iliukhin
*/
abstract class AbstractTransactionCheck
extends BasicCheck
{
protected static final String COMMIT_TRANSACTION_RU = "ЗафиксироватьТранзакцию"; //$NON-NLS-1$
protected static final String COMMIT_TRANSACTION = "CommitTransaction"; //$NON-NLS-1$
protected static final String BEGIN_TRANSACTION = "BeginTransaction"; //$NON-NLS-1$
protected static final String BEGIN_TRANSACTION_RU = "НачатьТранзакцию"; //$NON-NLS-1$
protected static final String ROLLBACK_TRANSACTION = "RollbackTransaction"; //$NON-NLS-1$
protected static final String ROLLBACK_TRANSACTION_RU = "ОтменитьТранзакцию"; //$NON-NLS-1$
/**
* Checks if is rollback statement.
*
* @param statement the statement
* @return true, if is rollback statement
*/
protected final boolean isRollbackStatement(Statement statement)
{
if (statement instanceof SimpleStatement && ((SimpleStatement)statement).getLeft() instanceof Invocation)
{
Invocation invocation = (Invocation)((SimpleStatement)statement).getLeft();
String invocName = invocation.getMethodAccess().getName();
if (ROLLBACK_TRANSACTION_RU.equals(invocName) || ROLLBACK_TRANSACTION.equals(invocName))
{
return true;
}
}
return false;
}
/**
* Gets the all statements.
*
* @param statements the statements
* @return the all statements, cannot return {@code null}.
*/
protected final List<Statement> getAllStatement(List<Statement> statements)
{
List<Statement> res = Lists.newArrayList(statements);
Statement lastStatement = getLastStatement(res);
while (lastStatement instanceof RegionPreprocessor)
{
RegionPreprocessor regionPreprocessorStatement = (RegionPreprocessor)lastStatement;
PreprocessorItem item = regionPreprocessorStatement.getItem();
if (item instanceof PreprocessorItemStatements && item.hasStatements())
{
PreprocessorItemStatements itemStatements = (PreprocessorItemStatements)item;
res.addAll(itemStatements.getStatements());
}
item = regionPreprocessorStatement.getItemAfter();
if (item instanceof PreprocessorItemStatements && item.hasStatements())
{
PreprocessorItemStatements itemStatements = (PreprocessorItemStatements)item;
res.addAll(itemStatements.getStatements());
}
lastStatement = getLastStatement(res);
}
return res;
}
/**
* Gets the last statement or {@code null} if not found.
*
* @param statements the statements
* @return the last statement, can return {@code null}.
*/
protected final Statement getLastStatement(List<Statement> statements)
{
int index = statements.size() - 1;
while (index >= 0 && statements.get(index) instanceof EmptyStatement)
{
index--;
}
if (index >= 0)
{
return statements.get(index);
}
return null;
}
/**
* Gets the next statement or {@code null} if not found.
*
* @param statement the statement
* @return the next statement, can return {@code null}
*/
protected final Statement getNextStatement(Statement statement)
{
Iterator<EObject> it = EcoreUtil2.getAllContainers(statement).iterator();
while (it.hasNext())
{
EObject container = it.next();
List<Statement> st = null;
if (container instanceof LoopStatement)
{
st = ((LoopStatement)container).getStatements();
}
else if (container instanceof Conditional)
{
st = ((Conditional)container).getStatements();
}
else if (container instanceof IfStatement)
{
st = ((IfStatement)container).getElseStatements();
}
else if (container instanceof TryExceptStatement)
{
st = getStatementsFromContainer((TryExceptStatement)container);
}
else if (container instanceof PreprocessorItemStatements)
{
st = ((PreprocessorItemStatements)container).getStatements();
}
else
{
st = getStatementsFromContainer(container);
}
if (st != null)
{
int index = st.indexOf(statement);
if (index != -1 && index + 1 < st.size())
{
return st.get(index + 1);
}
}
}
return null;
}
/**
* Gets the statement from invoc or {@code null} if not found.
*
* @param invocation the invocation
* @return the statement from invoc, can return {@code null}
*/
protected final Statement getStatementFromInvoc(Invocation invocation)
{
EObject container = invocation.eContainer();
while (!(container instanceof Statement))
{
container = container.eContainer();
}
return container instanceof Statement ? (Statement)container : null;
}
/**
* Checks if is commit statement.
*
* @param statement the statement
* @return true, if is commit statement
*/
protected final boolean isCommitStatement(Statement statement)
{
if (statement instanceof SimpleStatement && ((SimpleStatement)statement).getLeft() instanceof Invocation)
{
Invocation invocation = (Invocation)((SimpleStatement)statement).getLeft();
String invocName = invocation.getMethodAccess().getName();
if (COMMIT_TRANSACTION_RU.equals(invocName) || COMMIT_TRANSACTION.equals(invocName))
{
return true;
}
}
return false;
}
private List<Statement> getStatementsFromContainer(TryExceptStatement container)
{
List<Statement> res = Lists.newArrayList();
res.addAll(container.getTryStatements());
res.addAll(container.getExceptStatements());
return res;
}
@SuppressWarnings("unchecked")
private List<Statement> getStatementsFromContainer(EObject container)
{
Object obj = container.eGet(BslPackage.Literals.BLOCK__STATEMENTS);
return obj instanceof List ? (List<Statement>)obj : null;
}
}

View File

@ -0,0 +1,198 @@
/*******************************************************************************
* Copyright (C) 2022, 1C-Soft LLC and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* 1C-Soft LLC - initial API and implementation
*******************************************************************************/
package com.e1c.v8codestyle.bsl.check;
import static com._1c.g5.v8.dt.bsl.model.BslPackage.Literals.INVOCATION;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.xtext.EcoreUtil2;
import com._1c.g5.v8.dt.bsl.model.FeatureAccess;
import com._1c.g5.v8.dt.bsl.model.Invocation;
import com._1c.g5.v8.dt.bsl.model.Method;
import com._1c.g5.v8.dt.bsl.model.Statement;
import com._1c.g5.v8.dt.bsl.model.StaticFeatureAccess;
import com._1c.g5.v8.dt.bsl.model.TryExceptStatement;
import com.e1c.g5.v8.dt.check.CheckComplexity;
import com.e1c.g5.v8.dt.check.ICheckParameters;
import com.e1c.g5.v8.dt.check.settings.IssueSeverity;
import com.e1c.g5.v8.dt.check.settings.IssueType;
/**
* 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.
*
* @author Artem Iliukhin
*/
public final class CommitTransactionCheck
extends AbstractTransactionCheck
{
private static final String CHECK_ID = "commit-transaction"; //$NON-NLS-1$
@Override
public String getCheckId()
{
return CHECK_ID;
}
@Override
protected void configureCheck(CheckConfigurer builder)
{
builder.title(Messages.CommitTransactionCheck_Transactions_is_broken)
.description(Messages.CommitTransactionCheck_Transactions_is_broken_des)
.complexity(CheckComplexity.NORMAL)
.severity(IssueSeverity.MINOR)
.issueType(IssueType.WARNING)
.disable()
//.extension(new StandardCheckExtension(getCheckId(), BslPlugin.PLUGIN_ID))
.module()
.checkedObjectType(INVOCATION);
}
@Override
protected void check(Object object, ResultAcceptor resultAceptor, ICheckParameters parameters,
IProgressMonitor monitor)
{
Invocation inv = (Invocation)object;
FeatureAccess featureAccess = inv.getMethodAccess();
if (featureAccess instanceof StaticFeatureAccess)
{
String nameFeature = featureAccess.getName();
if (!(COMMIT_TRANSACTION_RU.equalsIgnoreCase(nameFeature)
|| COMMIT_TRANSACTION.equalsIgnoreCase(nameFeature)))
{
return;
}
TryExceptStatement tryExceptStatement = EcoreUtil2.getContainerOfType(inv, TryExceptStatement.class);
if (tryExceptStatement == null)
{
resultAceptor.addIssue(Messages.CommitTransactionCheck_Commit_transaction_must_be_in_try_catch, inv);
}
if (monitor.isCanceled())
{
return;
}
Method method = EcoreUtil2.getContainerOfType(inv, Method.class);
if (method == null)
{
return;
}
List<Invocation> invocations = EcoreUtil2.getAllContentsOfType(method, Invocation.class);
for (Invocation invocation : invocations)
{
String invocName = invocation.getMethodAccess().getName();
if (BEGIN_TRANSACTION_RU.equals(invocName) || BEGIN_TRANSACTION.equals(invocName))
{
if (monitor.isCanceled())
{
return;
}
Statement statement = getStatementFromInvoc(invocation);
Statement nextStatement = null;
if (statement != null)
{
nextStatement = getNextStatement(statement);
}
if (nextStatement instanceof TryExceptStatement)
{
anlyseTryExcept(invocation, (TryExceptStatement)nextStatement, resultAceptor);
}
break;
}
else if (COMMIT_TRANSACTION_RU.equals(invocName) || COMMIT_TRANSACTION.equals(invocName))
{
resultAceptor.addIssue(Messages.CommitTransactionCheck_No_begin_transaction_for_commit_transaction,
invocation);
}
}
}
}
private void anlyseTryExcept(Invocation beginTrans, TryExceptStatement tryExceptStatement,
ResultAcceptor resultAceptor)
{
if (tryExceptStatement.getExceptStatements().isEmpty())
{
resultAceptor.addIssue(Messages.CommitTransactionCheck_Transaction_contains_empty_except,
tryExceptStatement);
}
List<Statement> tryStatements = getAllStatement(tryExceptStatement.getTryStatements());
if (!tryStatements.isEmpty())
{
analyseTryPart(tryStatements, resultAceptor);
}
List<Statement> exceptStatement = getAllStatement(tryExceptStatement.getExceptStatements());
if (!exceptStatement.isEmpty())
{
analyseExceptPart(beginTrans, exceptStatement, resultAceptor);
}
}
private void analyseExceptPart(Invocation beginTrans, List<Statement> exceptStatement, ResultAcceptor resultAceptor)
{
boolean invocThereIs = false;
for (Statement statement : exceptStatement)
{
if (isRollbackStatement(statement))
{
invocThereIs = true;
break;
}
}
if (!invocThereIs)
{
resultAceptor.addIssue(Messages.CommitTransactionCheck_No_rollback_transaction_for_begin_transaction,
beginTrans);
}
}
private void analyseTryPart(List<Statement> tryStatements,
ResultAcceptor resultAceptor)
{
boolean invocThereIs = false;
for (Statement statement : tryStatements)
{
if (isCommitStatement(statement))
{
invocThereIs = true;
break;
}
}
if (invocThereIs)
{
Statement lastStatement = getLastStatement(tryStatements);
if (!isCommitStatement(lastStatement))
{
resultAceptor.addIssue(
Messages.CommitTransactionCheck_Should_be_no_executable_code_between_commit_and_exception,
lastStatement);
}
}
}
}

View File

@ -46,6 +46,26 @@ final class Messages
public static String ChangeAndValidateInsteadOfAroundCheck_Use_ChangeAndValidate_instead_of_Around;
public static String ChangeAndValidateInsteadOfAroundCheck_title;
public static String CommitTransactionCheck_Commit_transaction_must_be_in_try_catch;
public static String CommitTransactionCheck_No_begin_transaction_for_commit_transaction;
public static String RollbackTransactionCheck_No_begin_transaction_for_rollback_transaction;
public static String RollbackTransactionCheck_No_commit_transaction_for_begin_transaction;
public static String CommitTransactionCheck_No_rollback_transaction_for_begin_transaction;
public static String CommitTransactionCheck_Should_be_no_executable_code_between_commit_and_exception;
public static String RollbackTransactionCheck_Should_be_no_executable_code_between_exception_and_rollback;
public static String CommitTransactionCheck_Transaction_contains_empty_except;
public static String CommitTransactionCheck_Transactions_is_broken;
public static String CommitTransactionCheck_Transactions_is_broken_des;
public static String CommonModuleNamedSelfReferenceCheck_description;
public static String CommonModuleNamedSelfReferenceCheck_issue;
@ -167,6 +187,12 @@ final class Messages
public static String RegionEmptyCheck_title;
public static String RollbackTransactionCheck_Rollback_transaction_must_be_in_try_catch;
public static String RollbackTransactionCheck_Transactions_is_broken;
public static String RollbackTransactionCheck_Transactions_is_broken_des;
public static String UseNonRecommendedMethods_description;
public static String UseNonRecommendedMethods_message;

View File

@ -0,0 +1,192 @@
/*******************************************************************************
* Copyright (C) 2022, 1C-Soft LLC and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* 1C-Soft LLC - initial API and implementation
*******************************************************************************/
package com.e1c.v8codestyle.bsl.check;
import static com._1c.g5.v8.dt.bsl.model.BslPackage.Literals.INVOCATION;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.xtext.EcoreUtil2;
import com._1c.g5.v8.dt.bsl.model.FeatureAccess;
import com._1c.g5.v8.dt.bsl.model.Invocation;
import com._1c.g5.v8.dt.bsl.model.Method;
import com._1c.g5.v8.dt.bsl.model.Statement;
import com._1c.g5.v8.dt.bsl.model.StaticFeatureAccess;
import com._1c.g5.v8.dt.bsl.model.TryExceptStatement;
import com.e1c.g5.v8.dt.check.CheckComplexity;
import com.e1c.g5.v8.dt.check.ICheckParameters;
import com.e1c.g5.v8.dt.check.settings.IssueSeverity;
import com.e1c.g5.v8.dt.check.settings.IssueType;
/**
* Rollback transaction must be in a try-catch,
* there is no begin transaction for rollback transaction,
* there should be no executable code between exception and rollback transaction,
* there is no commit transaction for begin transaction.
*
* @author Artem Iliukhin
*/
public final class RollbackTransactionCheck
extends AbstractTransactionCheck
{
private static final String CHECK_ID = "rollback-transaction"; //$NON-NLS-1$
@Override
public String getCheckId()
{
return CHECK_ID;
}
@Override
protected void configureCheck(CheckConfigurer builder)
{
builder.title(Messages.RollbackTransactionCheck_Transactions_is_broken)
.description(Messages.RollbackTransactionCheck_Transactions_is_broken_des)
.complexity(CheckComplexity.NORMAL)
.severity(IssueSeverity.MINOR)
.issueType(IssueType.WARNING)
.disable()
//.extension(new StandardCheckExtension(getCheckId(), BslPlugin.PLUGIN_ID))
.module()
.checkedObjectType(INVOCATION);
}
@Override
protected void check(Object object, ResultAcceptor resultAceptor, ICheckParameters parameters,
IProgressMonitor monitor)
{
Invocation inv = (Invocation)object;
FeatureAccess featureAccess = inv.getMethodAccess();
if (featureAccess instanceof StaticFeatureAccess)
{
String nameFeature = featureAccess.getName();
if (!(ROLLBACK_TRANSACTION_RU.equalsIgnoreCase(nameFeature)
|| ROLLBACK_TRANSACTION.equalsIgnoreCase(nameFeature)))
{
return;
}
TryExceptStatement tryExceptStatement = EcoreUtil2.getContainerOfType(inv, TryExceptStatement.class);
if (tryExceptStatement == null)
{
resultAceptor.addIssue(Messages.RollbackTransactionCheck_Rollback_transaction_must_be_in_try_catch,
inv);
}
if (monitor.isCanceled())
{
return;
}
Method method = EcoreUtil2.getContainerOfType(inv, Method.class);
if (method == null)
{
return;
}
List<Invocation> invocations = EcoreUtil2.getAllContentsOfType(method, Invocation.class);
for (Invocation invocation : invocations)
{
String invocName = invocation.getMethodAccess().getName();
if (BEGIN_TRANSACTION_RU.equals(invocName) || BEGIN_TRANSACTION.equals(invocName))
{
if (monitor.isCanceled())
{
return;
}
Statement statement = getStatementFromInvoc(invocation);
Statement nextStatement = null;
if (statement != null)
{
nextStatement = getNextStatement(statement);
}
if (nextStatement instanceof TryExceptStatement)
{
analyzeTryExcept(invocation, (TryExceptStatement)nextStatement, resultAceptor);
}
break;
}
else if (ROLLBACK_TRANSACTION_RU.equals(invocName) || ROLLBACK_TRANSACTION.equals(invocName))
{
resultAceptor.addIssue(
Messages.RollbackTransactionCheck_No_begin_transaction_for_rollback_transaction, invocation);
}
}
}
}
private void analyzeTryExcept(Invocation beginTrans, TryExceptStatement tryExceptStatement,
ResultAcceptor resultAceptor)
{
List<Statement> tryStatements = getAllStatement(tryExceptStatement.getTryStatements());
if (!tryStatements.isEmpty())
{
analyzeTryPart(beginTrans, tryStatements, resultAceptor);
}
List<Statement> exceptStatement = getAllStatement(tryExceptStatement.getExceptStatements());
if (!exceptStatement.isEmpty())
{
analyzeExceptPart(exceptStatement, resultAceptor);
}
}
private void analyzeTryPart(Invocation beginTrans, List<Statement> tryStatements, ResultAcceptor resultAceptor)
{
boolean invocThereIs = false;
for (Statement statement : tryStatements)
{
if (isCommitStatement(statement))
{
invocThereIs = true;
break;
}
}
if (!invocThereIs)
{
resultAceptor.addIssue(Messages.RollbackTransactionCheck_No_commit_transaction_for_begin_transaction,
beginTrans);
}
}
private void analyzeExceptPart(List<Statement> exceptStatement, ResultAcceptor resultAceptor)
{
boolean invocThereIs = false;
for (Statement statement : exceptStatement)
{
if (isRollbackStatement(statement))
{
invocThereIs = true;
break;
}
}
if (invocThereIs)
{
Statement firstStatement = exceptStatement.get(0);
if (!isRollbackStatement(firstStatement))
{
resultAceptor.addIssue(
Messages.RollbackTransactionCheck_Should_be_no_executable_code_between_exception_and_rollback,
firstStatement);
}
}
}
}

View File

@ -40,6 +40,26 @@ ChangeAndValidateInsteadOfAroundCheck_description = Checks that pragma &ChangeAn
ChangeAndValidateInsteadOfAroundCheck_title = Use pragma &ChangeAndValidate instead of &Around
CommitTransactionCheck_Commit_transaction_must_be_in_try_catch=Commit transaction must be in a try-catch
CommitTransactionCheck_No_begin_transaction_for_commit_transaction=There is no begin transaction for commit transaction
RollbackTransactionCheck_No_begin_transaction_for_rollback_transaction=There is no begin transaction for rollback transaction
RollbackTransactionCheck_No_commit_transaction_for_begin_transaction=There is no commit transaction for begin transaction
CommitTransactionCheck_No_rollback_transaction_for_begin_transaction=There is no rollback transaction for begin transaction
CommitTransactionCheck_Should_be_no_executable_code_between_commit_and_exception=There should be no executable code between commit transaction and exception
RollbackTransactionCheck_Should_be_no_executable_code_between_exception_and_rollback=There should be no executable code between exception and rollback transaction
CommitTransactionCheck_Transaction_contains_empty_except=The transaction contains an empty exception block
CommitTransactionCheck_Transactions_is_broken=Commit transaction is incorrect
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.
CommonModuleNamedSelfReferenceCheck_description=Excessive named self reference
CommonModuleNamedSelfReferenceCheck_issue=Excessive named self reference
@ -231,6 +251,12 @@ RegionEmptyCheck_description = Check that module region is empty
RegionEmptyCheck_title = Region is empty
RollbackTransactionCheck_Rollback_transaction_must_be_in_try_catch=Rollback transaction must be in a try-catch
RollbackTransactionCheck_Transactions_is_broken=Rollback transaction is incorrect
RollbackTransactionCheck_Transactions_is_broken_des=Rollback transaction must be in a try-catch, there should be no executable code between exception and rollback transaction, there is no begin transaction for rollback transaction, there is no commit transaction for begin transaction.
SelfReferenceCheck_check_only_existing_form_properties=Check only existing form properties
SelfReferenceCheck_Description=Excessive usage of self reference (when referencing method, property or attribute)

View File

@ -40,6 +40,30 @@ ChangeAndValidateInsteadOfAroundCheck_description = Проверяет, что
ChangeAndValidateInsteadOfAroundCheck_title = Используется аннотация &ИзменениеИКонтроль вместо &Вместо
CommitTransactionCheck_Commit_transaction_must_be_in_try_catch=Вызов "ЗафиксироватьТранзакцию()" находится вне конструкции "Попытка... Исключение"
CommitTransactionCheck_No_begin_transaction_for_commit_transaction=Отсутствует вызов "НачатьТранзакцию()", хотя вызываются "ЗафиксироватьТранзакцию()"
CommitTransactionCheck_No_begin_transaction_for_rollback_transaction=Отсутствует вызов "НачатьТранзакцию()", хотя вызываются "ОтменитьТранзакцию()"
CommitTransactionCheck_No_commit_transaction_for_begin_transaction=Для вызова "НачатьТранзакцию()" отсутствует парный вызов "ЗафиксироватьТранзакцию()"
CommitTransactionCheck_No_rollback_transaction_for_begin_transaction=Для вызова "НачатьТранзакцию()" отсутствует парный вызов "ОтменитьТранзакцию()"
CommitTransactionCheck_Should_be_no_executable_code_between_commit_and_exception=Mежду "ЗафиксироватьТранзакцию()" и "Исключение" есть исполняемый код, который может вызвать исключение
CommitTransactionCheck_Should_be_no_executable_code_between_exception_and_rollback=Mежду "Исключение" и "ОтменитьТранзакцию()" есть исполняемый код, который может вызвать исключение
CommitTransactionCheck_Transaction_contains_empty_except=Транзакция содержит пустой блок Исключение
CommitTransactionCheck_Transactions_is_broken=Нарушена схема работы с "ЗафиксироватьТранзакцию()"
CommitTransactionCheck_Transactions_is_broken_des=Вызов "ЗафиксироватьТранзакцию()" находится вне конструкции "Попытка... Исключение". Отсутствует вызов "НачатьТранзакцию()", хотя вызываются "ЗафиксироватьТранзакцию()". Для вызова "НачатьТранзакцию()" отсутствует парный вызов "ОтменитьТранзакцию()". Mежду "ЗафиксироватьТранзакцию()" и "Исключение" есть исполняемый код, который может вызвать исключение.
RollbackTransactionCheck_Transactions_is_broken=Нарушена схема работы с "ОтменитьТранзакцию()"
RollbackTransactionCheck_Transactions_is_broken_des=Вызов "ОтменитьТранзакцию()" находится вне конструкции "Попытка... Исключение". Отсутствует вызов "НачатьТранзакцию()", хотя вызываются "ОтменитьТранзакцию()". Для вызова "НачатьТранзакцию()" отсутствует парный вызов "ЗафиксироватьТранзакцию()". Mежду "Исключение" и "ОтменитьТранзакцию()" есть исполняемый код, который может вызвать исключение.
CommonModuleNamedSelfReferenceCheck_description=Избыточное обращение по собственному имени
CommonModuleNamedSelfReferenceCheck_issue=Избыточное обращение по собственному имени
@ -234,6 +258,8 @@ RegionEmptyCheck_description = Проверяет что область моду
RegionEmptyCheck_title = Область пустая
RollbackTransactionCheck_Rollback_transaction_must_be_in_try_catch=Вызов "ОтменитьТранзакцию()" находится вне конструкции "Попытка... Исключение"
SelfReferenceCheck_check_only_existing_form_properties=Проверять только существовующие свойства в форме
SelfReferenceCheck_Description=Избыточное обращение внутри модуля через псевдоним "ЭтотОбъект" (к методу, свойству или реквизиту)

View File

@ -0,0 +1,16 @@
Процедура Тест()
НачатьТранзакцию();
ЗафиксироватьТранзакцию();
Попытка
// 2. Вся логика блокировки и обработки данных размещается в блоке Попытка-Исключение
// 3. В самом конце обработки данных выполняется попытка зафиксировать транзакцию
Исключение
// 4. В случае любых проблем с СУБД, транзакция сначала отменяется...
ОтменитьТранзакцию();
// 5. ...затем проблема фиксируется в журнале регистрации...
// 6. ... после чего, проблема передается дальше вызывающему коду.
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры

View File

@ -0,0 +1,15 @@
Процедура Тест()
Попытка
// 2. Вся логика блокировки и обработки данных размещается в блоке Попытка-Исключение
// 3. В самом конце обработки данных выполняется попытка зафиксировать транзакцию
ЗафиксироватьТранзакцию();
Исключение
// 4. В случае любых проблем с СУБД, транзакция сначала отменяется...
ОтменитьТранзакцию();
// 5. ...затем проблема фиксируется в журнале регистрации...
// 6. ... после чего, проблема передается дальше вызывающему коду.
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры

View File

@ -0,0 +1,14 @@
Процедура Тест()
Попытка
// 2. Вся логика блокировки и обработки данных размещается в блоке Попытка-Исключение
// 3. В самом конце обработки данных выполняется попытка зафиксировать транзакцию
Исключение
// 4. В случае любых проблем с СУБД, транзакция сначала отменяется...
ОтменитьТранзакцию();
// 5. ...затем проблема фиксируется в журнале регистрации...
// 6. ... после чего, проблема передается дальше вызывающему коду.
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры

View File

@ -0,0 +1,16 @@
Процедура Тест()
НачатьТранзакцию();
Попытка
// 2. Вся логика блокировки и обработки данных размещается в блоке Попытка-Исключение
// 3. В самом конце обработки данных выполняется попытка зафиксировать транзакцию
А = 2 + 2;
Исключение
// 4. В случае любых проблем с СУБД, транзакция сначала отменяется...
ОтменитьТранзакцию();
// 5. ...затем проблема фиксируется в журнале регистрации...
// 6. ... после чего, проблема передается дальше вызывающему коду.
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры

View File

@ -0,0 +1,15 @@
Процедура Тест()
НачатьТранзакцию();
Попытка
// 2. Вся логика блокировки и обработки данных размещается в блоке Попытка-Исключение
// 3. В самом конце обработки данных выполняется попытка зафиксировать транзакцию
ЗафиксироватьТранзакцию();
Исключение
// 4. В случае любых проблем с СУБД, транзакция сначала отменяется...
// 5. ...затем проблема фиксируется в журнале регистрации...
// 6. ... после чего, проблема передается дальше вызывающему коду.
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры

View File

@ -0,0 +1,18 @@
Процедура Тест()
НачатьТранзакцию();
Попытка
// 2. Вся логика блокировки и обработки данных размещается в блоке Попытка-Исключение
// 3. В самом конце обработки данных выполняется попытка зафиксировать транзакцию
ЗафиксироватьТранзакцию();
Исключение
// 4. В случае любых проблем с СУБД, транзакция сначала отменяется...
// 5. ...затем проблема фиксируется в журнале регистрации...
// 6. ... после чего, проблема передается дальше вызывающему коду.
ВызватьИсключение;
КонецПопытки;
ОтменитьТранзакцию();
КонецПроцедуры

View File

@ -0,0 +1,17 @@
Процедура Тест()
НачатьТранзакцию();
Попытка
// 2. Вся логика блокировки и обработки данных размещается в блоке Попытка-Исключение
// 3. В самом конце обработки данных выполняется попытка зафиксировать транзакцию
ЗафиксироватьТранзакцию();
Тест();
Исключение
// 4. В случае любых проблем с СУБД, транзакция сначала отменяется...
ОтменитьТранзакцию();
// 5. ...затем проблема фиксируется в журнале регистрации...
// 6. ... после чего, проблема передается дальше вызывающему коду.
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры

View File

@ -0,0 +1,17 @@
Процедура Тест()
НачатьТранзакцию();
Попытка
// 2. Вся логика блокировки и обработки данных размещается в блоке Попытка-Исключение
// 3. В самом конце обработки данных выполняется попытка зафиксировать транзакцию
ЗафиксироватьТранзакцию();
Исключение
Тест();
// 4. В случае любых проблем с СУБД, транзакция сначала отменяется...
ОтменитьТранзакцию();
// 5. ...затем проблема фиксируется в журнале регистрации...
// 6. ... после чего, проблема передается дальше вызывающему коду.
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры

View File

@ -0,0 +1,85 @@
/*******************************************************************************
* Copyright (C) 2022, 1C-Soft LLC and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* 1C-Soft LLC - initial API and implementation
*******************************************************************************/
package com.e1c.v8codestyle.bsl.check.itests;
import static org.junit.Assert.assertEquals;
import java.util.List;
import org.junit.Test;
import com._1c.g5.v8.dt.validation.marker.Marker;
import com.e1c.v8codestyle.bsl.check.CommitTransactionCheck;
/**
* Tests for {@link CommitTransactionCheck} check.
*
* @author Artem Iliukhin
*/
public class CommitTransactionCheckTest
extends AbstractSingleModuleTestBase
{
/**
* Instantiates a new commit transaction check test.
*/
public CommitTransactionCheckTest()
{
super(CommitTransactionCheck.class);
}
@Test
public void testCommitTransactionMustBeInTtryCatch() throws Exception
{
updateModule(FOLDER_RESOURCE + "commit-transaction-must-be-in-try-catch.bsl");
List<Marker> markers = getModuleMarkers();
assertEquals(1, markers.size());
Marker marker = markers.get(0);
assertEquals("Commit transaction must be in a try-catch", marker.getMessage());
}
@Test
public void testNoBeginTransactionForCommitTransaction() throws Exception
{
updateModule(FOLDER_RESOURCE + "no-begin-transaction-for-commit-transaction.bsl");
List<Marker> markers = getModuleMarkers();
assertEquals(1, markers.size());
Marker marker = markers.get(0);
assertEquals("There is no begin transaction for commit transaction", marker.getMessage());
}
@Test
public void testNoRollbackTransactionForBeginTransaction() throws Exception
{
updateModule(FOLDER_RESOURCE + "no-rollback-transaction-for-begin-transaction.bsl");
List<Marker> markers = getModuleMarkers();
assertEquals(1, markers.size());
Marker marker = markers.get(0);
assertEquals("There is no rollback transaction for begin transaction", marker.getMessage());
}
@Test
public void testShouldBeNoExecutableCodebetweenCommitAndException() throws Exception
{
updateModule(FOLDER_RESOURCE + "should-be-no-executable-code-between-commit-and-exception.bsl");
List<Marker> markers = getModuleMarkers();
assertEquals(1, markers.size());
Marker marker = markers.get(0);
assertEquals("There should be no executable code between commit transaction and exception",
marker.getMessage());
}
}

View File

@ -0,0 +1,85 @@
/*******************************************************************************
* Copyright (C) 2022, 1C-Soft LLC and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* 1C-Soft LLC - initial API and implementation
*******************************************************************************/
package com.e1c.v8codestyle.bsl.check.itests;
import static org.junit.Assert.assertEquals;
import java.util.List;
import org.junit.Test;
import com._1c.g5.v8.dt.validation.marker.Marker;
import com.e1c.v8codestyle.bsl.check.RollbackTransactionCheck;
/**
* Tests for {@link RollbackTransactionCheck} check.
*
* @author Artem Iliukhin
*/
public class RollbackTransactionCheckTest
extends AbstractSingleModuleTestBase
{
/**
* Instantiates a new commit transaction check test.
*/
public RollbackTransactionCheckTest()
{
super(RollbackTransactionCheck.class);
}
@Test
public void testRollbackTransactionMustBeInTtryCatch() throws Exception
{
updateModule(FOLDER_RESOURCE + "rollback-transaction-must-be-in-try-catch.bsl");
List<Marker> markers = getModuleMarkers();
assertEquals(1, markers.size());
Marker marker = markers.get(0);
assertEquals("Rollback transaction must be in a try-catch", marker.getMessage());
}
@Test
public void testNoBeginTransactionForRollbackTransaction() throws Exception
{
updateModule(FOLDER_RESOURCE + "no-begin-transaction-for-rollback-transaction.bsl");
List<Marker> markers = getModuleMarkers();
assertEquals(1, markers.size());
Marker marker = markers.get(0);
assertEquals("There is no begin transaction for rollback transaction", marker.getMessage());
}
@Test
public void testNoCommitTransactionForBeginTransaction() throws Exception
{
updateModule(FOLDER_RESOURCE + "no-commit-transaction-for-begin-transaction.bsl");
List<Marker> markers = getModuleMarkers();
assertEquals(1, markers.size());
Marker marker = markers.get(0);
assertEquals("There is no commit transaction for begin transaction", marker.getMessage());
}
@Test
public void testShouldBeNoExecutableCodebetweenExceptionAndRollback() throws Exception
{
updateModule(FOLDER_RESOURCE + "should-be-no-executable-code-between-exception-and-rollback.bsl");
List<Marker> markers = getModuleMarkers();
assertEquals(1, markers.size());
Marker marker = markers.get(0);
assertEquals("There should be no executable code between exception and rollback transaction",
marker.getMessage());
}
}