1
0
mirror of https://github.com/1C-Company/v8-code-style.git synced 2025-02-22 00:13:11 +02:00

G5V8DT-24189 При добавлении обработчика события или команды автоматически размещать его в соответствующей области

This commit is contained in:
Nikita Kuznetsov 2023-10-13 14:14:54 +03:00
parent 5fee19e5a6
commit 1fe8e9da0a
9 changed files with 416 additions and 27 deletions

View File

@ -23,6 +23,7 @@ Import-Package: com._1c.g5.ides.ui.texteditor.xtext.embedded;version="[6.0.0,7.0
com._1c.g5.v8.dt.bsl.common;version="[6.0.0,7.0.0)",
com._1c.g5.v8.dt.bsl.documentation.comment;version="[4.0.0,5.0.0)",
com._1c.g5.v8.dt.bsl.model;version="[5.0.0,6.0.0)",
com._1c.g5.v8.dt.bsl.model.util;version="4.7.0",
com._1c.g5.v8.dt.bsl.services;version="[7.0.0,8.0.0)",
com._1c.g5.v8.dt.bsl.ui;version="[9.0.0,10.0.0)",
com._1c.g5.v8.dt.bsl.ui.contentassist;version="[8.0.0,9.0.0)",

View File

@ -368,5 +368,11 @@
class="com.e1c.v8codestyle.internal.bsl.ui.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.ui.qfix.ServerExecutionSafeModeFix">
</fix>
</extension>
<extension
point="com._1c.g5.v8.dt.bsl.ui.bslModuleRegionsService">
<bslModuleRegionsService
class="com.e1c.v8codestyle.internal.bsl.ui.services.BslModuleRegionsService">
</bslModuleRegionsService>
</extension>
</plugin>

View File

@ -0,0 +1,238 @@
/**
* Copyright (C) 2023, 1C
*/
package com.e1c.v8codestyle.internal.bsl.ui.services;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.xtext.nodemodel.INode;
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
import org.eclipse.xtext.ui.editor.model.IXtextDocument;
import com._1c.g5.v8.dt.bsl.common.IBslModuleRegionsService;
import com._1c.g5.v8.dt.bsl.model.RegionPreprocessor;
import com._1c.g5.v8.dt.common.Pair;
import com._1c.g5.v8.dt.metadata.mdclass.ScriptVariant;
import com.e1c.v8codestyle.bsl.ModuleStructureSection;
/**
* Implementation of {@link IBslModuleRegionsService}
*
* @author Kuznetsov Nikita
*/
public class BslModuleRegionsService
implements IBslModuleRegionsService
{
private static final String FORM_NAME = "Form"; //$NON-NLS-1$
private static final String GRAPHICAL_SCHEME_NAME = "GraphicalScheme"; //$NON-NLS-1$
@Override
public Pair<Integer, String> getRegionInformation(IXtextDocument document,
List<RegionPreprocessor> regionPreprocessors, String suffix, int defaultOffset, ScriptVariant scriptVariant,
String eventOwnerRootName, boolean isMain, boolean isCommand, boolean isTable)
{
String declaredRegionName =
getDeclaredRegionName(eventOwnerRootName, isMain, isCommand, isTable, scriptVariant);
Map<String, ModuleRegionInformation> regionOffsets =
getRegionOffsets(document, regionPreprocessors, declaredRegionName, scriptVariant);
int offset = getRegionOffset(regionOffsets, declaredRegionName, suffix, defaultOffset, scriptVariant);
String regionName = null;
if (!isRegionExists(regionOffsets, declaredRegionName, suffix))
{
regionName = suffix.isEmpty() ? declaredRegionName : (declaredRegionName + suffix);
}
return new Pair<>(offset, regionName);
}
@Override
public String wrapByRegion(String content, String regionName, String beginRegion, String endRegion, String space,
String lineSeparator)
{
StringBuilder builder = new StringBuilder();
builder.append(lineSeparator).append(beginRegion).append(space).append(regionName);
builder.append(content);
builder.append(endRegion);
builder.append(lineSeparator);
return builder.toString();
}
private Map<String, ModuleRegionInformation> getRegionOffsets(IXtextDocument document,
List<RegionPreprocessor> regionPreprocessors, String targetRegionName, ScriptVariant scriptVariant)
{
ModuleStructureSection[] declaredRegionNames = ModuleStructureSection.values();
Map<String, ModuleRegionInformation> regionOffsets = new HashMap<>(declaredRegionNames.length / 2);
for (RegionPreprocessor regionPreprocessor : regionPreprocessors)
{
INode nodeAfter = NodeModelUtils.findActualNodeFor(regionPreprocessor.getItemAfter());
if (nodeAfter != null)
{
String preprocessorRegionName = regionPreprocessor.getName();
for (int regionNameIndex = 0; regionNameIndex < declaredRegionNames.length; regionNameIndex++)
{
ModuleStructureSection moduleStructureSection = declaredRegionNames[regionNameIndex];
String declaredRegionName = moduleStructureSection.getName(scriptVariant);
if ((preprocessorRegionName != null)
&& isMatchingRegion(preprocessorRegionName, declaredRegionName))
{
INode node = NodeModelUtils.findActualNodeFor(regionPreprocessor.getItem());
if (node != null)
{
ModuleRegionInformation moduleRegionInformation = null;
if (!preprocessorRegionName.equals(declaredRegionName))
{
if (!moduleStructureSection.isSuffixed())
{
continue;
}
String suffix = getSuffixOfMatchingRegion(preprocessorRegionName, declaredRegionName);
moduleRegionInformation = regionOffsets.get(declaredRegionName);
if (moduleRegionInformation == null)
{
moduleRegionInformation = ModuleRegionInformation.create(document, node, nodeAfter);
if (moduleRegionInformation == null)
{
return regionOffsets;
}
}
moduleRegionInformation.addSuffix(suffix, document, node, nodeAfter);
}
if (moduleRegionInformation == null && !moduleStructureSection.isSuffixed())
{
moduleRegionInformation = ModuleRegionInformation.create(document, node, nodeAfter);
}
if (moduleRegionInformation != null)
{
regionOffsets.put(declaredRegionName, moduleRegionInformation);
if ((targetRegionName != null) && targetRegionName.equals(preprocessorRegionName))
{
return regionOffsets;
}
}
}
}
}
}
}
return regionOffsets;
}
private int getRegionOffset(Map<String, ModuleRegionInformation> regionOffsets, String declaredRegionName,
String suffix, int defaultOffset, ScriptVariant scriptVariant)
{
int offset = defaultOffset;
boolean createNewRegion = !isRegionExists(regionOffsets, declaredRegionName, suffix);
ModuleRegionInformation regionOffset = regionOffsets.get(declaredRegionName);
if (regionOffset != null)
{
if (!suffix.isEmpty())
{
ModuleRegionInformation suffixedRegionInformation = regionOffset.getInformationBySuffix(suffix);
if (suffixedRegionInformation != null)
{
return suffixedRegionInformation.getBeforeEndOffset();
}
else if (createNewRegion)
{
return getNewRegionOffset(regionOffsets, declaredRegionName, suffix, defaultOffset, scriptVariant);
}
}
return regionOffset.getBeforeEndOffset();
}
if (createNewRegion)
{
return getNewRegionOffset(regionOffsets, declaredRegionName, suffix, defaultOffset, scriptVariant);
}
return offset;
}
private boolean isRegionExists(Map<String, ModuleRegionInformation> regionOffsets, String declaredRegionName,
String suffix)
{
ModuleRegionInformation moduleRegionInformation = regionOffsets.get(declaredRegionName);
return (moduleRegionInformation != null)
&& (suffix.isEmpty() || moduleRegionInformation.getInformationBySuffix(suffix) != null);
}
private int getNewRegionOffset(Map<String, ModuleRegionInformation> regionOffsets, String regionName,
String suffix, int defaultOffset, ScriptVariant scriptVariant)
{
boolean placeBefore = false;
int offset = regionOffsets.isEmpty() ? 0 : defaultOffset;
ModuleStructureSection[] declaredRegionNames = ModuleStructureSection.values();
for (int regionNameIndex = 0; regionNameIndex < declaredRegionNames.length; regionNameIndex++)
{
ModuleStructureSection moduleStructuredSection = declaredRegionNames[regionNameIndex];
String declaredRegionName = moduleStructuredSection.getName(scriptVariant);
if (declaredRegionName.equals(regionName))
{
placeBefore = true;
}
ModuleRegionInformation regionInformation = regionOffsets.get(declaredRegionName);
if (regionInformation != null)
{
if (placeBefore && (suffix.isEmpty() || !declaredRegionName.equals(regionName)))
{
return regionInformation.getStartOffset();
}
offset = placeBefore ? regionInformation.getStartOffset() : regionInformation.getEndOffset();
}
}
return offset;
}
private String getDeclaredRegionName(String eventOwnerRootName, boolean isMain, boolean isCommand, boolean isTable,
ScriptVariant scriptVariant)
{
if (eventOwnerRootName.equals(FORM_NAME))
{
return getDeclaredRegionNameForForm(isMain, isCommand, isTable, scriptVariant);
}
if (eventOwnerRootName.equals(GRAPHICAL_SCHEME_NAME))
{
return getDeclaredRegionNameForGraphicalScheme(scriptVariant);
}
return getDefaultRegionName(scriptVariant);
}
private String getDeclaredRegionNameForForm(boolean isMain, boolean isCommand, boolean isTable,
ScriptVariant scriptVariant)
{
if (isMain)
{
return ModuleStructureSection.FORM_EVENT_HANDLERS.getName(scriptVariant);
}
else if (isCommand)
{
return ModuleStructureSection.FORM_COMMAND_EVENT_HANDLERS.getName(scriptVariant);
}
else if (isTable)
{
return ModuleStructureSection.FORM_TABLE_ITEMS_EVENT_HANDLERS.getName(scriptVariant);
}
return ModuleStructureSection.FORM_HEADER_ITEMS_EVENT_HANDLERS.getName(scriptVariant);
}
private String getDeclaredRegionNameForGraphicalScheme(ScriptVariant scriptVariant)
{
return ModuleStructureSection.EVENT_HANDLERS.getName(scriptVariant);
}
private String getDefaultRegionName(ScriptVariant scriptVariant)
{
return ModuleStructureSection.PRIVATE.getName(scriptVariant);
}
private String getSuffixOfMatchingRegion(String regionName, String declaredRegionName)
{
return regionName.substring(declaredRegionName.length(), regionName.length());
}
private boolean isMatchingRegion(String regionName, String declaredRegionName)
{
int declaredRegionNameLength = declaredRegionName.length();
return regionName.length() >= declaredRegionNameLength
&& regionName.substring(0, declaredRegionNameLength).equals(declaredRegionName);
}
}

View File

@ -0,0 +1,147 @@
/**
* Copyright (C) 2023, 1C
*/
package com.e1c.v8codestyle.internal.bsl.ui.services;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.xtext.nodemodel.INode;
import com.e1c.v8codestyle.internal.bsl.ui.UiPlugin;
/**
* Provides offset and suffixes information of module region
*
* @author Kuznetsov Nikita
*/
public class ModuleRegionInformation
{
private int startOffset;
private int endOffset;
private int insertOffset;
private Map<String, ModuleRegionInformation> suffixes;
/**
* Start offset of module region
*
* @return offset before region declaration
*/
public int getStartOffset()
{
return startOffset;
}
/**
* End offset of module region
*
* @return offset after region declaration
*/
public int getEndOffset()
{
return endOffset;
}
/**
* Before end offset inside module region
*
* @return offset before end of region declaration
*/
public int getBeforeEndOffset()
{
return insertOffset;
}
/**
* Add suffix of the name of this module region
*
* @param suffix to add to suffixes map of this module region
* @param document to update offsets, can't be {@code null}
* @param node to update offsets, can't be {@code null}
* @param nodeAfter to update offsets, can't be {@code null}
*/
public void addSuffix(String suffix, IDocument document, INode node, INode nodeAfter)
{
if (suffixes == null)
{
suffixes = new HashMap<>();
}
ModuleRegionInformation suffixRegionInformation = create(document, node, nodeAfter);
if (suffixRegionInformation != null)
{
suffixes.put(suffix, suffixRegionInformation);
int suffixStartOffset = suffixRegionInformation.getStartOffset();
int suffixEndOffset = suffixRegionInformation.getEndOffset();
int suffixInsertOffset = suffixRegionInformation.getBeforeEndOffset();
if (insertOffset < suffixInsertOffset)
{
insertOffset = suffixInsertOffset;
endOffset = suffixEndOffset;
}
if (startOffset > suffixStartOffset)
{
startOffset = suffixStartOffset;
}
}
}
/**
* Is module region has suffixes
*
* @return {@code true} if module region has suffixes, {@code false} otherwise
*/
public boolean hasSuffixes()
{
return (suffixes != null);
}
/**
* Get module region information by suffix if exists
*
* @param suffix {@link String} suffix of declared name module region
* @return {@link ModuleRegionInformation} if suffix exists, {@code null} otherwise
*/
public ModuleRegionInformation getInformationBySuffix(String suffix)
{
if (hasSuffixes())
{
return suffixes.get(suffix);
}
return null;
}
private ModuleRegionInformation(int startOffset, int endOffset, int insertOffset)
{
this.startOffset = startOffset;
this.endOffset = endOffset;
this.insertOffset = insertOffset;
}
/**
* Create and calculate module region offsets
*
* @param document actual {@link IDocument} to get offsets from, can't be {@code null}
* @param node {@link INode} to get offsets from, can't be {@code null}
* @param nodeAfter {@link INode} to get offsets from, can't be {@code null}
* @return module region information with calculated region offsets or {@code null}
*/
public static ModuleRegionInformation create(IDocument document, INode node, INode nodeAfter)
{
try
{
int startLine = node.getTotalStartLine() - 1;
int startOffset = document.getLineOffset((startLine <= 1) ? 0 : startLine);
int endOffset = nodeAfter.getTotalOffset();
int insertOffset = document.getLineOffset(document.getLineOfOffset(nodeAfter.getTotalOffset()));
return new ModuleRegionInformation(startOffset, endOffset, insertOffset);
}
catch (BadLocationException ex)
{
UiPlugin.log(UiPlugin.createErrorStatus("Can't create module region information", ex)); //$NON-NLS-1$
}
return null;
}
}

View File

@ -15,29 +15,37 @@ package com.e1c.v8codestyle.bsl;
import com._1c.g5.v8.dt.metadata.mdclass.ScriptVariant;
/**
* Standard module structure dually-named section.
* Standard module structure dually-named section;
* <br>Sorted by priority of module regions standard.
*
* @author Dmitriy Marmyshev
*/
public enum ModuleStructureSection
{
PUBLIC("Public", "ПрограммныйИнтерфейс"), //$NON-NLS-1$ //$NON-NLS-2$
INTERNAL("Internal", "СлужебныйПрограммныйИнтерфейс"), //$NON-NLS-1$ //$NON-NLS-2$
PRIVATE("Private", "СлужебныеПроцедурыИФункции"), //$NON-NLS-1$ //$NON-NLS-2$
VARIABLES("Variables", "ОписаниеПеременных"), //$NON-NLS-1$ //$NON-NLS-2$
INITIALIZE("Initialize", "Инициализация"), //$NON-NLS-1$ //$NON-NLS-2$
PUBLIC("Public", "ПрограммныйИнтерфейс"), //$NON-NLS-1$ //$NON-NLS-2$
EVENT_HANDLERS("EventHandlers", "ОбработчикиСобытий"), //$NON-NLS-1$ //$NON-NLS-2$
INTERNAL("Internal", "СлужебныйПрограммныйИнтерфейс"), //$NON-NLS-1$ //$NON-NLS-2$
FORM_EVENT_HANDLERS("FormEventHandlers", "ОбработчикиСобытийФормы"), //$NON-NLS-1$ //$NON-NLS-2$
FORM_HEADER_ITEMS_EVENT_HANDLERS("FormHeaderItemsEventHandlers", "ОбработчикиСобытийЭлементовШапкиФормы"), //$NON-NLS-1$ //$NON-NLS-2$
FORM_TABLE_ITEMS_EVENT_HANDLERS("FormTableItemsEventHandlers", "ОбработчикиСобытийЭлементовТаблицыФормы", true), //$NON-NLS-1$ //$NON-NLS-2$
FORM_COMMAND_EVENT_HANDLERS("FormCommandsEventHandlers", "ОбработчикиКомандФормы"), //$NON-NLS-1$ //$NON-NLS-2$
FORM_TABLE_ITEMS_EVENT_HANDLERS("FormTableItemsEventHandlers", "ОбработчикиСобытийЭлементовТаблицыФормы"), //$NON-NLS-1$ //$NON-NLS-2$
PRIVATE("Private", "СлужебныеПроцедурыИФункции"), //$NON-NLS-1$ //$NON-NLS-2$
INITIALIZE("Initialize", "Инициализация"), //$NON-NLS-1$ //$NON-NLS-2$
DEPRECATED_REGION("Deprecated", "УстаревшиеПроцедурыИФункции"); //$NON-NLS-1$ //$NON-NLS-2$
private final String[] names;
private final boolean isSuffixed;
ModuleStructureSection(String name, String nameRu, boolean isSuffixed)
{
this.names = new String[] { name, nameRu };
this.isSuffixed = isSuffixed;
}
ModuleStructureSection(String name, String nameRu)
{
this.names = new String[] { name, nameRu };
this(name, nameRu, false);
}
/**
@ -61,4 +69,13 @@ public enum ModuleStructureSection
return names[scriptVariant.getValue()];
}
/**
* Is module region name used only with suffix
*
* @return <code>true</code> if region name must be suffixed, <code>false</code> otherwise
*/
public boolean isSuffixed()
{
return isSuffixed;
}
}

View File

@ -2,9 +2,7 @@
#Region EventHandlers
// Enter code here.
//%CURRENT_CODE%
#EndRegion
#Region Private

View File

@ -6,9 +6,7 @@
#Region FormEventHandlers
// Enter code here.
//%CURRENT_CODE%
#EndRegion
#Region FormHeaderItemsEventHandlers
@ -17,12 +15,6 @@
#EndRegion
#Region FormTableItemsEventHandlers //<FromTableName>
// Enter code here.
#EndRegion
#Region FormCommandsEventHandlers
// Enter code here.

View File

@ -2,9 +2,7 @@
#Область ОбработчикиСобытий
// Код процедур и функций
//%CURRENT_CODE%
#КонецОбласти
#Область СлужебныеПроцедурыИФункции

View File

@ -6,9 +6,7 @@
#Область ОбработчикиСобытийФормы
// Код процедур и функций
//%CURRENT_CODE%
#КонецОбласти
#Область ОбработчикиСобытийЭлементовШапкиФормы
@ -17,12 +15,6 @@
#КонецОбласти
#Область ОбработчикиСобытийЭлементовТаблицыФормы //<ИмяТаблицыФормы>
// Код процедур и функций
#КонецОбласти
#Область ОбработчикиКомандФормы
// Код процедур и функций