1
0
mirror of https://github.com/1C-Company/v8-code-style.git synced 2025-04-07 07:29:59 +02:00

Merge remote-tracking branch 'origin/master' into edt-2023-1

This commit is contained in:
Dmitriy Marmyshev 2023-04-16 12:33:40 -07:00
commit 2477562cd2
56 changed files with 1921 additions and 39 deletions

View File

@ -17,9 +17,11 @@
#### Формы
- Использована ролевая настройка видимости, редактирования, использования для элемента формы
#### Код модулей
- Проверка отсутствия кода после асинхронного вызова
- Проверка использования метода ДанныеФормыВЗначение вместо РеквизитФормыВЗначение
- В проверку использования нерекомендуемых методов (use-non-recommended-method) добавлен метод ПолучитьФорму(GetForm)
- Использование устаревшего метода Найти
@ -30,6 +32,7 @@
#### Запросы
- Доработана проверка ql-temp-table-index: параметр MAX_TOP (Макс. кол-во строк в выборке) теперь настраиваемый.
#### Права ролей
@ -74,7 +77,6 @@
- Устаревшая процедура (функция) расположена вне области "УстаревшиеПроцедурыИФункции"
- Использован обработчик событий, подключаемый из кода и не содержащий префикса "Подключаемый_"
### Новые быстрые исправления (Quick-fix)
- Исправление превышения максимального количества допустимых пустых строк

View File

@ -18,6 +18,8 @@ Automatic-Module-Name: com.e1c.v8codestyle.bsl
Bundle-ActivationPolicy: lazy
Import-Package: com._1c.g5.v8.bm.core;version="[8.0.0,9.0.0)",
com._1c.g5.v8.bm.integration;version="[11.0.0,12.0.0)",
com._1c.g5.v8.dt.bm.xtext;version="[15.0.0,16.0.0)",
com._1c.g5.v8.dt.bsl;version="[6.0.0,7.0.0)",
com._1c.g5.v8.dt.bsl.comment;version="[3.0.0,4.0.0)",
com._1c.g5.v8.dt.bsl.common;version="[6.0.0,7.0.0)",
com._1c.g5.v8.dt.bsl.contextdef;version="[2.0.0,3.0.0)",

View File

@ -0,0 +1,24 @@
# The asynchronous method is not followed by lines of code
In the asynchronous approach the method is called as usual, but control returns to the caller before the asynchronous
method is completed. After that, execution of the caller continues.
## Noncompliant Code Example
```bsl
Text = "Warning text";
ShowMessageBox( , Text);
Message("Warning is closed");
```
## Compliant Solution
```bsl
Text = "Warning text";
Await DoMessageBoxAsync(Text);
Message("Warning is closed");
```
## See
- [Synchronous and asynchronous operations](https://kb.1ci.com/1C_Enterprise_Platform/Guides/Developer_Guides/1C_Enterprise_8.3.19_Developer_Guide/Chapter_4._1C_Enterprise_language/4.7._Queries/4.7.9._Synchronous_and_asynchronous_operations/)

View File

@ -0,0 +1,54 @@
# Код расположен после асинхронного вызова
При асинхронном подходе вызов метода выполняется как обычно, но управление возвращается вызывающему коду до того,
как асинхронный метод завершит свою работу. После этого вызывающий код продолжает свое выполнение.
Особенность асинхронного выполнения: исполнение на стороне вызывающего кода продолжится до того,
как полностью закончилось исполнение вызванного метода.
Для правильного решения нужно вынести весь код, который должен быть выполнен после выполнения асинхронного действия,
в экспортный метод и указать его имя в обработке оповещения, которая будет вызвана после завершения асинхронного действия.
Или использовать асинхронность через обещания, например, Ждать ПредупреждениеАсинх(Текст).
## Неправильно
```bsl
Текст = "Текст предупреждения";
ПоказатьПредупреждение( , Текст);
Сообщить("Закрыли предупреждение");
```
```bsl
ПоказатьПредупреждение(,ТекстПредупреждения);
Отказ = Истина;
```
## Правильно
```bsl
Текст = "Текст предупреждения";
Ждать ПредупреждениеАсинх(Текст);
Сообщить("Закрыли предупреждение");
```
```bsl
&НаКлиенте
Процедура Команда1(Команда)
Оповещение = Новый ОписаниеОповещения("ПредупреждениеЗавершение", ЭтотОбъект);
Текст = "Текст предупреждения";
ПоказатьПредупреждение(Оповещение, Текст);
КонецПроцедуры
&НаКлиенте
Процедура ПредупреждениеЗавершение(ДополнительныеПараметры) Экспорт
Сообщить("Закрыли предупреждение");
КонецПроцедуры;
```
```bsl
Отказ = Истина;
ПоказатьПредупреждение(,ТекстПредупреждения);
```
## См.
- [Синхронные и асинхронные методы работы](https://its.1c.ru/db/v8319doc#bookmark:dev:TI000001505)

View File

@ -347,6 +347,10 @@
category="com.e1c.v8codestyle.bsl"
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.check.DeprecatedProcedureOutsideDeprecatedRegionCheck">
</check>
<check
category="com.e1c.v8codestyle.bsl"
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.check.CodeAfterAsyncCallCheck">
</check>
<check
category="com.e1c.v8codestyle.bsl"
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.check.UnknownFormParameterAccessCheck">

View File

@ -0,0 +1,44 @@
/*******************************************************************************
* Copyright (C) 2023, 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;
import java.util.Collection;
import java.util.Map;
import com._1c.g5.v8.dt.platform.version.Version;
/**
* Platform context asynchronous methods provider
*
* @author Artem Iliukhin
*/
public interface IAsyncInvocationProvider
{
/**
* Global context methods.
*
* @param version the version of platform, cannot be {@code null}
* @return the asynchronous invocation names
*/
Collection<String> getAsyncInvocationNames(Version version);
/**
* Methods with a list of types in which they are used.
*
* @param version the version of platform, cannot be {@code null}
* @return the asynchronous type method names
*/
Map<String, Collection<String>> getAsyncTypeMethodNames(Version version);
}

View File

@ -0,0 +1,261 @@
/*******************************************************************************
* Copyright (C) 2023, 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.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.EcoreUtil2;
import com._1c.g5.v8.dt.bsl.model.AwaitStatement;
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.DynamicFeatureAccess;
import com._1c.g5.v8.dt.bsl.model.EmptyStatement;
import com._1c.g5.v8.dt.bsl.model.Expression;
import com._1c.g5.v8.dt.bsl.model.FeatureAccess;
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.PreprocessorConditional;
import com._1c.g5.v8.dt.bsl.model.PreprocessorItemStatements;
import com._1c.g5.v8.dt.bsl.model.ReturnStatement;
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._1c.g5.v8.dt.bsl.resource.TypesComputer;
import com._1c.g5.v8.dt.mcore.Environmental;
import com._1c.g5.v8.dt.mcore.TypeItem;
import com._1c.g5.v8.dt.mcore.util.McoreUtil;
import com._1c.g5.v8.dt.platform.version.IRuntimeVersionSupport;
import com._1c.g5.v8.dt.platform.version.Version;
import com.e1c.g5.v8.dt.check.CheckComplexity;
import com.e1c.g5.v8.dt.check.ICheckParameters;
import com.e1c.g5.v8.dt.check.components.BasicCheck;
import com.e1c.g5.v8.dt.check.settings.IssueSeverity;
import com.e1c.g5.v8.dt.check.settings.IssueType;
import com.e1c.v8codestyle.bsl.IAsyncInvocationProvider;
import com.e1c.v8codestyle.check.CommonSenseCheckExtension;
import com.e1c.v8codestyle.internal.bsl.BslPlugin;
import com.google.common.collect.Lists;
import com.google.inject.Inject;
/**
* Checks that the asynchronous method is not followed by lines of code,
* since in this case the specified lines of code are executed immediately,
* without waiting for the asynchronous method to execute.
*
* @author Artem Iliukhin
*/
public final class CodeAfterAsyncCallCheck
extends BasicCheck
{
private static final String CHECK_ID = "code-after-async-call"; //$NON-NLS-1$
private static final String DEFAULT_CHECK = Boolean.toString(Boolean.TRUE);
private static final String PARAMETER_NAME = "notifyDescriptionIsDefined"; //$NON-NLS-1$
private static final String TYPE_NAME = "NotifyDescription"; //$NON-NLS-1$
private final IAsyncInvocationProvider asyncInvocationProvider;
private final IRuntimeVersionSupport runtimeVersionSupport;
private final TypesComputer typesComputer;
@Inject
public CodeAfterAsyncCallCheck(IRuntimeVersionSupport runtimeVersionSupport,
IAsyncInvocationProvider asyncInvocationProvider, TypesComputer typesComputer)
{
super();
this.asyncInvocationProvider = asyncInvocationProvider;
this.runtimeVersionSupport = runtimeVersionSupport;
this.typesComputer = typesComputer;
}
@Override
public String getCheckId()
{
return CHECK_ID;
}
@Override
protected void configureCheck(CheckConfigurer builder)
{
builder.title(Messages.CodeAfterAsyncCallCheck_Title)
.description(Messages.CodeAfterAsyncCallCheck_Description)
.complexity(CheckComplexity.NORMAL)
.severity(IssueSeverity.MAJOR)
.issueType(IssueType.WARNING)
.extension(new CommonSenseCheckExtension(getCheckId(), BslPlugin.PLUGIN_ID))
.module()
.checkedObjectType(INVOCATION)
.parameter(PARAMETER_NAME, Boolean.class, DEFAULT_CHECK,
Messages.CodeAfterAsyncCallCheck_Parameter);
}
@Override
protected void check(Object object, ResultAcceptor resultAceptor, ICheckParameters parameters,
IProgressMonitor monitor)
{
Version version = runtimeVersionSupport.getRuntimeVersionOrDefault((EObject)object, Version.LATEST);
Invocation inv = (Invocation)object;
FeatureAccess featureAccess = inv.getMethodAccess();
if (featureAccess instanceof StaticFeatureAccess)
{
Collection<String> asyncMethodsNames = asyncInvocationProvider.getAsyncInvocationNames(version);
if (asyncMethodsNames.contains(featureAccess.getName())
&& (isNotifyDescriptionDefined(inv) || !parameters.getBoolean(PARAMETER_NAME)))
{
checkNeighboringStatement(resultAceptor, inv);
}
}
else if (featureAccess instanceof DynamicFeatureAccess)
{
Map<String, Collection<String>> names = asyncInvocationProvider.getAsyncTypeMethodNames(version);
if (names.containsKey(featureAccess.getName())
&& (isNotifyDescriptionDefined(inv) || !parameters.getBoolean(PARAMETER_NAME)))
{
Expression source = ((DynamicFeatureAccess)featureAccess).getSource();
List<TypeItem> sourceTypes = computeTypes(source);
Collection<String> collection = names.get(featureAccess.getName());
if (collection.retainAll(sourceTypes.stream().map(McoreUtil::getTypeName).collect(Collectors.toSet())))
{
checkNeighboringStatement(resultAceptor, inv);
}
}
}
}
private boolean isNotifyDescriptionDefined(Invocation inv)
{
for (Expression param : inv.getParams())
{
List<TypeItem> sourceTypes = computeTypes(param);
for (TypeItem typeItem : sourceTypes)
{
if (TYPE_NAME.equals(McoreUtil.getTypeName(typeItem)))
{
return true;
}
}
}
return false;
}
private List<TypeItem> computeTypes(Expression expression)
{
Environmental environmental = EcoreUtil2.getContainerOfType(expression, Environmental.class);
if (environmental != null)
{
return typesComputer.computeTypes(expression, environmental.environments());
}
return List.of();
}
private void checkNeighboringStatement(ResultAcceptor resultAceptor, Invocation inv)
{
Statement statement = getStatementFromInvoc(inv);
if (statement != null && !(statement instanceof AwaitStatement))
{
statement = getNextStatement(statement);
if (statement != null && !(statement instanceof ReturnStatement)
&& !(statement instanceof EmptyStatement) && !(statement instanceof AwaitStatement))
{
resultAceptor.addIssue(Messages.CodeAfterAsyncCallCheck_Issue, statement);
}
}
}
private Statement getStatementFromInvoc(Invocation invocation)
{
EObject container = invocation.eContainer();
while (!(container instanceof Statement))
{
container = container.eContainer();
}
return container instanceof Statement ? (Statement)container : null;
}
private Statement getNextStatement(Statement statement)
{
Iterator<EObject> it = EcoreUtil2.getAllContainers(statement).iterator();
while (it.hasNext())
{
EObject container = it.next();
if (container instanceof PreprocessorConditional)
{
continue;
}
List<Statement> st = getContainer(container);
if (st != null)
{
int index = st.indexOf(statement);
if (index != -1 && index + 1 < st.size())
{
return st.get(index + 1);
}
}
}
return null;
}
private List<Statement> getContainer(EObject container)
{
List<Statement> statements = null;
if (container instanceof LoopStatement)
{
statements = ((LoopStatement)container).getStatements();
}
else if (container instanceof Conditional)
{
statements = ((Conditional)container).getStatements();
}
else if (container instanceof IfStatement)
{
statements = ((IfStatement)container).getElseStatements();
}
else if (container instanceof TryExceptStatement)
{
statements = getStatementsFromContainer((TryExceptStatement)container);
}
else if (container instanceof PreprocessorItemStatements)
{
statements = ((PreprocessorItemStatements)container).getStatements();
}
else
{
statements = getStatementsFromContainer(container);
}
return statements;
}
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

@ -61,6 +61,14 @@ final class Messages
public static String ChangeAndValidateInsteadOfAroundCheck_Use_ChangeAndValidate_instead_of_Around;
public static String ChangeAndValidateInsteadOfAroundCheck_title;
public static String CodeAfterAsyncCallCheck_Description;
public static String CodeAfterAsyncCallCheck_Issue;
public static String CodeAfterAsyncCallCheck_Parameter;
public static String CodeAfterAsyncCallCheck_Title;
public static String CommitTransactionCheck_Commit_transaction_must_be_in_try_catch;
public static String CommitTransactionCheck_No_begin_transaction_for_commit_transaction;

View File

@ -62,6 +62,14 @@ ChangeAndValidateInsteadOfAroundCheck_description = Checks that pragma &ChangeAn
ChangeAndValidateInsteadOfAroundCheck_title = Use pragma &ChangeAndValidate instead of &Around
CodeAfterAsyncCallCheck_Description = Checks that the asynchronous method is not followed by lines of code, since in this case the specified lines of code are executed immediately, without waiting for the asynchronous method to execute
CodeAfterAsyncCallCheck_Issue = The asynchronous method is followed by lines of code
CodeAfterAsyncCallCheck_Parameter = Only with the defined parameter NotifyDescription, if applicable
CodeAfterAsyncCallCheck_Title = The code should not follow an asynchronous call
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
@ -146,6 +154,12 @@ ExportMethodInCommandModule_Do_not_emded_export_method_in_modules_of_command_res
ExportMethodInCommandModule_Do_not_use_export_method_in_commands_module = Restrictions on the use of export procedures and functions
ExportProcedureMissingCommentCheck_Export_procedure_missing_comment = Export procedure (function) "{0}" should be described by adding comment
ExportProcedureMissingCommentCheck_description = Export procedure (function) should be described by adding comment
ExportProcedureMissingCommentCheck_title = Export procedure (function) should be described by adding comment
ExportVariableInObjectModuleCheck_Description = Use of an export variable is not recommended
ExportVariableInObjectModuleCheck_Issue = It's not recommended to use the export variable in the object module
@ -156,12 +170,6 @@ ExtensionMethodPrefixCheck_Description = The procedure (function) in the module
ExtensionMethodPrefixCheck_Ext_method__0__should_have__1__prefix = The method "{0}" should have "{1}" prefix
ExportProcedureMissingCommentCheck_description=Export procedure (function) should be described by adding comment
ExportProcedureMissingCommentCheck_Export_procedure_missing_comment=Export procedure (function) "{0}" should be described by adding comment
ExportProcedureMissingCommentCheck_title=Export procedure (function) should be described by adding comment
ExtensionMethodPrefixCheck_Title = Extension method does not have extension prefix
ExtensionVariablePrefixCheck_Description = The variable in the module of the extension object does not have a prefix corresponding to the prefix of the extension itself
@ -464,16 +472,16 @@ UseNonRecommendedMethods_parameter = List of non-recommended methods
UseNonRecommendedMethods_title = Using non-recommended methods
VariableNameInvalidCheck_description=Variable name is invalid
VariableNameInvalidCheck_description = Variable name is invalid
VariableNameInvalidCheck_message_variable_length_is_less_than=variable length is less than {0}
VariableNameInvalidCheck_message_variable_length_is_less_than = variable length is less than {0}
VariableNameInvalidCheck_param_MIN_NAME_LENGTH_PARAM_title=Min. lenght of variable name
VariableNameInvalidCheck_param_MIN_NAME_LENGTH_PARAM_title = Min. lenght of variable name
VariableNameInvalidCheck_title=Variable name is invalid
VariableNameInvalidCheck_title = Variable name is invalid
VariableNameInvalidCheck_variable_name_is_invalid=Variable name {0} is invalid: {1}
VariableNameInvalidCheck_variable_name_is_invalid = Variable name {0} is invalid: {1}
VariableNameInvalidCheck_variable_name_must_start_with_a_capital_letter=variable name must start with a capital letter
VariableNameInvalidCheck_variable_name_must_start_with_a_capital_letter = variable name must start with a capital letter
VariableNameInvalidCheck_variable_name_starts_with_an_underline=variable name starts with an underline
VariableNameInvalidCheck_variable_name_starts_with_an_underline = variable name starts with an underline

View File

@ -62,6 +62,14 @@ ChangeAndValidateInsteadOfAroundCheck_description = Проверяет, что
ChangeAndValidateInsteadOfAroundCheck_title = Используется аннотация &ИзменениеИКонтроль вместо &Вместо
CodeAfterAsyncCallCheck_Description = Проверяет, что за асинхронным методом не следуют строки кода, поскольку в этом случае указанные строки кода выполняются немедленно, не дожидаясь выполнения асинхронного метода
CodeAfterAsyncCallCheck_Issue = За асинхронным методом следуют строки кода
CodeAfterAsyncCallCheck_Parameter = Tолько с заданным параметром ОписаниеОповещения, если применимо
CodeAfterAsyncCallCheck_Title = Код не должен следовать за асинхронным вызовом
CommitTransactionCheck_Commit_transaction_must_be_in_try_catch = Вызов "ЗафиксироватьТранзакцию()" находится вне конструкции "Попытка... Исключение"
CommitTransactionCheck_No_begin_transaction_for_commit_transaction = Отсутствует вызов "НачатьТранзакцию()", хотя вызываются "ЗафиксироватьТранзакцию()"
@ -146,6 +154,12 @@ ExportMethodInCommandModule_Do_not_emded_export_method_in_modules_of_command_res
ExportMethodInCommandModule_Do_not_use_export_method_in_commands_module = Ограничения на использование экспортных процедур и функций
ExportProcedureMissingCommentCheck_Export_procedure_missing_comment = Отсутствует комментарий к экспортной процедуре (функции) "{0}"
ExportProcedureMissingCommentCheck_description = Отсутствует комментарий к экспортной процедуре (функции)
ExportProcedureMissingCommentCheck_title = Отсутствует комментарий к экспортной процедуре (функции)
ExportVariableInObjectModuleCheck_Description = Использование экспортной переменной не рекомендовано
ExportVariableInObjectModuleCheck_Issue = Не рекомендуется использовать экспортную переменную в модуле объекта
@ -162,12 +176,6 @@ ExtensionVariablePrefixCheck_Description = Переменная модуля р
ExtensionVariablePrefixCheck_Title = Переменная расширения должна содержать в имени префикс расширения
ExportProcedureMissingCommentCheck_description=Отсутствует комментарий к экспортной процедуре (функции)
ExportProcedureMissingCommentCheck_Export_procedure_missing_comment=Отсутствует комментарий к экспортной процедуре (функции) "{0}"
ExportProcedureMissingCommentCheck_title=Отсутствует комментарий к экспортной процедуре (функции)
ExtensionVariablePrefixCheck_Variable_0_should_have_1_prefix = Переменная "{0}" должна иметь префикс "{1}"
FormDataToValueCheck_Description = Использование ДанныеФормыВЗначение вместо РеквизитФормыВЗначение
@ -476,4 +484,4 @@ VariableNameInvalidCheck_variable_name_is_invalid = Имя переменной
VariableNameInvalidCheck_variable_name_must_start_with_a_capital_letter = имя переменной должно начинаться с заглавной буквы
VariableNameInvalidCheck_variable_name_starts_with_an_underline = имя переменной начинается с символа подчеркивания
VariableNameInvalidCheck_variable_name_starts_with_an_underline = имя переменной начинается с символа подчеркивания

View File

@ -0,0 +1,242 @@
/*******************************************************************************
* Copyright (C) 2023, 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.internal.bsl;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.xtext.resource.IEObjectDescription;
import com._1c.g5.v8.dt.bm.xtext.BmAwareResourceSetProvider;
import com._1c.g5.v8.dt.core.platform.IV8Project;
import com._1c.g5.v8.dt.core.platform.IV8ProjectManager;
import com._1c.g5.v8.dt.mcore.ContextDef;
import com._1c.g5.v8.dt.mcore.McorePackage;
import com._1c.g5.v8.dt.mcore.Method;
import com._1c.g5.v8.dt.mcore.ParamSet;
import com._1c.g5.v8.dt.mcore.Parameter;
import com._1c.g5.v8.dt.mcore.Type;
import com._1c.g5.v8.dt.mcore.TypeItem;
import com._1c.g5.v8.dt.mcore.TypeSet;
import com._1c.g5.v8.dt.mcore.util.Environment;
import com._1c.g5.v8.dt.mcore.util.McoreUtil;
import com._1c.g5.v8.dt.platform.IEObjectProvider;
import com._1c.g5.v8.dt.platform.version.Version;
import com.e1c.v8codestyle.bsl.IAsyncInvocationProvider;
import com.google.inject.Inject;
/**
* Implementing service to provide asynchronous methods
*
* @author Artem Iliukhin
*/
public class AsyncInvocationProvider
implements IAsyncInvocationProvider
{
private static final String RET_TYPE_NAME = "Promise"; //$NON-NLS-1$
private static final String EXEPTION_NAME = "RunCallback"; //$NON-NLS-1$
private static final String TYPE_NAME = "NotifyDescription"; //$NON-NLS-1$
private final Map<Version, Collection<String>> cashNames;
private final Map<Version, Map<String, Collection<String>>> cashTypesMethodNames;
private final IV8ProjectManager v8ProjectManager;
private final BmAwareResourceSetProvider resourceSetProvider;
private final Set<Environment> clientEnv;
@Inject
public AsyncInvocationProvider(IV8ProjectManager v8ProjectManager, BmAwareResourceSetProvider resourceSetProvider)
{
super();
this.v8ProjectManager = v8ProjectManager;
this.resourceSetProvider = resourceSetProvider;
this.cashNames = new ConcurrentHashMap<>();
this.cashTypesMethodNames = new ConcurrentHashMap<>();
this.clientEnv = Set.of(Environment.CLIENT, Environment.MNG_CLIENT, Environment.MOBILE_CLIENT,
Environment.MOBILE_THIN_CLIENT, Environment.THIN_CLIENT, Environment.WEB_CLIENT);
}
@Override
public Collection<String> getAsyncInvocationNames(Version version)
{
return cashNames.computeIfAbsent(version, this::collectGlobalAsyncMethods);
}
@Override
public Map<String, Collection<String>> getAsyncTypeMethodNames(Version version)
{
return cashTypesMethodNames.computeIfAbsent(version, this::collectAsyncMethods);
}
private Collection<String> collectGlobalAsyncMethods(Version version)
{
Collection<String> asyncMethodsNames = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
Iterator<IV8Project> iterator = v8ProjectManager.getProjects().iterator();
if (iterator.hasNext())
{
ResourceSet context = resourceSetProvider.get(iterator.next().getProject());
IEObjectProvider provider = IEObjectProvider.Registry.INSTANCE.get(McorePackage.Literals.METHOD, version);
Iterable<IEObjectDescription> items = provider.getEObjectDescriptions(null);
for (IEObjectDescription item : items)
{
EObject object = EcoreUtil.resolve(item.getEObjectOrProxy(), context);
if (object instanceof Method)
{
collectMethod(asyncMethodsNames, (Method)object);
}
}
}
return asyncMethodsNames;
}
private Map<String, Collection<String>> collectAsyncMethods(Version version)
{
Map<String, Collection<String>> asyncMethodsNames = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
Iterator<IV8Project> iterator = v8ProjectManager.getProjects().iterator();
if (iterator.hasNext())
{
ResourceSet context = resourceSetProvider.get(iterator.next().getProject());
IEObjectProvider provider =
IEObjectProvider.Registry.INSTANCE.get(McorePackage.Literals.TYPE_ITEM, version);
Iterable<IEObjectDescription> items = provider.getEObjectDescriptions(null);
for (IEObjectDescription item : items)
{
EObject object = EcoreUtil.resolve(item.getEObjectOrProxy(), context);
if (object instanceof Type)
{
Type type = (Type)object;
process(asyncMethodsNames, type);
}
else if (object instanceof TypeSet)
{
TypeSet typeSet = (TypeSet)object;
for (Type type : typeSet.getTypes())
{
process(asyncMethodsNames, type);
}
}
}
}
return asyncMethodsNames;
}
private void process(Map<String, Collection<String>> asyncMethodsNames, Type type)
{
if (type == null || type.eIsProxy())
{
return;
}
ContextDef contextDef = type.getContextDef();
if (contextDef == null)
{
return;
}
for (Method method : contextDef.allMethods())
{
if (isClient(method) && isRetTypePromise(method))
{
if (asyncMethodsNames.get(method.getName()) == null)
{
asyncMethodsNames.putIfAbsent(method.getName(), new TreeSet<>());
asyncMethodsNames.putIfAbsent(method.getNameRu(), new TreeSet<>());
}
asyncMethodsNames.get(method.getName()).add(type.getName());
asyncMethodsNames.get(method.getName()).add(type.getNameRu());
asyncMethodsNames.get(method.getNameRu()).add(type.getName());
asyncMethodsNames.get(method.getNameRu()).add(type.getNameRu());
}
}
}
private void collectMethod(Collection<String> asyncMethodsNames, Method method)
{
if (EXEPTION_NAME.equals(method.getName()))
{
return;
}
if (isMethodAsync(method))
{
asyncMethodsNames.add(method.getName());
asyncMethodsNames.add(method.getNameRu());
}
}
private boolean isMethodAsync(Method method)
{
if (isClient(method) && isRetTypePromise(method))
{
return true;
}
for (ParamSet paramSet : method.getParamSet())
{
for (Parameter param : paramSet.getParams())
{
if (isCallbackDescription(param))
{
return true;
}
}
}
return false;
}
private boolean isClient(Method method)
{
for (Environment env : method.environments().toArray())
{
if (!clientEnv.contains(env))
{
return false;
}
}
return true;
}
private boolean isRetTypePromise(Method method)
{
for (TypeItem type : method.getRetValType())
{
if (RET_TYPE_NAME.equals(McoreUtil.getTypeName(type)))
{
return true;
}
}
return false;
}
private boolean isCallbackDescription(Parameter param)
{
for (TypeItem type : param.getType())
{
if (TYPE_NAME.equals(McoreUtil.getTypeName(type)))
{
return true;
}
}
return false;
}
}

View File

@ -20,6 +20,7 @@ import org.osgi.framework.BundleContext;
import com._1c.g5.v8.dt.bsl.model.BslPackage;
import com._1c.g5.wiring.InjectorAwareServiceRegistrator;
import com._1c.g5.wiring.ServiceInitialization;
import com.e1c.v8codestyle.bsl.IAsyncInvocationProvider;
import com.e1c.v8codestyle.bsl.IModuleStructureProvider;
import com.google.inject.Guice;
import com.google.inject.Injector;
@ -131,6 +132,7 @@ public class BslPlugin
ServiceInitialization.schedule(() -> {
// register services from injector
registrator.service(IModuleStructureProvider.class).registerInjected();
registrator.service(IAsyncInvocationProvider.class).registerInjected();
registrator.managedService(MultiCheckFixRegistrator.class).activateBeforeRegistration().registerInjected();
});
}

View File

@ -25,6 +25,7 @@ import org.eclipse.xtext.resource.IResourceServiceProvider;
import org.eclipse.xtext.resource.impl.ResourceDescriptionsProvider;
import org.eclipse.xtext.scoping.IScopeProvider;
import com._1c.g5.v8.dt.bm.xtext.BmAwareResourceSetProvider;
import com._1c.g5.v8.dt.bsl.common.IBslPreferences;
import com._1c.g5.v8.dt.bsl.contextdef.IBslModuleContextDefService;
import com._1c.g5.v8.dt.bsl.documentation.comment.BslMultiLineCommentDocumentationProvider;
@ -96,5 +97,6 @@ class ExternalDependenciesModule
bind(ResourceDescriptionsProvider.class).toService();
bind(IConfigurationProvider.class).toService();
bind(BslGrammarAccess.class).toProvider(() -> rsp.get(BslGrammarAccess.class));
bind(BmAwareResourceSetProvider.class).toProvider(() -> rsp.get(BmAwareResourceSetProvider.class));
}
}

View File

@ -12,6 +12,7 @@
*******************************************************************************/
package com.e1c.v8codestyle.internal.bsl;
import com.e1c.v8codestyle.bsl.IAsyncInvocationProvider;
import com.e1c.v8codestyle.bsl.IModuleStructureProvider;
import com.google.inject.AbstractModule;
import com.google.inject.Singleton;
@ -29,6 +30,7 @@ public class ServiceModule
protected void configure()
{
bind(IModuleStructureProvider.class).to(ModuleStructureProvider.class).in(Singleton.class);
bind(IAsyncInvocationProvider.class).to(AsyncInvocationProvider.class).in(Singleton.class);
}
}

View File

@ -0,0 +1,15 @@
# Role-based setting of visibility (editing, use) for the form element is used
In case of a large number of roles in the configuration (from several
tens) it is not recommended to use the role-based visibility setting in
form elements (viewing and editing details by roles,
user visibility of form fields by roles, use of commands by
roles).
## Noncompliant Code Example
## Compliant Solution
## See
[Checking permissions](https://its.1c.ru/db/v8std#content:737:hdoc:1)

View File

@ -0,0 +1,15 @@
# Использована ролевая настройка видимости (редактирования, использования) для элемента формы
В случае большого количества ролей в конфигурации (от нескольких
десятков) не рекомендуется использовать ролевую настройку видимости в
элементах форм (просмотр и редактирование реквизитов по ролям,
пользовательскую видимость полей формы по ролям, использование команд по
ролям).
## Неправильно
## Правильно
## См.
[Checking permissions](https://its.1c.ru/db/v8std#content:737:hdoc:1)

View File

@ -50,6 +50,10 @@
category="com.e1c.v8codestyle.form"
class="com.e1c.v8codestyle.internal.form.ExecutableExtensionFactory:com.e1c.v8codestyle.form.check.FormCommandsSingleEventHandlerCheck">
</check>
<check
category="com.e1c.v8codestyle.form"
class="com.e1c.v8codestyle.form.check.FormItemVisibleSettingsByRolesCheck">
</check>
</extension>
<extension
point="com.e1c.g5.v8.dt.check.fixes">

View File

@ -0,0 +1,171 @@
/*******************************************************************************
* Copyright (C) 2023, 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.form.check;
import static com._1c.g5.v8.dt.form.model.FormPackage.Literals.ABSTRACT_FORM_ATTRIBUTE__EDIT;
import static com._1c.g5.v8.dt.form.model.FormPackage.Literals.ABSTRACT_FORM_ATTRIBUTE__VIEW;
import static com._1c.g5.v8.dt.form.model.FormPackage.Literals.FORM;
import static com._1c.g5.v8.dt.form.model.FormPackage.Literals.FORM_COMMAND__USE;
import static com._1c.g5.v8.dt.form.model.FormPackage.Literals.VISIBLE__USER_VISIBLE;
import static com._1c.g5.v8.dt.metadata.mdclass.MdClassPackage.Literals.ADJUSTABLE_BOOLEAN;
import static com._1c.g5.v8.dt.metadata.mdclass.MdClassPackage.Literals.ADJUSTABLE_BOOLEAN__COMMON;
import java.text.MessageFormat;
import java.util.Set;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import com._1c.g5.v8.dt.form.model.FormAttribute;
import com._1c.g5.v8.dt.form.model.FormCommand;
import com._1c.g5.v8.dt.form.model.Visible;
import com._1c.g5.v8.dt.mcore.NamedElement;
import com._1c.g5.v8.dt.metadata.mdclass.AdjustableBoolean;
import com._1c.g5.v8.dt.metadata.mdclass.ForRoleType;
import com.e1c.g5.v8.dt.check.CheckComplexity;
import com.e1c.g5.v8.dt.check.ICheckParameters;
import com.e1c.g5.v8.dt.check.components.BasicCheck;
import com.e1c.g5.v8.dt.check.settings.IssueSeverity;
import com.e1c.g5.v8.dt.check.settings.IssueType;
import com.e1c.v8codestyle.check.StandardCheckExtension;
import com.e1c.v8codestyle.internal.form.CorePlugin;
/**
* Check if Form Item (attribute, command, visible item) use role-based settings for visible, use edit.
*
* @author Vadim Goncharov
*/
public class FormItemVisibleSettingsByRolesCheck
extends BasicCheck
{
private static final String CHECK_ID = "form-item-visible-settings-by-roles"; //$NON-NLS-1$
private static final Set<EStructuralFeature> FEATURE_LIST =
Set.of(VISIBLE__USER_VISIBLE, FORM_COMMAND__USE, ABSTRACT_FORM_ATTRIBUTE__EDIT, ABSTRACT_FORM_ATTRIBUTE__VIEW);
public FormItemVisibleSettingsByRolesCheck()
{
super();
}
@Override
public String getCheckId()
{
return CHECK_ID;
}
@Override
protected void configureCheck(CheckConfigurer builder)
{
builder.title(Messages.FormItemVisibleSettingsByRoles_title)
.description(Messages.FormItemVisibleSettingsByRoles_description)
.complexity(CheckComplexity.NORMAL)
.severity(IssueSeverity.MINOR)
.issueType(IssueType.WARNING)
.extension(new StandardCheckExtension(737, getCheckId(), CorePlugin.PLUGIN_ID))
.topObject(FORM)
.containment(ADJUSTABLE_BOOLEAN)
.features(ADJUSTABLE_BOOLEAN__COMMON);
}
@Override
protected void check(Object object, ResultAcceptor resultAceptor, ICheckParameters parameters,
IProgressMonitor monitor)
{
AdjustableBoolean adjBoolean = (AdjustableBoolean)object;
EObject eContainer = adjBoolean.eContainer();
EStructuralFeature eContainingFeature = adjBoolean.eContainingFeature();
if (monitor.isCanceled() || !(adjBoolean.isCommon() && isCorrectContainer(eContainer)
&& isCorrectContainmentFeature(eContainingFeature)))
{
return;
}
EList<ForRoleType> forRoleList = adjBoolean.getFor();
if (monitor.isCanceled() || forRoleList == null)
{
return;
}
if (!forRoleList.isEmpty())
{
String itemName = getItemName(eContainer);
String propertyName = getPropertyName(eContainer, eContainingFeature);
resultAceptor.addIssue(
MessageFormat.format(Messages.FormItemVisibleSettingsByRoles_Message_template, propertyName, itemName),
adjBoolean,
ADJUSTABLE_BOOLEAN__COMMON);
}
}
private boolean isCorrectContainer(EObject eContainer)
{
return eContainer instanceof Visible || eContainer instanceof FormCommand
|| eContainer instanceof FormAttribute;
}
private boolean isCorrectContainmentFeature(EStructuralFeature feature)
{
return FEATURE_LIST.contains(feature);
}
private String getItemName(EObject eContainer)
{
String itemName = null;
if (eContainer instanceof Visible && eContainer instanceof NamedElement)
{
itemName = ((NamedElement)eContainer).getName();
}
else if (eContainer instanceof FormCommand)
{
itemName = ((FormCommand)eContainer).getName();
}
else if (eContainer instanceof FormAttribute)
{
itemName = ((FormAttribute)eContainer).getName();
}
return itemName;
}
private String getPropertyName(EObject eContainer, EStructuralFeature eContainingFeature)
{
String propertyName = null;
if (eContainer instanceof Visible
|| eContainer instanceof FormAttribute && eContainingFeature.equals(ABSTRACT_FORM_ATTRIBUTE__VIEW))
{
propertyName = Messages.FormItemVisibleSettingsByRoles_Property_name_visible;
}
else if (eContainer instanceof FormAttribute && eContainingFeature.equals(ABSTRACT_FORM_ATTRIBUTE__EDIT))
{
propertyName = Messages.FormItemVisibleSettingsByRoles_Property_name_edit;
}
else if (eContainer instanceof FormCommand)
{
propertyName = Messages.FormItemVisibleSettingsByRoles_Property_name_use;
}
return propertyName;
}
}

View File

@ -33,6 +33,12 @@ final class Messages
public static String FormItemsSingleEventHandlerCheck_itemName_dot_eventName;
public static String FormItemsSingleEventHandlerCheck_the_handler_is_already_assigned_to_event;
public static String FormItemsSingleEventHandlerCheck_title;
public static String FormItemVisibleSettingsByRoles_description;
public static String FormItemVisibleSettingsByRoles_Message_template;
public static String FormItemVisibleSettingsByRoles_Property_name_edit;
public static String FormItemVisibleSettingsByRoles_Property_name_use;
public static String FormItemVisibleSettingsByRoles_Property_name_visible;
public static String FormItemVisibleSettingsByRoles_title;
public static String FormListFieldRefNotAddedCheck_description;
public static String FormListFieldRefNotAddedCheck_The_Ref_field_is_not_added_to_dynamic_list;
public static String FormListFieldRefNotAddedCheck_title;

View File

@ -25,6 +25,18 @@ FormCommandsSingleEventHandlerCheck_Handler__0__command__1__assigned_to_command_
FormCommandsSingleEventHandlerCheck_Title = One handler assigned to multiple commands
FormItemVisibleSettingsByRoles_Message_template = Use role-based setting "{0}" for form item "{1}"
FormItemVisibleSettingsByRoles_Property_name_edit = Edit
FormItemVisibleSettingsByRoles_Property_name_use = Use
FormItemVisibleSettingsByRoles_Property_name_visible = Visible
FormItemVisibleSettingsByRoles_description = Use role-based settings for form item
FormItemVisibleSettingsByRoles_title = Use role-based settings for form item
FormItemsSingleEventHandlerCheck_description = Each event in the form items should have a unique handler
FormItemsSingleEventHandlerCheck_itemName_dot_eventName = {0}.{1}

View File

@ -25,6 +25,18 @@ FormCommandsSingleEventHandlerCheck_Handler__0__command__1__assigned_to_command_
FormCommandsSingleEventHandlerCheck_Title = Один обработчик назначен нескольким командам
FormItemVisibleSettingsByRoles_Message_template = Использована ролевая настройка "{0}" для элемента формы "{1}"
FormItemVisibleSettingsByRoles_Property_name_edit = Редактирование
FormItemVisibleSettingsByRoles_Property_name_use = Использование
FormItemVisibleSettingsByRoles_Property_name_visible = Видимость
FormItemVisibleSettingsByRoles_description = Использована ролевая настройка для элемента формы
FormItemVisibleSettingsByRoles_title = Использована ролевая настройка для элемента формы
FormItemsSingleEventHandlerCheck_description = У каждого события должна быть назначена своя процедура-обработчик
FormItemsSingleEventHandlerCheck_itemName_dot_eventName = {0}.{1}

View File

@ -1,6 +1,12 @@
# Temporary table should have indexes
1. Indexing is reasonable if:
1.1 A large temporary table is involved in a join (regardless of on which side).
Add fields involved in the BY condition to the index.
1.2 A temporary table is called in a subquery of the construct of the logical IN (...) operator.
To the index, add fields of the temporary table from a selection list that match fields listed
on the left side of the logical IN(...) operator.
2. You do not need to index small temporary tables consisting of less than 1,000 records.
## Noncompliant Code Example
@ -8,3 +14,4 @@
## See
- [Using temporary tables](https://kb.1ci.com/1C_Enterprise_Platform/Guides/Developer_Guides/1C_Enterprise_Development_Standards/Data_processing/Optimizing_queries/Using_temporary_tables/)

View File

@ -1,10 +1,104 @@
# Временная таблица должна содержать индексы
1. Индекс следует строить если:
1.1 Большая временная таблица участвует в соединении (не важно, с какой стороны).
В индекс следует добавлять поля, участвующие в условии ПО.
1.2 Обращение к временной таблице выполняется в подзапросе конструкции логического оператора В (...).
В индекс следует добавлять поля временной таблицы из списка выбора, соответствующие перечисленным
с левой стороны логического оператора В (...).
2. Маленькие временные таблицы индексировать не нужно (менее 1000 записей).
## Неправильно
```bsl
// Пример 1. Создаем врем. таблицу и делаем из нее выборку по полю "Контрагент". Т.к. врем. таблица не ограничена
// количеством записей (их может быть больше 1000), необходимо создать индекс.
ВЫБРАТЬ
СФПолученная.Контрагент КАК Контрагент,
СФПолученная.Сумма КАК Сумма
ПОМЕСТИТЬ ВТ
ИЗ
Документ.СФПолученная КАК СФПолученная
ГДЕ
СФПолученная.Дата МЕЖДУ &НачалоПериода И &КонецПериода
СФПолученная.Контрагент В(&Контрагенты);
ВЫБРАТЬ
ВТ.Сумма КАК Сумма
ИЗ
ВТ КАК ВТ
ГДЕ
ВТ.Контрагент = &Контрагент_ТД;
// Пример 2. Врем. таблица ВТ содержит не более 500 записей, поэтому ее индексирование будет излишним.
ВЫБРАТЬ ПЕРВЫЕ 500
Сотрудники.Ссылка КАК Сотрудник,
Сотрудники.Организация КАК Организация
ПОМЕСТИТЬ ВТ
ИЗ
Справочник.Сотрудники КАК Сотрудники
ГДЕ
Сотрудники.ВАрхиве
ИНДЕКСИРОВАТЬ ПО
Сотрудник;
ВЫБРАТЬ
ВТ.Сотрудник КАК Сотрудник
ИЗ
ВТ КАК ВТ
ГДЕ
ВТ.Организация = &Организация;
```
## Правильно
```bsl
// Пример 1. Создаем временную таблицу и выбираем из нее данные. Врем. таблица не ограничена кол-вом записей
// и может быть большого размера, поэтому индексируем по полю Контагент, т.к. выборка из ВТ с отбором по этому полю.
ВЫБРАТЬ
СФПолученная.Контрагент КАК Контрагент,
СФПолученная.Сумма КАК Сумма
ПОМЕСТИТЬ ВТ
ИЗ
Документ.СФПолученная КАК СФПолученная
ГДЕ
СФПолученная.Контрагент В(&Контрагенты)
ИНДЕКСИРОВАТЬ ПО
Контрагент;
ВЫБРАТЬ
ВТ.Сумма КАК Сумма
ИЗ
ВТ КАК ВТ
ГДЕ
ВТ.Контрагент = &Контрагент_Астория;
// Пример 2. Врем. таблица может иметь до 10000 строк, поэтому индексирование необходимо.
ВЫБРАТЬ ПЕРВЫЕ 10000
Сотрудники.Ссылка КАК Сотрудник,
Сотрудники.Организация КАК Организация
ПОМЕСТИТЬ ВТ
ИЗ
Справочник.Сотрудники КАК Сотрудники
ГДЕ
Сотрудники.ВАрхиве
ИНДЕКСИРОВАТЬ ПО
Сотрудник;
ВЫБРАТЬ
ВТ.Сотрудник КАК Сотрудник
ИЗ
ВТ КАК ВТ
ГДЕ
ВТ.Организация = &Организация;
```
## См.
- [Использование временных таблиц](https://its.1c.ru/db/v8std/content/777/hdoc)

View File

@ -44,6 +44,7 @@ final class Messages
public static String TempTableHasIndex_description;
public static String TempTableHasIndex_Exclude_table_name_pattern;
public static String TempTableHasIndex_New_temporary_table_should_have_indexes;
public static String TempTableHasIndex_Parameter_max_top;
public static String TempTableHasIndex_title;
public static String UsingForUpdateCheck_description;
public static String UsingForUpdateCheck_title;

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (C) 2021, 1C-Soft LLC and others.
* Copyright (C) 2023, 1C-Soft LLC and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
@ -34,6 +34,7 @@ import com.e1c.v8codestyle.internal.ql.CorePlugin;
* This check may be enhanced in the future.
*
* @author Dmitriy Marmyshev
* @author Vadim Goncharov
*/
public class TempTableHasIndex
extends QlBasicDelegateCheck
@ -43,7 +44,9 @@ public class TempTableHasIndex
private static final String PARAMETER_EXCLUDE_TABLE_NAME_PATTERN = "excludeObjectNamePattern"; //$NON-NLS-1$
private static final int MAX_TOP = 1000;
private static final String PARAMETER_MAX_TOP = "maxTop"; //$NON-NLS-1$
private static final int MAX_TOP_DEFAULT = 1000;
@Override
public String getCheckId()
@ -61,8 +64,11 @@ public class TempTableHasIndex
.issueType(IssueType.PERFORMANCE)
.extension(new StandardCheckExtension(777, getCheckId(), CorePlugin.PLUGIN_ID))
.delegate(QuerySchemaSelectQuery.class);
builder.parameter(PARAMETER_EXCLUDE_TABLE_NAME_PATTERN, String.class, StringUtils.EMPTY,
Messages.TempTableHasIndex_Exclude_table_name_pattern);
builder
.parameter(PARAMETER_EXCLUDE_TABLE_NAME_PATTERN, String.class, StringUtils.EMPTY,
Messages.TempTableHasIndex_Exclude_table_name_pattern)
.parameter(PARAMETER_MAX_TOP, Integer.class, Integer.toString(MAX_TOP_DEFAULT),
Messages.TempTableHasIndex_Parameter_max_top);
}
@Override
@ -70,7 +76,8 @@ public class TempTableHasIndex
ICheckParameters parameters, IProgressMonitor monitor)
{
QuerySchemaSelectQuery selectQuery = (QuerySchemaSelectQuery)object;
if (selectQuery.getPlacementTable() == null || isTopLessThenThousand(selectQuery))
int maxTop = parameters.getInt(PARAMETER_MAX_TOP);
if (selectQuery.getPlacementTable() == null || isTopLessThenMaxTop(selectQuery, maxTop))
{
return;
}
@ -89,7 +96,7 @@ public class TempTableHasIndex
}
}
private boolean isTopLessThenThousand(QuerySchemaSelectQuery selectQuery)
private boolean isTopLessThenMaxTop(QuerySchemaSelectQuery selectQuery, int maxTop)
{
if (!selectQuery.getOperators().isEmpty() && selectQuery.getOperators().get(0).getGetRecordsCount() != null)
{
@ -97,7 +104,7 @@ public class TempTableHasIndex
try
{
int top = Integer.parseInt(count);
return top < MAX_TOP;
return top < maxTop;
}
catch (NumberFormatException e)
{

View File

@ -56,6 +56,8 @@ TempTableHasIndex_New_temporary_table_should_have_indexes = New temporary table
TempTableHasIndex_description = Temporary table should have indexes
TempTableHasIndex_Parameter_max_top = Max rows in query
TempTableHasIndex_title = Temporary table should have indexes
UsingForUpdateCheck_description = Check if query contains "FOR UPDATE"

View File

@ -57,6 +57,8 @@ TempTableHasIndex_New_temporary_table_should_have_indexes = Новая врем
TempTableHasIndex_description = Временная таблица должна содержать индексы
TempTableHasIndex_Parameter_max_top = Макс. количество строк в запросе
TempTableHasIndex_title = Временная таблица должна содержать индексы
UsingForUpdateCheck_description = Проверка наличия конструкции "ДЛЯ ИЗМЕНЕНИЯ" в запросе

View File

@ -0,0 +1,16 @@
&НаКлиенте
Процедура Тест()
Оповещение = Новый ОписаниеОповещения("ПредупреждениеЗавершение", ЭтотОбъект);
Текст = "Текст предупреждения";
ПоказатьПредупреждение(Оповещение, Текст);
КонецПроцедуры
&НаКлиенте
Процедура ПредупреждениеЗавершение(ДополнительныеПараметры) Экспорт
Сообщить("Закрыли предупреждение");
КонецПроцедуры;

View File

@ -0,0 +1,7 @@
Асинх Процедура Тест1(Параметры)
Ждать ВопросАсинх(Параметры,);
Сообщить("Закрыли предупреждение");
КонецПроцедуры

View File

@ -0,0 +1,8 @@
Асинх Процедура Тест2(Параметры)
Обещание = ПредупреждениеАсинх(Параметры);
Ждать Обещание;
Сообщить("Закрыли предупреждение");
КонецПроцедуры

View File

@ -0,0 +1,6 @@
Асинх Функция Тест3(Параметры)
Возврат Ждать ПредупреждениеАсинх(Параметры);
КонецФункции

View File

@ -0,0 +1,7 @@
Асинх Функция Тест4(Параметры)
Обещание = ПредупреждениеАсинх(Параметры);
Возврат Ждать Обещание;
КонецФункции

View File

@ -0,0 +1,10 @@
Процедура Тест()
ТабДок = Новый ТабличныйДокумент;
ТабДок.ЗаписатьАсинх();
Сообщить("кто быстрее?");
КонецПроцедуры

View File

@ -0,0 +1,9 @@
&НаКлиенте
Процедура Тест()
Текст = "Текст предупреждения";
ПоказатьПредупреждение(, Текст);
Сообщить("Закрыли предупреждение");
КонецПроцедуры

View File

@ -0,0 +1,135 @@
/*******************************************************************************
* Copyright (C) 2023, 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 static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import java.util.Collections;
import org.eclipse.core.resources.IProject;
import org.junit.Test;
import com._1c.g5.v8.dt.core.platform.IDtProject;
import com._1c.g5.v8.dt.validation.marker.IExtraInfoKeys;
import com._1c.g5.v8.dt.validation.marker.Marker;
import com.e1c.g5.v8.dt.check.settings.CheckUid;
import com.e1c.g5.v8.dt.check.settings.ICheckSettings;
import com.e1c.v8codestyle.bsl.check.CodeAfterAsyncCallCheck;
import com.e1c.v8codestyle.internal.bsl.BslPlugin;
/**
* Tests for {@link CodeAfterAsyncCallCheck} check.
*
* @author Artem Iliukhin
*/
public class CodeAfterAsyncCallCheckTest
extends AbstractSingleModuleTestBase
{
private static final String CHECK_ID = "code-after-async-call"; //$NON-NLS-1$
private static final String PARAMETER_NAME = "notifyDescriptionIsDefined"; //$NON-NLS-1$
/**
* Instantiates a new code after async call check test.
*/
public CodeAfterAsyncCallCheckTest()
{
super(CodeAfterAsyncCallCheck.class);
}
@Test
public void testCodeAfterExistence() throws Exception
{
setParameterValue(Boolean.FALSE);
updateModule(FOLDER_RESOURCE + "code-after-async-call-existence.bsl");
Marker marker = getFirstMarker(CHECK_ID, getModuleId(), getProject());
assertNotNull(marker);
assertEquals("7", marker.getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_LINE_KEY));
}
@Test
public void testCallBackDescriptionCompliant() throws Exception
{
updateModule(FOLDER_RESOURCE + "async-call-back-descr.bsl");
Marker marker = getFirstMarker(CHECK_ID, getModuleId(), getProject());
assertNull(marker);
}
@Test
public void testPromiseCompliant() throws Exception
{
setParameterValue(Boolean.FALSE);
updateModule(FOLDER_RESOURCE + "async-call-promise.bsl");
Marker marker = getFirstMarker(CHECK_ID, getModuleId(), getProject());
assertNull(marker);
}
@Test
public void testPromiseCompliant2() throws Exception
{
setParameterValue(Boolean.FALSE);
updateModule(FOLDER_RESOURCE + "async-call-promise2.bsl");
Marker marker = getFirstMarker(CHECK_ID, getModuleId(), getProject());
assertNull(marker);
}
@Test
public void testPromiseCompliant3() throws Exception
{
setParameterValue(Boolean.FALSE);
updateModule(FOLDER_RESOURCE + "async-call-promise3.bsl");
Marker marker = getFirstMarker(CHECK_ID, getModuleId(), getProject());
assertNull(marker);
}
@Test
public void testPromiseComplian4() throws Exception
{
setParameterValue(Boolean.FALSE);
updateModule(FOLDER_RESOURCE + "async-call-promise4.bsl");
Marker marker = getFirstMarker(CHECK_ID, getModuleId(), getProject());
assertNull(marker);
}
@Test
public void testSpreadsheetDocumentNonCompliant() throws Exception
{
updateModule(FOLDER_RESOURCE + "async-call-spread-sh-doc.bsl");
Marker marker = getFirstMarker(CHECK_ID, getModuleId(), getProject());
assertNotNull(marker);
assertEquals("8", marker.getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_LINE_KEY));
}
private void setParameterValue(Boolean value)
{
IDtProject dtProject = getProject();
IProject project = dtProject.getWorkspaceProject();
ICheckSettings settings = checkRepository.getSettings(new CheckUid(CHECK_ID, BslPlugin.PLUGIN_ID), project);
settings.getParameters().get(PARAMETER_NAME).setValue(Boolean.toString(value));
checkRepository.applyChanges(Collections.singleton(settings), project);
waitForDD(dtProject);
}
}

View File

@ -0,0 +1,87 @@
/*******************************************************************************
* Copyright (C) 2023, 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.form.check.itests;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import org.junit.Test;
import com._1c.g5.v8.dt.core.platform.IDtProject;
import com._1c.g5.v8.dt.validation.marker.Marker;
import com.e1c.g5.v8.dt.testing.check.CheckTestBase;
import com.e1c.v8codestyle.form.check.FormItemVisibleSettingsByRolesCheck;
/**
* Tests for {@link FormItemVisibleSettingsByRolesCheck} check.
* @author Vadim Goncharov
*/
public class FormItemVisibleSettingsByRolesCheckTest
extends CheckTestBase
{
private static final String CHECK_ID = "form-item-visible-settings-by-roles";
private static final String PROJECT_NAME = "FormItemVisibleSettingsByRoles";
/**
* Test form item use role based settings.
*
* @throws Exception the exception
*/
@Test
public void testFormItemUseRoleBasedSettings() throws Exception
{
IDtProject project = openProjectAndWaitForValidationFinish(PROJECT_NAME);
assertNotNull(project);
// Form attribute edit setting by roles
long id = getTopObjectIdByFqn("CommonForm.TestForm1.Form", project);
Marker marker = getFirstNestedMarker(CHECK_ID, id, project);
assertNotNull(marker);
// Form attribute view setting by roles
id = getTopObjectIdByFqn("CommonForm.TestForm2.Form", project);
marker = getFirstNestedMarker(CHECK_ID, id, project);
assertNotNull(marker);
// Form visible item view setting by roles
id = getTopObjectIdByFqn("CommonForm.TestForm3.Form", project);
marker = getFirstNestedMarker(CHECK_ID, id, project);
assertNotNull(marker);
// Form command use setting by roles
id = getTopObjectIdByFqn("CommonForm.TestForm4.Form", project);
marker = getFirstNestedMarker(CHECK_ID, id, project);
assertNotNull(marker);
}
/**
* Test form item not use role based settings.
*
* @throws Exception the exception
*/
@Test
public void testFormItemNotUseRoleBasedSettings() throws Exception
{
IDtProject project = openProjectAndWaitForValidationFinish(PROJECT_NAME);
assertNotNull(project);
// Form attribute, visible item and command
long id = getTopObjectIdByFqn("CommonForm.TestForm5.Form", project);
Marker marker = getFirstNestedMarker(CHECK_ID, id, project);
assertNull(marker);
}
}

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>FormItemVisibleSettingsByRoles</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.xtext.ui.shared.xtextBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.xtext.ui.shared.xtextNature</nature>
<nature>com._1c.g5.v8.dt.core.V8ConfigurationNature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,2 @@
Manifest-Version: 1.0
Runtime-Version: 8.3.19

View File

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<form:Form xmlns:form="http://g5.1c.ru/v8/dt/form">
<autoCommandBar>
<name>FormCommandBar</name>
<id>-1</id>
<visible>true</visible>
<enabled>true</enabled>
<userVisible>
<common>true</common>
</userVisible>
<horizontalAlign>Left</horizontalAlign>
<autoFill>true</autoFill>
</autoCommandBar>
<autoTitle>true</autoTitle>
<autoUrl>true</autoUrl>
<group>Vertical</group>
<autoFillCheck>true</autoFillCheck>
<allowFormCustomize>true</allowFormCustomize>
<enabled>true</enabled>
<showTitle>true</showTitle>
<showCloseButton>true</showCloseButton>
<attributes>
<name>TestAttributeEditByRoles</name>
<title>
<key>en</key>
<value>Test attribute edit by roles</value>
</title>
<id>1</id>
<valueType>
<types>String</types>
<stringQualifiers/>
</valueType>
<view>
<common>true</common>
</view>
<edit>
<common>true</common>
<for>
<value>true</value>
<role>Role.TestRole1</role>
</for>
</edit>
</attributes>
<commandInterface>
<navigationPanel/>
<commandBar/>
</commandInterface>
</form:Form>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<mdclass:CommonForm xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass" uuid="420e0b97-3465-4d75-b55b-c383c7ef9341">
<name>TestForm1</name>
<synonym>
<key>en</key>
<value>Test form1</value>
</synonym>
<usePurposes>PersonalComputer</usePurposes>
<usePurposes>MobileDevice</usePurposes>
</mdclass:CommonForm>

View File

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<form:Form xmlns:form="http://g5.1c.ru/v8/dt/form">
<autoCommandBar>
<name>FormCommandBar</name>
<id>-1</id>
<visible>true</visible>
<enabled>true</enabled>
<userVisible>
<common>true</common>
</userVisible>
<horizontalAlign>Left</horizontalAlign>
<autoFill>true</autoFill>
</autoCommandBar>
<autoTitle>true</autoTitle>
<autoUrl>true</autoUrl>
<group>Vertical</group>
<autoFillCheck>true</autoFillCheck>
<allowFormCustomize>true</allowFormCustomize>
<enabled>true</enabled>
<showTitle>true</showTitle>
<showCloseButton>true</showCloseButton>
<attributes>
<name>TestAttributeViewByRoles</name>
<title>
<key>en</key>
<value>Test attribute view by roles</value>
</title>
<id>1</id>
<valueType>
<types>String</types>
<stringQualifiers/>
</valueType>
<view>
<common>true</common>
<for>
<value>true</value>
<role>Role.TestRole1</role>
</for>
</view>
<edit>
<common>true</common>
</edit>
</attributes>
<commandInterface>
<navigationPanel/>
<commandBar/>
</commandInterface>
</form:Form>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<mdclass:CommonForm xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass" uuid="87a0eb6a-8818-41ec-a5e8-f112703bbf3a">
<name>TestForm2</name>
<synonym>
<key>en</key>
<value>Test form2</value>
</synonym>
<usePurposes>PersonalComputer</usePurposes>
<usePurposes>MobileDevice</usePurposes>
</mdclass:CommonForm>

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<form:Form xmlns:form="http://g5.1c.ru/v8/dt/form">
<autoCommandBar>
<name>FormCommandBar</name>
<id>-1</id>
<visible>true</visible>
<enabled>true</enabled>
<userVisible>
<common>true</common>
</userVisible>
<horizontalAlign>Left</horizontalAlign>
<autoFill>true</autoFill>
</autoCommandBar>
<autoTitle>true</autoTitle>
<autoUrl>true</autoUrl>
<group>Vertical</group>
<autoFillCheck>true</autoFillCheck>
<allowFormCustomize>true</allowFormCustomize>
<enabled>true</enabled>
<showTitle>true</showTitle>
<showCloseButton>true</showCloseButton>
<formCommands>
<name>TestCommandUseByRoles</name>
<title>
<key>en</key>
<value>Test command use by roles</value>
</title>
<id>1</id>
<use>
<common>true</common>
<for>
<value>true</value>
<role>Role.TestRole1</role>
</for>
<for>
<role>Role.TestRole2</role>
</for>
</use>
<currentRowUse>Auto</currentRowUse>
</formCommands>
<commandInterface>
<navigationPanel/>
<commandBar/>
</commandInterface>
</form:Form>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<mdclass:CommonForm xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass" uuid="251a878c-0393-42c4-9ac8-5ac5ba982171">
<name>TestForm3</name>
<synonym>
<key>en</key>
<value>Test form3</value>
</synonym>
<usePurposes>PersonalComputer</usePurposes>
<usePurposes>MobileDevice</usePurposes>
</mdclass:CommonForm>

View File

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8"?>
<form:Form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:form="http://g5.1c.ru/v8/dt/form">
<items xsi:type="form:FormField">
<name>TestAttribute</name>
<id>1</id>
<visible>true</visible>
<enabled>true</enabled>
<userVisible>
<common>true</common>
<for>
<value>true</value>
<role>Role.TestRole1</role>
</for>
</userVisible>
<dataPath xsi:type="form:DataPath">
<segments>TestAttribute</segments>
</dataPath>
<extendedTooltip>
<name>TestAttributeExtendedTooltip</name>
<id>3</id>
<visible>true</visible>
<enabled>true</enabled>
<userVisible>
<common>true</common>
</userVisible>
<type>Label</type>
<autoMaxWidth>true</autoMaxWidth>
<autoMaxHeight>true</autoMaxHeight>
<extInfo xsi:type="form:LabelDecorationExtInfo">
<horizontalAlign>Left</horizontalAlign>
</extInfo>
</extendedTooltip>
<contextMenu>
<name>TestAttributeContextMenu</name>
<id>2</id>
<visible>true</visible>
<enabled>true</enabled>
<userVisible>
<common>true</common>
</userVisible>
<autoFill>true</autoFill>
</contextMenu>
<type>InputField</type>
<editMode>Enter</editMode>
<showInHeader>true</showInHeader>
<headerHorizontalAlign>Left</headerHorizontalAlign>
<showInFooter>true</showInFooter>
<extInfo xsi:type="form:InputFieldExtInfo">
<autoMaxWidth>true</autoMaxWidth>
<autoMaxHeight>true</autoMaxHeight>
<wrap>true</wrap>
<chooseType>true</chooseType>
<typeDomainEnabled>true</typeDomainEnabled>
<textEdit>true</textEdit>
</extInfo>
</items>
<autoCommandBar>
<name>FormCommandBar</name>
<id>-1</id>
<visible>true</visible>
<enabled>true</enabled>
<userVisible>
<common>true</common>
</userVisible>
<horizontalAlign>Left</horizontalAlign>
<autoFill>true</autoFill>
</autoCommandBar>
<autoTitle>true</autoTitle>
<autoUrl>true</autoUrl>
<group>Vertical</group>
<autoFillCheck>true</autoFillCheck>
<allowFormCustomize>true</allowFormCustomize>
<enabled>true</enabled>
<showTitle>true</showTitle>
<showCloseButton>true</showCloseButton>
<attributes>
<name>TestAttribute</name>
<title>
<key>en</key>
<value>Test attribute</value>
</title>
<id>1</id>
<valueType>
<types>String</types>
<stringQualifiers/>
</valueType>
<view>
<common>true</common>
</view>
<edit>
<common>true</common>
</edit>
</attributes>
<commandInterface>
<navigationPanel/>
<commandBar/>
</commandInterface>
</form:Form>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<mdclass:CommonForm xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass" uuid="7730a94f-eacf-4d47-bf4d-fb224ffb5734">
<name>TestForm4</name>
<synonym>
<key>en</key>
<value>Test form4</value>
</synonym>
<usePurposes>PersonalComputer</usePurposes>
<usePurposes>MobileDevice</usePurposes>
</mdclass:CommonForm>

View File

@ -0,0 +1,106 @@
<?xml version="1.0" encoding="UTF-8"?>
<form:Form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:form="http://g5.1c.ru/v8/dt/form">
<items xsi:type="form:FormField">
<name>TestAttribute</name>
<id>1</id>
<visible>true</visible>
<enabled>true</enabled>
<userVisible>
<common>true</common>
</userVisible>
<dataPath xsi:type="form:DataPath">
<segments>TestAttribute</segments>
</dataPath>
<extendedTooltip>
<name>TestAttributeExtendedTooltip</name>
<id>3</id>
<visible>true</visible>
<enabled>true</enabled>
<userVisible>
<common>true</common>
</userVisible>
<type>Label</type>
<autoMaxWidth>true</autoMaxWidth>
<autoMaxHeight>true</autoMaxHeight>
<extInfo xsi:type="form:LabelDecorationExtInfo">
<horizontalAlign>Left</horizontalAlign>
</extInfo>
</extendedTooltip>
<contextMenu>
<name>TestAttributeContextMenu</name>
<id>2</id>
<visible>true</visible>
<enabled>true</enabled>
<userVisible>
<common>true</common>
</userVisible>
<autoFill>true</autoFill>
</contextMenu>
<type>InputField</type>
<editMode>Enter</editMode>
<showInHeader>true</showInHeader>
<headerHorizontalAlign>Left</headerHorizontalAlign>
<showInFooter>true</showInFooter>
<extInfo xsi:type="form:InputFieldExtInfo">
<autoMaxWidth>true</autoMaxWidth>
<autoMaxHeight>true</autoMaxHeight>
<wrap>true</wrap>
<chooseType>true</chooseType>
<typeDomainEnabled>true</typeDomainEnabled>
<textEdit>true</textEdit>
</extInfo>
</items>
<autoCommandBar>
<name>FormCommandBar</name>
<id>-1</id>
<visible>true</visible>
<enabled>true</enabled>
<userVisible>
<common>true</common>
</userVisible>
<horizontalAlign>Left</horizontalAlign>
<autoFill>true</autoFill>
</autoCommandBar>
<autoTitle>true</autoTitle>
<autoUrl>true</autoUrl>
<group>Vertical</group>
<autoFillCheck>true</autoFillCheck>
<allowFormCustomize>true</allowFormCustomize>
<enabled>true</enabled>
<showTitle>true</showTitle>
<showCloseButton>true</showCloseButton>
<attributes>
<name>TestAttribute</name>
<title>
<key>en</key>
<value>Test attribute</value>
</title>
<id>1</id>
<valueType>
<types>String</types>
<stringQualifiers/>
</valueType>
<view>
<common>true</common>
</view>
<edit>
<common>true</common>
</edit>
</attributes>
<formCommands>
<name>TestCommand</name>
<title>
<key>en</key>
<value>Test command</value>
</title>
<id>1</id>
<use>
<common>true</common>
</use>
<currentRowUse>Auto</currentRowUse>
</formCommands>
<commandInterface>
<navigationPanel/>
<commandBar/>
</commandInterface>
</form:Form>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<mdclass:CommonForm xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass" uuid="813fe8ef-b5b1-4d65-b24b-8829dc74f337">
<name>TestForm5</name>
<synonym>
<key>en</key>
<value>Test form5</value>
</synonym>
<usePurposes>PersonalComputer</usePurposes>
<usePurposes>MobileDevice</usePurposes>
</mdclass:CommonForm>

View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<cmi:CommandInterface xmlns:cmi="http://g5.1c.ru/v8/dt/cmi"/>

View File

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<mdclass:Configuration xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass" uuid="26f4970b-c897-4aa2-866d-ad17153eafb2">
<name>FormItemVisibleSettingsByRoles</name>
<synonym>
<key>en</key>
<value>Form item visible settings by roles</value>
</synonym>
<containedObjects classId="9cd510cd-abfc-11d4-9434-004095e12fc7" objectId="196a845a-13dd-4713-99d0-217a5022aabc"/>
<containedObjects classId="9fcd25a0-4822-11d4-9414-008048da11f9" objectId="14efdbc2-c91a-4592-8894-eaece1e78015"/>
<containedObjects classId="e3687481-0a87-462c-a166-9f34594f9bba" objectId="d8f46aa6-ef9b-4824-af95-24cda3b203fc"/>
<containedObjects classId="9de14907-ec23-4a07-96f0-85521cb6b53b" objectId="a63d8cf6-8d73-48ab-a95d-c439ef46d0d9"/>
<containedObjects classId="51f2d5d8-ea4d-4064-8892-82951750031e" objectId="44fa1756-5d92-4466-b9a3-58482e2b466e"/>
<containedObjects classId="e68182ea-4237-4383-967f-90c1e3370bc7" objectId="97c6744f-e578-49e1-9616-6f8dd26045bc"/>
<containedObjects classId="fb282519-d103-4dd3-bc12-cb271d631dfc" objectId="1f4a3b62-d948-46d7-8a84-7c4e318ad383"/>
<configurationExtensionCompatibilityMode>8.3.19</configurationExtensionCompatibilityMode>
<defaultRunMode>ManagedApplication</defaultRunMode>
<usePurposes>PersonalComputer</usePurposes>
<usedMobileApplicationFunctionalities>
<functionality>
<use>true</use>
</functionality>
<functionality>
<functionality>OSBackup</functionality>
<use>true</use>
</functionality>
</usedMobileApplicationFunctionalities>
<defaultLanguage>Language.English</defaultLanguage>
<dataLockControlMode>Managed</dataLockControlMode>
<objectAutonumerationMode>NotAutoFree</objectAutonumerationMode>
<modalityUseMode>DontUse</modalityUseMode>
<synchronousPlatformExtensionAndAddInCallUseMode>DontUse</synchronousPlatformExtensionAndAddInCallUseMode>
<compatibilityMode>8.3.19</compatibilityMode>
<languages uuid="8b1f0920-6533-48d6-8daa-726a6c5cfbb9">
<name>English</name>
<synonym>
<key>en</key>
<value>English</value>
</synonym>
<languageCode>en</languageCode>
</languages>
<roles>Role.TestRole1</roles>
<roles>Role.TestRole2</roles>
<commonForms>CommonForm.TestForm1</commonForms>
<commonForms>CommonForm.TestForm2</commonForms>
<commonForms>CommonForm.TestForm3</commonForms>
<commonForms>CommonForm.TestForm4</commonForms>
<commonForms>CommonForm.TestForm5</commonForms>
</mdclass:Configuration>

View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<cmi:CommandInterface xmlns:cmi="http://g5.1c.ru/v8/dt/cmi"/>

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<Rights xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://v8.1c.ru/8.2/roles" xsi:type="Rights">
<setForNewObjects>false</setForNewObjects>
<setForAttributesByDefault>true</setForAttributesByDefault>
<independentRightsOfChildObjects>false</independentRightsOfChildObjects>
<object>
<name>Configuration.FormItemVisibleSettingsByRoles</name>
<right>
<name>SaveUserData</name>
<value>true</value>
</right>
<right>
<name>ThinClient</name>
<value>true</value>
</right>
<right>
<name>WebClient</name>
<value>true</value>
</right>
<right>
<name>MainWindowModeEmbeddedWorkplace</name>
<value>true</value>
</right>
<right>
<name>MainWindowModeKiosk</name>
<value>true</value>
</right>
<right>
<name>MainWindowModeNormal</name>
<value>true</value>
</right>
<right>
<name>MainWindowModeFullscreenWorkplace</name>
<value>true</value>
</right>
<right>
<name>MainWindowModeWorkplace</name>
<value>true</value>
</right>
<right>
<name>AnalyticsSystemClient</name>
<value>true</value>
</right>
</object>
</Rights>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<mdclass:Role xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass" uuid="60eac3fb-13fa-4915-ba23-dedf42d6ed46">
<name>TestRole1</name>
<synonym>
<key>en</key>
<value>Test role1</value>
</synonym>
</mdclass:Role>

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<Rights xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://v8.1c.ru/8.2/roles" xsi:type="Rights">
<setForNewObjects>false</setForNewObjects>
<setForAttributesByDefault>true</setForAttributesByDefault>
<independentRightsOfChildObjects>false</independentRightsOfChildObjects>
<object>
<name>Configuration.FormItemVisibleSettingsByRoles</name>
<right>
<name>SaveUserData</name>
<value>true</value>
</right>
<right>
<name>ThinClient</name>
<value>true</value>
</right>
<right>
<name>WebClient</name>
<value>true</value>
</right>
<right>
<name>MainWindowModeEmbeddedWorkplace</name>
<value>true</value>
</right>
<right>
<name>MainWindowModeKiosk</name>
<value>true</value>
</right>
<right>
<name>MainWindowModeNormal</name>
<value>true</value>
</right>
<right>
<name>MainWindowModeFullscreenWorkplace</name>
<value>true</value>
</right>
<right>
<name>MainWindowModeWorkplace</name>
<value>true</value>
</right>
<right>
<name>AnalyticsSystemClient</name>
<value>true</value>
</right>
</object>
</Rights>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<mdclass:Role xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass" uuid="c53e26d0-429f-4bd3-a323-20dbd44a8135">
<name>TestRole2</name>
<synonym>
<key>en</key>
<value>Test role2</value>
</synonym>
</mdclass:Role>

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (C) 2021, 1C-Soft LLC and others.
* Copyright (C) 2023, 1C-Soft LLC and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
@ -38,6 +38,7 @@ import com.e1c.v8codestyle.ql.check.TempTableHasIndex;
* Test {@link TempTableHasIndex} class that checks selection query that put to new temporary table and has indexes.
*
* @author Dmitriy Marmyshev
* @author Vadim Goncharov
*/
public class TempTableHasIndexTest
extends SingleProjectReadOnlyCheckTestBase
@ -49,11 +50,15 @@ public class TempTableHasIndexTest
private static final String PARAMETER_EXCLUDE_TABLE_NAME_PATTERN = "excludeObjectNamePattern";
private static final String PARAMETER_MAX_TOP = "maxTop";
private static final int MAX_TOP_DEFAULT = 1000;
private TestingCheckResultAcceptor resultAcceptor;
private TestingQlResultAcceptor qlResultAcceptor;
private TestingCheckParameters emptyParameters;
private TestingCheckParameters defaultParameters;
private TempTableHasIndex check;
@ -68,7 +73,8 @@ public class TempTableHasIndexTest
{
resultAcceptor = new TestingCheckResultAcceptor();
qlResultAcceptor = new TestingQlResultAcceptor();
emptyParameters = new TestingCheckParameters(Map.of(PARAMETER_EXCLUDE_TABLE_NAME_PATTERN, ""));
defaultParameters = new TestingCheckParameters(
Map.of(PARAMETER_EXCLUDE_TABLE_NAME_PATTERN, "", PARAMETER_MAX_TOP, MAX_TOP_DEFAULT));
QlBasicDelegateCheck.setResultAcceptor((o, f) -> qlResultAcceptor);
check = new TempTableHasIndex();
}
@ -90,13 +96,13 @@ public class TempTableHasIndexTest
EObject selectQuery = querySchema.getQueries().get(1);
assertTrue(selectQuery instanceof QuerySchemaSelectQuery);
check.check(selectQuery, resultAcceptor, emptyParameters, new NullProgressMonitor());
check.check(selectQuery, resultAcceptor, defaultParameters, new NullProgressMonitor());
assertTrue(qlResultAcceptor.getMarkers().isEmpty());
selectQuery = querySchema.getQueries().get(0);
assertTrue(selectQuery instanceof QuerySchemaSelectQuery);
check.check(selectQuery, resultAcceptor, emptyParameters, new NullProgressMonitor());
check.check(selectQuery, resultAcceptor, defaultParameters, new NullProgressMonitor());
assertFalse(qlResultAcceptor.getMarkers().isEmpty());
@ -119,16 +125,23 @@ public class TempTableHasIndexTest
EObject selectQuery = querySchema.getQueries().get(1);
assertTrue(selectQuery instanceof QuerySchemaSelectQuery);
check.check(selectQuery, resultAcceptor, emptyParameters, new NullProgressMonitor());
check.check(selectQuery, resultAcceptor, defaultParameters, new NullProgressMonitor());
assertTrue(qlResultAcceptor.getMarkers().isEmpty());
selectQuery = querySchema.getQueries().get(0);
assertTrue(selectQuery instanceof QuerySchemaSelectQuery);
check.check(selectQuery, resultAcceptor, emptyParameters, new NullProgressMonitor());
check.check(selectQuery, resultAcceptor, defaultParameters, new NullProgressMonitor());
assertFalse(qlResultAcceptor.getMarkers().isEmpty());
qlResultAcceptor.getMarkers().clear();
TestingCheckParameters newParameters =
new TestingCheckParameters(Map.of(PARAMETER_EXCLUDE_TABLE_NAME_PATTERN, "", PARAMETER_MAX_TOP, 110000));
check.check(selectQuery, resultAcceptor, newParameters, new NullProgressMonitor());
assertTrue(qlResultAcceptor.getMarkers().isEmpty());
}
@Test
@ -147,13 +160,13 @@ public class TempTableHasIndexTest
EObject selectQuery = querySchema.getQueries().get(1);
assertTrue(selectQuery instanceof QuerySchemaSelectQuery);
check.check(selectQuery, resultAcceptor, emptyParameters, new NullProgressMonitor());
check.check(selectQuery, resultAcceptor, defaultParameters, new NullProgressMonitor());
assertTrue(qlResultAcceptor.getMarkers().isEmpty());
selectQuery = querySchema.getQueries().get(0);
assertTrue(selectQuery instanceof QuerySchemaSelectQuery);
check.check(selectQuery, resultAcceptor, emptyParameters, new NullProgressMonitor());
check.check(selectQuery, resultAcceptor, defaultParameters, new NullProgressMonitor());
assertTrue(qlResultAcceptor.getMarkers().isEmpty());
}