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

#374 #486 Проверка на пустые области и вложенные стандартные (#866)

This commit is contained in:
Dmitriy Marmyshev 2021-11-19 16:05:08 +03:00 committed by GitHub
parent 6ab7f54b59
commit 1f18140a49
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 1002 additions and 2 deletions

View File

@ -57,6 +57,8 @@
- Использование не рекомендуемых методов:
- ТекущаяДата
- Сообщить
- Область пустая
- Стандартная область структуры модуля верхнеуровневая
#### Запросы

View File

@ -0,0 +1,33 @@
# Region is empty
Check that module region is empty
## Noncompliant Code Example
```bsl
#Region Empty
#EndRegion
```bsl
## Compliant Solution
```bsl
#Region NotEmpty
Procedure Test()
EndProcedure
#EndRegion
```bsl
## See
- [Module structure](https://1c-dn.com/library/module_structure/)
- [Module structure](https://support.1ci.com/hc/en-us/articles/360011002360-Module-structure)

View File

@ -0,0 +1,41 @@
# Module stucture top region
Check that module structure region is on top
## Noncompliant Code Example
```bsl
#Region NotEmpty
#Region Public
Procedure Test() Export
EndProcedure
#EndRegion
#EndRegion
```bsl
## Compliant Solution
```bsl
#Region Public
Procedure Test1() Export
EndProcedure
#EndRegion
```bsl
## See
- [Module structure](https://1c-dn.com/library/module_structure/)
- [Module structure](https://support.1ci.com/hc/en-us/articles/360011002360-Module-structure)

View File

@ -0,0 +1,31 @@
# Область пустая
Проверяет что область модуля пустая
## Неправильно
```bsl
#Область ОписаниеПеременных
// объявление переменных
#КонецОбласти
```
## Правильно
```bsl
#Область ОписаниеПеременных
Перем ВалютаУчета;
Перем АдресПоддержки;
...
#КонецОбласти
```
## См.
- [Структура модуля](https://its.1c.ru/db/v8std#content:455:hdoc:1.8)

View File

@ -0,0 +1,40 @@
# Стандартная область структуры модуля верхнеуровневая
Проверяет что стандартная область структуры модуля не является вложенной
## Неправильно
```bsl
#Область НеПустая
#Область ПрограммныйИнтерфейс
Процедура Тест() Экспорт
КонецПроцедуры
#КонецОбласти
#КонецОбласти
```bsl
## Правильно
```bsl
#Область ПрограммныйИнтерфейс
Процедура Тест() Экспорт
КонецПроцедуры
#КонецОбласти
```bsl
## См.
- [Структура модуля](https://its.1c.ru/db/v8std#content:455:hdoc)

View File

@ -112,6 +112,14 @@
category="com.e1c.v8codestyle.bsl"
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.check.UseNonRecommendedMethodCheck">
</check>
<check
category="com.e1c.v8codestyle.bsl"
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.check.RegionEmptyCheck">
</check>
<check
category="com.e1c.v8codestyle.bsl"
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.check.ModuleStructureTopRegionCheck">
</check>
</extension>
<extension

View File

@ -13,6 +13,7 @@
package com.e1c.v8codestyle.bsl;
import java.io.InputStream;
import java.util.Collection;
import java.util.function.Supplier;
import org.eclipse.core.resources.IProject;
@ -40,7 +41,6 @@ public interface IModuleStructureProvider
/** The default value of creating module structure. */
boolean PREF_DEFAULT_CREATE_STRUCTURE = true;
/**
* Can create module structure template for the project. This checks project or default settings.
*
@ -60,5 +60,13 @@ public interface IModuleStructureProvider
*/
Supplier<InputStream> getModuleStructureTemplate(IProject project, ModuleType moduleType, ScriptVariant script);
/**
* Gets the module structure top regions in order of as they should be in module.
*
* @param moduleType the module type, cannot be {@code null}.
* @param scriptVariant the script variant, cannot be {@code null}.
* @return the module structure sorted and unique regions, cannot return {@code null}.
*/
Collection<String> getModuleStructureRegions(ModuleType moduleType, ScriptVariant scriptVariant);
}

View File

@ -0,0 +1,120 @@
/*******************************************************************************
* Copyright (C) 2021, 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.SortedSet;
import com._1c.g5.v8.dt.bsl.model.ModuleType;
import com.google.common.collect.ImmutableSortedSet;
/**
* Default module structure list of sections by the module type.
*
* @author Dmitriy Marmyshev
*/
public enum ModuleStructure
{
BOT_MODULE(ModuleStructureSection.EVENT_HANDLERS, ModuleStructureSection.PRIVATE),
COMMAND_MODULE(ModuleStructureSection.EVENT_HANDLERS, ModuleStructureSection.PRIVATE),
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),
HTTP_SERVICE_MODULE(ModuleStructureSection.EVENT_HANDLERS, ModuleStructureSection.PRIVATE),
INTEGRATION_SERVICE_MODULE(ModuleStructureSection.EVENT_HANDLERS, ModuleStructureSection.PRIVATE),
MANAGED_APP_MODULE(ModuleStructureSection.VARIABLES, ModuleStructureSection.EVENT_HANDLERS,
ModuleStructureSection.PRIVATE, ModuleStructureSection.INITIALIZE),
MANAGER_MODULE(ModuleStructureSection.PUBLIC, ModuleStructureSection.EVENT_HANDLERS,
ModuleStructureSection.INTERNAL, ModuleStructureSection.PRIVATE),
OBJECT_MODULE(ModuleStructureSection.VARIABLES, ModuleStructureSection.PUBLIC,
ModuleStructureSection.EVENT_HANDLERS, ModuleStructureSection.INTERNAL, ModuleStructureSection.PRIVATE,
ModuleStructureSection.INITIALIZE),
ORDINARY_APP_MODULE(ModuleStructureSection.VARIABLES, ModuleStructureSection.EVENT_HANDLERS,
ModuleStructureSection.PRIVATE, ModuleStructureSection.INITIALIZE),
RECORDSET_MODULE(ModuleStructureSection.VARIABLES, ModuleStructureSection.PUBLIC,
ModuleStructureSection.EVENT_HANDLERS, ModuleStructureSection.INTERNAL, ModuleStructureSection.PRIVATE,
ModuleStructureSection.INITIALIZE),
SESSION_MODULE(ModuleStructureSection.EVENT_HANDLERS, ModuleStructureSection.PRIVATE),
VALUE_MANAGER_MODULE(ModuleStructureSection.VARIABLES, ModuleStructureSection.PUBLIC,
ModuleStructureSection.EVENT_HANDLERS, ModuleStructureSection.INTERNAL, ModuleStructureSection.PRIVATE,
ModuleStructureSection.INITIALIZE),
WEB_SERVICE_MODULE(ModuleStructureSection.EVENT_HANDLERS, ModuleStructureSection.PRIVATE);
/**
* Gets the module structure regions with order how they should be placed in module.
*
* @param moduleType the module type, cannot be {@code null}.
* @return the module structure regions, cannot return {@code null}.
*/
public static Collection<ModuleStructureSection> getStructureByType(ModuleType moduleType)
{
switch (moduleType)
{
case BOT_MODULE:
return BOT_MODULE.getSections();
case COMMAND_MODULE:
return COMMAND_MODULE.getSections();
case COMMON_MODULE:
return COMMON_MODULE.getSections();
case EXTERNAL_CONN_MODULE:
return EXTERNAL_CONN_MODULE.getSections();
case FORM_MODULE:
return FORM_MODULE.getSections();
case HTTP_SERVICE_MODULE:
return HTTP_SERVICE_MODULE.getSections();
case INTEGRATION_SERVICE_MODULE:
return INTEGRATION_SERVICE_MODULE.getSections();
case MANAGED_APP_MODULE:
return MANAGED_APP_MODULE.getSections();
case MANAGER_MODULE:
return MANAGER_MODULE.getSections();
case OBJECT_MODULE:
return OBJECT_MODULE.getSections();
case ORDINARY_APP_MODULE:
return ORDINARY_APP_MODULE.getSections();
case RECORDSET_MODULE:
return RECORDSET_MODULE.getSections();
case SESSION_MODULE:
return SESSION_MODULE.getSections();
case VALUE_MANAGER_MODULE:
return VALUE_MANAGER_MODULE.getSections();
case WEB_SERVICE_MODULE:
return WEB_SERVICE_MODULE.getSections();
default:
break;
}
return ImmutableSortedSet.of();
}
private final SortedSet<ModuleStructureSection> sections;
ModuleStructure(ModuleStructureSection... sections)
{
this.sections = ImmutableSortedSet.copyOf(sections);
}
/**
* Gets the module structure regions with order how they should be placed in module.
*
* @return the sections, cannot return {@code null}.
*/
public Collection<ModuleStructureSection> getSections()
{
return sections;
}
}

View File

@ -0,0 +1,63 @@
/*******************************************************************************
* Copyright (C) 2021, 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 com._1c.g5.v8.dt.metadata.mdclass.ScriptVariant;
/**
* Standard module structure dually-named section.
*
* @author Dmitriy Marmyshev
*/
public enum ModuleStructureSection
{
PUBLIC("Public", "ПрограммныйИнтерфейс"), //$NON-NLS-1$ //$NON-NLS-2$
INTERNAL("Internal", "СлужебныйПрограммныйИнтерфейс"), //$NON-NLS-1$ //$NON-NLS-2$
PRIVATE("Private", "СлужебныеПроцедурыИФункции"), //$NON-NLS-1$ //$NON-NLS-2$
VARIABLES("Variables", "ОписаниеПеременных"), //$NON-NLS-1$ //$NON-NLS-2$
INITIALIZE("Initialize", "Инициализация"), //$NON-NLS-1$ //$NON-NLS-2$
EVENT_HANDLERS("EventHandlers", "ОбработчикиСобытий"), //$NON-NLS-1$ //$NON-NLS-2$
FORM_EVENT_HANDLERS("FormEventHandlers", "ОбработчикиСобытийФормы"), //$NON-NLS-1$ //$NON-NLS-2$
FORM_HEADER_ITEMS_EVENT_HANDLERS("FormHeaderItemsEventHandlers", "ОбработчикиСобытийЭлементовШапкиФормы"), //$NON-NLS-1$ //$NON-NLS-2$
FORM_COMMAND_EVENT_HANDLERS("FormCommandsEventHandlers", "ОбработчикиКомандФормы"), //$NON-NLS-1$ //$NON-NLS-2$
FORM_TABLE_ITEMS_EVENT_HANDLERS("FormTableItemsEventHandlers", "ОбработчикиСобытийЭлементовТаблицыФормы"); //$NON-NLS-1$ //$NON-NLS-2$
private final String[] names;
ModuleStructureSection(String name, String nameRu)
{
this.names = new String[] { name, nameRu };
}
/**
* Gets the dually-named name where first is English script variant and second is Russian script variant.
*
* @return the names, cannot return {@code null}.
*/
public String[] getNames()
{
return names;
}
/**
* Gets the name for the specific script variant of the project.
*
* @param scriptVariant the script variant, cannot be {@code null}.
* @return the name, cannot return {@code null}.
*/
public String getName(ScriptVariant scriptVariant)
{
return names[scriptVariant.getValue()];
}
}

View File

@ -0,0 +1,100 @@
/*******************************************************************************
* Copyright (C) 2021, 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 java.util.Optional;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.EcoreUtil2;
import com._1c.g5.v8.dt.bsl.model.Module;
import com._1c.g5.v8.dt.bsl.model.ModuleType;
import com._1c.g5.v8.dt.bsl.model.PreprocessorItem;
import com._1c.g5.v8.dt.bsl.model.RegionPreprocessor;
import com.e1c.g5.v8.dt.check.components.BasicCheck;
/**
* Abstract check of module structure, which declare top region names and order, where method should be included
* and etc.
*
* @author Dmitriy Marmyshev
* @author Victor Golubev
*/
public abstract class AbstractModuleStructureCheck
extends BasicCheck
{
/**
* Checks if the region is empty and has no any code elements.
*
* @param region the region, cannot be {@code null}.
* @return true, if the region is empty
*/
protected boolean isEmpty(RegionPreprocessor region)
{
PreprocessorItem item = region.getItem();
return item == null || !item.hasElement();
}
/**
* Gets the type of module by the given module objec as contect.
*
* @param context the context, cannot be {@code null}.
* @return the module type, may return {@code null} if cannot find module or the module has no type.
*/
protected ModuleType getModuleType(EObject context)
{
Module module = EcoreUtil2.getContainerOfType(context, Module.class);
if (module == null)
{
return null;
}
return module.getModuleType();
}
/**
* Gets the parent region of given region.
*
* @param object the region to find the parent, cannot be {@code null}.
* @return the parent region, cannot return {@code null}.
*/
protected Optional<RegionPreprocessor> getParentRegion(RegionPreprocessor object)
{
EObject parent = object.eContainer();
PreprocessorItem lastItem = null;
do
{
if (parent instanceof RegionPreprocessor)
{
RegionPreprocessor parentRegion = (RegionPreprocessor)parent;
if (parentRegion.getItem().equals(lastItem) || parentRegion.getItem().eContents().contains(object))
{
return Optional.ofNullable(parentRegion);
}
return Optional.empty();
}
else if (parent instanceof PreprocessorItem)
{
lastItem = (PreprocessorItem)parent;
}
parent = parent.eContainer();
}
while (parent != null);
return Optional.empty();
}
}

View File

@ -56,6 +56,12 @@ final class Messages
public static String EventHandlerBooleanParamCheck_title;
public static String ModuleStructureTopRegionCheck_description;
public static String ModuleStructureTopRegionCheck_error_message;
public static String ModuleStructureTopRegionCheck_title;
public static String QueryInLoop_check_query_in_infinite_loop;
public static String QueryInLoop_description;
public static String QueryInLoop_Loop_has_method_with_query__0;
@ -85,6 +91,12 @@ final class Messages
public static String NstrStringLiteralFormatCheck_title;
public static String RegionEmptyCheck_description;
public static String RegionEmptyCheck_Region_is_empty;
public static String RegionEmptyCheck_title;
public static String UseNonRecommendedMethods_description;
public static String UseNonRecommendedMethods_message;
@ -93,7 +105,6 @@ final class Messages
public static String UseNonRecommendedMethods_title;
static
{
// initialize resource bundle

View File

@ -0,0 +1,105 @@
/*******************************************************************************
* Copyright (C) 2021, 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.REGION_PREPROCESSOR;
import static com._1c.g5.v8.dt.mcore.McorePackage.Literals.NAMED_ELEMENT__NAME;
import java.util.Collection;
import java.util.Optional;
import org.eclipse.core.runtime.IProgressMonitor;
import com._1c.g5.v8.dt.bsl.model.ModuleType;
import com._1c.g5.v8.dt.bsl.model.RegionPreprocessor;
import com._1c.g5.v8.dt.core.platform.IV8Project;
import com._1c.g5.v8.dt.core.platform.IV8ProjectManager;
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.google.inject.Inject;
/**
* Checks that region named as module structure name is on top level of module.
*
* @author Dmitriy Marmyshev
*
*/
public class ModuleStructureTopRegionCheck
extends AbstractModuleStructureCheck
{
private static final String CHECK_ID = "module-structure-top-region"; //$NON-NLS-1$
private final IModuleStructureProvider moduleStructureProvider;
private final IV8ProjectManager v8ProjectManager;
@Inject
public ModuleStructureTopRegionCheck(IModuleStructureProvider moduleStructureProvider,
IV8ProjectManager v8ProjectManager)
{
super();
this.moduleStructureProvider = moduleStructureProvider;
this.v8ProjectManager = v8ProjectManager;
}
@Override
public String getCheckId()
{
return CHECK_ID;
}
@Override
protected void configureCheck(CheckConfigurer builder)
{
builder.title(Messages.ModuleStructureTopRegionCheck_title)
.description(Messages.ModuleStructureTopRegionCheck_description)
.complexity(CheckComplexity.NORMAL)
.severity(IssueSeverity.MAJOR)
.issueType(IssueType.CODE_STYLE)
.extension(new ModuleTopObjectNameFilterExtension())
.module()
.checkedObjectType(REGION_PREPROCESSOR);
}
@Override
protected void check(Object object, ResultAcceptor resultAceptor, ICheckParameters parameters,
IProgressMonitor monitor)
{
RegionPreprocessor region = (RegionPreprocessor)object;
if (region.getName() == null)
{
return;
}
IV8Project project = v8ProjectManager.getProject(region);
ModuleType moduleType = getModuleType(region);
Collection<String> names =
moduleStructureProvider.getModuleStructureRegions(moduleType, project.getScriptVariant());
if (!names.contains(region.getName()))
{
return;
}
Optional<RegionPreprocessor> parent = getParentRegion(region);
if (parent.isPresent())
{
resultAceptor.addIssue(Messages.ModuleStructureTopRegionCheck_error_message, NAMED_ELEMENT__NAME);
}
}
}

View File

@ -0,0 +1,68 @@
/*******************************************************************************
* Copyright (C) 2021, 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.REGION_PREPROCESSOR;
import static com._1c.g5.v8.dt.mcore.McorePackage.Literals.NAMED_ELEMENT__NAME;
import org.eclipse.core.runtime.IProgressMonitor;
import com._1c.g5.v8.dt.bsl.model.RegionPreprocessor;
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;
/**
* Check that region is empty.
*
* @author Dmitriy Marmyshev
*/
public class RegionEmptyCheck
extends AbstractModuleStructureCheck
{
private static final String CHECK_ID = "module-region-empty"; //$NON-NLS-1$
@Override
public String getCheckId()
{
return CHECK_ID;
}
@Override
protected void configureCheck(CheckConfigurer builder)
{
builder.title(Messages.RegionEmptyCheck_title)
.description(Messages.RegionEmptyCheck_description)
.complexity(CheckComplexity.NORMAL)
.severity(IssueSeverity.MINOR)
.issueType(IssueType.CODE_STYLE)
.extension(new ModuleTopObjectNameFilterExtension())
.module()
.checkedObjectType(REGION_PREPROCESSOR);
}
@Override
protected void check(Object object, ResultAcceptor resultAceptor, ICheckParameters parameters,
IProgressMonitor monitor)
{
RegionPreprocessor region = (RegionPreprocessor)object;
if (isEmpty(region))
{
resultAceptor.addIssue(Messages.RegionEmptyCheck_Region_is_empty, NAMED_ELEMENT__NAME);
}
}
}

View File

@ -56,6 +56,12 @@ EventHandlerBooleanParamCheck_description = Use event handler boolean parameter
EventHandlerBooleanParamCheck_title = Use event handler boolean parameter
ModuleStructureTopRegionCheck_description = Check that module structure region is on top
ModuleStructureTopRegionCheck_error_message = Module structure region is not on top
ModuleStructureTopRegionCheck_title = Module stucture top region
NstrStringLiteralFormatCheck_Check_empty_interface_for_each_language = Check empty interface for each language
NstrStringLiteralFormatCheck_NStr_contains_unknown_language_code__S = NStr contains unknown language code {0}
@ -84,6 +90,12 @@ QueryInLoop_description = Check query in loop
QueryInLoop_title = Query in loop
RegionEmptyCheck_Region_is_empty = Region is empty
RegionEmptyCheck_description = Check that module region is empty
RegionEmptyCheck_title = Region is empty
StructureCtorTooManyKeysCheck_Maximum_structure_constructor_keys = Maximum structure constructor keys
StructureCtorTooManyKeysCheck_Structure_constructor_has_more_than__0__keys = Structure constructor has more than {0} keys

View File

@ -56,6 +56,12 @@ EventHandlerBooleanParamCheck_description = Использование буле
EventHandlerBooleanParamCheck_title = Использование булевного параметра обработчика события
ModuleStructureTopRegionCheck_description = Проверяет что стандартная область структуры модуля не является вложенной
ModuleStructureTopRegionCheck_error_message = Стандартная область структуры модуля является вложенной
ModuleStructureTopRegionCheck_title = Стандартная область структуры модуля верхнеуровневая
NstrStringLiteralFormatCheck_Check_empty_interface_for_each_language = Проверять пустой интерфейс для каждого языка
NstrStringLiteralFormatCheck_NStr_contains_unknown_language_code__S = НСтр содержит неизвестный код языка {0}
@ -84,6 +90,12 @@ QueryInLoop_description = Проверка запрос в цикле
QueryInLoop_title = Запрос в цикле
RegionEmptyCheck_Region_is_empty = Область пустая
RegionEmptyCheck_description = Проверяет что область модуля пустая
RegionEmptyCheck_title = Область пустая
StructureCtorTooManyKeysCheck_Maximum_structure_constructor_keys = Максимальное количество ключей структуры в контструкторе
StructureCtorTooManyKeysCheck_Structure_constructor_has_more_than__0__keys = Конструктор структуры содержит более чем {0} ключей

View File

@ -17,8 +17,10 @@ import static com.e1c.v8codestyle.bsl.strict.StrictTypeUtil.BSL_FILE_EXTENSION;
import java.io.InputStream;
import java.net.URL;
import java.text.MessageFormat;
import java.util.Collection;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
@ -35,6 +37,8 @@ import org.eclipse.core.runtime.preferences.InstanceScope;
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;
/**
* The default implementation of module structure provider.
@ -124,4 +128,13 @@ public class ModuleStructureProvider
URL url = getClass().getResource(path);
return Optional.ofNullable(url);
}
@Override
public Collection<String> getModuleStructureRegions(ModuleType moduleType, ScriptVariant scriptVariant)
{
return ImmutableSortedSet.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 Test1()
EndProcedure
#EndRegion
#Region Private
Procedure Test2()
EndProcedure
#Region Internal
Procedure Test3()
EndProcedure
#EndRegion
#EndRegion
#EndIf

View File

@ -0,0 +1,24 @@
#If Server Or ThickClientOrdinaryApplication Or ExternalConnection Then
#Region Public
Procedure Test1()
EndProcedure
#EndRegion
#Region NotEmpty
#Region Public
Procedure Test()
EndProcedure
#EndRegion
#EndRegion
#EndIf

View File

@ -0,0 +1,12 @@
#If Server Or ThickClientOrdinaryApplication Or ExternalConnection Then
#Region Public
Procedure Test1()
EndProcedure
#EndRegion
#EndIf

View File

@ -0,0 +1,13 @@
#Region NotEmpty
Procedure Test()
EndProcedure
#EndRegion
#Region Empty
#EndRegion

View File

@ -0,0 +1,13 @@
#Region Empty
#EndRegion
#Region NotEmpty
Procedure Test()
EndProcedure
#EndRegion

View File

@ -0,0 +1,8 @@
#Region NotEmpty
#Region Empty
#EndRegion
#EndRegion

View File

@ -0,0 +1,4 @@
#Region Empty
#EndRegion

View File

@ -0,0 +1,8 @@
#Region NotEmpty
Procedure Test()
EndProcedure
#EndRegion

View File

@ -0,0 +1,89 @@
/*******************************************************************************
* Copyright (C) 2021, 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.assertTrue;
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.ModuleStructureTopRegionCheck;
/**
* Tests for {@link ModuleStructureTopRegionCheck} check.
*
* @author Dmitriy Marmyshev
*/
public class ModuleStructureTopRegionCheckTest
extends AbstractSingleModuleTestBase
{
public ModuleStructureTopRegionCheckTest()
{
super(ModuleStructureTopRegionCheck.class);
}
/**
* Test that the region is on top of the module structure.
*
* @throws Exception the exception
*/
@Test
public void testRegionIsOnTop() throws Exception
{
updateModule(FOLDER_RESOURCE + "module-structure.bsl");
List<Marker> markers = getModuleMarkers();
assertTrue(markers.isEmpty());
}
/**
* Test that top module structure region is sub region.
*
* @throws Exception the exception
*/
@Test
public void testSubRegion() throws Exception
{
updateModule(FOLDER_RESOURCE + "module-structure-sub-region.bsl");
List<Marker> markers = getModuleMarkers();
assertEquals(2, markers.size());
Marker marker = markers.get(0);
assertEquals("14", marker.getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_LINE_KEY));
// FIXME remove after marker duplication fix
marker = markers.get(1);
assertEquals("14", marker.getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_LINE_KEY));
}
/**
* Test that top module structure region is sub region and goes after method.
*
* @throws Exception the exception
*/
@Test
public void testSubRegionAfterMethod() throws Exception
{
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());
}
}

View File

@ -0,0 +1,134 @@
/*******************************************************************************
* Copyright (C) 2021, 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.assertTrue;
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.RegionEmptyCheck;
/**
* Tests for {@link RegionEmptyCheck} check.
*
* @author Dmitriy Marmyshev
*/
public class RegionEmptyCheckTest
extends AbstractSingleModuleTestBase
{
public RegionEmptyCheckTest()
{
super(RegionEmptyCheck.class);
}
/**
* Test region is empty.
*
* @throws Exception the exception
*/
@Test
public void testRegionIsEmpty() throws Exception
{
updateModule(FOLDER_RESOURCE + "region-empty.bsl");
List<Marker> markers = getModuleMarkers();
assertEquals(2, markers.size());
Marker marker = markers.get(0);
assertEquals("2", marker.getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_LINE_KEY));
// FIXME remove after marker duplication fix
marker = markers.get(1);
assertEquals("2", marker.getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_LINE_KEY));
}
/**
* Test region after another region is empty.
*
* @throws Exception the exception
*/
@Test
public void testRegionAfterIsEmpty() throws Exception
{
updateModule(FOLDER_RESOURCE + "region-empty-after.bsl");
List<Marker> markers = getModuleMarkers();
assertEquals(2, markers.size());
Marker marker = markers.get(0);
assertEquals("10", marker.getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_LINE_KEY));
// FIXME remove after marker duplication fix
marker = markers.get(1);
assertEquals("10", marker.getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_LINE_KEY));
}
/**
* Test region before another region is empty.
*
* @throws Exception the exception
*/
@Test
public void testRegionBeforeIsEmpty() throws Exception
{
updateModule(FOLDER_RESOURCE + "region-empty-before.bsl");
List<Marker> markers = getModuleMarkers();
assertEquals(2, markers.size());
Marker marker = markers.get(0);
assertEquals("2", marker.getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_LINE_KEY));
// FIXME remove after marker duplication fix
marker = markers.get(1);
assertEquals("2", marker.getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_LINE_KEY));
}
/**
* Test region has empty sub region.
*
* @throws Exception the exception
*/
@Test
public void testRegionHasEmptySubRegion() throws Exception
{
updateModule(FOLDER_RESOURCE + "region-empty-sub-region.bsl");
List<Marker> markers = getModuleMarkers();
assertEquals(2, markers.size());
Marker marker = markers.get(0);
assertEquals("4", marker.getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_LINE_KEY));
// FIXME remove after marker duplication fix
marker = markers.get(1);
assertEquals("4", marker.getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_LINE_KEY));
}
/**
* Test region is not empty.
*
* @throws Exception the exception
*/
@Test
public void testRegionIsNotEmpty() throws Exception
{
updateModule(FOLDER_RESOURCE + "region-not-empty.bsl");
List<Marker> markers = getModuleMarkers();
assertTrue(markers.isEmpty());
}
}