1
0
mirror of https://github.com/1C-Company/v8-code-style.git synced 2024-12-01 10:41:05 +02:00

Стандарт 492: Использован обработчик событий, подключаемый из кода и не

содержащий префикса "Подключаемый_". #392
This commit is contained in:
Dmitriy Marmyshev 2022-10-10 19:48:54 +03:00
parent 87afe0ee2c
commit 1b056b185b
10 changed files with 313 additions and 0 deletions

View File

@ -19,6 +19,7 @@
- Добавление типизированного значения в не типизированную коллекцию - Добавление типизированного значения в не типизированную коллекцию
- Устаревшая процедура (функция) расположена вне области "УстаревшиеПроцедурыИФункции" - Устаревшая процедура (функция) расположена вне области "УстаревшиеПроцедурыИФункции"
- Использован обработчик событий, подключаемый из кода и не содержащий префикса "Подключаемый_"
#### Запросы #### Запросы

View File

@ -0,0 +1,31 @@
# Attachable event handler name
Programmatically added event handler name should match pattern: **Attachable_** prefix
## Noncompliant Code Example
```bsl
// Parameters:
// Item - FormField
Procedure Incorrect(Item)
Item.SetAction("OnChange", "IncorrectOnChange");
EndProcedure
```
## Compliant Solution
```bsl
// Parameters:
// Item - FormField
Procedure Correct(Item)
Item.SetAction("OnChange", "Attachable_CorrectOnChange");
EndProcedure
```
## See
- [Form module event handlers attached in code](https://kb.1ci.com/1C_Enterprise_Platform/Guides/Developer_Guides/1C_Enterprise_Development_Standards/Code_conventions/Using_1C_Enterprise_language_structures/Form_module_event_handlers_attached_in_code/)

View File

@ -0,0 +1,31 @@
# Имя подключаемого обработчка события
Имя программно добавленного обработчика события должно соответствать шаблону: префикс **Подключаемый_**
## Неправильно
```bsl
// Параметры:
// Элемент - FormField
Процедура Неправильно(Элемент)
Элемент.SetAction("ПриИзменении", "НеправильноПриИзменении");
КонецПроцедуры
```
## Правильно
```bsl
// Параметры:
// Элемент - FormField
Процедура Правильно(Элемент)
Элемент.SetAction("ПриИзменении", "Подключаемый_ПравильноПриИзменении");
КонецПроцедуры
```
## См.
- [Обработчики событий модуля формы, подключаемые из кода](https://its.1c.ru/db/v8std#content:492:hdoc)

View File

@ -299,6 +299,10 @@
category="com.e1c.v8codestyle.bsl" category="com.e1c.v8codestyle.bsl"
class="com.e1c.v8codestyle.bsl.check.BeginTransactionCheck"> class="com.e1c.v8codestyle.bsl.check.BeginTransactionCheck">
</check> </check>
<check
category="com.e1c.v8codestyle.bsl"
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.check.AttachableEventHandlerNameCheck">
</check>
<check <check
category="com.e1c.v8codestyle.bsl" category="com.e1c.v8codestyle.bsl"
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.check.ModuleStructureInitCodeInRegionCheck"> class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.check.ModuleStructureInitCodeInRegionCheck">

View File

@ -0,0 +1,151 @@
/*******************************************************************************
* 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.text.MessageFormat;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.xtext.EcoreUtil2;
import com._1c.g5.v8.dt.bsl.model.DynamicFeatureAccess;
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.Invocation;
import com._1c.g5.v8.dt.bsl.model.ModuleType;
import com._1c.g5.v8.dt.bsl.model.StringLiteral;
import com._1c.g5.v8.dt.bsl.resource.TypesComputer;
import com._1c.g5.v8.dt.common.StringUtils;
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.IEObjectTypeNames;
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.bsl.BslPlugin;
import com.google.inject.Inject;
/**
* The check finds invocation {@code object.SetAction("Event", "Attachable_HandlerName");} and validate that handler
* name matches pattern for attachable procedures.
* Form modules should be excluded because local methods must be found by direct reference.
*
* @author Dmitriy Marmyshev
*/
public class AttachableEventHandlerNameCheck
extends BasicCheck
{
private static final String CHECK_ID = "module-attachable-event-handler-name"; //$NON-NLS-1$
private static final String METHOD_NAME = "SetAction"; //$NON-NLS-1$
private static final String METHOD_NAME_RU = "УстановитьДействие"; //$NON-NLS-1$
private static final String DEFAULT_PARAM_ACTION_PATTERN = "^(?U)(Подключаемый|Attachable)_.*$"; //$NON-NLS-1$
private static final String PARAM_ACTION_PATTERN = "actionNamePattern"; //$NON-NLS-1$
//@formatter:off
private static final Set<String> SET_ACTION_TYPES = Set.of(
IEObjectTypeNames.CLIENT_APPLICATION_FORM,
IEObjectTypeNames.MANAGED_FORM,
IEObjectTypeNames.FORM_FIELD,
IEObjectTypeNames.FORM_GROUP,
IEObjectTypeNames.FORM_TABLE,
IEObjectTypeNames.FORM_DECORATION);
//@formatter:on
private final TypesComputer typesComputer;
/**
* Instantiates a new attachable event handler name check.
*
* @param typesComputer the types computer, cannot be {@code null}.
*/
@Inject
public AttachableEventHandlerNameCheck(TypesComputer typesComputer)
{
this.typesComputer = typesComputer;
}
@Override
public String getCheckId()
{
return CHECK_ID;
}
@Override
protected void configureCheck(CheckConfigurer builder)
{
builder.title(Messages.AttachableEventHandlerNameCheck_Title)
.description(Messages.AttachableEventHandlerNameCheck_Description)
.complexity(CheckComplexity.NORMAL)
.severity(IssueSeverity.MINOR)
.issueType(IssueType.CODE_STYLE)
.extension(new StandardCheckExtension(492, getCheckId(), BslPlugin.PLUGIN_ID))
.extension(ModuleTypeFilter.excludeTypes(ModuleType.FORM_MODULE))
.module()
.checkedObjectType(INVOCATION)
.parameter(PARAM_ACTION_PATTERN, String.class, DEFAULT_PARAM_ACTION_PATTERN,
Messages.AttachableEventHandlerNameCheck_Event_handler_name_pattern);
}
@Override
protected void check(Object object, ResultAcceptor resultAceptor, ICheckParameters parameters,
IProgressMonitor monitor)
{
Invocation inv = (Invocation)object;
FeatureAccess method = inv.getMethodAccess();
String methodName = method.getName();
String actionPattern = parameters.getString(PARAM_ACTION_PATTERN);
if (!(method instanceof DynamicFeatureAccess) || StringUtils.isEmpty(actionPattern)
|| inv.getParams().size() != 2 || !(inv.getParams().get(1) instanceof StringLiteral)
|| !(METHOD_NAME_RU.equalsIgnoreCase(methodName) || METHOD_NAME.equalsIgnoreCase(methodName)))
{
return;
}
Expression parameter = inv.getParams().get(1);
String content = getStringContent(parameter);
if (content != null && !content.matches(actionPattern)
&& isExpectedTypes(((DynamicFeatureAccess)method).getSource()))
{
String message = MessageFormat.format(Messages.AttachableEventHandlerNameCheck_Message, methodName);
resultAceptor.addIssue(message, parameter);
}
}
private boolean isExpectedTypes(Expression object)
{
Environmental env = EcoreUtil2.getContainerOfType(object, Environmental.class);
List<TypeItem> types = typesComputer.computeTypes(object, env.environments());
return types.stream().map(McoreUtil::getTypeName).filter(Objects::nonNull).anyMatch(SET_ACTION_TYPES::contains);
}
private String getStringContent(Expression parameter)
{
// TODO #1187 get string from content computer in future, for now hard-coded StringLiteral
StringLiteral literal = (StringLiteral)parameter;
return String.join(StringUtils.EMPTY, literal.lines(true));
}
}

View File

@ -38,6 +38,14 @@ final class Messages
public static String AccessibilityAtClientInObjectModuleCheck_Methods_should_be_AtClient; public static String AccessibilityAtClientInObjectModuleCheck_Methods_should_be_AtClient;
public static String AccessibilityAtClientInObjectModuleCheck_title; public static String AccessibilityAtClientInObjectModuleCheck_title;
public static String AttachableEventHandlerNameCheck_Description;
public static String AttachableEventHandlerNameCheck_Event_handler_name_pattern;
public static String AttachableEventHandlerNameCheck_Message;
public static String AttachableEventHandlerNameCheck_Title;
public static String CanonicalPragmaCheck_description; public static String CanonicalPragmaCheck_description;
public static String CanonicalPragmaCheck_Pragma_0_is_not_written_canonically_correct_spelling_is_1; public static String CanonicalPragmaCheck_Pragma_0_is_not_written_canonically_correct_spelling_is_1;
public static String CanonicalPragmaCheck_title; public static String CanonicalPragmaCheck_title;

View File

@ -28,6 +28,14 @@ AccessibilityAtClientInObjectModuleCheck_description = Method or variable access
AccessibilityAtClientInObjectModuleCheck_title = Method or variable accessible AtClient AccessibilityAtClientInObjectModuleCheck_title = Method or variable accessible AtClient
AttachableEventHandlerNameCheck_Description = Programmatically added event handler name should match pattern
AttachableEventHandlerNameCheck_Event_handler_name_pattern = Event handler name pattern
AttachableEventHandlerNameCheck_Message = Programmatically added event handler name "{0}" should match pattern
AttachableEventHandlerNameCheck_Title = Attachable event handler name
CanonicalPragmaCheck_Pragma_0_is_not_written_canonically_correct_spelling_is_1 = Annotation {0} is not written canonically, correct spelling is {1} CanonicalPragmaCheck_Pragma_0_is_not_written_canonically_correct_spelling_is_1 = Annotation {0} is not written canonically, correct spelling is {1}
CanonicalPragmaCheck_description = Check pragma is written canonically CanonicalPragmaCheck_description = Check pragma is written canonically

View File

@ -28,6 +28,14 @@ AccessibilityAtClientInObjectModuleCheck_description = Метод или пер
AccessibilityAtClientInObjectModuleCheck_title = Метод или переменная доступны НаКлиенте AccessibilityAtClientInObjectModuleCheck_title = Метод или переменная доступны НаКлиенте
AttachableEventHandlerNameCheck_Description = Имя программно добавленного обработчика события должно соответствать шаблону
AttachableEventHandlerNameCheck_Event_handler_name_pattern = Шаблон имени обработчика события
AttachableEventHandlerNameCheck_Message = Программно добавленное имя обработчика события "{0}" должно соответствать шаблону
AttachableEventHandlerNameCheck_Title = Имя подключаемого обработчка события
CanonicalPragmaCheck_Pragma_0_is_not_written_canonically_correct_spelling_is_1 = Аннотация {0} написана не канонически, правильное написание {1} CanonicalPragmaCheck_Pragma_0_is_not_written_canonically_correct_spelling_is_1 = Аннотация {0} написана не канонически, правильное написание {1}
CanonicalPragmaCheck_description = Проверяет что аннотация метода написана канонически CanonicalPragmaCheck_description = Проверяет что аннотация метода написана канонически

View File

@ -0,0 +1,17 @@
// Parameters:
// Item - FormField
Procedure Incorrect(Item)
Item.SetAction("OnChange", "CorrectOnChange");
EndProcedure
// Parameters:
// Item - FormField
Procedure Correct(Item)
Item.SetAction("OnChange", "Attachable_CorrectOnChange");
EndProcedure

View File

@ -0,0 +1,54 @@
/*******************************************************************************
* 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.IExtraInfoKeys;
import com._1c.g5.v8.dt.validation.marker.Marker;
import com.e1c.v8codestyle.bsl.check.AttachableEventHandlerNameCheck;
/**
* Tests for {@link AttachableEventHandlerNameCheck} check.
*
* @author Dmitriy Marmyshev
*/
public class AttachableEventHandlerNameCheckTest
extends AbstractSingleModuleTestBase
{
public AttachableEventHandlerNameCheckTest()
{
super(AttachableEventHandlerNameCheck.class);
}
/**
* Test attachable event handler name.
*
* @throws Exception the exception
*/
@Test
public void testAttachableEventHandlerName() throws Exception
{
updateModule(FOLDER_RESOURCE + "module-attachable-event-handler-name.bsl");
List<Marker> markers = getModuleMarkers();
assertEquals(1, markers.size());
Marker marker = markers.get(0);
assertEquals("6", marker.getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_LINE_KEY));
}
}