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

Консольная команда сортировки проекта #1325 (#1326)

This commit is contained in:
Dmitriy Marmyshev 2023-05-25 10:29:31 +03:00 committed by GitHub
parent f06b252935
commit a8b9767305
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 475 additions and 9 deletions

View File

@ -51,6 +51,7 @@
- В свойствах проекта секция "Авто сортировка" теперь располагается по пути "V8 -> Сортировка объектов метаданных -> Авто сортировка"
- В свойствах проекта в секции "Авто сортировка" более недоступна настройка направления и порядка сортировки. Настройка направления и порядка сортировки доступна в секции "Сортировка объектов метаданных"
- В свойствах проекта в секции "Авто сортировка" добавлена возможность переноса заданных пользователем настроек направления и порядка сортировки в секцию "Сортировка объектов метаданных" и их очистки
- Добавлена консольная команда сортировки проекта
### Исправленные ошибки

View File

@ -1,4 +1,5 @@
eclipse.preferences.version=1
encoding//src/com/e1c/v8codestyle/internal/autosort/cli/messages_ru.properties=UTF-8
encoding//src/com/e1c/v8codestyle/internal/autosort/messages_ru.properties=UTF-8
encoding/<project>=UTF-8
encoding/plugin_ru.properties=UTF-8

View File

@ -26,10 +26,13 @@ Import-Package: com._1c.g5.v8.bm.common.collections;version="[4.0.0,5.0.0)",
com._1c.g5.v8.dt.lifecycle;version="[3.0.0,4.0.0)",
com._1c.g5.v8.dt.md.sort;version="[1.0.0,2.0.0)",
com._1c.g5.v8.dt.metadata.mdclass;version="[8.0.0,9.0.0)",
com.e1c.g5.v8.dt.cli.api;version="[1.0.0,2.0.0)",
com.e1c.g5.v8.dt.cli.api.components;version="[1.0.0,2.0.0)",
com.e1c.v8codestyle;version="[0.5.0,0.6.0)",
com.google.common.base;version="[30.1.0,31.0.0)",
com.google.inject;version="[5.0.1,6.0.0)",
com.google.inject.binder;version="[5.0.1,6.0.0)"
com.google.inject.binder;version="[5.0.1,6.0.0)",
org.slf4j;version="[1.7.2,2.0.0)"
Export-Package: com.e1c.v8codestyle.autosort;version="0.5.0";
uses:="org.eclipse.emf.ecore,
org.eclipse.core.runtime,

View File

@ -25,5 +25,11 @@
class="com.e1c.v8codestyle.internal.autosort.AutoSortProjectOptionProvider">
</provider>
</extension>
<extension
point="com.e1c.g5.v8.dt.cli.api.cliCommand">
<cliCommand
class="com.e1c.v8codestyle.internal.autosort.ExecutableExtensionFactory:com.e1c.v8codestyle.internal.autosort.cli.SortCommand">
</cliCommand>
</extension>
</plugin>

View File

@ -14,7 +14,7 @@ package com.e1c.v8codestyle.internal.autosort;
import org.osgi.framework.Bundle;
import com._1c.g5.wiring.AbstractGuiceAwareExecutableExtensionFactory;
import com.e1c.g5.v8.dt.cli.api.components.BaseCliCommandExtensionFactory;
import com.google.inject.Injector;
/**
@ -23,7 +23,7 @@ import com.google.inject.Injector;
* @author Dmitriy Marmyshev
*/
public class ExecutableExtensionFactory
extends AbstractGuiceAwareExecutableExtensionFactory
extends BaseCliCommandExtensionFactory
{
@Override
protected Bundle getBundle()

View File

@ -13,12 +13,11 @@
package com.e1c.v8codestyle.internal.autosort;
import org.eclipse.core.runtime.Plugin;
import com._1c.g5.v8.dt.core.model.IModelEditingSupport;
import com._1c.g5.v8.dt.core.platform.IBmModelManager;
import com._1c.g5.v8.dt.core.platform.IConfigurationProvider;
import com._1c.g5.v8.dt.core.platform.IDtProjectManager;
import com._1c.g5.v8.dt.core.platform.IWorkspaceOrchestrator;
import com._1c.g5.wiring.AbstractServiceAwareModule;
import com.e1c.g5.v8.dt.cli.api.components.BaseCliCommandExternalDependencyModule;
/**
* The external dependencies for AutoSort plugin
@ -26,7 +25,7 @@ import com._1c.g5.wiring.AbstractServiceAwareModule;
* @author Dmitriy Marmyshev
*/
class ExternalDependenciesModule
extends AbstractServiceAwareModule
extends BaseCliCommandExternalDependencyModule
{
ExternalDependenciesModule(Plugin plugin)
@ -37,11 +36,10 @@ class ExternalDependenciesModule
@Override
protected void doConfigure()
{
super.doConfigure();
// V8 DT
bind(IDtProjectManager.class).toService();
bind(IBmModelManager.class).toService();
bind(IConfigurationProvider.class).toService();
bind(IWorkspaceOrchestrator.class).toService();
bind(IModelEditingSupport.class).toService();
}

View File

@ -0,0 +1,41 @@
/*******************************************************************************
* Copyright (C) 2023, 1C-Soft LLC and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* 1C-Soft LLC - initial API and implementation
*******************************************************************************/
package com.e1c.v8codestyle.internal.autosort.cli;
import org.eclipse.osgi.util.NLS;
/**
* @author Dmitriy Marmyshev
*
*/
final class Messages
extends NLS
{
private static final String BUNDLE_NAME = Messages.class.getPackageName() + ".messages"; //$NON-NLS-1$
public static String SortCommand_Description;
public static String SortCommand_Project__0__did_not_import_into_workspace;
public static String SortCommand_Project__0__not_found_in_workspace;
public static String SortCommand_Project_names_Description;
public static String SortCommand_Project_paths_Description;
public static String SortCommand_Sort_project__0__finished;
public static String SortCommand_Sort_projects__0;
static
{
// initialize resource bundle
NLS.initializeMessages(BUNDLE_NAME, Messages.class);
}
private Messages()
{
}
}

View File

@ -0,0 +1,176 @@
/*******************************************************************************
* Copyright (C) 2023, 1C-Soft LLC and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* 1C-Soft LLC - initial API and implementation
*******************************************************************************/
package com.e1c.v8codestyle.internal.autosort.cli;
import java.io.File;
import java.nio.file.Path;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import com._1c.g5.v8.dt.core.operations.ProjectPipelineJob;
import com._1c.g5.v8.dt.core.platform.IDtProject;
import com.e1c.g5.v8.dt.cli.api.Argument;
import com.e1c.g5.v8.dt.cli.api.CliCommand;
import com.e1c.g5.v8.dt.cli.api.components.BaseCliCommand;
import com.e1c.v8codestyle.autosort.AutoSortPreferences;
import com.e1c.v8codestyle.autosort.ISortService;
import com.e1c.v8codestyle.internal.autosort.AutoSortPlugin;
import com.google.inject.Inject;
/**
* The CLI command allows to import and to sort project in workspace or to sort existing project in workspace.
* When it runs on each project it turns on default sort settings if not set up.
*
* @author Dmitriy Marmyshev
*/
public class SortCommand
extends BaseCliCommand
{
private final ISortService sortService;
@Inject
public SortCommand(ISortService sortService)
{
this.sortService = sortService;
}
/**
* Import projects into workspace and sort projects.
*
* @param projectPaths the project paths where to find all projects recursively
* @return the status of command
*/
@CliCommand(command = "sort-project", value = "SortCommand_Description")
public IStatus importAndSortProjects(@Argument(value = "--projects", elementType = Path.class,
descriptor = "SortCommand_Project_paths_Description") Path[] projectPaths)
{
if (projectPaths == null || projectPaths.length == 0)
{
return Status.OK_STATUS;
}
Path[] paths = new Path[projectPaths.length];
for (int i = 0; i < projectPaths.length; i++)
{
Path path = projectPaths[i];
paths[i] = path.toAbsolutePath();
}
Collection<File> projectFilePaths = findProjectsRecursively(paths);
List<IDtProject> projects = new ArrayList<>();
for (File prjectFile : projectFilePaths)
{
IDtProject dtProject = startDtProject(prjectFile.getParentFile().toPath());
if (dtProject != null && dtProject.getWorkspaceProject() != null)
{
projects.add(dtProject);
}
else
{
logError(
MessageFormat.format(Messages.SortCommand_Project__0__did_not_import_into_workspace, prjectFile));
}
}
if (projects.isEmpty())
{
// here we tried to import any project but not found - so command should be unsuccessful
return Status.CANCEL_STATUS;
}
sortProjects(projects);
return Status.OK_STATUS;
}
/**
* Sort projects that are existing in workspace.
*
* @param projectNames the project names
* @return the status of command
*/
@CliCommand(command = "sort-project", value = "SortCommand_Description")
public IStatus sortExistingProjects(@Argument(value = "--project-names", elementType = IProject.class,
descriptor = "SortCommand_Project_names_Description") IProject[] projectNames)
{
if (projectNames == null || projectNames.length == 0)
{
return Status.OK_STATUS;
}
List<IDtProject> projects = new ArrayList<>();
for (int i = 0; i < projectNames.length; i++)
{
IProject project = projectNames[i];
if (!project.isAccessible())
{
String error =
MessageFormat.format(Messages.SortCommand_Project__0__not_found_in_workspace, project.getName());
logError(error);
return AutoSortPlugin.createErrorStatus(error, null);
}
waitUntilStarted(project, DT_PROJECT_STARTUP_DURATION);
IDtProject dtProject = getContext().getDtProjectManager().getDtProject(project);
if (dtProject != null && dtProject.getWorkspaceProject() != null)
{
projects.add(dtProject);
}
else
{
logError(
MessageFormat.format(Messages.SortCommand_Project__0__not_found_in_workspace, project.getName()));
}
}
sortProjects(projects);
return Status.OK_STATUS;
}
private void sortProjects(List<IDtProject> projects)
{
String info = MessageFormat.format(Messages.SortCommand_Sort_projects__0,
projects.stream().map(IDtProject::getName).collect(Collectors.joining(", "))); //$NON-NLS-1$
getContext().getLogger().info(info);
for (IDtProject project : projects)
{
if (!AutoSortPreferences.isAutoSortEnabled(project.getWorkspaceProject()))
{
AutoSortPreferences.setupProjectDefault(project.getWorkspaceProject());
}
exclusiveOperation("Sort-MD-objects", project, ProjectPipelineJob.AFTER_BUILD_DD, () -> { //$NON-NLS-1$
sortService.sortAllMetadata(project, new NullProgressMonitor());
return null;
});
info = MessageFormat.format(Messages.SortCommand_Sort_project__0__finished, project.getName());
getContext().getLogger().info(info);
}
for (IDtProject project : projects)
{
// wait here to build project after sorting, to avoid dropping/stopping project while saving
exclusiveOperation("After-Sort-MD-objects", project, ProjectPipelineJob.AFTER_BUILD_DD, () -> null); //$NON-NLS-1$
}
}
}

View File

@ -0,0 +1,27 @@
#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/)
###############################################################################
# Copyright (C) 2021, 2023, 1C-Soft LLC and others.
#
# This program and the accompanying materials are made
# available under the terms of the Eclipse Public License 2.0
# which is available at https://www.eclipse.org/legal/epl-2.0/
#
# SPDX-License-Identifier: EPL-2.0
#
# Contributors:
# 1C-Soft LLC - initial API and implementation
###############################################################################
SortCommand_Description = Sort 1C:Enterprise projects with current auto-sort settings. If auto-sorting is not enabled yet, then default sort settings will enable for the project.
SortCommand_Project__0__did_not_import_into_workspace = Project "{0}" was not imported into workspace
SortCommand_Project__0__not_found_in_workspace = Project "{0}" was not found in workspace
SortCommand_Project_names_Description = List of project names, imported into workspace earlier, which will be sorted
SortCommand_Project_paths_Description = List of project paths, which will be imported into workspace and will be sorted
SortCommand_Sort_project__0__finished = Sort project "{0}" is finished.
SortCommand_Sort_projects__0 = Sort projects: {0}

View File

@ -0,0 +1,28 @@
#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/)
###############################################################################
# Copyright (C) 2021, 2023, 1C-Soft LLC and others.
#
# This program and the accompanying materials are made
# available under the terms of the Eclipse Public License 2.0
# which is available at https://www.eclipse.org/legal/epl-2.0/
#
# SPDX-License-Identifier: EPL-2.0
#
# Contributors:
# 1C-Soft LLC - initial API and implementation
###############################################################################
#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/)
SortCommand_Description = Сортирует проекты 1С:Предприятия с текущиими настройками авто-сортировки. Если авто-сортировка еще не была включена, тогда для проекта включатся настройки сортировки по умолчанию.
SortCommand_Project__0__did_not_import_into_workspace = Проект "{0}" не был импортирован в рабочее пространство
SortCommand_Project__0__not_found_in_workspace = Проект "{0}" не найден в рабочем пространстве
SortCommand_Project_names_Description = Список имен проектов, ранее импортированных в рабочее пространство, которые будут отсортированы
SortCommand_Project_paths_Description = Список путей к проектам, которые будут импортированы в рабочее пространство и отсортированы
SortCommand_Sort_project__0__finished = Сортировка проекта "{0}" завершена.
SortCommand_Sort_projects__0 = Сортировать проекты: {0}

View File

@ -17,6 +17,25 @@
- Не сортируются объекты, порядок которых влияет на реструктуризацию БД (измерения регистров, общие реквизиты конфигурации)
- Сортировка подчиненных объектов метаданных (реквизиты, формы, макеты и т.д.) - настройка по умолчанию не включена
## Запуск из командной строки (CLI)
Доступен запуск сортировки проекта из командной строки.
Команда может выполнять импорт проекта в рабочее пространство и сортировку проекта.
Если в проекте не настроена сортировка - будет включена авто-сортировка с настройками по умолчанию.
Пример:
```bash
// вывод справки по команде сортировки
1cedtcli -data ./ws -command help sort-project
// запуск сортировки по проекту с импортом в рабочую область
1cedtcli -data ./ws -command sort-project --projects "${PWD}/myproject"
```
## Отключение настройки
- Отключить настройку автосортировки можно в настройках проекта `Свойства - V8 - Авто сортировка - Все верхнеуровневые объекты метаданных` (Англ. `Properties -> V8 -> Auto sort -> All top metadata objects`)

View File

@ -0,0 +1,166 @@
/*******************************************************************************
* Copyright (C) 2023, 1C-Soft LLC and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* 1C-Soft LLC - initial API and implementation
*******************************************************************************/
package com.e1c.v8codestyle.autosort.itests;
import static com._1c.g5.v8.dt.metadata.mdclass.MdClassPackage.Literals.CONFIGURATION;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.nio.file.Path;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import com._1c.g5.v8.bm.core.IBmObject;
import com._1c.g5.v8.bm.core.IBmTransaction;
import com._1c.g5.v8.bm.integration.AbstractBmTask;
import com._1c.g5.v8.bm.integration.IBmModel;
import com._1c.g5.v8.dt.core.platform.IBmModelManager;
import com._1c.g5.v8.dt.core.platform.IDtProject;
import com._1c.g5.v8.dt.core.platform.IDtProjectManager;
import com._1c.g5.v8.dt.metadata.mdclass.Configuration;
import com._1c.g5.v8.dt.testing.GuiceModules;
import com._1c.g5.v8.dt.testing.JUnitGuiceRunner;
import com._1c.g5.v8.dt.testing.TestingWorkspace;
import com.e1c.v8codestyle.internal.autosort.cli.SortCommand;
import com.google.inject.Inject;
/**
* Tests for {@link SortCommand}.
*/
@RunWith(JUnitGuiceRunner.class)
@GuiceModules(modules = { ExternalDependenciesModule.class })
public class SortCommandTest
{
private static final String CLASS_NAME =
"com.e1c.v8codestyle.internal.autosort.ExecutableExtensionFactory:com.e1c.v8codestyle.internal.autosort.cli.SortCommand";
private static final String PROJECT_NAME = "Sort";
@Rule
public TestingWorkspace testingWorkspace = new TestingWorkspace(true, true);
@Inject
private IDtProjectManager dtProjectManager;
@Inject
private IBmModelManager bmModelManager;
private SortCommand command;
@Before
public void setUp() throws Exception
{
command = createSortCommand();
}
@Test
public void testSortExisting() throws Exception
{
IProject project = testingWorkspace.setUpProject(PROJECT_NAME, getClass());
assertNotNull(project);
IDtProject dtProject = dtProjectManager.getDtProject(project);
assertNotNull(dtProject);
IStatus status = command.sortExistingProjects(new IProject[] { project });
assertTrue(status.isOK());
IBmObject object = getTopObjectByFqn(CONFIGURATION.getName(), dtProject);
assertTrue(object instanceof Configuration);
Configuration configuration = (Configuration)object;
assertFalse(configuration.getCommonModules().isEmpty());
assertEquals("АМ2_4Модуль", configuration.getCommonModules().get(0).getName());
assertEquals("АМ_Модуль", configuration.getCommonModules().get(1).getName());
assertEquals("АМодуль", configuration.getCommonModules().get(2).getName());
assertEquals("БМодуль", configuration.getCommonModules().get(3).getName());
assertEquals("ГМодуль", configuration.getCommonModules().get(4).getName());
assertEquals("ОбщийМодуль", configuration.getCommonModules().get(5).getName());
}
@Test
public void testSortNonExisting() throws Exception
{
IProject project = testingWorkspace.getProject("OtherProject");
IStatus status = command.sortExistingProjects(new IProject[] { project });
assertFalse(status.isOK());
}
@Test
public void testImportAndSort() throws Exception
{
IProject project = testingWorkspace.setUpProject(PROJECT_NAME, getClass());
assertNotNull(project);
IDtProject dtProject = dtProjectManager.getDtProject(project);
assertNotNull(dtProject);
IStatus status = command.importAndSortProjects(new Path[] { project.getLocation().toFile().toPath() });
assertTrue(status.isOK());
IBmObject object = getTopObjectByFqn(CONFIGURATION.getName(), dtProject);
assertTrue(object instanceof Configuration);
Configuration configuration = (Configuration)object;
assertFalse(configuration.getCommonModules().isEmpty());
assertEquals("АМ2_4Модуль", configuration.getCommonModules().get(0).getName());
assertEquals("АМ_Модуль", configuration.getCommonModules().get(1).getName());
assertEquals("АМодуль", configuration.getCommonModules().get(2).getName());
assertEquals("БМодуль", configuration.getCommonModules().get(3).getName());
assertEquals("ГМодуль", configuration.getCommonModules().get(4).getName());
assertEquals("ОбщийМодуль", configuration.getCommonModules().get(5).getName());
}
private IBmObject getTopObjectByFqn(final String fqn, IDtProject dtProject)
{
IBmModel model = this.bmModelManager.getModel(dtProject);
return model.executeReadonlyTask(new AbstractBmTask<IBmObject>("GetObject")
{
@Override
public IBmObject execute(IBmTransaction transaction, IProgressMonitor progressMonitor)
{
return transaction.getTopObjectByFqn(fqn);
}
});
}
private SortCommand createSortCommand() throws Exception
{
IConfigurationElement[] elements = Platform.getExtensionRegistry()
.getExtensionPoint("com.e1c.g5.v8.dt.cli.api", "cliCommand")
.getConfigurationElements();
for (int i = 0; i < elements.length; i++)
{
IConfigurationElement element = elements[i];
if (!CLASS_NAME.equals(element.getAttribute("class")))
{
continue;
}
return (SortCommand)element.createExecutableExtension("class");
}
return null;
}
}