mirror of
https://github.com/1C-Company/v8-code-style.git
synced 2025-02-03 18:02:08 +02:00
Проверка на запросы в цикле (#32)
#17 Добавлена проверка на запросы в цикле
This commit is contained in:
parent
464de06c3b
commit
4b9bf9530b
@ -16,12 +16,15 @@ Automatic-Module-Name: com.e1c.v8codestyle.bsl
|
|||||||
Bundle-ActivationPolicy: lazy
|
Bundle-ActivationPolicy: lazy
|
||||||
Import-Package: com._1c.g5.v8.bm.core;version="[7.0.0,8.0.0)",
|
Import-Package: com._1c.g5.v8.bm.core;version="[7.0.0,8.0.0)",
|
||||||
com._1c.g5.v8.dt.bsl.model;version="[4.0.0,5.0.0)",
|
com._1c.g5.v8.dt.bsl.model;version="[4.0.0,5.0.0)",
|
||||||
|
com._1c.g5.v8.dt.bsl.model.util;version="[4.6.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)",
|
com._1c.g5.v8.dt.bsl.typesystem;version="[9.0.0,10.0.0)",
|
||||||
com._1c.g5.v8.dt.bsl.util;version="[7.0.0,8.0.0)",
|
com._1c.g5.v8.dt.bsl.util;version="[7.0.0,8.0.0)",
|
||||||
com._1c.g5.v8.dt.mcore;version="[6.0.0,7.0.0)",
|
com._1c.g5.v8.dt.mcore;version="[6.0.0,7.0.0)",
|
||||||
com._1c.g5.v8.dt.mcore.util;version="[3.6.0,4.0.0)",
|
com._1c.g5.v8.dt.mcore.util;version="[3.6.0,4.0.0)",
|
||||||
com._1c.g5.v8.dt.metadata.mdclass;version="[8.0.0,9.0.0)",
|
com._1c.g5.v8.dt.metadata.mdclass;version="[8.0.0,9.0.0)",
|
||||||
com._1c.g5.v8.dt.platform;version="[5.0.0,6.0.0)",
|
com._1c.g5.v8.dt.platform;version="[5.0.0,6.0.0)",
|
||||||
|
com._1c.g5.v8.dt.platform.version;version="[2.13.0,3.0.0)",
|
||||||
com._1c.g5.wiring;version="[2.0.0,3.0.0)",
|
com._1c.g5.wiring;version="[2.0.0,3.0.0)",
|
||||||
com._1c.g5.wiring.binder;version="[1.0.0,2.0.0)",
|
com._1c.g5.wiring.binder;version="[1.0.0,2.0.0)",
|
||||||
com.e1c.g5.v8.dt.bsl.check;version="[1.0.0,2.0.0)",
|
com.e1c.g5.v8.dt.bsl.check;version="[1.0.0,2.0.0)",
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
# query-in-loop
|
||||||
|
|
||||||
|
## Noncompliant Code Example
|
||||||
|
|
||||||
|
## Compliant Solution
|
||||||
|
|
||||||
|
## See
|
||||||
|
|
@ -0,0 +1,9 @@
|
|||||||
|
# query-in-loop
|
||||||
|
|
||||||
|
## Неправильно
|
||||||
|
|
||||||
|
## Правильно
|
||||||
|
|
||||||
|
## См.
|
||||||
|
|
||||||
|
https://its.1c.ru/db/pubqlang#content:150:hdoc
|
@ -11,21 +11,30 @@
|
|||||||
|
|
||||||
Contributors:
|
Contributors:
|
||||||
1C-Soft LLC - initial API and implementation
|
1C-Soft LLC - initial API and implementation
|
||||||
|
Aleksandr Kapralov - issue #17
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<extension
|
<extension
|
||||||
point="com.e1c.g5.v8.dt.check.checks">
|
point="com.e1c.g5.v8.dt.check.checks">
|
||||||
|
|
||||||
<category
|
<category
|
||||||
category="com.e1c.v8codestyle"
|
category="com.e1c.v8codestyle"
|
||||||
description="%category.bls.description"
|
description="%category.bls.description"
|
||||||
id="com.e1c.v8codestyle.bsl"
|
id="com.e1c.v8codestyle.bsl"
|
||||||
title="%category.bsl.title">
|
title="%category.bsl.title">
|
||||||
</category>
|
</category>
|
||||||
|
|
||||||
<check
|
<check
|
||||||
category="com.e1c.v8codestyle.bsl"
|
category="com.e1c.v8codestyle.bsl"
|
||||||
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.check.StructureCtorTooManyKeysCheck">
|
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.check.StructureCtorTooManyKeysCheck">
|
||||||
</check>
|
</check>
|
||||||
|
|
||||||
|
<check
|
||||||
|
category="com.e1c.v8codestyle.bsl"
|
||||||
|
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.check.QueryInLoopCheck">
|
||||||
|
</check>
|
||||||
|
|
||||||
</extension>
|
</extension>
|
||||||
|
|
||||||
</plugin>
|
</plugin>
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* 1C-Soft LLC - initial API and implementation
|
* 1C-Soft LLC - initial API and implementation
|
||||||
|
* Aleksandr Kapralov - issue #17
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -25,10 +26,18 @@ final class Messages
|
|||||||
extends NLS
|
extends NLS
|
||||||
{
|
{
|
||||||
private static final String BUNDLE_NAME = "com.e1c.v8codestyle.bsl.check.messages"; //$NON-NLS-1$
|
private static final String BUNDLE_NAME = "com.e1c.v8codestyle.bsl.check.messages"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
public static String QueryInLoop_check_query_in_infinite_loop;
|
||||||
|
public static String QueryInLoop_description;
|
||||||
|
public static String QueryInLoop_Loop_has_query;
|
||||||
|
public static String QueryInLoop_Loop_has_method_with_query__0;
|
||||||
|
public static String QueryInLoop_title;
|
||||||
|
|
||||||
public static String StructureCtorTooManyKeysCheck_description;
|
public static String StructureCtorTooManyKeysCheck_description;
|
||||||
public static String StructureCtorTooManyKeysCheck_Maximum_structure_constructor_keys;
|
public static String StructureCtorTooManyKeysCheck_Maximum_structure_constructor_keys;
|
||||||
public static String StructureCtorTooManyKeysCheck_Structure_constructor_has_more_than__0__keys;
|
public static String StructureCtorTooManyKeysCheck_Structure_constructor_has_more_than__0__keys;
|
||||||
public static String StructureCtorTooManyKeysCheck_title;
|
public static String StructureCtorTooManyKeysCheck_title;
|
||||||
|
|
||||||
static
|
static
|
||||||
{
|
{
|
||||||
// initialize resource bundle
|
// initialize resource bundle
|
||||||
|
@ -0,0 +1,390 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* 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:
|
||||||
|
* Aleksandr Kapralov - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package com.e1c.v8codestyle.bsl.check;
|
||||||
|
|
||||||
|
import static com._1c.g5.v8.dt.bsl.model.BslPackage.Literals.FEATURE_ACCESS__NAME;
|
||||||
|
import static com._1c.g5.v8.dt.bsl.model.BslPackage.Literals.MODULE;
|
||||||
|
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.emf.common.util.EList;
|
||||||
|
import org.eclipse.emf.common.util.URI;
|
||||||
|
import org.eclipse.emf.ecore.EObject;
|
||||||
|
import org.eclipse.emf.ecore.util.EcoreUtil;
|
||||||
|
import org.eclipse.xtext.EcoreUtil2;
|
||||||
|
import org.eclipse.xtext.nodemodel.ICompositeNode;
|
||||||
|
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
|
||||||
|
import org.eclipse.xtext.resource.IResourceServiceProvider;
|
||||||
|
|
||||||
|
import com._1c.g5.v8.dt.bsl.model.BooleanLiteral;
|
||||||
|
import com._1c.g5.v8.dt.bsl.model.DynamicFeatureAccess;
|
||||||
|
import com._1c.g5.v8.dt.bsl.model.Expression;
|
||||||
|
import com._1c.g5.v8.dt.bsl.model.FeatureAccess;
|
||||||
|
import com._1c.g5.v8.dt.bsl.model.Invocation;
|
||||||
|
import com._1c.g5.v8.dt.bsl.model.LoopStatement;
|
||||||
|
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.StaticFeatureAccess;
|
||||||
|
import com._1c.g5.v8.dt.bsl.model.WhileStatement;
|
||||||
|
import com._1c.g5.v8.dt.bsl.model.util.BslUtil;
|
||||||
|
import com._1c.g5.v8.dt.bsl.resource.TypesComputer;
|
||||||
|
import com._1c.g5.v8.dt.mcore.ContextDef;
|
||||||
|
import com._1c.g5.v8.dt.mcore.Environmental;
|
||||||
|
import com._1c.g5.v8.dt.mcore.McorePackage;
|
||||||
|
import com._1c.g5.v8.dt.mcore.Type;
|
||||||
|
import com._1c.g5.v8.dt.mcore.TypeItem;
|
||||||
|
import com._1c.g5.v8.dt.mcore.util.McoreUtil;
|
||||||
|
import com._1c.g5.v8.dt.platform.IEObjectProvider;
|
||||||
|
import com._1c.g5.v8.dt.platform.IEObjectTypeNames;
|
||||||
|
import com._1c.g5.v8.dt.platform.version.IRuntimeVersionSupport;
|
||||||
|
import com._1c.g5.v8.dt.platform.version.Version;
|
||||||
|
import com.e1c.g5.v8.dt.check.CheckComplexity;
|
||||||
|
import com.e1c.g5.v8.dt.check.ICheckParameters;
|
||||||
|
import com.e1c.g5.v8.dt.check.components.BasicCheck;
|
||||||
|
import com.e1c.g5.v8.dt.check.settings.IssueSeverity;
|
||||||
|
import com.e1c.g5.v8.dt.check.settings.IssueType;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks queries in loops.
|
||||||
|
* Skip checks for queries in infinite while loops by default.
|
||||||
|
*
|
||||||
|
* @author Aleksandr Kapralov
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class QueryInLoopCheck
|
||||||
|
extends BasicCheck
|
||||||
|
{
|
||||||
|
|
||||||
|
private static final String CHECK_ID = "query-in-loop"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
private static final String PARAM_CHECK_QUERIY_IN_INFINITE_LOOP = "checkQueryInInfiniteLoop"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
private static final String DEFAULT_CHECK_QUERY_IN_INFINITE_LOOP = Boolean.toString(false);
|
||||||
|
|
||||||
|
private final TypesComputer typesComputer;
|
||||||
|
|
||||||
|
private final IRuntimeVersionSupport versionSupport;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public QueryInLoopCheck(IRuntimeVersionSupport versionSupport)
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
|
||||||
|
IResourceServiceProvider rsp =
|
||||||
|
IResourceServiceProvider.Registry.INSTANCE.getResourceServiceProvider(URI.createURI("*.bsl")); //$NON-NLS-1$
|
||||||
|
typesComputer = rsp.get(TypesComputer.class);
|
||||||
|
|
||||||
|
this.versionSupport = versionSupport;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCheckId()
|
||||||
|
{
|
||||||
|
return CHECK_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configureCheck(CheckConfigurer builder)
|
||||||
|
{
|
||||||
|
//@formatter:off
|
||||||
|
builder.title(Messages.QueryInLoop_title)
|
||||||
|
.description(Messages.QueryInLoop_description)
|
||||||
|
.disable()
|
||||||
|
.complexity(CheckComplexity.NORMAL)
|
||||||
|
.severity(IssueSeverity.CRITICAL)
|
||||||
|
.issueType(IssueType.PERFORMANCE)
|
||||||
|
.module()
|
||||||
|
.checkedObjectType(MODULE)
|
||||||
|
.parameter(PARAM_CHECK_QUERIY_IN_INFINITE_LOOP, Boolean.class, DEFAULT_CHECK_QUERY_IN_INFINITE_LOOP,
|
||||||
|
Messages.QueryInLoop_check_query_in_infinite_loop);
|
||||||
|
//@formatter:on
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void check(Object object, ResultAcceptor resultAceptor, ICheckParameters parameters,
|
||||||
|
IProgressMonitor monitor)
|
||||||
|
{
|
||||||
|
if (monitor.isCanceled() || !(object instanceof Module))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Module module = (Module)object;
|
||||||
|
|
||||||
|
Set<String> queryExecutionMethods = getQueryExecutionMethods(module);
|
||||||
|
if (queryExecutionMethods.isEmpty())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, String> methodsWithQuery = getMethodsWithQuery(module, queryExecutionMethods, monitor);
|
||||||
|
if (methodsWithQuery.isEmpty())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean checkQueryInInfiniteLoop = parameters.getBoolean(PARAM_CHECK_QUERIY_IN_INFINITE_LOOP);
|
||||||
|
Collection<FeatureAccess> queryInLoopCallers =
|
||||||
|
getQueryInLoopCallers(module, methodsWithQuery, queryExecutionMethods, checkQueryInInfiniteLoop, monitor);
|
||||||
|
|
||||||
|
for (FeatureAccess featureAccess : queryInLoopCallers)
|
||||||
|
{
|
||||||
|
if (monitor.isCanceled())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (featureAccess instanceof DynamicFeatureAccess)
|
||||||
|
{
|
||||||
|
resultAceptor.addIssue(Messages.QueryInLoop_Loop_has_query, featureAccess, FEATURE_ACCESS__NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (featureAccess instanceof StaticFeatureAccess)
|
||||||
|
{
|
||||||
|
String errorPath = methodsWithQuery.get(featureAccess.getName());
|
||||||
|
String errorMessage =
|
||||||
|
MessageFormat.format(Messages.QueryInLoop_Loop_has_method_with_query__0, errorPath);
|
||||||
|
resultAceptor.addIssue(errorMessage, featureAccess, FEATURE_ACCESS__NAME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<String> getQueryExecutionMethods(EObject object)
|
||||||
|
{
|
||||||
|
Set<String> queryExecuteMethods = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
|
||||||
|
|
||||||
|
IEObjectProvider provider = IEObjectProvider.Registry.INSTANCE.get(McorePackage.Literals.TYPE_ITEM,
|
||||||
|
versionSupport.getRuntimeVersionOrDefault(object, Version.LATEST));
|
||||||
|
EObject proxyType = provider.getProxy(IEObjectTypeNames.QUERY);
|
||||||
|
if (!(proxyType instanceof Type))
|
||||||
|
{
|
||||||
|
return queryExecuteMethods;
|
||||||
|
}
|
||||||
|
|
||||||
|
Type queryType = (Type)EcoreUtil.resolve(proxyType, object);
|
||||||
|
|
||||||
|
ContextDef contextDef = queryType.getContextDef();
|
||||||
|
if (contextDef == null)
|
||||||
|
{
|
||||||
|
return queryExecuteMethods;
|
||||||
|
}
|
||||||
|
|
||||||
|
EList<com._1c.g5.v8.dt.mcore.Method> queryMethods = contextDef.allMethods();
|
||||||
|
for (com._1c.g5.v8.dt.mcore.Method queryMethod : queryMethods)
|
||||||
|
{
|
||||||
|
if (!queryMethod.getName().startsWith("Execute")) //$NON-NLS-1$
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
queryExecuteMethods.add(queryMethod.getName());
|
||||||
|
queryExecuteMethods.add(queryMethod.getNameRu());
|
||||||
|
}
|
||||||
|
|
||||||
|
return queryExecuteMethods;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isQueryTypeSource(Expression source)
|
||||||
|
{
|
||||||
|
Environmental envs = EcoreUtil2.getContainerOfType(source, Environmental.class);
|
||||||
|
List<TypeItem> sourceTypes = typesComputer.computeTypes(source, envs.environments());
|
||||||
|
if (sourceTypes.isEmpty())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (TypeItem sourceType : sourceTypes)
|
||||||
|
{
|
||||||
|
if (IEObjectTypeNames.QUERY.equals(McoreUtil.getTypeName(sourceType)))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isQueryExecution(DynamicFeatureAccess dfa, Set<String> queryExecutionMethods)
|
||||||
|
{
|
||||||
|
return queryExecutionMethods.contains(dfa.getName()) && BslUtil.getInvocation(dfa) != null
|
||||||
|
&& isQueryTypeSource(dfa.getSource());
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getSourceName(Expression source)
|
||||||
|
{
|
||||||
|
String result = ""; //$NON-NLS-1$
|
||||||
|
|
||||||
|
if (source instanceof FeatureAccess)
|
||||||
|
{
|
||||||
|
result = ((FeatureAccess)source).getName() + "."; //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (source instanceof Invocation)
|
||||||
|
{
|
||||||
|
result = getSourceName(((Invocation)source).getMethodAccess());
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getPositionForFeatureObject(EObject object)
|
||||||
|
{
|
||||||
|
ICompositeNode node = NodeModelUtils.findActualNodeFor(object);
|
||||||
|
return MessageFormat.format("'{'{0}'}' ", String.valueOf(node.getStartLine())); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getMethodPath(Method method, Map<String, String> result)
|
||||||
|
{
|
||||||
|
if (result.containsKey(method.getName()))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
StaticFeatureAccess calledMethod = getMethodWithQuery(method, result);
|
||||||
|
if (calledMethod == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String calledMethodPath = result.get(calledMethod.getName());
|
||||||
|
if (calledMethodPath == null)
|
||||||
|
{
|
||||||
|
calledMethodPath = calledMethod.getName() + "()"; //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
return String.join("", method.getName(), "() -> ", //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
getPositionForFeatureObject(calledMethod), calledMethodPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, String> getMethodsWithQuery(Module module, Set<String> queryExecutionMethods,
|
||||||
|
IProgressMonitor monitor)
|
||||||
|
{
|
||||||
|
Map<String, String> result = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
|
||||||
|
|
||||||
|
for (DynamicFeatureAccess dfa : EcoreUtil2.eAllOfType(module, DynamicFeatureAccess.class))
|
||||||
|
{
|
||||||
|
if (monitor.isCanceled())
|
||||||
|
{
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isQueryExecution(dfa, queryExecutionMethods))
|
||||||
|
{
|
||||||
|
Method method = EcoreUtil2.getContainerOfType(dfa, Method.class);
|
||||||
|
String sourceName = getSourceName(dfa.getSource());
|
||||||
|
|
||||||
|
String methodPath = String.join("", method.getName(), "() -> ", //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
getPositionForFeatureObject(dfa), sourceName, dfa.getName(), "()"); //$NON-NLS-1$
|
||||||
|
result.put(method.getName(), methodPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EList<Method> methods = module.allMethods();
|
||||||
|
|
||||||
|
int methodsCount = 0;
|
||||||
|
while (result.size() != methodsCount)
|
||||||
|
{
|
||||||
|
for (Method method : methods)
|
||||||
|
{
|
||||||
|
if (monitor.isCanceled())
|
||||||
|
{
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
String methodPath = getMethodPath(method, result);
|
||||||
|
if (methodPath == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.put(method.getName(), methodPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
methodsCount = result.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isMethodWithQueryCalled(StaticFeatureAccess sfa, Map<String, String> methodsWithQuery)
|
||||||
|
{
|
||||||
|
return methodsWithQuery.containsKey(sfa.getName()) && BslUtil.getInvocation(sfa) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private StaticFeatureAccess getMethodWithQuery(Method method, Map<String, String> methodsWithQuery)
|
||||||
|
{
|
||||||
|
for (StaticFeatureAccess sfa : EcoreUtil2.eAllOfType(method, StaticFeatureAccess.class))
|
||||||
|
{
|
||||||
|
if (isMethodWithQueryCalled(sfa, methodsWithQuery))
|
||||||
|
{
|
||||||
|
return sfa;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isInfiniteWhileLoop(LoopStatement loopStatement)
|
||||||
|
{
|
||||||
|
if (!(loopStatement instanceof WhileStatement))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression predicate = ((WhileStatement)loopStatement).getPredicate();
|
||||||
|
return predicate instanceof BooleanLiteral;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Collection<FeatureAccess> getQueryInLoopCallers(Module module, Map<String, String> methodsWithQuery,
|
||||||
|
Set<String> queryExecutionMethods, boolean checkQueryInInfiniteLoop, IProgressMonitor monitor)
|
||||||
|
{
|
||||||
|
Collection<FeatureAccess> result = new ArrayList<>();
|
||||||
|
|
||||||
|
for (LoopStatement loopStatement : EcoreUtil2.eAllOfType(module, LoopStatement.class))
|
||||||
|
{
|
||||||
|
if (monitor.isCanceled())
|
||||||
|
{
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!checkQueryInInfiniteLoop && isInfiniteWhileLoop(loopStatement))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (FeatureAccess featureAccess : EcoreUtil2.eAllOfType(loopStatement, FeatureAccess.class))
|
||||||
|
{
|
||||||
|
if (featureAccess instanceof StaticFeatureAccess
|
||||||
|
&& isMethodWithQueryCalled((StaticFeatureAccess)featureAccess, methodsWithQuery)
|
||||||
|
|| featureAccess instanceof DynamicFeatureAccess
|
||||||
|
&& isQueryExecution((DynamicFeatureAccess)featureAccess, queryExecutionMethods))
|
||||||
|
{
|
||||||
|
result.add(featureAccess);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/)
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Copyright (C) 2021, 1C-Soft LLC and others.
|
# Copyright (C) 2021, 1C-Soft LLC and others.
|
||||||
#
|
#
|
||||||
@ -9,8 +10,23 @@
|
|||||||
#
|
#
|
||||||
# Contributors:
|
# Contributors:
|
||||||
# 1C-Soft LLC - initial API and implementation
|
# 1C-Soft LLC - initial API and implementation
|
||||||
|
# Aleksandr Kapralov - issue #17
|
||||||
###############################################################################
|
###############################################################################
|
||||||
StructureCtorTooManyKeysCheck_description=Check structure constructor has too many keys
|
|
||||||
StructureCtorTooManyKeysCheck_Maximum_structure_constructor_keys=Maximum structure constructor keys
|
QueryInLoop_Loop_has_method_with_query__0 = Loop has method with query "{0}"
|
||||||
StructureCtorTooManyKeysCheck_Structure_constructor_has_more_than__0__keys=Structure constructor has more than {0} keys
|
|
||||||
StructureCtorTooManyKeysCheck_title=Structure constructor has too many keys
|
QueryInLoop_Loop_has_query = Loop has query
|
||||||
|
|
||||||
|
QueryInLoop_check_query_in_infinite_loop = Check query in infinite loop
|
||||||
|
|
||||||
|
QueryInLoop_description = Check query in loop
|
||||||
|
|
||||||
|
QueryInLoop_title = Query in loop
|
||||||
|
|
||||||
|
StructureCtorTooManyKeysCheck_Maximum_structure_constructor_keys = Maximum structure constructor keys
|
||||||
|
|
||||||
|
StructureCtorTooManyKeysCheck_Structure_constructor_has_more_than__0__keys = Structure constructor has more than {0} keys
|
||||||
|
|
||||||
|
StructureCtorTooManyKeysCheck_description = Check structure constructor has too many keys
|
||||||
|
|
||||||
|
StructureCtorTooManyKeysCheck_title = Structure constructor has too many keys
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/)
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Copyright (C) 2021, 1C-Soft LLC and others.
|
# Copyright (C) 2021, 1C-Soft LLC and others.
|
||||||
#
|
#
|
||||||
@ -9,10 +10,20 @@
|
|||||||
#
|
#
|
||||||
# Contributors:
|
# Contributors:
|
||||||
# 1C-Soft LLC - initial API and implementation
|
# 1C-Soft LLC - initial API and implementation
|
||||||
|
# Aleksandr Kapralov - issue #17
|
||||||
###############################################################################
|
###############################################################################
|
||||||
#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/)
|
|
||||||
|
|
||||||
StructureCtorTooManyKeysCheck_Maximum_structure_constructor_keys = Мксимальное количество ключей структуры в контструкторе
|
QueryInLoop_Loop_has_method_with_query__0 = Цикл содержит вызов метода с запросом "{0}"
|
||||||
|
|
||||||
|
QueryInLoop_Loop_has_query = Цикл содержит выполнение запроса
|
||||||
|
|
||||||
|
QueryInLoop_check_query_in_infinite_loop = Проверять запрос в бесконечном цикле
|
||||||
|
|
||||||
|
QueryInLoop_description = Проверка запрос в цикле
|
||||||
|
|
||||||
|
QueryInLoop_title = Запрос в цикле
|
||||||
|
|
||||||
|
StructureCtorTooManyKeysCheck_Maximum_structure_constructor_keys = Максимальное количество ключей структуры в контструкторе
|
||||||
|
|
||||||
StructureCtorTooManyKeysCheck_Structure_constructor_has_more_than__0__keys = Конструктор структуры содержит более чем {0} ключей
|
StructureCtorTooManyKeysCheck_Structure_constructor_has_more_than__0__keys = Конструктор структуры содержит более чем {0} ключей
|
||||||
|
|
||||||
|
@ -9,11 +9,13 @@
|
|||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* 1C-Soft LLC - initial API and implementation
|
* 1C-Soft LLC - initial API and implementation
|
||||||
|
* Aleksandr Kapralov - issue #17
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package com.e1c.v8codestyle.internal.bsl;
|
package com.e1c.v8codestyle.internal.bsl;
|
||||||
|
|
||||||
import org.eclipse.core.runtime.Plugin;
|
import org.eclipse.core.runtime.Plugin;
|
||||||
|
|
||||||
|
import com._1c.g5.v8.dt.platform.version.IRuntimeVersionSupport;
|
||||||
import com._1c.g5.wiring.AbstractServiceAwareModule;
|
import com._1c.g5.wiring.AbstractServiceAwareModule;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -32,8 +34,7 @@ class ExternalDependenciesModule
|
|||||||
@Override
|
@Override
|
||||||
protected void doConfigure()
|
protected void doConfigure()
|
||||||
{
|
{
|
||||||
// bind V8 services
|
bind(IRuntimeVersionSupport.class).toService();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,195 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* 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:
|
||||||
|
* Aleksandr Kapralov - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.e1c.v8codestyle.bsl.check.itests;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
import org.eclipse.emf.ecore.util.EcoreUtil;
|
||||||
|
import org.eclipse.xtext.EcoreUtil2;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com._1c.g5.v8.bm.core.IBmObject;
|
||||||
|
import com._1c.g5.v8.dt.bsl.model.FeatureAccess;
|
||||||
|
import com._1c.g5.v8.dt.bsl.model.Method;
|
||||||
|
import com._1c.g5.v8.dt.bsl.model.Module;
|
||||||
|
import com._1c.g5.v8.dt.core.platform.IDtProject;
|
||||||
|
import com._1c.g5.v8.dt.metadata.mdclass.CommonModule;
|
||||||
|
import com._1c.g5.v8.dt.validation.marker.IExtraInfoKeys;
|
||||||
|
import com._1c.g5.v8.dt.validation.marker.Marker;
|
||||||
|
import com.e1c.g5.v8.dt.check.settings.CheckUid;
|
||||||
|
import com.e1c.g5.v8.dt.check.settings.ICheckSettings;
|
||||||
|
import com.e1c.g5.v8.dt.testing.check.CheckTestBase;
|
||||||
|
import com.e1c.v8codestyle.bsl.check.QueryInLoopCheck;
|
||||||
|
import com.e1c.v8codestyle.internal.bsl.BslPlugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link QueryInLoopCheck} check.
|
||||||
|
*
|
||||||
|
* @author Aleksandr Kapralov
|
||||||
|
*/
|
||||||
|
public class QueryInLoopCheckTest
|
||||||
|
extends CheckTestBase
|
||||||
|
{
|
||||||
|
|
||||||
|
private static final String PROJECT_NAME = "QueryInLoop";
|
||||||
|
|
||||||
|
private static final String CHECK_ID = "query-in-loop"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
private static final String PARAM_CHECK_QUERIY_IN_INFINITE_LOOP = "checkQueryInInfiniteLoop"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testQueryInLoop() throws Exception
|
||||||
|
{
|
||||||
|
IDtProject dtProject = openProjectAndWaitForValidationFinish(PROJECT_NAME);
|
||||||
|
assertNotNull(dtProject);
|
||||||
|
|
||||||
|
IBmObject mdObject = getTopObjectByFqn("CommonModule.CommonModule", dtProject);
|
||||||
|
assertTrue(mdObject instanceof CommonModule);
|
||||||
|
Module module = ((CommonModule)mdObject).getModule();
|
||||||
|
assertNotNull(module);
|
||||||
|
|
||||||
|
String id = module.eResource().getURI().toPlatformString(true);
|
||||||
|
Marker[] markers = markerManager.getMarkers(dtProject.getWorkspaceProject(), id);
|
||||||
|
assertNotNull(markers);
|
||||||
|
|
||||||
|
Set<String> uriErrors = new HashSet<>();
|
||||||
|
|
||||||
|
for (Method method : module.allMethods())
|
||||||
|
{
|
||||||
|
List<FeatureAccess> featureAccessList = EcoreUtil2.eAllOfType(method, FeatureAccess.class);
|
||||||
|
|
||||||
|
switch (method.getName())
|
||||||
|
{
|
||||||
|
case "QueryCorrect":
|
||||||
|
case "QueryExecutionCorrect":
|
||||||
|
case "MethodCallsQueryCorrect":
|
||||||
|
case "MethodCallsIncorrectMethodCorrect":
|
||||||
|
case "GetNewQuery":
|
||||||
|
{
|
||||||
|
// Those methods doesn't have errors
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case "ForEachStatementIncorrect":
|
||||||
|
{
|
||||||
|
assertEquals(14, featureAccessList.size());
|
||||||
|
uriErrors.add(EcoreUtil.getURI(featureAccessList.get(8)).toString());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "ForToStatementIncorrect":
|
||||||
|
{
|
||||||
|
assertEquals(12, featureAccessList.size());
|
||||||
|
uriErrors.add(EcoreUtil.getURI(featureAccessList.get(7)).toString());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "WhileStatementIncorrect":
|
||||||
|
{
|
||||||
|
assertEquals(9, featureAccessList.size());
|
||||||
|
uriErrors.add(EcoreUtil.getURI(featureAccessList.get(3)).toString());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "LoopCallsMethodIncorrect":
|
||||||
|
{
|
||||||
|
assertEquals(9, featureAccessList.size());
|
||||||
|
uriErrors.add(EcoreUtil.getURI(featureAccessList.get(4)).toString());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "LoopCallsMethodWithOtherMethodIncorrect":
|
||||||
|
{
|
||||||
|
assertEquals(6, featureAccessList.size());
|
||||||
|
uriErrors.add(EcoreUtil.getURI(featureAccessList.get(3)).toString());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "LoopWithConditionsIncorrect":
|
||||||
|
{
|
||||||
|
assertEquals(12, featureAccessList.size());
|
||||||
|
uriErrors.add(EcoreUtil.getURI(featureAccessList.get(2)).toString());
|
||||||
|
uriErrors.add(EcoreUtil.getURI(featureAccessList.get(6)).toString());
|
||||||
|
uriErrors.add(EcoreUtil.getURI(featureAccessList.get(8)).toString());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "QueryTypeFromFunctionIncorrect":
|
||||||
|
{
|
||||||
|
assertEquals(9, featureAccessList.size());
|
||||||
|
uriErrors.add(EcoreUtil.getURI(featureAccessList.get(2)).toString());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
throw new IllegalStateException(MessageFormat.format("Unknown method name {0}", method.getName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Marker marker : markers)
|
||||||
|
{
|
||||||
|
String checkUid = getCheckIdFromMarker(marker, dtProject);
|
||||||
|
assertNotNull(checkUid);
|
||||||
|
assertTrue(CHECK_ID.equals(checkUid));
|
||||||
|
|
||||||
|
String uriToProblem = marker.getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_URI_TO_PROBLEM_KEY);
|
||||||
|
assertTrue(uriErrors.contains(uriToProblem));
|
||||||
|
uriErrors.remove(uriToProblem);
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(0, uriErrors.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
private CheckUid cuid(String checkId)
|
||||||
|
{
|
||||||
|
return new CheckUid(checkId, BslPlugin.PLUGIN_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInfiniteLoop() throws Exception
|
||||||
|
{
|
||||||
|
IDtProject dtProject = openProjectAndWaitForValidationFinish(PROJECT_NAME);
|
||||||
|
assertNotNull(dtProject);
|
||||||
|
|
||||||
|
IBmObject mdObject = getTopObjectByFqn("CommonModule.InfiniteLoop", dtProject);
|
||||||
|
assertTrue(mdObject instanceof CommonModule);
|
||||||
|
Module module = ((CommonModule)mdObject).getModule();
|
||||||
|
assertNotNull(module);
|
||||||
|
|
||||||
|
String id = module.eResource().getURI().toPlatformString(true);
|
||||||
|
Marker[] markers = markerManager.getMarkers(dtProject.getWorkspaceProject(), id);
|
||||||
|
assertNotNull(markers);
|
||||||
|
|
||||||
|
assertEquals(0, markers.length);
|
||||||
|
|
||||||
|
IProject project = dtProject.getWorkspaceProject();
|
||||||
|
ICheckSettings settings = checkRepository.getSettings(cuid(CHECK_ID), project);
|
||||||
|
settings.getParameters().get(PARAM_CHECK_QUERIY_IN_INFINITE_LOOP).setValue(Boolean.toString(true));
|
||||||
|
checkRepository.applyChanges(Collections.singleton(settings), project);
|
||||||
|
waitForDD(dtProject);
|
||||||
|
|
||||||
|
markers = markerManager.getMarkers(dtProject.getWorkspaceProject(), id);
|
||||||
|
assertNotNull(markers);
|
||||||
|
|
||||||
|
assertEquals(1, markers.length);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>QueryInLoop</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.xtext.ui.shared.xtextBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.xtext.ui.shared.xtextNature</nature>
|
||||||
|
<nature>com._1c.g5.v8.dt.core.V8ConfigurationNature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"settings": {
|
||||||
|
"query-in-loop": {
|
||||||
|
"enabled": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,2 @@
|
|||||||
|
eclipse.preferences.version=1
|
||||||
|
topObjects=true
|
@ -0,0 +1,2 @@
|
|||||||
|
eclipse.preferences.version=1
|
||||||
|
encoding/<project>=UTF-8
|
@ -0,0 +1,2 @@
|
|||||||
|
Manifest-Version: 1.0
|
||||||
|
Runtime-Version: 8.3.19
|
@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<mdclass:CommonModule xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass" uuid="1f97dda8-37e7-4746-915e-00498e2ecd48">
|
||||||
|
<name>CommonModule</name>
|
||||||
|
<synonym>
|
||||||
|
<key>en</key>
|
||||||
|
<value>Common module</value>
|
||||||
|
</synonym>
|
||||||
|
<server>true</server>
|
||||||
|
<externalConnection>true</externalConnection>
|
||||||
|
<clientOrdinaryApplication>true</clientOrdinaryApplication>
|
||||||
|
</mdclass:CommonModule>
|
@ -0,0 +1,148 @@
|
|||||||
|
Procedure QueryCorrect(SomeParameter) Export
|
||||||
|
|
||||||
|
SimpleQuery = New Query;
|
||||||
|
|
||||||
|
SimpleQuery.SetParameter("SomeParameter", SomeParameter);
|
||||||
|
|
||||||
|
SimpleQuery.Text =
|
||||||
|
"SELECT
|
||||||
|
| 1";
|
||||||
|
|
||||||
|
SimpleQuery.Execute();
|
||||||
|
|
||||||
|
EndProcedure
|
||||||
|
|
||||||
|
Function QueryExecutionCorrect(Query) Export
|
||||||
|
|
||||||
|
Result = Query.Execute();
|
||||||
|
|
||||||
|
Return Result;
|
||||||
|
|
||||||
|
EndFunction
|
||||||
|
|
||||||
|
Procedure MethodCallsQueryCorrect(SomeParameter) Export
|
||||||
|
|
||||||
|
QueryCorrect(SomeParameter);
|
||||||
|
|
||||||
|
EndProcedure
|
||||||
|
|
||||||
|
Procedure ForEachStatementIncorrect(SomeArray) Export
|
||||||
|
|
||||||
|
ForEachQuery = New Query;
|
||||||
|
|
||||||
|
ForEachQuery.Text =
|
||||||
|
"SELECT
|
||||||
|
| 1";
|
||||||
|
|
||||||
|
For Each ArrayElement In SomeArray Do
|
||||||
|
ForEachQuery.SetParameter("SomeParameter", ArrayElement);
|
||||||
|
Selection = ForEachQuery.Execute().Select();
|
||||||
|
Selection.Next();
|
||||||
|
EndDo;
|
||||||
|
|
||||||
|
EndProcedure
|
||||||
|
|
||||||
|
Procedure ForToStatementIncorrect(SomeArray) Export
|
||||||
|
|
||||||
|
ForToQuery = New Query;
|
||||||
|
|
||||||
|
ForToQuery.Text =
|
||||||
|
"SELECT
|
||||||
|
| 1";
|
||||||
|
|
||||||
|
For ArrayElement = 1 To 10 Do
|
||||||
|
ForToQuery.SetParameter("SomeParameter", ArrayElement);
|
||||||
|
Result = ForToQuery.ExecuteBatch();
|
||||||
|
Result[0].Select();
|
||||||
|
EndDo;
|
||||||
|
|
||||||
|
EndProcedure
|
||||||
|
|
||||||
|
Procedure WhileStatementIncorrect(SomeArray) Export
|
||||||
|
|
||||||
|
WhileQuery = New Query;
|
||||||
|
|
||||||
|
WhileQuery.Text =
|
||||||
|
"SELECT
|
||||||
|
| 1";
|
||||||
|
|
||||||
|
While SomeArray.Count() > 0 And SomeArray.Count() < 5 Do
|
||||||
|
WhileQuery.ExecuteBatchWithIntermediateData();
|
||||||
|
EndDo;
|
||||||
|
|
||||||
|
EndProcedure
|
||||||
|
|
||||||
|
Procedure MethodCallsIncorrectMethodCorrect(SomeArray) Export
|
||||||
|
|
||||||
|
ForEachStatementIncorrect(SomeArray);
|
||||||
|
|
||||||
|
EndProcedure
|
||||||
|
|
||||||
|
Procedure LoopCallsMethodIncorrect(SomeParameter) Export
|
||||||
|
|
||||||
|
LoopCallQuery = New Query;
|
||||||
|
|
||||||
|
LoopCallQuery.Text =
|
||||||
|
"SELECT
|
||||||
|
| 1";
|
||||||
|
|
||||||
|
While SomeParameter = 0 Do
|
||||||
|
Result = QueryExecutionCorrect(LoopCallQuery);
|
||||||
|
Result.Select();
|
||||||
|
EndDo;
|
||||||
|
|
||||||
|
EndProcedure
|
||||||
|
|
||||||
|
Procedure LoopCallsMethodWithOtherMethodIncorrect(SomeParameter) Export
|
||||||
|
|
||||||
|
MethodCallQuery = New Query;
|
||||||
|
|
||||||
|
MethodCallQuery.Text =
|
||||||
|
"SELECT
|
||||||
|
| 1";
|
||||||
|
|
||||||
|
While SomeParameter = 0 Do
|
||||||
|
MethodCallsQueryCorrect(MethodCallQuery);
|
||||||
|
EndDo;
|
||||||
|
|
||||||
|
EndProcedure
|
||||||
|
|
||||||
|
Procedure LoopWithConditionsIncorrect(SomeArray) Export
|
||||||
|
|
||||||
|
While SomeArray.Count() = 0 Do
|
||||||
|
If SomeArray.Size() = 1 Then
|
||||||
|
ForEachStatementIncorrect(SomeArray);
|
||||||
|
|
||||||
|
ElsIf SomeArray.Size() = 2 Then
|
||||||
|
ForToStatementIncorrect(SomeArray);
|
||||||
|
|
||||||
|
Else
|
||||||
|
WhileStatementIncorrect(SomeArray);
|
||||||
|
|
||||||
|
EndIf;
|
||||||
|
EndDo;
|
||||||
|
|
||||||
|
EndProcedure
|
||||||
|
|
||||||
|
Function GetNewQuery(ArrayElement)
|
||||||
|
|
||||||
|
FunctionQuery = New Query;
|
||||||
|
|
||||||
|
FunctionQuery.Text =
|
||||||
|
"SELECT
|
||||||
|
| 1";
|
||||||
|
|
||||||
|
FunctionQuery.SetParameter("SomeParameter", ArrayElement);
|
||||||
|
|
||||||
|
Return FunctionQuery;
|
||||||
|
|
||||||
|
EndFunction
|
||||||
|
|
||||||
|
Procedure QueryTypeFromFunctionIncorrect(SomeArray) Export
|
||||||
|
|
||||||
|
For Each ArrayElement In SomeArray Do
|
||||||
|
Selection = GetNewQuery(ArrayElement).Execute().Select();
|
||||||
|
Selection.Next();
|
||||||
|
EndDo;
|
||||||
|
|
||||||
|
EndProcedure
|
@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<mdclass:CommonModule xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass" uuid="d83a4f24-b0a1-49f1-96be-01e8955a2adf">
|
||||||
|
<name>InfiniteLoop</name>
|
||||||
|
<synonym>
|
||||||
|
<key>en</key>
|
||||||
|
<value>Infinite loop</value>
|
||||||
|
</synonym>
|
||||||
|
<server>true</server>
|
||||||
|
<externalConnection>true</externalConnection>
|
||||||
|
<clientOrdinaryApplication>true</clientOrdinaryApplication>
|
||||||
|
</mdclass:CommonModule>
|
@ -0,0 +1,13 @@
|
|||||||
|
Procedure WhileStatementInfiniteLoop(SomeArray) Export
|
||||||
|
|
||||||
|
Query = New Query;
|
||||||
|
|
||||||
|
Query.Text =
|
||||||
|
"SELECT
|
||||||
|
| 1";
|
||||||
|
|
||||||
|
While True Do
|
||||||
|
Query.ExecuteBatchWithIntermediateData();
|
||||||
|
EndDo;
|
||||||
|
|
||||||
|
EndProcedure
|
@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<cmi:CommandInterface xmlns:cmi="http://g5.1c.ru/v8/dt/cmi"/>
|
@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<mdclass:Configuration xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass" uuid="f8166085-112b-4451-8d9e-88dbfe86d90f">
|
||||||
|
<name>QueryInLoop</name>
|
||||||
|
<synonym>
|
||||||
|
<key>en</key>
|
||||||
|
<value>Query in loop</value>
|
||||||
|
</synonym>
|
||||||
|
<containedObjects classId="9cd510cd-abfc-11d4-9434-004095e12fc7" objectId="133ede92-0c7f-4f71-9e9c-9f44c3da9722"/>
|
||||||
|
<containedObjects classId="9fcd25a0-4822-11d4-9414-008048da11f9" objectId="8d533318-a072-4c80-aa16-8893a3602ec4"/>
|
||||||
|
<containedObjects classId="e3687481-0a87-462c-a166-9f34594f9bba" objectId="5ec2f4d8-7bd9-4088-b89c-83e979381dae"/>
|
||||||
|
<containedObjects classId="9de14907-ec23-4a07-96f0-85521cb6b53b" objectId="aa80ec52-e027-4261-8209-52d0c99d52d9"/>
|
||||||
|
<containedObjects classId="51f2d5d8-ea4d-4064-8892-82951750031e" objectId="f44271e2-de0e-4466-8fe5-296bb6de7def"/>
|
||||||
|
<containedObjects classId="e68182ea-4237-4383-967f-90c1e3370bc7" objectId="ea7014f6-7658-4fd7-aa94-3abb90a8ac1c"/>
|
||||||
|
<configurationExtensionCompatibilityMode>8.3.16</configurationExtensionCompatibilityMode>
|
||||||
|
<defaultRunMode>ManagedApplication</defaultRunMode>
|
||||||
|
<usePurposes>PersonalComputer</usePurposes>
|
||||||
|
<requiredMobileApplicationPermissions>
|
||||||
|
<permission>AllowOSBackup</permission>
|
||||||
|
<use>true</use>
|
||||||
|
</requiredMobileApplicationPermissions>
|
||||||
|
<defaultLanguage>Language.English</defaultLanguage>
|
||||||
|
<dataLockControlMode>Managed</dataLockControlMode>
|
||||||
|
<objectAutonumerationMode>NotAutoFree</objectAutonumerationMode>
|
||||||
|
<modalityUseMode>DontUse</modalityUseMode>
|
||||||
|
<synchronousPlatformExtensionAndAddInCallUseMode>DontUse</synchronousPlatformExtensionAndAddInCallUseMode>
|
||||||
|
<compatibilityMode>8.3.19</compatibilityMode>
|
||||||
|
<languages uuid="0ced1c9f-d92b-4c54-80c9-6c421fac2136">
|
||||||
|
<name>English</name>
|
||||||
|
<synonym>
|
||||||
|
<key>en</key>
|
||||||
|
<value>English</value>
|
||||||
|
</synonym>
|
||||||
|
<languageCode>en</languageCode>
|
||||||
|
</languages>
|
||||||
|
<commonModules>CommonModule.CommonModule</commonModules>
|
||||||
|
<commonModules>CommonModule.InfiniteLoop</commonModules>
|
||||||
|
</mdclass:Configuration>
|
@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<cmi:CommandInterface xmlns:cmi="http://g5.1c.ru/v8/dt/cmi"/>
|
Loading…
x
Reference in New Issue
Block a user