1
0
mirror of https://github.com/1C-Company/v8-code-style.git synced 2025-09-16 17:46:24 +02:00

Merge branch 'master' into edt-2022-1

This commit is contained in:
Dmitriy Marmyshev
2022-03-24 12:25:27 +03:00
269 changed files with 12349 additions and 917 deletions

View File

@@ -17,9 +17,9 @@
Общее:
- [ ] ветка PR обновлена из `master` и нет конфликтов
- [ ] Тесты-кейсы, JUnit тесты правильного и неправильного состояния
- [ ] Измененные Вами исходники отформатированы в соответствии [с конвенцией](docs/contributing/code_style.md)
- [ ] Измененные Вами исходники отформатированы в соответствии [с конвенцией](https://github.com/1C-Company/v8-code-style/blob/master/docs/contributing/code_style.md)
- [ ] Авто-аудит (SonarQube и CheckStyle) пройден, покрытие кода хорошее, ошибок нет, плохой код устранен
- [ ] Добавлена запись в [ИСТОРИЮ ИЗМЕНЕНИЯ](CHANGELOG.md), включаемая в пользовательскую документацию плагина
- [ ] Добавлена запись в [ИСТОРИЮ ИЗМЕНЕНИЯ](https://github.com/1C-Company/v8-code-style/blob/master/CHANGELOG.md), включаемая в пользовательскую документацию плагина
Если применимо:
- [ ] Пользовательская документация на доп.инструменты написана (на русском)

View File

@@ -70,7 +70,7 @@ jobs:
Xvfb :5 -screen 0 1280x1024x8 -fbdir /tmp &
export DISPLAY=:5
echo "Sonar param: \"${SONAR_PARAM}\""
mvn clean verify ${SONAR_PARAM} -PSDK,find-bugs -Dtycho.localArtifacts=ignore -B -V -T 1C
mvn clean verify ${SONAR_PARAM} -PSDK,find-bugs -Dtycho.localArtifacts=ignore -B -V
- name: Publish Test Report
uses: scacap/action-surefire-report@v1

View File

@@ -5,18 +5,24 @@
## 0.2.0
Выпуск бета-версии для 1C:EDT 2021.3
- Выпуск бета-версии для 1C:EDT 2021.3
- Автоматические индексы описаний проверок в справке `Help -> Help contents -> 1C:Code style V8`
### Новые фичи
- Функциональные опции, добавляемые 1C:Code Style, собраны в одном месте для удобного включения/выключения - в помощнике создания нового проекта или в свойствах проекта.
- В автосортировке метаданных добавлен учет системы запрета редактирования объектов (правила поддержки)
- Контекстное включение строгой типизации в модулях: по проекту, по списку объектов 1С или по списку файлов/каталогов, из контекстного меню в редакторе модуля
### Новые проверки
#### Метаданные
- Периодичность выполнения регламентного задания меньше одной минуты
- Общий модуль, для которого предусмотрен вызов сервера, должен именоваться с постфиксом "ВызовСервера"
- Общий модуль с повторно используемыми значениями должен именоваться с постфиксом "ПовтИсп"
- Клиентский общий модуль с повторно используемыми значениями должен именоваться с постфиксом "КлиентПовтИсп"
- Общий модуль ВызовСервера с повторно используемыми значениями должен именоваться с постфиксом "ВызовСервераПовтИсп"
#### Формы
@@ -26,17 +32,46 @@
- Программный вызов обработчика события формы
- Изменение категории проверки use-non-recommended-method на "стандарты разработки"
- Использование конструкции "Новый Цвет"
- Перенесены проверки документирующего комментария:
1. Тип коллекций в документирующем комментарии содержит тип элемента коллекции
2. Поле документирующего комментария использует объявление сложного типа вместо ссылки на тип
3. Многострочное описание документирующего комментария оканчивается на точку
4. Серкция возвращаемого значения документирующего комментария для экспортной функции
5. Многострочное описание документирующего комментария содержит определение поля
6. Поле документирующего комментария является корректным именем
7. Поле документирующего комментария не имеет определения типа
8. Многострочное описание документирующего комментария содержит определение параметра
9. В секции параметров документирующего комментария пропущено определение параметра
10. Документирующий комментарий содежрит секцию возвращаемого значения для процедуры
11. Ссылка документирующего комментария на существующий объект
12. Секция возвращаемого значения документирующего комментария содержит корректные типы
13. Определение типа документирующего комментария
14. Активирована ранее отключенная проверка: Секция возвращаемого значения функции-конструктора данных
- Исправлен идентификатор проверки тип в строгой типизации: `doc-comment-field-type` -> `doc-comment-field-type-strict`
- Ограничения на использование экспортных процедур и функций в модулях команд и форм
- Вызов "Заблокировать()" находится вне попытки
- Для проверок dynamic-access-method-not-found и property-return-type добавлена возможность исключения по типам (COM-Объекты)
- Проверка типов invocation-parameter-type-intersect проверяет типы элементов коллекций: Массив, Соотвествие, СписокЗначений
#### Запросы
#### Права ролей
### Новые быстрые исправления (Quick-fix)
- Удаление аннотации строгой типизации из модуля
- Открытие панели документирующего комментария
- Удаление ключевого слова Экспорт для процедур или функций в модуле команды и в модуле формы
### Исправленные ошибки
- Падение NPE в проверке ql-using-for-update, корректный учет зависимых проектов (обработки, расширения)
- Клиентский глобальный модуль: ошибочное предупреждение о некорректном типе
- Отключено создание модуля менеджера при создании перечисления
- Для проверки md-standard-attribute-synonym-empty исправлена регистрация и улучшена точность позиции ошибки
- Исправлен расчета типов возвращаемых значений функций с вызовом сервера
- Испрвление проверки типа локальной переменной в variable-value-type
- Проверка типов invocation-parameter-type-intersect при вызове метода, если существуют документирующие комментарии использует только декларированные типы
## 0.1.0

View File

@@ -267,9 +267,14 @@
<headerHtmlFile>${markdown.page.generator.html.file.path}/html/header.html</headerHtmlFile>
<footerHtmlFile>${markdown.page.generator.html.file.path}/html/footer.html</footerHtmlFile>
<pegdownExtensions>TABLES,FENCED_CODE_BLOCKS,AUTOLINKS,SMARTS,TASKLISTITEMS,EXTANCHORLINKS,TOC</pegdownExtensions>
<attributes>
<attribute>TableBlock|class=table table-striped table-bordered</attribute>
<attribute>BlockQuote|class=red</attribute>
</attributes>
<transformRelativeMarkdownLinks>true</transformRelativeMarkdownLinks>
<inputEncoding>UTF-8</inputEncoding>
<outputEncoding>UTF-8</outputEncoding>
<applyFiltering>true</applyFiltering>
</configuration>
</plugin>
<plugin>

View File

@@ -1,4 +1,5 @@
eclipse.preferences.version=1
encoding//src/com/e1c/v8codestyle/bsl/ui/qfix/messages_ru.properties=UTF-8
encoding//src/com/e1c/v8codestyle/internal/bsl/ui/preferences/messages_ru.properties=UTF-8
encoding//src/com/e1c/v8codestyle/internal/bsl/ui/properties/messages_ru.properties=UTF-8
encoding//src/com/e1c/v8codestyle/internal/bsl/ui/views/messages_ru.properties=UTF-8

View File

@@ -13,21 +13,32 @@ Require-Bundle: org.eclipse.ui;bundle-version="[3.119.0,4.0.0)",
org.eclipse.emf.databinding;bundle-version="[1.5.0,2.0.0)",
org.eclipse.xtext;bundle-version="[2.24.0,3.0.0)",
org.eclipse.xtext.ui;bundle-version="[2.24.0,3.0.0)",
org.eclipse.handly.xtext.ui;bundle-version="[1.5.0,2.0.0)"
org.eclipse.handly.xtext.ui;bundle-version="[1.5.0,2.0.0)",
org.eclipse.handly;bundle-version="[1.5.0,2.0.0)"
Bundle-RequiredExecutionEnvironment: JavaSE-11
Automatic-Module-Name: com.e1c.v8codestyle.bsl.ui
Bundle-ActivationPolicy: lazy
Bundle-Localization: plugin
Import-Package: com._1c.g5.v8.bm.core;version="[7.5.0,8.0.0)",
Import-Package: com._1c.g5.ides.ui.texteditor.xtext.embedded;version="[5.0.0,6.0.0)",
com._1c.g5.v8.bm.core;version="[7.5.0,8.0.0)",
com._1c.g5.v8.dt.bsl.comment;version="[3.0.0,4.0.0)",
com._1c.g5.v8.dt.bsl.common;version="[6.0.0,7.0.0)",
com._1c.g5.v8.dt.bsl.documentation.comment;version="[3.0.0,4.0.0)",
com._1c.g5.v8.dt.bsl.model;version="[5.0.0,6.0.0)",
com._1c.g5.v8.dt.bsl.services;version="[6.0.0,7.0.0)",
com._1c.g5.v8.dt.bsl.ui;version="[8.2.0,9.0.0)",
com._1c.g5.v8.dt.bsl.ui.contentassist;version="[8.0.0,9.0.0)",
com._1c.g5.v8.dt.bsl.ui.editor;version="[8.0.0,9.0.0)",
com._1c.g5.v8.dt.bsl.ui.menu;version="[6.0.0,7.0.0)",
com._1c.g5.v8.dt.bsl.ui.quickfix;version="[4.1.0,5.0.0)",
com._1c.g5.v8.dt.bsl.util;version="[7.0.0,8.0.0)",
com._1c.g5.v8.dt.common;version="[6.0.0,7.0.0)",
com._1c.g5.v8.dt.core.filesystem;version="[5.0.0,6.0.0)",
com._1c.g5.v8.dt.core.model;version="[6.0.0,7.0.0)",
com._1c.g5.v8.dt.core.platform;version="[10.0.0,11.0.0)",
com._1c.g5.v8.dt.lcore.ui.editor;version="[2.3.0,3.0.0)",
com._1c.g5.v8.dt.lcore.ui.texteditor;version="[1.1.0,2.0.0)",
com._1c.g5.v8.dt.lcore.util;version="[2.0.0,3.0.0)",
com._1c.g5.v8.dt.mcore;version="[6.0.0,7.0.0)",
com._1c.g5.v8.dt.metadata.mdclass;version="[8.0.0,9.0.0)",
com._1c.g5.v8.dt.theming.ui.util;version="[1.0.0,2.0.0)",
@@ -35,5 +46,10 @@ Import-Package: com._1c.g5.v8.bm.core;version="[7.5.0,8.0.0)",
com._1c.g5.v8.dt.ui.wizards;version="[8.0.0,9.0.0)",
com._1c.g5.wiring;version="[2.2.0,3.0.0)",
com._1c.g5.wiring.binder;version="[1.1.0,2.0.0)",
com.e1c.g5.v8.dt.bsl.check.qfix;version="[1.0.0,2.0.0)",
com.e1c.g5.v8.dt.check.qfix;version="[1.0.0,2.0.0)",
com.e1c.g5.v8.dt.check.qfix.components;version="[1.0.0,2.0.0)",
com.e1c.g5.v8.dt.check.settings;version="[2.0.0,3.0.0)",
com.e1c.v8codestyle.bsl;version="[0.2.0,0.3.0)",
com.e1c.v8codestyle.bsl.qfix.external;version="[0.2.0,0.3.0)",
com.e1c.v8codestyle.bsl.strict;version="[0.2.0,0.3.0)"

View File

@@ -13,6 +13,11 @@
###############################################################################
#Properties file for com.e1c.v8codestyle.bsl.ui
command.enableStrictTypes.mnemonic = E
command.enableStrictTypes.name = Enable @strict-types in modules
menu.label = Source
pluginName = 1C:Code style V8 Bsl UI plugin
preferences.modulestructure.name = Module structure

View File

@@ -230,5 +230,125 @@
name="%preferences.modulestructure.name">
</page>
</extension>
<extension
point="org.eclipse.ui.commands">
<command
defaultHandler="com.e1c.v8codestyle.internal.bsl.ui.ExecutableExtensionFactory:com.e1c.v8codestyle.internal.bsl.ui.handlers.AddStrictTypeAnnotationHandler"
id="com.e1c.v8codestyle.bsl.ui.commands.addStrictTypesAnnotationCommand"
name="%command.enableStrictTypes.name">
</command>
</extension>
<extension
point="org.eclipse.ui.menus">
<menuContribution
allPopups="false"
locationURI="popup:com._1c.g5.v8.dt.navigator.ui.navigator.popup?after=group.edit">
<command
commandId="com.e1c.v8codestyle.bsl.ui.commands.addStrictTypesAnnotationCommand"
mnemonic="%command.enableStrictTypes.mnemonic"
style="push">
<visibleWhen
checkEnabled="false">
<iterate
ifEmpty="false"
operator="or">
<or>
<instanceof
value="com._1c.g5.v8.dt.metadata.mdclass.MdObject">
</instanceof>
<and>
<instanceof
value="org.eclipse.core.resources.IResource">
</instanceof>
<or>
<test
property="org.eclipse.core.resources.projectNature"
value="com._1c.g5.v8.dt.core.V8ConfigurationNature">
</test>
<test
property="org.eclipse.core.resources.projectNature"
value="com._1c.g5.v8.dt.core.V8ExtensionNature">
</test>
<test
property="org.eclipse.core.resources.projectNature"
value="com._1c.g5.v8.dt.core.V8ExternalObjectsNature">
</test>
</or>
</and>
</or>
</iterate>
</visibleWhen>
</command>
</menuContribution>
<menuContribution
allPopups="false"
locationURI="popup:org.eclipse.ui.navigator.ProjectExplorer#PopupMenu?after=group.edit">
<command
commandId="com.e1c.v8codestyle.bsl.ui.commands.addStrictTypesAnnotationCommand"
style="push">
<visibleWhen
checkEnabled="false">
<iterate
ifEmpty="false"
operator="or">
<and>
<instanceof
value="org.eclipse.core.resources.IResource">
</instanceof>
<or>
<test
property="org.eclipse.core.resources.projectNature"
value="com._1c.g5.v8.dt.core.V8ConfigurationNature">
</test>
<test
property="org.eclipse.core.resources.projectNature"
value="com._1c.g5.v8.dt.core.V8ExtensionNature">
</test>
<test
property="org.eclipse.core.resources.projectNature"
value="com._1c.g5.v8.dt.core.V8ExternalObjectsNature">
</test>
</or>
</and>
</iterate>
</visibleWhen>
</command>
</menuContribution>
<menuContribution
allPopups="false"
locationURI="popup:#BslEditorContext?after=group.edit">
<menu
id="xtext.ui.SourceMenu"
label="%menu.label">
<command
commandId="com.e1c.v8codestyle.bsl.ui.commands.addStrictTypesAnnotationCommand"
style="push">
<visibleWhen
checkEnabled="false">
<reference
definitionId="com._1c.g5.v8.dt.bsl.Bsl.Editor.editable">
</reference>
</visibleWhen>
</command>
</menu>
</menuContribution>
</extension>
<extension
point="org.eclipse.ui.handlers">
<handler
class="com.e1c.v8codestyle.internal.bsl.ui.ExecutableExtensionFactory:com.e1c.v8codestyle.internal.bsl.ui.handlers.AddStrictTypeAnnotationModuleEditorHandler"
commandId="com.e1c.v8codestyle.bsl.ui.commands.addStrictTypesAnnotationCommand">
<activeWhen>
<reference
definitionId="com._1c.g5.v8.dt.bsl.Bsl.Editor.editable">
</reference></activeWhen>
</handler>
</extension>
<extension point="com.e1c.g5.v8.dt.check.fixes">
<fix class="com.e1c.v8codestyle.internal.bsl.ui.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.ui.qfix.UndefinedMethodFix"/>
<fix class="com.e1c.v8codestyle.internal.bsl.ui.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.ui.qfix.UndefinedFunctionFix"/>
<fix class="com.e1c.v8codestyle.internal.bsl.ui.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.ui.qfix.UndefinedVariableFix"/>
</extension>
</plugin>

View File

@@ -12,6 +12,11 @@
# 1C-Soft LLC - initial API and implementation
###############################################################################
command.enableStrictTypes.mnemonic = В
command.enableStrictTypes.name = Включить строгую типизацию (@strict-types) в модулях
menu.label = Исходники
pluginName = 1С:Стандарты разработки V8 UI плагин Встроенного языка
preferences.modulestructure.name = Структура модуля

View File

@@ -0,0 +1,48 @@
/*******************************************************************************
* 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.ui.qfix;
import org.eclipse.osgi.util.NLS;
/**
* NLS messages
*
* @author Vadim Geraskin
*/
final class Messages
extends NLS
{
private static final String BUNDLE_NAME = "com.e1c.v8codestyle.bsl.ui.qfix.messages"; //$NON-NLS-1$
public static String OpenBslDocCommentViewFix_Description;
public static String OpenBslDocCommentViewFix_Details;
public static String UndefinedMethodFix_func_title;
public static String UndefinedMethodFix_func_desc;
public static String UndefinedMethodFix_proc_title;
public static String UndefinedMethodFix_proc_desc;
public static String UndefinedVariableFix_title;
public static String UndefinedVariableFix_desc;
static
{
// initialize resource bundle
NLS.initializeMessages(BUNDLE_NAME, Messages.class);
}
private Messages()
{
// N/A
}
}

View File

@@ -0,0 +1,115 @@
/*******************************************************************************
* 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.ui.qfix;
import java.util.Collection;
import java.util.Set;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.swt.widgets.Display;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.xtext.resource.XtextResource;
import com._1c.g5.v8.dt.bsl.ui.quickfix.BslQuickFixUtil;
import com.e1c.g5.v8.dt.check.settings.CheckUid;
import com.e1c.v8codestyle.bsl.qfix.external.IXtextBslModuleFixModel;
import com.e1c.v8codestyle.bsl.qfix.external.IXtextInteractiveBslModuleFixModel;
import com.e1c.v8codestyle.bsl.qfix.external.SingleVariantXtextBslModuleFix;
import com.e1c.v8codestyle.internal.bsl.ui.UiPlugin;
import com.e1c.v8codestyle.internal.bsl.ui.views.BslDocCommentView;
/**
* The fix for all strict types checks that allows to remove annotation.
*
* @author Dmitriy Marmyshev
*/
public class OpenBslDocCommentViewFix
extends SingleVariantXtextBslModuleFix
{
@SuppressWarnings("nls")
public static Collection<String> getCheckIds()
{
return Set.of("doc-comment-field-type-strict", "doc-comment-collection-item-type",
"constructor-function-return-section", "doc-comment-use-minus",
"doc-comment-export-function-return-section", "doc-comment-field-name", "doc-comment-field-type",
"doc-comment-complex-type-with-link", "doc-comment-return-section-type",
"doc-comment-description-ends-on-dot", "doc-comment-field-in-description-suggestion",
"doc-comment-parameter-in-description-suggestion", "doc-comment-parameter-section",
"doc-comment-procedure-return-section", "doc-comment-ref-link", "doc-comment-type");
}
private final CheckUid checkUid;
/**
* Instantiates a new open BSL doc comment view fix.
*
* @param checkId the check id, cannot be {@code null}.
*/
public OpenBslDocCommentViewFix(CheckUid checkId)
{
this.checkUid = checkId;
}
@Override
public CheckUid getCheckId()
{
return checkUid;
}
@Override
protected void configureFix(FixConfigurer configurer)
{
configurer.interactive(true)
.description(Messages.OpenBslDocCommentViewFix_Description)
.details(Messages.OpenBslDocCommentViewFix_Details);
}
@Override
protected TextEdit fixIssue(XtextResource state, IXtextBslModuleFixModel model) throws BadLocationException
{
IXtextInteractiveBslModuleFixModel interactiveModel = (IXtextInteractiveBslModuleFixModel)model;
Integer offset = model.getIssue().getOffset() + 1;
Display display = PlatformUI.getWorkbench().getDisplay();
if (display.isDisposed())
{
return null;
}
display.asyncExec(() -> {
try
{
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().showView(BslDocCommentView.ID);
}
catch (PartInitException e)
{
UiPlugin.logError(e);
}
});
ITextViewer viewer = BslQuickFixUtil.getTextViewer(interactiveModel.getModificationContext());
if (viewer != null && !display.isDisposed())
{
display.asyncExec(() -> {
viewer.revealRange(offset, 1);
viewer.getTextWidget().setFocus();
viewer.setSelectedRange(offset, 1);
});
}
return null;
}
}

View File

@@ -0,0 +1,232 @@
/*******************************************************************************
* 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.ui.qfix;
import java.util.Optional;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.link.LinkedModeModel;
import org.eclipse.jface.text.link.LinkedPosition;
import org.eclipse.jface.text.link.LinkedPositionGroup;
import org.eclipse.xtext.EcoreUtil2;
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
import org.eclipse.xtext.ui.editor.model.IXtextDocument;
import com._1c.g5.v8.dt.bsl.model.Method;
import com._1c.g5.v8.dt.bsl.model.StaticFeatureAccess;
import com._1c.g5.v8.dt.bsl.ui.contentassist.BslProposalProvider;
import com._1c.g5.v8.dt.bsl.ui.quickfix.BslQuickFixUtil;
import com._1c.g5.v8.dt.metadata.mdclass.ScriptVariant;
import com.e1c.v8codestyle.bsl.qfix.external.IXtextBslModuleFixModel;
import com.e1c.v8codestyle.bsl.qfix.external.IXtextInteractiveBslModuleFixModel;
import com.google.common.base.Strings;
/**
* Helper methods for xtext-based quick fixes
*
* @author Vadim Geraskin
*/
public final class QuickFixMethodsHelper
{
/**
* Creates method and writes it to module
*
* @param model the xtext BSL quick fix model, cannot be {@code null}
* @param isFunc indicates whether the method is function or procedure
* @throws BadLocationException
*/
static void createMethod(IXtextInteractiveBslModuleFixModel model, boolean isFunc) throws BadLocationException
{
EObject element = model.getElement();
String methodName = getMethodName(((StaticFeatureAccess)element).getName());
String directiveName = ""; //$NON-NLS-1$
//up to Method class
Method method = EcoreUtil2.getContainerOfType(element, Method.class);
if (method != null)
{
String methodKeywordType = getTypeMethodName(model, isFunc);
String methodEndKeywordType = getTypeEndMethodName(model, isFunc);
//calculation offset
int totalEndOffset = NodeModelUtils.getNode(method).getTotalEndOffset();
Optional<String> indent = model.getFormatString(method);
if (indent.isPresent())
{
String func = createMethod(model, indent.get(), directiveName, methodName, methodKeywordType,
methodEndKeywordType);
// Write method to module
IXtextDocument document = (IXtextDocument)model.getDocument();
BslQuickFixUtil.writeToDoc(document, totalEndOffset, func);
flushMethod(model, indent.get(), methodKeywordType, totalEndOffset, directiveName);
}
}
}
/**
* Provides offset for the given {@Method}
*
* @param method the method, cannot be {@code null}
* @return offset
*/
static int getMethodOffset(Method method)
{
//method always has statement
return NodeModelUtils.findActualNodeFor(method.allStatements().get(0)).getOffset();
}
/**
* Gets 'Procedure' or 'Function'
*
* @param model {@link IXtextBslModuleFixModel}, cannot be {@code null}
* @param isFunc defines what will be return
* @return 'Procedure' if <code>isFunc == false, else return 'Function'</code>
*/
static String getTypeMethodName(IXtextBslModuleFixModel model, boolean isFunc)
{
boolean isRussion = model.getScriptVariant() == ScriptVariant.RUSSIAN;
return BslProposalProvider.getTypeMethodName(model.getBslGrammar(), isFunc, isRussion);
}
/**
* Gets 'EndProcedure' or 'EndFunction'
*
* @param model {@link IXtextBslModuleFixModel}, cannot be {@code null}
* @param isFunc defines what will be return
* @return 'EndProcedure' if <code>isFunc == false, else return 'EndFunction'</code>
*/
static String getTypeEndMethodName(IXtextBslModuleFixModel model, boolean isFunc)
{
boolean isRussion = model.getScriptVariant() == ScriptVariant.RUSSIAN;
return BslProposalProvider.getTypeEndMethodName(model.getBslGrammar(), isFunc, isRussion);
}
private static String getMethodName(String name)
{
StringBuilder builder = new StringBuilder();
builder.append(name);
builder.append('(');
builder.append(')');
return builder.toString();
}
private static String createMethod(IXtextInteractiveBslModuleFixModel model, String indent, String directive,
String methodName, String methodKeyword, String methodEndKeyword)
{
String lineSeparator = model.getLineSeparator();
String commentContent = Strings.repeat(lineSeparator, 2);
String todoComment = indent + model.getIndentProvider().getIndent()
+ model.getBslGeneratorMultiLangProposals().getImplementationPropStr();
StringBuilder builder = new StringBuilder();
//add comment above function
builder.append(commentContent);
//create function body
if (!Strings.isNullOrEmpty(directive))
{
builder.append(indent).append('&').append(directive).append(lineSeparator);
}
builder.append(indent).append(methodKeyword).append(' ');
builder.append(methodName);
builder.append(lineSeparator).append(todoComment).append(lineSeparator);
builder.append(indent).append(methodEndKeyword);
return builder.toString();
}
private static void flushMethod(IXtextInteractiveBslModuleFixModel model, String indent, String methodKeywordType,
int totalEndOffset, String directiveName)
{
IXtextDocument document = (IXtextDocument)model.getDocument();
String lineSeparator = model.getLineSeparator();
String commentContent = Strings.repeat(lineSeparator, 2);
//creating LinkedModeModel
LinkedPosition[] groupParams = calculateParamsGroupForMethod(commentContent, indent, lineSeparator,
methodKeywordType, document, model.getIssueData(), totalEndOffset);
int posDec = totalEndOffset + indent.length() + methodKeywordType.length() + 1 + commentContent.length();
if (!Strings.isNullOrEmpty(directiveName))
{
posDec += indent.length() + 1 + directiveName.length() + lineSeparator.length();
}
int posUse = model.getIssue().getOffset();
int nameLen = ((StaticFeatureAccess)model.getElement()).getName().length();
createLinkedModeModel(model, posDec, posUse, nameLen, groupParams);
}
private static LinkedPosition[] calculateParamsGroupForMethod(String commentContent, String indent,
String lineSeparator, String functionKeywordType, IXtextDocument doc, String[] data, int offset)
{
if (data != null && data.length >= 2)
{
int numParams = Integer.parseInt(data[2]);
LinkedPosition[] groupParams = new LinkedPosition[numParams];
int startLen = data[1].length() + 2 + offset + commentContent.length() + indent.length()
+ functionKeywordType.length();
if (!Strings.isNullOrEmpty(data[0]))
{
startLen += indent.length() + data[0].length() + lineSeparator.length() + 1;
}
for (int i = 3; i < data.length; ++i)
{
groupParams[i - 3] = new LinkedPosition(doc, startLen, data[i].length());
startLen += data[i].length() + 2;
}
return groupParams;
}
else
{
return new LinkedPosition[0];
}
}
private static void createLinkedModeModel(IXtextInteractiveBslModuleFixModel model, int posDec, int posUse,
int length, LinkedPosition[] params)
{
IXtextDocument document = (IXtextDocument)model.getDocument();
try
{
// create groups - this step is independent of the linked mode
LinkedPositionGroup group = new LinkedPositionGroup();
group.addPosition(new LinkedPosition(document, posDec, length));
group.addPosition(new LinkedPosition(document, posUse, length));
/* set up linked mode */
LinkedModeModel linkedModeModel = model.getLinkedModeModel();
linkedModeModel.addGroup(group);
for (int i = 0; i < params.length; ++i)
{
LinkedPositionGroup groupParam = new LinkedPositionGroup();
groupParam.addPosition(params[i]);
linkedModeModel.addGroup(groupParam);
}
LinkedModeModel.closeAllModels(document);
linkedModeModel.forceInstall();
model.enterUiMode();
model.selectAndRevealForLinkedModeModel(posDec, length);
}
catch (Exception e)
{
model.selectAndRevealForLinkedModeModel(posUse, length);
}
}
private QuickFixMethodsHelper()
{
// Not to be instantiated
}
}

View File

@@ -0,0 +1,46 @@
/*******************************************************************************
* 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.ui.qfix;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.xtext.resource.XtextResource;
import com.e1c.g5.v8.dt.check.qfix.components.QuickFix;
import com.e1c.v8codestyle.bsl.qfix.external.IXtextBslModuleFixModel;
import com.e1c.v8codestyle.bsl.qfix.external.IXtextInteractiveBslModuleFixModel;
import com.e1c.v8codestyle.bsl.qfix.external.SingleVariantXtextBslModuleFix;
/**
* Quick fix for check com.e1c.v8codestyle.bsl.check:undefined-function
*
* @author Vadim Geraskin
*/
@QuickFix(checkId = "module-undefined-function", supplierId = "com.e1c.v8codestyle.bsl")
public class UndefinedFunctionFix
extends SingleVariantXtextBslModuleFix
{
@Override
protected void configureFix(FixConfigurer configurer)
{
configurer.interactive(true).description(Messages.UndefinedMethodFix_func_title);
}
@Override
protected TextEdit fixIssue(XtextResource state, IXtextBslModuleFixModel model) throws BadLocationException
{
QuickFixMethodsHelper.createMethod((IXtextInteractiveBslModuleFixModel)model, true);
return null;
}
}

View File

@@ -0,0 +1,72 @@
/*******************************************************************************
* 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.ui.qfix;
import org.eclipse.jface.text.BadLocationException;
import com.e1c.g5.v8.dt.check.qfix.components.QuickFix;
import com.e1c.v8codestyle.bsl.qfix.external.IXtextInteractiveBslModuleFixModel;
import com.e1c.v8codestyle.bsl.qfix.external.MultiVariantXtextBslModuleFix;
import com.e1c.v8codestyle.internal.bsl.ui.UiPlugin;
/**
* Quick fix for check com.e1c.v8codestyle.bsl.check:undefined-method
*
* @author Vadim Geraskin
*/
@QuickFix(checkId = "module-undefined-method", supplierId = "com.e1c.v8codestyle.bsl")
public class UndefinedMethodFix
extends MultiVariantXtextBslModuleFix
{
@Override
protected void buildVariants()
{
// 1-st variant of issue qf: create function
VariantBuilder.create(this)
.description(Messages.UndefinedMethodFix_func_title, Messages.UndefinedMethodFix_func_desc)
.interactive(true)
.change((context, session, state, model) -> createFunction((IXtextInteractiveBslModuleFixModel)model))
.build();
// 2-nd variant of issue qf: create procedure
VariantBuilder.create(this)
.description(Messages.UndefinedMethodFix_proc_title, Messages.UndefinedMethodFix_proc_desc)
.interactive(true)
.change((context, session, state, model) -> createProcedure((IXtextInteractiveBslModuleFixModel)model))
.build();
}
private void createFunction(IXtextInteractiveBslModuleFixModel model)
{
try
{
QuickFixMethodsHelper.createMethod(model, true);
}
catch (BadLocationException e)
{
UiPlugin.log(UiPlugin.createErrorStatus("Error occured when creating function", e)); //$NON-NLS-1$
}
}
private void createProcedure(IXtextInteractiveBslModuleFixModel model)
{
try
{
QuickFixMethodsHelper.createMethod(model, false);
}
catch (BadLocationException e)
{
UiPlugin.log(UiPlugin.createErrorStatus("Error occured when creating procedure", e)); //$NON-NLS-1$
}
}
}

View File

@@ -0,0 +1,129 @@
/*******************************************************************************
* 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.ui.qfix;
import java.util.Optional;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.link.LinkedModeModel;
import org.eclipse.jface.text.link.LinkedPosition;
import org.eclipse.jface.text.link.LinkedPositionGroup;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.xtext.EcoreUtil2;
import org.eclipse.xtext.resource.XtextResource;
import org.eclipse.xtext.ui.editor.model.IXtextDocument;
import com._1c.g5.v8.dt.bsl.model.Method;
import com._1c.g5.v8.dt.bsl.model.StaticFeatureAccess;
import com._1c.g5.v8.dt.bsl.ui.quickfix.BslQuickFixUtil;
import com._1c.g5.v8.dt.metadata.mdclass.ScriptVariant;
import com.e1c.g5.v8.dt.check.qfix.components.QuickFix;
import com.e1c.v8codestyle.bsl.qfix.external.IXtextBslModuleFixModel;
import com.e1c.v8codestyle.bsl.qfix.external.IXtextInteractiveBslModuleFixModel;
import com.e1c.v8codestyle.bsl.qfix.external.SingleVariantXtextBslModuleFix;
/**
* Quick fix for check com.e1c.v8codestyle.bsl.check:undefined-variable
*
* @author Vadim Geraskin
*/
@QuickFix(checkId = "module-undefined-variable", supplierId = "com.e1c.v8codestyle.bsl")
public class UndefinedVariableFix
extends SingleVariantXtextBslModuleFix
{
@Override
protected void configureFix(FixConfigurer configurer)
{
configurer.interactive(true)
.description(Messages.UndefinedVariableFix_title)
.details(Messages.UndefinedVariableFix_desc);
}
@Override
protected TextEdit fixIssue(XtextResource state, IXtextBslModuleFixModel model) throws BadLocationException
{
IXtextInteractiveBslModuleFixModel interactiveModel = (IXtextInteractiveBslModuleFixModel)model;
EObject element = model.getElement();
String declarationKeyWord = getDeclarationKeyword(model);
//up to Method class
Method method = EcoreUtil2.getContainerOfType(element, Method.class);
if (method != null)
{
Optional<String> indent = interactiveModel.getFormatString(method);
if (indent.isPresent())
{
int offset = QuickFixMethodsHelper.getMethodOffset(method);
String variableName = ((StaticFeatureAccess)model.getElement()).getName();
IXtextDocument document = (IXtextDocument)interactiveModel.getDocument();
String lineSeparator = model.getLineSeparator();
String variable = BslQuickFixUtil.createVariable(declarationKeyWord, variableName,
indent.get() + interactiveModel.getIndentProvider().getIndent(), lineSeparator);
//write var to module
BslQuickFixUtil.writeToDoc(document, offset, variable);
//linked mode model
int posDec = offset + declarationKeyWord.length() + 1;
int posUse = model.getIssue().getOffset() + variable.length();
int length = variableName.length();
createLinkedModeModel(interactiveModel, posDec, posUse, length);
}
}
return null;
}
//CHECKSTYLE.OFF: LineLength
private static String getDeclarationKeyword(IXtextBslModuleFixModel model)
{
boolean isRussion = model.getScriptVariant() == ScriptVariant.RUSSIAN;
return !isRussion ? model.getBslGrammar().getDeclareStatementAccess().getVarKeyword_0_0().getValue() : model
.getBslGrammar()
.getDeclareStatementAccess()
.getCyrillicCapitalLetterPeCyrillicSmallLetterIeCyrillicSmallLetterErCyrillicSmallLetterIeCyrillicSmallLetterEmKeyword_0_1()
.getValue();
}
//CHECKSTYLE.ON: LineLength
private static void createLinkedModeModel(IXtextInteractiveBslModuleFixModel model, int posDec, int posUse,
int length)
{
IXtextDocument document = (IXtextDocument)model.getDocument();
try
{
//create groups - this step is independent of the linked mode
LinkedPositionGroup group = new LinkedPositionGroup();
group.addPosition(new LinkedPosition(document, posDec, length));
group.addPosition(new LinkedPosition(document, posUse, length));
//set up linked mode
LinkedModeModel linkedModeModel = model.getLinkedModeModel();
linkedModeModel.addGroup(group);
LinkedModeModel.closeAllModels(document);
linkedModeModel.forceInstall();
model.enterUiMode();
model.selectAndRevealForLinkedModeModel(posUse, length);
}
catch (Exception e)
{
//mark using varible
model.selectAndRevealForLinkedModeModel(posUse, length);
}
}
}

View File

@@ -0,0 +1,24 @@
OpenBslDocCommentViewFix_Details=Open documentation comment data structure view and show current probleme object.
#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/)
###############################################################################
# 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
# Vadim Geraskin - initial contibution
###############################################################################
OpenBslDocCommentViewFix_Description=Open documentation comment structure view
UndefinedMethodFix_func_title=Create function
UndefinedMethodFix_func_desc=Create a new function in the module
UndefinedMethodFix_proc_title=Create procedure
UndefinedMethodFix_proc_desc=Create a new procedure in the module
UndefinedVariableFix_title=Create variable
UndefinedVariableFix_desc=Create a missing variable in the method or module.\nSave changes in the editor after quick fix is applied.

View File

@@ -0,0 +1,30 @@
#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/)
###############################################################################
# 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
# Vadim Geraskin - initial contibution
###############################################################################
OpenBslDocCommentViewFix_Description = Открыть панель структуры документирующего комментария
OpenBslDocCommentViewFix_Details = Открыть панель структуры документирующего комментария и показать текущий проблемный объект.
UndefinedMethodFix_func_desc = Создать новую функцию в модуле
UndefinedMethodFix_func_title = Создать функцию
UndefinedMethodFix_proc_desc = Создать новую процедуру в модуле
UndefinedMethodFix_proc_title = Создать процедуру
UndefinedVariableFix_desc = Создать пропущенную переменную на уровне метода или модуля.\nПосле применения исправления сохраните изменения в редакторе.
UndefinedVariableFix_title = Создать переменную

View File

@@ -16,9 +16,11 @@ import org.eclipse.core.runtime.Plugin;
import com._1c.g5.v8.dt.bsl.common.IBslPreferences;
import com._1c.g5.v8.dt.core.filesystem.IQualifiedNameFilePathConverter;
import com._1c.g5.v8.dt.core.model.IModelEditingSupport;
import com._1c.g5.v8.dt.core.platform.IResourceLookup;
import com._1c.g5.v8.dt.core.platform.IV8ProjectManager;
import com._1c.g5.wiring.AbstractServiceAwareModule;
import com.e1c.g5.v8.dt.check.qfix.IFixRepository;
import com.e1c.v8codestyle.bsl.IModuleStructureProvider;
/**
@@ -44,6 +46,8 @@ class ExternalDependenciesModule
bind(IBslPreferences.class).toService();
bind(IQualifiedNameFilePathConverter.class).toService();
bind(IV8ProjectManager.class).toService();
bind(IModelEditingSupport.class).toService();
bind(IFixRepository.class).toService();
// CodeStyle Services
bind(IModuleStructureProvider.class).toService();

View File

@@ -0,0 +1,62 @@
/*******************************************************************************
* 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.internal.bsl.ui;
import com._1c.g5.wiring.IManagedService;
import com.e1c.g5.v8.dt.check.qfix.IFix;
import com.e1c.g5.v8.dt.check.qfix.IFixContext;
import com.e1c.g5.v8.dt.check.qfix.IFixRepository;
import com.e1c.g5.v8.dt.check.settings.CheckUid;
import com.e1c.v8codestyle.bsl.ui.qfix.OpenBslDocCommentViewFix;
import com.google.inject.Inject;
/**
* The registrar of quick-fix instance that applicable for several checks.
* The quick-fix should have public constructor with 1 parameter of {@link CheckUid}.
*
* @author Dmitriy Marmyshev
*/
public class MultiCheckFixRegistrator
implements IManagedService
{
private static final String CHECK_BUNDLE = "com.e1c.v8codestyle.bsl"; //$NON-NLS-1$
@Inject
private IFixRepository fixRepository;
/**
* Multi-check fix should be added here
*/
@Override
public void activate()
{
registerOpenBslDocCommentViewFix();
}
@Override
public void deactivate()
{
// do nothing
}
private void registerOpenBslDocCommentViewFix()
{
for (String checkId : OpenBslDocCommentViewFix.getCheckIds())
{
CheckUid id = new CheckUid(checkId, CHECK_BUNDLE);
IFix<? extends IFixContext> instance = new OpenBslDocCommentViewFix(id);
fixRepository.registerFix(instance);
}
}
}

View File

@@ -22,6 +22,8 @@ import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;
import com._1c.g5.v8.dt.bsl.model.BslPackage;
import com._1c.g5.wiring.InjectorAwareServiceRegistrator;
import com._1c.g5.wiring.ServiceInitialization;
import com.google.inject.Guice;
import com.google.inject.Injector;
@@ -43,6 +45,8 @@ public class UiPlugin
private volatile Injector injector;
private InjectorAwareServiceRegistrator registrator;
private static BundleContext context;
/**
@@ -129,6 +133,11 @@ public class UiPlugin
plugin = this;
BslPackage.eINSTANCE.eClass();
registrator = new InjectorAwareServiceRegistrator(bundleContext, this::getInjector);
ServiceInitialization.schedule(() -> {
// register services from injector
registrator.managedService(MultiCheckFixRegistrator.class).activateBeforeRegistration().registerInjected();
});
}

View File

@@ -0,0 +1,364 @@
/*******************************************************************************
* 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.internal.bsl.ui.handlers;
import static com._1c.g5.v8.dt.bsl.model.BslPackage.Literals.MODULE;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.Adapters;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.ICoreRunnable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.ui.handlers.HandlerUtil;
import com._1c.g5.v8.dt.core.model.EditingMode;
import com._1c.g5.v8.dt.core.model.IModelEditingSupport;
import com._1c.g5.v8.dt.core.platform.IResourceLookup;
import com._1c.g5.v8.dt.metadata.mdclass.MdObject;
import com.e1c.v8codestyle.bsl.strict.StrictTypeUtil;
import com.e1c.v8codestyle.internal.bsl.ui.UiPlugin;
import com.google.inject.Inject;
/**
* The Handler collects selection of objects and start {@link Job} by each project
* to add {@code @strict-types} annotation.
* Handler support {@link IProject}, {@link MdObject} and any files and folders.
*
* @author Dmitriy Marmyshev
*/
public class AddStrictTypeAnnotationHandler
extends AbstractHandler
{
@Inject
private IResourceLookup resourceLookup;
@Inject
private IModelEditingSupport modelEditingSupport;
@Override
public Object execute(ExecutionEvent event) throws ExecutionException
{
IStructuredSelection selection = HandlerUtil.getCurrentStructuredSelection(event);
if (!selection.isEmpty())
{
processSelection(selection);
}
return null;
}
private void processSelection(IStructuredSelection selection)
{
Collection<IProject> projects = getSelectedProjects(selection);
if (!projects.isEmpty())
{
projects.forEach(this::startProcessProject);
return;
}
Map<IProject, Collection<MdObject>> mdObjects = getSelectedMdObjects(selection);
if (!mdObjects.isEmpty())
{
mdObjects.forEach(this::startProcessMdObjects);
return;
}
Map<IProject, Collection<IResource>> resource = getSelectedResources(selection);
if (!resource.isEmpty())
{
resource.forEach(this::startProcessResources);
}
}
private Collection<IProject> getSelectedProjects(IStructuredSelection selection)
{
Collection<IProject> result = new ArrayList<>();
for (Iterator<?> iterator = selection.iterator(); iterator.hasNext();)
{
Object object = iterator.next();
if (object instanceof IProject)
{
result.add((IProject)object);
}
}
return result;
}
private Map<IProject, Collection<MdObject>> getSelectedMdObjects(IStructuredSelection selection)
{
Map<IProject, Collection<MdObject>> result = new HashMap<>();
for (Iterator<?> iterator = selection.iterator(); iterator.hasNext();)
{
Object object = iterator.next();
if (object instanceof MdObject)
{
IProject project = resourceLookup.getProject((MdObject)object);
if (project != null)
{
result.computeIfAbsent(project, p -> new ArrayList<>()).add((MdObject)object);
}
}
}
return result;
}
private Map<IProject, Collection<IResource>> getSelectedResources(IStructuredSelection selection)
{
Map<IProject, Collection<IResource>> result = new HashMap<>();
for (Iterator<?> iterator = selection.iterator(); iterator.hasNext();)
{
Object object = iterator.next();
IResource adapted = Adapters.adapt(object, IResource.class, true);
if (adapted != null && adapted.getProject() != null)
{
result.computeIfAbsent(adapted.getProject(), p -> new ArrayList<>()).add(adapted);
}
}
return result;
}
private void startProcessProject(IProject project)
{
createJobAndSchedule(project, m -> processProject(project, m));
}
private void startProcessMdObjects(IProject project, Collection<MdObject> mdObjects)
{
createJobAndSchedule(project, m -> processMdObjects(project, mdObjects, m));
}
private void startProcessResources(IProject project, Collection<IResource> resource)
{
createJobAndSchedule(project, m -> processResources(project, resource, m));
}
private void createJobAndSchedule(IProject project, ICoreRunnable runnable)
{
String title = MessageFormat.format(Messages.AddStrictTypeAnnotationHandler_Job_title, project.getName());
Job job = Job.create(title, runnable);
job.setUser(true);
job.setRule(project);
job.schedule();
}
private void processProject(IProject project, IProgressMonitor monitor)
{
if (!project.isAccessible())
{
return;
}
monitor.beginTask(Messages.AddStrictTypeAnnotationHandler_Get_prject_module_files, IProgressMonitor.UNKNOWN);
Collection<IFile> files = new HashSet<>();
appendFilesHierarchically(project, files, monitor);
monitor.done();
if (monitor.isCanceled() || files.isEmpty())
{
return;
}
updateFiles(files, monitor);
}
private void processMdObjects(IProject project, Collection<MdObject> mdObjects, IProgressMonitor monitor)
{
if (!project.isAccessible())
{
return;
}
monitor.beginTask(Messages.AddStrictTypeAnnotationHandler_Get_prject_module_files, IProgressMonitor.UNKNOWN);
Collection<IFile> files = getFiles(mdObjects, monitor);
monitor.done();
if (monitor.isCanceled() || files.isEmpty())
{
return;
}
updateFiles(files, monitor);
}
private void processResources(IProject project, Collection<IResource> resources, IProgressMonitor monitor)
{
if (!project.isAccessible())
{
return;
}
monitor.beginTask(Messages.AddStrictTypeAnnotationHandler_Get_prject_module_files, IProgressMonitor.UNKNOWN);
Collection<IFile> files = new HashSet<>();
for (IResource resource : resources)
{
if (monitor.isCanceled())
{
return;
}
appendFilesHierarchically(resource, files, monitor);
}
monitor.done();
if (monitor.isCanceled() || files.isEmpty())
{
return;
}
updateFiles(files, monitor);
}
private void appendFilesHierarchically(IResource resource, Collection<IFile> files, IProgressMonitor monitor)
{
try
{
resource.accept(r -> {
if (monitor.isCanceled())
{
return false;
}
if (r instanceof IFile)
{
IFile file = (IFile)r;
if (needUpdate(file))
{
files.add(file);
}
return false;
}
return true;
});
}
catch (CoreException e)
{
UiPlugin.logError(e);
}
}
private void updateFiles(Collection<IFile> files, IProgressMonitor monitor)
{
monitor.beginTask(Messages.AddStrictTypeAnnotationHandler_Update_module_files, files.size());
for (IFile file : files)
{
if (monitor.isCanceled())
{
return;
}
addAnnotationIfAbsent(file, monitor);
monitor.worked(1);
}
monitor.done();
}
private boolean needUpdate(IFile file)
{
if (StrictTypeUtil.BSL_FILE_EXTENSION.equals(file.getFileExtension()) && file.isAccessible())
{
try
{
return !StrictTypeUtil.hasStrictTypeAnnotation(file);
}
catch (CoreException | IOException e)
{
UiPlugin.logError(e);
}
}
return false;
}
private void addAnnotationIfAbsent(IFile file, IProgressMonitor monitor)
{
if (monitor.isCanceled())
{
return;
}
try
{
if (!StrictTypeUtil.hasStrictTypeAnnotation(file)
&& modelEditingSupport.canEdit(createModuleProxy(file), EditingMode.DIRECT) && !monitor.isCanceled())
{
StrictTypeUtil.setStrictTypeAnnotation(file, monitor);
}
}
catch (CoreException | IOException e)
{
IStatus status = UiPlugin.createErrorStatus("Can't update bsl file with name: " + file.getName(), e); //$NON-NLS-1$
UiPlugin.log(status);
}
}
private EObject createModuleProxy(IFile bslFile)
{
EObject module = EcoreUtil.create(MODULE);
URI uri = URI.createPlatformResourceURI(bslFile.getFullPath().toString(), true).appendFragment("/0"); //$NON-NLS-1$
((InternalEObject)module).eSetProxyURI(uri);
return module;
}
private Collection<IFile> getFiles(Collection<MdObject> mdObjects, IProgressMonitor monitor)
{
Collection<IFile> files = new HashSet<>();
for (MdObject mdObject : mdObjects)
{
if (monitor.isCanceled())
{
return files;
}
IFile mdFile = resourceLookup.getPlatformResource(mdObject);
if (mdFile == null)
{
continue;
}
appendFilesHierarchically(mdFile.getParent(), files, monitor);
}
return files;
}
}

View File

@@ -0,0 +1,179 @@
/*******************************************************************************
* 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.internal.bsl.ui.handlers;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.handly.buffer.BufferChange;
import org.eclipse.handly.snapshot.NonExpiringSnapshot;
import org.eclipse.text.edits.InsertEdit;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.handlers.HandlerUtil;
import org.eclipse.xtext.nodemodel.ICompositeNode;
import org.eclipse.xtext.nodemodel.ILeafNode;
import org.eclipse.xtext.nodemodel.INode;
import org.eclipse.xtext.parser.IParseResult;
import org.eclipse.xtext.resource.XtextResource;
import org.eclipse.xtext.ui.editor.XtextEditor;
import org.eclipse.xtext.ui.editor.model.IXtextDocument;
import org.eclipse.xtext.util.CancelIndicator;
import org.eclipse.xtext.util.Pair;
import org.eclipse.xtext.util.Tuples;
import org.eclipse.xtext.util.concurrent.CancelableUnitOfWork;
import com._1c.g5.ides.ui.texteditor.xtext.embedded.EmbeddedEditorBuffer;
import com._1c.g5.v8.dt.bsl.documentation.comment.BslCommentUtils;
import com._1c.g5.v8.dt.bsl.documentation.comment.IBslCommentToken;
import com._1c.g5.v8.dt.bsl.ui.menu.BslHandlerUtil;
import com._1c.g5.v8.dt.common.PreferenceUtils;
import com._1c.g5.v8.dt.core.model.EditingMode;
import com._1c.g5.v8.dt.core.model.IModelEditingSupport;
import com._1c.g5.v8.dt.core.platform.IResourceLookup;
import com.e1c.v8codestyle.bsl.strict.StrictTypeUtil;
import com.e1c.v8codestyle.internal.bsl.ui.UiPlugin;
import com.google.inject.Inject;
/**
* The Handler to update current module opened in BSL editor if {@code @strict-types} annotation is not added yet.
*
* @author Dmitriy Marmyshev
*/
public class AddStrictTypeAnnotationModuleEditorHandler
extends AbstractHandler
{
@Inject
private IResourceLookup resourceLookup;
@Inject
private IModelEditingSupport modelEditingSupport;
@Override
public Object execute(ExecutionEvent event) throws ExecutionException
{
IWorkbenchPart part = HandlerUtil.getActivePart(event);
XtextEditor target = BslHandlerUtil.extractXtextEditor(part);
if (target != null)
{
IXtextDocument document = target.getDocument();
Pair<IProject, Integer> pair =
document.readOnly(new CancelableUnitOfWork<Pair<IProject, Integer>, XtextResource>()
{
@Override
public Pair<IProject, Integer> exec(XtextResource resource, CancelIndicator monitor)
throws Exception
{
return getInsertContextIfPossible(resource,
monitor == null ? CancelIndicator.NullImpl : monitor);
}
});
if (pair != null && pair.getFirst() != null && pair.getSecond() > -1)
{
addAnnotation(document, pair.getFirst(), pair.getSecond());
}
}
return null;
}
private Pair<IProject, Integer> getInsertContextIfPossible(XtextResource resource, CancelIndicator monitor)
{
if (monitor.isCanceled() || resource.getParseResult() == null)
{
return null;
}
IParseResult parseResult = resource.getParseResult();
EObject root = parseResult.getRootASTElement();
if (!modelEditingSupport.canEdit(root, EditingMode.DIRECT))
{
return null;
}
ICompositeNode node = parseResult.getRootNode();
if (StrictTypeUtil.hasStrictTypeAnnotation(node))
{
return null;
}
int offset = getInsertOffset(node);
IProject project = resourceLookup.getProject(root);
if (monitor.isCanceled())
{
return null;
}
return Tuples.create(project, offset);
}
private void addAnnotation(IXtextDocument document, IProject project, int insertOffset)
{
String preferedLineSeparator = PreferenceUtils.getLineSeparator(project);
StringBuilder sb = new StringBuilder();
if (insertOffset > 0)
{
sb.append(preferedLineSeparator);
}
sb.append(IBslCommentToken.LINE_STARTER);
sb.append(" "); //$NON-NLS-1$
sb.append(StrictTypeUtil.STRICT_TYPE_ANNOTATION);
sb.append(preferedLineSeparator);
sb.append(preferedLineSeparator);
TextEdit change = new InsertEdit(insertOffset, sb.toString());
try (EmbeddedEditorBuffer buffer = new EmbeddedEditorBuffer(document))
{
NonExpiringSnapshot snapshot = new NonExpiringSnapshot(buffer);
BufferChange bufferChange = new BufferChange(change);
bufferChange.setBase(snapshot);
buffer.applyChange(bufferChange, new NullProgressMonitor());
}
catch (CoreException e)
{
UiPlugin.logError(e);
}
}
private static int getInsertOffset(INode root)
{
for (ILeafNode node : root.getLeafNodes())
{
if (!node.isHidden())
{
return 0;
}
if (!BslCommentUtils.isCommentNode(node))
{
return node.getOffset();
}
}
return 0;
}
}

View File

@@ -0,0 +1,37 @@
/*******************************************************************************
* 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.internal.bsl.ui.handlers;
import org.eclipse.osgi.util.NLS;
/**
* @author Dmitriy Marmyshev
*
*/
final class Messages
extends NLS
{
private static final String BUNDLE_NAME = "com.e1c.v8codestyle.internal.bsl.ui.handlers.messages"; //$NON-NLS-1$
public static String AddStrictTypeAnnotationHandler_Get_prject_module_files;
public static String AddStrictTypeAnnotationHandler_Job_title;
public static String AddStrictTypeAnnotationHandler_Update_module_files;
static
{
// initialize resource bundle
NLS.initializeMessages(BUNDLE_NAME, Messages.class);
}
private Messages()
{
}
}

View File

@@ -0,0 +1,19 @@
#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/)
###############################################################################
# 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
###############################################################################
AddStrictTypeAnnotationHandler_Get_prject_module_files = Collect prject module files
AddStrictTypeAnnotationHandler_Job_title = Enable @strict-types in modules: {0}
AddStrictTypeAnnotationHandler_Update_module_files = Process module files

View File

@@ -0,0 +1,19 @@
###############################################################################
# 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
###############################################################################
#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/)
AddStrictTypeAnnotationHandler_Get_prject_module_files = Сбор файлов модулей проекта
AddStrictTypeAnnotationHandler_Job_title = Включить @strict-types в модулях: {0}
AddStrictTypeAnnotationHandler_Update_module_files = Обработка файлов модулей

View File

@@ -12,13 +12,7 @@
*******************************************************************************/
package com.e1c.v8codestyle.internal.bsl.ui.wizard;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Set;
import org.eclipse.core.resources.IFile;
@@ -28,16 +22,12 @@ import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.emf.ecore.EObject;
import com._1c.g5.v8.dt.bsl.documentation.comment.IBslCommentToken;
import com._1c.g5.v8.dt.bsl.model.Module;
import com._1c.g5.v8.dt.common.PreferenceUtils;
import com._1c.g5.v8.dt.common.StringUtils;
import com._1c.g5.v8.dt.core.filesystem.IQualifiedNameFilePathConverter;
import com._1c.g5.v8.dt.metadata.mdclass.AbstractForm;
import com._1c.g5.v8.dt.ui.wizards.IDtNewWizardContext;
import com.e1c.v8codestyle.bsl.strict.StrictTypeUtil;
import com.e1c.v8codestyle.internal.bsl.ui.UiPlugin;
import com.google.common.io.CharStreams;
import com.google.inject.Inject;
/**
@@ -79,7 +69,7 @@ public class ModuleStrictTypesNewWizardRelatedModelsFactory
IFile bslFile = getModuleFile(module);
if (bslFile != null)
{
createOrUpdateModule(bslFile, context);
createOrUpdateModule(bslFile);
}
}
}
@@ -89,7 +79,7 @@ public class ModuleStrictTypesNewWizardRelatedModelsFactory
IFile bslFile = getModuleFile(formToAddModule, project);
if (bslFile != null)
{
createOrUpdateModule(bslFile, context);
createOrUpdateModule(bslFile);
EObject module = createBslProxyModule(bslFile);
createdModels.add(module);
@@ -98,7 +88,7 @@ public class ModuleStrictTypesNewWizardRelatedModelsFactory
}
private void createOrUpdateModule(IFile bslFile, IDtNewWizardContext<EObject> context)
private void createOrUpdateModule(IFile bslFile)
{
try
{
@@ -112,84 +102,19 @@ public class ModuleStrictTypesNewWizardRelatedModelsFactory
UiPlugin.logError(e);
}
String currentCode = StringUtils.EMPTY;
if (bslFile.exists())
try
{
try (InputStream in = bslFile.getContents();
Reader reader = new InputStreamReader(in, StandardCharsets.UTF_8);)
{
currentCode = CharStreams.toString(reader);
}
catch (IOException | CoreException e)
{
IStatus status = UiPlugin.createErrorStatus("Can't read bsl file with name: " + bslFile.getName(), e); //$NON-NLS-1$
UiPlugin.log(status);
}
}
IProject project = context.getV8project().getProject();
String preferedLineSeparator = PreferenceUtils.getLineSeparator(project);
StringBuilder sb = new StringBuilder();
int insertOffset = getInsertOffset(currentCode);
if (insertOffset > 0)
{
sb.append(currentCode.substring(0, insertOffset));
sb.append(preferedLineSeparator);
}
sb.append(IBslCommentToken.LINE_STARTER);
sb.append(" "); //$NON-NLS-1$
sb.append(StrictTypeUtil.STRICT_TYPE_ANNOTATION);
sb.append(preferedLineSeparator);
sb.append(preferedLineSeparator);
sb.append(currentCode.substring(insertOffset));
try (InputStream in = new ByteArrayInputStream(sb.toString().getBytes(StandardCharsets.UTF_8));)
{
if (bslFile.exists())
{
bslFile.setContents(in, true, true, new NullProgressMonitor());
}
else
if (!bslFile.exists())
{
createParentFolders(bslFile);
bslFile.create(in, true, new NullProgressMonitor());
}
StrictTypeUtil.setStrictTypeAnnotation(bslFile, new NullProgressMonitor());
}
catch (CoreException | IOException e)
catch (IOException | CoreException e)
{
IStatus status = UiPlugin.createErrorStatus("Can't create bsl file with name: " + bslFile.getName(), e); //$NON-NLS-1$
UiPlugin.log(status);
}
}
private int getInsertOffset(String currentCode)
{
int separator = resolveLineSeparator(currentCode).length();
int offset = 0;
for (Iterator<String> iterator = currentCode.lines().iterator(); iterator.hasNext();)
{
if (offset > 0)
{
offset = offset + separator;
}
String line = iterator.next();
if (StringUtils.isBlank(line))
{
return offset;
}
else if (!line.stripLeading().startsWith(IBslCommentToken.LINE_STARTER))
{
return 0;
}
offset = offset + line.length();
}
return 0;
}
}

View File

@@ -6,42 +6,59 @@ Bundle-Version: 0.2.0.qualifier
Bundle-Activator: com.e1c.v8codestyle.internal.bsl.BslPlugin
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.0.0,4.0.0)",
Require-Bundle: org.eclipse.core.resources;bundle-version="[3.13.0,4.0.0)",
org.eclipse.core.runtime;bundle-version="[3.0.0,4.0.0)",
org.eclipse.emf.common;bundle-version="[2.15.0,3.0.0)",
org.eclipse.text;bundle-version="[3.8.100,4.0.0)",
org.eclipse.xtext;bundle-version="[2.17.0,3.0.0)",
org.eclipse.core.resources;bundle-version="[3.13.0,4.0.0)",
org.eclipse.xtext.builder;bundle-version="[2.18.0,3.0.0)"
org.eclipse.xtext.builder;bundle-version="[2.18.0,3.0.0)",
org.eclipse.xtext.ui;bundle-version="[2.24.0,3.0.0)",
org.eclipse.handly;bundle-version="[1.5.0,2.0.0)",
org.eclipse.xtext.ui.shared;bundle-version="[2.19.0,3.0.0)"
Bundle-RequiredExecutionEnvironment: JavaSE-11
Automatic-Module-Name: com.e1c.v8codestyle.bsl
Bundle-ActivationPolicy: lazy
Import-Package: com._1c.g5.v8.bm.core;version="[7.0.0,8.0.0)",
com._1c.g5.v8.dt.bsl;version="[4.4.0,5.0.0)",
com._1c.g5.v8.dt.bsl.comment;version="[3.0.0,4.0.0)",
com._1c.g5.v8.dt.bsl.common;version="[6.0.0,7.0.0)",
com._1c.g5.v8.dt.bsl.contextdef;version="[2.0.0,3.0.0)",
com._1c.g5.v8.dt.bsl.documentation.comment;version="[3.0.0,4.0.0)",
com._1c.g5.v8.dt.bsl.model;version="[5.0.0,6.0.0)",
com._1c.g5.v8.dt.bsl.model.resource.owner;version="[2.0.0,3.0.0)",
com._1c.g5.v8.dt.bsl.model.typesytem;version="[6.0.0,7.0.0)",
com._1c.g5.v8.dt.bsl.model.util;version="[4.0.0,5.0.0)",
com._1c.g5.v8.dt.bsl.resource;version="[13.0.0,14.0.0)",
com._1c.g5.v8.dt.bsl.services;version="[6.0.0,7.0.0)",
com._1c.g5.v8.dt.bsl.typesystem;version="[9.0.0,10.0.0)",
com._1c.g5.v8.dt.bsl.typesystem.util;version="[9.0.0,10.0.0)",
com._1c.g5.v8.dt.bsl.ui;version="[8.2.0,9.0.0)",
com._1c.g5.v8.dt.bsl.ui.quickfix;version="[4.1.0,5.0.0)",
com._1c.g5.v8.dt.bsl.util;version="[7.0.0,8.0.0)",
com._1c.g5.v8.dt.bsl.validation;version="[16.0.0,17.0.0)",
com._1c.g5.v8.dt.common;version="[6.0.0,7.0.0)",
com._1c.g5.v8.dt.core.platform;version="[10.0.0,11.0.0)",
com._1c.g5.v8.dt.form.model;version="[10.0.0,11.0.0)",
com._1c.g5.v8.dt.lcore.ui.editor;version="[2.3.0,3.0.0)",
com._1c.g5.v8.dt.lcore.ui.texteditor;version="[1.1.0,2.0.0)",
com._1c.g5.v8.dt.lcore.util;version="[2.0.0,3.0.0)",
com._1c.g5.v8.dt.mcore;version="[6.0.0,7.0.0)",
com._1c.g5.v8.dt.mcore.util;version="[3.6.0,4.0.0)",
com._1c.g5.v8.dt.metadata.mdclass;version="[8.0.0,9.0.0)",
com._1c.g5.v8.dt.platform;version="[5.0.0,6.0.0)",
com._1c.g5.v8.dt.platform.version;version="[2.13.0,3.0.0)",
com._1c.g5.v8.dt.validation.marker;version="[5.0.0,6.0.0)",
com._1c.g5.wiring;version="[2.0.0,3.0.0)",
com._1c.g5.wiring.binder;version="[1.0.0,2.0.0)",
com.e1c.g5.v8.dt.bsl.check;version="[1.0.0,2.0.0)",
com.e1c.g5.v8.dt.bsl.check.qfix;version="[1.0.0,3.0.0)",
com.e1c.g5.v8.dt.check;version="[2.0.0,3.0.0)",
com.e1c.g5.v8.dt.check.components;version="[2.0.0,3.0.0)",
com.e1c.g5.v8.dt.check.qfix;version="[1.0.0,2.0.0)",
com.e1c.g5.v8.dt.check.qfix.components;version="[1.0.0,2.0.0)",
com.e1c.g5.v8.dt.check.settings;version="[3.0.0,4.0.0)",
com.e1c.v8codestyle;version="[0.2.0,0.3.0)",
com.e1c.v8codestyle.check;version="[0.2.0,0.3.0)"
Export-Package: com.e1c.v8codestyle.bsl;version="0.2.0",
com.e1c.v8codestyle.bsl.qfix.external;version="0.2.0",
com.e1c.v8codestyle.bsl.strict;version="0.2.0"

View File

@@ -0,0 +1,26 @@
# Documentation comment collection type definition has contain item type
## Noncompliant Code Example
```bsl
// Parameters:
// Parameters - Array - here array without item type
Procedure NonComplaint(Parameters) Export
// empty
EndProcedure
```
## Compliant Solution
```bsl
// Parameters:
// Parameters - Array of Number - has type of collection item
Procedure Complaint(Parameters) Export
// empty
EndProcedure
```
## See

View File

@@ -0,0 +1,39 @@
# Documentation comment field use declaration of complex type instead of link to type
## Noncompliant Code Example
```bsl
// Parameters:
// Parameters - Structure - (See NewStructureObject.)
Procedure NonComplaint(Parameters) Export
// empty
EndProcedure
// Returns:
// Parameters - Structure:
// * Key1 - Number - has type for key
Function NewStructureObject()
// empty
EndFunction
```
## Compliant Solution
```bsl
// Parameters:
// Parameters - See NewStructureObject
Procedure Complaint(Parameters) Export
// empty
EndProcedure
// Returns:
// Parameters - Structure:
// * Key1 - Number - has type for key
Function NewStructureObject()
// empty
EndFunction
```
## See

View File

@@ -0,0 +1,25 @@
# Documentation comment multi-line description ends on dot
## Noncompliant Code Example
```bsl
// First line
// second line
Procedure NonComplaint() Export
// empty
EndProcedure
```
## Compliant Solution
```bsl
// First line
// second line.
Procedure Complaint() Export
// empty
EndProcedure
```
## See

View File

@@ -0,0 +1,38 @@
# Documentation comment return section for export function
## Noncompliant Code Example
```bsl
// Description without return section
Function NonComplaint() Export
// empty
EndFunction
// See NonComplaint
Function NonComplaint2() Export
// empty
EndFunction
```
## Compliant Solution
```bsl
// See Complaint2
Function Complaint() Export
// empty
EndFunction
// Returns:
// Structure - Parameters:
// * Key1 - Number - has type for key
Function Complaint2() Export
// empty
EndFunction
```
## See

View File

@@ -0,0 +1,30 @@
# Documentation comment multi-line description contains field definition
## Noncompliant Code Example
```bsl
// Parameters
// Parameters - Structure - description
// * Key1 - this field is part of description
Procedure NonComplaint(Parameters) Export
// empty
EndProcedure
```
## Compliant Solution
```bsl
// Parameters:
// Parameters - Structure - description:
// * Key1 - Number - this field is extension of the structure
Procedure Complaint(Parameters) Export
// empty
EndProcedure
```
## See

View File

@@ -0,0 +1,32 @@
# Documentation comment field is correct name
## Noncompliant Code Example
```bsl
// Parameters:
// Parameters - Structure:
// * 1Name - incorrect name
//
Procedure NonComplaint(Parameters)
EndProcedure
```
## Compliant Solution
```bsl
// Parameters:
// Parameters - Structure:
// * Name - correct name
//
Procedure Complaint(Parameters)
EndProcedure
```
## See

View File

@@ -0,0 +1,32 @@
# Documentation comment Field has no type definition
Check of module strict types system that documentation comment field has section with types
## Noncompliant Code Example
```bsl
// Parameters:
// Parameters - Structure:
// * Key1 - has no type for key
Procedure NonComplaint(Parameters) Export
// empty
EndProcedure
```
## Compliant Solution
```bsl
// Parameters:
// Parameters - Structure:
// * Key1 - Number - has type for key
// * Key2 - See NonComplaint.Parameters
Procedure Complaint(Parameters) Export
// empty
EndProcedure
```
## See

View File

@@ -1,10 +1,30 @@
# Documentation comment Field has no type defenition
Check of module strict types system that documentation comment field has section with types
# Documentation comment field has no type definition
## Noncompliant Code Example
```bsl
// Parameters:
// Parameters - Structure:
// * Key1 - has no type for key
Procedure NonComplaint(Parameters) Export
// empty
EndProcedure
```
## Compliant Solution
```bsl
// Parameters:
// Parameters - Structure:
// * Key1 - Number - has type for key
// * Key2 - See NonComplaint.Parameters
Procedure Complaint(Parameters) Export
// empty
EndProcedure
```
## See

View File

@@ -0,0 +1,30 @@
# Documentation comment multi-line description contains parameter definition
## Noncompliant Code Example
```bsl
// Description
//
// Parameters
// Parameter1 - this parameter is part of description
Procedure NonComplaint(Parameter1) Export
// empty
EndProcedure
```
## Compliant Solution
```bsl
// Description
//
// Parameters:
// Parameter1 - this parameter is the section of parameters
Procedure Complaint(Parameters) Export
// empty
EndProcedure
```
## See

View File

@@ -0,0 +1,41 @@
# Documentation comment parameter section missed parameter definition
## Noncompliant Code Example
```bsl
// For export method all parameters should be in parameter section
//
// Parameters:
// Parameters - Only first parameter here
Procedure NonComplaint(Parameters, SecondParameter) Export
// empty
EndProcedure
// Parameters:
// Parameters - Method should not have parameter section
Procedure NonComplaint2() Export
// empty
EndProcedure
```
## Compliant Solution
```bsl
// Parameters:
// Parameters - Structure
Procedure Complaint(Parameters) Export
// empty
EndProcedure
// Parameters:
// Parameters - local methods may not contains all parameters
Procedure Complaint2(Parameters, SecondParameter)
// empty
EndProcedure
```
## See

View File

@@ -0,0 +1,27 @@
# Documentation comment has return section for procedure
## Noncompliant Code Example
```bsl
// Returns:
// Structure - procedure should not have return section!
Procedure NonComplaint() Export
// empty
EndProcedure
```
## Compliant Solution
```bsl
// Procedure description
Procedure Complaint() Export
// empty
EndProcedure
```
## See

View File

@@ -0,0 +1,31 @@
# Documentation comment link referenced object exists
## Noncompliant Code Example
```bsl
// Parameters:
// Parameters - See Complaint.UnknownParameter
Procedure NonComplaint(Parameters) Export
// empty
EndProcedure
```
## Compliant Solution
```bsl
// See word - this "word" is not link in description
//
// Parameters:
// Parameters - Here valid web-link See https://1c.ru
// LinkToMethod - See NonComplaint()
Procedure Complaint(Parameters, LinkToMethod) Export
// empty
EndProcedure
```
## See

View File

@@ -0,0 +1,48 @@
# Documentation comment return section contains valid types
## Noncompliant Code Example
```bsl
// Returns:
// Empty types here
Function NonComplaint(Parameters) Export
// empty
EndFunction
// Here ref link to function without return type
//
// Returns:
// See NonComplaint()
Function NonComplaint2(Parameters) Export
// empty
EndFunction
// Returns:
// UnknownType - here unknown return type
Function NonComplaint3(Parameters) Export
// empty
EndFunction
```
## Compliant Solution
```bsl
// Parameters:
// See Complaint2()
Function Complaint(Parameters) Export
// empty
EndFunction
// Parameters:
// Structure - has return type
Function Complaint2(Parameters) Export
// empty
EndFunction
```
## See

View File

@@ -0,0 +1,26 @@
# Documentation comment type definition
## Noncompliant Code Example
```bsl
// Parameters:
// Parameters - Structure1 - incorrect type
Procedure NonComplaint(Parameters) Export
// empty
EndProcedure
```
## Compliant Solution
```bsl
// Parameters:
// Parameters - Structure - correct type
Procedure Complaint(Parameters) Export
// empty
EndProcedure
```
## See

View File

@@ -0,0 +1,31 @@
# Restrictions on the use of export procedures and functions in a command and form modules
Do not place export procedures and functions in command and form modules.
To implement export procedures and functions, it is recommended that you use object modules, object manager modules, or
common modules.
Recommended once a form is opened, don't address form methods and properties.
An exception to this rule are export procedures that handle notifications (NotifyDescription.ProcedureName).
## Noncompliant Code Example
```bsl
&AtClient
Procedure CommandProcessing(CommandParameter, CommandExecuteParameters) Export
EndProcedure
```
## Compliant Solution
```bsl
&AtClient
Procedure CommandProcessing(CommandParameter, CommandExecuteParameters)
EndProcedure
```
## See
- [Restrictions on the use of export procedures and functions](https://support.1ci.com/hc/en-us/articles/360011002940-Restrictions-on-the-use-of-export-procedures-and-functions)
- [Rules for creating form modules](https://support.1ci.com/hc/en-us/articles/360011003920-Rules-for-creating-form-modules)
- [Opening forms](https://support.1ci.com/hc/en-us/articles/360011003960-Opening-forms)

View File

@@ -0,0 +1,40 @@
# The "Lock()" call is out of the try block
The rule checks for initialization of the data lock. If the
creation of a lock is found, the call of the "Lock()" method is checked,
and the call must be in a try block.
## Noncompliant Code Example
```bsl
DataLock = new DataLock;
DataLockItem = DataLock.Add("Document.Test");
DataLockItem.Mode = DataLockMode.Exclusive;
DataLock.Lock();
```
## Compliant Solution
```bsl
BeginTransaction();
Try
DataLock = new DataLock;
DataLockItem = DataLock.Add("Document.Test");
DataLockItem.Mode = DataLockMode.Exclusive;
DataLock.Lock();
CommitTransaction();
Except
RollbackTransaction();
Raise;
EndTry;
```
## See
- [Catching exceptions in code](https://support.1ci.com/hc/en-us/articles/360011002440-Catching-exceptions-in-code)
- [Transactions: rules of use](https://support.1ci.com/hc/en-us/articles/360011121239-Transactions-rules-of-use)

View File

@@ -0,0 +1,10 @@
# Undefined function
## Noncompliant Code Example
## Compliant Solution
## See

View File

@@ -0,0 +1,11 @@
# Undefined method
Undefined function or procedure
## Noncompliant Code Example
## Compliant Solution
## See

View File

@@ -0,0 +1,10 @@
# Undefined variable
## Noncompliant Code Example
## Compliant Solution
## See

View File

@@ -0,0 +1,8 @@
# Тип коллекций в документирующем комментарии содержит тип элемента коллекции
## Неправильно
## Правильно
## См.

View File

@@ -0,0 +1,8 @@
# Поле документирующего комментария использует объявление сложного типа вместо ссылки на тип
## Неправильно
## Правильно
## См.

View File

@@ -0,0 +1,8 @@
# Многострочное описание документирующего комментария оканчивается на точку
## Неправильно
## Правильно
## См.

View File

@@ -0,0 +1,8 @@
# Секция возвращаемого значения документирующего комментария для экспортной функции
## Неправильно
## Правильно
## См.

View File

@@ -0,0 +1,8 @@
# Многострочное описание документирующего комментария содержит определение поля
## Неправильно
## Правильно
## См.

View File

@@ -0,0 +1,8 @@
# Поле документирующего комментария является корректным именем
## Неправильно
## Правильно
## См.

View File

@@ -0,0 +1,10 @@
# Поле документирующего комментария имеет описание типа
Система строгой типизации кода проверяет, что поле документирующего комментария имеет описание типа
## Неправильно
## Правильно
## См.

View File

@@ -1,6 +1,4 @@
# Поле документирующего комментария имеет описание типа
Система строгой типизации кода проверяет что поле документирующего комментария имеет описание типа
# Поле документирующего комментария не имеет определения типа
## Неправильно

View File

@@ -0,0 +1,8 @@
# Многострочное описание документирующего комментария содержит определение параметра
## Неправильно
## Правильно
## См.

View File

@@ -0,0 +1,8 @@
# В секции параметров документирующего комментария пропущено определение параметра
## Неправильно
## Правильно
## См.

View File

@@ -0,0 +1,8 @@
# Документирующий комментарий содежрит секцию возвращаемого значения для процедуры
## Неправильно
## Правильно
## См.

View File

@@ -0,0 +1,8 @@
# Ссылка документирующего комментария на существующий объект
## Неправильно
## Правильно
## См.

View File

@@ -0,0 +1,8 @@
# Секция возвращаемого значения документирующего комментария содержит корректные типы
## Неправильно
## Правильно
## См.

View File

@@ -0,0 +1,8 @@
# Определение типа документирующего комментария
## Неправильно
## Правильно
## См.

View File

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

View File

@@ -0,0 +1,41 @@
# Вызов "Заблокировать()" находится вне попытки
Правило проверяет наличие инициализации блокировки данных. В случае если
найдено создание блокировки, проверяется вызов метода "Заблокировать()",
при этом вызов должен быть в попытке.
## Неправильно
```bsl
БлокировкаДанных = Новый БлокировкаДанных;
ЭлементБлокировкиДанных = БлокировкаДанных.Добавить("Документ.ПриходнаяНакладная");
ЭлементБлокировкиДанных.Режим = РежимБлокировкиДанных.Исключительный;
БлокировкаДанных.Заблокировать();
```
## Правильно
```bsl
НачатьТранзакцию();
Попытка
БлокировкаДанных = Новый БлокировкаДанных;
ЭлементБлокировкиДанных = БлокировкаДанных.Добавить("Документ.ПриходнаяНакладная");
ЭлементБлокировкиДанных.Режим = РежимБлокировкиДанных.Исключительный;
БлокировкаДанных.Заблокировать();
// чтение или запись данных
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;
```
## См.
- [Перехват исключений в коде](https://its.1c.ru/db/v8std#content:499:hdoc:3.6)
- [Транзакции: правила использования](https://its.1c.ru/db/v8std#content:783:hdoc:1.3)

View File

@@ -0,0 +1,8 @@
# Функция не определена
## Неправильно
## Правильно
## См.

View File

@@ -0,0 +1,10 @@
# Метод не определен
Функция или процедура не определена
## Неправильно
## Правильно
## См.

View File

@@ -0,0 +1,8 @@
# Переменная не определена
## Неправильно
## Правильно
## См.

View File

@@ -1,3 +1,4 @@
#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/)
###############################################################################
# Copyright (C) 2021, 1C-Soft LLC and others.
#
@@ -11,10 +12,14 @@
# 1C-Soft LLC - initial API and implementation
###############################################################################
#Properties file for com.e1c.v8codestyle.bsl
providerName = 1C-Soft LLC
category.bsl.comment.description = Checks of method documentation comment model
category.bsl.comment.title = Documentation comment
category.bsl.description = Checks of 1C:Enterprise build-in module language by 1C:Development standard (code style)
category.bsl.strict.description = Checks of 1C:Enterprise build-in module language that each object strictly typed
category.bsl.strict.title = Strict types system
category.bsl.title = Built-in script language
pluginName = 1C:Code style V8 Bsl plugin
category.bsl.title = Built-in script language
category.bsl.description = Checks of 1C:Enterprise build-in module language by 1C:Development standard (code style)
category.bsl.strict.title = Strict types system
category.bsl.strict.description = Checks of 1C:Enterprise build-in module language that each object strictly typed
providerName = 1C-Soft LLC

View File

@@ -24,6 +24,12 @@
id="com.e1c.v8codestyle.bsl"
title="%category.bsl.title">
</category>
<category
category="com.e1c.v8codestyle.bsl"
description="%category.bsl.comment.description"
id="com.e1c.v8codestyle.bsl.comment"
title="%category.bsl.comment.title">
</category>
<category
category="com.e1c.v8codestyle.bsl"
description="%category.bsl.strict.description"
@@ -60,7 +66,7 @@
</check>
<check
category="com.e1c.v8codestyle.bsl"
class="com.e1c.v8codestyle.bsl.check.EmptyExceptStatementCheck">
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.check.EmptyExceptStatementCheck">
</check>
<check
category="com.e1c.v8codestyle.bsl"
@@ -106,12 +112,10 @@
category="com.e1c.v8codestyle.bsl.strict"
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.strict.check.FunctionReturnTypeCheck">
</check>
<!-- Disabled untill release 2021.2.6+
<check
category="com.e1c.v8codestyle.bsl.strict"
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.strict.check.FunctionCtorReturnSectionCheck">
</check>
-->
<check
category="com.e1c.v8codestyle.bsl.strict"
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.strict.check.DocCommentFieldTypeCheck">
@@ -125,9 +129,61 @@
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.check.EventHandlerBooleanParamCheck">
</check>
<check
category="com.e1c.v8codestyle.bsl"
category="com.e1c.v8codestyle.bsl.comment"
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.comment.check.DocCommentUseMinusCheck">
</check>
<check
category="com.e1c.v8codestyle.bsl.comment"
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.comment.check.CollectionTypeDefinitionCheck">
</check>
<check
category="com.e1c.v8codestyle.bsl.comment"
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.comment.check.ExportFunctionReturnSectionCheck">
</check>
<check
category="com.e1c.v8codestyle.bsl.comment"
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.comment.check.FieldDefinitionNameCheck">
</check>
<check
category="com.e1c.v8codestyle.bsl.comment"
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.comment.check.FieldDefinitionTypeCheck">
</check>
<check
category="com.e1c.v8codestyle.bsl.comment"
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.comment.check.FieldDefinitionTypeWithLinkRefCheck">
</check>
<check
category="com.e1c.v8codestyle.bsl.comment"
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.comment.check.FunctionReturnSectionCheck">
</check>
<check
category="com.e1c.v8codestyle.bsl.comment"
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.comment.check.MultilineDescriptionEndsOnDotCheck">
</check>
<check
category="com.e1c.v8codestyle.bsl.comment"
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.comment.check.MultilineDescriptionFieldSuggestionCheck">
</check>
<check
category="com.e1c.v8codestyle.bsl.comment"
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.comment.check.MultilineDescriptionParameterSuggestionCheck">
</check>
<check
category="com.e1c.v8codestyle.bsl.comment"
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.comment.check.ParametersSectionCheck">
</check>
<check
category="com.e1c.v8codestyle.bsl.comment"
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.comment.check.ProcedureReturnSectionCheck">
</check>
<check
category="com.e1c.v8codestyle.bsl.comment"
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.comment.check.RefLinkPartCheck">
</check>
<check
category="com.e1c.v8codestyle.bsl.comment"
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.comment.check.TypeDefinitionCheck">
</check>
<check
category="com.e1c.v8codestyle.bsl"
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.check.UseNonRecommendedMethodCheck">
@@ -154,15 +210,34 @@
</check>
<check
category="com.e1c.v8codestyle.bsl"
class="com.e1c.v8codestyle.bsl.check.IsInRoleCheck">
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.check.IsInRoleCheck">
</check>
<!-- Temporary disabling checks
<check category="com.e1c.v8codestyle.bsl"
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.check.UndefinedMethodCheck">
</check>
<check category="com.e1c.v8codestyle.bsl"
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.check.UndefinedFunctionCheck">
</check>
<check category="com.e1c.v8codestyle.bsl"
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.check.UndefinedVariableCheck">
</check>
-->
<check
category="com.e1c.v8codestyle.bsl"
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.check.InvocationFormEventHandlerCheck">
</check>
<check
category="com.e1c.v8codestyle.bsl"
class="com.e1c.v8codestyle.bsl.check.InvocationFormEventHandlerCheck">
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.check.NewColorCheck">
</check>
<check
category="com.e1c.v8codestyle.bsl"
class="com.e1c.v8codestyle.bsl.check.NewColorCheck">
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.check.ExportMethodInCommandFormModuleCheck">
</check>
<check
category="com.e1c.v8codestyle.bsl"
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.check.LockOutOfTryCheck">
</check>
</extension>
@@ -181,5 +256,11 @@
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.internal.bsl.StrictTypesProjectOptionProvider">
</provider>
</extension>
<extension
point="com.e1c.g5.v8.dt.check.fixes">
<fix
class="com.e1c.v8codestyle.bsl.qfix.RemoveExportFix">
</fix>
</extension>
</plugin>

View File

@@ -13,10 +13,12 @@
###############################################################################
#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/)
category.bsl.description = Проверки встроенного языка исполнения 1С:Предприятия по Старндартам разработки
category.bsl.strict.description = Проверки встроенного языка исполнения 1С:Предприятия, что каждый объект строго типизирован
category.bsl.strict.title = Система строгой типизации
category.bsl.title = Встроенный язык исполнения
category.bsl.comment.description = Проверки модели документирующего комментария метода
category.bsl.comment.title = Документирующий комментарий
category.bsl.description = Проверки встроенного языка исполнения 1С:Предприятия по Стандартам разработки
category.bsl.strict.description = Проверки встроенного языка исполнения 1С:Предприятия, что каждый объект строго типизирован
category.bsl.strict.title = Система строгой типизации
category.bsl.title = Встроенный язык исполнения
pluginName = 1С:Стандарты разработки V8 плагин Встроенного языка

View File

@@ -23,10 +23,8 @@ import java.util.Set;
import java.util.TreeSet;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.EcoreUtil2;
import org.eclipse.xtext.resource.IResourceServiceProvider;
import com._1c.g5.v8.dt.bsl.contextdef.IBslModuleContextDefService;
import com._1c.g5.v8.dt.bsl.model.BinaryExpression;
@@ -83,24 +81,24 @@ public class EventHandlerBooleanParamCheck
private static final Set<String> DEFAULT_PARAMS_TO_FALSE = Set.of("StandardProcessing", "Perform"); //$NON-NLS-1$ //$NON-NLS-2$
private BslEventsService bslEventsService;
private final BslEventsService bslEventsService;
private IBslModuleContextDefService contextDefService;
private final IBslModuleContextDefService contextDefService;
/**
* Instantiates a new event handler boolean parameter check.
*
* @param contextDefService the context definition service, cannot be {@code null}.
* @param bslEventsService the BSL events service service, cannot be {@code null}.
*/
@Inject
public EventHandlerBooleanParamCheck(IBslModuleContextDefService contextDefService)
public EventHandlerBooleanParamCheck(IBslModuleContextDefService contextDefService,
BslEventsService bslEventsService)
{
super();
this.contextDefService = contextDefService;
IResourceServiceProvider rsp =
IResourceServiceProvider.Registry.INSTANCE.getResourceServiceProvider(URI.createURI("*.bsl")); //$NON-NLS-1$
this.bslEventsService = rsp.get(BslEventsService.class);
this.bslEventsService = bslEventsService;
}
@Override

View File

@@ -0,0 +1,225 @@
/*******************************************************************************
* 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.MODULE;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.EcoreUtil2;
import com._1c.g5.v8.dt.bsl.common.IBslPreferences;
import com._1c.g5.v8.dt.bsl.model.BslPackage;
import com._1c.g5.v8.dt.bsl.model.Expression;
import com._1c.g5.v8.dt.bsl.model.Method;
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.OperatorStyleCreator;
import com._1c.g5.v8.dt.bsl.model.StringLiteral;
import com._1c.g5.v8.dt.common.StringUtils;
import com._1c.g5.v8.dt.mcore.Environmental;
import com._1c.g5.v8.dt.mcore.util.Environments;
import com._1c.g5.v8.dt.mcore.util.McoreUtil;
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;
/**
* Checks an export procedure or function was found in the command or form module.
*
* @author Artem Iliukhin
*/
public final class ExportMethodInCommandFormModuleCheck
extends BasicCheck
{
private static final String PATTERN_EXCLUDE = "^(?U)(Подключаемый|Attachable)_.*$"; //$NON-NLS-1$
private static final String TYPE_NAME = "NotifyDescription"; //$NON-NLS-1$
private static final String CHECK_ID = "export-method-in-command-form-module"; //$NON-NLS-1$
private static final String PARAMETER_NOTIFY_METHODS_EXCLUSION = "notifyDescriptionMethods"; //$NON-NLS-1$
private static final String PARAMETER_EXCLUDE_METHOD_NAME_PATTERN = "excludeModuleMethodNamePattern"; //$NON-NLS-1$
private static final String PARAMETER_CHECK_FORM_SERVER_METHODS = "checkFormServerMethods"; //$NON-NLS-1$
private static final String PARAMETER_CHECK_FORM_CLIENT_METHODS = "checkFormClientMethods"; //$NON-NLS-1$
private final IBslPreferences bslPreferences;
/**
* Instantiates a new export method in command form module check.
*
* @param bslPreferences the BSL preferences service, cannot be {@code null}.
*/
@Inject
public ExportMethodInCommandFormModuleCheck(IBslPreferences bslPreferences)
{
super();
this.bslPreferences = bslPreferences;
}
@Override
public String getCheckId()
{
return CHECK_ID;
}
@Override
protected void configureCheck(CheckConfigurer builder)
{
builder.title(Messages.ExportMethodInCommandModule_Do_not_use_export_method_in_commands_module)
.description(Messages.ExportMethodInCommandModule_Do_not_emded_export_method_in_modules_of_command_des)
.complexity(CheckComplexity.NORMAL)
.severity(IssueSeverity.MINOR)
.issueType(IssueType.WARNING)
.extension(new StandardCheckExtension(getCheckId(), BslPlugin.PLUGIN_ID))
.module()
.checkedObjectType(MODULE)
.parameter(PARAMETER_CHECK_FORM_SERVER_METHODS, Boolean.class, Boolean.TRUE.toString(),
Messages.ExportMethodInCommandFormModuleCheck_CheckServerMethodForm)
.parameter(PARAMETER_CHECK_FORM_CLIENT_METHODS, Boolean.class, Boolean.FALSE.toString(),
Messages.ExportMethodInCommandFormModuleCheck_CheckClientMethodForm)
.parameter(PARAMETER_EXCLUDE_METHOD_NAME_PATTERN, String.class, PATTERN_EXCLUDE,
Messages.ExportMethodInCommandFormModuleCheck_ExludeMethodNamePattern)
.parameter(PARAMETER_NOTIFY_METHODS_EXCLUSION, String.class, StringUtils.EMPTY,
Messages.ExportMethodInCommandFormModuleCheck_Notify_description_methods);
}
@Override
protected void check(Object object, ResultAcceptor resultAceptor, ICheckParameters parameters,
IProgressMonitor monitor)
{
Module module = (Module)object;
ModuleType type = module.getModuleType();
boolean serverMethodCheck =
parameters.getBoolean(PARAMETER_CHECK_FORM_SERVER_METHODS) && type == ModuleType.FORM_MODULE;
boolean clientMethodCheck =
parameters.getBoolean(PARAMETER_CHECK_FORM_CLIENT_METHODS) && type == ModuleType.FORM_MODULE;
boolean commandModule = type == ModuleType.COMMAND_MODULE;
if (!commandModule && !(serverMethodCheck || clientMethodCheck))
{
return;
}
Map<String, Method> exportMethods = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
for (Method method : module.allMethods())
{
if (monitor.isCanceled())
{
return;
}
if (method.isExport())
{
if (commandModule)
{
exportMethods.put(method.getName(), method);
}
else if (serverMethodCheck && clientMethodCheck)
{
exportMethods.put(method.getName(), method);
}
else if (serverMethodCheck ^ clientMethodCheck)
{
Environmental environmental = EcoreUtil2.getContainerOfType(method, Environmental.class);
Environments enivronmetsObject = environmental.environments();
Environments checkingEnvs = bslPreferences.getLoadEnvs(method)
.intersect(serverMethodCheck ? Environments.ALL_SERVERS : Environments.ALL_CLIENTS);
if (enivronmetsObject.containsAny(checkingEnvs))
{
exportMethods.put(method.getName(), method);
}
}
}
}
String parameterMethodNames = parameters.getString(PARAMETER_NOTIFY_METHODS_EXCLUSION);
if (!StringUtils.isEmpty(parameterMethodNames))
{
List<String> list = List.of(parameterMethodNames.split(",\\s*")); //$NON-NLS-1$
list.forEach(exportMethods::remove);
}
if (exportMethods.isEmpty())
{
return;
}
String excludeNamePattern = parameters.getString(PARAMETER_EXCLUDE_METHOD_NAME_PATTERN);
if (!StringUtils.isEmpty(excludeNamePattern))
{
for (Iterator<Entry<String, Method>> it = exportMethods.entrySet().iterator(); it.hasNext();)
{
Map.Entry<String, Method> entry = it.next();
if (isExcludeName(entry.getKey(), excludeNamePattern))
{
it.remove();
}
}
}
if (exportMethods.isEmpty())
{
return;
}
for (TreeIterator<EObject> iterator = module.eAllContents(); iterator.hasNext();)
{
if (monitor.isCanceled())
{
return;
}
EObject containedObject = iterator.next();
if (containedObject instanceof OperatorStyleCreator
&& TYPE_NAME.equals(McoreUtil.getTypeName(((OperatorStyleCreator)containedObject).getType())))
{
List<Expression> params = ((OperatorStyleCreator)containedObject).getParams();
if (!params.isEmpty() && params.get(0) instanceof StringLiteral)
{
StringLiteral literal = (StringLiteral)params.get(0);
List<String> lines = literal.lines(true);
if (!lines.isEmpty())
{
exportMethods.remove(lines.get(0));
if (exportMethods.isEmpty())
{
return;
}
}
}
}
}
for (Method method : exportMethods.values())
{
resultAceptor.addIssue(
Messages.ExportMethodInCommandModule_Do_not_emded_export_method_in_modules_of_command_result, method,
BslPackage.Literals.METHOD__EXPORT);
}
}
private boolean isExcludeName(String name, String excludeNamePattern)
{
return StringUtils.isNotEmpty(excludeNamePattern) && name.matches(excludeNamePattern);
}
}

View File

@@ -65,8 +65,8 @@ public final class InvocationFormEventHandlerCheck
builder.title(Messages.InvocationFormEventHandlerCheck_Program_invocation_of_form_event_handler_title)
.description(Messages.InvocationFormEventHandlerCheck_Program_invocation_of_form_event_handler_description)
.complexity(CheckComplexity.NORMAL)
.severity(IssueSeverity.MAJOR)
.issueType(IssueType.WARNING)
.severity(IssueSeverity.TRIVIAL)
.issueType(IssueType.CODE_STYLE)
.extension(new StandardCheckExtension(getCheckId(), BslPlugin.PLUGIN_ID))
.module()
.checkedObjectType(INVOCATION);

View File

@@ -26,8 +26,11 @@ import com._1c.g5.v8.dt.bsl.model.StringLiteral;
import com._1c.g5.v8.dt.bsl.model.util.BslUtil;
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;
/**
* Checking the use of the IsInRole method that is not recommended.
@@ -35,7 +38,7 @@ import com.e1c.g5.v8.dt.check.settings.IssueType;
* @author Artem Iliukhin
*/
public class IsInRoleCheck
extends AbstractModuleStructureCheck
extends BasicCheck
{
private static final String EXCEPTION_ROLES_PARAM = "exceptionRoles"; //$NON-NLS-1$
@@ -63,6 +66,7 @@ public class IsInRoleCheck
.complexity(CheckComplexity.NORMAL)
.severity(IssueSeverity.MINOR)
.issueType(IssueType.WARNING)
.extension(new StandardCheckExtension(getCheckId(), BslPlugin.PLUGIN_ID))
.module()
.checkedObjectType(STATIC_FEATURE_ACCESS)
.parameter(EXCEPTION_ROLES_PARAM, String.class, DEFAULT_EXCEPTION_ROLES_PARAM,

View File

@@ -0,0 +1,188 @@
/*******************************************************************************
* 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.DYNAMIC_FEATURE_ACCESS;
import java.util.List;
import java.util.Objects;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.EcoreUtil2;
import com._1c.g5.v8.dt.bsl.contextdef.IBslModuleContextDefService;
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.Method;
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.TryExceptStatement;
import com._1c.g5.v8.dt.bsl.model.util.BslUtil;
import com._1c.g5.v8.dt.bsl.resource.BslEventsService;
import com._1c.g5.v8.dt.bsl.resource.TypesComputer;
import com._1c.g5.v8.dt.lcore.util.CaseInsensitiveString;
import com._1c.g5.v8.dt.mcore.Environmental;
import com._1c.g5.v8.dt.mcore.Event;
import com._1c.g5.v8.dt.mcore.TypeItem;
import com._1c.g5.v8.dt.mcore.util.McoreUtil;
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;
/**
* Checks for initialization of the data lock. If the creation of a lock is found, the call of the Lock() method is
* checked, and the call must be in a try.
*
* @author Artem Iliukhin
*/
public final class LockOutOfTryCheck
extends BasicCheck
{
private static final List<String> EXLUDED_EVENTS =
List.of("BeforeDelete", "BeforeWrite", "OnWrite", "BeforeDelete", "OnWriteAtServer", "Posting"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
private static final String CHECK_ID = "lock-out-of-try"; //$NON-NLS-1$
private static final String NAME_DATA_LOCK = "DataLock"; //$NON-NLS-1$
private static final String NAME_LOCK = "Lock"; //$NON-NLS-1$
private static final String NAME_LOCK_RU = "Заблокировать"; //$NON-NLS-1$
private final TypesComputer typesComputer;
private BslEventsService bslEventsService;
private IBslModuleContextDefService contextDefService;
/**
* Instantiates a new lock out of try check.
*
* @param contextDefService the context def service, cannot be {@code null}
* @param typesComputer the types computer service, cannot be {@code null}
* @param bslEventsService the BSL events service, cannot be {@code null}
*/
@Inject
public LockOutOfTryCheck(IBslModuleContextDefService contextDefService, TypesComputer typesComputer,
BslEventsService bslEventsService)
{
super();
this.contextDefService = contextDefService;
this.bslEventsService = bslEventsService;
this.typesComputer = typesComputer;
}
@Override
public String getCheckId()
{
return CHECK_ID;
}
@Override
protected void configureCheck(CheckConfigurer builder)
{
builder.title(Messages.LockOutOfTry_Lock_out_of_try)
.description(Messages.LockOutOfTry_Checks_for_init_of_the_data_lock)
.complexity(CheckComplexity.NORMAL)
.severity(IssueSeverity.MINOR)
.issueType(IssueType.WARNING)
.extension(new StandardCheckExtension(getCheckId(), BslPlugin.PLUGIN_ID))
.module()
.checkedObjectType(DYNAMIC_FEATURE_ACCESS);
}
@Override
protected void check(Object object, ResultAcceptor resultAceptor, ICheckParameters parameters,
IProgressMonitor monitor)
{
DynamicFeatureAccess dynamicFeatureAccess = (DynamicFeatureAccess)object;
String name = dynamicFeatureAccess.getName();
if (BslUtil.getInvocation(dynamicFeatureAccess) == null
|| !NAME_LOCK.equalsIgnoreCase(name) && !NAME_LOCK_RU.equalsIgnoreCase(name))
{
return;
}
Expression source = dynamicFeatureAccess.getSource();
Environmental env = EcoreUtil2.getContainerOfType(source, Environmental.class);
if (Objects.isNull(env))
{
return;
}
Method method = EcoreUtil2.getContainerOfType(source, Method.class);
if (monitor.isCanceled() || method == null)
{
return;
}
Module module = EcoreUtil2.getContainerOfType(method, Module.class);
if (monitor.isCanceled())
{
return;
}
if (isExcluded(module, method))
{
return;
}
List<TypeItem> types = typesComputer.computeTypes(source, env.environments());
for (TypeItem type : types)
{
if (NAME_DATA_LOCK.equals(McoreUtil.getTypeName(type))
&& Objects.isNull(EcoreUtil2.getContainerOfType(source, TryExceptStatement.class)))
{
resultAceptor.addIssue(Messages.LockOutOfTry_Method_lock_out_of_try, object);
}
}
}
private boolean isExcluded(Module module, Method method)
{
CaseInsensitiveString methodName = new CaseInsensitiveString(method.getName());
if (module.getModuleType() == ModuleType.FORM_MODULE)
{
List<EObject> eventHandlers = bslEventsService.getEventHandlers(module).get(methodName);
if (!Objects.isNull(eventHandlers) && !eventHandlers.isEmpty())
{
for (EObject handler : eventHandlers)
{
if (handler instanceof Event && (EXLUDED_EVENTS.contains(((Event)handler).getName())))
{
return true;
}
}
}
}
else if (module.getModuleType() == ModuleType.OBJECT_MODULE)
{
List<Event> moduleEvents = contextDefService.getModuleEvents(module);
for (Event event : moduleEvents)
{
if (EXLUDED_EVENTS.contains(event.getName()))
{
CaseInsensitiveString name = new CaseInsensitiveString(event.getName());
CaseInsensitiveString nameRu = new CaseInsensitiveString(event.getNameRu());
if (name.equals(methodName) || nameRu.equals(methodName))
{
return true;
}
}
}
}
return false;
}
}

View File

@@ -16,8 +16,9 @@ package com.e1c.v8codestyle.bsl.check;
import org.eclipse.osgi.util.NLS;
/**
* @author Dmitriy Marmyshev
* NLS messages
*
* @author Dmitriy Marmyshev
*/
final class Messages
extends NLS
@@ -69,6 +70,20 @@ final class Messages
public static String EventHandlerBooleanParamCheck_title;
public static String ExportMethodInCommandFormModuleCheck_CheckClientMethodForm;
public static String ExportMethodInCommandFormModuleCheck_CheckServerMethodForm;
public static String ExportMethodInCommandFormModuleCheck_ExludeMethodNamePattern;
public static String ExportMethodInCommandFormModuleCheck_Notify_description_methods;
public static String ExportMethodInCommandModule_Do_not_emded_export_method_in_modules_of_command_des;
public static String ExportMethodInCommandModule_Do_not_emded_export_method_in_modules_of_command_result;
public static String ExportMethodInCommandModule_Do_not_use_export_method_in_commands_module;
public static String ModuleStructureTopRegionCheck_description;
public static String ModuleStructureTopRegionCheck_error_message;
@@ -186,6 +201,22 @@ final class Messages
public static String IsInRoleCheck_Using_IsInRole;
public static String ModuleUndefinedVariableCheck_Title;
public static String ModuleUndefinedVariableCheck_Description;
public static String ModuleUndefinedVariable_msg;
public static String ModuleUndefinedMethodCheck_Title;
public static String ModuleUndefinedMethodCheck_Description;
public static String ModuleUndefinedFunctionCheck_Title;
public static String ModuleUndefinedFunctionCheck_Description;
public static String ModuleUndefinedFunction_msg;
public static String ModuleUndefinedMethod_msg;
public static String LockOutOfTry_Checks_for_init_of_the_data_lock;
public static String LockOutOfTry_Lock_out_of_try;
public static String LockOutOfTry_Method_lock_out_of_try;
static
{
// initialize resource bundle
@@ -194,5 +225,6 @@ final class Messages
private Messages()
{
// N/A
}
}

View File

@@ -20,11 +20,9 @@ import java.util.Map;
import java.util.stream.Collectors;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.EcoreUtil2;
import org.eclipse.xtext.nodemodel.INode;
import org.eclipse.xtext.resource.IResourceServiceProvider;
import com._1c.g5.v8.dt.bsl.common.VariableProcessor;
import com._1c.g5.v8.dt.bsl.model.Block;
@@ -49,6 +47,7 @@ import com.e1c.g5.v8.dt.check.settings.IssueType;
import com.e1c.v8codestyle.check.CommonSenseCheckExtension;
import com.e1c.v8codestyle.internal.bsl.BslPlugin;
import com.google.common.collect.Lists;
import com.google.inject.Inject;
/**
* Unused module local variable check.
@@ -66,15 +65,18 @@ public final class ModuleUnusedLocalVariableCheck
/**
* Instantiates a new module unused local variable check.
*
* @param dynamicComputer the dynamic computer service, cannot be {@code null}
* @param ownerService the owner service service, cannot be {@code null}
*/
public ModuleUnusedLocalVariableCheck()
@Inject
public ModuleUnusedLocalVariableCheck(DynamicFeatureAccessComputer dynamicComputer,
IBslOwnerComputerService ownerService)
{
super();
IResourceServiceProvider serviceProvider =
IResourceServiceProvider.Registry.INSTANCE.getResourceServiceProvider(URI.createURI("*.bsl")); //$NON-NLS-1$
dynamicComputer = serviceProvider.get(DynamicFeatureAccessComputer.class);
ownerService = serviceProvider.get(IBslOwnerComputerService.class);
this.dynamicComputer = dynamicComputer;
this.ownerService = ownerService;
}
@Override

View File

@@ -23,7 +23,6 @@ import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.xtext.EcoreUtil2;
import org.eclipse.xtext.resource.IResourceServiceProvider;
import com._1c.g5.v8.dt.bsl.model.DynamicFeatureAccess;
import com._1c.g5.v8.dt.bsl.model.Expression;
@@ -50,6 +49,7 @@ import com.e1c.g5.v8.dt.check.settings.IssueSeverity;
import com.e1c.g5.v8.dt.check.settings.IssueType;
import com.e1c.v8codestyle.check.CommonSenseCheckExtension;
import com.e1c.v8codestyle.internal.bsl.BslPlugin;
import com.google.inject.Inject;
/**
* Check that notify description procedure is exist and available at the client.
@@ -78,16 +78,17 @@ public class NotifyDescriptionToServerProcedureCheck
/**
* Instantiates a new notify description to server procedure check.
*
* @param dynamicFeatureAccessComputer the dynamic feature access computer service, cannot be {@code null}
* @param exportMethodProvider the export method provider service, cannot be {@code null}
*/
public NotifyDescriptionToServerProcedureCheck()
@Inject
public NotifyDescriptionToServerProcedureCheck(DynamicFeatureAccessComputer dynamicFeatureAccessComputer,
ExportMethodProvider exportMethodProvider)
{
super();
IResourceServiceProvider rsp =
IResourceServiceProvider.Registry.INSTANCE.getResourceServiceProvider(URI.createURI("*.bsl")); //$NON-NLS-1$
this.dynamicFeatureAccessComputer = rsp.get(DynamicFeatureAccessComputer.class);
this.exportMethodProvider = rsp.get(ExportMethodProvider.class);
this.dynamicFeatureAccessComputer = dynamicFeatureAccessComputer;
this.exportMethodProvider = exportMethodProvider;
}
@Override

View File

@@ -27,13 +27,11 @@ import java.util.TreeSet;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.xtext.EcoreUtil2;
import org.eclipse.xtext.nodemodel.ICompositeNode;
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
import org.eclipse.xtext.resource.IResourceServiceProvider;
import com._1c.g5.v8.dt.bsl.model.BooleanLiteral;
import com._1c.g5.v8.dt.bsl.model.DynamicFeatureAccess;
@@ -89,17 +87,17 @@ public class QueryInLoopCheck
private final IRuntimeVersionSupport versionSupport;
/**
* Instantiates a new query in loop check.
*
* @param versionSupport - Version support for 1C:Enterprise projects service, cannot be {@code null}
* @param typesComputer the types computer service, cannot be {@code null}
*/
@Inject
public QueryInLoopCheck(IRuntimeVersionSupport versionSupport)
public QueryInLoopCheck(IRuntimeVersionSupport versionSupport, TypesComputer typesComputer)
{
super();
IResourceServiceProvider rsp =
IResourceServiceProvider.Registry.INSTANCE.getResourceServiceProvider(URI.createURI("*.bsl")); //$NON-NLS-1$
typesComputer = rsp.get(TypesComputer.class);
this.typesComputer = typesComputer;
this.versionSupport = versionSupport;
}

View File

@@ -0,0 +1,82 @@
/*******************************************************************************
* 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 org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.osgi.util.NLS;
import com._1c.g5.v8.dt.bsl.model.BslPackage;
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.StaticFeatureAccess;
import com._1c.g5.v8.dt.bsl.model.util.BslUtil;
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;
/**
* Check for undefined function or procedure in module
*
* @author Vadim Geraskin
*/
public class UndefinedFunctionCheck
extends BasicCheck
{
private static final String CHECK_ID = "module-undefined-function"; //$NON-NLS-1$
@Override
public String getCheckId()
{
return CHECK_ID;
}
@Override
protected void check(Object object, ResultAcceptor resultAcceptor, ICheckParameters parameters,
IProgressMonitor progressMonitor)
{
if (progressMonitor.isCanceled())
{
return;
}
Invocation invocation = (Invocation)object;
if (invocation != null)
{
FeatureAccess fa = invocation.getMethodAccess();
if (fa instanceof StaticFeatureAccess)
{
String name = fa.getName();
String msg;
if (((StaticFeatureAccess)fa).getImplicitVariable() == null
&& !BslUtil.isProcedureInvocation(invocation))
{
msg = NLS.bind(Messages.ModuleUndefinedFunction_msg, name);
resultAcceptor.addIssue(msg, fa);
}
}
}
}
@Override
protected void configureCheck(CheckConfigurer configurationBuilder)
{
configurationBuilder.title(Messages.ModuleUndefinedFunctionCheck_Title)
.description(Messages.ModuleUndefinedFunctionCheck_Description)
.complexity(CheckComplexity.NORMAL)
.severity(IssueSeverity.MAJOR)
.issueType(IssueType.ERROR)
.module()
.checkedObjectType(BslPackage.Literals.INVOCATION);
}
}

View File

@@ -0,0 +1,78 @@
/*******************************************************************************
* 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 org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.osgi.util.NLS;
import com._1c.g5.v8.dt.bsl.model.BslPackage;
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.StaticFeatureAccess;
import com._1c.g5.v8.dt.bsl.model.util.BslUtil;
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;
/**
* Check for undefined function or procedure in module
*
* @author Vadim Geraskin
*/
public class UndefinedMethodCheck
extends BasicCheck
{
private static final String CHECK_ID = "module-undefined-method"; //$NON-NLS-1$
@Override
public String getCheckId()
{
return CHECK_ID;
}
@Override
protected void check(Object object, ResultAcceptor resultAcceptor, ICheckParameters parameters,
IProgressMonitor progressMonitor)
{
if (progressMonitor.isCanceled())
{
return;
}
Invocation invocation = (Invocation)object;
FeatureAccess fa = invocation.getMethodAccess();
if (fa instanceof StaticFeatureAccess)
{
String name = fa.getName();
String msg;
if (((StaticFeatureAccess)fa).getImplicitVariable() == null && BslUtil.isProcedureInvocation(invocation))
{
msg = NLS.bind(Messages.ModuleUndefinedMethod_msg, name);
resultAcceptor.addIssue(msg, fa);
}
}
}
@Override
protected void configureCheck(CheckConfigurer configurationBuilder)
{
configurationBuilder.title(Messages.ModuleUndefinedMethodCheck_Title)
.description(Messages.ModuleUndefinedMethodCheck_Description)
.complexity(CheckComplexity.NORMAL)
.severity(IssueSeverity.MAJOR)
.issueType(IssueType.ERROR)
.module()
.checkedObjectType(BslPackage.Literals.INVOCATION);
}
}

View File

@@ -0,0 +1,133 @@
/*******************************************************************************
* 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 java.util.Arrays;
import java.util.stream.Collectors;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.osgi.util.NLS;
import org.eclipse.xtext.EcoreUtil2;
import com._1c.g5.v8.dt.bsl.model.BslPackage;
import com._1c.g5.v8.dt.bsl.model.FeatureEntry;
import com._1c.g5.v8.dt.bsl.model.Invocation;
import com._1c.g5.v8.dt.bsl.model.Method;
import com._1c.g5.v8.dt.bsl.model.StaticFeatureAccess;
import com._1c.g5.v8.dt.bsl.model.util.BslUtil;
import com._1c.g5.v8.dt.bsl.validation.BslPreferences;
import com._1c.g5.v8.dt.mcore.util.Environment;
import com._1c.g5.v8.dt.mcore.util.Environments;
import com._1c.g5.v8.dt.mcore.util.McoreUtil;
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;
/**
* Check for undefined variable in bsl module
*
* @author Vadim Geraskin
*/
public class UndefinedVariableCheck
extends BasicCheck
{
private static final String CHECK_ID = "module-undefined-variable"; //$NON-NLS-1$
@Override
public String getCheckId()
{
return CHECK_ID;
}
@Override
protected void check(Object object, ResultAcceptor resultAcceptor, ICheckParameters parameters,
IProgressMonitor progressMonitor)
{
if (progressMonitor.isCanceled())
{
return;
}
StaticFeatureAccess fa = (StaticFeatureAccess)object;
if (fa.eContainer() instanceof Invocation || fa.getImplicitVariable() == null)
{
return;
}
String varName = fa.getName();
String msg = NLS.bind(Messages.ModuleUndefinedVariable_msg, varName);
if (!fa.getFeatureEntries().isEmpty())
{
if (allStatementsAreDeclare(fa, varName))
{
return;
}
FeatureEntry entry = fa.getFeatureEntries().get(0);
Environments envs = getEnv(entry);
Invocation invocation = BslUtil.getInvocation(entry);
if (invocation == null && !BslUtil.isEventHandler(entry))
{
msg += " [" + Arrays.stream(envs.toArray()) //$NON-NLS-1$
.map(McoreUtil::getEnvironmentText)
.collect(Collectors.joining(", ")) //$NON-NLS-1$
+ ']';
}
else
{
return;
}
}
resultAcceptor.addIssue(msg, fa);
}
@Override
protected void configureCheck(CheckConfigurer configurationBuilder)
{
configurationBuilder.title(Messages.ModuleUndefinedVariableCheck_Title)
.description(Messages.ModuleUndefinedVariableCheck_Description)
.complexity(CheckComplexity.NORMAL)
.severity(IssueSeverity.MAJOR)
.issueType(IssueType.ERROR)
.module()
.checkedObjectType(BslPackage.Literals.STATIC_FEATURE_ACCESS);
}
private static boolean allStatementsAreDeclare(StaticFeatureAccess fa, String varName)
{
Method method = EcoreUtil2.getContainerOfType(fa, Method.class);
return method.allDeclareStatements()
.stream()
.flatMap(ds -> ds.getVariables().stream())
.anyMatch(v -> v.getName().equals(varName));
}
private static Environments getEnv(FeatureEntry entry)
{
Environments envs = new Environments(entry.getEnvironments().toArray());
if (entry.eContainer() instanceof StaticFeatureAccess && envs.contains(Environment.MNG_CLIENT)
&& !envs.contains(Environment.SERVER) && !BslPreferences.detectIsClientServer(entry))
{
StaticFeatureAccess sfa = (StaticFeatureAccess)entry.eContainer();
if (sfa.getFeatureEntries()
.stream()
.anyMatch(item -> item != entry && item.getEnvironments().contains(Environment.SERVER)))
{
envs = envs.remove(Environment.MNG_CLIENT);
}
}
return envs;
}
}

View File

@@ -1,7 +1,7 @@
#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/)
###############################################################################
# Copyright (C) 2021, 1C-Soft LLC and others.
# Copyright (C) 2021-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
@@ -70,6 +70,17 @@ EventHandlerBooleanParamCheck_description = Use event handler boolean parameter
EventHandlerBooleanParamCheck_title = Use event handler boolean parameter
ExportMethodInCommandFormModuleCheck_CheckClientMethodForm=Check the client method of the form
ExportMethodInCommandFormModuleCheck_CheckServerMethodForm=Check the server method of the form
ExportMethodInCommandFormModuleCheck_ExludeMethodNamePattern=Exclude method name pattern
ExportMethodInCommandFormModuleCheck_Notify_description_methods=Comma-separated list of excluded notification method names
ExportMethodInCommandModule_Do_not_emded_export_method_in_modules_of_command_des=Do not embed export procedures and functions in modules of commands and forms. You cannot address such modules from external code, so embedded export procedures and functions become dysfunctional.
ExportMethodInCommandModule_Do_not_emded_export_method_in_modules_of_command_result=Do not embed export procedures and functions in modules of commands and forms. You cannot address such modules from external code, so embedded export procedures and functions become dysfunctional.
ExportMethodInCommandModule_Do_not_use_export_method_in_commands_module=Restrictions on the use of export procedures and functions
FormModuleMissingPragmaCheck_Missing_compilation_directives = Missing compilation directives
FormModuleMissingPragmaCheck_description = Always use compilation pragma in form module
@@ -96,6 +107,12 @@ IsInRoleCheck_Use_AccessRight_instead_IsInRole=Use the AccessRight() function in
IsInRoleCheck_Using_IsInRole=Using "IsInRole" method
LockOutOfTry_Checks_for_init_of_the_data_lock=Checks for initialization of the data lock. If the creation of a lock is found, the call of the Lock() method is checked, and the call must be in a try.
LockOutOfTry_Lock_out_of_try=Lock out of Try
LockOutOfTry_Method_lock_out_of_try=Method Lock() out of try block
MethodTooManyPramsCheck_Max_parameters = Max parameters
MethodTooManyPramsCheck_Max_parameters_with_default_value = Max parameters with default value
@@ -203,3 +220,15 @@ UseNonRecommendedMethods_message = Using non-recommended method
UseNonRecommendedMethods_parameter = List of non-recommended methods
UseNonRecommendedMethods_title = Using non-recommended methods
ModuleUndefinedVariableCheck_Title = Undefined variable
ModuleUndefinedVariableCheck_Description = Undefined variable
ModuleUndefinedVariable_msg = Variable "{0}" is not defined
ModuleUndefinedMethodCheck_Title = Undefined method
ModuleUndefinedMethodCheck_Description = Undefined function or procedure
ModuleUndefinedFunctionCheck_Title = Undefined function
ModuleUndefinedFunctionCheck_Description = Undefined function
ModuleUndefinedFunction_msg = Function "{0}" is not defined
ModuleUndefinedMethod_msg = Procedure or function "{0}" is not defined

View File

@@ -1,6 +1,6 @@
#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/)
###############################################################################
# Copyright (C) 2021, 1C-Soft LLC and others.
# Copyright (C) 2021-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
@@ -70,6 +70,20 @@ EventHandlerBooleanParamCheck_description = Использование буле
EventHandlerBooleanParamCheck_title = Использование булевого параметра обработчика события
ExportMethodInCommandFormModuleCheck_CheckClientMethodForm=Проверить клиентский метод формы
ExportMethodInCommandFormModuleCheck_CheckServerMethodForm=Проверить серверный метод формы
ExportMethodInCommandFormModuleCheck_ExludeMethodNamePattern=Шаблон исключаемых имен методов
ExportMethodInCommandFormModuleCheck_Notify_description_methods=Список исключаемых имен методов оповещения, разделенные запятой
ExportMethodInCommandModule_Do_not_emded_export_method_in_modules_of_command_des=Не следует размещать экспортные процедуры и функции в модулях команд и форм. К этим модулям нет возможности обращаться из внешнего по отношению к ним кода, поэтому экспортные процедуры и функции в этих модулях не имеют смысла.
ExportMethodInCommandModule_Do_not_emded_export_method_in_modules_of_command_result=Не следует размещать экспортные процедуры и функции в модулях команд и форм. К этим модулям нет возможности обращаться из внешнего по отношению к ним кода, поэтому экспортные процедуры и функции в этих модулях не имеют смысла.
ExportMethodInCommandModule_Do_not_use_export_method_in_commands_module=Ограничения на использование экспортных процедур и функций
FormModuleMissingPragmaCheck_Missing_compilation_directives = Пропущена директива компиляции
FormModuleMissingPragmaCheck_description = Всегда использовать директивы компиляции в модуле формы
@@ -96,6 +110,12 @@ IsInRoleCheck_Using_IsInRole = Использован не рекомендов
IsInRoleCheck_Use_AccessRight_instead_IsInRole = Используйте функцию "ПравоДоступа()" вместо "РольДоступна()"
LockOutOfTry_Checks_for_init_of_the_data_lock=Правило проверяет наличие инициализации блокировки данных. В случае если найдено создание блокировки, проверяется вызов метода "Заблокировать()", при этом вызов должен быть в попытке.
LockOutOfTry_Lock_out_of_try=Метод Заблокировать() вне блока Попытка-Исключение
LockOutOfTry_Method_lock_out_of_try=Метод Заблокировать() вне блока Попытка-Исключение
MethodTooManyPramsCheck_Max_parameters = Максимум параметров
MethodTooManyPramsCheck_Max_parameters_with_default_value = Максимум параметров со значением по умолчанию
@@ -203,3 +223,14 @@ UseNonRecommendedMethods_message = Используется не рекомен
UseNonRecommendedMethods_parameter = Список дополнительных не рекомендуемых методов для проверки
UseNonRecommendedMethods_title = Использование не рекомендуемых методов
ModuleUndefinedVariableCheck_Title = Переменная не определена
ModuleUndefinedVariableCheck_Description = Переменная не определена
ModuleUndefinedVariable_msg = Переменная "{0}" не определена
ModuleUndefinedMethodCheck_Title = Метод не определен
ModuleUndefinedMethodCheck_Description = Функция или процедура не определена
ModuleUndefinedFunctionCheck_Title = Функция не определена
ModuleUndefinedFunctionCheck_Description = Функция не определена
ModuleUndefinedFunction_msg = Функция "{0}" не определена
ModuleUndefinedMethod_msg = Процедура или функция "{0}" не определена

View File

@@ -0,0 +1,190 @@
/*******************************************************************************
* 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.comment.check;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.scoping.IScopeProvider;
import com._1c.g5.v8.dt.bsl.documentation.comment.BslDocumentationComment.Description;
import com._1c.g5.v8.dt.bsl.documentation.comment.IBslCommentToken;
import com._1c.g5.v8.dt.bsl.documentation.comment.IDescriptionPart;
import com._1c.g5.v8.dt.bsl.documentation.comment.LinkPart;
import com._1c.g5.v8.dt.bsl.documentation.comment.TextPart;
import com._1c.g5.v8.dt.bsl.documentation.comment.TypeSection;
import com._1c.g5.v8.dt.bsl.documentation.comment.TypeSection.FieldDefinition;
import com._1c.g5.v8.dt.bsl.documentation.comment.TypeSection.TypeDefinition;
import com._1c.g5.v8.dt.bsl.model.FormalParam;
import com._1c.g5.v8.dt.bsl.model.Function;
import com._1c.g5.v8.dt.bsl.resource.TypesComputer;
import com._1c.g5.v8.dt.common.StringUtils;
import com._1c.g5.v8.dt.mcore.Method;
import com._1c.g5.v8.dt.mcore.Parameter;
import com._1c.g5.v8.dt.mcore.Property;
import com._1c.g5.v8.dt.mcore.TypeItem;
import com.e1c.g5.v8.dt.bsl.check.DocumentationCommentBasicDelegateCheck;
/**
* Abstract check documentation comment model when needs to process types.
*
* @author Dmitriy Marmyshev
*/
public abstract class AbstractDocCommentTypeCheck
extends DocumentationCommentBasicDelegateCheck
{
/**
* Gets the link part from description only if the link is single element of the description.
* This method skips empty text parts.
*
* @param description the description, cannot be {@link null}.
* @return the single link part or returns {@code null} if no link or there are other parts in description.
*/
protected LinkPart getSingleLinkPart(Description description)
{
List<IDescriptionPart> parts = description.getParts();
List<LinkPart> linkParts = new ArrayList<>(parts.size());
int lastLine = -1;
for (IDescriptionPart part : parts)
{
if (part instanceof LinkPart && lastLine != part.getLineNumber())
{
linkParts.add((LinkPart)part);
lastLine = part.getLineNumber();
}
else if (!isCanSkipEmptyTextPart(part, lastLine))
{
return null;
}
}
return linkParts.size() == 1 ? linkParts.get(0) : null;
}
/**
* Checks if the part is {@link TextPart} and can be skipped because it contains only ending symbols - dot or dash.
*
* @param part the part, cannot be {@link null}.
* @param lastLine the last line, cannot be {@link null}.
* @return true, if is can skip empty text part
*/
protected boolean isCanSkipEmptyTextPart(IDescriptionPart part, int lastLine)
{
if (part instanceof TextPart)
{
String text = ((TextPart)part).getText();
if (text != null && (".".equals(text.trim()) //$NON-NLS-1$
|| IBslCommentToken.TYPE_SECTION_DASH.equals(text.trim()) && lastLine != part.getLineNumber()))
{
return true;
}
}
return false;
}
/**
* Checks if the field types are empty.
*
* @param fieldDef the field definition, cannot be {@link null}.
* @return true, if the field type is empty
*/
protected boolean isFieldTypeEmpty(FieldDefinition fieldDef)
{
List<TypeSection> typeSections = fieldDef.getTypeSections();
Description description = fieldDef.getDescription();
return isTypeEmptyAndNoLink(typeSections, description);
}
/**
* Checks if the type is empty and no link in description.
*
* @param typeSections the type sections, cannot be {@link null}.
* @param description the description, cannot be {@link null}.
* @return true, if the type is empty and no link in description.
*/
protected boolean isTypeEmptyAndNoLink(List<TypeSection> typeSections, Description description)
{
if (typeSections.isEmpty())
{
return getSingleLinkPart(description) == null;
}
for (TypeSection typeSection : typeSections)
{
for (TypeDefinition typeDef : typeSection.getTypeDefinitions())
{
if (StringUtils.isNotEmpty(typeDef.getTypeName()))
{
return false;
}
}
}
return true;
}
/**
* Gets the last referenced object of the link part.
*
* @param linkPart the link part, cannot be {@link null}.
* @param scopeProvider the scope provider, cannot be {@link null}.
* @param context the context, cannot be {@link null}.
* @return the last object of link part
*/
protected Optional<EObject> getLinkPartLastObject(LinkPart linkPart, IScopeProvider scopeProvider, EObject context)
{
// get object of last segment of the link to method/parameter,
// without final brackets "(See ModuleName.MethodName.)".
if (linkPart.getInitialContent().startsWith("(") //$NON-NLS-1$
&& linkPart.getPartsWithOffset().size() > 1
&& (linkPart.getPartsWithOffset().get(linkPart.getPartsWithOffset().size() - 1)).getFirst().isEmpty())
{
return Optional.ofNullable(
linkPart.getActualObjectForPart(linkPart.getPartsWithOffset().size() - 2, scopeProvider, context));
}
else
{
return Optional.ofNullable(
linkPart.getActualObjectForPart(linkPart.getPartsWithOffset().size() - 1, scopeProvider, context));
}
}
/**
* Checks if the link part referenced to the existing object with return types.
* Note that here may be not all the object with return types.
* Use {@link #getLinkPartLastObject(LinkPart, IScopeProvider, EObject)} instead to check link exit or
* compute parameter type via {@link TypesComputer} or methods of doc-comment model.
*
* @param linkPart the link part, cannot be {@link null}.
* @param scopeProvider the scope provider, cannot be {@link null}.
* @param context the context, cannot be {@link null}.
* @return true, if the object of link part is exist
*/
protected boolean isLinkPartObjectExist(LinkPart linkPart, IScopeProvider scopeProvider, EObject context)
{
Optional<EObject> optional = getLinkPartLastObject(linkPart, scopeProvider, context);
if (optional.isPresent())
{
EObject object = optional.get();
return object instanceof Method || object instanceof Function || object instanceof Parameter
|| object instanceof FormalParam || object instanceof TypeItem || object instanceof Property;
}
return false;
}
}

View File

@@ -0,0 +1,113 @@
/*******************************************************************************
* 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.comment.check;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import org.eclipse.core.runtime.IProgressMonitor;
import com._1c.g5.v8.dt.bsl.documentation.comment.BslDocumentationComment;
import com._1c.g5.v8.dt.bsl.documentation.comment.IDescriptionPart;
import com._1c.g5.v8.dt.bsl.documentation.comment.TypeSection.LinkContainsTypeDefinition;
import com._1c.g5.v8.dt.bsl.documentation.comment.TypeSection.TypeDefinition;
import com._1c.g5.v8.dt.common.StringUtils;
import com._1c.g5.v8.dt.platform.IEObjectTypeNames;
import com.e1c.g5.v8.dt.bsl.check.DocumentationCommentBasicDelegateCheck;
import com.e1c.g5.v8.dt.check.CheckComplexity;
import com.e1c.g5.v8.dt.check.ICheckParameters;
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;
/**
* Check type definition that collection type (like array, map etc.) has type of contain item.
*
* @author Dmitriy Marmyshev
*/
public class CollectionTypeDefinitionCheck
extends DocumentationCommentBasicDelegateCheck
{
private static final String CHECK_ID = "doc-comment-collection-item-type"; //$NON-NLS-1$
private static final String PARAMETER_COLLECTION_TYPES = "collectionTypes"; //$NON-NLS-1$
private static final String TYPE_DELIMITER = ","; //$NON-NLS-1$
//@formatter:off
private static final String DEFAULT_COLLECTION_TYPES = String.join(TYPE_DELIMITER, Set.of(
IEObjectTypeNames.ARRAY, "Массив", //$NON-NLS-1$
IEObjectTypeNames.FIXED_ARRAY, "ФиксированныйМассив", //$NON-NLS-1$
IEObjectTypeNames.MAP, "Соответствие", //$NON-NLS-1$
IEObjectTypeNames.FIXED_MAP, "ФиксированноеСоответствие", //$NON-NLS-1$
IEObjectTypeNames.VALUE_LIST, "СписокЗначений", //$NON-NLS-1$
"FixedCollection", "ФиксированнаяКоллекция")); //$NON-NLS-1$ //$NON-NLS-2$
//@formatter:on
@Override
public String getCheckId()
{
return CHECK_ID;
}
@Override
protected void configureCheck(CheckConfigurer builder)
{
builder.title(Messages.CollectionTypeDefinitionCheck_title)
.description(Messages.CollectionTypeDefinitionCheck_description)
.complexity(CheckComplexity.NORMAL)
.severity(IssueSeverity.MINOR)
.issueType(IssueType.CODE_STYLE)
.extension(new StandardCheckExtension(getCheckId(), BslPlugin.PLUGIN_ID))
.delegate(TypeDefinition.class);
builder.parameter(PARAMETER_COLLECTION_TYPES, String.class, DEFAULT_COLLECTION_TYPES,
Messages.CollectionTypeDefinitionCheck_Collection_types);
}
@Override
protected void checkDocumentationCommentObject(IDescriptionPart object, BslDocumentationComment root,
DocumentationCommentResultAcceptor resultAceptor, ICheckParameters parameters, IProgressMonitor monitor)
{
if (object instanceof LinkContainsTypeDefinition)
{
return;
}
String parameterCollectionTypes = parameters.getString(PARAMETER_COLLECTION_TYPES);
if (StringUtils.isBlank(parameterCollectionTypes))
{
return;
}
TypeDefinition typeDef = (TypeDefinition)object;
String typeName = typeDef.getTypeName();
if (StringUtils.isEmpty(typeName))
{
return;
}
Set<String> types = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
String[] paramTypes = parameterCollectionTypes.split(TYPE_DELIMITER);
types.addAll(List.of(paramTypes));
if (typeDef.getContainTypes().isEmpty() && types.contains(typeName))
{
resultAceptor.addIssue(Messages.CollectionTypeDefinitionCheck_Collection_type_should_have_contain_item_type,
typeName.length());
}
}
}

View File

@@ -0,0 +1,129 @@
/*******************************************************************************
* 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.comment.check;
import static com._1c.g5.v8.dt.mcore.McorePackage.Literals.NAMED_ELEMENT__NAME;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.xtext.scoping.IScopeProvider;
import com._1c.g5.v8.dt.bsl.comment.DocumentationCommentProperties;
import com._1c.g5.v8.dt.bsl.common.IBslPreferences;
import com._1c.g5.v8.dt.bsl.documentation.comment.BslCommentUtils;
import com._1c.g5.v8.dt.bsl.documentation.comment.BslDocumentationComment;
import com._1c.g5.v8.dt.bsl.documentation.comment.BslMultiLineCommentDocumentationProvider;
import com._1c.g5.v8.dt.bsl.documentation.comment.IDescriptionPart;
import com._1c.g5.v8.dt.bsl.documentation.comment.LinkPart;
import com._1c.g5.v8.dt.bsl.model.Function;
import com._1c.g5.v8.dt.core.platform.IResourceLookup;
import com.e1c.g5.v8.dt.check.CheckComplexity;
import com.e1c.g5.v8.dt.check.ICheckParameters;
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;
/**
* Validator of export function that has return section in documentation comment if function has anything
* in documentation comment. If function has link to some other function this means documentation inherits and
* validator checks documentation comment of linked function. Otherwise this function should have return section.
*
* @author Dmitriy Marmyshev
*/
public class ExportFunctionReturnSectionCheck
extends AbstractDocCommentTypeCheck
{
private static final String CHECK_ID = "doc-comment-export-function-return-section"; //$NON-NLS-1$
private final IResourceLookup resourceLookup;
private final IBslPreferences bslPreferences;
private final IScopeProvider scopeProvider;
private final BslMultiLineCommentDocumentationProvider commentProvider;
/**
* Instantiates a new check of export function return section.
*
* @param resourceLookup the resource lookup service, cannot be {@code null}.
* @param bslPreferences the BSL preferences service, cannot be {@code null}.
* @param commentProvider the comment provider service, cannot be {@code null}.
* @param scopeProvider the scope provider service, cannot be {@code null}.
*/
@Inject
public ExportFunctionReturnSectionCheck(IResourceLookup resourceLookup, IBslPreferences bslPreferences,
BslMultiLineCommentDocumentationProvider commentProvider, IScopeProvider scopeProvider)
{
this.resourceLookup = resourceLookup;
this.bslPreferences = bslPreferences;
this.commentProvider = commentProvider;
this.scopeProvider = scopeProvider;
}
@Override
public String getCheckId()
{
return CHECK_ID;
}
@Override
protected void configureCheck(CheckConfigurer builder)
{
builder.title(Messages.ExportFunctionReturnSectionCheck_title)
.description(Messages.ExportFunctionReturnSectionCheck_description)
.complexity(CheckComplexity.NORMAL)
.severity(IssueSeverity.MAJOR)
.issueType(IssueType.CODE_STYLE)
.extension(new StandardCheckExtension(getCheckId(), BslPlugin.PLUGIN_ID))
.delegate(BslDocumentationComment.class);
}
@Override
protected void checkDocumentationCommentObject(IDescriptionPart object, BslDocumentationComment root,
DocumentationCommentResultAcceptor resultAceptor, ICheckParameters parameters, IProgressMonitor monitor)
{
if (!(root.getMethod() instanceof Function) || !root.getMethod().isExport())
{
return;
}
BslDocumentationComment docComment = (BslDocumentationComment)object;
if (isInheritedFromLink(docComment))
{
LinkPart linkPart = getSingleLinkPart(docComment.getDescription());
IProject project = resourceLookup.getProject(root.getModule());
DocumentationCommentProperties props = bslPreferences.getDocumentCommentProperties(project);
docComment = BslCommentUtils.getLinkPartCommentContent(linkPart, scopeProvider, commentProvider,
props.oldCommentFormat(), root.getMethod());
}
if (docComment == null || docComment.getReturnSection() == null
|| isTypeEmptyAndNoLink(docComment.getReturnSection().getReturnTypes(),
docComment.getReturnSection().getDescription()))
{
resultAceptor.addIssue(Messages.ExportFunctionReturnSectionCheck_Export_function_return_section_required,
root.getMethod(), NAMED_ELEMENT__NAME);
}
}
private boolean isInheritedFromLink(BslDocumentationComment docComment)
{
return docComment.getReturnSection() == null && docComment.getParametersSection() == null
&& getSingleLinkPart(docComment.getDescription()) != null;
}
}

View File

@@ -0,0 +1,76 @@
/*******************************************************************************
* 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.comment.check;
import java.text.MessageFormat;
import org.eclipse.core.runtime.IProgressMonitor;
import com._1c.g5.v8.dt.bsl.documentation.comment.BslDocumentationComment;
import com._1c.g5.v8.dt.bsl.documentation.comment.IDescriptionPart;
import com._1c.g5.v8.dt.bsl.documentation.comment.TypeSection.FieldDefinition;
import com._1c.g5.v8.dt.common.StringUtils;
import com.e1c.g5.v8.dt.bsl.check.DocumentationCommentBasicDelegateCheck;
import com.e1c.g5.v8.dt.check.CheckComplexity;
import com.e1c.g5.v8.dt.check.ICheckParameters;
import com.e1c.g5.v8.dt.check.settings.IssueSeverity;
import com.e1c.g5.v8.dt.check.settings.IssueType;
import com.e1c.v8codestyle.check.CommonSenseCheckExtension;
import com.e1c.v8codestyle.internal.bsl.BslPlugin;
/**
* Validates that field name in documentation comment is valid name (not starts with number or does not contains any
* special symbols except alphabet).
*
* @author Dmitriy Marmyshev
*
*/
public class FieldDefinitionNameCheck
extends DocumentationCommentBasicDelegateCheck
{
private static final String CHECK_ID = "doc-comment-field-name"; //$NON-NLS-1$
@Override
public String getCheckId()
{
return CHECK_ID;
}
@Override
protected void configureCheck(CheckConfigurer builder)
{
builder.title(Messages.FieldDefinitionNameCheck_title)
.description(Messages.FieldDefinitionNameCheck_description)
.complexity(CheckComplexity.NORMAL)
.severity(IssueSeverity.MINOR)
.issueType(IssueType.CODE_STYLE)
.extension(new CommonSenseCheckExtension(getCheckId(), BslPlugin.PLUGIN_ID))
.delegate(FieldDefinition.class);
}
@Override
protected void checkDocumentationCommentObject(IDescriptionPart object, BslDocumentationComment root,
DocumentationCommentResultAcceptor resultAceptor, ICheckParameters parameters, IProgressMonitor monitor)
{
FieldDefinition fieldDef = (FieldDefinition)object;
if (!StringUtils.isValidName(fieldDef.getName()))
{
String message = MessageFormat.format(Messages.FieldDefinitionNameCheck_Field_name__N__is_incorrect_name,
fieldDef.getName());
resultAceptor.addIssue(message, fieldDef.getLineNumber(), fieldDef.getNameOffset(),
fieldDef.getName().length());
}
}
}

View File

@@ -0,0 +1,69 @@
/*******************************************************************************
* 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.comment.check;
import java.text.MessageFormat;
import org.eclipse.core.runtime.IProgressMonitor;
import com._1c.g5.v8.dt.bsl.documentation.comment.BslDocumentationComment;
import com._1c.g5.v8.dt.bsl.documentation.comment.IDescriptionPart;
import com._1c.g5.v8.dt.bsl.documentation.comment.TypeSection.FieldDefinition;
import com.e1c.g5.v8.dt.check.CheckComplexity;
import com.e1c.g5.v8.dt.check.ICheckParameters;
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;
/**
* Checks that field definition in documentation comment has type definition section.
*
* @author Dmitriy Marmyshev
*/
public class FieldDefinitionTypeCheck
extends AbstractDocCommentTypeCheck
{
private static final String CHECK_ID = "doc-comment-field-type"; //$NON-NLS-1$
@Override
public String getCheckId()
{
return CHECK_ID;
}
@Override
protected void configureCheck(CheckConfigurer builder)
{
builder.title(Messages.FieldDefinitionTypeCheck_title)
.description(Messages.FieldDefinitionTypeCheck_description)
.complexity(CheckComplexity.NORMAL)
.severity(IssueSeverity.MINOR)
.issueType(IssueType.CODE_STYLE)
.extension(new StandardCheckExtension(getCheckId(), BslPlugin.PLUGIN_ID))
.delegate(FieldDefinition.class);
}
@Override
protected void checkDocumentationCommentObject(IDescriptionPart object, BslDocumentationComment root,
DocumentationCommentResultAcceptor resultAceptor, ICheckParameters parameters, IProgressMonitor monitor)
{
FieldDefinition fieldDef = (FieldDefinition)object;
if (isFieldTypeEmpty(fieldDef))
{
String message = MessageFormat.format(Messages.FieldDefinitionTypeCheck_Field_M_has_no_type_definition,
fieldDef.getName());
resultAceptor.addIssue(message, fieldDef.getName().length());
}
}
}

View File

@@ -0,0 +1,170 @@
/*******************************************************************************
* 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.comment.check;
import java.text.MessageFormat;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.scoping.IScopeProvider;
import com._1c.g5.v8.dt.bsl.documentation.comment.BslDocumentationComment;
import com._1c.g5.v8.dt.bsl.documentation.comment.IDescriptionPart;
import com._1c.g5.v8.dt.bsl.documentation.comment.LinkPart;
import com._1c.g5.v8.dt.bsl.documentation.comment.TypeSection;
import com._1c.g5.v8.dt.bsl.documentation.comment.TypeSection.FieldDefinition;
import com._1c.g5.v8.dt.bsl.documentation.comment.TypeSection.TypeDefinition;
import com._1c.g5.v8.dt.common.StringUtils;
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.settings.IssueSeverity;
import com.e1c.g5.v8.dt.check.settings.IssueType;
import com.e1c.v8codestyle.check.CommonSenseCheckExtension;
import com.e1c.v8codestyle.internal.bsl.BslPlugin;
import com.google.inject.Inject;
/**
* Check field that it has definition of complex type and also reference to constructor function instead of just only
* the reference to function.
*
* @author Dmitriy Marmyshev
*/
public class FieldDefinitionTypeWithLinkRefCheck
extends AbstractDocCommentTypeCheck
{
private static final String CHECK_ID = "doc-comment-complex-type-with-link"; //$NON-NLS-1$
private static final String PARAMETER_COLLECTION_TYPES = "collectionTypes"; //$NON-NLS-1$
private static final String TYPE_DELIMITER = ","; //$NON-NLS-1$
//@formatter:off
private static final String DEFAULT_COLLECTION_TYPES = String.join(TYPE_DELIMITER, Set.of(
IEObjectTypeNames.STRUCTURE, IEObjectTypeNames.STRUCTURE_RU,
IEObjectTypeNames.FIXED_STRUCTURE, "ФиксированнаяСтруктура", //$NON-NLS-1$
IEObjectTypeNames.ARRAY, "Массив", //$NON-NLS-1$
IEObjectTypeNames.FIXED_ARRAY, "ФиксированныйМассив", //$NON-NLS-1$
IEObjectTypeNames.VALUE_TREE, IEObjectTypeNames.VALUE_TREE_RU,
IEObjectTypeNames.VALUE_TREE_ROW_COLLECTION, "КоллекцияСтрокДереваЗначений", //$NON-NLS-1$
IEObjectTypeNames.VALUE_TREE_ROW, "строкадеревазначений", //$NON-NLS-1$
IEObjectTypeNames.VALUE_TREE_COLUMN_COLLECTION, "КоллекцияКолонокДереваЗначений", //$NON-NLS-1$
IEObjectTypeNames.VALUE_TABLE, IEObjectTypeNames.VALUE_TABLE_RU,
IEObjectTypeNames.VALUE_TABLE_ROW, "СтрокаТаблицыЗначений", //$NON-NLS-1$
IEObjectTypeNames.VALUE_TABLE_COLUMN_COLLECTION, "КоллекцияКолонокТаблицыЗначений", //$NON-NLS-1$
IEObjectTypeNames.MAP, "Соответствие", //$NON-NLS-1$
IEObjectTypeNames.FIXED_MAP, "ФиксированноеСоответствие", //$NON-NLS-1$
IEObjectTypeNames.VALUE_LIST, "СписокЗначений" //$NON-NLS-1$
));
//@formatter:on
private final IScopeProvider scopeProvider;
/**
* Instantiates a new field definition type with link reference to constructor function check.
*
* @param scopeProvider the scope provider service, cannot be {@code null}.
*/
@Inject
public FieldDefinitionTypeWithLinkRefCheck(IScopeProvider scopeProvider)
{
this.scopeProvider = scopeProvider;
}
@Override
public String getCheckId()
{
return CHECK_ID;
}
@Override
protected void configureCheck(CheckConfigurer builder)
{
builder.title(Messages.FieldDefinitionTypeWithLinkRefCheck_title)
.description(Messages.FieldDefinitionTypeWithLinkRefCheck_description)
.complexity(CheckComplexity.NORMAL)
.severity(IssueSeverity.MINOR)
.issueType(IssueType.CODE_STYLE)
.extension(new CommonSenseCheckExtension(getCheckId(), BslPlugin.PLUGIN_ID))
.delegate(FieldDefinition.class);
builder.parameter(PARAMETER_COLLECTION_TYPES, String.class, DEFAULT_COLLECTION_TYPES,
Messages.CollectionTypeDefinitionCheck_Collection_types);
}
@Override
protected void checkDocumentationCommentObject(IDescriptionPart object, BslDocumentationComment root,
DocumentationCommentResultAcceptor resultAceptor, ICheckParameters parameters, IProgressMonitor monitor)
{
String parameterCollectionTypes = parameters.getString(PARAMETER_COLLECTION_TYPES);
if (StringUtils.isBlank(parameterCollectionTypes))
{
return;
}
Set<String> types = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
String[] paramTypes = parameterCollectionTypes.split(TYPE_DELIMITER);
types.addAll(List.of(paramTypes));
FieldDefinition fieldDef = (FieldDefinition)object;
if (isFieldTypeWithLinkRef(fieldDef, types, root.getMethod()))
{
String message = MessageFormat.format(
Messages.FieldDefinitionTypeWithLinkRefCheck_Field__F__use_declaration_of_complex_type_instead_of_link,
fieldDef.getName());
resultAceptor.addIssue(message, fieldDef.getName().length());
}
}
private boolean isFieldTypeWithLinkRef(FieldDefinition fieldDef, Set<String> types, EObject context)
{
if (fieldDef.getTypeSections().size() == 1 && isComplexType(fieldDef.getTypeSections().get(0), types))
{
LinkPart linkPart = getSingleLinkPartForField(fieldDef);
return linkPart != null && isLinkPartObjectExist(linkPart, scopeProvider, context);
}
return false;
}
private boolean isComplexType(TypeSection typeSection, Set<String> types)
{
if (typeSection.getTypeDefinitions().size() == 1)
{
TypeDefinition type = typeSection.getTypeDefinitions().get(0);
if (!type.getContainTypes().isEmpty())
{
return false;
}
String typeName = type.getTypeName();
return types.contains(typeName);
}
return false;
}
private LinkPart getSingleLinkPartForField(FieldDefinition fieldDef)
{
if (fieldDef.getTypeSections().size() != 1)
{
return null;
}
TypeSection typeSection = fieldDef.getTypeSections().get(0);
return getSingleLinkPart(typeSection.getDescription());
}
}

View File

@@ -0,0 +1,133 @@
/*******************************************************************************
* 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.comment.check;
import java.util.Collection;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.naming.IQualifiedNameConverter;
import org.eclipse.xtext.scoping.IScope;
import org.eclipse.xtext.scoping.IScopeProvider;
import com._1c.g5.v8.dt.bsl.common.IBslPreferences;
import com._1c.g5.v8.dt.bsl.documentation.comment.BslDocumentationComment;
import com._1c.g5.v8.dt.bsl.documentation.comment.BslDocumentationComment.ReturnSection;
import com._1c.g5.v8.dt.bsl.documentation.comment.BslMultiLineCommentDocumentationProvider;
import com._1c.g5.v8.dt.bsl.documentation.comment.IDescriptionPart;
import com._1c.g5.v8.dt.bsl.model.Function;
import com._1c.g5.v8.dt.bsl.model.Method;
import com._1c.g5.v8.dt.core.platform.IResourceLookup;
import com._1c.g5.v8.dt.mcore.McorePackage;
import com._1c.g5.v8.dt.mcore.TypeItem;
import com.e1c.g5.v8.dt.check.CheckComplexity;
import com.e1c.g5.v8.dt.check.ICheckParameters;
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;
/**
* Checks that documentation comment return section contains valid return types.
*
* @author Dmitriy Marmyshev
*
*/
public class FunctionReturnSectionCheck
extends AbstractDocCommentTypeCheck
{
private static final String CHECK_ID = "doc-comment-return-section-type"; //$NON-NLS-1$
private final IResourceLookup resourceLookup;
private final IBslPreferences bslPreferences;
private final IScopeProvider scopeProvider;
private final BslMultiLineCommentDocumentationProvider commentProvider;
private final IQualifiedNameConverter qualifiedNameConverter;
@Inject
public FunctionReturnSectionCheck(IResourceLookup resourceLookup, IBslPreferences bslPreferences,
IQualifiedNameConverter qualifiedNameConverter, IScopeProvider scopeProvider,
BslMultiLineCommentDocumentationProvider commentProvider)
{
this.resourceLookup = resourceLookup;
this.bslPreferences = bslPreferences;
this.qualifiedNameConverter = qualifiedNameConverter;
this.scopeProvider = scopeProvider;
this.commentProvider = commentProvider;
}
@Override
public String getCheckId()
{
return CHECK_ID;
}
@Override
protected void configureCheck(CheckConfigurer builder)
{
builder.title(Messages.FunctionReturnSectionCheck_title)
.description(Messages.FunctionReturnSectionCheck_description)
.complexity(CheckComplexity.NORMAL)
.severity(IssueSeverity.MINOR)
.issueType(IssueType.CODE_STYLE)
.extension(new StandardCheckExtension(getCheckId(), BslPlugin.PLUGIN_ID))
.delegate(ReturnSection.class);
}
@Override
protected void checkDocumentationCommentObject(IDescriptionPart object, BslDocumentationComment root,
DocumentationCommentResultAcceptor resultAceptor, ICheckParameters parameters, IProgressMonitor monitor)
{
Method method = root.getMethod();
if (!(method instanceof Function))
{
return;
}
ReturnSection returnSection = (ReturnSection)object;
if (isTypeEmptyAndNoLink(returnSection.getReturnTypes(), returnSection.getDescription()))
{
resultAceptor.addIssue(Messages.FunctionReturnSectionCheck_Return_type_is_mandatory,
returnSection.getHeaderKeywordLength());
return;
}
IScope typeScope = scopeProvider.getScope(method, McorePackage.Literals.TYPE_DESCRIPTION__TYPES);
Collection<TypeItem> computedReturnTypes = root.computeReturnTypes(typeScope, scopeProvider,
qualifiedNameConverter, commentProvider, oldCommentFormat(root.getModule()), method);
if (computedReturnTypes.isEmpty())
{
resultAceptor.addIssue(Messages.FunctionReturnSectionCheck_Return_type_unknown,
returnSection.getHeaderKeywordLength());
}
}
private boolean oldCommentFormat(EObject context)
{
IProject project = resourceLookup.getProject(context);
return bslPreferences.getDocumentCommentProperties(project).oldCommentFormat();
}
}

View File

@@ -22,9 +22,53 @@ final class Messages
extends NLS
{
private static final String BUNDLE_NAME = "com.e1c.v8codestyle.bsl.comment.check.messages"; //$NON-NLS-1$
public static String CollectionTypeDefinitionCheck_Collection_type_should_have_contain_item_type;
public static String CollectionTypeDefinitionCheck_Collection_types;
public static String CollectionTypeDefinitionCheck_description;
public static String CollectionTypeDefinitionCheck_title;
public static String DocCommentUseMinusCheck_description;
public static String DocCommentUseMinusCheck_Only_hyphen_minus_symbol_is_allowed_in_doc_comment_but_found_0;
public static String DocCommentUseMinusCheck_title;
public static String ExportFunctionReturnSectionCheck_description;
public static String ExportFunctionReturnSectionCheck_Export_function_return_section_required;
public static String ExportFunctionReturnSectionCheck_title;
public static String FieldDefinitionNameCheck_description;
public static String FieldDefinitionNameCheck_Field_name__N__is_incorrect_name;
public static String FieldDefinitionNameCheck_title;
public static String FieldDefinitionTypeCheck_description;
public static String FieldDefinitionTypeCheck_Field_M_has_no_type_definition;
public static String FieldDefinitionTypeCheck_title;
public static String FieldDefinitionTypeWithLinkRefCheck_description;
public static String FieldDefinitionTypeWithLinkRefCheck_Field__F__use_declaration_of_complex_type_instead_of_link;
public static String FieldDefinitionTypeWithLinkRefCheck_title;
public static String FunctionReturnSectionCheck_description;
public static String FunctionReturnSectionCheck_Return_type_is_mandatory;
public static String FunctionReturnSectionCheck_Return_type_unknown;
public static String FunctionReturnSectionCheck_title;
public static String MultilineDescriptionEndsOnDotCheck_description;
public static String MultilineDescriptionEndsOnDotCheck_Method_comment_doesnt_ends_on_dot;
public static String MultilineDescriptionEndsOnDotCheck_title;
public static String MultilineDescriptionFieldSuggestionCheck_description;
public static String MultilineDescriptionFieldSuggestionCheck_Probably_Field_is_defined_in_description;
public static String MultilineDescriptionFieldSuggestionCheck_title;
public static String MultilineDescriptionParameterSuggestionCheck_description;
public static String MultilineDescriptionParameterSuggestionCheck_Probably_method_parameter_is_defined;
public static String MultilineDescriptionParameterSuggestionCheck_title;
public static String ParametersSectionCheck_Check_only_export_method_parameter_section;
public static String ParametersSectionCheck_description;
public static String ParametersSectionCheck_Parameter_definition_missed_for__N;
public static String ParametersSectionCheck_Remove_useless_parameter_section;
public static String ParametersSectionCheck_title;
public static String ProcedureReturnSectionCheck_description;
public static String ProcedureReturnSectionCheck_Procedure_should_has_no_return_section;
public static String ProcedureReturnSectionCheck_title;
public static String RefLinkPartCheck_Allow_See_in_description;
public static String RefLinkPartCheck_description;
public static String RefLinkPartCheck_Link_referenced_to_unexisting_object;
public static String RefLinkPartCheck_title;
public static String TypeDefinitionCheck_description;
public static String TypeDefinitionCheck_title;
public static String TypeDefinitionCheck_Unkown_type_M_specified;
static
{
// initialize resource bundle

View File

@@ -0,0 +1,99 @@
/*******************************************************************************
* 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.comment.check;
import org.eclipse.core.runtime.IProgressMonitor;
import com._1c.g5.v8.dt.bsl.documentation.comment.BslDocumentationComment;
import com._1c.g5.v8.dt.bsl.documentation.comment.BslDocumentationComment.Description;
import com._1c.g5.v8.dt.bsl.documentation.comment.IDescriptionPart;
import com._1c.g5.v8.dt.bsl.documentation.comment.TextPart;
import com.e1c.g5.v8.dt.bsl.check.DocumentationCommentBasicDelegateCheck;
import com.e1c.g5.v8.dt.check.CheckComplexity;
import com.e1c.g5.v8.dt.check.ICheckParameters;
import com.e1c.g5.v8.dt.check.settings.IssueSeverity;
import com.e1c.g5.v8.dt.check.settings.IssueType;
/**
* Check multi-line description of the documentation comment that last line ends on dot.
*
* @author Dmitriy Marmyshev
*/
public class MultilineDescriptionEndsOnDotCheck
extends DocumentationCommentBasicDelegateCheck
{
private static final String CHECK_ID = "doc-comment-description-ends-on-dot"; //$NON-NLS-1$
@Override
public String getCheckId()
{
return CHECK_ID;
}
@Override
protected void configureCheck(CheckConfigurer builder)
{
builder.title(Messages.MultilineDescriptionEndsOnDotCheck_title)
.description(Messages.MultilineDescriptionEndsOnDotCheck_description)
.complexity(CheckComplexity.NORMAL)
.severity(IssueSeverity.TRIVIAL)
.issueType(IssueType.CODE_STYLE)
.disable()
.delegate(Description.class);
}
@Override
protected void checkDocumentationCommentObject(IDescriptionPart object, BslDocumentationComment root,
DocumentationCommentResultAcceptor resultAceptor, ICheckParameters parameters, IProgressMonitor monitor)
{
Description description = (Description)object;
if (description == null || description.getParts().isEmpty())
{
return;
}
int startLine = description.getParts().get(0).getLineNumber();
//@formatter:off
TextPart lastPart = description.getParts()
.stream()
.filter(TextPart.class::isInstance)
.map(TextPart.class::cast)
.reduce((first, second) -> second)
.orElse(null);
//@formatter:on
if (lastPart == null || startLine == lastPart.getLineNumber())
{
return;
}
String lastLine = lastPart.getText();
if (lastLine != null)
{
lastLine = lastLine.trim();
}
if (lastLine != null && lastLine.endsWith(".")) //$NON-NLS-1$
{
return;
}
resultAceptor.addIssue(Messages.MultilineDescriptionEndsOnDotCheck_Method_comment_doesnt_ends_on_dot,
lastPart.getLineNumber(), lastPart.getOffset(), lastPart.getText().length());
}
}

View File

@@ -0,0 +1,118 @@
/*******************************************************************************
* 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.comment.check;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.core.runtime.IProgressMonitor;
import com._1c.g5.v8.dt.bsl.documentation.comment.BslDocumentationComment;
import com._1c.g5.v8.dt.bsl.documentation.comment.BslDocumentationComment.Description;
import com._1c.g5.v8.dt.bsl.documentation.comment.IDescriptionPart;
import com._1c.g5.v8.dt.bsl.documentation.comment.TextPart;
import com._1c.g5.v8.dt.bsl.model.Procedure;
import com.e1c.g5.v8.dt.bsl.check.DocumentationCommentBasicDelegateCheck;
import com.e1c.g5.v8.dt.check.CheckComplexity;
import com.e1c.g5.v8.dt.check.ICheckParameters;
import com.e1c.g5.v8.dt.check.settings.IssueSeverity;
import com.e1c.g5.v8.dt.check.settings.IssueType;
import com.e1c.v8codestyle.check.CommonSenseCheckExtension;
import com.e1c.v8codestyle.internal.bsl.BslPlugin;
/**
* Validates any description in documentation comment that is multi-line and may contains File definition like:
* <pre>
* // * FieldName - ...
* </pre>
* where description line begins with one or more stars and then a name of field.
*
* @author Dmitriy Marmyshev
*
*/
public class MultilineDescriptionFieldSuggestionCheck
extends DocumentationCommentBasicDelegateCheck
{
private static final String CHECK_ID = "doc-comment-field-in-description-suggestion"; //$NON-NLS-1$
/** The Pattern of field search.
* RegEx: ^\s*\*+\s*\w+\s*-
**/
private static final Pattern PATTERN_FIELD =
Pattern.compile("^\\s*\\*+\\s*\\w+\\s*-", Pattern.UNICODE_CHARACTER_CLASS | Pattern.CASE_INSENSITIVE); //$NON-NLS-1$
@Override
public String getCheckId()
{
return CHECK_ID;
}
@Override
protected void configureCheck(CheckConfigurer builder)
{
builder.title(Messages.MultilineDescriptionFieldSuggestionCheck_title)
.description(Messages.MultilineDescriptionFieldSuggestionCheck_description)
.complexity(CheckComplexity.NORMAL)
.severity(IssueSeverity.TRIVIAL)
.issueType(IssueType.CODE_STYLE)
.extension(new CommonSenseCheckExtension(getCheckId(), BslPlugin.PLUGIN_ID))
.delegate(Description.class);
}
@Override
protected void checkDocumentationCommentObject(IDescriptionPart object, BslDocumentationComment root,
DocumentationCommentResultAcceptor resultAceptor, ICheckParameters parameters, IProgressMonitor monitor)
{
Description description = (Description)object;
if (description.getParts().isEmpty() || (root.getMethod().getFormalParams().isEmpty()
&& (root.getMethod() instanceof Procedure || object.getParent() instanceof BslDocumentationComment)))
{
// do not check if empty, or Procedure has no params, or it is function description with no params
return;
}
int startLine = description.getParts().get(0).getLineNumber();
TextPart lastPart = description.getParts()
.stream()
.filter(TextPart.class::isInstance)
.map(TextPart.class::cast)
.reduce((first, second) -> second)
.orElse(null);
if (lastPart == null || startLine == lastPart.getLineNumber())
{
return;
}
int prevLine = 0;
for (IDescriptionPart part : description.getParts())
{
if (part instanceof TextPart && part.getLineNumber() > startLine && part.getLineNumber() > prevLine)
{
String text = ((TextPart)part).getText();
Matcher matcher = PATTERN_FIELD.matcher(text);
if (matcher.find())
{
resultAceptor.addIssue(
Messages.MultilineDescriptionFieldSuggestionCheck_Probably_Field_is_defined_in_description,
part.getLineNumber(), part.getOffset(), matcher.end());
}
}
prevLine = part.getLineNumber();
}
}
}

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.comment.check;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.eclipse.core.runtime.IProgressMonitor;
import com._1c.g5.v8.dt.bsl.documentation.comment.BslDocumentationComment;
import com._1c.g5.v8.dt.bsl.documentation.comment.BslDocumentationComment.Description;
import com._1c.g5.v8.dt.bsl.documentation.comment.IDescriptionPart;
import com._1c.g5.v8.dt.bsl.documentation.comment.TextPart;
import com._1c.g5.v8.dt.bsl.model.FormalParam;
import com._1c.g5.v8.dt.common.StringUtils;
import com.e1c.g5.v8.dt.bsl.check.DocumentationCommentBasicDelegateCheck;
import com.e1c.g5.v8.dt.check.CheckComplexity;
import com.e1c.g5.v8.dt.check.ICheckParameters;
import com.e1c.g5.v8.dt.check.settings.IssueSeverity;
import com.e1c.g5.v8.dt.check.settings.IssueType;
import com.e1c.v8codestyle.check.CommonSenseCheckExtension;
import com.e1c.v8codestyle.internal.bsl.BslPlugin;
/**
* Validates method description in documentation comment that is multi-line and may contains parameter definition like:
* <pre>
* // ParameterName - ...
* </pre>
* where description line begins with one of names of method parameters.
*
* @author Dmitriy Marmyshev
*
*/
public class MultilineDescriptionParameterSuggestionCheck
extends DocumentationCommentBasicDelegateCheck
{
private static final String CHECK_ID = "doc-comment-parameter-in-description-suggestion"; //$NON-NLS-1$
@Override
public String getCheckId()
{
return CHECK_ID;
}
@Override
protected void configureCheck(CheckConfigurer builder)
{
builder.title(Messages.MultilineDescriptionParameterSuggestionCheck_title)
.description(Messages.MultilineDescriptionParameterSuggestionCheck_description)
.complexity(CheckComplexity.NORMAL)
.severity(IssueSeverity.TRIVIAL)
.issueType(IssueType.CODE_STYLE)
.extension(new CommonSenseCheckExtension(getCheckId(), BslPlugin.PLUGIN_ID))
.delegate(Description.class);
}
@Override
protected void checkDocumentationCommentObject(IDescriptionPart object, BslDocumentationComment root,
DocumentationCommentResultAcceptor resultAceptor, ICheckParameters parameters, IProgressMonitor monitor)
{
if (root.getMethod().getFormalParams().isEmpty() || !(object.getParent() instanceof BslDocumentationComment)
|| root.getParametersSection() != null)
{
return;
}
Description description = (Description)object;
if (description.getParts().isEmpty())
{
return;
}
int startLine = description.getParts().get(0).getLineNumber();
//@formatter:off
TextPart lastPart = description.getParts()
.stream()
.filter(TextPart.class::isInstance)
.map(TextPart.class::cast)
.reduce((first, second) -> second)
.orElse(null);
//@formatter:on
if (lastPart == null || startLine == lastPart.getLineNumber())
{
return;
}
List<String> paramNames = root.getMethod()
.getFormalParams()
.stream()
.filter(p -> StringUtils.isValidName(p.getName()))
.map(FormalParam::getName)
.collect(Collectors.toList());
/** The Pattern of parameter search.
* RegEx: ^\/*\s*(Param1|Param2)\s*-
**/
Pattern paramPattern = Pattern.compile("^\\s*(" + String.join("|", paramNames) + ")\\s*-", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE);
int prevLine = 0;
for (IDescriptionPart part : description.getParts())
{
if (part instanceof TextPart && part.getLineNumber() > startLine && part.getLineNumber() > prevLine)
{
String text = ((TextPart)part).getText();
Matcher matcher = paramPattern.matcher(text);
if (matcher.find())
{
resultAceptor.addIssue(
Messages.MultilineDescriptionParameterSuggestionCheck_Probably_method_parameter_is_defined,
part.getLineNumber(), part.getOffset(), matcher.end());
}
}
prevLine = part.getLineNumber();
}
}
}

View File

@@ -0,0 +1,108 @@
/*******************************************************************************
* 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.comment.check;
import java.text.MessageFormat;
import java.util.Set;
import java.util.TreeSet;
import org.eclipse.core.runtime.IProgressMonitor;
import com._1c.g5.v8.dt.bsl.documentation.comment.BslDocumentationComment;
import com._1c.g5.v8.dt.bsl.documentation.comment.BslDocumentationComment.ParametersSection;
import com._1c.g5.v8.dt.bsl.documentation.comment.IDescriptionPart;
import com._1c.g5.v8.dt.bsl.documentation.comment.TypeSection.FieldDefinition;
import com._1c.g5.v8.dt.common.StringUtils;
import com.e1c.g5.v8.dt.bsl.check.DocumentationCommentBasicDelegateCheck;
import com.e1c.g5.v8.dt.check.CheckComplexity;
import com.e1c.g5.v8.dt.check.ICheckParameters;
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;
/**
* Validates that each of parameters specified in documenting comments.
*
* @author Maxim Degtyarev
* @author Dmitriy Marmyshev
*
*/
public class ParametersSectionCheck
extends DocumentationCommentBasicDelegateCheck
{
private static final String CHECK_ID = "doc-comment-parameter-section"; //$NON-NLS-1$
private static final String PARAMETER_CHECK_ONLY_EXPORT = "checkOnlyExport"; //$NON-NLS-1$
@Override
public String getCheckId()
{
return CHECK_ID;
}
@Override
protected void configureCheck(CheckConfigurer builder)
{
builder.title(Messages.ParametersSectionCheck_title)
.description(Messages.ParametersSectionCheck_description)
.complexity(CheckComplexity.NORMAL)
.severity(IssueSeverity.MINOR)
.issueType(IssueType.CODE_STYLE)
.extension(new StandardCheckExtension(getCheckId(), BslPlugin.PLUGIN_ID))
.delegate(ParametersSection.class);
builder.parameter(PARAMETER_CHECK_ONLY_EXPORT, Boolean.class, Boolean.FALSE.toString(),
Messages.ParametersSectionCheck_Check_only_export_method_parameter_section);
}
@Override
protected void checkDocumentationCommentObject(IDescriptionPart object, BslDocumentationComment root,
DocumentationCommentResultAcceptor resultAceptor, ICheckParameters parameters, IProgressMonitor monitor)
{
ParametersSection parameterSection = (ParametersSection)object;
if (root.getMethod().getFormalParams().isEmpty())
{
// TODO Extract to new check that parameter section is empty and useless
resultAceptor.addIssue(Messages.ParametersSectionCheck_Remove_useless_parameter_section,
parameterSection.getHeaderKeywordLength());
return;
}
if (!root.getMethod().isExport() && parameters.getBoolean(PARAMETER_CHECK_ONLY_EXPORT))
{
return;
}
Set<String> parameterNames = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
root.getMethod().getFormalParams().forEach(p -> {
if (p != null && StringUtils.isNotBlank(p.getName()))
{
parameterNames.add(p.getName());
}
});
for (FieldDefinition parameterDefinition : parameterSection.getParameterDefinitions())
{
parameterNames.remove(parameterDefinition.getName());
}
if (!parameterNames.isEmpty())
{
String message = MessageFormat.format(Messages.ParametersSectionCheck_Parameter_definition_missed_for__N,
String.join(", ", parameterNames)); //$NON-NLS-1$
resultAceptor.addIssue(message, parameterSection.getHeaderKeywordLength());
}
}
}

View File

@@ -0,0 +1,72 @@
/*******************************************************************************
* 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.comment.check;
import org.eclipse.core.runtime.IProgressMonitor;
import com._1c.g5.v8.dt.bsl.documentation.comment.BslDocumentationComment;
import com._1c.g5.v8.dt.bsl.documentation.comment.BslDocumentationComment.ReturnSection;
import com._1c.g5.v8.dt.bsl.documentation.comment.IDescriptionPart;
import com._1c.g5.v8.dt.bsl.model.Procedure;
import com.e1c.g5.v8.dt.bsl.check.DocumentationCommentBasicDelegateCheck;
import com.e1c.g5.v8.dt.check.CheckComplexity;
import com.e1c.g5.v8.dt.check.ICheckParameters;
import com.e1c.g5.v8.dt.check.settings.IssueSeverity;
import com.e1c.g5.v8.dt.check.settings.IssueType;
import com.e1c.v8codestyle.check.CommonSenseCheckExtension;
import com.e1c.v8codestyle.internal.bsl.BslPlugin;
/**
* The check validate {@link ReturnSection} of documentation comment if the method is {@link Procedure} which should not
* have return section.
*
* @author Dmitriy Marmyshev
*/
public class ProcedureReturnSectionCheck
extends DocumentationCommentBasicDelegateCheck
{
private static final String CHECK_ID = "doc-comment-procedure-return-section"; //$NON-NLS-1$
@Override
public String getCheckId()
{
return CHECK_ID;
}
@Override
protected void configureCheck(CheckConfigurer builder)
{
builder.title(Messages.ProcedureReturnSectionCheck_title)
.description(Messages.ProcedureReturnSectionCheck_description)
.complexity(CheckComplexity.NORMAL)
.severity(IssueSeverity.MINOR)
.issueType(IssueType.CODE_STYLE)
.extension(new CommonSenseCheckExtension(getCheckId(), BslPlugin.PLUGIN_ID))
.delegate(ReturnSection.class);
}
@Override
protected void checkDocumentationCommentObject(IDescriptionPart object, BslDocumentationComment root,
DocumentationCommentResultAcceptor resultAceptor, ICheckParameters parameters, IProgressMonitor monitor)
{
ReturnSection returnSection = (ReturnSection)object;
if (root.getMethod() instanceof Procedure)
{
resultAceptor.addIssue(Messages.ProcedureReturnSectionCheck_Procedure_should_has_no_return_section,
returnSection.getLineNumber(), returnSection.getOffset(), returnSection.getHeaderKeywordLength());
}
}
}

View File

@@ -0,0 +1,116 @@
/*******************************************************************************
* 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.comment.check;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.xtext.scoping.IScopeProvider;
import com._1c.g5.v8.dt.bsl.documentation.comment.BslDocumentationComment;
import com._1c.g5.v8.dt.bsl.documentation.comment.BslDocumentationComment.Description;
import com._1c.g5.v8.dt.bsl.documentation.comment.IDescriptionPart;
import com._1c.g5.v8.dt.bsl.documentation.comment.LinkPart;
import com._1c.g5.v8.dt.common.StringUtils;
import com.e1c.g5.v8.dt.check.CheckComplexity;
import com.e1c.g5.v8.dt.check.ICheckParameters;
import com.e1c.g5.v8.dt.check.settings.IssueSeverity;
import com.e1c.g5.v8.dt.check.settings.IssueType;
import com.e1c.v8codestyle.check.CommonSenseCheckExtension;
import com.e1c.v8codestyle.internal.bsl.BslPlugin;
import com.google.inject.Inject;
/**
* Validates {@link LinkPart} of documentation comment that it referenced to an existing object.
* This check allows to skip link with single word in {@link Description}
* <pre>
* // Method description here.
* // And also see something here...
* </pre>
* but it validates this
* <pre>
* // Method description here.
* // And also see some.thing here
* </pre>
* as reference to method "thing" of common module "some".
*
* @author Dmitriy Marmyshev
*/
public class RefLinkPartCheck
extends AbstractDocCommentTypeCheck
{
private static final String CHECK_ID = "doc-comment-ref-link"; //$NON-NLS-1$
private static final String PARAMETER_ALLOW_SEE_IN_DESCRIPTION = "allowSeeInDescription"; //$NON-NLS-1$
private final IScopeProvider scopeProvider;
/**
* Instantiates a new reference link part check.
*
* @param scopeProvider the scope provider service, cannot be {@code null}.
*/
@Inject
public RefLinkPartCheck(IScopeProvider scopeProvider)
{
this.scopeProvider = scopeProvider;
}
@Override
public String getCheckId()
{
return CHECK_ID;
}
@Override
protected void configureCheck(CheckConfigurer builder)
{
builder.title(Messages.RefLinkPartCheck_title)
.description(Messages.RefLinkPartCheck_description)
.complexity(CheckComplexity.NORMAL)
.severity(IssueSeverity.MINOR)
.issueType(IssueType.CODE_STYLE)
.extension(new CommonSenseCheckExtension(getCheckId(), BslPlugin.PLUGIN_ID))
.delegate(LinkPart.class);
builder.parameter(PARAMETER_ALLOW_SEE_IN_DESCRIPTION, Boolean.class, Boolean.TRUE.toString(),
Messages.RefLinkPartCheck_Allow_See_in_description);
}
@Override
protected void checkDocumentationCommentObject(IDescriptionPart object, BslDocumentationComment root,
DocumentationCommentResultAcceptor resultAceptor, ICheckParameters parameters, IProgressMonitor monitor)
{
LinkPart linkPart = (LinkPart)object;
boolean isSingleWordInDescription = parameters.getBoolean(PARAMETER_ALLOW_SEE_IN_DESCRIPTION)
&& object.getParent() instanceof Description && linkPart.getPartsWithOffset().size() == 1;
if (!isWebLink(linkPart) && !isSingleWordInDescription
&& getLinkPartLastObject(linkPart, scopeProvider, root.getMethod()).isEmpty())
{
resultAceptor.addIssue(Messages.RefLinkPartCheck_Link_referenced_to_unexisting_object,
linkPart.getLineNumber(), linkPart.getLinkTextOffset(), linkPart.getLinkText().length());
}
}
private boolean isWebLink(LinkPart linkPart)
{
String text = linkPart.getLinkText();
if (StringUtils.isEmpty(text))
{
// just skip other checks
return true;
}
return text.startsWith("http://") || text.startsWith("https://") || text.startsWith("ftp://"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
}

View File

@@ -0,0 +1,107 @@
/*******************************************************************************
* 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.comment.check;
import java.text.MessageFormat;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.xtext.naming.IQualifiedNameConverter;
import org.eclipse.xtext.resource.IEObjectDescription;
import org.eclipse.xtext.scoping.IScope;
import org.eclipse.xtext.scoping.IScopeProvider;
import com._1c.g5.v8.dt.bsl.documentation.comment.BslDocumentationComment;
import com._1c.g5.v8.dt.bsl.documentation.comment.IDescriptionPart;
import com._1c.g5.v8.dt.bsl.documentation.comment.TypeSection.LinkContainsTypeDefinition;
import com._1c.g5.v8.dt.bsl.documentation.comment.TypeSection.TypeDefinition;
import com._1c.g5.v8.dt.common.StringUtils;
import com._1c.g5.v8.dt.mcore.McorePackage;
import com.e1c.g5.v8.dt.check.CheckComplexity;
import com.e1c.g5.v8.dt.check.ICheckParameters;
import com.e1c.g5.v8.dt.check.settings.IssueSeverity;
import com.e1c.g5.v8.dt.check.settings.IssueType;
import com.e1c.v8codestyle.check.CommonSenseCheckExtension;
import com.e1c.v8codestyle.internal.bsl.BslPlugin;
import com.google.inject.Inject;
/**
* Check type definition contains valid existing type.
*
* @author Dmitriy Marmyshev
*/
public class TypeDefinitionCheck
extends AbstractDocCommentTypeCheck
{
private static final String CHECK_ID = "doc-comment-type"; //$NON-NLS-1$
private final IScopeProvider scopeProvider;
private final IQualifiedNameConverter qualifiedNameConverter;
@Inject
public TypeDefinitionCheck(IQualifiedNameConverter qualifiedNameConverter, IScopeProvider scopeProvider)
{
this.qualifiedNameConverter = qualifiedNameConverter;
this.scopeProvider = scopeProvider;
}
@Override
public String getCheckId()
{
return CHECK_ID;
}
@Override
protected void configureCheck(CheckConfigurer builder)
{
builder.title(Messages.TypeDefinitionCheck_title)
.description(Messages.TypeDefinitionCheck_description)
.complexity(CheckComplexity.NORMAL)
.severity(IssueSeverity.MINOR)
.issueType(IssueType.CODE_STYLE)
.extension(new CommonSenseCheckExtension(getCheckId(), BslPlugin.PLUGIN_ID))
.delegate(TypeDefinition.class);
}
@Override
protected void checkDocumentationCommentObject(IDescriptionPart object, BslDocumentationComment root,
DocumentationCommentResultAcceptor resultAceptor, ICheckParameters parameters, IProgressMonitor monitor)
{
if (object instanceof LinkContainsTypeDefinition)
{
return;
}
TypeDefinition typeDef = (TypeDefinition)object;
String typeName = typeDef.getTypeName();
if (StringUtils.isEmpty(typeName))
{
return;
}
IScope typeScope = scopeProvider.getScope(root.getMethod(), McorePackage.Literals.TYPE_DESCRIPTION__TYPES);
IEObjectDescription obj = typeScope.getSingleElement(qualifiedNameConverter.toQualifiedName(typeName));
if (obj == null)
{
String message = MessageFormat.format(Messages.TypeDefinitionCheck_Unkown_type_M_specified, typeName);
resultAceptor.addIssue(message, typeName.length());
}
}
}

View File

@@ -1,3 +1,4 @@
#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/)
###############################################################################
# Copyright (C) 2021, 1C-Soft LLC and others.
@@ -11,9 +12,96 @@
# Contributors:
# 1C-Soft LLC - initial API and implementation
###############################################################################
CollectionTypeDefinitionCheck_Collection_type_should_have_contain_item_type = Collection type should have contain item type
DocCommentUseMinusCheck_Only_hyphen_minus_symbol_is_allowed_in_doc_comment_but_found_0=Only hyphen-minus symbol is allowed in documentation comment, but found: "{0}"
CollectionTypeDefinitionCheck_Collection_types = Collection types
CollectionTypeDefinitionCheck_description = Documentation comment collection type definition has contain item type
CollectionTypeDefinitionCheck_title = Documentation comment collection type definition has contain item type
DocCommentUseMinusCheck_Only_hyphen_minus_symbol_is_allowed_in_doc_comment_but_found_0 = Only hyphen-minus symbol is allowed in documentation comment, but found: "{0}"
DocCommentUseMinusCheck_description = Use only hyphen-minus in documentation comment
DocCommentUseMinusCheck_title = Use only hyphen-minus in documentation comment
ExportFunctionReturnSectionCheck_Export_function_return_section_required = Return section is mandatory for exported function
ExportFunctionReturnSectionCheck_description = Documentation comment return section for export function
ExportFunctionReturnSectionCheck_title = Documentation comment return section for export function
FieldDefinitionNameCheck_Field_name__N__is_incorrect_name = Field name "{0}" is incorrect name
FieldDefinitionNameCheck_description = Documentation comment field is correct name
FieldDefinitionNameCheck_title = Documentation comment field is correct name
FieldDefinitionTypeCheck_Field_M_has_no_type_definition = Field "{0}" has no type definition
FieldDefinitionTypeCheck_description = Documentation comment field has no type definition
FieldDefinitionTypeCheck_title = Documentation comment field has no type definition
FieldDefinitionTypeWithLinkRefCheck_Field__F__use_declaration_of_complex_type_instead_of_link = Field "{0}" use declaration of complex type instead of link to type
FieldDefinitionTypeWithLinkRefCheck_description = Documentation comment field use declaration of complex type instead of link to type
FieldDefinitionTypeWithLinkRefCheck_title = Documentation comment field use declaration of complex type instead of link to type
FunctionReturnSectionCheck_Return_type_is_mandatory = Return type is mandatory
FunctionReturnSectionCheck_Return_type_unknown = Return type unknown
FunctionReturnSectionCheck_description = Documentation comment return section contains valid types
FunctionReturnSectionCheck_title = Documentation comment return section contains valid types
MultilineDescriptionEndsOnDotCheck_Method_comment_doesnt_ends_on_dot = Method comment doesn't ends on dot
MultilineDescriptionEndsOnDotCheck_description = Documentation comment multi-line description ends on dot
MultilineDescriptionEndsOnDotCheck_title = Documentation comment multi-line description ends on dot
MultilineDescriptionFieldSuggestionCheck_Probably_Field_is_defined_in_description = Probably Field is defined in description
MultilineDescriptionFieldSuggestionCheck_description = Documentation comment multi-line description contains field definition
MultilineDescriptionFieldSuggestionCheck_title = Documentation comment multi-line description contains field definition
MultilineDescriptionParameterSuggestionCheck_Probably_method_parameter_is_defined = Probably method parameter is defined in description
MultilineDescriptionParameterSuggestionCheck_description = Documentation comment multi-line description contains parameter definition
MultilineDescriptionParameterSuggestionCheck_title = Documentation comment multi-line description contains parameter definition
ParametersSectionCheck_Check_only_export_method_parameter_section = Check only export method parameter section
ParametersSectionCheck_Parameter_definition_missed_for__N = Parameter definition missed for: {0}
ParametersSectionCheck_Remove_useless_parameter_section = Remove useless parameter section
ParametersSectionCheck_description = Documentation comment parameter section missed parameter definition
ParametersSectionCheck_title = Documentation comment parameter section missed parameter definition
ProcedureReturnSectionCheck_Procedure_should_has_no_return_section = Return section is not allowed for procedure
ProcedureReturnSectionCheck_description = Documentation comment has return section for procedure
ProcedureReturnSectionCheck_title = Documentation comment has return section for procedure
RefLinkPartCheck_Allow_See_in_description = Allow 'See something' in description
RefLinkPartCheck_Link_referenced_to_unexisting_object = Link referenced to unexisting object
RefLinkPartCheck_description = Documentation comment link referenced object exist
RefLinkPartCheck_title = Documentation comment link referenced object exist
TypeDefinitionCheck_Unkown_type_M_specified = Unknown type "{0}" specified in documentation comment
TypeDefinitionCheck_description = Documentation comment type definition contains valid type name
TypeDefinitionCheck_title = Documentation comment type definition

View File

@@ -12,8 +12,96 @@
# 1C-Soft LLC - initial API and implementation
###############################################################################
CollectionTypeDefinitionCheck_Collection_type_should_have_contain_item_type = Тип коллекции должен содержать тип элемента коллекции
CollectionTypeDefinitionCheck_Collection_types = Типы коллекций
CollectionTypeDefinitionCheck_description = Тип коллекций в документирующем комментарии содержит тип элемента коллекции
CollectionTypeDefinitionCheck_title = Тип коллекций в документирующем комментарии содержит тип элемента коллекции
DocCommentUseMinusCheck_Only_hyphen_minus_symbol_is_allowed_in_doc_comment_but_found_0 = Только символ дефис-минуса разрешено использовать в документирующем комментарии, но найдено: "{0}"
DocCommentUseMinusCheck_description = Использование только дефис-минуса в документирующем комментарии
DocCommentUseMinusCheck_title = Использование только дефис-минуса в документирующем комментарии
ExportFunctionReturnSectionCheck_Export_function_return_section_required = Описание экспортируемой функции должно содержать блок "Возвращаемое значение"
ExportFunctionReturnSectionCheck_description = Секция возвращаемого значения документирующего комментария для экспортной функции
ExportFunctionReturnSectionCheck_title = Секция возвращаемого значения документирующего комментария для экспортной функции
FieldDefinitionNameCheck_Field_name__N__is_incorrect_name = Имя поля "{0}" является некорректным
FieldDefinitionNameCheck_description = Поле документирующего комментария является корректным именем
FieldDefinitionNameCheck_title = Поле документирующего комментария является корректным именем
FieldDefinitionTypeCheck_Field_M_has_no_type_definition = Поле "{0}" не имеет определения типа
FieldDefinitionTypeCheck_description = Поле документирующего комментария не имеет определения типа
FieldDefinitionTypeCheck_title = Поле документирующего комментария не имеет определения типа
FieldDefinitionTypeWithLinkRefCheck_Field__F__use_declaration_of_complex_type_instead_of_link = Поле "{0}" использует объявление сложного типа вместо ссылки на тип
FieldDefinitionTypeWithLinkRefCheck_description = Поле документирующего комментария использует объявление сложного типа вместо ссылки на тип
FieldDefinitionTypeWithLinkRefCheck_title = Поле документирующего комментария использует объявление сложного типа вместо ссылки на тип
FunctionReturnSectionCheck_Return_type_is_mandatory = Возвращаемый тип обязателен
FunctionReturnSectionCheck_Return_type_unknown = Возвращаемый тип не известен
FunctionReturnSectionCheck_description = Секция возвращаемого значения документирующего комментария содержит корректные типы
FunctionReturnSectionCheck_title = Секция возвращаемого значения документирующего комментария содержит корректные типы
MultilineDescriptionEndsOnDotCheck_Method_comment_doesnt_ends_on_dot = Комментарий метода не содержит точки в конце
MultilineDescriptionEndsOnDotCheck_description = Многострочное описание документирующего комментария оканчивается на точку
MultilineDescriptionEndsOnDotCheck_title = Многострочное описание документирующего комментария оканчивается на точку
MultilineDescriptionFieldSuggestionCheck_Probably_Field_is_defined_in_description = Возможно Поле указано в описании
MultilineDescriptionFieldSuggestionCheck_description = Многострочное описание документирующего комментария содержит определение поля
MultilineDescriptionFieldSuggestionCheck_title = Многострочное описание документирующего комментария содержит определение поля
MultilineDescriptionParameterSuggestionCheck_Probably_method_parameter_is_defined = Возможно параметр метода указан в описании
MultilineDescriptionParameterSuggestionCheck_description = Многострочное описание документирующего комментария содержит определение параметра
MultilineDescriptionParameterSuggestionCheck_title = Многострочное описание документирующего комментария содержит определение параметра
ParametersSectionCheck_Check_only_export_method_parameter_section = Проверять секцию параметров только экспортных методов
ParametersSectionCheck_Parameter_definition_missed_for__N = Пропущено определение параметра для: {0}
ParametersSectionCheck_Remove_useless_parameter_section = Удалите бесполезную секцию параметров
ParametersSectionCheck_description = В секции параметров документирующего комментария пропущено определение параметра
ParametersSectionCheck_title = В секции параметров документирующего комментария пропущено определение параметра
ProcedureReturnSectionCheck_Procedure_should_has_no_return_section = Описание процедуры не должно содержать блок "Возвращаемое значение"
ProcedureReturnSectionCheck_description = Документирующий комментарий содежрит секцию возвращаемого значения для процедуры
ProcedureReturnSectionCheck_title = Документирующий комментарий содежрит секцию возвращаемого значения для процедуры
RefLinkPartCheck_Allow_See_in_description = Разрешить 'См. сюда' в элементе описания
RefLinkPartCheck_Link_referenced_to_unexisting_object = Ссылка на несуществующий объект
RefLinkPartCheck_description = Ссылка документирующего комментария на существующий объект
RefLinkPartCheck_title = Ссылка документирующего комментария на существующий объект
TypeDefinitionCheck_Unkown_type_M_specified = Неизвестный тип "{0}" указан в документирующем комментарии
TypeDefinitionCheck_description = Определение типа документирующего комментария содержит правильное имя типа
TypeDefinitionCheck_title = Определение типа документирующего комментария

View File

@@ -0,0 +1,37 @@
/*******************************************************************************
* 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.qfix;
import org.eclipse.osgi.util.NLS;
/**
* @author Artem Iliukhin
*
*/
final class Messages
extends NLS
{
private static final String BUNDLE_NAME = "com.e1c.v8codestyle.bsl.qfix.messages"; //$NON-NLS-1$
public static String RemoveExportFix_Remove_export_keyword_des;
public static String RemoveExportFix_Remove_export_keyword_det;
static
{
// initialize resource bundle
NLS.initializeMessages(BUNDLE_NAME, Messages.class);
}
private Messages()
{
// N/A
}
}

Some files were not shown because too many files have changed in this diff Show More