mirror of
https://github.com/1C-Company/v8-code-style.git
synced 2024-12-01 02:32:18 +02:00
Стандарт 492: Использован обработчик событий, подключаемый из кода и не
содержащий префикса "Подключаемый_". #392
This commit is contained in:
parent
87afe0ee2c
commit
1b056b185b
@ -19,6 +19,7 @@
|
||||
|
||||
- Добавление типизированного значения в не типизированную коллекцию
|
||||
- Устаревшая процедура (функция) расположена вне области "УстаревшиеПроцедурыИФункции"
|
||||
- Использован обработчик событий, подключаемый из кода и не содержащий префикса "Подключаемый_"
|
||||
|
||||
#### Запросы
|
||||
|
||||
|
@ -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/)
|
@ -0,0 +1,31 @@
|
||||
# Имя подключаемого обработчка события
|
||||
|
||||
Имя программно добавленного обработчика события должно соответствать шаблону: префикс **Подключаемый_**
|
||||
|
||||
## Неправильно
|
||||
|
||||
```bsl
|
||||
// Параметры:
|
||||
// Элемент - FormField
|
||||
Процедура Неправильно(Элемент)
|
||||
|
||||
Элемент.SetAction("ПриИзменении", "НеправильноПриИзменении");
|
||||
|
||||
КонецПроцедуры
|
||||
```
|
||||
|
||||
## Правильно
|
||||
|
||||
```bsl
|
||||
// Параметры:
|
||||
// Элемент - FormField
|
||||
Процедура Правильно(Элемент)
|
||||
|
||||
Элемент.SetAction("ПриИзменении", "Подключаемый_ПравильноПриИзменении");
|
||||
|
||||
КонецПроцедуры
|
||||
```
|
||||
|
||||
## См.
|
||||
|
||||
- [Обработчики событий модуля формы, подключаемые из кода](https://its.1c.ru/db/v8std#content:492:hdoc)
|
@ -299,6 +299,10 @@
|
||||
category="com.e1c.v8codestyle.bsl"
|
||||
class="com.e1c.v8codestyle.bsl.check.BeginTransactionCheck">
|
||||
</check>
|
||||
<check
|
||||
category="com.e1c.v8codestyle.bsl"
|
||||
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.check.AttachableEventHandlerNameCheck">
|
||||
</check>
|
||||
<check
|
||||
category="com.e1c.v8codestyle.bsl"
|
||||
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.check.ModuleStructureInitCodeInRegionCheck">
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
@ -38,6 +38,14 @@ final class Messages
|
||||
public static String AccessibilityAtClientInObjectModuleCheck_Methods_should_be_AtClient;
|
||||
|
||||
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_Pragma_0_is_not_written_canonically_correct_spelling_is_1;
|
||||
public static String CanonicalPragmaCheck_title;
|
||||
|
@ -28,6 +28,14 @@ AccessibilityAtClientInObjectModuleCheck_description = Method or variable access
|
||||
|
||||
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_description = Check pragma is written canonically
|
||||
|
@ -28,6 +28,14 @@ AccessibilityAtClientInObjectModuleCheck_description = Метод или пер
|
||||
|
||||
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_description = Проверяет что аннотация метода написана канонически
|
||||
|
@ -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
|
@ -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));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user