mirror of
https://github.com/1C-Company/v8-code-style.git
synced 2025-02-09 12:03:44 +02:00
parent
1f4c291075
commit
4348dd1911
@ -20,6 +20,7 @@ Import-Package: com._1c.g5.v8.bm.core;version="[7.0.0,8.0.0)",
|
||||
com._1c.g5.v8.dt.bsl.contextdef;version="[2.0.0,3.0.0)",
|
||||
com._1c.g5.v8.dt.bsl.documentation.comment;version="[3.0.0,4.0.0)",
|
||||
com._1c.g5.v8.dt.bsl.model;version="[5.0.0,6.0.0)",
|
||||
com._1c.g5.v8.dt.bsl.model.resource.owner;version="[2.0.0,3.0.0)",
|
||||
com._1c.g5.v8.dt.bsl.model.util;version="[4.0.0,5.0.0)",
|
||||
com._1c.g5.v8.dt.bsl.resource;version="[13.0.0,14.0.0)",
|
||||
com._1c.g5.v8.dt.bsl.typesystem;version="[9.0.0,10.0.0)",
|
||||
|
@ -140,6 +140,18 @@
|
||||
category="com.e1c.v8codestyle.bsl"
|
||||
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.check.ModuleStructureTopRegionCheck">
|
||||
</check>
|
||||
<check
|
||||
category="com.e1c.v8codestyle.bsl"
|
||||
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.check.ModuleEmptyMethodCheck">
|
||||
</check>
|
||||
<check
|
||||
category="com.e1c.v8codestyle.bsl"
|
||||
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.check.ModuleUnusedLocalVariableCheck">
|
||||
</check>
|
||||
<check
|
||||
category="com.e1c.v8codestyle.bsl"
|
||||
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.check.ModuleUnusedMethodCheck">
|
||||
</check>
|
||||
|
||||
</extension>
|
||||
<extension
|
||||
|
@ -75,6 +75,22 @@ final class Messages
|
||||
|
||||
public static String ModuleStructureTopRegionCheck_title;
|
||||
|
||||
public static String ModuleUnusedMethodCheck_Title;
|
||||
public static String ModuleUnusedMethodCheck_Description;
|
||||
public static String ModuleUnusedMethodCheck_Exclude_method_name_pattern_title;
|
||||
public static String ModuleUnusedMethodCheck_Unused_method__0;
|
||||
|
||||
public static String ModuleEmptyMethodCheck_Title;
|
||||
public static String ModuleEmptyMethodCheck_Description;
|
||||
public static String ModuleEmptyMethodCheck_Exclude_method_name_pattern_title;
|
||||
public static String ModuleEmptyMethodCheck_Allow_method_comments_title;
|
||||
public static String ModuleEmptyMethodCheck_Empty_method__0;
|
||||
|
||||
public static String ModuleUnusedLocalVariableCheck_Title;
|
||||
public static String ModuleUnusedLocalVariableCheck_Description;
|
||||
public static String ModuleUnusedLocalVariableCheck_Unused_local_variable__0;
|
||||
public static String ModuleUnusedLocalVariableCheck_Probably_variable_not_initilized_yet__0;
|
||||
|
||||
public static String QueryInLoop_check_query_in_infinite_loop;
|
||||
public static String QueryInLoop_description;
|
||||
public static String QueryInLoop_Loop_has_method_with_query__0;
|
||||
|
@ -0,0 +1,132 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2021, 1C-Soft LLC and others.
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* 1C-Soft LLC - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.e1c.v8codestyle.bsl.check;
|
||||
|
||||
import static com._1c.g5.v8.dt.bsl.model.BslPackage.Literals.METHOD;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.xtext.nodemodel.ILeafNode;
|
||||
import org.eclipse.xtext.nodemodel.INode;
|
||||
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
|
||||
|
||||
import com._1c.g5.v8.dt.bsl.documentation.comment.BslCommentUtils;
|
||||
import com._1c.g5.v8.dt.bsl.model.EmptyStatement;
|
||||
import com._1c.g5.v8.dt.bsl.model.Method;
|
||||
import com._1c.g5.v8.dt.bsl.model.Statement;
|
||||
import com._1c.g5.v8.dt.common.StringUtils;
|
||||
import com._1c.g5.v8.dt.mcore.McorePackage;
|
||||
import com.e1c.g5.v8.dt.check.ICheckParameters;
|
||||
import com.e1c.g5.v8.dt.check.components.BasicCheck;
|
||||
import com.e1c.g5.v8.dt.check.components.ModuleTopObjectNameFilterExtension;
|
||||
import com.e1c.g5.v8.dt.check.settings.IssueType;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
/**
|
||||
* Empty module method check.
|
||||
*
|
||||
* @author Andrey Volkov
|
||||
*/
|
||||
public final class ModuleEmptyMethodCheck
|
||||
extends BasicCheck
|
||||
{
|
||||
private static final String CHECK_ID = "module-empty-method"; //$NON-NLS-1$
|
||||
|
||||
private static final String EXCLUDE_METHOD_NAME_PATTERN_PARAMETER_NAME = "excludeModuleMethodNamePattern"; //$NON-NLS-1$
|
||||
|
||||
private static final String ALLOW_METHOD_COMMENTS_PARAMETER_NAME = "allowMethodComments"; //$NON-NLS-1$
|
||||
|
||||
@Override
|
||||
public String getCheckId()
|
||||
{
|
||||
return CHECK_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureCheck(CheckConfigurer builder)
|
||||
{
|
||||
builder.title(Messages.ModuleEmptyMethodCheck_Title)
|
||||
.description(Messages.ModuleEmptyMethodCheck_Description)
|
||||
.extension(new ModuleTopObjectNameFilterExtension())
|
||||
.parameter(EXCLUDE_METHOD_NAME_PATTERN_PARAMETER_NAME, String.class, StringUtils.EMPTY,
|
||||
Messages.ModuleEmptyMethodCheck_Exclude_method_name_pattern_title)
|
||||
.parameter(ALLOW_METHOD_COMMENTS_PARAMETER_NAME, Boolean.class, Boolean.TRUE.toString(),
|
||||
Messages.ModuleEmptyMethodCheck_Allow_method_comments_title)
|
||||
.issueType(IssueType.WARNING)
|
||||
.module()
|
||||
.checkedObjectType(METHOD);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void check(Object object, ResultAcceptor resultAceptor, ICheckParameters parameters,
|
||||
IProgressMonitor progressMonitor)
|
||||
{
|
||||
Method method = (Method)object;
|
||||
String methodName = method.getName();
|
||||
|
||||
String excludeNamePattern = parameters.getString(EXCLUDE_METHOD_NAME_PATTERN_PARAMETER_NAME);
|
||||
boolean allowMethodComments = parameters.getBoolean(ALLOW_METHOD_COMMENTS_PARAMETER_NAME);
|
||||
if (!isExcludeName(methodName, excludeNamePattern) && isEmpty(method, allowMethodComments))
|
||||
{
|
||||
resultAceptor.addIssue(MessageFormat.format(Messages.ModuleEmptyMethodCheck_Empty_method__0, methodName),
|
||||
method, McorePackage.Literals.NAMED_ELEMENT__NAME);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isEmpty(Method method, boolean allowMethodComments)
|
||||
{
|
||||
if (method.allStatements().isEmpty())
|
||||
{
|
||||
return !allowMethodComments || isMethodHasNoComment(method);
|
||||
}
|
||||
for (Statement statement : method.allStatements())
|
||||
{
|
||||
if (!(statement instanceof EmptyStatement))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isMethodHasNoComment(Method method)
|
||||
{
|
||||
INode node = NodeModelUtils.findActualNodeFor(method);
|
||||
if (node != null)
|
||||
{
|
||||
List<ILeafNode> allLeafNode = Lists.newArrayList(node.getLeafNodes());
|
||||
for (int i = allLeafNode.size() - 1; i >= 0; --i)
|
||||
{
|
||||
ILeafNode leafNode = allLeafNode.get(i);
|
||||
|
||||
if (leafNode.getOffset() < node.getOffset())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (BslCommentUtils.isCommentNode(leafNode))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isExcludeName(String name, String excludeNamePattern)
|
||||
{
|
||||
return StringUtils.isNotEmpty(excludeNamePattern) && name.matches(excludeNamePattern);
|
||||
}
|
||||
}
|
@ -0,0 +1,282 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2021, 1C-Soft LLC and others.
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* 1C-Soft LLC - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.e1c.v8codestyle.bsl.check;
|
||||
|
||||
import static com._1c.g5.v8.dt.bsl.model.BslPackage.Literals.MODULE;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.emf.common.util.URI;
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.xtext.EcoreUtil2;
|
||||
import org.eclipse.xtext.nodemodel.INode;
|
||||
import org.eclipse.xtext.resource.IResourceServiceProvider;
|
||||
|
||||
import com._1c.g5.v8.dt.bsl.common.VariableProcessor;
|
||||
import com._1c.g5.v8.dt.bsl.model.Block;
|
||||
import com._1c.g5.v8.dt.bsl.model.BslPackage;
|
||||
import com._1c.g5.v8.dt.bsl.model.DeclareStatement;
|
||||
import com._1c.g5.v8.dt.bsl.model.ExplicitVariable;
|
||||
import com._1c.g5.v8.dt.bsl.model.ForToStatement;
|
||||
import com._1c.g5.v8.dt.bsl.model.FormalParam;
|
||||
import com._1c.g5.v8.dt.bsl.model.ImplicitVariable;
|
||||
import com._1c.g5.v8.dt.bsl.model.Method;
|
||||
import com._1c.g5.v8.dt.bsl.model.Module;
|
||||
import com._1c.g5.v8.dt.bsl.model.SimpleStatement;
|
||||
import com._1c.g5.v8.dt.bsl.model.StaticFeatureAccess;
|
||||
import com._1c.g5.v8.dt.bsl.model.Variable;
|
||||
import com._1c.g5.v8.dt.bsl.model.resource.owner.IBslOwnerComputerService;
|
||||
import com._1c.g5.v8.dt.bsl.resource.BslResource;
|
||||
import com._1c.g5.v8.dt.bsl.resource.DynamicFeatureAccessComputer;
|
||||
import com._1c.g5.v8.dt.bsl.typesystem.util.TypeSystemUtil;
|
||||
import com.e1c.g5.v8.dt.check.ICheckParameters;
|
||||
import com.e1c.g5.v8.dt.check.components.BasicCheck;
|
||||
import com.e1c.g5.v8.dt.check.settings.IssueType;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
/**
|
||||
* Unused module local variable check.
|
||||
*
|
||||
* @author Andrey Volkov
|
||||
*/
|
||||
public final class ModuleUnusedLocalVariableCheck
|
||||
extends BasicCheck
|
||||
{
|
||||
private static final String CHECK_ID = "module-unused-local-variable"; //$NON-NLS-1$
|
||||
|
||||
private final DynamicFeatureAccessComputer dynamicComputer;
|
||||
|
||||
private final IBslOwnerComputerService ownerService;
|
||||
|
||||
/**
|
||||
* Instantiates a new module unused local variable check.
|
||||
*/
|
||||
public ModuleUnusedLocalVariableCheck()
|
||||
{
|
||||
super();
|
||||
IResourceServiceProvider serviceProvider =
|
||||
IResourceServiceProvider.Registry.INSTANCE.getResourceServiceProvider(URI.createURI("*.bsl")); //$NON-NLS-1$
|
||||
|
||||
dynamicComputer = serviceProvider.get(DynamicFeatureAccessComputer.class);
|
||||
ownerService = serviceProvider.get(IBslOwnerComputerService.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCheckId()
|
||||
{
|
||||
return CHECK_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureCheck(CheckConfigurer builder)
|
||||
{
|
||||
builder.title(Messages.ModuleUnusedLocalVariableCheck_Title)
|
||||
.description(Messages.ModuleUnusedLocalVariableCheck_Description)
|
||||
.issueType(IssueType.WARNING)
|
||||
.module()
|
||||
.checkedObjectType(MODULE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void check(Object object, ResultAcceptor resultAceptor, ICheckParameters parameters,
|
||||
IProgressMonitor progressMonitor)
|
||||
{
|
||||
Module module = (Module)object;
|
||||
|
||||
VariableProcessor processor = new VariableProcessor(module.allStatements(), dynamicComputer);
|
||||
processor.process();
|
||||
Map<Variable, List<INode>> variablesChangeValueModule = processor.variablesForChangeValue();
|
||||
Map<Variable, List<INode>> variablesForReadValueModule = processor.variablesForReadValue();
|
||||
for (Method method : getProcessMethods(module))
|
||||
{
|
||||
processor = new VariableProcessor(method.allStatements(), dynamicComputer);
|
||||
processor.process();
|
||||
Map<Variable, List<INode>> variablesChangeValue = processor.variablesForChangeValue();
|
||||
Map<Variable, List<INode>> variablesForReadValue = processor.variablesForReadValue();
|
||||
for (Map.Entry<Variable, List<INode>> variable : variablesChangeValue.entrySet())
|
||||
{
|
||||
if (variable.getKey() instanceof FormalParam)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Block actualVariableBlock = EcoreUtil2.getContainerOfType(variable.getKey(), Block.class);
|
||||
if (actualVariableBlock != method)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (variable.getKey() instanceof ExplicitVariable && ((ExplicitVariable)variable.getKey()).isExport())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (variable.getKey() instanceof ImplicitVariable)
|
||||
{
|
||||
ImplicitVariable implicitVariable = (ImplicitVariable)variable.getKey();
|
||||
if (implicitVariable.eContainer()
|
||||
.eContainingFeature() == BslPackage.Literals.FOR_STATEMENT__VARIABLE_ACCESS
|
||||
&& implicitVariable.eContainer().eContainer() instanceof ForToStatement)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (isUniqueForStaticFeatureAccess(implicitVariable))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (actualVariableBlock == module)
|
||||
{
|
||||
variablesChangeValueModule.computeIfAbsent(variable.getKey(), item -> Lists.newArrayList())
|
||||
.addAll(variable.getValue());
|
||||
}
|
||||
List<INode> readValueNodes = variablesForReadValue.get(variable.getKey());
|
||||
if (readValueNodes == null)
|
||||
{
|
||||
resultAceptor
|
||||
.addIssue(MessageFormat.format(Messages.ModuleUnusedLocalVariableCheck_Unused_local_variable__0,
|
||||
variable.getKey().getName()), variable.getKey());
|
||||
}
|
||||
else if (variable.getKey() instanceof ImplicitVariable)
|
||||
{
|
||||
ImplicitVariable implicitVariable = (ImplicitVariable)variable.getKey();
|
||||
EObject variableOwner = implicitVariable.eContainer();
|
||||
if (variableOwner instanceof StaticFeatureAccess
|
||||
&& variableOwner.eContainer() instanceof SimpleStatement)
|
||||
{
|
||||
for (INode readValueNode : readValueNodes)
|
||||
{
|
||||
if (readValueNode.getSemanticElement() == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (EcoreUtil2.getContainerOfType(readValueNode.getSemanticElement(),
|
||||
SimpleStatement.class) == variableOwner.eContainer())
|
||||
{
|
||||
resultAceptor.addIssue(MessageFormat.format(
|
||||
Messages.ModuleUnusedLocalVariableCheck_Probably_variable_not_initilized_yet__0,
|
||||
implicitVariable.getName()), readValueNode.getSemanticElement());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Map.Entry<Variable, List<INode>> variable : variablesForReadValue.entrySet())
|
||||
{
|
||||
Block actualVariableBlock = EcoreUtil2.getContainerOfType(variable.getKey(), Block.class);
|
||||
if (actualVariableBlock == module)
|
||||
{
|
||||
variablesForReadValueModule.computeIfAbsent(variable.getKey(), item -> Lists.newArrayList())
|
||||
.addAll(variable.getValue());
|
||||
}
|
||||
}
|
||||
for (DeclareStatement decl : method.allDeclareStatements())
|
||||
{
|
||||
for (ExplicitVariable variable : decl.getVariables())
|
||||
{
|
||||
if (variable.isExport())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
boolean foundInChange = variablesChangeValue.keySet().contains(variable);
|
||||
boolean foundInRead = variablesForReadValue.keySet().contains(variable);
|
||||
if (!foundInChange && !foundInRead)
|
||||
{
|
||||
resultAceptor.addIssue(
|
||||
MessageFormat.format(Messages.ModuleUnusedLocalVariableCheck_Unused_local_variable__0,
|
||||
variable.getName()),
|
||||
variable);
|
||||
}
|
||||
if (!foundInChange)
|
||||
{
|
||||
resultAceptor.addIssue(MessageFormat.format(
|
||||
Messages.ModuleUnusedLocalVariableCheck_Probably_variable_not_initilized_yet__0,
|
||||
variable.getName()), variable);
|
||||
}
|
||||
if (foundInChange && foundInRead)
|
||||
{
|
||||
INode changeValueNode = variablesChangeValue.get(variable).get(0);
|
||||
INode readValueNode = variablesForReadValue.get(variable).get(0);
|
||||
if (readValueNode.getOffset() < changeValueNode.getOffset())
|
||||
{
|
||||
resultAceptor.addIssue(MessageFormat.format(
|
||||
Messages.ModuleUnusedLocalVariableCheck_Probably_variable_not_initilized_yet__0,
|
||||
variable.getName()), readValueNode.getSemanticElement());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Map.Entry<Variable, List<INode>> variable : variablesChangeValueModule.entrySet())
|
||||
{
|
||||
if (EcoreUtil2.getContainerOfType(variable.getKey(), Block.class) != module)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (variable.getKey() instanceof ExplicitVariable && ((ExplicitVariable)variable.getKey()).isExport())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
List<INode> readValueNodes = variablesForReadValueModule.get(variable.getKey());
|
||||
if (readValueNodes == null && !(variable.getKey() instanceof ImplicitVariable
|
||||
&& isUniqueForStaticFeatureAccess((ImplicitVariable)variable.getKey())))
|
||||
{
|
||||
resultAceptor
|
||||
.addIssue(MessageFormat.format(Messages.ModuleUnusedLocalVariableCheck_Unused_local_variable__0,
|
||||
variable.getKey().getName()), variable.getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<Method> getProcessMethods(Module module)
|
||||
{
|
||||
List<Method> processingObjects;
|
||||
if (!onlyMethodReparse(module))
|
||||
{
|
||||
processingObjects = Lists.newArrayList(module.allMethods());
|
||||
}
|
||||
else
|
||||
{
|
||||
BslResource resource = (BslResource)module.eResource();
|
||||
processingObjects = com._1c.g5.v8.dt.bsl.util.BslUtil.getDependMethodsTree(resource.getReparseMethod())
|
||||
.stream()
|
||||
.filter(item -> item instanceof Method)
|
||||
.map(item -> (Method)item)
|
||||
.collect(Collectors.toList());
|
||||
processingObjects.add(resource.getReparseMethod());
|
||||
}
|
||||
return processingObjects;
|
||||
}
|
||||
|
||||
private boolean onlyMethodReparse(Module module)
|
||||
{
|
||||
// TODO - only full validation first, optimization later
|
||||
//return module.eResource() != null && ((BslResource)module.eResource()).isOnlyMethodReparse()
|
||||
// && getCheckMode() != BslCancelableDiagnostician.ALL_FOR_FULL_MODULE;
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO - only full validation first, optimization later
|
||||
//private CheckMode getCheckMode()
|
||||
//{
|
||||
// return state.get().checkMode;
|
||||
//}
|
||||
|
||||
private boolean isUniqueForStaticFeatureAccess(ImplicitVariable implicitVariable)
|
||||
{
|
||||
return implicitVariable.eContainer() instanceof StaticFeatureAccess && !implicitVariable.getEnvironments()
|
||||
.equals(TypeSystemUtil.getActualEnvironments(implicitVariable.eContainer(), ownerService));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,135 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2021, 1C-Soft LLC and others.
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* 1C-Soft LLC - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.e1c.v8codestyle.bsl.check;
|
||||
|
||||
import static com._1c.g5.v8.dt.bsl.model.BslPackage.Literals.MODULE;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.emf.common.util.URI;
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.emf.ecore.resource.Resource;
|
||||
import org.eclipse.emf.ecore.util.EcoreUtil;
|
||||
import org.eclipse.xtext.builder.MonitorBasedCancelIndicator;
|
||||
import org.eclipse.xtext.naming.IQualifiedNameProvider;
|
||||
import org.eclipse.xtext.resource.IResourceDescription;
|
||||
|
||||
import com._1c.g5.v8.dt.bsl.common.IModuleExtensionService;
|
||||
import com._1c.g5.v8.dt.bsl.common.IModuleExtensionServiceProvider;
|
||||
import com._1c.g5.v8.dt.bsl.model.Method;
|
||||
import com._1c.g5.v8.dt.bsl.model.Module;
|
||||
import com._1c.g5.v8.dt.bsl.resource.BslResourceDescription;
|
||||
import com._1c.g5.v8.dt.common.StringUtils;
|
||||
import com._1c.g5.v8.dt.mcore.McorePackage;
|
||||
import com.e1c.g5.v8.dt.check.ICheckParameters;
|
||||
import com.e1c.g5.v8.dt.check.components.BasicCheck;
|
||||
import com.e1c.g5.v8.dt.check.components.ModuleTopObjectNameFilterExtension;
|
||||
import com.e1c.g5.v8.dt.check.settings.IssueType;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
* Unused module method check. This class needs {@link IQualifiedNameProvider} to inject other service.
|
||||
*
|
||||
* @author Andrey Volkov
|
||||
* @author Dmitriy Marmyshev
|
||||
*/
|
||||
public final class ModuleUnusedMethodCheck
|
||||
extends BasicCheck
|
||||
{
|
||||
private static final String CHECK_ID = "module-unused-method"; //$NON-NLS-1$
|
||||
|
||||
private static final String EXCLUDE_METHOD_NAME_PATTERN_PARAMETER_NAME = "excludeModuleMethodNamePattern"; //$NON-NLS-1$
|
||||
|
||||
private final IResourceDescription.Manager resourceDescriptionManager;
|
||||
|
||||
/**
|
||||
* Instantiates a new module unused method check.
|
||||
*
|
||||
* @param resourceDescriptionManager the resource description manager service, cannot be {@code null}.
|
||||
*/
|
||||
@Inject
|
||||
public ModuleUnusedMethodCheck(IResourceDescription.Manager resourceDescriptionManager)
|
||||
{
|
||||
super();
|
||||
this.resourceDescriptionManager = resourceDescriptionManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCheckId()
|
||||
{
|
||||
return CHECK_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureCheck(CheckConfigurer builder)
|
||||
{
|
||||
builder.title(Messages.ModuleUnusedMethodCheck_Title)
|
||||
.description(Messages.ModuleUnusedMethodCheck_Description)
|
||||
.extension(new ModuleTopObjectNameFilterExtension())
|
||||
.parameter(EXCLUDE_METHOD_NAME_PATTERN_PARAMETER_NAME, String.class, StringUtils.EMPTY,
|
||||
Messages.ModuleUnusedMethodCheck_Exclude_method_name_pattern_title)
|
||||
.issueType(IssueType.WARNING)
|
||||
.module()
|
||||
.checkedObjectType(MODULE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void check(Object object, ResultAcceptor resultAceptor, ICheckParameters parameters,
|
||||
IProgressMonitor progressMonitor)
|
||||
{
|
||||
Module module = (Module)object;
|
||||
|
||||
IModuleExtensionService service = IModuleExtensionServiceProvider.INSTANCE.getModuleExtensionService();
|
||||
String excludeNamePattern = parameters.getString(EXCLUDE_METHOD_NAME_PATTERN_PARAMETER_NAME);
|
||||
|
||||
Predicate<? super Method> predicate = method -> !method.isUsed() && !method.isExport() && !method.isEvent()
|
||||
&& service.getSourceMethodNames(method).isEmpty() && !isExcludeName(method.getName(), excludeNamePattern);
|
||||
|
||||
// TODO - only full validation first, optimization later
|
||||
//@formatter:off
|
||||
//if (!((BslResource)module.eResource()).isOnlyMethodReparse())
|
||||
//{
|
||||
Set<URI> usedMethods = getUsedMethods(progressMonitor, module.eResource());
|
||||
predicate = predicate.and(method -> !usedMethods.contains(EcoreUtil.getURI((EObject)method)));
|
||||
//}
|
||||
//@formatter:on
|
||||
|
||||
module.allMethods()
|
||||
.stream()
|
||||
.filter(predicate)
|
||||
.forEach(unusedMethod -> resultAceptor.addIssue(
|
||||
MessageFormat.format(Messages.ModuleUnusedMethodCheck_Unused_method__0, unusedMethod.getName()),
|
||||
unusedMethod, McorePackage.Literals.NAMED_ELEMENT__NAME));
|
||||
}
|
||||
|
||||
private Set<URI> getUsedMethods(IProgressMonitor progressMonitor, Resource resource)
|
||||
{
|
||||
IResourceDescription descr = resourceDescriptionManager.getResourceDescription(resource);
|
||||
return (descr instanceof BslResourceDescription
|
||||
? Lists.newArrayList(((BslResourceDescription)descr)
|
||||
.getReferenceDescriptions(new MonitorBasedCancelIndicator(progressMonitor)))
|
||||
: Lists.newArrayList(descr.getReferenceDescriptions())).stream()
|
||||
.map(reference -> reference.getTargetEObjectUri())
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
private boolean isExcludeName(String name, String excludeNamePattern)
|
||||
{
|
||||
return StringUtils.isNotEmpty(excludeNamePattern) && name.matches(excludeNamePattern);
|
||||
}
|
||||
}
|
@ -94,12 +94,38 @@ MethodTooManyPramsCheck_description = Method has to many parameters
|
||||
|
||||
MethodTooManyPramsCheck_title = Method has to many parameters
|
||||
|
||||
ModuleEmptyMethodCheck_Allow_method_comments_title = Allow method comments
|
||||
|
||||
ModuleEmptyMethodCheck_Description = Empty module method check
|
||||
|
||||
ModuleEmptyMethodCheck_Empty_method__0 = Empty method "{0}"
|
||||
|
||||
ModuleEmptyMethodCheck_Exclude_method_name_pattern_title = Exclude method name pattern
|
||||
|
||||
ModuleEmptyMethodCheck_Title = Empty method check
|
||||
|
||||
ModuleStructureTopRegionCheck_description = Check that module structure region is on top
|
||||
|
||||
ModuleStructureTopRegionCheck_error_message = Module structure region is not on top
|
||||
|
||||
ModuleStructureTopRegionCheck_title = Module structure top region
|
||||
|
||||
ModuleUnusedLocalVariableCheck_Description = Unused module local variable check
|
||||
|
||||
ModuleUnusedLocalVariableCheck_Probably_variable_not_initilized_yet__0 = Probably local variable "{0}" has not been initiliazed yet
|
||||
|
||||
ModuleUnusedLocalVariableCheck_Title = Unused local variable check
|
||||
|
||||
ModuleUnusedLocalVariableCheck_Unused_local_variable__0 = Unused local variable "{0}"
|
||||
|
||||
ModuleUnusedMethodCheck_Description = Unused module method check
|
||||
|
||||
ModuleUnusedMethodCheck_Exclude_method_name_pattern_title = Exclude method name pattern
|
||||
|
||||
ModuleUnusedMethodCheck_Title = Unused method check
|
||||
|
||||
ModuleUnusedMethodCheck_Unused_method__0 = Unused method "{0}"
|
||||
|
||||
NotifyDescriptionToServerProcedureCheck_Notify_description_procedure_should_be_export = Notify description procedure should exist and be export
|
||||
|
||||
NotifyDescriptionToServerProcedureCheck_Notify_description_to_Server_procedure = Notify description to Server procedure
|
||||
|
@ -94,12 +94,38 @@ MethodTooManyPramsCheck_description = Метод содержит слишком
|
||||
|
||||
MethodTooManyPramsCheck_title = Метод содержит слишком много параметров
|
||||
|
||||
ModuleEmptyMethodCheck_Allow_method_comments_title = Учитывать комментарии метода
|
||||
|
||||
ModuleEmptyMethodCheck_Description = Проверка модуля на наличие пустых методов
|
||||
|
||||
ModuleEmptyMethodCheck_Empty_method__0 = Пустой метод "{0}"
|
||||
|
||||
ModuleEmptyMethodCheck_Exclude_method_name_pattern_title = Шаблон исключаемых имен методов
|
||||
|
||||
ModuleEmptyMethodCheck_Title = Проверка пустых методов
|
||||
|
||||
ModuleStructureTopRegionCheck_description = Проверяет что стандартная область структуры модуля не является вложенной
|
||||
|
||||
ModuleStructureTopRegionCheck_error_message = Стандартная область структуры модуля является вложенной
|
||||
|
||||
ModuleStructureTopRegionCheck_title = Стандартная область структуры модуля верхнеуровневая
|
||||
|
||||
ModuleUnusedLocalVariableCheck_Description = Проверка модуля на наличие неиспользуемых локальных переменных
|
||||
|
||||
ModuleUnusedLocalVariableCheck_Probably_variable_not_initilized_yet__0 = Возможно, переменная ''{0}'' еще не была проинициализирована
|
||||
|
||||
ModuleUnusedLocalVariableCheck_Title = Проверка неиспользуемых локальных переменных
|
||||
|
||||
ModuleUnusedLocalVariableCheck_Unused_local_variable__0 = Неиспользуемая локальная переменная ''{0}''
|
||||
|
||||
ModuleUnusedMethodCheck_Description = Проверка модуля на наличие неиспользуемых методов
|
||||
|
||||
ModuleUnusedMethodCheck_Exclude_method_name_pattern_title = Шаблон исключаемых имен методов
|
||||
|
||||
ModuleUnusedMethodCheck_Title = Проверка неиспользуемых методов
|
||||
|
||||
ModuleUnusedMethodCheck_Unused_method__0 = Неиспользуемый метод "{0}"
|
||||
|
||||
NotifyDescriptionToServerProcedureCheck_Notify_description_procedure_should_be_export = Процедура описания оповещения должна существовать и быть экспортной
|
||||
|
||||
NotifyDescriptionToServerProcedureCheck_Notify_description_to_Server_procedure = Описание оповещения на серверную процедуру
|
||||
|
@ -15,6 +15,7 @@ package com.e1c.v8codestyle.internal.bsl;
|
||||
|
||||
import org.eclipse.core.runtime.Plugin;
|
||||
import org.eclipse.xtext.naming.IQualifiedNameConverter;
|
||||
import org.eclipse.xtext.naming.IQualifiedNameProvider;
|
||||
|
||||
import com._1c.g5.v8.dt.bsl.common.IBslPreferences;
|
||||
import com._1c.g5.v8.dt.bsl.contextdef.IBslModuleContextDefService;
|
||||
@ -47,6 +48,7 @@ class ExternalDependenciesModule
|
||||
bind(IBslPreferences.class).toService();
|
||||
bind(IQualifiedNameConverter.class).toService();
|
||||
bind(IBslModuleContextDefService.class).toService();
|
||||
bind(IQualifiedNameProvider.class).toService();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,8 @@
|
||||
Procedure BeforeExit(Cancel, WarningText)
|
||||
i = 0;
|
||||
i = i + 1;
|
||||
EndProcedure
|
||||
|
||||
Procedure ModuleEmptyMethodCheck()
|
||||
|
||||
EndProcedure
|
@ -0,0 +1,11 @@
|
||||
Procedure BeforeExit(Cancel, WarningText)
|
||||
|
||||
ModuleUnusedMethodCheck();
|
||||
|
||||
EndProcedure
|
||||
|
||||
Procedure ModuleUnusedMethodCheck()
|
||||
|
||||
i = 0;
|
||||
|
||||
EndProcedure
|
@ -0,0 +1,9 @@
|
||||
Procedure BeforeExit(Cancel, WarningText)
|
||||
i = 0;
|
||||
i = i + 1;
|
||||
EndProcedure
|
||||
|
||||
Procedure ModuleUnusedMethodCheck()
|
||||
i = 0;
|
||||
i = i + 1;
|
||||
EndProcedure
|
@ -253,8 +253,11 @@ public class AbstractSingleModuleTestBase
|
||||
String chekcId = getCheckId();
|
||||
assertNotNull(chekcId);
|
||||
|
||||
CheckUid id = new CheckUid(chekcId, BslPlugin.PLUGIN_ID);
|
||||
|
||||
return markers.stream()
|
||||
.filter(m -> chekcId.equals(getCheckIdFromMarker(m, getProject())))
|
||||
.filter(
|
||||
m -> id.equals(checkRepository.getUidForShortUid(m.getCheckId(), getProject().getWorkspaceProject())))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,51 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2021, 1C-Soft LLC and others.
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* 1C-Soft LLC - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.e1c.v8codestyle.bsl.check.itests;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com._1c.g5.v8.dt.validation.marker.IExtraInfoKeys;
|
||||
import com._1c.g5.v8.dt.validation.marker.Marker;
|
||||
import com.e1c.v8codestyle.bsl.check.ModuleEmptyMethodCheck;
|
||||
|
||||
/**
|
||||
* Tests for the {@link ModuleEmptyMethodCheck}
|
||||
*
|
||||
* @author Andrey Volkov
|
||||
* @author Dmitriy Marmyshev
|
||||
*/
|
||||
public class ModuleEmptyMethodCheckTest
|
||||
extends AbstractSingleModuleTestBase
|
||||
{
|
||||
public ModuleEmptyMethodCheckTest()
|
||||
{
|
||||
super(ModuleEmptyMethodCheck.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleCheckMarker() throws Exception
|
||||
{
|
||||
|
||||
updateModule(FOLDER_RESOURCE + "module-empty-method.bsl");
|
||||
|
||||
List<Marker> markers = getModuleMarkers();
|
||||
assertEquals(1, markers.size());
|
||||
Marker marker = markers.get(0);
|
||||
assertEquals("6", marker.getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_LINE_KEY));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2021, 1C-Soft LLC and others.
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* 1C-Soft LLC - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.e1c.v8codestyle.bsl.check.itests;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com._1c.g5.v8.dt.validation.marker.IExtraInfoKeys;
|
||||
import com._1c.g5.v8.dt.validation.marker.Marker;
|
||||
import com.e1c.v8codestyle.bsl.check.ModuleUnusedLocalVariableCheck;
|
||||
|
||||
/**
|
||||
* Tests for the {@link ModuleUnusedLocalVariableCheck}
|
||||
*
|
||||
* @author Andrey Volkov
|
||||
* @author Dmitriy Marmyshev
|
||||
*/
|
||||
public class ModuleUnusedLocalVariableCheckTest
|
||||
extends AbstractSingleModuleTestBase
|
||||
{
|
||||
|
||||
public ModuleUnusedLocalVariableCheckTest()
|
||||
{
|
||||
super(ModuleUnusedLocalVariableCheck.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleCheckMarker() throws Exception
|
||||
{
|
||||
|
||||
updateModule(FOLDER_RESOURCE + "module-unused-local-variable.bsl");
|
||||
|
||||
List<Marker> markers = getModuleMarkers();
|
||||
assertEquals(1, markers.size());
|
||||
Marker marker = markers.get(0);
|
||||
assertEquals("9", marker.getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_LINE_KEY));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2021, 1C-Soft LLC and others.
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* 1C-Soft LLC - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.e1c.v8codestyle.bsl.check.itests;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com._1c.g5.v8.dt.validation.marker.IExtraInfoKeys;
|
||||
import com._1c.g5.v8.dt.validation.marker.Marker;
|
||||
import com.e1c.v8codestyle.bsl.check.ModuleUnusedMethodCheck;
|
||||
|
||||
/**
|
||||
* Tests for the {@link ModuleUnusedMethodCheck}
|
||||
*
|
||||
* @author Andrey Volkov
|
||||
* @author Dmitriy Marmyshev
|
||||
*/
|
||||
public class ModuleUnusedMethodCheckTest
|
||||
extends AbstractSingleModuleTestBase
|
||||
{
|
||||
|
||||
private static final String CONFIG_MODULE_FILE_NAME = "/src/Configuration/ManagedApplicationModule.bsl";
|
||||
|
||||
public ModuleUnusedMethodCheckTest()
|
||||
{
|
||||
super(ModuleUnusedMethodCheck.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleCheckMarker() throws Exception
|
||||
{
|
||||
|
||||
updateModule(FOLDER_RESOURCE + "module-unused-method.bsl");
|
||||
|
||||
List<Marker> markers = getModuleMarkers();
|
||||
assertEquals(1, markers.size());
|
||||
Marker marker = markers.get(0);
|
||||
assertEquals("6", marker.getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_LINE_KEY));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getModuleFileName()
|
||||
{
|
||||
return CONFIG_MODULE_FILE_NAME;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user