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

#1119 Реализована проверка "Unknown-form-parameter-access" (#1263)

This commit is contained in:
Vadim Goncharov 2023-03-21 00:02:58 +03:00 committed by GitHub
parent bb151bf321
commit 8ef4226278
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 413 additions and 0 deletions

View File

@ -26,6 +26,7 @@
- Отсутствует комментарий к экспортной процедуре (функции)
- Документирующий комментарий не содержит секцию "Описание" для экспортной процедуры (функции)
- Проверка корректного наименования переменных
- Обращение к несуществующему параметру формы
#### Запросы

View File

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

View File

@ -0,0 +1,14 @@
# Unknown form parameter access
For parameterizable forms, all parameters must be provided in the form's parameter set.
By this, all the form's parametrization options are described in the parameter set in a declarative way.
Specify the parameters in the code that opens the form (OpenForm).
## Noncompliant Code Example
## Compliant Solution
## См.
- [Opening form](https://kb.1ci.com/1C_Enterprise_Platform/Guides/Developer_Guides/1C_Enterprise_Development_Standards/Designing_user_interfaces/Implementation_of_form/Opening_forms/?language=en)

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.UnknownFormParameterAccessCheck">
</check>
<check
category="com.e1c.v8codestyle.bsl"
class="com.e1c.v8codestyle.bsl.check.VariableNameInvalidCheck">

View File

@ -344,6 +344,12 @@ final class Messages
public static String RollbackTransactionCheck_Transactions_is_broken_des;
public static String UnknownFormParameterAccessCheck_description;
public static String UnknownFormParameterAccessCheck_title;
public static String UnknownFormParameterAccessCheck_Unknown_form_parameter_access;
public static String UseNonRecommendedMethods_description;
public static String UseNonRecommendedMethods_message;

View File

@ -0,0 +1,144 @@
/*******************************************************************************
* 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.DYNAMIC_FEATURE_ACCESS;
import static com._1c.g5.v8.dt.bsl.model.BslPackage.Literals.FEATURE_ACCESS__NAME;
import static com._1c.g5.v8.dt.mcore.McorePackage.Literals.CONTAINING_SOURCE_DERIVED_PROPERTY__CONTAINING_SOURCE;
import static com._1c.g5.v8.dt.mcore.McorePackage.Literals.DERIVED_PROPERTY__SOURCE;
import java.text.MessageFormat;
import java.util.Collection;
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.FeatureEntry;
import com._1c.g5.v8.dt.bsl.model.ModuleType;
import com._1c.g5.v8.dt.bsl.model.StaticFeatureAccess;
import com._1c.g5.v8.dt.bsl.resource.DynamicFeatureAccessComputer;
import com._1c.g5.v8.dt.mcore.ContainingSourceDerivedProperty;
import com._1c.g5.v8.dt.mcore.DerivedProperty;
import com._1c.g5.v8.dt.mcore.Environmental;
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;
/**
* Check the use unknown form parameter access in form module
* @author Vadim Goncharov
*/
public class UnknownFormParameterAccessCheck
extends BasicCheck
{
private static final String CHECK_ID = "unknown-form-parameter-access"; //$NON-NLS-1$
private static final String PARAMETERS_KEYWORD = "Parameters"; //$NON-NLS-1$
private static final String PARAMETERS_KEYWORD_RU = "Параметры"; //$NON-NLS-1$
private final DynamicFeatureAccessComputer dynamicComputer;
/**
* Instantiates a new unknown form parameter access check.
*
* @param dynamicComputer the dynamic computer, cannot be {@code null}
*/
@Inject
public UnknownFormParameterAccessCheck(DynamicFeatureAccessComputer dynamicComputer)
{
super();
this.dynamicComputer = dynamicComputer;
}
@Override
public String getCheckId()
{
return CHECK_ID;
}
@Override
protected void configureCheck(CheckConfigurer builder)
{
builder.title(Messages.UnknownFormParameterAccessCheck_title)
.description(Messages.UnknownFormParameterAccessCheck_description)
.complexity(CheckComplexity.NORMAL)
.severity(IssueSeverity.MINOR)
.issueType(IssueType.CODE_STYLE)
.extension(new StandardCheckExtension(741, getCheckId(), BslPlugin.PLUGIN_ID))
.extension(ModuleTypeFilter.onlyTypes(ModuleType.FORM_MODULE))
.module()
.checkedObjectType(DYNAMIC_FEATURE_ACCESS);
}
@Override
protected void check(Object object, ResultAcceptor resultAcceptor, ICheckParameters parameters,
IProgressMonitor monitor)
{
DynamicFeatureAccess dfa = (DynamicFeatureAccess)object;
String dfaName = dfa.getName();
Expression src = dfa.getSource();
if (!(src instanceof StaticFeatureAccess) || !isFormParameterAccess((StaticFeatureAccess)src)
|| monitor.isCanceled())
{
return;
}
Environmental envs = EcoreUtil2.getContainerOfType(dfa, Environmental.class);
if (!monitor.isCanceled() && isEmptySource(dynamicComputer.resolveObject(dfa, envs.environments())))
{
resultAcceptor.addIssue(
MessageFormat.format(Messages.UnknownFormParameterAccessCheck_Unknown_form_parameter_access, dfaName),
dfa, FEATURE_ACCESS__NAME);
}
}
private boolean isFormParameterAccess(StaticFeatureAccess sfa)
{
String name = sfa.getName();
return name.equalsIgnoreCase(PARAMETERS_KEYWORD) || name.equalsIgnoreCase(PARAMETERS_KEYWORD_RU);
}
// TODO replace this method with BslUtil after 2022.2+
private static boolean isEmptySource(Collection<FeatureEntry> features)
{
if (features.isEmpty())
{
return true;
}
return features.stream().allMatch(e -> {
if (e.getFeature() instanceof ContainingSourceDerivedProperty)
{
return e.getFeature().eGet(CONTAINING_SOURCE_DERIVED_PROPERTY__CONTAINING_SOURCE, false) == null;
}
else if (e.getFeature() instanceof DerivedProperty)
{
return e.getFeature().eGet(DERIVED_PROPERTY__SOURCE, false) == null;
}
return false;
});
}
}

View File

@ -450,6 +450,12 @@ StructureCtorTooManyKeysCheck_description = Check structure constructor has too
StructureCtorTooManyKeysCheck_title = Structure constructor has too many keys
UnknownFormParameterAccessCheck_Unknown_form_parameter_access = Unknown form parameter "{0}" access
UnknownFormParameterAccessCheck_description = Unknown form parameter access
UnknownFormParameterAccessCheck_title = Unknown form parameter access
UseNonRecommendedMethods_description = Using non-recommended methods
UseNonRecommendedMethods_message = Using non-recommended method

View File

@ -450,6 +450,12 @@ StructureCtorTooManyKeysCheck_description = Проверка конструкт
StructureCtorTooManyKeysCheck_title = Конструктор структуры содержит слишком много ключей
UnknownFormParameterAccessCheck_Unknown_form_parameter_access = Обращение к несуществующему параметру формы "{0}"
UnknownFormParameterAccessCheck_description = Обращение к несуществующему параметру формы
UnknownFormParameterAccessCheck_title = Обращение к несуществующему параметру формы
UseNonRecommendedMethods_description = Использование не рекомендованных методов
UseNonRecommendedMethods_message = Используется не рекомендуемый метод

View File

@ -0,0 +1,74 @@
/*******************************************************************************
* 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 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.UnknownFormParameterAccessCheck;
/**
* Test class for {@link UnknownFormParameterAccessCheck}.
* @author Vadim Goncharov
*/
public class UnknownFormParameterAccessCheckTest
extends AbstractSingleModuleTestBase
{
private static final String PROJECT_NAME = "UnknownFormParameterAccess";
private static final String COMMON_FORM_FILE_NAME = "/src/CommonForms/TestForm/Module.bsl";
public UnknownFormParameterAccessCheckTest()
{
super(UnknownFormParameterAccessCheck.class);
}
@Override
protected String getTestConfigurationName()
{
return PROJECT_NAME;
}
@Override
protected String getModuleFileName()
{
return COMMON_FORM_FILE_NAME;
}
/**
* Test the form module use unknown parameters access.
*
* @throws Exception the exception
*/
@Test
public void testFormModuleUnknownParametersAccess() throws Exception
{
List<Marker> markers = getModuleMarkers();
assertEquals(2, markers.size());
Marker marker = markers.get(0);
assertEquals("8", marker.getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_LINE_KEY));
marker = markers.get(1);
assertEquals("10", marker.getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_LINE_KEY));
}
}

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>UnknownFormParameterAccess</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 @@
eclipse.preferences.version=1
encoding/<project>=UTF-8

View File

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

View File

@ -0,0 +1,51 @@
<?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>
<handlers>
<event>OnCreateAtServer</event>
<name>OnCreateAtServer</name>
</handlers>
<autoTitle>true</autoTitle>
<autoUrl>true</autoUrl>
<group>Vertical</group>
<autoFillCheck>true</autoFillCheck>
<allowFormCustomize>true</allowFormCustomize>
<enabled>true</enabled>
<showTitle>true</showTitle>
<showCloseButton>true</showCloseButton>
<parameters>
<name>Parameter1</name>
<valueType>
<types>String</types>
<stringQualifiers/>
</valueType>
</parameters>
<parameters>
<name>Parameter2</name>
<valueType>
<types>String</types>
<stringQualifiers/>
</valueType>
</parameters>
<parameters>
<name>Parameter3</name>
<valueType>
<types>String</types>
<stringQualifiers/>
</valueType>
</parameters>
<commandInterface>
<navigationPanel/>
<commandBar/>
</commandInterface>
</form:Form>

View File

@ -0,0 +1,15 @@
&AtServer
Procedure OnCreateAtServer(Cancel, StandardProcessing)
P1 = Parameters.Parameter1;
P2 = Parameters.Parameter2;
P3 = Parameters.Parameter3;
P4 = Parameters.Parameter4;
If Parameters.Property("Parameter5") Then
P5 = Parameters.Parameter5;
EndIf;
//@skip-check unknown-form-parameter-access
P6 = Parameters.Parameter6;
EndProcedure

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="8dc7cfba-d593-432a-b0c3-7ac2b5d38bd9">
<name>TestForm</name>
<synonym>
<key>en</key>
<value>Test form</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,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<mdclass:Configuration xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass" uuid="6234ca5c-8e27-4656-945d-048f274720a1">
<name>UnknownFormParameterAccess</name>
<synonym>
<key>en</key>
<value>Unknown form parameter access</value>
</synonym>
<containedObjects classId="9cd510cd-abfc-11d4-9434-004095e12fc7" objectId="6b9561da-fe94-41a2-9388-44b1e2dfb672"/>
<containedObjects classId="9fcd25a0-4822-11d4-9414-008048da11f9" objectId="4748215e-a509-4cb7-ac81-d7a1ec6ca42d"/>
<containedObjects classId="e3687481-0a87-462c-a166-9f34594f9bba" objectId="c2e48825-e973-41eb-8f1d-5ec5f006a910"/>
<containedObjects classId="9de14907-ec23-4a07-96f0-85521cb6b53b" objectId="54d0cc7d-5970-41e0-b9f2-33a7e0360836"/>
<containedObjects classId="51f2d5d8-ea4d-4064-8892-82951750031e" objectId="64a8c69e-aa14-40b8-9097-5f1e9c54a0f6"/>
<containedObjects classId="e68182ea-4237-4383-967f-90c1e3370bc7" objectId="1f353d72-1841-437b-8b63-a08c470dd1ec"/>
<containedObjects classId="fb282519-d103-4dd3-bc12-cb271d631dfc" objectId="38d1b124-f2dc-44e6-b025-26bbe53c9bc1"/>
<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="84439c11-320a-4cf4-8042-61fe3b450cb1">
<name>English</name>
<synonym>
<key>en</key>
<value>English</value>
</synonym>
<languageCode>en</languageCode>
</languages>
<commonForms>CommonForm.TestForm</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"/>