From 4eedcf9ff697f8ab053d5d708ec72f9e844db8bf Mon Sep 17 00:00:00 2001 From: Dmitriy Marmyshev Date: Thu, 28 Oct 2021 19:18:20 +0300 Subject: [PATCH] =?UTF-8?q?#824=20=D0=90=D0=B2=D1=82=D0=BE=D0=BC=D0=B0?= =?UTF-8?q?=D1=82=D0=B8=D1=87=D0=B5=D1=81=D0=BA=D0=BE=D0=B5=20=D1=81=D0=BE?= =?UTF-8?q?=D0=B7=D0=B4=D0=B0=D0=BD=D0=B8=D0=B5=20=D1=81=D1=82=D1=80=D1=83?= =?UTF-8?q?=D0=BA=D1=82=D1=83=D1=80=D1=8B=20=D0=BC=D0=BE=D0=B4=D1=83=D0=BB?= =?UTF-8?q?=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + README.md | 1 + bom/pom.xml | 26 ++ .../META-INF/MANIFEST.MF | 12 +- .../plugin.properties | 4 + bundles/com.e1c.v8codestyle.bsl.ui/plugin.xml | 107 +++++ .../plugin_ru.properties | 6 +- .../bsl/ui/ExternalDependenciesModule.java | 9 + .../internal/bsl/ui/preferences/Messages.java | 35 ++ .../ModuleStructurePreferencePage.java | 61 +++ .../bsl/ui/preferences/messages.properties | 14 + .../bsl/ui/preferences/messages_ru.properties | 15 + .../internal/bsl/ui/properties/Messages.java | 40 ++ .../ModuleStructurePropertyPage.java | 367 ++++++++++++++++++ .../bsl/ui/properties/messages.properties | 24 ++ .../bsl/ui/properties/messages_ru.properties | 25 ++ ...tructureNewWizardRelatedModelsFactory.java | 249 ++++++++++++ .../META-INF/MANIFEST.MF | 3 +- .../com.e1c.v8codestyle.bsl/build.properties | 3 +- bundles/com.e1c.v8codestyle.bsl/plugin.xml | 6 + .../bsl/IModuleStructureProvider.java | 64 +++ .../v8codestyle/internal/bsl/BslPlugin.java | 4 +- .../internal/bsl/ModuleStructureProvider.java | 144 +++++++ ...tructureProviderPreferenceInitializer.java | 38 ++ .../internal/bsl/ServiceModule.java | 35 ++ .../templates/en/bot_module.bsl | 12 + .../templates/en/command_module.bsl | 14 + .../templates/en/common_module.bsl | 18 + .../templates/en/external_conn_module.bsl | 12 + .../templates/en/form_module.bsl | 36 ++ .../templates/en/http_service_module.bsl | 12 + .../en/integration_service_module.bsl | 12 + .../templates/en/managed_app_module.bsl | 20 + .../templates/en/manager_module.bsl | 28 ++ .../templates/en/object_module.bsl | 36 ++ .../templates/en/ordinary_app_module.bsl | 20 + .../templates/en/recordset_module.bsl | 36 ++ .../templates/en/session_module.bsl | 16 + .../templates/en/value_manager_module.bsl | 36 ++ .../templates/en/web_service_module.bsl | 12 + .../templates/ru/bot_module.bsl | 12 + .../templates/ru/command_module.bsl | 14 + .../templates/ru/common_module.bsl | 18 + .../templates/ru/external_conn_module.bsl | 12 + .../templates/ru/form_module.bsl | 36 ++ .../templates/ru/http_service_module.bsl | 12 + .../ru/integration_service_module.bsl | 12 + .../templates/ru/managed_app_module.bsl | 20 + .../templates/ru/manager_module.bsl | 28 ++ .../templates/ru/object_module.bsl | 36 ++ .../templates/ru/ordinary_app_module.bsl | 20 + .../templates/ru/recordset_module.bsl | 36 ++ .../templates/ru/session_module.bsl | 16 + .../templates/ru/value_manager_module.bsl | 36 ++ .../templates/ru/web_service_module.bsl | 12 + docs/README.md | 2 + docs/tools/module-structure.md | 55 +++ docs/tools/readme.md | 1 + .../ModuleStructurePreferencePageTest.java | 93 +++++ .../ModuleStructurePropertyPageTest.java | 314 +++++++++++++++ 60 files changed, 2392 insertions(+), 6 deletions(-) create mode 100644 bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/preferences/Messages.java create mode 100644 bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/preferences/ModuleStructurePreferencePage.java create mode 100644 bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/preferences/messages.properties create mode 100644 bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/preferences/messages_ru.properties create mode 100644 bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/properties/Messages.java create mode 100644 bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/properties/ModuleStructurePropertyPage.java create mode 100644 bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/properties/messages.properties create mode 100644 bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/properties/messages_ru.properties create mode 100644 bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/wizard/ModuleStructureNewWizardRelatedModelsFactory.java create mode 100644 bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/IModuleStructureProvider.java create mode 100644 bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/ModuleStructureProvider.java create mode 100644 bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/ModuleStructureProviderPreferenceInitializer.java create mode 100644 bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/ServiceModule.java create mode 100644 bundles/com.e1c.v8codestyle.bsl/templates/en/bot_module.bsl create mode 100644 bundles/com.e1c.v8codestyle.bsl/templates/en/command_module.bsl create mode 100644 bundles/com.e1c.v8codestyle.bsl/templates/en/common_module.bsl create mode 100644 bundles/com.e1c.v8codestyle.bsl/templates/en/external_conn_module.bsl create mode 100644 bundles/com.e1c.v8codestyle.bsl/templates/en/form_module.bsl create mode 100644 bundles/com.e1c.v8codestyle.bsl/templates/en/http_service_module.bsl create mode 100644 bundles/com.e1c.v8codestyle.bsl/templates/en/integration_service_module.bsl create mode 100644 bundles/com.e1c.v8codestyle.bsl/templates/en/managed_app_module.bsl create mode 100644 bundles/com.e1c.v8codestyle.bsl/templates/en/manager_module.bsl create mode 100644 bundles/com.e1c.v8codestyle.bsl/templates/en/object_module.bsl create mode 100644 bundles/com.e1c.v8codestyle.bsl/templates/en/ordinary_app_module.bsl create mode 100644 bundles/com.e1c.v8codestyle.bsl/templates/en/recordset_module.bsl create mode 100644 bundles/com.e1c.v8codestyle.bsl/templates/en/session_module.bsl create mode 100644 bundles/com.e1c.v8codestyle.bsl/templates/en/value_manager_module.bsl create mode 100644 bundles/com.e1c.v8codestyle.bsl/templates/en/web_service_module.bsl create mode 100644 bundles/com.e1c.v8codestyle.bsl/templates/ru/bot_module.bsl create mode 100644 bundles/com.e1c.v8codestyle.bsl/templates/ru/command_module.bsl create mode 100644 bundles/com.e1c.v8codestyle.bsl/templates/ru/common_module.bsl create mode 100644 bundles/com.e1c.v8codestyle.bsl/templates/ru/external_conn_module.bsl create mode 100644 bundles/com.e1c.v8codestyle.bsl/templates/ru/form_module.bsl create mode 100644 bundles/com.e1c.v8codestyle.bsl/templates/ru/http_service_module.bsl create mode 100644 bundles/com.e1c.v8codestyle.bsl/templates/ru/integration_service_module.bsl create mode 100644 bundles/com.e1c.v8codestyle.bsl/templates/ru/managed_app_module.bsl create mode 100644 bundles/com.e1c.v8codestyle.bsl/templates/ru/manager_module.bsl create mode 100644 bundles/com.e1c.v8codestyle.bsl/templates/ru/object_module.bsl create mode 100644 bundles/com.e1c.v8codestyle.bsl/templates/ru/ordinary_app_module.bsl create mode 100644 bundles/com.e1c.v8codestyle.bsl/templates/ru/recordset_module.bsl create mode 100644 bundles/com.e1c.v8codestyle.bsl/templates/ru/session_module.bsl create mode 100644 bundles/com.e1c.v8codestyle.bsl/templates/ru/value_manager_module.bsl create mode 100644 bundles/com.e1c.v8codestyle.bsl/templates/ru/web_service_module.bsl create mode 100644 docs/tools/module-structure.md create mode 100644 tests/com.e1c.v8codestyle.bsl.ui.itests/src/com/e1c/v8codestyle/bsl/ui/itests/ModuleStructurePreferencePageTest.java create mode 100644 tests/com.e1c.v8codestyle.bsl.ui.itests/src/com/e1c/v8codestyle/bsl/ui/itests/ModuleStructurePropertyPageTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index d0678c1e..07ea1035 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ - Автосортировка метаданных, сортировка объектов верхнего уровня по умолчанию, для подчиненных настраивается - Выбор подходящего тип общего модуля из списка при создании нового - Панель "Bsl Документирующий комментарий" +- Автоматическое создание структуры модуля ### Новые проверки diff --git a/README.md b/README.md index 9c53b150..6c6b6355 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ - [Авто-сортировка метаданных](docs/tools/autosort.md) - [Создание общих модулей по типам](docs/tools/common-module-types.md) - [Панель "Bsl Документирующий комментарий"](docs/tools/bsl-doc-comment-view.md) + - [Автоматическое создание структуры модуля](docs/tools/module-structure.md) diff --git a/bom/pom.xml b/bom/pom.xml index 29910861..5328dd23 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -59,6 +59,32 @@ ${project.groupId}:${project.artifactId} ../../**/target/site/jacoco*/jacoco.xml + + e1,e2,e3,e4,t1,t2,t3,t4 + + java:S3008 + **/Messages.java + + java:S2696 + **/*Plugin.java + + java:S112 + **/*Plugin.java + + java:S3077 + **/*Plugin.java + + java:S112 + /tests/**/*.java + + java:S2259 + /tests/**/*.java + + java:S1130 + /tests/**/*.java + + java:S3011 + /tests/**/*.java diff --git a/bundles/com.e1c.v8codestyle.bsl.ui/META-INF/MANIFEST.MF b/bundles/com.e1c.v8codestyle.bsl.ui/META-INF/MANIFEST.MF index 7b9452d4..3794f52b 100644 --- a/bundles/com.e1c.v8codestyle.bsl.ui/META-INF/MANIFEST.MF +++ b/bundles/com.e1c.v8codestyle.bsl.ui/META-INF/MANIFEST.MF @@ -18,14 +18,22 @@ Bundle-RequiredExecutionEnvironment: JavaSE-11 Automatic-Module-Name: com.e1c.v8codestyle.bsl.ui Bundle-ActivationPolicy: lazy Bundle-Localization: plugin -Import-Package: com._1c.g5.v8.dt.bsl.comment;version="[3.0.0,4.0.0)", +Import-Package: 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="[4.0.0,5.0.0)", com._1c.g5.v8.dt.bsl.ui.editor;version="[8.0.0,9.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.platform;version="[10.0.0,11.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)", + com._1c.g5.v8.dt.ui.util;version="[6.0.0,7.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._1c.g5.wiring.binder;version="[1.1.0,2.0.0)", + com.e1c.v8codestyle.bsl;version="[0.1.0,0.2.0)", + com.e1c.v8codestyle.bsl.strict;version="[0.1.0,0.2.0)" diff --git a/bundles/com.e1c.v8codestyle.bsl.ui/plugin.properties b/bundles/com.e1c.v8codestyle.bsl.ui/plugin.properties index 7a09b374..cf2bdba7 100644 --- a/bundles/com.e1c.v8codestyle.bsl.ui/plugin.properties +++ b/bundles/com.e1c.v8codestyle.bsl.ui/plugin.properties @@ -15,6 +15,10 @@ pluginName = 1C:Code style V8 Bsl UI plugin +preferences.modulestructure.name = Module structure + +properties.modulestructure.name = Module structure + providerName = 1C-Soft LLC views.BslDocCommentView.name = Bsl Documentation Comment diff --git a/bundles/com.e1c.v8codestyle.bsl.ui/plugin.xml b/bundles/com.e1c.v8codestyle.bsl.ui/plugin.xml index a66f1379..794234b3 100644 --- a/bundles/com.e1c.v8codestyle.bsl.ui/plugin.xml +++ b/bundles/com.e1c.v8codestyle.bsl.ui/plugin.xml @@ -44,5 +44,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/com.e1c.v8codestyle.bsl.ui/plugin_ru.properties b/bundles/com.e1c.v8codestyle.bsl.ui/plugin_ru.properties index c61cf5ad..13dba8e9 100644 --- a/bundles/com.e1c.v8codestyle.bsl.ui/plugin_ru.properties +++ b/bundles/com.e1c.v8codestyle.bsl.ui/plugin_ru.properties @@ -1,3 +1,4 @@ +#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/) ############################################################################### # Copyright (C) 2021, 1C-Soft LLC and others. # @@ -10,10 +11,13 @@ # Contributors: # 1C-Soft LLC - initial API and implementation ############################################################################### -#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/) pluginName = 1С:Стандарты разработки V8 UI плагин Встроенного языка +preferences.modulestructure.name = Структура модуля + +properties.modulestructure.name = Структура модуля + providerName = ООО "1С-Софт" views.BslDocCommentView.name = Bsl Документирующий комментарий diff --git a/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/ExternalDependenciesModule.java b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/ExternalDependenciesModule.java index 4f81242a..52477ac6 100644 --- a/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/ExternalDependenciesModule.java +++ b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/ExternalDependenciesModule.java @@ -15,8 +15,11 @@ package com.e1c.v8codestyle.internal.bsl.ui; 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.platform.IResourceLookup; +import com._1c.g5.v8.dt.core.platform.IV8ProjectManager; import com._1c.g5.wiring.AbstractServiceAwareModule; +import com.e1c.v8codestyle.bsl.IModuleStructureProvider; /** * The external dependencies for plugin @@ -36,8 +39,14 @@ class ExternalDependenciesModule @Override protected void doConfigure() { + // V8 services bind(IResourceLookup.class).toService(); bind(IBslPreferences.class).toService(); + bind(IQualifiedNameFilePathConverter.class).toService(); + bind(IV8ProjectManager.class).toService(); + + // CodeStyle Services + bind(IModuleStructureProvider.class).toService(); } } diff --git a/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/preferences/Messages.java b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/preferences/Messages.java new file mode 100644 index 00000000..7462c51b --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/preferences/Messages.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * 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.internal.bsl.ui.preferences; + +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.preferences.messages"; //$NON-NLS-1$ + public static String ModuleStructurePreferencePage_Automatically_create_module_structure; + static + { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + private Messages() + { + } +} diff --git a/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/preferences/ModuleStructurePreferencePage.java b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/preferences/ModuleStructurePreferencePage.java new file mode 100644 index 00000000..81c2beaa --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/preferences/ModuleStructurePreferencePage.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * 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.internal.bsl.ui.preferences; + +import org.eclipse.core.runtime.preferences.InstanceScope; +import org.eclipse.jface.preference.BooleanFieldEditor; +import org.eclipse.jface.preference.FieldEditorPreferencePage; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; +import org.eclipse.ui.preferences.ScopedPreferenceStore; + +import com.e1c.v8codestyle.bsl.IModuleStructureProvider; + +/** + * The preference page of module structure settings. + * Allows to disable auto-creating module structure. + * + * @author Dmitriy Marmyshev + */ +public class ModuleStructurePreferencePage + extends FieldEditorPreferencePage + implements IWorkbenchPreferencePage +{ + + /** + * Instantiates a new module structure preference page. + */ + public ModuleStructurePreferencePage() + { + super(GRID); + IPreferenceStore preferenceStore = + new ScopedPreferenceStore(InstanceScope.INSTANCE, IModuleStructureProvider.PREF_QUALIFIER); + setPreferenceStore(preferenceStore); + } + + @Override + public void createFieldEditors() + { + addField(new BooleanFieldEditor(IModuleStructureProvider.PREF_KEY_CREATE_STRUCTURE, + Messages.ModuleStructurePreferencePage_Automatically_create_module_structure, getFieldEditorParent())); + + } + + @Override + public void init(IWorkbench workbench) + { + // Do nothing + } + +} diff --git a/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/preferences/messages.properties b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/preferences/messages.properties new file mode 100644 index 00000000..1794061a --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/preferences/messages.properties @@ -0,0 +1,14 @@ +############################################################################### +# 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 +############################################################################### + +ModuleStructurePreferencePage_Automatically_create_module_structure = &Automatically create module structure diff --git a/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/preferences/messages_ru.properties b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/preferences/messages_ru.properties new file mode 100644 index 00000000..ef2c6e54 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/preferences/messages_ru.properties @@ -0,0 +1,15 @@ +############################################################################### +# 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 +############################################################################### +#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/) + +ModuleStructurePreferencePage_Automatically_create_module_structure = &Автоматически создавать структуру модуля diff --git a/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/properties/Messages.java b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/properties/Messages.java new file mode 100644 index 00000000..04d1af61 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/properties/Messages.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * 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.internal.bsl.ui.properties; + +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.properties.messages"; //$NON-NLS-1$ + public static String ModuleStructurePropertyPage_Automatically_create_module_structure; + public static String ModuleStructurePropertyPage_Open_template; + public static String ModuleStructurePropertyPage_Open_template_tooltip; + public static String ModuleStructurePropertyPage_Save_custom_template_to_project_settings; + public static String ModuleStructurePropertyPage_Save_settings; + public static String ModuleStructurePropertyPage_Select_module_type_to_create_custom_structure_templates; + static + { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + private Messages() + { + } +} diff --git a/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/properties/ModuleStructurePropertyPage.java b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/properties/ModuleStructurePropertyPage.java new file mode 100644 index 00000000..23457942 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/properties/ModuleStructurePropertyPage.java @@ -0,0 +1,367 @@ +/******************************************************************************* + * 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.internal.bsl.ui.properties; + +import static com.e1c.v8codestyle.bsl.strict.StrictTypeUtil.BSL_FILE_EXTENSION; + +import java.io.IOException; +import java.io.InputStream; +import java.util.HashSet; +import java.util.Set; +import java.util.function.Supplier; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.ProjectScope; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.preferences.IEclipsePreferences; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.preference.PreferenceDialog; +import org.eclipse.jface.preference.PreferencePage; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.CheckboxTableViewer; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.ui.dialogs.PropertyPage; +import org.osgi.service.prefs.BackingStoreException; + +import com._1c.g5.v8.dt.bsl.model.ModuleType; +import com._1c.g5.v8.dt.common.FileUtil; +import com._1c.g5.v8.dt.common.StringUtils; +import com._1c.g5.v8.dt.core.platform.IV8Project; +import com._1c.g5.v8.dt.core.platform.IV8ProjectManager; +import com._1c.g5.v8.dt.metadata.mdclass.ScriptVariant; +import com._1c.g5.v8.dt.ui.util.OpenHelper; +import com.e1c.v8codestyle.bsl.IModuleStructureProvider; +import com.e1c.v8codestyle.internal.bsl.ui.UiPlugin; +import com.google.inject.Inject; + +/** + * The property page of module structure settings. + * Allows to disable auto-creating module structure or manage custom project templates. + * + * @author Dmitriy Marmyshev + */ +public class ModuleStructurePropertyPage + extends PropertyPage +{ + private static final IPath FOLDER_SETTINGS = new Path(".settings/templates"); //$NON-NLS-1$ + + private final IModuleStructureProvider moduleStructureProvider; + + private final IV8ProjectManager v8ProjectManager; + + private Button createStructureButton; + + private CheckboxTableViewer checkBoxViewer; + + private final Set existTemplates = new HashSet<>(); + + private boolean currentCreateStructure; + + private final OpenHelper openHelper = new OpenHelper(); + + /** + * Constructor for module structure Property Page. + * + * @param moduleStructureProvider the module structure provider, cannot be {@code null}. + * @param v8ProjectManager the v8 project manager, cannot be {@code null}. + */ + @Inject + public ModuleStructurePropertyPage(IModuleStructureProvider moduleStructureProvider, + IV8ProjectManager v8ProjectManager) + { + super(); + this.moduleStructureProvider = moduleStructureProvider; + this.v8ProjectManager = v8ProjectManager; + } + + /** + * @see PreferencePage#createContents(Composite) + */ + @Override + protected Control createContents(Composite parent) + { + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + composite.setLayout(layout); + GridData data = new GridData(GridData.FILL); + data.grabExcessHorizontalSpace = true; + composite.setLayoutData(data); + + addFirstSection(composite); + addSeparator(composite); + addSecondSection(composite); + + return composite; + } + + private Composite createDefaultComposite(Composite parent) + { + Composite composite = new Composite(parent, SWT.NULL); + GridLayout layout = new GridLayout(); + layout.numColumns = 2; + composite.setLayout(layout); + + GridData data = new GridData(); + data.verticalAlignment = GridData.FILL; + data.horizontalAlignment = GridData.FILL; + composite.setLayoutData(data); + + return composite; + } + + @Override + protected void performDefaults() + { + super.performDefaults(); + createStructureButton.setSelection(IModuleStructureProvider.PREF_DEFAULT_CREATE_STRUCTURE); + existTemplates.forEach(type -> checkBoxViewer.setChecked(type, true)); + } + + @Override + public boolean performOk() + { + ProjectScope scope = new ProjectScope(getProject()); + IEclipsePreferences node = scope.getNode(IModuleStructureProvider.PREF_QUALIFIER); + boolean value = createStructureButton.getSelection(); + node.putBoolean(IModuleStructureProvider.PREF_KEY_CREATE_STRUCTURE, value); + try + { + node.flush(); + } + catch (BackingStoreException e) + { + UiPlugin.logError(e); + return false; + } + currentCreateStructure = value; + for (ModuleType type : ModuleType.VALUES) + { + if (checkBoxViewer.getChecked(type) && !existTemplates.contains(type)) + { + saveTemplate(type); + } + else if (existTemplates.contains(type) && !checkBoxViewer.getChecked(type)) + { + removeTemplate(type); + } + } + loadExistTemplate(); + return true; + } + + private void saveTemplate(ModuleType type) + { + IFile file = getFileByType(type); + if (file.isAccessible()) + { + return; + } + IV8Project v8Project = v8ProjectManager.getProject(getProject()); + if (v8Project == null) + { + return; + } + ScriptVariant script = v8Project.getScriptVariant(); + Supplier content = moduleStructureProvider.getModuleStructureTemplate(getProject(), type, script); + if (content == null) + { + return; + } + try + { + FileUtil.createParentFolders(file); + } + catch (CoreException e) + { + UiPlugin.logError(e); + return; + } + + try (InputStream in = content.get()) + { + file.create(in, true, new NullProgressMonitor()); + } + catch (CoreException | IOException e) + { + UiPlugin.logError(e); + } + + } + + private void removeTemplate(ModuleType type) + { + IFile file = getFileByType(type); + if (!file.isAccessible()) + { + return; + } + try + { + file.delete(true, true, new NullProgressMonitor()); + } + catch (CoreException e) + { + UiPlugin.logError(e); + } + } + + private void addFirstSection(Composite parent) + { + Composite composite = createDefaultComposite(parent); + + Label createStructureLabel = new Label(composite, SWT.NONE); + createStructureLabel.setText(Messages.ModuleStructurePropertyPage_Automatically_create_module_structure); + + currentCreateStructure = moduleStructureProvider.canCreateStructure(getProject()); + + createStructureButton = new Button(composite, SWT.CHECK); + createStructureButton.setSelection(currentCreateStructure); + + } + + private void addSeparator(Composite parent) + { + Label separator = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL); + GridData gridData = new GridData(); + gridData.horizontalAlignment = GridData.FILL; + gridData.grabExcessHorizontalSpace = true; + separator.setLayoutData(gridData); + } + + private void addSecondSection(Composite parent) + { + Composite composite = createDefaultComposite(parent); + + Label customTemplatesLabel = new Label(composite, SWT.NONE | SWT.WRAP); + customTemplatesLabel + .setText(Messages.ModuleStructurePropertyPage_Select_module_type_to_create_custom_structure_templates); + GridData data = new GridData(); + data.horizontalAlignment = GridData.FILL; + data.horizontalSpan = 2; + customTemplatesLabel.setLayoutData(data); + + checkBoxViewer = CheckboxTableViewer.newCheckList(composite, + SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE | SWT.FULL_SELECTION | SWT.BORDER); + checkBoxViewer.setContentProvider(ArrayContentProvider.getInstance()); + checkBoxViewer.setLabelProvider(LabelProvider.createTextProvider(type -> { + if (type instanceof ModuleType) + { + String label = StringUtils.nameToText(((ModuleType)type).getName()).toLowerCase(); + return StringUtils.capitalize(label); + } + return type == null ? "" : type.toString(); //$NON-NLS-1$ + })); + + checkBoxViewer.setInput(ModuleType.VALUES); + + Composite buttonPanel = createDefaultComposite(composite); + Button openButton = new Button(buttonPanel, SWT.PUSH); + openButton.setText(Messages.ModuleStructurePropertyPage_Open_template); + openButton.setToolTipText(Messages.ModuleStructurePropertyPage_Open_template_tooltip); + openButton.setEnabled(false); + openButton.addSelectionListener(SelectionListener.widgetSelectedAdapter(e -> { + IStructuredSelection selection = checkBoxViewer.getStructuredSelection(); + if (!selection.isEmpty()) + { + ModuleType type = (ModuleType)selection.getFirstElement(); + saveSettingsAndOpenTemplateAndClose(type); + } + })); + checkBoxViewer.addPostSelectionChangedListener(e -> { + boolean enable = !e.getStructuredSelection().isEmpty() + && checkBoxViewer.getChecked(e.getStructuredSelection().getFirstElement()); + openButton.setEnabled(enable); + }); + + loadExistTemplate(); + + } + + private IProject getProject() + { + return (IProject)getElement(); + } + + private void loadExistTemplate() + { + existTemplates.clear(); + + for (ModuleType type : ModuleType.VALUES) + { + IFile file = getFileByType(type); + if (file.isAccessible()) + { + existTemplates.add(type); + } + } + + checkBoxViewer.setCheckedElements(new ModuleType[0]); + existTemplates.forEach(type -> checkBoxViewer.setChecked(type, true)); + } + + private IFile getFileByType(ModuleType type) + { + return getProject() + .getFile(FOLDER_SETTINGS.append(type.getName().toLowerCase()).addFileExtension(BSL_FILE_EXTENSION)); + } + + private boolean isDirty() + { + if (createStructureButton.getSelection() != currentCreateStructure) + { + return true; + } + Set checked = Set.of(checkBoxViewer.getCheckedElements()); + return !existTemplates.equals(checked); + } + + private void saveSettingsAndOpenTemplateAndClose(ModuleType type) + { + if (isDirty()) + { + if (!MessageDialog.openQuestion(getShell(), Messages.ModuleStructurePropertyPage_Save_settings, + Messages.ModuleStructurePropertyPage_Save_custom_template_to_project_settings)) + { + return; + } + if (!performOk()) + { + return; + } + } + getShell().getDisplay().asyncExec(() -> { + IFile file = getFileByType(type); + if (file.isAccessible()) + { + openHelper.openEditor(file, null); + } + }); + if (getContainer() instanceof PreferenceDialog) + { + ((PreferenceDialog)getContainer()).close(); + } + } +} diff --git a/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/properties/messages.properties b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/properties/messages.properties new file mode 100644 index 00000000..6219ee82 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/properties/messages.properties @@ -0,0 +1,24 @@ +############################################################################### +# 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 +############################################################################### + +ModuleStructurePropertyPage_Automatically_create_module_structure = Automatically create module structure + +ModuleStructurePropertyPage_Open_template = Open template + +ModuleStructurePropertyPage_Open_template_tooltip = Open existing custom project template with saving settings. + +ModuleStructurePropertyPage_Save_custom_template_to_project_settings = Save custom templates to the project settings? + +ModuleStructurePropertyPage_Save_settings = Save settings? + +ModuleStructurePropertyPage_Select_module_type_to_create_custom_structure_templates = Select module type to create custom structure templates.\nOr deselect to remove existing custom template. diff --git a/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/properties/messages_ru.properties b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/properties/messages_ru.properties new file mode 100644 index 00000000..96b79ed8 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/properties/messages_ru.properties @@ -0,0 +1,25 @@ +############################################################################### +# 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 +############################################################################### +#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/) + +ModuleStructurePropertyPage_Automatically_create_module_structure = Автоматически создавать структуру модуля + +ModuleStructurePropertyPage_Open_template = Открыть шаблон + +ModuleStructurePropertyPage_Open_template_tooltip = Открыть существующий шаблон проекта с сохранением настроек. + +ModuleStructurePropertyPage_Save_custom_template_to_project_settings = Сохранить шаблоны в настройки проекта? + +ModuleStructurePropertyPage_Save_settings = Сохранить настройки? + +ModuleStructurePropertyPage_Select_module_type_to_create_custom_structure_templates = Отметьте тип модуля чтобы создать пользовательский шаблон структуры модуля.\nИли снемите флажок чтобы удалить существующий пользовательский шаблон. diff --git a/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/wizard/ModuleStructureNewWizardRelatedModelsFactory.java b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/wizard/ModuleStructureNewWizardRelatedModelsFactory.java new file mode 100644 index 00000000..73015aa6 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/internal/bsl/ui/wizard/ModuleStructureNewWizardRelatedModelsFactory.java @@ -0,0 +1,249 @@ +/******************************************************************************* + * 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.internal.bsl.ui.wizard; + +import static com._1c.g5.v8.dt.bsl.model.BslPackage.Literals.MODULE; +import static com._1c.g5.v8.dt.metadata.mdclass.MdClassPackage.Literals.ABSTRACT_FORM__MODULE; + +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.Set; +import java.util.function.Supplier; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Path; +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.xtext.naming.QualifiedName; + +import com._1c.g5.v8.bm.core.IBmObject; +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.util.BslUtil; +import com._1c.g5.v8.dt.common.FileUtil; +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.metadata.mdclass.ScriptVariant; +import com._1c.g5.v8.dt.ui.wizards.IDtNewWizardContext; +import com._1c.g5.v8.dt.ui.wizards.IDtNewWizardRelatedModelsFactory; +import com.e1c.v8codestyle.bsl.IModuleStructureProvider; +import com.e1c.v8codestyle.internal.bsl.ui.UiPlugin; +import com.google.common.io.CharStreams; +import com.google.inject.Inject; + +/** + * A factory for creating module structure when creating new object in wizard. + * + * @author Dmitriy Marmyshev + */ +public class ModuleStructureNewWizardRelatedModelsFactory + implements IDtNewWizardRelatedModelsFactory +{ + + private static final String CURRENT_CODE = "%CURRENT_CODE%"; //$NON-NLS-1$ + + private static final String LINE_SEPARATOR_WIN = "\r\n"; //$NON-NLS-1$ + + private static final String LINE_SEPARATOR_LINUX = "\n"; //$NON-NLS-1$ + + private final IQualifiedNameFilePathConverter qualifiedNameFilePathConverter; + + private final IModuleStructureProvider moduleStructureProvider; + + /** + * Instantiates a new module structure new wizard related models factory. + * + * @param qualifiedNameFilePathConverter the qualified name file path converter service, cannot be {@code null}. + * @param moduleStructureProvider the module structure provider service, cannot be {@code null}. + */ + @Inject + public ModuleStructureNewWizardRelatedModelsFactory(IQualifiedNameFilePathConverter qualifiedNameFilePathConverter, + IModuleStructureProvider moduleStructureProvider) + { + this.qualifiedNameFilePathConverter = qualifiedNameFilePathConverter; + this.moduleStructureProvider = moduleStructureProvider; + } + + @Override + public void createModels(IDtNewWizardContext context, Set createdModels) + { + IProject project = context.getV8project().getProject(); + if (!moduleStructureProvider.canCreateStructure(project)) + { + return; + } + + AbstractForm formToAddModule = null; + for (EObject model : context.getRelatedModels()) + { + if (model instanceof AbstractForm) + { + formToAddModule = (AbstractForm)model; + } + else if (model instanceof Module) + { + formToAddModule = null; + Module module = (Module)model; + IFile bslFile = getModuleFile(module); + if (bslFile != null) + { + ModuleType type = BslUtil.computeModuleType(module, qualifiedNameFilePathConverter); + createOrUpdateModule(bslFile, type, context); + } + } + } + + if (formToAddModule != null) + { + IFile bslFile = getModuleFile(formToAddModule, project); + if (bslFile != null) + { + createOrUpdateModule(bslFile, ModuleType.FORM_MODULE, context); + + EObject module = createBslProxyModule(bslFile); + createdModels.add(module); + } + } + } + + private void createOrUpdateModule(IFile bslFile, ModuleType type, IDtNewWizardContext context) + { + ScriptVariant script = context.getV8project().getScriptVariant(); + Supplier content = + moduleStructureProvider.getModuleStructureTemplate(bslFile.getProject(), type, script); + if (content == null) + { + return; + } + + String currentCode = StringUtils.EMPTY; + if (bslFile.exists()) + { + 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(); + + try (InputStream template = content.get(); + Reader reader = new InputStreamReader(template, StandardCharsets.UTF_8);) + { + String text = CharStreams.toString(reader); + + // Depends where plug-in is build (Windows or Linux) need to fix line-endings with + // project settings. + String actualLineSeparator = resolveLineSeparator(text); + String preferedLineSeparator = PreferenceUtils.getLineSeparator(project); + if (!actualLineSeparator.equals(preferedLineSeparator)) + { + text = text.replace(actualLineSeparator, preferedLineSeparator); + } + + if (text.contains(CURRENT_CODE)) + { + text = text.replace(CURRENT_CODE, currentCode); + } + else if (!currentCode.isEmpty()) + { + text = text.concat(currentCode); + } + + InputStream in = new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8)); + if (bslFile.exists()) + { + bslFile.setContents(in, true, true, new NullProgressMonitor()); + } + else + { + createParentFolders(bslFile); + bslFile.create(in, true, new NullProgressMonitor()); + } + } + catch (CoreException | IOException e) + { + IStatus status = UiPlugin.createErrorStatus("Can't create bsl file with name: " + bslFile.getName(), e); //$NON-NLS-1$ + UiPlugin.log(status); + } + } + + private String resolveLineSeparator(String text) + { + return text.contains(LINE_SEPARATOR_WIN) ? LINE_SEPARATOR_WIN : LINE_SEPARATOR_LINUX; + } + + private EObject createBslProxyModule(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 IFile getModuleFile(Module model) + { + URI uri = EcoreUtil.getURI(model); + + if (uri != null && uri.isPlatform()) + { + IPath path = new Path(uri.trimFragment().toPlatformString(true)); + return ResourcesPlugin.getWorkspace().getRoot().getFile(path); + } + return null; + } + + private IFile getModuleFile(AbstractForm model, IProject project) + { + String fqn = ((IBmObject)model).bmGetFqn(); + + QualifiedName name = QualifiedName.create(fqn).append(StringUtils.capitalize(ABSTRACT_FORM__MODULE.getName())); + + IPath path = qualifiedNameFilePathConverter.getFilePath(name, MODULE); + + return project.getFile(path); + } + + private void createParentFolders(IFile bslFile) + { + try + { + FileUtil.createParentFolders(bslFile); + } + catch (Exception e) + { + // skip if cannot create parent folders in other threads + } + } + +} diff --git a/bundles/com.e1c.v8codestyle.bsl/META-INF/MANIFEST.MF b/bundles/com.e1c.v8codestyle.bsl/META-INF/MANIFEST.MF index 36ebbe2d..8bef6b4e 100644 --- a/bundles/com.e1c.v8codestyle.bsl/META-INF/MANIFEST.MF +++ b/bundles/com.e1c.v8codestyle.bsl/META-INF/MANIFEST.MF @@ -39,4 +39,5 @@ Import-Package: com._1c.g5.v8.bm.core;version="[7.0.0,8.0.0)", com.e1c.g5.v8.dt.check;version="[1.0.0,2.0.0)", com.e1c.g5.v8.dt.check.components;version="[1.0.0,2.0.0)", com.e1c.g5.v8.dt.check.settings;version="[1.0.0,2.0.0)" -Export-Package: com.e1c.v8codestyle.bsl.strict;version="0.1.0" +Export-Package: com.e1c.v8codestyle.bsl;version="0.1.0", + com.e1c.v8codestyle.bsl.strict;version="0.1.0" diff --git a/bundles/com.e1c.v8codestyle.bsl/build.properties b/bundles/com.e1c.v8codestyle.bsl/build.properties index 981a2668..d8e9ca62 100644 --- a/bundles/com.e1c.v8codestyle.bsl/build.properties +++ b/bundles/com.e1c.v8codestyle.bsl/build.properties @@ -17,4 +17,5 @@ bin.includes = META-INF/,\ plugin.xml,\ plugin.properties,\ plugin_ru.properties,\ - check.descriptions/ + check.descriptions/,\ + templates/ diff --git a/bundles/com.e1c.v8codestyle.bsl/plugin.xml b/bundles/com.e1c.v8codestyle.bsl/plugin.xml index 5ddc00cf..e8c19fa7 100644 --- a/bundles/com.e1c.v8codestyle.bsl/plugin.xml +++ b/bundles/com.e1c.v8codestyle.bsl/plugin.xml @@ -114,5 +114,11 @@ + + + + diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/IModuleStructureProvider.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/IModuleStructureProvider.java new file mode 100644 index 00000000..fee64f71 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/IModuleStructureProvider.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * Copyright (C) 2021, 1C-Soft LLC and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * 1C-Soft LLC - initial API and implementation + *******************************************************************************/ +package com.e1c.v8codestyle.bsl; + +import java.io.InputStream; +import java.util.function.Supplier; + +import org.eclipse.core.resources.IProject; + +import com._1c.g5.v8.dt.bsl.model.ModuleType; +import com._1c.g5.v8.dt.metadata.mdclass.ScriptVariant; +import com.e1c.v8codestyle.internal.bsl.BslPlugin; + +/** + * The provider of module structure template by module type. + * This service return either template from project settings or default template from the bundle. + * + * + * @author Dmitriy Marmyshev + */ +public interface IModuleStructureProvider +{ + + /** The preference root qualifier. */ + String PREF_QUALIFIER = BslPlugin.PLUGIN_ID; + + /** The key for preferences store the state of the creating module structure. */ + String PREF_KEY_CREATE_STRUCTURE = "createModuleStructure"; //$NON-NLS-1$ + + /** The default value of creating module structure. */ + boolean PREF_DEFAULT_CREATE_STRUCTURE = true; + + + /** + * Can create module structure template for the project. This checks project or default settings. + * + * @param project the project, cannot be {@code null}. + * @return true, if can create module structure for the project + */ + boolean canCreateStructure(IProject project); + + /** + * Gets the module structure template supplier of input stream. + * + * @param project the project, cannot be {@code null}. + * @param moduleType the module type, cannot be {@code null}. + * @param script the script, cannot be {@code null}. + * @return the module structure template supplier of input stream, may return {@code null} if there is no template + * for such module type and script variant. + */ + Supplier getModuleStructureTemplate(IProject project, ModuleType moduleType, ScriptVariant script); + + +} diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/BslPlugin.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/BslPlugin.java index 92c466e7..7269e4ed 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/BslPlugin.java +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/BslPlugin.java @@ -20,6 +20,7 @@ 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.e1c.v8codestyle.bsl.IModuleStructureProvider; import com.google.inject.Guice; import com.google.inject.Injector; @@ -131,6 +132,7 @@ public class BslPlugin ServiceInitialization.schedule(() -> { // register services from injector + registrator.service(IModuleStructureProvider.class).registerInjected(); }); } @@ -180,7 +182,7 @@ public class BslPlugin { try { - return Guice.createInjector(new ExternalDependenciesModule(this)); + return Guice.createInjector(new ServiceModule(), new ExternalDependenciesModule(this)); } catch (Exception e) { diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/ModuleStructureProvider.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/ModuleStructureProvider.java new file mode 100644 index 00000000..1cedd417 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/ModuleStructureProvider.java @@ -0,0 +1,144 @@ +/******************************************************************************* + * 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.internal.bsl; + +import static com.e1c.v8codestyle.bsl.strict.StrictTypeUtil.BSL_FILE_EXTENSION; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.text.MessageFormat; +import java.util.Optional; +import java.util.function.Supplier; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.ProjectScope; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.FileLocator; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.preferences.ConfigurationScope; +import org.eclipse.core.runtime.preferences.DefaultScope; +import org.eclipse.core.runtime.preferences.IScopeContext; +import org.eclipse.core.runtime.preferences.InstanceScope; + +import com._1c.g5.v8.dt.bsl.model.ModuleType; +import com._1c.g5.v8.dt.metadata.mdclass.ScriptVariant; +import com.e1c.v8codestyle.bsl.IModuleStructureProvider; + +/** + * The default implementation of module structure provider. + * + * @author Dmitriy Marmyshev + */ +public class ModuleStructureProvider + implements IModuleStructureProvider +{ + + private static final String FOLDER_RU = "/templates/ru/"; //$NON-NLS-1$ + + private static final String FOLDER_EN = "/templates/en/"; //$NON-NLS-1$ + + private static final IPath FOLDER_SETTINGS = new org.eclipse.core.runtime.Path(".settings/templates"); //$NON-NLS-1$ + + @Override + public boolean canCreateStructure(IProject project) + { + ProjectScope scope = new ProjectScope(project); + IScopeContext[] contexts = + new IScopeContext[] { scope, InstanceScope.INSTANCE, ConfigurationScope.INSTANCE, DefaultScope.INSTANCE }; + + return Platform.getPreferencesService() + .getBoolean(PREF_QUALIFIER, PREF_KEY_CREATE_STRUCTURE, PREF_DEFAULT_CREATE_STRUCTURE, contexts); + } + + @Override + public Supplier getModuleStructureTemplate(IProject project, ModuleType moduleType, + ScriptVariant script) + { + + if (moduleType == null || script == null) + { + return null; + } + + StringBuilder sb = new StringBuilder(); + sb.append(moduleType.getName().toLowerCase()); + sb.append("."); //$NON-NLS-1$ + sb.append(BSL_FILE_EXTENSION); + + IFile templateFile = project.getFile(FOLDER_SETTINGS.append(sb.toString())); + + if (script == ScriptVariant.ENGLISH) + { + sb.insert(0, FOLDER_EN); + } + else + { + sb.insert(0, FOLDER_RU); + } + String path = sb.toString(); + + if (templateFile.exists()) + { + return () -> { + try + { + return templateFile.getContents(); + } + catch (CoreException e) + { + IStatus message = + BslPlugin.createErrorStatus("Cannot read tempate file " + templateFile.toString(), e); //$NON-NLS-1$ + BslPlugin.log(message); + } + return getClass().getResourceAsStream(path); + }; + } + + Optional template = getBundleEntry(path); + if (template.isPresent()) + { + return () -> getClass().getResourceAsStream(path); + } + String message = MessageFormat.format("Cannot find module template for type: {0} and language: {1} in {2}", //$NON-NLS-1$ + moduleType.getName(), script, path); + IStatus status = BslPlugin.createWarningStatus(message); + BslPlugin.log(status); + return null; + + } + + private Optional getBundleEntry(String path) + { + URL url = getClass().getResource(path); + if (url == null) + { + return Optional.empty(); + } + try + { + URL fileUrl = FileLocator.toFileURL(url); + return Optional.of(Paths.get(fileUrl.toURI())); + } + catch (IOException | java.net.URISyntaxException e) + { + BslPlugin.logError(e); + } + return Optional.empty(); + } +} diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/ModuleStructureProviderPreferenceInitializer.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/ModuleStructureProviderPreferenceInitializer.java new file mode 100644 index 00000000..1d28fa03 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/ModuleStructureProviderPreferenceInitializer.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * 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.internal.bsl; + +import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer; +import org.eclipse.core.runtime.preferences.DefaultScope; + +import com.e1c.v8codestyle.bsl.IModuleStructureProvider; + +/** + * Initializer of default values for module structure service. + * + * @author Dmitriy Marmyshev + */ +public class ModuleStructureProviderPreferenceInitializer + extends AbstractPreferenceInitializer +{ + + @Override + public void initializeDefaultPreferences() + { + DefaultScope.INSTANCE.getNode(IModuleStructureProvider.PREF_QUALIFIER) + .putBoolean(IModuleStructureProvider.PREF_KEY_CREATE_STRUCTURE, + IModuleStructureProvider.PREF_DEFAULT_CREATE_STRUCTURE); + + } + +} diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/ServiceModule.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/ServiceModule.java new file mode 100644 index 00000000..d7b38207 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/ServiceModule.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * 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.internal.bsl; + +import com.e1c.v8codestyle.bsl.IModuleStructureProvider; +import com.google.inject.AbstractModule; +import com.google.inject.Singleton; + +/** + * Internal services of the bundle. + * + * @author Dmitriy Marmyshev + */ +public class ServiceModule + extends AbstractModule +{ + + @Override + protected void configure() + { + bind(IModuleStructureProvider.class).to(ModuleStructureProvider.class).in(Singleton.class); + + } + +} diff --git a/bundles/com.e1c.v8codestyle.bsl/templates/en/bot_module.bsl b/bundles/com.e1c.v8codestyle.bsl/templates/en/bot_module.bsl new file mode 100644 index 00000000..6139d22b --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/templates/en/bot_module.bsl @@ -0,0 +1,12 @@ + +#Region EventHandlers + +// Enter code here. + +#EndRegion + +#Region Private + +// Enter code here. + +#EndRegion diff --git a/bundles/com.e1c.v8codestyle.bsl/templates/en/command_module.bsl b/bundles/com.e1c.v8codestyle.bsl/templates/en/command_module.bsl new file mode 100644 index 00000000..2b901cb5 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/templates/en/command_module.bsl @@ -0,0 +1,14 @@ + +#Region EventHandlers + +// Enter code here. + +%CURRENT_CODE% + +#EndRegion + +#Region Private + +// Enter code here. + +#EndRegion diff --git a/bundles/com.e1c.v8codestyle.bsl/templates/en/common_module.bsl b/bundles/com.e1c.v8codestyle.bsl/templates/en/common_module.bsl new file mode 100644 index 00000000..0906f51b --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/templates/en/common_module.bsl @@ -0,0 +1,18 @@ + +#Region Public + +// Enter code here. + +#EndRegion + +#Region Internal + +// Enter code here. + +#EndRegion + +#Region Private + +// Enter code here. + +#EndRegion diff --git a/bundles/com.e1c.v8codestyle.bsl/templates/en/external_conn_module.bsl b/bundles/com.e1c.v8codestyle.bsl/templates/en/external_conn_module.bsl new file mode 100644 index 00000000..6139d22b --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/templates/en/external_conn_module.bsl @@ -0,0 +1,12 @@ + +#Region EventHandlers + +// Enter code here. + +#EndRegion + +#Region Private + +// Enter code here. + +#EndRegion diff --git a/bundles/com.e1c.v8codestyle.bsl/templates/en/form_module.bsl b/bundles/com.e1c.v8codestyle.bsl/templates/en/form_module.bsl new file mode 100644 index 00000000..d7d43304 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/templates/en/form_module.bsl @@ -0,0 +1,36 @@ + +#Region Variables + +#EndRegion + +#Region FormEventHandlers + +// Enter code here. + +%CURRENT_CODE% + +#EndRegion + +#Region FormHeaderItemsEventHandlers + +// Enter code here. + +#EndRegion + +#Region FormTableItemsEventHandlers + +// Enter code here. + +#EndRegion + +#Region FormCommandsEventHandlers + +// Enter code here. + +#EndRegion + +#Region Private + +// Enter code here. + +#EndRegion diff --git a/bundles/com.e1c.v8codestyle.bsl/templates/en/http_service_module.bsl b/bundles/com.e1c.v8codestyle.bsl/templates/en/http_service_module.bsl new file mode 100644 index 00000000..6139d22b --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/templates/en/http_service_module.bsl @@ -0,0 +1,12 @@ + +#Region EventHandlers + +// Enter code here. + +#EndRegion + +#Region Private + +// Enter code here. + +#EndRegion diff --git a/bundles/com.e1c.v8codestyle.bsl/templates/en/integration_service_module.bsl b/bundles/com.e1c.v8codestyle.bsl/templates/en/integration_service_module.bsl new file mode 100644 index 00000000..6139d22b --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/templates/en/integration_service_module.bsl @@ -0,0 +1,12 @@ + +#Region EventHandlers + +// Enter code here. + +#EndRegion + +#Region Private + +// Enter code here. + +#EndRegion diff --git a/bundles/com.e1c.v8codestyle.bsl/templates/en/managed_app_module.bsl b/bundles/com.e1c.v8codestyle.bsl/templates/en/managed_app_module.bsl new file mode 100644 index 00000000..e1185695 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/templates/en/managed_app_module.bsl @@ -0,0 +1,20 @@ + +#Region Variables + +#EndRegion + +#Region EventHandlers + +// Enter code here. + +#EndRegion + +#Region Private + +// Enter code here. + +#EndRegion + +#Region Initialize + +#EndRegion diff --git a/bundles/com.e1c.v8codestyle.bsl/templates/en/manager_module.bsl b/bundles/com.e1c.v8codestyle.bsl/templates/en/manager_module.bsl new file mode 100644 index 00000000..5fddc9aa --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/templates/en/manager_module.bsl @@ -0,0 +1,28 @@ + +#If Server Or ThickClientOrdinaryApplication Or ExternalConnection Then + +#Region Public + +// Enter code here. + +#EndRegion + +#Region EventHandlers + +// Enter code here. + +#EndRegion + +#Region Internal + +// Enter code here. + +#EndRegion + +#Region Private + +// Enter code here. + +#EndRegion + +#EndIf diff --git a/bundles/com.e1c.v8codestyle.bsl/templates/en/object_module.bsl b/bundles/com.e1c.v8codestyle.bsl/templates/en/object_module.bsl new file mode 100644 index 00000000..38ac8212 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/templates/en/object_module.bsl @@ -0,0 +1,36 @@ + +#If Server Or ThickClientOrdinaryApplication Or ExternalConnection Then + +#Region Variables + +#EndRegion + +#Region Public + +// Enter code here. + +#EndRegion + +#Region EventHandlers + +// Enter code here. + +#EndRegion + +#Region Internal + +// Enter code here. + +#EndRegion + +#Region Private + +// Enter code here. + +#EndRegion + +#Region Initialize + +#EndRegion + +#EndIf diff --git a/bundles/com.e1c.v8codestyle.bsl/templates/en/ordinary_app_module.bsl b/bundles/com.e1c.v8codestyle.bsl/templates/en/ordinary_app_module.bsl new file mode 100644 index 00000000..e1185695 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/templates/en/ordinary_app_module.bsl @@ -0,0 +1,20 @@ + +#Region Variables + +#EndRegion + +#Region EventHandlers + +// Enter code here. + +#EndRegion + +#Region Private + +// Enter code here. + +#EndRegion + +#Region Initialize + +#EndRegion diff --git a/bundles/com.e1c.v8codestyle.bsl/templates/en/recordset_module.bsl b/bundles/com.e1c.v8codestyle.bsl/templates/en/recordset_module.bsl new file mode 100644 index 00000000..38ac8212 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/templates/en/recordset_module.bsl @@ -0,0 +1,36 @@ + +#If Server Or ThickClientOrdinaryApplication Or ExternalConnection Then + +#Region Variables + +#EndRegion + +#Region Public + +// Enter code here. + +#EndRegion + +#Region EventHandlers + +// Enter code here. + +#EndRegion + +#Region Internal + +// Enter code here. + +#EndRegion + +#Region Private + +// Enter code here. + +#EndRegion + +#Region Initialize + +#EndRegion + +#EndIf diff --git a/bundles/com.e1c.v8codestyle.bsl/templates/en/session_module.bsl b/bundles/com.e1c.v8codestyle.bsl/templates/en/session_module.bsl new file mode 100644 index 00000000..165f4542 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/templates/en/session_module.bsl @@ -0,0 +1,16 @@ + +#If Server Or ThickClientOrdinaryApplication Or ExternalConnection Then + +#Region EventHandlers + +// Enter code here. + +#EndRegion + +#Region Private + +// Enter code here. + +#EndRegion + +#EndIf diff --git a/bundles/com.e1c.v8codestyle.bsl/templates/en/value_manager_module.bsl b/bundles/com.e1c.v8codestyle.bsl/templates/en/value_manager_module.bsl new file mode 100644 index 00000000..38ac8212 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/templates/en/value_manager_module.bsl @@ -0,0 +1,36 @@ + +#If Server Or ThickClientOrdinaryApplication Or ExternalConnection Then + +#Region Variables + +#EndRegion + +#Region Public + +// Enter code here. + +#EndRegion + +#Region EventHandlers + +// Enter code here. + +#EndRegion + +#Region Internal + +// Enter code here. + +#EndRegion + +#Region Private + +// Enter code here. + +#EndRegion + +#Region Initialize + +#EndRegion + +#EndIf diff --git a/bundles/com.e1c.v8codestyle.bsl/templates/en/web_service_module.bsl b/bundles/com.e1c.v8codestyle.bsl/templates/en/web_service_module.bsl new file mode 100644 index 00000000..6139d22b --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/templates/en/web_service_module.bsl @@ -0,0 +1,12 @@ + +#Region EventHandlers + +// Enter code here. + +#EndRegion + +#Region Private + +// Enter code here. + +#EndRegion diff --git a/bundles/com.e1c.v8codestyle.bsl/templates/ru/bot_module.bsl b/bundles/com.e1c.v8codestyle.bsl/templates/ru/bot_module.bsl new file mode 100644 index 00000000..da45fd62 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/templates/ru/bot_module.bsl @@ -0,0 +1,12 @@ + +#Область ОбработчикиСобытий + +// Код процедур и функций + +#КонецОбласти + +#Область СлужебныеПроцедурыИФункции + +// Код процедур и функций + +#КонецОбласти diff --git a/bundles/com.e1c.v8codestyle.bsl/templates/ru/command_module.bsl b/bundles/com.e1c.v8codestyle.bsl/templates/ru/command_module.bsl new file mode 100644 index 00000000..b1ef6169 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/templates/ru/command_module.bsl @@ -0,0 +1,14 @@ + +#Область ОбработчикиСобытий + +// Код процедур и функций + +%CURRENT_CODE% + +#КонецОбласти + +#Область СлужебныеПроцедурыИФункции + +// Код процедур и функций + +#КонецОбласти diff --git a/bundles/com.e1c.v8codestyle.bsl/templates/ru/common_module.bsl b/bundles/com.e1c.v8codestyle.bsl/templates/ru/common_module.bsl new file mode 100644 index 00000000..411ea13e --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/templates/ru/common_module.bsl @@ -0,0 +1,18 @@ + +#Область ПрограммныйИнтерфейс + +// Код процедур и функций + +#КонецОбласти + +#Область СлужебныйПрограммныйИнтерфейс + +// Код процедур и функций + +#КонецОбласти + +#Область СлужебныеПроцедурыИФункции + +// Код процедур и функций + +#КонецОбласти diff --git a/bundles/com.e1c.v8codestyle.bsl/templates/ru/external_conn_module.bsl b/bundles/com.e1c.v8codestyle.bsl/templates/ru/external_conn_module.bsl new file mode 100644 index 00000000..da45fd62 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/templates/ru/external_conn_module.bsl @@ -0,0 +1,12 @@ + +#Область ОбработчикиСобытий + +// Код процедур и функций + +#КонецОбласти + +#Область СлужебныеПроцедурыИФункции + +// Код процедур и функций + +#КонецОбласти diff --git a/bundles/com.e1c.v8codestyle.bsl/templates/ru/form_module.bsl b/bundles/com.e1c.v8codestyle.bsl/templates/ru/form_module.bsl new file mode 100644 index 00000000..acbe8513 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/templates/ru/form_module.bsl @@ -0,0 +1,36 @@ + +#Область ОписаниеПеременных + +#КонецОбласти + +#Область ОбработчикиСобытийФормы + +// Код процедур и функций + +%CURRENT_CODE% + +#КонецОбласти + +#Область ОбработчикиСобытийЭлементовШапкиФормы + +// Код процедур и функций + +#КонецОбласти + +#Область ОбработчикиСобытийЭлементовТаблицыФормы<ИмяТаблицыФормы> + +// Код процедур и функций + +#КонецОбласти + +#Область ОбработчикиКомандФормы + +// Код процедур и функций + +#КонецОбласти + +#Область СлужебныеПроцедурыИФункции + +// Код процедур и функций + +#КонецОбласти diff --git a/bundles/com.e1c.v8codestyle.bsl/templates/ru/http_service_module.bsl b/bundles/com.e1c.v8codestyle.bsl/templates/ru/http_service_module.bsl new file mode 100644 index 00000000..da45fd62 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/templates/ru/http_service_module.bsl @@ -0,0 +1,12 @@ + +#Область ОбработчикиСобытий + +// Код процедур и функций + +#КонецОбласти + +#Область СлужебныеПроцедурыИФункции + +// Код процедур и функций + +#КонецОбласти diff --git a/bundles/com.e1c.v8codestyle.bsl/templates/ru/integration_service_module.bsl b/bundles/com.e1c.v8codestyle.bsl/templates/ru/integration_service_module.bsl new file mode 100644 index 00000000..da45fd62 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/templates/ru/integration_service_module.bsl @@ -0,0 +1,12 @@ + +#Область ОбработчикиСобытий + +// Код процедур и функций + +#КонецОбласти + +#Область СлужебныеПроцедурыИФункции + +// Код процедур и функций + +#КонецОбласти diff --git a/bundles/com.e1c.v8codestyle.bsl/templates/ru/managed_app_module.bsl b/bundles/com.e1c.v8codestyle.bsl/templates/ru/managed_app_module.bsl new file mode 100644 index 00000000..4f97f3e5 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/templates/ru/managed_app_module.bsl @@ -0,0 +1,20 @@ + +#Область ОписаниеПеременных + +#КонецОбласти + +#Область ОбработчикиСобытий + +// Код процедур и функций + +#КонецОбласти + +#Область СлужебныеПроцедурыИФункции + +// Код процедур и функций + +#КонецОбласти + +#Область Инициализация + +#КонецОбласти diff --git a/bundles/com.e1c.v8codestyle.bsl/templates/ru/manager_module.bsl b/bundles/com.e1c.v8codestyle.bsl/templates/ru/manager_module.bsl new file mode 100644 index 00000000..2d4c2bf9 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/templates/ru/manager_module.bsl @@ -0,0 +1,28 @@ + +#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда + +#Область ПрограммныйИнтерфейс + +// Код процедур и функций + +#КонецОбласти + +#Область ОбработчикиСобытий + +// Код процедур и функций + +#КонецОбласти + +#Область СлужебныйПрограммныйИнтерфейс + +// Код процедур и функций + +#КонецОбласти + +#Область СлужебныеПроцедурыИФункции + +// Код процедур и функций + +#КонецОбласти + +#КонецЕсли diff --git a/bundles/com.e1c.v8codestyle.bsl/templates/ru/object_module.bsl b/bundles/com.e1c.v8codestyle.bsl/templates/ru/object_module.bsl new file mode 100644 index 00000000..1e99f649 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/templates/ru/object_module.bsl @@ -0,0 +1,36 @@ + +#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда + +#Область ОписаниеПеременных + +#КонецОбласти + +#Область ПрограммныйИнтерфейс + +// Код процедур и функций + +#КонецОбласти + +#Область ОбработчикиСобытий + +// Код процедур и функций + +#КонецОбласти + +#Область СлужебныйПрограммныйИнтерфейс + +// Код процедур и функций + +#КонецОбласти + +#Область СлужебныеПроцедурыИФункции + +// Код процедур и функций + +#КонецОбласти + +#Область Инициализация + +#КонецОбласти + +#КонецЕсли diff --git a/bundles/com.e1c.v8codestyle.bsl/templates/ru/ordinary_app_module.bsl b/bundles/com.e1c.v8codestyle.bsl/templates/ru/ordinary_app_module.bsl new file mode 100644 index 00000000..4f97f3e5 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/templates/ru/ordinary_app_module.bsl @@ -0,0 +1,20 @@ + +#Область ОписаниеПеременных + +#КонецОбласти + +#Область ОбработчикиСобытий + +// Код процедур и функций + +#КонецОбласти + +#Область СлужебныеПроцедурыИФункции + +// Код процедур и функций + +#КонецОбласти + +#Область Инициализация + +#КонецОбласти diff --git a/bundles/com.e1c.v8codestyle.bsl/templates/ru/recordset_module.bsl b/bundles/com.e1c.v8codestyle.bsl/templates/ru/recordset_module.bsl new file mode 100644 index 00000000..1e99f649 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/templates/ru/recordset_module.bsl @@ -0,0 +1,36 @@ + +#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда + +#Область ОписаниеПеременных + +#КонецОбласти + +#Область ПрограммныйИнтерфейс + +// Код процедур и функций + +#КонецОбласти + +#Область ОбработчикиСобытий + +// Код процедур и функций + +#КонецОбласти + +#Область СлужебныйПрограммныйИнтерфейс + +// Код процедур и функций + +#КонецОбласти + +#Область СлужебныеПроцедурыИФункции + +// Код процедур и функций + +#КонецОбласти + +#Область Инициализация + +#КонецОбласти + +#КонецЕсли diff --git a/bundles/com.e1c.v8codestyle.bsl/templates/ru/session_module.bsl b/bundles/com.e1c.v8codestyle.bsl/templates/ru/session_module.bsl new file mode 100644 index 00000000..cac1cdec --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/templates/ru/session_module.bsl @@ -0,0 +1,16 @@ + +#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда + +#Область ОбработчикиСобытий + +// Код процедур и функций + +#КонецОбласти + +#Область СлужебныеПроцедурыИФункции + +// Код процедур и функций + +#КонецОбласти + +#КонецЕсли diff --git a/bundles/com.e1c.v8codestyle.bsl/templates/ru/value_manager_module.bsl b/bundles/com.e1c.v8codestyle.bsl/templates/ru/value_manager_module.bsl new file mode 100644 index 00000000..1e99f649 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/templates/ru/value_manager_module.bsl @@ -0,0 +1,36 @@ + +#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда + +#Область ОписаниеПеременных + +#КонецОбласти + +#Область ПрограммныйИнтерфейс + +// Код процедур и функций + +#КонецОбласти + +#Область ОбработчикиСобытий + +// Код процедур и функций + +#КонецОбласти + +#Область СлужебныйПрограммныйИнтерфейс + +// Код процедур и функций + +#КонецОбласти + +#Область СлужебныеПроцедурыИФункции + +// Код процедур и функций + +#КонецОбласти + +#Область Инициализация + +#КонецОбласти + +#КонецЕсли diff --git a/bundles/com.e1c.v8codestyle.bsl/templates/ru/web_service_module.bsl b/bundles/com.e1c.v8codestyle.bsl/templates/ru/web_service_module.bsl new file mode 100644 index 00000000..da45fd62 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/templates/ru/web_service_module.bsl @@ -0,0 +1,12 @@ + +#Область ОбработчикиСобытий + +// Код процедур и функций + +#КонецОбласти + +#Область СлужебныеПроцедурыИФункции + +// Код процедур и функций + +#КонецОбласти diff --git a/docs/README.md b/docs/README.md index d67beb5b..a3495832 100644 --- a/docs/README.md +++ b/docs/README.md @@ -13,6 +13,8 @@ - Дополнительные инструменты, улучшающие и ускоряющие работу по стандартам 1С - [Авто-сортировка метаданных](tools/autosort.md) - [Создание общих модулей по типам](tools/common-module-types.md) + - [Панель "Bsl Документирующий комментарий"](tools/bsl-doc-comment-view.md) + - [Автоматическое создание структуры модуля](tools/module-structure.md) ## Участие в проекте diff --git a/docs/tools/module-structure.md b/docs/tools/module-structure.md new file mode 100644 index 00000000..6c178fcc --- /dev/null +++ b/docs/tools/module-structure.md @@ -0,0 +1,55 @@ +# Автоматическое создание структуры модуля + +При создании объектов метаданных для всех модулей автоматически создается структура модуля. + +Для каждого из типов модулей используется своя структура модуля. Подробнее см. стандарт + +## Отключение авто-создания + +Для проекта можно принудительно отключить или включить создание структуры модуля. + +Отрокройте свйства проекта: `Properties -> V8 -> Built-in language -> Module structure -> Automatically create module structure`. + +Альтернативный способ: создать файл настроек `ProjectName/.settings/com.e1c.v8codestyle.bsl.prefs` с ключем управления созданием структуры модуля: + +``` + +eclipse.preferences.version=1 +createModuleStructure=false + +``` + +Для отключения создания структуры модуля в текущем воркспейсе откройте: + +Меню Window или 1C:EDT (в macOS): `Preferences -> V8 -> Built-in language -> Module structure -> Automatically create module structure`. + +Общие настройки могут быть заданы для всей инсталяции 1C:EDT или поствлятся через 1С:Стартер. + +## Переопределение шаблонов + +Отрокройте свйства проекта: `Properties -> V8 -> Built-in language -> Module structure`. +Установите флажок для тех типов модулей, для которых в текущем проекте следует изменить шаблон структуры модуля. + +При этом будет создан файл с типом модуля для которого необходимо переопределение. Например, для модуля менеджера: `ProjectName/.settings/templates/manager_module.bsl` + +Имена файлов модулей по типам: + +- `manager_module.bsl` - для модуля менеджера +- `object_module.bsl` - для модуля объекта +- `recordset_module.bsl` - для модуля набора записей регистра +- `command_module.bsl` - для модуля команды +- `form_module.bsl` - для модуля формы +- `common_module.bsl` - для общего модуля +- `value_manager_module.bsl` - для модуля менеджера значения константы +- `external_conn_module.bsl` - для модуля внешнего соединения +- `session_module.bsl` - для модуля сессии +- `managed_app_module.bsl` - для модуля приложения +- `ordinary_app_module.bsl` - для модуля обычного приложения +- `web_service_module.bsl` - для модуля веб-сервиса +- `http_service_module.bsl` - для модуля http-сервиса +- `integration_service_module.bsl` - для модуля сервиса интеграции +- `bot_module.bsl` - для модуля бота + +## См. также + +- [Стандарт 455: Структура модуля](https://its.1c.ru/db/v8std#content:455:hdoc) diff --git a/docs/tools/readme.md b/docs/tools/readme.md index 84e842e8..a0b0e592 100644 --- a/docs/tools/readme.md +++ b/docs/tools/readme.md @@ -5,3 +5,4 @@ - [Авто-сортировка метаданных](autosort.md) - [Создание общих модулей по типам](common-module-types.md) - [Панель "Bsl Документирующий комментарий"](bsl-doc-comment-view.md) +- [Автоматическое создание структуры модуля](module-structure.md) diff --git a/tests/com.e1c.v8codestyle.bsl.ui.itests/src/com/e1c/v8codestyle/bsl/ui/itests/ModuleStructurePreferencePageTest.java b/tests/com.e1c.v8codestyle.bsl.ui.itests/src/com/e1c/v8codestyle/bsl/ui/itests/ModuleStructurePreferencePageTest.java new file mode 100644 index 00000000..0f62de2a --- /dev/null +++ b/tests/com.e1c.v8codestyle.bsl.ui.itests/src/com/e1c/v8codestyle/bsl/ui/itests/ModuleStructurePreferencePageTest.java @@ -0,0 +1,93 @@ +/******************************************************************************* + * 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.ui.itests; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.preference.PreferenceDialog; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.dialogs.PreferencesUtil; +import org.eclipse.ui.intro.IIntroPart; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import com._1c.g5.v8.dt.testing.TestingWorkspace; +import com.e1c.v8codestyle.internal.bsl.ui.preferences.ModuleStructurePreferencePage; + +/** + * Integration test of the {@link ModuleStructurePreferencePage}. + * + * @author Dmitriy Marmyshev + */ +public class ModuleStructurePreferencePageTest +{ + private static final String PROJECT_NAME = "CommonModule"; + + private static final String PREFERENCE_PAGE_ID = + "com.e1c.v8codestyle.bsl.ui.preferences.ModuleStructurePreferencePage"; + + @Rule + public TestingWorkspace testingWorkspace = new TestingWorkspace(true, false); + + protected static final String FOLDER_RESOURCE = "/resources/"; + + private IProject project; + + @Before + public void setUp() throws CoreException + { + + project = testingWorkspace.getProject(PROJECT_NAME); + + if (!project.exists() || !project.isAccessible()) + { + testingWorkspace.cleanUpWorkspace(); + project = this.testingWorkspace.setUpProject(PROJECT_NAME, getClass()); + } + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().closeAllEditors(false); + + IIntroPart introPart = PlatformUI.getWorkbench().getIntroManager().getIntro(); + PlatformUI.getWorkbench().getIntroManager().closeIntro(introPart); + } + + @After + public void shutDown() + { + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().closeAllEditors(false); + } + + /** + * Test open module structure preference page. + * + * @throws Exception the exception + */ + @Test + public void testOpenModuleStructurePreferencePage() throws Exception + { + Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); + PreferenceDialog dialog = + PreferencesUtil.createPreferenceDialogOn(shell, + PREFERENCE_PAGE_ID, null, null); + + dialog.setBlockOnOpen(false); + shell.getDisplay().syncExec(dialog::open); + shell.getDisplay().syncExec(dialog::close); + } + +} diff --git a/tests/com.e1c.v8codestyle.bsl.ui.itests/src/com/e1c/v8codestyle/bsl/ui/itests/ModuleStructurePropertyPageTest.java b/tests/com.e1c.v8codestyle.bsl.ui.itests/src/com/e1c/v8codestyle/bsl/ui/itests/ModuleStructurePropertyPageTest.java new file mode 100644 index 00000000..053ab0b6 --- /dev/null +++ b/tests/com.e1c.v8codestyle.bsl.ui.itests/src/com/e1c/v8codestyle/bsl/ui/itests/ModuleStructurePropertyPageTest.java @@ -0,0 +1,314 @@ +/******************************************************************************* + * 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.ui.itests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.lang.reflect.Field; +import java.nio.charset.StandardCharsets; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; +import java.util.function.Supplier; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.jface.dialogs.DialogPage; +import org.eclipse.jface.preference.PreferenceDialog; +import org.eclipse.jface.preference.PreferencePage; +import org.eclipse.jface.viewers.CheckboxTableViewer; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.dialogs.PreferencesUtil; +import org.eclipse.ui.intro.IIntroPart; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import com._1c.g5.v8.dt.bsl.model.ModuleType; +import com._1c.g5.v8.dt.metadata.mdclass.ScriptVariant; +import com._1c.g5.v8.dt.testing.TestingWorkspace; +import com._1c.g5.wiring.ServiceAccess; +import com.e1c.v8codestyle.bsl.IModuleStructureProvider; +import com.e1c.v8codestyle.internal.bsl.ui.properties.ModuleStructurePropertyPage; +import com.google.common.io.CharStreams; + +/** + * Integration test of the {@link ModuleStructurePropertyPage}. + * + * @author Dmitriy Marmyshev + */ +public class ModuleStructurePropertyPageTest +{ + private static final String PROJECT_NAME = "CommonModule"; + + private static final String SETTINGS_TEMPLATES_COMMON_MODULE_BSL = ".settings/templates/common_module.bsl"; + + private static final String EDTOR_TITLE = "/" + PROJECT_NAME + "/" + SETTINGS_TEMPLATES_COMMON_MODULE_BSL; + + private static final String PROPERTY_PAGE_ID = + "com.e1c.v8codestyle.bsl.ui.properties.moduleStructurePropertyPage"; + + @Rule + public TestingWorkspace testingWorkspace = new TestingWorkspace(true, false); + + protected static final String FOLDER_RESOURCE = "/resources/"; + + private IProject project; + + @Before + public void setUp() throws CoreException + { + + project = testingWorkspace.getProject(PROJECT_NAME); + + if (!project.exists() || !project.isAccessible()) + { + testingWorkspace.cleanUpWorkspace(); + project = this.testingWorkspace.setUpProject(PROJECT_NAME, getClass()); + } + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().closeAllEditors(false); + + IIntroPart introPart = PlatformUI.getWorkbench().getIntroManager().getIntro(); + PlatformUI.getWorkbench().getIntroManager().closeIntro(introPart); + } + + @After + public void shutDown() + { + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().closeAllEditors(false); + } + + /** + * Test open and close module structure property page. + * + * @throws Exception the exception + */ + @Test + public void testOpenAndCloseModuleStructurePropertyPage() throws Exception + { + Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); + PreferenceDialog dialog = PreferencesUtil.createPropertyDialogOn(shell, project, PROPERTY_PAGE_ID, null, null); + + dialog.setBlockOnOpen(false); + shell.getDisplay().syncExec(dialog::open); + waitEventSetnd(dialog); + Object selected = dialog.getSelectedPage(); + assertTrue(selected instanceof ModuleStructurePropertyPage); + shell.getDisplay().syncExec(dialog::close); + } + + /** + * Test open module structure property page. + * + * @throws Exception the exception + */ + @Test + public void testOpenModuleTemplate() throws Exception + { + + IModuleStructureProvider moduleStructureProvider = ServiceAccess.get(IModuleStructureProvider.class); + Supplier templateProvider = moduleStructureProvider.getModuleStructureTemplate(project, + ModuleType.COMMON_MODULE, null); + assertNull(templateProvider); + templateProvider = moduleStructureProvider.getModuleStructureTemplate(project, null, ScriptVariant.ENGLISH); + assertNull(templateProvider); + templateProvider = moduleStructureProvider.getModuleStructureTemplate(project, + ModuleType.COMMON_MODULE, ScriptVariant.ENGLISH); + assertNotNull(templateProvider); + + Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); + PreferenceDialog dialog = PreferencesUtil.createPropertyDialogOn(shell, project, PROPERTY_PAGE_ID, null, null); + + dialog.setBlockOnOpen(false); + shell.getDisplay().syncExec(dialog::open); + Object selected = dialog.getSelectedPage(); + assertTrue(selected instanceof ModuleStructurePropertyPage); + ModuleStructurePropertyPage page = (ModuleStructurePropertyPage)selected; + + CheckboxTableViewer viewer = getViewer(page); + assertFalse(viewer.getChecked(ModuleType.COMMON_MODULE)); + viewer.setChecked(ModuleType.COMMON_MODULE, true); + + Button applyButton = getApplyButtonControl(page); + applyButton.notifyListeners(SWT.Selection, new Event()); + waitEventSetnd(dialog); + + Button buttonOpen = getButtonByName(page, "Open template"); + assertNotNull(buttonOpen); + + viewer.setSelection(new StructuredSelection(ModuleType.FORM_MODULE)); + waitEventSetnd(dialog); + assertFalse(buttonOpen.isEnabled()); + + viewer.setSelection(new StructuredSelection(ModuleType.COMMON_MODULE)); + waitEventSetnd(dialog); + assertTrue(buttonOpen.isEnabled()); + + + buttonOpen.notifyListeners(SWT.Selection, new Event()); + assertNull(dialog.getShell()); + waitEventSetnd(); + + // check editor content equals base template + IFile file = project.getFile(SETTINGS_TEMPLATES_COMMON_MODULE_BSL); + assertTrue(file.exists()); + + try (InputStream in = file.getContents(); + Reader fileReader = new InputStreamReader(in, StandardCharsets.UTF_8); + InputStream template = templateProvider.get(); + Reader templateReader = new InputStreamReader(template, StandardCharsets.UTF_8);) + { + String templateText = CharStreams.toString(templateReader); + assertNotNull(templateText); + String fileText = CharStreams.toString(fileReader); + assertEquals(templateText, fileText); + } + + // wait until open editor + waitEventSetnd(); + IEditorPart editor = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor(); + assertNotNull(editor); + assertEquals(EDTOR_TITLE, editor.getTitle()); + + String newContent = "New template"; + try (InputStream in = new ByteArrayInputStream(newContent.getBytes(StandardCharsets.UTF_8));) + { + file.setContents(in, true, true, new NullProgressMonitor()); + } + + templateProvider = moduleStructureProvider.getModuleStructureTemplate(project, ModuleType.COMMON_MODULE, + ScriptVariant.ENGLISH); + + try (InputStream in = file.getContents(); + Reader fileReader = new InputStreamReader(in, StandardCharsets.UTF_8); + InputStream template = templateProvider.get(); + Reader templateReader = new InputStreamReader(template, StandardCharsets.UTF_8);) + { + String templateText = CharStreams.toString(templateReader); + assertNotNull(templateText); + String fileText = CharStreams.toString(fileReader); + assertEquals(templateText, fileText); + } + + // re-open properties to check selection + dialog = PreferencesUtil.createPropertyDialogOn(shell, project, PROPERTY_PAGE_ID, null, null); + + dialog.setBlockOnOpen(false); + shell.getDisplay().syncExec(dialog::open); + selected = dialog.getSelectedPage(); + assertTrue(selected instanceof ModuleStructurePropertyPage); + page = (ModuleStructurePropertyPage)selected; + + viewer = getViewer(page); + assertTrue(viewer.getChecked(ModuleType.COMMON_MODULE)); + + viewer.setChecked(ModuleType.COMMON_MODULE, false); + + applyButton = getApplyButtonControl(page); + applyButton.notifyListeners(SWT.Selection, new Event()); + waitEventSetnd(dialog); + + shell.getDisplay().syncExec(dialog::close); + + assertFalse(file.exists()); + + } + + private CheckboxTableViewer getViewer(ModuleStructurePropertyPage page) throws Exception + { + Field field = page.getClass().getDeclaredField("checkBoxViewer"); + field.setAccessible(true); + return (CheckboxTableViewer)field.get(page); + } + + private Button getButtonByName(ModuleStructurePropertyPage page, String name) throws Exception + { + + Composite top = getTopControl(page); + assertNotNull(top); + Queue toCheck = new LinkedList<>(); + toCheck.add(top); + + while (!toCheck.isEmpty()) + { + Control control = toCheck.poll(); + if (control instanceof Button && name.equalsIgnoreCase(((Button)control).getText())) + { + return (Button)control; + } + else if (control instanceof Composite) + { + toCheck.addAll(List.of(((Composite)control).getChildren())); + } + } + + return null; + } + + private Composite getTopControl(ModuleStructurePropertyPage page) throws Exception + { + Field field = DialogPage.class.getDeclaredField("control"); + field.setAccessible(true); + return (Composite)field.get(page); + } + + private Button getApplyButtonControl(ModuleStructurePropertyPage page) throws Exception + { + Field field = PreferencePage.class.getDeclaredField("applyButton"); + field.setAccessible(true); + return (Button)field.get(page); + } + + private void waitEventSetnd(PreferenceDialog dialog) + { + Display display = dialog.getShell().getDisplay(); + while (!display.isDisposed() && display.readAndDispatch()) + { + // do it + } + } + + private void waitEventSetnd() + { + + Display display = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell().getDisplay(); + while (!display.isDisposed() && display.readAndDispatch()) + { + // do it + } + } + +}