1
0
mirror of https://github.com/1C-Company/v8-code-style.git synced 2025-02-09 04:03:27 +02:00

Обновлена проверка областей верхнего уровня (#1103)

- Проверка состава областей верхнего уровня, соотвествие его стандарту #532 #533
- Проверка порядка областей верхнего уровня #488
- Проверка дублей стандартных областей #614
This commit is contained in:
Artem Iliukhin 2022-08-10 02:50:22 -06:00 committed by GitHub
parent 1d8670a98c
commit 3feac401f3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 1089 additions and 54 deletions

View File

@ -52,6 +52,7 @@
- Структура модуля. Добавлена проверка области событий.
- Отсутствует включение безопасного режима перед вызовом метода "Выполнить" или "Вычислить"
- Структура модуля. Добавлена проверка метода вне области.
- Структура модуля. Добавлена проверка соответсвия состава областей верхнего модуля стандарту, их порядка и наличия дублей.
- Структура модуля. Проверка что код инициализации расположен в области инициализации.
- Структура модуля. Область объявления переменных.

View File

@ -1,23 +1,40 @@
# Module stucture top region
# Module stucture top regions
Check that module structure region is on top
A program module (common module, object module, object manager module, form module, command module, and so on)
can have the following sections ordered as listed below:
- module header
- variable description section
- export procedures and functions of the module, which comprise its program interface
- event handlers of an object (form)
- internal procedures and functions of the module
- initialization section
Some sections only appear in modules of specific types. For example, event handlers of form items can only exist in
form modules, while the variable description and initialization sections cannot be defined in nonglobal common modules,
object manager modules, record set modules, constant value modules, or the session module.
Dividing the module code into sections makes the code easier to read and modify for different authors (developers),
both during group development and during application customization within specific deployment projects.
## Noncompliant Code Example
```bsl
#Region NotEmpty
#Region Public
// Enter code here.
#EndRegion
Procedure Test() Export
EndProcedure
#Region Internal
// Enter code here.
#Region Private
// Enter code here.
#EndRegion
#EndRegion
```bsl
## Compliant Solution
@ -25,11 +42,15 @@ EndProcedure
```bsl
#Region Public
// Enter code here.
#EndRegion
Procedure Test1() Export
EndProcedure
#Region Internal
// Enter code here.
#EndRegion
#Region Private
// Enter code here.
#EndRegion
```bsl

View File

@ -1,19 +1,36 @@
# Стандартная область структуры модуля верхнеуровневая
# Стандартные области структуры модуля верхнего уровня
Проверяет что стандартная область структуры модуля не является вложенной
В программном модуле (общие модули, модули объектов, модули менеджеров объектов, модули форм, команд и т.п.)
в общем случае могут присутствовать следующие разделы в приведенной ниже последовательности:
- заголовок модуля
- раздел описания переменных
- экспортные процедуры и функции модуля, составляющие его программный интерфейс
- обработчики событий объекта (формы)
- служебные процедуры и функции модуля
- раздел инициализации
Некоторые разделы могут присутствовать только в модулях определенного вида. Например, обработчики событий элементов форм
могут присутствовать только в модулях форм, а раздел описания переменных и раздел инициализации не могут быть определены
в неглобальных общих модулях, модулях менеджеров объектов, наборов записей, значений констант и модуле сеанса.
Требование о разделении кода модуля на разделы призвано повысить читаемость кода и упростить внесение изменений
в код разными авторами (разработчиками) как при коллективной разработке, так и при доработке прикладных решений
на конкретных внедрениях.
## Неправильно
```bsl
#Область НеПустая
#Область ПрограммныйИнтерфейс
// Код процедур и функций
#КонецОбласти
Процедура Тест() Экспорт
КонецПроцедуры
#Область СлужебныйПрограммныйИнтерфейс
// Код процедур и функций
#Область СлужебныеПроцедурыИФункции
// Код процедур и функций
#КонецОбласти
#КонецОбласти
@ -25,11 +42,15 @@
```bsl
#Область ПрограммныйИнтерфейс
// Код процедур и функций
#КонецОбласти
Процедура Тест() Экспорт
КонецПроцедуры
#Область СлужебныйПрограммныйИнтерфейс
// Код процедур и функций
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
// Код процедур и функций
#КонецОбласти
```

View File

@ -13,10 +13,10 @@
package com.e1c.v8codestyle.bsl;
import java.util.Collection;
import java.util.SortedSet;
import java.util.Set;
import com._1c.g5.v8.dt.bsl.model.ModuleType;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.ImmutableSet;
/**
* Default module structure list of sections by the module type.
@ -31,8 +31,8 @@ public enum ModuleStructure
COMMON_MODULE(ModuleStructureSection.PUBLIC, ModuleStructureSection.INTERNAL, ModuleStructureSection.PRIVATE),
EXTERNAL_CONN_MODULE(ModuleStructureSection.EVENT_HANDLERS, ModuleStructureSection.PRIVATE),
FORM_MODULE(ModuleStructureSection.VARIABLES, ModuleStructureSection.FORM_EVENT_HANDLERS,
ModuleStructureSection.FORM_COMMAND_EVENT_HANDLERS, ModuleStructureSection.FORM_HEADER_ITEMS_EVENT_HANDLERS,
ModuleStructureSection.FORM_TABLE_ITEMS_EVENT_HANDLERS, ModuleStructureSection.PRIVATE),
ModuleStructureSection.FORM_HEADER_ITEMS_EVENT_HANDLERS, ModuleStructureSection.FORM_TABLE_ITEMS_EVENT_HANDLERS,
ModuleStructureSection.FORM_COMMAND_EVENT_HANDLERS, ModuleStructureSection.PRIVATE),
HTTP_SERVICE_MODULE(ModuleStructureSection.EVENT_HANDLERS, ModuleStructureSection.PRIVATE),
INTEGRATION_SERVICE_MODULE(ModuleStructureSection.EVENT_HANDLERS, ModuleStructureSection.PRIVATE),
MANAGED_APP_MODULE(ModuleStructureSection.VARIABLES, ModuleStructureSection.EVENT_HANDLERS,
@ -97,14 +97,14 @@ public enum ModuleStructure
default:
break;
}
return ImmutableSortedSet.of();
return Set.of();
}
private final SortedSet<ModuleStructureSection> sections;
private final ImmutableSet<ModuleStructureSection> sections;
ModuleStructure(ModuleStructureSection... sections)
{
this.sections = ImmutableSortedSet.copyOf(sections);
this.sections = ImmutableSet.copyOf(sections);
}
/**

View File

@ -132,10 +132,22 @@ final class Messages
public static String ManagerModuleNamedSelfReferenceCheck_title;
public static String ModuleStructureTopRegionCheck_Check_duplicates_of_standard_regions;
public static String ModuleStructureTopRegionCheck_Check_order_of_standard_regions;
public static String ModuleStructureTopRegionCheck_description;
public static String ModuleStructureTopRegionCheck_error_message;
public static String ModuleStructureTopRegionCheck_Exclude_region_name;
public static String ModuleStructureTopRegionCheck_Region_has_duplicate;
public static String ModuleStructureTopRegionCheck_Region_has_the_wrong_order;
public static String ModuleStructureTopRegionCheck_Region_is_not_standard_for_current_type_of_module;
public static String ModuleStructureTopRegionCheck_title;
public static String ModuleUnusedMethodCheck_Title;

View File

@ -12,32 +12,42 @@
*******************************************************************************/
package com.e1c.v8codestyle.bsl.check;
import static com._1c.g5.v8.dt.bsl.model.BslPackage.Literals.REGION_PREPROCESSOR;
import static com._1c.g5.v8.dt.bsl.model.BslPackage.Literals.MODULE;
import static com._1c.g5.v8.dt.mcore.McorePackage.Literals.NAMED_ELEMENT__NAME;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Optional;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.eclipse.core.runtime.IProgressMonitor;
import com._1c.g5.v8.dt.bsl.model.ModuleType;
import com._1c.g5.v8.dt.bsl.model.Module;
import com._1c.g5.v8.dt.bsl.model.RegionPreprocessor;
import com._1c.g5.v8.dt.core.platform.IV8Project;
import com._1c.g5.v8.dt.bsl.model.util.BslUtil;
import com._1c.g5.v8.dt.common.StringUtils;
import com._1c.g5.v8.dt.core.platform.IV8ProjectManager;
import com._1c.g5.v8.dt.metadata.mdclass.ScriptVariant;
import com.e1c.g5.v8.dt.check.CheckComplexity;
import com.e1c.g5.v8.dt.check.ICheckParameters;
import com.e1c.g5.v8.dt.check.components.ModuleTopObjectNameFilterExtension;
import com.e1c.g5.v8.dt.check.settings.IssueSeverity;
import com.e1c.g5.v8.dt.check.settings.IssueType;
import com.e1c.v8codestyle.bsl.IModuleStructureProvider;
import com.e1c.v8codestyle.bsl.ModuleStructureSection;
import com.e1c.v8codestyle.check.StandardCheckExtension;
import com.e1c.v8codestyle.internal.bsl.BslPlugin;
import com.google.inject.Inject;
/**
* Checks that region named as module structure name is on top level of module.
* Checks order of standard regions.
* Checks duplicate of standard regions.
*
* @author Dmitriy Marmyshev
* @author Artem Iliukhin
*
*/
public class ModuleStructureTopRegionCheck
@ -45,6 +55,12 @@ public class ModuleStructureTopRegionCheck
{
private static final String CHECK_ID = "module-structure-top-region"; //$NON-NLS-1$
private static final String CHECK_DUPLICATES_OF_STANDARD_REGIONS = "checkDuplicates"; //$NON-NLS-1$
private static final String CHECK_ORDER_OF_STANDARD_REGIONS = "checkOrder"; //$NON-NLS-1$
private static final String PARAMETER_EXCLUDE_REGION_LIST = "excludeRegionName"; //$NON-NLS-1$
private final IModuleStructureProvider moduleStructureProvider;
private final IV8ProjectManager v8ProjectManager;
@ -70,39 +86,214 @@ public class ModuleStructureTopRegionCheck
builder.title(Messages.ModuleStructureTopRegionCheck_title)
.description(Messages.ModuleStructureTopRegionCheck_description)
.complexity(CheckComplexity.NORMAL)
.severity(IssueSeverity.MAJOR)
.severity(IssueSeverity.MINOR)
.issueType(IssueType.CODE_STYLE)
.extension(new ModuleTopObjectNameFilterExtension())
.extension(new StandardCheckExtension(getCheckId(), BslPlugin.PLUGIN_ID))
.module()
.checkedObjectType(REGION_PREPROCESSOR);
.checkedObjectType(MODULE)
.parameter(CHECK_DUPLICATES_OF_STANDARD_REGIONS, Boolean.class, Boolean.TRUE.toString(),
Messages.ModuleStructureTopRegionCheck_Check_duplicates_of_standard_regions)
.parameter(CHECK_ORDER_OF_STANDARD_REGIONS, Boolean.class, Boolean.TRUE.toString(),
Messages.ModuleStructureTopRegionCheck_Check_order_of_standard_regions)
.parameter(PARAMETER_EXCLUDE_REGION_LIST, String.class, StringUtils.EMPTY,
Messages.ModuleStructureTopRegionCheck_Exclude_region_name);
}
@Override
protected void check(Object object, ResultAcceptor resultAceptor, ICheckParameters parameters,
IProgressMonitor monitor)
{
RegionPreprocessor region = (RegionPreprocessor)object;
if (region.getName() == null)
if (monitor.isCanceled())
{
return;
}
IV8Project project = v8ProjectManager.getProject(region);
Module module = (Module)object;
ModuleType moduleType = getModuleType(region);
List<RegionPreprocessor> allRegions = BslUtil.getAllRegionPreprocessors(module);
if (allRegions.isEmpty())
{
return;
}
ScriptVariant scriptVariant = v8ProjectManager.getProject(module).getScriptVariant();
Collection<String> names =
moduleStructureProvider.getModuleStructureRegions(moduleType, project.getScriptVariant());
if (!names.contains(region.getName()))
{
return;
}
moduleStructureProvider.getModuleStructureRegions(module.getModuleType(), scriptVariant);
Optional<RegionPreprocessor> parent = getFirstParentRegion(region);
if (parent.isPresent())
check(resultAceptor, allRegions, names, parameters, scriptVariant, monitor);
}
private void check(ResultAcceptor resultAceptor, List<RegionPreprocessor> allRegions, Collection<String> baseNames,
ICheckParameters parameters, ScriptVariant scriptVariant, IProgressMonitor monitor)
{
Map<String, List<RegionPreprocessor>> countRegions = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
List<String> topRegions = new ArrayList<>();
countDoublesAndFindTopRegions(allRegions, topRegions, countRegions);
LinkedList<String> baseOrdered = new LinkedList<>(baseNames);
String tableName = ModuleStructureSection.FORM_TABLE_ITEMS_EVENT_HANDLERS.getName(scriptVariant);
String commandName = ModuleStructureSection.FORM_COMMAND_EVENT_HANDLERS.getName(scriptVariant);
String[] regionNames = parameters.getString(PARAMETER_EXCLUDE_REGION_LIST).split(","); //$NON-NLS-1$
boolean checkDuplicates = parameters.getBoolean(CHECK_DUPLICATES_OF_STANDARD_REGIONS);
boolean checkOrder = parameters.getBoolean(CHECK_ORDER_OF_STANDARD_REGIONS);
for (RegionPreprocessor region : allRegions)
{
resultAceptor.addIssue(Messages.ModuleStructureTopRegionCheck_error_message, NAMED_ELEMENT__NAME);
if (monitor.isCanceled())
{
return;
}
String regionName = region.getName();
if (isExcludeName(regionName, regionNames))
{
continue;
}
boolean isStandard = baseNames.stream().anyMatch(regionName::equalsIgnoreCase)
|| startsWithIgnoreCase(regionName, tableName);
boolean isTop = topRegions.stream().anyMatch(regionName::equalsIgnoreCase);
boolean isDuplicate = countRegions.get(regionName).size() > 1;
if (checkDuplicates && isStandard && isDuplicate)
{
addIssueDuplicates(resultAceptor, region);
}
if (!isTop && isStandard)
{
addIssueTop(resultAceptor, region);
}
if (isTop && baseNames.stream().noneMatch(regionName::equalsIgnoreCase)
&& !startsWithIgnoreCase(regionName, tableName))
{
addIssueStandard(resultAceptor, region);
}
if (isTop && isStandard && checkOrder && !isDuplicate)
{
addIssueOrder(resultAceptor, topRegions, baseOrdered, regionName, region, tableName, commandName);
}
}
}
private static boolean startsWithIgnoreCase(String str, String prefix)
{
if (str == null || prefix == null)
{
return str == null && prefix == null;
}
if (prefix.length() > str.length())
{
return false;
}
boolean ignoreCase = true;
return str.regionMatches(ignoreCase, 0, prefix, 0, prefix.length());
}
private void check(ResultAcceptor resultAceptor, RegionPreprocessor region, List<String> topRegions,
LinkedList<String> baseOrdered, String tableName, String commandName)
{
while (baseOrdered.peek() != null && !startsWithIgnoreCase(baseOrdered.peek(), tableName)
&& !commandName.equalsIgnoreCase(baseOrdered.peek()))
{
baseOrdered.poll();
}
if (baseOrdered.peek() != null && startsWithIgnoreCase(baseOrdered.peek(), tableName))
{
baseOrdered.poll();
}
else if (baseOrdered.isEmpty() && topRegions.size() > 1
|| baseOrdered.peek() != null && !commandName.equalsIgnoreCase(baseOrdered.peek()))
{
resultAceptor.addIssue(Messages.ModuleStructureTopRegionCheck_Region_has_the_wrong_order, region,
NAMED_ELEMENT__NAME);
}
}
private void check(ResultAcceptor resultAceptor, RegionPreprocessor region, LinkedList<String> baseOrdered,
String regionName)
{
while (baseOrdered.peek() != null && !regionName.equalsIgnoreCase(baseOrdered.peek()))
{
baseOrdered.poll();
}
if (baseOrdered.peek() != null && regionName.equalsIgnoreCase(baseOrdered.peek()))
{
baseOrdered.poll();
}
else if (baseOrdered.isEmpty())
{
resultAceptor.addIssue(Messages.ModuleStructureTopRegionCheck_Region_has_the_wrong_order, region,
NAMED_ELEMENT__NAME);
}
}
private void addIssueOrder(ResultAcceptor resultAceptor, List<String> topRegions, LinkedList<String> baseOrdered,
String regionName, RegionPreprocessor regionPreprocessor, String tableName, String commandName)
{
if (startsWithIgnoreCase(regionName, tableName))
{
check(resultAceptor, regionPreprocessor, topRegions, baseOrdered, tableName, commandName);
}
else
{
check(resultAceptor, regionPreprocessor, baseOrdered, regionName);
}
}
private void addIssueStandard(ResultAcceptor resultAceptor, RegionPreprocessor region)
{
resultAceptor.addIssue(Messages.ModuleStructureTopRegionCheck_Region_is_not_standard_for_current_type_of_module,
region, NAMED_ELEMENT__NAME);
}
private void addIssueTop(ResultAcceptor resultAceptor, RegionPreprocessor region)
{
resultAceptor.addIssue(Messages.ModuleStructureTopRegionCheck_error_message, region, NAMED_ELEMENT__NAME);
}
private void addIssueDuplicates(ResultAcceptor resultAceptor, RegionPreprocessor region)
{
resultAceptor.addIssue(Messages.ModuleStructureTopRegionCheck_Region_has_duplicate, region,
NAMED_ELEMENT__NAME);
}
private void countDoublesAndFindTopRegions(List<RegionPreprocessor> allRegions, List<String> topRegions,
Map<String, List<RegionPreprocessor>> countRegions)
{
for (RegionPreprocessor region : allRegions)
{
String regionName = region.getName();
countRegions.putIfAbsent(regionName, new ArrayList<>());
countRegions.get(regionName).add(region);
if (getFirstParentRegion(region).isEmpty())
{
topRegions.add(regionName);
}
}
}
private boolean isExcludeName(String regionName, String[] regionNames)
{
for (String name : regionNames)
{
if (regionName.equalsIgnoreCase(name))
{
return true;
}
}
return false;
}
}

View File

@ -197,10 +197,22 @@ ModuleEmptyMethodCheck_Exclude_method_name_pattern_title = Exclude method name p
ModuleEmptyMethodCheck_Title = Empty method check
ModuleStructureTopRegionCheck_description = Check that module structure region is on top
ModuleStructureTopRegionCheck_Check_duplicates_of_standard_regions=Check duplicates of standard regions
ModuleStructureTopRegionCheck_Check_order_of_standard_regions=Check order of standard regions
ModuleStructureTopRegionCheck_description = Check that the regions on top of the module structure matches with the standard
ModuleStructureTopRegionCheck_error_message = Module structure region is not on top
ModuleStructureTopRegionCheck_Exclude_region_name=Comma-separated list of excluded region names
ModuleStructureTopRegionCheck_Region_has_duplicate=Region has duplicate
ModuleStructureTopRegionCheck_Region_has_the_wrong_order=Region has the wrong order
ModuleStructureTopRegionCheck_Region_is_not_standard_for_current_type_of_module=Region is not standard for current type of module
ModuleStructureTopRegionCheck_title = Module structure top region
ModuleUnusedLocalVariableCheck_Description = Unused module local variable check

View File

@ -206,12 +206,24 @@ ModuleEmptyMethodCheck_Exclude_method_name_pattern_title = Шаблон искл
ModuleEmptyMethodCheck_Title = Проверка пустых методов
ModuleStructureTopRegionCheck_description = Проверяет что стандартная область структуры модуля не является вложенной
ModuleStructureTopRegionCheck_description = Проверить, что области верхнего уровня структуры модуля соответствуют стандарту
ModuleStructureTopRegionCheck_error_message = Стандартная область структуры модуля является вложенной
ModuleStructureTopRegionCheck_title = Стандартная область структуры модуля верхнеуровневая
ModuleStructureTopRegionCheck_Check_duplicates_of_standard_regions=Дубли стандартных областей
ModuleStructureTopRegionCheck_Check_order_of_standard_regions=Порядок стандартных областей
ModuleStructureTopRegionCheck_Exclude_region_name=Comma-separated list of excluded region names
ModuleStructureTopRegionCheck_Region_has_duplicate=Дублирование стандартной области
ModuleStructureTopRegionCheck_Region_has_the_wrong_order=Неправильный порядок стандартной области
ModuleStructureTopRegionCheck_Region_is_not_standard_for_current_type_of_module=Region is not standard for current type of module
ModuleStructureEventFormRegionsCheck_Multilevel_nesting_of_regions = Разрешить многоуровневое вложение областей
ModuleStructureMethodInRegionCheck_Multilevel_nesting_of_regions = Разрешить многоуровневое вложение областей

View File

@ -38,7 +38,7 @@ import com._1c.g5.v8.dt.bsl.model.ModuleType;
import com._1c.g5.v8.dt.metadata.mdclass.ScriptVariant;
import com.e1c.v8codestyle.bsl.IModuleStructureProvider;
import com.e1c.v8codestyle.bsl.ModuleStructure;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.ImmutableSet;
/**
* The default implementation of module structure provider.
@ -132,7 +132,7 @@ public class ModuleStructureProvider
@Override
public Collection<String> getModuleStructureRegions(ModuleType moduleType, ScriptVariant scriptVariant)
{
return ImmutableSortedSet.copyOf(ModuleStructure.getStructureByType(moduleType)
return ImmutableSet.copyOf(ModuleStructure.getStructureByType(moduleType)
.stream()
.map(s -> s.getName(scriptVariant))
.collect(Collectors.toList()));

View File

@ -0,0 +1,28 @@
#If Server Or ThickClientOrdinaryApplication Or ExternalConnection Then
#Region public
Procedure PublicMethod() Export
PrivateMethod();
EndProcedure
#Region Public
Procedure InternalMethod() Export
PrivateMethod();
EndProcedure
#EndRegion
#EndRegion
#Region Private
Procedure PrivateMethod()
// add code
EndProcedure
#EndRegion
#EndIf

View File

@ -0,0 +1,28 @@
#If Server Or ThickClientOrdinaryApplication Or ExternalConnection Then
#Region Public
Procedure PublicMethod() Export
PrivateMethod();
EndProcedure
#Region Internal
Procedure InternalMethod() Export
PrivateMethod();
EndProcedure
#EndRegion
#EndRegion
#Region Private
Procedure PrivateMethod()
// add code
EndProcedure
#EndRegion
#EndIf

View File

@ -0,0 +1,28 @@
#If Server Or ThickClientOrdinaryApplication Or ExternalConnection Then
#Region private
Procedure PrivateMethod()
// add code
EndProcedure
#EndRegion
#Region public
Procedure PublicMethod() Export
PrivateMethod();
EndProcedure
#EndRegion
#Region internal
Procedure InternalMethod() Export
PrivateMethod();
EndProcedure
#EndRegion
#EndIf

View File

@ -11,7 +11,7 @@ EndProcedure
#Region NotEmpty
#Region Public
#Region Public1
Procedure Test()

View File

@ -0,0 +1,28 @@
#
If Server Or ThickClientOrdinaryApplication Or ExternalConnection Then
#Region Public
Procedure PublicMethod() Export
PrivateMethod();
EndProcedure
#EndRegion
#Region Internal
Procedure InternalMethod() Export
PrivateMethod();
EndProcedure
#EndRegion
#Region Private
Procedure PrivateMethod()
// add code
EndProcedure
#EndRegion
#EndIf

View File

@ -0,0 +1,28 @@
#If Server Or ThickClientOrdinaryApplication Or ExternalConnection Then
#Region NonPublic
Procedure PublicMethod() Export
PrivateMethod();
EndProcedure
#EndRegion
#Region Internal
Procedure InternalMethod() Export
PrivateMethod();
EndProcedure
#EndRegion
#Region Private
Procedure PrivateMethod()
// add code
EndProcedure
#EndRegion
#EndIf

View File

@ -13,6 +13,7 @@
package com.e1c.v8codestyle.bsl.check.itests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.util.List;
@ -32,11 +33,23 @@ public class ModuleStructureTopRegionCheckTest
extends AbstractSingleModuleTestBase
{
private static final String REGION_HAS_THE_WRONG_ORDER = "Region has the wrong order";
private static final String REGION_HAS_DUPLICATE = "Region has duplicate";
private static final String CATALOG_FORM_MODULE_FILE_NAME = "/src/Catalogs/Catalog/Forms/ItemForm/Module.bsl";
private static final String CHECK_ID = "module-structure-top-region"; //$NON-NLS-1$
public ModuleStructureTopRegionCheckTest()
{
super(ModuleStructureTopRegionCheck.class);
}
@Override
protected String getTestConfigurationName()
{
return "ModuleStructureTopRegionCheck";
}
/**
* Test that the region is on top of the module structure.
*
@ -63,8 +76,7 @@ public class ModuleStructureTopRegionCheckTest
List<Marker> markers = getModuleMarkers();
assertEquals(1, markers.size());
Marker marker = markers.get(0);
assertEquals("14", marker.getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_LINE_KEY));
assertEquals("12", markers.get(0).getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_LINE_KEY));
}
/**
@ -78,8 +90,98 @@ public class ModuleStructureTopRegionCheckTest
updateModule(FOLDER_RESOURCE + "module-structure-sub-region-after-method.bsl");
List<Marker> markers = getModuleMarkers();
// FIXME has to be an error in line 18
assertTrue(markers.isEmpty());
assertEquals(1, markers.size());
Marker marker = markers.get(0);
assertEquals("18", marker.getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_LINE_KEY));
}
/**
* Test that top module structure regions is compliant.
*
* @throws Exception the exception
*/
@Test
public void testTopRegionCompliant() throws Exception
{
updateModule(FOLDER_RESOURCE + "module-structure-top-region-compliant.bsl");
List<Marker> markers = getModuleMarkers();
assertTrue(markers.isEmpty());
}
/**
* Test that top module structure regions is non compliant.
*
* @throws Exception the exception
*/
@Test
public void testTopRegionNonCompliant() throws Exception
{
updateModule(FOLDER_RESOURCE + "module-structure-top-region-noncompliant.bsl");
List<Marker> markers = getModuleMarkers();
assertEquals(1, markers.size());
Marker marker = markers.get(0);
assertEquals("4", marker.getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_LINE_KEY));
}
/**
* Test that top module structure region is on top.
*
* @throws Exception the exception
*/
@Test
public void testTopRegionNotOnTop() throws Exception
{
updateModule(FOLDER_RESOURCE + "module-structure-region-is-not-on-top.bsl");
List<Marker> markers = getModuleMarkers();
assertEquals(1, markers.size());
Marker marker = markers.get(0);
assertEquals("10", marker.getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_LINE_KEY));
}
/**
* Test that top module structure region is duplicated.
*
* @throws Exception the exception
*/
@Test
public void testTopRegionIsDuplicated() throws Exception
{
updateModule(FOLDER_RESOURCE + "module-structure-region-is-duplicated.bsl");
List<Marker> markers = getModuleMarkers();
assertEquals(2, markers.size());
assertEquals(REGION_HAS_DUPLICATE, markers.get(0).getMessage());
assertEquals(REGION_HAS_DUPLICATE, markers.get(1).getMessage());
}
/**
* Test that top module structure region is wrong order.
*
* @throws Exception the exception
*/
@Test
public void testTopRegionIsWrongOrder() throws Exception
{
updateModule(FOLDER_RESOURCE + "module-structure-region-is-wrong-order.bsl");
List<Marker> markers = getModuleMarkers();
assertEquals(2, markers.size());
assertEquals(REGION_HAS_THE_WRONG_ORDER, markers.get(0).getMessage());
assertEquals(REGION_HAS_THE_WRONG_ORDER, markers.get(1).getMessage());
}
/**
* Test that top module structure regions in form module is compliant.
*
* @throws Exception the exception
*/
@Test
public void testTopRegionFormModuleCompliant() throws Exception
{
Marker marker = getFirstMarker(CHECK_ID, CATALOG_FORM_MODULE_FILE_NAME, getProject());
assertNull(marker);
}
}

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>ModuleStructureTopRegionCheck</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,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<mdclass:Catalog xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass" uuid="fee64820-607f-4568-bfd4-698eb33cd5be">
<producedTypes>
<objectType typeId="f8e6a0cd-208e-4b82-af26-bc71f79baa89" valueTypeId="f28c21a7-0c31-4d13-b7fa-979d5f655a72"/>
<refType typeId="b8d2fb67-dba9-4a55-95c8-600386034fe3" valueTypeId="3a8f2aba-7986-414e-b86b-86a731887717"/>
<selectionType typeId="afb2783d-953b-41c6-9082-b2818873de44" valueTypeId="19b25ab5-0077-4150-9929-4228f7929c7d"/>
<listType typeId="3e856fef-2668-49c3-b0f0-a8a43f535012" valueTypeId="495cea4c-3eb6-4d08-919d-6d59abff655e"/>
<managerType typeId="f3064463-f8fb-4faf-9e87-98a17486351a" valueTypeId="0c01ce0d-43ec-4cbb-ae90-f4769cd22ed6"/>
</producedTypes>
<name>Catalog</name>
<synonym>
<key>en</key>
<value>Catalog</value>
</synonym>
<useStandardCommands>true</useStandardCommands>
<inputByString>Catalog.Catalog.StandardAttribute.Code</inputByString>
<inputByString>Catalog.Catalog.StandardAttribute.Description</inputByString>
<fullTextSearchOnInputByString>DontUse</fullTextSearchOnInputByString>
<createOnInput>Use</createOnInput>
<dataLockControlMode>Managed</dataLockControlMode>
<fullTextSearch>Use</fullTextSearch>
<levelCount>2</levelCount>
<foldersOnTop>true</foldersOnTop>
<codeLength>9</codeLength>
<descriptionLength>25</descriptionLength>
<codeType>String</codeType>
<codeAllowedLength>Variable</codeAllowedLength>
<checkUnique>true</checkUnique>
<autonumbering>true</autonumbering>
<defaultPresentation>AsDescription</defaultPresentation>
<editType>InDialog</editType>
<choiceMode>BothWays</choiceMode>
<defaultObjectForm>Catalog.Catalog.Form.ItemForm</defaultObjectForm>
<forms uuid="9f57359a-1602-4756-98f6-c84a49f8422b">
<name>ItemForm</name>
<synonym>
<key>en</key>
<value>Item form</value>
</synonym>
<usePurposes>PersonalComputer</usePurposes>
<usePurposes>MobileDevice</usePurposes>
</forms>
</mdclass:Catalog>

View File

@ -0,0 +1,174 @@
<?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>Code</name>
<id>1</id>
<visible>true</visible>
<enabled>true</enabled>
<userVisible>
<common>true</common>
</userVisible>
<dataPath xsi:type="form:DataPath">
<segments>Object.Code</segments>
</dataPath>
<extendedTooltip>
<name>CodeExtendedTooltip</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>CodeContextMenu</name>
<id>2</id>
<visible>true</visible>
<enabled>true</enabled>
<userVisible>
<common>true</common>
</userVisible>
<autoFill>true</autoFill>
</contextMenu>
<type>InputField</type>
<editMode>EnterOnInput</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>
<items xsi:type="form:FormField">
<name>Description</name>
<id>4</id>
<visible>true</visible>
<enabled>true</enabled>
<userVisible>
<common>true</common>
</userVisible>
<dataPath xsi:type="form:DataPath">
<segments>Object.Description</segments>
</dataPath>
<extendedTooltip>
<name>DescriptionExtendedTooltip</name>
<id>6</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>DescriptionContextMenu</name>
<id>5</id>
<visible>true</visible>
<enabled>true</enabled>
<userVisible>
<common>true</common>
</userVisible>
<autoFill>true</autoFill>
</contextMenu>
<type>InputField</type>
<editMode>EnterOnInput</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>
<windowOpeningMode>LockOwnerWindow</windowOpeningMode>
<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>Object</name>
<id>1</id>
<valueType>
<types>CatalogObject.Catalog</types>
</valueType>
<view>
<common>true</common>
</view>
<edit>
<common>true</common>
</edit>
<main>true</main>
<savedData>true</savedData>
</attributes>
<attributes>
<name>Table</name>
<title>
<key>en</key>
<value>Table</value>
</title>
<id>2</id>
<valueType>
<types>ValueTable</types>
</valueType>
<view>
<common>true</common>
</view>
<edit>
<common>true</common>
</edit>
<columns>
<name>Attribute1</name>
<id>3</id>
<valueType>
<types>String</types>
<stringQualifiers/>
</valueType>
<view>
<common>true</common>
</view>
<edit>
<common>true</common>
</edit>
</columns>
</attributes>
<commandInterface>
<navigationPanel/>
<commandBar/>
</commandInterface>
<extInfo xsi:type="form:CatalogFormExtInfo"/>
</form:Form>

View File

@ -0,0 +1,23 @@
#Region Variables
#EndRegion
#Region FormEventHandlers
// Enter code here.
#EndRegion
#Region FormHeaderItemsEventHandlers
// Enter code here.
#EndRegion
#Region FormTableItemsEventHandlersFormTableName
// Enter code here.
#EndRegion
#Region FormCommandsEventHandlers
// Enter code here.
#EndRegion
#Region Private
// Enter code here.
#EndRegion

View File

@ -0,0 +1,23 @@
#Region Variables
#EndRegion
#Region Public
// Enter code here.
#EndRegion
#Region EventHandlers
// Enter code here.
#EndRegion
#Region Internal
// Enter code here.
#EndRegion
#Region Private
// Enter code here.
#EndRegion
#Region Initialize
#EndRegion

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<mdclass:CommonModule xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass" uuid="bcf0cc44-2ace-435f-a3c8-3ab91adb8e11">
<name>CommonModule</name>
<synonym>
<key>en</key>
<value>Common module</value>
</synonym>
<server>true</server>
<externalConnection>true</externalConnection>
<clientOrdinaryApplication>true</clientOrdinaryApplication>
</mdclass:CommonModule>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<mdclass:CommonModule xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass" uuid="e14591c8-e61f-42d8-8363-3b086482a27e">
<name>ComplientCommonModule</name>
<synonym>
<key>en</key>
<value>Complient common module</value>
</synonym>
<server>true</server>
<externalConnection>true</externalConnection>
<clientOrdinaryApplication>true</clientOrdinaryApplication>
</mdclass:CommonModule>

View File

@ -0,0 +1,24 @@
#Region Public
Procedure PublicMethod() Export
PrivateMethod();
EndProcedure
#EndRegion
#Region Internal
Procedure InternalMethod() Export
PrivateMethod();
EndProcedure
#EndRegion
#Region Private
Procedure PrivateMethod()
// add code
EndProcedure
#EndRegion

View File

@ -0,0 +1,24 @@
#Region NonPublic
Procedure PublicMethod() Export
PrivateMethod();
EndProcedure
#EndRegion
#Region Internal
Procedure InternalMethod() Export
PrivateMethod();
EndProcedure
#EndRegion
#Region Private
Procedure PrivateMethod()
// add code
EndProcedure
#EndRegion

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<mdclass:CommonModule xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass" uuid="2daf31c1-9297-4cd7-a9bd-5f044a4843cb">
<name>NonComplientCommonModule</name>
<synonym>
<key>en</key>
<value>Non complient common module</value>
</synonym>
<server>true</server>
<externalConnection>true</externalConnection>
<clientOrdinaryApplication>true</clientOrdinaryApplication>
</mdclass:CommonModule>

View File

@ -0,0 +1,24 @@
#Region Public
Procedure PublicMethod() Export
PrivateMethod();
EndProcedure
#Region Internal
Procedure InternalMethod() Export
PrivateMethod();
EndProcedure
#EndRegion
#EndRegion
#Region Private
Procedure PrivateMethod()
// add code
EndProcedure
#EndRegion

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<mdclass:CommonModule xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass" uuid="1728e682-e15d-4c31-a0d7-b330dd5c4b4d">
<name>NonComplientCommonModule1</name>
<synonym>
<key>en</key>
<value>Non complient common module1</value>
</synonym>
<server>true</server>
<externalConnection>true</externalConnection>
<clientOrdinaryApplication>true</clientOrdinaryApplication>
</mdclass:CommonModule>

View File

@ -0,0 +1,24 @@
#Region Public
Procedure PublicMethod() Export
PrivateMethod();
EndProcedure
#Region Public
Procedure InternalMethod() Export
PrivateMethod();
EndProcedure
#EndRegion
#EndRegion
#Region Private
Procedure PrivateMethod()
// add code
EndProcedure
#EndRegion

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<mdclass:CommonModule xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass" uuid="69c398a3-6f86-4c0d-b935-53e15745ac26">
<name>NonComplientCommonModule2</name>
<synonym>
<key>en</key>
<value>Non complient common module2</value>
</synonym>
<server>true</server>
<externalConnection>true</externalConnection>
<clientOrdinaryApplication>true</clientOrdinaryApplication>
</mdclass:CommonModule>

View File

@ -0,0 +1,24 @@
#Region Private
Procedure PrivateMethod()
// add code
EndProcedure
#EndRegion
#Region Public
Procedure PublicMethod() Export
PrivateMethod();
EndProcedure
#EndRegion
#Region Internal
Procedure InternalMethod() Export
PrivateMethod();
EndProcedure
#EndRegion

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<mdclass:CommonModule xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass" uuid="7917a3b9-e349-4d05-bd64-13540a738c93">
<name>NonComplientCommonModule3</name>
<synonym>
<key>en</key>
<value>Non complient common module3</value>
</synonym>
<server>true</server>
<externalConnection>true</externalConnection>
<clientOrdinaryApplication>true</clientOrdinaryApplication>
</mdclass:CommonModule>

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="04460a34-810c-48b0-9bcb-614d8eace302">
<name>ModuleStructureTopRegionCheck</name>
<synonym>
<key>en</key>
<value>Module structure top region check</value>
</synonym>
<containedObjects classId="9cd510cd-abfc-11d4-9434-004095e12fc7" objectId="251d7781-b73d-4c9d-92e3-2162fb032fb6"/>
<containedObjects classId="9fcd25a0-4822-11d4-9414-008048da11f9" objectId="3523fa9d-3ba3-4496-8bad-a09ebf8a42e2"/>
<containedObjects classId="e3687481-0a87-462c-a166-9f34594f9bba" objectId="b5a500b7-ee54-4ad1-87d7-f790e9391547"/>
<containedObjects classId="9de14907-ec23-4a07-96f0-85521cb6b53b" objectId="47674251-46ff-4f10-8f92-95a9992875fb"/>
<containedObjects classId="51f2d5d8-ea4d-4064-8892-82951750031e" objectId="ede1e22b-fb51-45dc-8217-da73e669e1ce"/>
<containedObjects classId="e68182ea-4237-4383-967f-90c1e3370bc7" objectId="597b5ef6-32b9-4830-a03c-a06a27b5b2f5"/>
<containedObjects classId="fb282519-d103-4dd3-bc12-cb271d631dfc" objectId="80aee558-2cfb-45ce-ac5a-241a29403d09"/>
<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="cebc9684-d49d-47fb-a13e-88c4a7af0224">
<name>English</name>
<synonym>
<key>en</key>
<value>English</value>
</synonym>
<languageCode>en</languageCode>
</languages>
<commonModules>CommonModule.ComplientCommonModule</commonModules>
<commonModules>CommonModule.NonComplientCommonModule</commonModules>
<commonModules>CommonModule.NonComplientCommonModule1</commonModules>
<commonModules>CommonModule.NonComplientCommonModule2</commonModules>
<commonModules>CommonModule.NonComplientCommonModule3</commonModules>
<commonModules>CommonModule.CommonModule</commonModules>
<catalogs>Catalog.Catalog</catalogs>
</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"/>