From 642868ef12786ed94005f3141a107fb059285df7 Mon Sep 17 00:00:00 2001 From: Artem Iliukhin Date: Fri, 9 Dec 2022 00:42:53 -0500 Subject: [PATCH 01/23] =?UTF-8?q?=D0=9F=D1=80=D0=BE=D0=B2=D0=B5=D1=80?= =?UTF-8?q?=D1=8F=D0=B5=D1=82=20=D0=BE=D1=82=D1=81=D1=83=D1=82=D1=81=D1=82?= =?UTF-8?q?=D0=B2=D0=B8=D0=B5=20=D0=BA=D0=BE=D0=B4=D0=B0=20=D0=BF=D0=BE?= =?UTF-8?q?=D1=81=D0=BB=D0=B5=20=D0=B0=D1=81=D0=B8=D0=BD=D1=85=D1=80=D0=BE?= =?UTF-8?q?=D0=BD=D0=BD=D0=BE=D0=B3=D0=BE=20=D0=B2=D1=8B=D0=B7=D0=BE=D0=B2?= =?UTF-8?q?=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + .../markdown/code-after-async-call.md | 24 ++ .../markdown/ru/code-after-async-call.md | 44 ++++ bundles/com.e1c.v8codestyle.bsl/plugin.xml | 4 + .../bsl/check/CodeAfterAsyncCallCheck.java | 217 ++++++++++++++++++ .../e1c/v8codestyle/bsl/check/Messages.java | 6 + .../v8codestyle/bsl/check/messages.properties | 6 + .../bsl/check/messages_ru.properties | 6 + .../resources/async-call-back-descr.bsl | 16 ++ .../resources/async-call-promise.bsl | 9 + .../code-after-async-call-existence.bsl | 9 + .../itests/CodeAfterAsyncCallCheckTest.java | 70 ++++++ 12 files changed, 412 insertions(+) create mode 100644 bundles/com.e1c.v8codestyle.bsl/markdown/code-after-async-call.md create mode 100644 bundles/com.e1c.v8codestyle.bsl/markdown/ru/code-after-async-call.md create mode 100644 bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java create mode 100644 tests/com.e1c.v8codestyle.bsl.itests/resources/async-call-back-descr.bsl create mode 100644 tests/com.e1c.v8codestyle.bsl.itests/resources/async-call-promise.bsl create mode 100644 tests/com.e1c.v8codestyle.bsl.itests/resources/code-after-async-call-existence.bsl create mode 100644 tests/com.e1c.v8codestyle.bsl.itests/src/com/e1c/v8codestyle/bsl/check/itests/CodeAfterAsyncCallCheckTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 61c812980..32942ef22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ - Проверка наличия префикса расширения в методе расширения. - Устаревшая процедура (функция) расположена вне области "УстаревшиеПроцедурыИФункции" - Использован обработчик событий, подключаемый из кода и не содержащий префикса "Подключаемый_" +- Проверка отсутствия кода после асинхронного вызова #### Запросы diff --git a/bundles/com.e1c.v8codestyle.bsl/markdown/code-after-async-call.md b/bundles/com.e1c.v8codestyle.bsl/markdown/code-after-async-call.md new file mode 100644 index 000000000..755bba6b8 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/markdown/code-after-async-call.md @@ -0,0 +1,24 @@ +# The asynchronous method is not followed by lines of code + +In the asynchronous approach the method is called as usual, but control returns to the caller before the asynchronous +method is completed. After that, execution of the caller continues. + +## Noncompliant Code Example + +```bsl +Text = "Warning text"; +ShowMessageBox( , Text); +Message("Warning is closed"); +``` + +## Compliant Solution + +```bsl +Text = "Warning text"; +Await DoMessageBoxAsync(Text); +Message("Warning is closed"); +``` + +## See + +- [Synchronous and asynchronous operations](https://kb.1ci.com/1C_Enterprise_Platform/Guides/Developer_Guides/1C_Enterprise_8.3.19_Developer_Guide/Chapter_4._1C_Enterprise_language/4.7._Queries/4.7.9._Synchronous_and_asynchronous_operations/) \ No newline at end of file diff --git a/bundles/com.e1c.v8codestyle.bsl/markdown/ru/code-after-async-call.md b/bundles/com.e1c.v8codestyle.bsl/markdown/ru/code-after-async-call.md new file mode 100644 index 000000000..d4040b3cb --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/markdown/ru/code-after-async-call.md @@ -0,0 +1,44 @@ +# Код расположен после асинхронного вызова + +При асинхронном подходе вызов метода выполняется как обычно, но управление возвращается вызывающему коду до того, +как асинхронный метод завершит свою работу. После этого вызывающий код продолжает свое выполнение. +Особенность асинхронного выполнения: исполнение на стороне вызывающего кода продолжится до того, +как полностью закончилось исполнение вызванного метода + +Для правильного решения нужно вынести весь код, который должен быть выполнен после выполнения асинхронного действия, +в экспортный метод и указать его имя в обработке оповещения, которая будет вызвана после завершения асинхронного действия. +Или использовать асинхронность через обещания, например, Ждать ПредупреждениеАсинх(Текст); + +## Неправильно + +```bsl +Текст = "Текст предупреждения"; +ПоказатьПредупреждение( , Текст); +Сообщить("Закрыли предупреждение"); +``` + +## Правильно + +```bsl +Текст = "Текст предупреждения"; +Ждать ПредупреждениеАсинх(Текст); +Сообщить("Закрыли предупреждение"); +``` + +```bsl +&НаКлиенте +Процедура Команда1(Команда) + Оповещение = Новый ОписаниеОповещения("ПредупреждениеЗавершение", ЭтотОбъект); + Текст = "Текст предупреждения"; + ПоказатьПредупреждение(Оповещение, Текст); +КонецПроцедуры + +&НаКлиенте +Процедура ПредупреждениеЗавершение(ДополнительныеПараметры) Экспорт + Сообщить("Закрыли предупреждение"); +КонецПроцедуры; +``` + +## См. + +- [Синхронные и асинхронные методы работы](https://its.1c.ru/db/v8319doc#bookmark:dev:TI000001505) diff --git a/bundles/com.e1c.v8codestyle.bsl/plugin.xml b/bundles/com.e1c.v8codestyle.bsl/plugin.xml index 02050ec42..0e05eaf4d 100644 --- a/bundles/com.e1c.v8codestyle.bsl/plugin.xml +++ b/bundles/com.e1c.v8codestyle.bsl/plugin.xml @@ -343,6 +343,10 @@ category="com.e1c.v8codestyle.bsl" class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.check.DeprecatedProcedureOutsideDeprecatedRegionCheck"> + + diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java new file mode 100644 index 000000000..3d28c0559 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java @@ -0,0 +1,217 @@ +/******************************************************************************* + * Copyright (C) 2023, 1C-Soft LLC and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * 1C-Soft LLC - initial API and implementation + *******************************************************************************/ +package com.e1c.v8codestyle.bsl.check; + +import static com._1c.g5.v8.dt.bsl.model.BslPackage.Literals.INVOCATION; + +import java.util.Iterator; +import java.util.List; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.xtext.EcoreUtil2; +import org.eclipse.xtext.naming.IQualifiedNameConverter; + +import com._1c.g5.v8.dt.bsl.common.IBslPreferences; +import com._1c.g5.v8.dt.bsl.model.BslPackage; +import com._1c.g5.v8.dt.bsl.model.Conditional; +import com._1c.g5.v8.dt.bsl.model.EmptyStatement; +import com._1c.g5.v8.dt.bsl.model.FeatureAccess; +import com._1c.g5.v8.dt.bsl.model.IfStatement; +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.PreprocessorItemStatements; +import com._1c.g5.v8.dt.bsl.model.ReturnStatement; +import com._1c.g5.v8.dt.bsl.model.Statement; +import com._1c.g5.v8.dt.bsl.model.StaticFeatureAccess; +import com._1c.g5.v8.dt.bsl.model.TryExceptStatement; +import com._1c.g5.v8.dt.core.platform.IResourceLookup; +import com.e1c.g5.v8.dt.check.CheckComplexity; +import com.e1c.g5.v8.dt.check.ICheckParameters; +import com.e1c.g5.v8.dt.check.settings.IssueSeverity; +import com.e1c.g5.v8.dt.check.settings.IssueType; +import com.e1c.v8codestyle.bsl.strict.check.AbstractTypeCheck; +import com.e1c.v8codestyle.check.CommonSenseCheckExtension; +import com.e1c.v8codestyle.internal.bsl.BslPlugin; +import com.google.common.collect.Lists; +import com.google.inject.Inject; + +/** + * Checks that the asynchronous method is not followed by lines of code, + * since in this case the specified lines of code are executed immediately, + * without waiting for the asynchronous method to execute. + * + * @author Artem Iliukhin + */ +public final class CodeAfterAsyncCallCheck + extends AbstractTypeCheck +{ + + private static final String CHECK_ID = "code-after-async-call"; //$NON-NLS-1$ + + // @formatter:off + private static final String[] ASYNCHRONOUS_METHODS = { + "ShowMessageBox", "ПоказатьПредупреждение", //$NON-NLS-1$ //$NON-NLS-2$ + "ShowInputDate", "ПоказатьВводДаты", //$NON-NLS-1$ //$NON-NLS-2$ + "ShowInputValue", "ПоказатьВводЗначения", //$NON-NLS-1$ //$NON-NLS-2$ + "ShowInputString", "ПоказатьВводСтроки", //$NON-NLS-1$ //$NON-NLS-2$ + "ShowInputNumber", "ПоказатьВводЧисла", //$NON-NLS-1$ //$NON-NLS-2$ + "ShowQueryBox", "ПоказатьВопрос", //$NON-NLS-1$ //$NON-NLS-2$ + "BeginRequestingUserPermission", "НачатьЗапросРазрешенияПользователя", //$NON-NLS-1$ //$NON-NLS-2$ + "BeginRunningApplication", "НачатьЗапускПриложения", //$NON-NLS-1$ //$NON-NLS-2$ + "BeginGettingTempFilesDir", "НачатьПолучениеКаталогаВременныхФайлов", //$NON-NLS-1$ //$NON-NLS-2$ + "BeginGettingDocumentsDir", "НачатьПолучениеКаталогаДокументов", //$NON-NLS-1$ //$NON-NLS-2$ + "BeginCopyingFile", "НачатьКопированиеФайла", //$NON-NLS-1$ //$NON-NLS-2$ + "BeginFindingFiles", "НачатьПоискФайлов", //$NON-NLS-1$ //$NON-NLS-2$ + "ShowValue", "ПоказатьЗначение", //$NON-NLS-1$ //$NON-NLS-2$ + "OpenForm", "ОткрытьФорму", //$NON-NLS-1$ //$NON-NLS-2$ + "BeginMovingFile", "НачатьПеремещениеФайла", //$NON-NLS-1$ //$NON-NLS-2$ + "BeginAttachingCryptoExtension", "НачатьПодключениеРасширенияРаботыСКриптографией", //$NON-NLS-1$ //$NON-NLS-2$ + "BeginAttachingFileSystemExtension", "НачатьПодключениеРасширенияРаботыСФайлами", //$NON-NLS-1$ //$NON-NLS-2$ + "BeginGetFilesFromServer", "НачатьПолучениеФайловССервера", //$NON-NLS-1$ //$NON-NLS-2$ + "BeginPutFileToServer", "НачатьПомещениеФайлаНаСервер", //$NON-NLS-1$ //$NON-NLS-2$ + "BeginPutFilesToServer", "НачатьПомещениеФайловНаСервер", //$NON-NLS-1$ //$NON-NLS-2$ + "BeginGettingUserDataWorkDir", "НачатьПолучениеРабочегоКаталогаДанныхПользователя", //$NON-NLS-1$ //$NON-NLS-2$ + "BeginCreatingDirectory", "НачатьСозданиеКаталога", //$NON-NLS-1$ //$NON-NLS-2$ + "BeginInstallAddIn", "НачатьУстановкуВнешнейКомпоненты", //$NON-NLS-1$ //$NON-NLS-2$ + "BeginInstallCryptoExtension", "НачатьУстановкуРасширенияРаботыСКриптографией", //$NON-NLS-1$ //$NON-NLS-2$ + "BeginInstallFileSystemExtension", "НачатьУстановкуРасширенияРаботыСФайлами"}; //$NON-NLS-1$ //$NON-NLS-2$ + // @formatter:on + + @Inject + public CodeAfterAsyncCallCheck(IResourceLookup resourceLookup, IBslPreferences bslPreferences, + IQualifiedNameConverter qualifiedNameConverter) + { + super(resourceLookup, bslPreferences, qualifiedNameConverter); + } + + @Override + public String getCheckId() + { + return CHECK_ID; + } + + @Override + protected void configureCheck(CheckConfigurer builder) + { + builder.title(Messages.CodeAfterAsyncCallCheck_Title) + .description(Messages.CodeAfterAsyncCallCheck_Description) + .complexity(CheckComplexity.NORMAL) + .severity(IssueSeverity.MAJOR) + .issueType(IssueType.WARNING) + .extension(new CommonSenseCheckExtension(getCheckId(), BslPlugin.PLUGIN_ID)) + .module() + .checkedObjectType(INVOCATION); + } + + @Override + protected void check(Object object, ResultAcceptor resultAceptor, ICheckParameters parameters, + IProgressMonitor monitor) + { + Invocation inv = (Invocation)object; + FeatureAccess featureAccess = inv.getMethodAccess(); + if (featureAccess instanceof StaticFeatureAccess) + { + if (monitor.isCanceled()) + { + return; + } + + String nameFeature = featureAccess.getName(); + for (int i = 0; i < ASYNCHRONOUS_METHODS.length; i++) + { + if (ASYNCHRONOUS_METHODS[i].equalsIgnoreCase(nameFeature)) + { + Statement statement = getStatementFromInvoc(inv); + if (statement != null) + { + statement = getNextStatement(statement); + if (statement != null && !(statement instanceof ReturnStatement) + && !(statement instanceof EmptyStatement)) + { + resultAceptor.addIssue(Messages.CodeAfterAsyncCallCheck_Issue, statement); + } + } + } + } + } + } + + private Statement getStatementFromInvoc(Invocation invocation) + { + EObject container = invocation.eContainer(); + while (!(container instanceof Statement)) + { + container = container.eContainer(); + } + return container instanceof Statement ? (Statement)container : null; + } + + private Statement getNextStatement(Statement statement) + { + Iterator it = EcoreUtil2.getAllContainers(statement).iterator(); + while (it.hasNext()) + { + EObject container = it.next(); + List st = null; + if (container instanceof LoopStatement) + { + st = ((LoopStatement)container).getStatements(); + } + else if (container instanceof Conditional) + { + st = ((Conditional)container).getStatements(); + } + else if (container instanceof IfStatement) + { + st = ((IfStatement)container).getElseStatements(); + } + else if (container instanceof TryExceptStatement) + { + st = getStatementsFromContainer((TryExceptStatement)container); + } + else if (container instanceof PreprocessorItemStatements) + { + st = ((PreprocessorItemStatements)container).getStatements(); + } + else + { + st = getStatementsFromContainer(container); + } + if (st != null) + { + int index = st.indexOf(statement); + if (index != -1 && index + 1 < st.size()) + { + return st.get(index + 1); + } + } + } + return null; + } + + private List getStatementsFromContainer(TryExceptStatement container) + { + List res = Lists.newArrayList(); + res.addAll(container.getTryStatements()); + res.addAll(container.getExceptStatements()); + return res; + } + + @SuppressWarnings("unchecked") + private List getStatementsFromContainer(EObject container) + { + Object obj = container.eGet(BslPackage.Literals.BLOCK__STATEMENTS); + return obj instanceof List ? (List)obj : null; + } +} diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/Messages.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/Messages.java index edc610d8c..0df3c9249 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/Messages.java +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/Messages.java @@ -61,6 +61,12 @@ final class Messages public static String ChangeAndValidateInsteadOfAroundCheck_Use_ChangeAndValidate_instead_of_Around; public static String ChangeAndValidateInsteadOfAroundCheck_title; + public static String CodeAfterAsyncCallCheck_Description; + + public static String CodeAfterAsyncCallCheck_Issue; + + public static String CodeAfterAsyncCallCheck_Title; + public static String CommitTransactionCheck_Commit_transaction_must_be_in_try_catch; public static String CommitTransactionCheck_No_begin_transaction_for_commit_transaction; diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages.properties b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages.properties index a64d8be01..e42464df6 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages.properties +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages.properties @@ -54,6 +54,12 @@ ChangeAndValidateInsteadOfAroundCheck_description = Checks that pragma &ChangeAn ChangeAndValidateInsteadOfAroundCheck_title = Use pragma &ChangeAndValidate instead of &Around +CodeAfterAsyncCallCheck_Description=Checks that the asynchronous method is not followed by lines of code, since in this case the specified lines of code are executed immediately, without waiting for the asynchronous method to execute + +CodeAfterAsyncCallCheck_Issue=The asynchronous method is followed by lines of code + +CodeAfterAsyncCallCheck_Title=The code should not follow an asynchronous call + CommitTransactionCheck_Commit_transaction_must_be_in_try_catch=Commit transaction must be in a try-catch CommitTransactionCheck_No_begin_transaction_for_commit_transaction=There is no begin transaction for commit transaction diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages_ru.properties b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages_ru.properties index 870a1a6c4..6a9f78570 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages_ru.properties +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages_ru.properties @@ -54,6 +54,12 @@ ChangeAndValidateInsteadOfAroundCheck_description = Проверяет, что ChangeAndValidateInsteadOfAroundCheck_title = Используется аннотация &ИзменениеИКонтроль вместо &Вместо +CodeAfterAsyncCallCheck_Description=Проверяет, что за асинхронным методом не следуют строки кода, поскольку в этом случае указанные строки кода выполняются немедленно, не дожидаясь выполнения асинхронного метода + +CodeAfterAsyncCallCheck_Issue=За асинхронным методом следуют строки кода + +CodeAfterAsyncCallCheck_Title=Код не должен следовать за асинхронным вызовом + CommitTransactionCheck_Commit_transaction_must_be_in_try_catch=Вызов "ЗафиксироватьТранзакцию()" находится вне конструкции "Попытка... Исключение" CommitTransactionCheck_No_begin_transaction_for_commit_transaction=Отсутствует вызов "НачатьТранзакцию()", хотя вызываются "ЗафиксироватьТранзакцию()" diff --git a/tests/com.e1c.v8codestyle.bsl.itests/resources/async-call-back-descr.bsl b/tests/com.e1c.v8codestyle.bsl.itests/resources/async-call-back-descr.bsl new file mode 100644 index 000000000..77361aa36 --- /dev/null +++ b/tests/com.e1c.v8codestyle.bsl.itests/resources/async-call-back-descr.bsl @@ -0,0 +1,16 @@ + +&НаКлиенте +Процедура Тест() + + Оповещение = Новый ОписаниеОповещения("ПредупреждениеЗавершение", ЭтотОбъект); + Текст = "Текст предупреждения"; + ПоказатьПредупреждение(Оповещение, Текст); + +КонецПроцедуры + +&НаКлиенте +Процедура ПредупреждениеЗавершение(ДополнительныеПараметры) Экспорт + + Сообщить("Закрыли предупреждение"); + +КонецПроцедуры; diff --git a/tests/com.e1c.v8codestyle.bsl.itests/resources/async-call-promise.bsl b/tests/com.e1c.v8codestyle.bsl.itests/resources/async-call-promise.bsl new file mode 100644 index 000000000..c708618e3 --- /dev/null +++ b/tests/com.e1c.v8codestyle.bsl.itests/resources/async-call-promise.bsl @@ -0,0 +1,9 @@ + +&НаКлиенте +Процедура Тест() + + Текст = "Текст предупреждения"; + Ждать ПредупреждениеАсинх(Текст); + Сообщить("Закрыли предупреждение"); + +КонецПроцедуры \ No newline at end of file diff --git a/tests/com.e1c.v8codestyle.bsl.itests/resources/code-after-async-call-existence.bsl b/tests/com.e1c.v8codestyle.bsl.itests/resources/code-after-async-call-existence.bsl new file mode 100644 index 000000000..a21e6bdd6 --- /dev/null +++ b/tests/com.e1c.v8codestyle.bsl.itests/resources/code-after-async-call-existence.bsl @@ -0,0 +1,9 @@ + +&НаКлиенте +Процедура Тест() + + Текст = "Текст предупреждения"; + ПоказатьПредупреждение(, Текст); + Сообщить("Закрыли предупреждение"); + +КонецПроцедуры \ No newline at end of file diff --git a/tests/com.e1c.v8codestyle.bsl.itests/src/com/e1c/v8codestyle/bsl/check/itests/CodeAfterAsyncCallCheckTest.java b/tests/com.e1c.v8codestyle.bsl.itests/src/com/e1c/v8codestyle/bsl/check/itests/CodeAfterAsyncCallCheckTest.java new file mode 100644 index 000000000..ef27f7bc1 --- /dev/null +++ b/tests/com.e1c.v8codestyle.bsl.itests/src/com/e1c/v8codestyle/bsl/check/itests/CodeAfterAsyncCallCheckTest.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright (C) 2023, 1C-Soft LLC and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * 1C-Soft LLC - initial API and implementation + *******************************************************************************/ +package com.e1c.v8codestyle.bsl.check.itests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +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.CodeAfterAsyncCallCheck; + +/** + * Tests for {@link CodeAfterAsyncCallCheck} check. + * + * @author Artem Iliukhin + */ +public class CodeAfterAsyncCallCheckTest + extends AbstractSingleModuleTestBase +{ + private static final String CHECK_ID = "code-after-async-call"; //$NON-NLS-1$ + + /** + * Instantiates a new code after async call check test. + */ + public CodeAfterAsyncCallCheckTest() + { + super(CodeAfterAsyncCallCheck.class); + } + + @Test + public void testCodeAfterExistence() throws Exception + { + updateModule(FOLDER_RESOURCE + "code-after-async-call-existence.bsl"); + + Marker marker = getFirstMarker(CHECK_ID, getModuleId(), getProject()); + assertNotNull(marker); + assertEquals("7", marker.getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_LINE_KEY)); + } + + @Test + public void testCallBackDescriptionCompliant() throws Exception + { + updateModule(FOLDER_RESOURCE + "async-call-back-descr.bsl"); + + Marker marker = getFirstMarker(CHECK_ID, getModuleId(), getProject()); + assertNull(marker); + } + + @Test + public void testPromiseCompliant() throws Exception + { + updateModule(FOLDER_RESOURCE + "async-call-promise.bsl"); + + Marker marker = getFirstMarker(CHECK_ID, getModuleId(), getProject()); + assertNull(marker); + } +} From 4b513d426c33afc8ffdfcf111cb165f248a39097 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=BB=D1=8E=D1=85=D0=B8=D0=BD=20=D0=90=D1=80=D1=82?= =?UTF-8?q?=D0=B5=D0=BC=20=D0=92=D0=B0=D1=81=D0=B8=D0=BB=D1=8C=D0=B5=D0=B2?= =?UTF-8?q?=D0=B8=D1=87?= Date: Thu, 26 Jan 2023 10:36:06 +0300 Subject: [PATCH 02/23] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B7=D0=B0=D0=BC=D0=B5=D1=87?= =?UTF-8?q?=D0=B0=D0=BD=D0=B8=D0=B9=20cr?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../markdown/ru/code-after-async-call.md | 4 +- .../bsl/check/CodeAfterAsyncCallCheck.java | 98 ++----------------- .../code-after-async-call-existence.bsl | 2 +- 3 files changed, 12 insertions(+), 92 deletions(-) diff --git a/bundles/com.e1c.v8codestyle.bsl/markdown/ru/code-after-async-call.md b/bundles/com.e1c.v8codestyle.bsl/markdown/ru/code-after-async-call.md index d4040b3cb..5b7f384b9 100644 --- a/bundles/com.e1c.v8codestyle.bsl/markdown/ru/code-after-async-call.md +++ b/bundles/com.e1c.v8codestyle.bsl/markdown/ru/code-after-async-call.md @@ -3,11 +3,11 @@ При асинхронном подходе вызов метода выполняется как обычно, но управление возвращается вызывающему коду до того, как асинхронный метод завершит свою работу. После этого вызывающий код продолжает свое выполнение. Особенность асинхронного выполнения: исполнение на стороне вызывающего кода продолжится до того, -как полностью закончилось исполнение вызванного метода +как полностью закончилось исполнение вызванного метода. Для правильного решения нужно вынести весь код, который должен быть выполнен после выполнения асинхронного действия, в экспортный метод и указать его имя в обработке оповещения, которая будет вызвана после завершения асинхронного действия. -Или использовать асинхронность через обещания, например, Ждать ПредупреждениеАсинх(Текст); +Или использовать асинхронность через обещания, например, Ждать ПредупреждениеАсинх(Текст). ## Неправильно diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java index 3d28c0559..08113c2a0 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java @@ -14,53 +14,40 @@ import static com._1c.g5.v8.dt.bsl.model.BslPackage.Literals.INVOCATION; -import java.util.Iterator; -import java.util.List; - import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.emf.ecore.EObject; -import org.eclipse.xtext.EcoreUtil2; import org.eclipse.xtext.naming.IQualifiedNameConverter; import com._1c.g5.v8.dt.bsl.common.IBslPreferences; -import com._1c.g5.v8.dt.bsl.model.BslPackage; -import com._1c.g5.v8.dt.bsl.model.Conditional; import com._1c.g5.v8.dt.bsl.model.EmptyStatement; import com._1c.g5.v8.dt.bsl.model.FeatureAccess; -import com._1c.g5.v8.dt.bsl.model.IfStatement; 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.PreprocessorItemStatements; import com._1c.g5.v8.dt.bsl.model.ReturnStatement; import com._1c.g5.v8.dt.bsl.model.Statement; import com._1c.g5.v8.dt.bsl.model.StaticFeatureAccess; -import com._1c.g5.v8.dt.bsl.model.TryExceptStatement; import com._1c.g5.v8.dt.core.platform.IResourceLookup; import com.e1c.g5.v8.dt.check.CheckComplexity; import com.e1c.g5.v8.dt.check.ICheckParameters; import com.e1c.g5.v8.dt.check.settings.IssueSeverity; import com.e1c.g5.v8.dt.check.settings.IssueType; -import com.e1c.v8codestyle.bsl.strict.check.AbstractTypeCheck; import com.e1c.v8codestyle.check.CommonSenseCheckExtension; import com.e1c.v8codestyle.internal.bsl.BslPlugin; -import com.google.common.collect.Lists; import com.google.inject.Inject; /** - * Checks that the asynchronous method is not followed by lines of code, - * since in this case the specified lines of code are executed immediately, + * Checks that the asynchronous method is not followed by lines of code, + * since in this case the specified lines of code are executed immediately, * without waiting for the asynchronous method to execute. - * + * * @author Artem Iliukhin */ public final class CodeAfterAsyncCallCheck - extends AbstractTypeCheck + extends AbstractTransactionCheck { private static final String CHECK_ID = "code-after-async-call"; //$NON-NLS-1$ // @formatter:off - private static final String[] ASYNCHRONOUS_METHODS = { + private static final String[] ASYNCHRONOUS_METHODS = { "ShowMessageBox", "ПоказатьПредупреждение", //$NON-NLS-1$ //$NON-NLS-2$ "ShowInputDate", "ПоказатьВводДаты", //$NON-NLS-1$ //$NON-NLS-2$ "ShowInputValue", "ПоказатьВводЗначения", //$NON-NLS-1$ //$NON-NLS-2$ @@ -92,7 +79,7 @@ public final class CodeAfterAsyncCallCheck public CodeAfterAsyncCallCheck(IResourceLookup resourceLookup, IBslPreferences bslPreferences, IQualifiedNameConverter qualifiedNameConverter) { - super(resourceLookup, bslPreferences, qualifiedNameConverter); + super(); } @Override @@ -109,6 +96,7 @@ protected void configureCheck(CheckConfigurer builder) .complexity(CheckComplexity.NORMAL) .severity(IssueSeverity.MAJOR) .issueType(IssueType.WARNING) + .disable() .extension(new CommonSenseCheckExtension(getCheckId(), BslPlugin.PLUGIN_ID)) .module() .checkedObjectType(INVOCATION); @@ -127,10 +115,10 @@ protected void check(Object object, ResultAcceptor resultAceptor, ICheckParamete return; } - String nameFeature = featureAccess.getName(); + String featureName = featureAccess.getName(); for (int i = 0; i < ASYNCHRONOUS_METHODS.length; i++) { - if (ASYNCHRONOUS_METHODS[i].equalsIgnoreCase(nameFeature)) + if (ASYNCHRONOUS_METHODS[i].equalsIgnoreCase(featureName)) { Statement statement = getStatementFromInvoc(inv); if (statement != null) @@ -146,72 +134,4 @@ protected void check(Object object, ResultAcceptor resultAceptor, ICheckParamete } } } - - private Statement getStatementFromInvoc(Invocation invocation) - { - EObject container = invocation.eContainer(); - while (!(container instanceof Statement)) - { - container = container.eContainer(); - } - return container instanceof Statement ? (Statement)container : null; - } - - private Statement getNextStatement(Statement statement) - { - Iterator it = EcoreUtil2.getAllContainers(statement).iterator(); - while (it.hasNext()) - { - EObject container = it.next(); - List st = null; - if (container instanceof LoopStatement) - { - st = ((LoopStatement)container).getStatements(); - } - else if (container instanceof Conditional) - { - st = ((Conditional)container).getStatements(); - } - else if (container instanceof IfStatement) - { - st = ((IfStatement)container).getElseStatements(); - } - else if (container instanceof TryExceptStatement) - { - st = getStatementsFromContainer((TryExceptStatement)container); - } - else if (container instanceof PreprocessorItemStatements) - { - st = ((PreprocessorItemStatements)container).getStatements(); - } - else - { - st = getStatementsFromContainer(container); - } - if (st != null) - { - int index = st.indexOf(statement); - if (index != -1 && index + 1 < st.size()) - { - return st.get(index + 1); - } - } - } - return null; - } - - private List getStatementsFromContainer(TryExceptStatement container) - { - List res = Lists.newArrayList(); - res.addAll(container.getTryStatements()); - res.addAll(container.getExceptStatements()); - return res; - } - - @SuppressWarnings("unchecked") - private List getStatementsFromContainer(EObject container) - { - Object obj = container.eGet(BslPackage.Literals.BLOCK__STATEMENTS); - return obj instanceof List ? (List)obj : null; - } } diff --git a/tests/com.e1c.v8codestyle.bsl.itests/resources/code-after-async-call-existence.bsl b/tests/com.e1c.v8codestyle.bsl.itests/resources/code-after-async-call-existence.bsl index a21e6bdd6..b9d95d628 100644 --- a/tests/com.e1c.v8codestyle.bsl.itests/resources/code-after-async-call-existence.bsl +++ b/tests/com.e1c.v8codestyle.bsl.itests/resources/code-after-async-call-existence.bsl @@ -2,7 +2,7 @@ &НаКлиенте Процедура Тест() - Текст = "Текст предупреждения"; + Текст = "Текст предупреждения"; ПоказатьПредупреждение(, Текст); Сообщить("Закрыли предупреждение"); From 80e93f735b9f225535bae0b39ddeb9fdde8c353e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=BB=D1=8E=D1=85=D0=B8=D0=BD=20=D0=90=D1=80=D1=82?= =?UTF-8?q?=D0=B5=D0=BC=20=D0=92=D0=B0=D1=81=D0=B8=D0=BB=D1=8C=D0=B5=D0=B2?= =?UTF-8?q?=D0=B8=D1=87?= Date: Tue, 7 Mar 2023 09:34:33 +0300 Subject: [PATCH 03/23] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BF=D0=BE=20=D0=B7=D0=B0?= =?UTF-8?q?=D0=BC=D0=B5=D1=87=D0=B0=D0=BD=D0=B8=D1=8F=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bsl/IAsyncInvocationProvider.java | 25 +++ .../bsl/check/CodeAfterAsyncCallCheck.java | 153 +++++++++---- .../internal/bsl/AsyncInvocationProvider.java | 205 ++++++++++++++++++ .../v8codestyle/internal/bsl/BslPlugin.java | 2 + .../internal/bsl/ServiceModule.java | 2 + 5 files changed, 340 insertions(+), 47 deletions(-) create mode 100644 bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/IAsyncInvocationProvider.java create mode 100644 bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/AsyncInvocationProvider.java diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/IAsyncInvocationProvider.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/IAsyncInvocationProvider.java new file mode 100644 index 000000000..1f75185f9 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/IAsyncInvocationProvider.java @@ -0,0 +1,25 @@ +/** + * Copyright (C) 2023, 1C + */ +package com.e1c.v8codestyle.bsl; + +import java.util.Collection; +import java.util.Map; + +import com._1c.g5.v8.dt.platform.version.Version; + +/** + * Platform context asynchronic methods provider + * + * @author Artem Iliukhin + */ +public interface IAsyncInvocationProvider +{ + + // Global context methods + Collection getAsyncInvocationNames(Version version); + + // Methods with a list of types in which they are used + Map> getAsyncTypeMethodNames(Version version); + +} diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java index 08113c2a0..4c4e0bd8a 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java @@ -14,23 +14,42 @@ import static com._1c.g5.v8.dt.bsl.model.BslPackage.Literals.INVOCATION; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.xtext.EcoreUtil2; import org.eclipse.xtext.naming.IQualifiedNameConverter; import com._1c.g5.v8.dt.bsl.common.IBslPreferences; +import com._1c.g5.v8.dt.bsl.model.BslPackage; +import com._1c.g5.v8.dt.bsl.model.Conditional; import com._1c.g5.v8.dt.bsl.model.EmptyStatement; import com._1c.g5.v8.dt.bsl.model.FeatureAccess; +import com._1c.g5.v8.dt.bsl.model.IfStatement; 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.PreprocessorItemStatements; import com._1c.g5.v8.dt.bsl.model.ReturnStatement; import com._1c.g5.v8.dt.bsl.model.Statement; import com._1c.g5.v8.dt.bsl.model.StaticFeatureAccess; +import com._1c.g5.v8.dt.bsl.model.TryExceptStatement; import com._1c.g5.v8.dt.core.platform.IResourceLookup; +import com._1c.g5.v8.dt.platform.version.IRuntimeVersionSupport; +import com._1c.g5.v8.dt.platform.version.Version; +import com._1c.g5.wiring.ServiceAccess; 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.e1c.v8codestyle.bsl.IAsyncInvocationProvider; import com.e1c.v8codestyle.check.CommonSenseCheckExtension; import com.e1c.v8codestyle.internal.bsl.BslPlugin; +import com.google.common.collect.Lists; import com.google.inject.Inject; /** @@ -41,45 +60,20 @@ * @author Artem Iliukhin */ public final class CodeAfterAsyncCallCheck - extends AbstractTransactionCheck + extends BasicCheck { private static final String CHECK_ID = "code-after-async-call"; //$NON-NLS-1$ - - // @formatter:off - private static final String[] ASYNCHRONOUS_METHODS = { - "ShowMessageBox", "ПоказатьПредупреждение", //$NON-NLS-1$ //$NON-NLS-2$ - "ShowInputDate", "ПоказатьВводДаты", //$NON-NLS-1$ //$NON-NLS-2$ - "ShowInputValue", "ПоказатьВводЗначения", //$NON-NLS-1$ //$NON-NLS-2$ - "ShowInputString", "ПоказатьВводСтроки", //$NON-NLS-1$ //$NON-NLS-2$ - "ShowInputNumber", "ПоказатьВводЧисла", //$NON-NLS-1$ //$NON-NLS-2$ - "ShowQueryBox", "ПоказатьВопрос", //$NON-NLS-1$ //$NON-NLS-2$ - "BeginRequestingUserPermission", "НачатьЗапросРазрешенияПользователя", //$NON-NLS-1$ //$NON-NLS-2$ - "BeginRunningApplication", "НачатьЗапускПриложения", //$NON-NLS-1$ //$NON-NLS-2$ - "BeginGettingTempFilesDir", "НачатьПолучениеКаталогаВременныхФайлов", //$NON-NLS-1$ //$NON-NLS-2$ - "BeginGettingDocumentsDir", "НачатьПолучениеКаталогаДокументов", //$NON-NLS-1$ //$NON-NLS-2$ - "BeginCopyingFile", "НачатьКопированиеФайла", //$NON-NLS-1$ //$NON-NLS-2$ - "BeginFindingFiles", "НачатьПоискФайлов", //$NON-NLS-1$ //$NON-NLS-2$ - "ShowValue", "ПоказатьЗначение", //$NON-NLS-1$ //$NON-NLS-2$ - "OpenForm", "ОткрытьФорму", //$NON-NLS-1$ //$NON-NLS-2$ - "BeginMovingFile", "НачатьПеремещениеФайла", //$NON-NLS-1$ //$NON-NLS-2$ - "BeginAttachingCryptoExtension", "НачатьПодключениеРасширенияРаботыСКриптографией", //$NON-NLS-1$ //$NON-NLS-2$ - "BeginAttachingFileSystemExtension", "НачатьПодключениеРасширенияРаботыСФайлами", //$NON-NLS-1$ //$NON-NLS-2$ - "BeginGetFilesFromServer", "НачатьПолучениеФайловССервера", //$NON-NLS-1$ //$NON-NLS-2$ - "BeginPutFileToServer", "НачатьПомещениеФайлаНаСервер", //$NON-NLS-1$ //$NON-NLS-2$ - "BeginPutFilesToServer", "НачатьПомещениеФайловНаСервер", //$NON-NLS-1$ //$NON-NLS-2$ - "BeginGettingUserDataWorkDir", "НачатьПолучениеРабочегоКаталогаДанныхПользователя", //$NON-NLS-1$ //$NON-NLS-2$ - "BeginCreatingDirectory", "НачатьСозданиеКаталога", //$NON-NLS-1$ //$NON-NLS-2$ - "BeginInstallAddIn", "НачатьУстановкуВнешнейКомпоненты", //$NON-NLS-1$ //$NON-NLS-2$ - "BeginInstallCryptoExtension", "НачатьУстановкуРасширенияРаботыСКриптографией", //$NON-NLS-1$ //$NON-NLS-2$ - "BeginInstallFileSystemExtension", "НачатьУстановкуРасширенияРаботыСФайлами"}; //$NON-NLS-1$ //$NON-NLS-2$ - // @formatter:on + private final IResourceLookup resourceLookup; + private final IAsyncInvocationProvider asyncInvocationProvider; @Inject public CodeAfterAsyncCallCheck(IResourceLookup resourceLookup, IBslPreferences bslPreferences, - IQualifiedNameConverter qualifiedNameConverter) + IQualifiedNameConverter qualifiedNameConverter, IAsyncInvocationProvider asyncInvocationProvider) { super(); + this.resourceLookup = resourceLookup; + this.asyncInvocationProvider = asyncInvocationProvider; } @Override @@ -96,7 +90,6 @@ protected void configureCheck(CheckConfigurer builder) .complexity(CheckComplexity.NORMAL) .severity(IssueSeverity.MAJOR) .issueType(IssueType.WARNING) - .disable() .extension(new CommonSenseCheckExtension(getCheckId(), BslPlugin.PLUGIN_ID)) .module() .checkedObjectType(INVOCATION); @@ -106,32 +99,98 @@ protected void configureCheck(CheckConfigurer builder) protected void check(Object object, ResultAcceptor resultAceptor, ICheckParameters parameters, IProgressMonitor monitor) { + + IProject project = resourceLookup.getProject((EObject)object); + + IRuntimeVersionSupport runtimeVersionSupport = ServiceAccess.get(IRuntimeVersionSupport.class); + Version version = runtimeVersionSupport.getRuntimeVersion(project); + Invocation inv = (Invocation)object; FeatureAccess featureAccess = inv.getMethodAccess(); if (featureAccess instanceof StaticFeatureAccess) { - if (monitor.isCanceled()) + Collection asyncMethodsNames = asyncInvocationProvider.getAsyncInvocationNames(version); + if (asyncMethodsNames.contains(featureAccess.getName())) { - return; + Statement statement = getStatementFromInvoc(inv); + if (statement != null) + { + statement = getNextStatement(statement); + if (statement != null && !(statement instanceof ReturnStatement) + && !(statement instanceof EmptyStatement)) + { + resultAceptor.addIssue(Messages.CodeAfterAsyncCallCheck_Issue, statement); + } + } } + } + } - String featureName = featureAccess.getName(); - for (int i = 0; i < ASYNCHRONOUS_METHODS.length; i++) + private final Statement getStatementFromInvoc(Invocation invocation) + { + EObject container = invocation.eContainer(); + while (!(container instanceof Statement)) + { + container = container.eContainer(); + } + return container instanceof Statement ? (Statement)container : null; + } + + private final Statement getNextStatement(Statement statement) + { + Iterator it = EcoreUtil2.getAllContainers(statement).iterator(); + while (it.hasNext()) + { + EObject container = it.next(); + List st = null; + if (container instanceof LoopStatement) + { + st = ((LoopStatement)container).getStatements(); + } + else if (container instanceof Conditional) + { + st = ((Conditional)container).getStatements(); + } + else if (container instanceof IfStatement) + { + st = ((IfStatement)container).getElseStatements(); + } + else if (container instanceof TryExceptStatement) { - if (ASYNCHRONOUS_METHODS[i].equalsIgnoreCase(featureName)) + st = getStatementsFromContainer((TryExceptStatement)container); + } + else if (container instanceof PreprocessorItemStatements) + { + st = ((PreprocessorItemStatements)container).getStatements(); + } + else + { + st = getStatementsFromContainer(container); + } + if (st != null) + { + int index = st.indexOf(statement); + if (index != -1 && index + 1 < st.size()) { - Statement statement = getStatementFromInvoc(inv); - if (statement != null) - { - statement = getNextStatement(statement); - if (statement != null && !(statement instanceof ReturnStatement) - && !(statement instanceof EmptyStatement)) - { - resultAceptor.addIssue(Messages.CodeAfterAsyncCallCheck_Issue, statement); - } - } + return st.get(index + 1); } } } + return null; + } + + private List getStatementsFromContainer(TryExceptStatement container) + { + List res = Lists.newArrayList(); + res.addAll(container.getTryStatements()); + res.addAll(container.getExceptStatements()); + return res; + } + + @SuppressWarnings("unchecked") + private List getStatementsFromContainer(EObject container) + { + Object obj = container.eGet(BslPackage.Literals.BLOCK__STATEMENTS); + return obj instanceof List ? (List)obj : null; } } diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/AsyncInvocationProvider.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/AsyncInvocationProvider.java new file mode 100644 index 000000000..d6c000dfd --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/AsyncInvocationProvider.java @@ -0,0 +1,205 @@ +/** + * Copyright (C) 2023, 1C + */ +package com.e1c.v8codestyle.internal.bsl; + +import java.util.Collection; +import java.util.Map; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.concurrent.ConcurrentHashMap; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.xtext.resource.IEObjectDescription; + +import com._1c.g5.v8.dt.core.platform.IConfigurationProvider; +import com._1c.g5.v8.dt.core.platform.IV8Project; +import com._1c.g5.v8.dt.core.platform.IV8ProjectManager; +import com._1c.g5.v8.dt.mcore.ContextDef; +import com._1c.g5.v8.dt.mcore.McorePackage; +import com._1c.g5.v8.dt.mcore.Method; +import com._1c.g5.v8.dt.mcore.ParamSet; +import com._1c.g5.v8.dt.mcore.Parameter; +import com._1c.g5.v8.dt.mcore.Type; +import com._1c.g5.v8.dt.mcore.TypeItem; +import com._1c.g5.v8.dt.mcore.TypeSet; +import com._1c.g5.v8.dt.mcore.util.McoreUtil; +import com._1c.g5.v8.dt.metadata.mdclass.Configuration; +import com._1c.g5.v8.dt.platform.IEObjectProvider; +import com._1c.g5.v8.dt.platform.IEObjectTypeNames; +import com._1c.g5.v8.dt.platform.version.Version; +import com.e1c.v8codestyle.bsl.IAsyncInvocationProvider; +import com.google.inject.Inject; + +/** + * Implementing service to provide asynchronous methods + * + * @author Artem Iliukhin + */ +public class AsyncInvocationProvider + implements IAsyncInvocationProvider +{ + + private final Map> cashNames; + private final Map>> cashTypesMethodNames; + private final IConfigurationProvider configurationProvider; + private final IV8ProjectManager v8ProjectManager; + + @Inject + public AsyncInvocationProvider(IConfigurationProvider configurationProvider, IV8ProjectManager v8ProjectManager) + { + super(); + this.configurationProvider = configurationProvider; + this.v8ProjectManager = v8ProjectManager; + this.cashNames = new ConcurrentHashMap<>(); + this.cashTypesMethodNames = new ConcurrentHashMap<>(); + } + + @Override + public Collection getAsyncInvocationNames(Version version) + { + if (cashNames.get(version) != null) + { + return cashNames.get(version); + } + + Collection asyncMethodsNames = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); + cashNames.put(version, asyncMethodsNames); + + Collection projects = v8ProjectManager.getProjects(); + for (IV8Project project : projects) + { + Configuration context = configurationProvider.getConfiguration(project.getProject()); + IEObjectProvider provider = IEObjectProvider.Registry.INSTANCE.get(McorePackage.Literals.METHOD, version); + + provider.getProxy(IEObjectTypeNames.SPREADSHEET_DOCUMENT); + + Iterable items = provider.getEObjectDescriptions(null); + for (IEObjectDescription item : items) + { + EObject object = EcoreUtil.resolve(item.getEObjectOrProxy(), context); + if (object instanceof Method) + { + collectMethods(asyncMethodsNames, object); + } + } + } + + return asyncMethodsNames; + } + + @Override + public Map> getAsyncTypeMethodNames(Version version) + { + if (cashTypesMethodNames.get(version) != null) + { + return cashTypesMethodNames.get(version); + } + + Map> asyncMethodsNames = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + cashTypesMethodNames.put(version, asyncMethodsNames); + + Collection projects = v8ProjectManager.getProjects(); + for (IV8Project project : projects) + { + Configuration context = configurationProvider.getConfiguration(project.getProject()); + + IEObjectProvider provider = + IEObjectProvider.Registry.INSTANCE.get(McorePackage.Literals.TYPE_ITEM, version); + Iterable items = provider.getEObjectDescriptions(null); + + for (IEObjectDescription item : items) + { + EObject object = EcoreUtil.resolve(item.getEObjectOrProxy(), context); + if (object instanceof Type) + { + Type type = (Type)object; + process(asyncMethodsNames, type); + } + else if (object instanceof TypeSet) + { + TypeSet typeSet = (TypeSet)object; + for (Type type : typeSet.getTypes()) + { + process(asyncMethodsNames, type); + } + } + } + } + + return asyncMethodsNames; + } + + private void process(Map> asyncMethodsNames, Type type) + { + if (type == null || type.eIsProxy()) + return; + + ContextDef contextDef = type.getContextDef(); + if (contextDef == null) + return; + + for (Method method : contextDef.allMethods()) + { + if (method.getName().endsWith("Async")) //$NON-NLS-1$ + { + if (asyncMethodsNames.get(method.getName()) != null) + { + asyncMethodsNames.get(method.getName()).add(type.getName()); + asyncMethodsNames.get(method.getNameRu()).add(type.getNameRu()); + } + asyncMethodsNames.putIfAbsent(method.getName(), new TreeSet<>()); + asyncMethodsNames.putIfAbsent(method.getNameRu(), new TreeSet<>()); + } + } + } + + private void collectMethods(Collection asyncMethodsNames, EObject object) + { + Method method = (Method)object; + if ("RunCallback".equals(method.getName())) //$NON-NLS-1$ + { + return; + } + + if (method.getName().endsWith("Async")) //$NON-NLS-1$ + { + asyncMethodsNames.add(method.getName()); + asyncMethodsNames.add(method.getNameRu()); + } + else + { + checkParamAndCollectMethods(asyncMethodsNames, method); + } + } + + private void checkParamAndCollectMethods(Collection asyncMethodsNames, Method method) + { + for (ParamSet paramSet : method.getParamSet()) + { + for (Parameter param : paramSet.getParams()) + { + if (isCallbackDescription(param)) + { + asyncMethodsNames.add(method.getName()); + asyncMethodsNames.add(method.getNameRu()); + break; + } + } + } + } + + private boolean isCallbackDescription(Parameter param) + { + for (TypeItem type : param.getType()) + { + if ("CallbackDescription".equals(McoreUtil.getTypeName(type))) //$NON-NLS-1$ + { + return true; + } + } + return false; + } + +} diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/BslPlugin.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/BslPlugin.java index 74df5ee6b..ad1f2ad26 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/BslPlugin.java +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/BslPlugin.java @@ -20,6 +20,7 @@ import com._1c.g5.v8.dt.bsl.model.BslPackage; import com._1c.g5.wiring.InjectorAwareServiceRegistrator; import com._1c.g5.wiring.ServiceInitialization; +import com.e1c.v8codestyle.bsl.IAsyncInvocationProvider; import com.e1c.v8codestyle.bsl.IModuleStructureProvider; import com.google.inject.Guice; import com.google.inject.Injector; @@ -131,6 +132,7 @@ public void start(BundleContext bundleContext) throws Exception ServiceInitialization.schedule(() -> { // register services from injector registrator.service(IModuleStructureProvider.class).registerInjected(); + registrator.service(IAsyncInvocationProvider.class).registerInjected(); registrator.managedService(MultiCheckFixRegistrator.class).activateBeforeRegistration().registerInjected(); }); } diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/ServiceModule.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/ServiceModule.java index fa7b056f1..eabb0233f 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/ServiceModule.java +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/ServiceModule.java @@ -12,6 +12,7 @@ *******************************************************************************/ package com.e1c.v8codestyle.internal.bsl; +import com.e1c.v8codestyle.bsl.IAsyncInvocationProvider; import com.e1c.v8codestyle.bsl.IModuleStructureProvider; import com.google.inject.AbstractModule; import com.google.inject.Singleton; @@ -29,6 +30,7 @@ public class ServiceModule protected void configure() { bind(IModuleStructureProvider.class).to(ModuleStructureProvider.class).in(Singleton.class); + bind(IAsyncInvocationProvider.class).to(AsyncInvocationProvider.class).in(Singleton.class); } } From 00ccad745cb1ceb7a9eed3ec91bd7ae07368be14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=BB=D1=8E=D1=85=D0=B8=D0=BD=20=D0=90=D1=80=D1=82?= =?UTF-8?q?=D0=B5=D0=BC=20=D0=92=D0=B0=D1=81=D0=B8=D0=BB=D1=8C=D0=B5=D0=B2?= =?UTF-8?q?=D0=B8=D1=87?= Date: Tue, 7 Mar 2023 09:49:32 +0300 Subject: [PATCH 04/23] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BE?= =?UTF-8?q?=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bsl/IAsyncInvocationProvider.java | 15 ++++++++++++--- .../bsl/check/CodeAfterAsyncCallCheck.java | 4 ++-- .../internal/bsl/AsyncInvocationProvider.java | 19 ++++++++++++++++--- 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/IAsyncInvocationProvider.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/IAsyncInvocationProvider.java index 1f75185f9..e6da6269b 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/IAsyncInvocationProvider.java +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/IAsyncInvocationProvider.java @@ -1,6 +1,15 @@ -/** - * Copyright (C) 2023, 1C - */ +/******************************************************************************* + * Copyright (C) 2023, 1C-Soft LLC and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * 1C-Soft LLC - initial API and implementation + *******************************************************************************/ package com.e1c.v8codestyle.bsl; import java.util.Collection; diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java index 4c4e0bd8a..788481e7b 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java @@ -126,7 +126,7 @@ protected void check(Object object, ResultAcceptor resultAceptor, ICheckParamete } } - private final Statement getStatementFromInvoc(Invocation invocation) + private Statement getStatementFromInvoc(Invocation invocation) { EObject container = invocation.eContainer(); while (!(container instanceof Statement)) @@ -136,7 +136,7 @@ private final Statement getStatementFromInvoc(Invocation invocation) return container instanceof Statement ? (Statement)container : null; } - private final Statement getNextStatement(Statement statement) + private Statement getNextStatement(Statement statement) { Iterator it = EcoreUtil2.getAllContainers(statement).iterator(); while (it.hasNext()) diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/AsyncInvocationProvider.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/AsyncInvocationProvider.java index d6c000dfd..b7c8b9d51 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/AsyncInvocationProvider.java +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/AsyncInvocationProvider.java @@ -1,6 +1,15 @@ -/** - * Copyright (C) 2023, 1C - */ +/******************************************************************************* + * Copyright (C) 2023, 1C-Soft LLC and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * 1C-Soft LLC - initial API and implementation + *******************************************************************************/ package com.e1c.v8codestyle.internal.bsl; import java.util.Collection; @@ -134,11 +143,15 @@ else if (object instanceof TypeSet) private void process(Map> asyncMethodsNames, Type type) { if (type == null || type.eIsProxy()) + { return; + } ContextDef contextDef = type.getContextDef(); if (contextDef == null) + { return; + } for (Method method : contextDef.allMethods()) { From 5b105633fe3d267b3df3fd111552788537413cce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=BB=D1=8E=D1=85=D0=B8=D0=BD=20=D0=90=D1=80=D1=82?= =?UTF-8?q?=D0=B5=D0=BC=20=D0=92=D0=B0=D1=81=D0=B8=D0=BB=D1=8C=D0=B5=D0=B2?= =?UTF-8?q?=D0=B8=D1=87?= Date: Thu, 9 Mar 2023 08:37:12 +0300 Subject: [PATCH 05/23] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BF=D0=BE=D1=82=D0=BE=D0=BA?= =?UTF-8?q?=D0=BE=D0=B1=D0=B5=D0=B7=D0=BE=D0=BF=D0=B0=D1=81=D0=BD=D0=BE?= =?UTF-8?q?=D1=81=D1=82=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../internal/bsl/AsyncInvocationProvider.java | 47 ++++++++++++++----- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/AsyncInvocationProvider.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/AsyncInvocationProvider.java index b7c8b9d51..15c1830f0 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/AsyncInvocationProvider.java +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/AsyncInvocationProvider.java @@ -68,13 +68,40 @@ public AsyncInvocationProvider(IConfigurationProvider configurationProvider, IV8 @Override public Collection getAsyncInvocationNames(Version version) { - if (cashNames.get(version) != null) + if (cashNames.get(version) == null) { - return cashNames.get(version); + synchronized (this) + { + if (cashNames.get(version) != null) + { + return cashNames.get(version); + } + collect(version); + } } + return cashNames.get(version); + } + @Override + public Map> getAsyncTypeMethodNames(Version version) + { + if (cashTypesMethodNames.get(version) == null) + { + synchronized (this) + { + if (cashTypesMethodNames.get(version) != null) + { + return cashTypesMethodNames.get(version); + } + process(version); + } + } + return cashTypesMethodNames.get(version); + } + + private void collect(Version version) + { Collection asyncMethodsNames = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); - cashNames.put(version, asyncMethodsNames); Collection projects = v8ProjectManager.getProjects(); for (IV8Project project : projects) @@ -94,20 +121,12 @@ public Collection getAsyncInvocationNames(Version version) } } } - - return asyncMethodsNames; + cashNames.put(version, asyncMethodsNames); } - @Override - public Map> getAsyncTypeMethodNames(Version version) + private Map> process(Version version) { - if (cashTypesMethodNames.get(version) != null) - { - return cashTypesMethodNames.get(version); - } - Map> asyncMethodsNames = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); - cashTypesMethodNames.put(version, asyncMethodsNames); Collection projects = v8ProjectManager.getProjects(); for (IV8Project project : projects) @@ -137,6 +156,8 @@ else if (object instanceof TypeSet) } } + cashTypesMethodNames.put(version, asyncMethodsNames); + return asyncMethodsNames; } From 7b2ef3ff177a2e351d9d233b3472ccd8d37ece3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=BB=D1=8E=D1=85=D0=B8=D0=BD=20=D0=90=D1=80=D1=82?= =?UTF-8?q?=D0=B5=D0=BC=20=D0=92=D0=B0=D1=81=D0=B8=D0=BB=D1=8C=D0=B5=D0=B2?= =?UTF-8?q?=D0=B8=D1=87?= Date: Thu, 9 Mar 2023 10:01:07 +0300 Subject: [PATCH 06/23] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B8=D0=BC=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=20=D1=82=D0=B8=D0=BF=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../v8codestyle/internal/bsl/AsyncInvocationProvider.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/AsyncInvocationProvider.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/AsyncInvocationProvider.java index 15c1830f0..d6ff9e05c 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/AsyncInvocationProvider.java +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/AsyncInvocationProvider.java @@ -36,7 +36,6 @@ import com._1c.g5.v8.dt.mcore.util.McoreUtil; import com._1c.g5.v8.dt.metadata.mdclass.Configuration; import com._1c.g5.v8.dt.platform.IEObjectProvider; -import com._1c.g5.v8.dt.platform.IEObjectTypeNames; import com._1c.g5.v8.dt.platform.version.Version; import com.e1c.v8codestyle.bsl.IAsyncInvocationProvider; import com.google.inject.Inject; @@ -109,8 +108,6 @@ private void collect(Version version) Configuration context = configurationProvider.getConfiguration(project.getProject()); IEObjectProvider provider = IEObjectProvider.Registry.INSTANCE.get(McorePackage.Literals.METHOD, version); - provider.getProxy(IEObjectTypeNames.SPREADSHEET_DOCUMENT); - Iterable items = provider.getEObjectDescriptions(null); for (IEObjectDescription item : items) { @@ -228,7 +225,7 @@ private boolean isCallbackDescription(Parameter param) { for (TypeItem type : param.getType()) { - if ("CallbackDescription".equals(McoreUtil.getTypeName(type))) //$NON-NLS-1$ + if ("NotifyDescription".equals(McoreUtil.getTypeName(type))) //$NON-NLS-1$ { return true; } From b0df18b1b411a60f6b4083d48884c8ace9d9197a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=BB=D1=8E=D1=85=D0=B8=D0=BD=20=D0=90=D1=80=D1=82?= =?UTF-8?q?=D0=B5=D0=BC=20=D0=92=D0=B0=D1=81=D0=B8=D0=BB=D1=8C=D0=B5=D0=B2?= =?UTF-8?q?=D0=B8=D1=87?= Date: Fri, 10 Mar 2023 08:10:06 +0300 Subject: [PATCH 07/23] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=83=D1=87=D1=82=D0=B5=D0=BD?= =?UTF-8?q?=20=D0=BE=D0=BF=D0=B5=D1=80=D0=B0=D1=82=D0=BE=D1=80=20=D0=96?= =?UTF-8?q?=D0=B4=D0=B0=D1=82=D1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bsl/check/CodeAfterAsyncCallCheck.java | 93 ++++++++++++++----- .../internal/bsl/AsyncInvocationProvider.java | 3 +- 2 files changed, 70 insertions(+), 26 deletions(-) diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java index 788481e7b..3235d57b1 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java @@ -28,12 +28,14 @@ import com._1c.g5.v8.dt.bsl.model.BslPackage; import com._1c.g5.v8.dt.bsl.model.Conditional; import com._1c.g5.v8.dt.bsl.model.EmptyStatement; +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.IfStatement; 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.PreprocessorItemStatements; import com._1c.g5.v8.dt.bsl.model.ReturnStatement; +import com._1c.g5.v8.dt.bsl.model.SimpleStatement; import com._1c.g5.v8.dt.bsl.model.Statement; import com._1c.g5.v8.dt.bsl.model.StaticFeatureAccess; import com._1c.g5.v8.dt.bsl.model.TryExceptStatement; @@ -63,6 +65,8 @@ public final class CodeAfterAsyncCallCheck extends BasicCheck { + private static final String STATEMENT_NAME_RU = "Ждать"; //$NON-NLS-1$ + private static final String STATEMENT_NAME = "Await"; //$NON-NLS-1$ private static final String CHECK_ID = "code-after-async-call"; //$NON-NLS-1$ private final IResourceLookup resourceLookup; private final IAsyncInvocationProvider asyncInvocationProvider; @@ -113,7 +117,7 @@ protected void check(Object object, ResultAcceptor resultAceptor, ICheckParamete if (asyncMethodsNames.contains(featureAccess.getName())) { Statement statement = getStatementFromInvoc(inv); - if (statement != null) + if (statement != null && isPreviousStatementAwait(statement)) { statement = getNextStatement(statement); if (statement != null && !(statement instanceof ReturnStatement) @@ -136,37 +140,46 @@ private Statement getStatementFromInvoc(Invocation invocation) return container instanceof Statement ? (Statement)container : null; } - private Statement getNextStatement(Statement statement) + private boolean isPreviousStatementAwait(Statement statement) { Iterator it = EcoreUtil2.getAllContainers(statement).iterator(); while (it.hasNext()) { EObject container = it.next(); - List st = null; - if (container instanceof LoopStatement) - { - st = ((LoopStatement)container).getStatements(); - } - else if (container instanceof Conditional) - { - st = ((Conditional)container).getStatements(); - } - else if (container instanceof IfStatement) - { - st = ((IfStatement)container).getElseStatements(); - } - else if (container instanceof TryExceptStatement) - { - st = getStatementsFromContainer((TryExceptStatement)container); - } - else if (container instanceof PreprocessorItemStatements) - { - st = ((PreprocessorItemStatements)container).getStatements(); - } - else + List st = getContainer(container); + if (st != null) { - st = getStatementsFromContainer(container); + int index = st.indexOf(statement); + if (index != -1 && index - 1 < st.size()) + { + Statement awaitStatement = st.get(index - 1); + if (awaitStatement instanceof SimpleStatement) + { + Expression left = ((SimpleStatement)awaitStatement).getLeft(); + if (left instanceof StaticFeatureAccess) + { + String name = ((StaticFeatureAccess)left).getName(); + if (STATEMENT_NAME.equalsIgnoreCase(name) || STATEMENT_NAME_RU.equalsIgnoreCase(name)) + { + return true; + } + } + } + + return awaitStatement != null; + } } + } + return false; + } + + private Statement getNextStatement(Statement statement) + { + Iterator it = EcoreUtil2.getAllContainers(statement).iterator(); + while (it.hasNext()) + { + EObject container = it.next(); + List st = getContainer(container); if (st != null) { int index = st.indexOf(statement); @@ -179,6 +192,36 @@ else if (container instanceof PreprocessorItemStatements) return null; } + private List getContainer(EObject container) + { + List st = null; + if (container instanceof LoopStatement) + { + st = ((LoopStatement)container).getStatements(); + } + else if (container instanceof Conditional) + { + st = ((Conditional)container).getStatements(); + } + else if (container instanceof IfStatement) + { + st = ((IfStatement)container).getElseStatements(); + } + else if (container instanceof TryExceptStatement) + { + st = getStatementsFromContainer((TryExceptStatement)container); + } + else if (container instanceof PreprocessorItemStatements) + { + st = ((PreprocessorItemStatements)container).getStatements(); + } + else + { + st = getStatementsFromContainer(container); + } + return st; + } + private List getStatementsFromContainer(TryExceptStatement container) { List res = Lists.newArrayList(); diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/AsyncInvocationProvider.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/AsyncInvocationProvider.java index d6ff9e05c..17aeacb03 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/AsyncInvocationProvider.java +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/AsyncInvocationProvider.java @@ -49,6 +49,7 @@ public class AsyncInvocationProvider implements IAsyncInvocationProvider { + private static final String TYPE_NAME = "NotifyDescription"; //$NON-NLS-1$ private final Map> cashNames; private final Map>> cashTypesMethodNames; private final IConfigurationProvider configurationProvider; @@ -225,7 +226,7 @@ private boolean isCallbackDescription(Parameter param) { for (TypeItem type : param.getType()) { - if ("NotifyDescription".equals(McoreUtil.getTypeName(type))) //$NON-NLS-1$ + if (TYPE_NAME.equals(McoreUtil.getTypeName(type))) { return true; } From 2967576b71630a83448fc7d8b4e96eecc8eb8d10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=BB=D1=8E=D1=85=D0=B8=D0=BD=20=D0=90=D1=80=D1=82?= =?UTF-8?q?=D0=B5=D0=BC=20=D0=92=D0=B0=D1=81=D0=B8=D0=BB=D1=8C=D0=B5=D0=B2?= =?UTF-8?q?=D0=B8=D1=87?= Date: Fri, 10 Mar 2023 09:32:15 +0300 Subject: [PATCH 08/23] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=20=D1=82=D0=B5=D1=81=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bsl/check/CodeAfterAsyncCallCheck.java | 35 +++++++++++++------ .../resources/async-call-spread-sh-doc.bsl | 10 ++++++ .../itests/CodeAfterAsyncCallCheckTest.java | 12 ++++++- 3 files changed, 46 insertions(+), 11 deletions(-) create mode 100644 tests/com.e1c.v8codestyle.bsl.itests/resources/async-call-spread-sh-doc.bsl diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java index 3235d57b1..03b43fea5 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java @@ -17,6 +17,7 @@ import java.util.Collection; import java.util.Iterator; import java.util.List; +import java.util.Map; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IProgressMonitor; @@ -27,6 +28,7 @@ import com._1c.g5.v8.dt.bsl.common.IBslPreferences; import com._1c.g5.v8.dt.bsl.model.BslPackage; import com._1c.g5.v8.dt.bsl.model.Conditional; +import com._1c.g5.v8.dt.bsl.model.DynamicFeatureAccess; import com._1c.g5.v8.dt.bsl.model.EmptyStatement; import com._1c.g5.v8.dt.bsl.model.Expression; import com._1c.g5.v8.dt.bsl.model.FeatureAccess; @@ -116,16 +118,29 @@ protected void check(Object object, ResultAcceptor resultAceptor, ICheckParamete Collection asyncMethodsNames = asyncInvocationProvider.getAsyncInvocationNames(version); if (asyncMethodsNames.contains(featureAccess.getName())) { - Statement statement = getStatementFromInvoc(inv); - if (statement != null && isPreviousStatementAwait(statement)) - { - statement = getNextStatement(statement); - if (statement != null && !(statement instanceof ReturnStatement) - && !(statement instanceof EmptyStatement)) - { - resultAceptor.addIssue(Messages.CodeAfterAsyncCallCheck_Issue, statement); - } - } + addIssue(resultAceptor, inv); + } + } + else if (featureAccess instanceof DynamicFeatureAccess) + { + Map> names = asyncInvocationProvider.getAsyncTypeMethodNames(version); + if (names.containsKey(featureAccess.getName())) + { + addIssue(resultAceptor, inv); + } + } + } + + private void addIssue(ResultAcceptor resultAceptor, Invocation inv) + { + Statement statement = getStatementFromInvoc(inv); + if (statement != null && isPreviousStatementAwait(statement)) + { + statement = getNextStatement(statement); + if (statement != null && !(statement instanceof ReturnStatement) + && !(statement instanceof EmptyStatement)) + { + resultAceptor.addIssue(Messages.CodeAfterAsyncCallCheck_Issue, statement); } } } diff --git a/tests/com.e1c.v8codestyle.bsl.itests/resources/async-call-spread-sh-doc.bsl b/tests/com.e1c.v8codestyle.bsl.itests/resources/async-call-spread-sh-doc.bsl new file mode 100644 index 000000000..07fe097a0 --- /dev/null +++ b/tests/com.e1c.v8codestyle.bsl.itests/resources/async-call-spread-sh-doc.bsl @@ -0,0 +1,10 @@ + + +Процедура Тест() + + ТабДок = Новый ТабличныйДокумент; + ТабДок.ЗаписатьАсинх(); + + Сообщить("кто быстрее?"); + +КонецПроцедуры \ No newline at end of file diff --git a/tests/com.e1c.v8codestyle.bsl.itests/src/com/e1c/v8codestyle/bsl/check/itests/CodeAfterAsyncCallCheckTest.java b/tests/com.e1c.v8codestyle.bsl.itests/src/com/e1c/v8codestyle/bsl/check/itests/CodeAfterAsyncCallCheckTest.java index ef27f7bc1..6dbf30e28 100644 --- a/tests/com.e1c.v8codestyle.bsl.itests/src/com/e1c/v8codestyle/bsl/check/itests/CodeAfterAsyncCallCheckTest.java +++ b/tests/com.e1c.v8codestyle.bsl.itests/src/com/e1c/v8codestyle/bsl/check/itests/CodeAfterAsyncCallCheckTest.java @@ -24,7 +24,7 @@ /** * Tests for {@link CodeAfterAsyncCallCheck} check. - * + * * @author Artem Iliukhin */ public class CodeAfterAsyncCallCheckTest @@ -67,4 +67,14 @@ public void testPromiseCompliant() throws Exception Marker marker = getFirstMarker(CHECK_ID, getModuleId(), getProject()); assertNull(marker); } + + @Test + public void testSpreadsheetDocumentNonCompliant() throws Exception + { + updateModule(FOLDER_RESOURCE + "async-call-spread-sh-doc.bsl"); + + Marker marker = getFirstMarker(CHECK_ID, getModuleId(), getProject()); + assertNotNull(marker); + assertEquals("8", marker.getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_LINE_KEY)); + } } From 7ca23997960799225fc8c170b5a45da2b0e99730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=BB=D1=8E=D1=85=D0=B8=D0=BD=20=D0=90=D1=80=D1=82?= =?UTF-8?q?=D0=B5=D0=BC=20=D0=92=D0=B0=D1=81=D0=B8=D0=BB=D1=8C=D0=B5=D0=B2?= =?UTF-8?q?=D0=B8=D1=87?= Date: Fri, 10 Mar 2023 10:27:35 +0300 Subject: [PATCH 09/23] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java | 2 +- .../e1c/v8codestyle/internal/bsl/AsyncInvocationProvider.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java index 03b43fea5..e3a2904da 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java @@ -165,7 +165,7 @@ private boolean isPreviousStatementAwait(Statement statement) if (st != null) { int index = st.indexOf(statement); - if (index != -1 && index - 1 < st.size()) + if (index > 0 && index - 1 < st.size()) { Statement awaitStatement = st.get(index - 1); if (awaitStatement instanceof SimpleStatement) diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/AsyncInvocationProvider.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/AsyncInvocationProvider.java index 17aeacb03..3cd8464f4 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/AsyncInvocationProvider.java +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/AsyncInvocationProvider.java @@ -49,6 +49,7 @@ public class AsyncInvocationProvider implements IAsyncInvocationProvider { + private static final String EXEPTION_NAME = "RunCallback"; //$NON-NLS-1$ private static final String TYPE_NAME = "NotifyDescription"; //$NON-NLS-1$ private final Map> cashNames; private final Map>> cashTypesMethodNames; @@ -190,7 +191,7 @@ private void process(Map> asyncMethodsNames, Type typ private void collectMethods(Collection asyncMethodsNames, EObject object) { Method method = (Method)object; - if ("RunCallback".equals(method.getName())) //$NON-NLS-1$ + if (EXEPTION_NAME.equals(method.getName())) { return; } From 0b530106d775bc4529fed67548b5eff5a4d6aecc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=BB=D1=8E=D1=85=D0=B8=D0=BD=20=D0=90=D1=80=D1=82?= =?UTF-8?q?=D0=B5=D0=BC=20=D0=92=D0=B0=D1=81=D0=B8=D0=BB=D1=8C=D0=B5=D0=B2?= =?UTF-8?q?=D0=B8=D1=87?= Date: Sat, 11 Mar 2023 06:32:07 +0300 Subject: [PATCH 10/23] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java index e3a2904da..f755f81cf 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java @@ -35,6 +35,7 @@ import com._1c.g5.v8.dt.bsl.model.IfStatement; 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.PreprocessorConditional; import com._1c.g5.v8.dt.bsl.model.PreprocessorItemStatements; import com._1c.g5.v8.dt.bsl.model.ReturnStatement; import com._1c.g5.v8.dt.bsl.model.SimpleStatement; @@ -161,6 +162,10 @@ private boolean isPreviousStatementAwait(Statement statement) while (it.hasNext()) { EObject container = it.next(); + if (container instanceof PreprocessorConditional) + { + continue; + } List st = getContainer(container); if (st != null) { @@ -194,6 +199,10 @@ private Statement getNextStatement(Statement statement) while (it.hasNext()) { EObject container = it.next(); + if (container instanceof PreprocessorConditional) + { + continue; + } List st = getContainer(container); if (st != null) { From 53b43419018f4fa2cfa6509c043097e9de83b9a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=BB=D1=8E=D1=85=D0=B8=D0=BD=20=D0=90=D1=80=D1=82?= =?UTF-8?q?=D0=B5=D0=BC=20=D0=92=D0=B0=D1=81=D0=B8=D0=BB=D1=8C=D0=B5=D0=B2?= =?UTF-8?q?=D0=B8=D1=87?= Date: Mon, 13 Mar 2023 08:15:53 +0300 Subject: [PATCH 11/23] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=20=D0=BF=D1=80=D0=B8=D0=BC=D0=B5=D1=80=20=D0=B2=20?= =?UTF-8?q?=D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=86?= =?UTF-8?q?=D0=B8=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../markdown/ru/code-after-async-call.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/bundles/com.e1c.v8codestyle.bsl/markdown/ru/code-after-async-call.md b/bundles/com.e1c.v8codestyle.bsl/markdown/ru/code-after-async-call.md index 5b7f384b9..de490bf20 100644 --- a/bundles/com.e1c.v8codestyle.bsl/markdown/ru/code-after-async-call.md +++ b/bundles/com.e1c.v8codestyle.bsl/markdown/ru/code-after-async-call.md @@ -17,6 +17,11 @@ Сообщить("Закрыли предупреждение"); ``` +```bsl +ПоказатьПредупреждение(,ТекстПредупреждения); +Отказ = Истина; +``` + ## Правильно ```bsl @@ -39,6 +44,11 @@ КонецПроцедуры; ``` +```bsl +Отказ = Истина; +ПоказатьПредупреждение(,ТекстПредупреждения); +``` + ## См. - [Синхронные и асинхронные методы работы](https://its.1c.ru/db/v8319doc#bookmark:dev:TI000001505) From ddda9f5f8e7b0c8e21a0a9859b7d0dd4e686f433 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=BB=D1=8E=D1=85=D0=B8=D0=BD=20=D0=90=D1=80=D1=82?= =?UTF-8?q?=D0=B5=D0=BC=20=D0=92=D0=B0=D1=81=D0=B8=D0=BB=D1=8C=D0=B5=D0=B2?= =?UTF-8?q?=D0=B8=D1=87?= Date: Tue, 14 Mar 2023 08:21:31 +0300 Subject: [PATCH 12/23] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B7=D0=B0=D0=BC=D0=B5=D1=87?= =?UTF-8?q?=D0=B0=D0=BD=D0=B8=D0=B9=20CR?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 3 +- .../META-INF/MANIFEST.MF | 1 + .../bsl/IAsyncInvocationProvider.java | 16 ++++- .../bsl/check/CodeAfterAsyncCallCheck.java | 40 +++++++++--- .../internal/bsl/AsyncInvocationProvider.java | 65 ++++++++++--------- .../bsl/ExternalDependenciesModule.java | 2 + 6 files changed, 82 insertions(+), 45 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 811f85fe0..bad1389a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ #### Код модулей +- Проверка отсутствия кода после асинхронного вызова #### Запросы @@ -61,8 +62,6 @@ - Проверка наличия префикса расширения в методе расширения. - Устаревшая процедура (функция) расположена вне области "УстаревшиеПроцедурыИФункции" - Использован обработчик событий, подключаемый из кода и не содержащий префикса "Подключаемый_" -- Проверка отсутствия кода после асинхронного вызова - ### Новые быстрые исправления (Quick-fix) diff --git a/bundles/com.e1c.v8codestyle.bsl/META-INF/MANIFEST.MF b/bundles/com.e1c.v8codestyle.bsl/META-INF/MANIFEST.MF index c673047c7..6ad695c18 100644 --- a/bundles/com.e1c.v8codestyle.bsl/META-INF/MANIFEST.MF +++ b/bundles/com.e1c.v8codestyle.bsl/META-INF/MANIFEST.MF @@ -20,6 +20,7 @@ Bundle-RequiredExecutionEnvironment: JavaSE-11 Automatic-Module-Name: com.e1c.v8codestyle.bsl Bundle-ActivationPolicy: lazy Import-Package: com._1c.g5.v8.bm.core;version="[7.0.0,8.0.0)", + com._1c.g5.v8.dt.bm.xtext;version="[14.1.100,15.0.0)", com._1c.g5.v8.dt.bsl;version="[5.0.0,6.0.0)", com._1c.g5.v8.dt.bsl.comment;version="[3.0.0,4.0.0)", com._1c.g5.v8.dt.bsl.common;version="[6.0.0,7.0.0)", diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/IAsyncInvocationProvider.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/IAsyncInvocationProvider.java index e6da6269b..97a374d45 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/IAsyncInvocationProvider.java +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/IAsyncInvocationProvider.java @@ -18,17 +18,27 @@ import com._1c.g5.v8.dt.platform.version.Version; /** - * Platform context asynchronic methods provider + * Platform context asynchronous methods provider * * @author Artem Iliukhin */ public interface IAsyncInvocationProvider { - // Global context methods + /** + * Global context methods. + * + * @param version the version of platform + * @return the asynchronous invocation names + */ Collection getAsyncInvocationNames(Version version); - // Methods with a list of types in which they are used + /** + * Methods with a list of types in which they are used. + * + * @param version the version of platform + * @return the asynchronous type method names + */ Map> getAsyncTypeMethodNames(Version version); } diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java index f755f81cf..40e72c0a2 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java @@ -18,14 +18,13 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.emf.ecore.EObject; import org.eclipse.xtext.EcoreUtil2; -import org.eclipse.xtext.naming.IQualifiedNameConverter; -import com._1c.g5.v8.dt.bsl.common.IBslPreferences; import com._1c.g5.v8.dt.bsl.model.BslPackage; import com._1c.g5.v8.dt.bsl.model.Conditional; import com._1c.g5.v8.dt.bsl.model.DynamicFeatureAccess; @@ -42,10 +41,13 @@ import com._1c.g5.v8.dt.bsl.model.Statement; import com._1c.g5.v8.dt.bsl.model.StaticFeatureAccess; import com._1c.g5.v8.dt.bsl.model.TryExceptStatement; +import com._1c.g5.v8.dt.bsl.resource.TypesComputer; import com._1c.g5.v8.dt.core.platform.IResourceLookup; +import com._1c.g5.v8.dt.mcore.Environmental; +import com._1c.g5.v8.dt.mcore.TypeItem; +import com._1c.g5.v8.dt.mcore.util.McoreUtil; import com._1c.g5.v8.dt.platform.version.IRuntimeVersionSupport; import com._1c.g5.v8.dt.platform.version.Version; -import com._1c.g5.wiring.ServiceAccess; 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; @@ -73,14 +75,18 @@ public final class CodeAfterAsyncCallCheck private static final String CHECK_ID = "code-after-async-call"; //$NON-NLS-1$ private final IResourceLookup resourceLookup; private final IAsyncInvocationProvider asyncInvocationProvider; + private final IRuntimeVersionSupport runtimeVersionSupport; + private final TypesComputer typesComputer; @Inject - public CodeAfterAsyncCallCheck(IResourceLookup resourceLookup, IBslPreferences bslPreferences, - IQualifiedNameConverter qualifiedNameConverter, IAsyncInvocationProvider asyncInvocationProvider) + public CodeAfterAsyncCallCheck(IResourceLookup resourceLookup, IRuntimeVersionSupport runtimeVersionSupport, + IAsyncInvocationProvider asyncInvocationProvider, TypesComputer typesComputer) { super(); this.resourceLookup = resourceLookup; this.asyncInvocationProvider = asyncInvocationProvider; + this.runtimeVersionSupport = runtimeVersionSupport; + this.typesComputer = typesComputer; } @Override @@ -106,10 +112,7 @@ protected void configureCheck(CheckConfigurer builder) protected void check(Object object, ResultAcceptor resultAceptor, ICheckParameters parameters, IProgressMonitor monitor) { - IProject project = resourceLookup.getProject((EObject)object); - - IRuntimeVersionSupport runtimeVersionSupport = ServiceAccess.get(IRuntimeVersionSupport.class); Version version = runtimeVersionSupport.getRuntimeVersion(project); Invocation inv = (Invocation)object; @@ -127,7 +130,24 @@ else if (featureAccess instanceof DynamicFeatureAccess) Map> names = asyncInvocationProvider.getAsyncTypeMethodNames(version); if (names.containsKey(featureAccess.getName())) { - addIssue(resultAceptor, inv); + Expression source = ((DynamicFeatureAccess)featureAccess).getSource(); + Environmental environmental = EcoreUtil2.getContainerOfType(source, Environmental.class); + if (environmental == null) + { + return; + } + + List sourceTypes = typesComputer.computeTypes(source, environmental.environments()); + if (sourceTypes.isEmpty()) + { + return; + } + + if (names.get(featureAccess.getName()) + .containsAll(sourceTypes.stream().map(McoreUtil::getTypeName).collect(Collectors.toSet()))) + { + addIssue(resultAceptor, inv); + } } } } @@ -135,7 +155,7 @@ else if (featureAccess instanceof DynamicFeatureAccess) private void addIssue(ResultAcceptor resultAceptor, Invocation inv) { Statement statement = getStatementFromInvoc(inv); - if (statement != null && isPreviousStatementAwait(statement)) + if (statement != null && !isPreviousStatementAwait(statement)) { statement = getNextStatement(statement); if (statement != null && !(statement instanceof ReturnStatement) diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/AsyncInvocationProvider.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/AsyncInvocationProvider.java index 3cd8464f4..806f0c894 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/AsyncInvocationProvider.java +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/AsyncInvocationProvider.java @@ -13,16 +13,18 @@ package com.e1c.v8codestyle.internal.bsl; import java.util.Collection; +import java.util.Iterator; import java.util.Map; import java.util.TreeMap; import java.util.TreeSet; import java.util.concurrent.ConcurrentHashMap; import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.xtext.resource.IEObjectDescription; -import com._1c.g5.v8.dt.core.platform.IConfigurationProvider; +import com._1c.g5.v8.dt.bm.xtext.BmAwareResourceSetProvider; import com._1c.g5.v8.dt.core.platform.IV8Project; import com._1c.g5.v8.dt.core.platform.IV8ProjectManager; import com._1c.g5.v8.dt.mcore.ContextDef; @@ -34,7 +36,6 @@ import com._1c.g5.v8.dt.mcore.TypeItem; import com._1c.g5.v8.dt.mcore.TypeSet; import com._1c.g5.v8.dt.mcore.util.McoreUtil; -import com._1c.g5.v8.dt.metadata.mdclass.Configuration; import com._1c.g5.v8.dt.platform.IEObjectProvider; import com._1c.g5.v8.dt.platform.version.Version; import com.e1c.v8codestyle.bsl.IAsyncInvocationProvider; @@ -49,19 +50,20 @@ public class AsyncInvocationProvider implements IAsyncInvocationProvider { + private static final String POSTFIX = "Async"; //$NON-NLS-1$ private static final String EXEPTION_NAME = "RunCallback"; //$NON-NLS-1$ private static final String TYPE_NAME = "NotifyDescription"; //$NON-NLS-1$ private final Map> cashNames; private final Map>> cashTypesMethodNames; - private final IConfigurationProvider configurationProvider; private final IV8ProjectManager v8ProjectManager; + private final BmAwareResourceSetProvider resourceSetProvider; @Inject - public AsyncInvocationProvider(IConfigurationProvider configurationProvider, IV8ProjectManager v8ProjectManager) + public AsyncInvocationProvider(IV8ProjectManager v8ProjectManager, BmAwareResourceSetProvider resourceSetProvider) { super(); - this.configurationProvider = configurationProvider; this.v8ProjectManager = v8ProjectManager; + this.resourceSetProvider = resourceSetProvider; this.cashNames = new ConcurrentHashMap<>(); this.cashTypesMethodNames = new ConcurrentHashMap<>(); } @@ -103,13 +105,11 @@ public Map> getAsyncTypeMethodNames(Version version) private void collect(Version version) { Collection asyncMethodsNames = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); - - Collection projects = v8ProjectManager.getProjects(); - for (IV8Project project : projects) + Iterator iterator = v8ProjectManager.getProjects().iterator(); + if (iterator.hasNext()) { - Configuration context = configurationProvider.getConfiguration(project.getProject()); + ResourceSet context = resourceSetProvider.get(iterator.next().getProject()); IEObjectProvider provider = IEObjectProvider.Registry.INSTANCE.get(McorePackage.Literals.METHOD, version); - Iterable items = provider.getEObjectDescriptions(null); for (IEObjectDescription item : items) { @@ -126,12 +126,10 @@ private void collect(Version version) private Map> process(Version version) { Map> asyncMethodsNames = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); - - Collection projects = v8ProjectManager.getProjects(); - for (IV8Project project : projects) + Iterator iterator = v8ProjectManager.getProjects().iterator(); + if (iterator.hasNext()) { - Configuration context = configurationProvider.getConfiguration(project.getProject()); - + ResourceSet context = resourceSetProvider.get(iterator.next().getProject()); IEObjectProvider provider = IEObjectProvider.Registry.INSTANCE.get(McorePackage.Literals.TYPE_ITEM, version); Iterable items = provider.getEObjectDescriptions(null); @@ -175,52 +173,59 @@ private void process(Map> asyncMethodsNames, Type typ for (Method method : contextDef.allMethods()) { - if (method.getName().endsWith("Async")) //$NON-NLS-1$ + if (method.getName().endsWith(POSTFIX)) { - if (asyncMethodsNames.get(method.getName()) != null) + if (asyncMethodsNames.get(method.getName()) == null) { - asyncMethodsNames.get(method.getName()).add(type.getName()); - asyncMethodsNames.get(method.getNameRu()).add(type.getNameRu()); + asyncMethodsNames.putIfAbsent(method.getName(), new TreeSet<>()); + asyncMethodsNames.putIfAbsent(method.getNameRu(), new TreeSet<>()); } - asyncMethodsNames.putIfAbsent(method.getName(), new TreeSet<>()); - asyncMethodsNames.putIfAbsent(method.getNameRu(), new TreeSet<>()); + asyncMethodsNames.get(method.getName()).add(type.getName()); + asyncMethodsNames.get(method.getName()).add(type.getNameRu()); + asyncMethodsNames.get(method.getNameRu()).add(type.getName()); + asyncMethodsNames.get(method.getNameRu()).add(type.getNameRu()); } } } private void collectMethods(Collection asyncMethodsNames, EObject object) { + if (!(object instanceof Method)) + { + return; + } + Method method = (Method)object; if (EXEPTION_NAME.equals(method.getName())) { return; } - if (method.getName().endsWith("Async")) //$NON-NLS-1$ + if (isMethodAsync(method)) { asyncMethodsNames.add(method.getName()); asyncMethodsNames.add(method.getNameRu()); } - else - { - checkParamAndCollectMethods(asyncMethodsNames, method); - } } - private void checkParamAndCollectMethods(Collection asyncMethodsNames, Method method) + private boolean isMethodAsync(Method method) { + if (method.getName().endsWith(POSTFIX)) + { + return true; + } + for (ParamSet paramSet : method.getParamSet()) { for (Parameter param : paramSet.getParams()) { if (isCallbackDescription(param)) { - asyncMethodsNames.add(method.getName()); - asyncMethodsNames.add(method.getNameRu()); - break; + return true; } } } + return false; } private boolean isCallbackDescription(Parameter param) diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/ExternalDependenciesModule.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/ExternalDependenciesModule.java index 27757dcca..389314050 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/ExternalDependenciesModule.java +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/ExternalDependenciesModule.java @@ -25,6 +25,7 @@ import org.eclipse.xtext.resource.impl.ResourceDescriptionsProvider; import org.eclipse.xtext.scoping.IScopeProvider; +import com._1c.g5.v8.dt.bm.xtext.BmAwareResourceSetProvider; import com._1c.g5.v8.dt.bsl.common.IBslPreferences; import com._1c.g5.v8.dt.bsl.contextdef.IBslModuleContextDefService; import com._1c.g5.v8.dt.bsl.documentation.comment.BslMultiLineCommentDocumentationProvider; @@ -91,5 +92,6 @@ protected void doConfigure() bind(ResourceDescriptionsProvider.class).toService(); bind(IConfigurationProvider.class).toService(); bind(BslGrammarAccess.class).toProvider(() -> rsp.get(BslGrammarAccess.class)); + bind(BmAwareResourceSetProvider.class).toProvider(() -> rsp.get(BmAwareResourceSetProvider.class)); } } From ecefabd3d262ff90d5dc17c808fbdd27a48d49a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=BB=D1=8E=D1=85=D0=B8=D0=BD=20=D0=90=D1=80=D1=82?= =?UTF-8?q?=D0=B5=D0=BC=20=D0=92=D0=B0=D1=81=D0=B8=D0=BB=D1=8C=D0=B5=D0=B2?= =?UTF-8?q?=D0=B8=D1=87?= Date: Tue, 14 Mar 2023 08:59:39 +0300 Subject: [PATCH 13/23] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=20=D0=BF=D0=B0=D1=80=D0=B0=D0=BC=D0=B5=D1=82=D1=80?= =?UTF-8?q?=20=D0=B2=20=D0=BD=D0=B0=D1=81=D1=82=D1=80=D0=BE=D0=B9=D0=BA?= =?UTF-8?q?=D1=83=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bsl/check/CodeAfterAsyncCallCheck.java | 26 ++++++++++++++++--- .../e1c/v8codestyle/bsl/check/Messages.java | 2 ++ .../v8codestyle/bsl/check/messages.properties | 2 ++ .../bsl/check/messages_ru.properties | 2 ++ 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java index 40e72c0a2..311eaaf32 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java @@ -28,6 +28,7 @@ import com._1c.g5.v8.dt.bsl.model.BslPackage; import com._1c.g5.v8.dt.bsl.model.Conditional; import com._1c.g5.v8.dt.bsl.model.DynamicFeatureAccess; +import com._1c.g5.v8.dt.bsl.model.EmptyExpression; import com._1c.g5.v8.dt.bsl.model.EmptyStatement; import com._1c.g5.v8.dt.bsl.model.Expression; import com._1c.g5.v8.dt.bsl.model.FeatureAccess; @@ -41,6 +42,7 @@ import com._1c.g5.v8.dt.bsl.model.Statement; import com._1c.g5.v8.dt.bsl.model.StaticFeatureAccess; import com._1c.g5.v8.dt.bsl.model.TryExceptStatement; +import com._1c.g5.v8.dt.bsl.model.UndefinedLiteral; import com._1c.g5.v8.dt.bsl.resource.TypesComputer; import com._1c.g5.v8.dt.core.platform.IResourceLookup; import com._1c.g5.v8.dt.mcore.Environmental; @@ -73,6 +75,8 @@ public final class CodeAfterAsyncCallCheck private static final String STATEMENT_NAME_RU = "Ждать"; //$NON-NLS-1$ private static final String STATEMENT_NAME = "Await"; //$NON-NLS-1$ private static final String CHECK_ID = "code-after-async-call"; //$NON-NLS-1$ + private static final String DEFAULT_CHECK = Boolean.toString(Boolean.TRUE); + private static final String PARAMETER_NAME = "NotifyDescriptionIsDefined"; //$NON-NLS-1$ private final IResourceLookup resourceLookup; private final IAsyncInvocationProvider asyncInvocationProvider; private final IRuntimeVersionSupport runtimeVersionSupport; @@ -105,7 +109,9 @@ protected void configureCheck(CheckConfigurer builder) .issueType(IssueType.WARNING) .extension(new CommonSenseCheckExtension(getCheckId(), BslPlugin.PLUGIN_ID)) .module() - .checkedObjectType(INVOCATION); + .checkedObjectType(INVOCATION) + .parameter(PARAMETER_NAME, Boolean.class, DEFAULT_CHECK, + Messages.CodeAfterAsyncCallCheck_Parameter); } @Override @@ -120,9 +126,11 @@ protected void check(Object object, ResultAcceptor resultAceptor, ICheckParamete if (featureAccess instanceof StaticFeatureAccess) { Collection asyncMethodsNames = asyncInvocationProvider.getAsyncInvocationNames(version); - if (asyncMethodsNames.contains(featureAccess.getName())) + if (asyncMethodsNames.contains(featureAccess.getName()) + && (parameters.getBoolean(PARAMETER_NAME) && isDefinedParam(inv) + || !parameters.getBoolean(PARAMETER_NAME))) { - addIssue(resultAceptor, inv); + addIssue(resultAceptor, inv); } } else if (featureAccess instanceof DynamicFeatureAccess) @@ -152,6 +160,18 @@ else if (featureAccess instanceof DynamicFeatureAccess) } } + private boolean isDefinedParam(Invocation inv) + { + for (Expression param : inv.getParams()) + { + if (param instanceof EmptyExpression || param instanceof UndefinedLiteral) + { + return true; + } + } + return false; + } + private void addIssue(ResultAcceptor resultAceptor, Invocation inv) { Statement statement = getStatementFromInvoc(inv); diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/Messages.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/Messages.java index 686e0d1bc..3dfc8f3d5 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/Messages.java +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/Messages.java @@ -65,6 +65,8 @@ final class Messages public static String CodeAfterAsyncCallCheck_Issue; + public static String CodeAfterAsyncCallCheck_Parameter; + public static String CodeAfterAsyncCallCheck_Title; public static String CommitTransactionCheck_Commit_transaction_must_be_in_try_catch; diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages.properties b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages.properties index d35c682f0..a3fb333bb 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages.properties +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages.properties @@ -66,6 +66,8 @@ CodeAfterAsyncCallCheck_Description=Checks that the asynchronous method is not f CodeAfterAsyncCallCheck_Issue=The asynchronous method is followed by lines of code +CodeAfterAsyncCallCheck_Parameter=Only with the defined parameter NotifyDescription + CodeAfterAsyncCallCheck_Title=The code should not follow an asynchronous call CommitTransactionCheck_Commit_transaction_must_be_in_try_catch = Commit transaction must be in a try-catch diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages_ru.properties b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages_ru.properties index de4f97010..2bd5614c7 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages_ru.properties +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages_ru.properties @@ -68,6 +68,8 @@ CodeAfterAsyncCallCheck_Issue=За асинхронным методом сле CodeAfterAsyncCallCheck_Title=Код не должен следовать за асинхронным вызовом +CodeAfterAsyncCallCheck_Parameter=Tолько с заданным параметром ОписаниеОповещения + CommitTransactionCheck_Commit_transaction_must_be_in_try_catch = Вызов "ЗафиксироватьТранзакцию()" находится вне конструкции "Попытка... Исключение" CommitTransactionCheck_No_begin_transaction_for_commit_transaction = Отсутствует вызов "НачатьТранзакцию()", хотя вызываются "ЗафиксироватьТранзакцию()" From 968ddaaf16ae4d7d54689d2825372a77c058b68b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=BB=D1=8E=D1=85=D0=B8=D0=BD=20=D0=90=D1=80=D1=82?= =?UTF-8?q?=D0=B5=D0=BC=20=D0=92=D0=B0=D1=81=D0=B8=D0=BB=D1=8C=D0=B5=D0=B2?= =?UTF-8?q?=D0=B8=D1=87?= Date: Tue, 14 Mar 2023 09:10:22 +0300 Subject: [PATCH 14/23] =?UTF-8?q?=D0=A3=D1=82=D0=BE=D1=87=D0=BD=D0=B5?= =?UTF-8?q?=D0=BD=20=D0=BA=D0=BE=D0=BC=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=80?= =?UTF-8?q?=D0=B8=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/com/e1c/v8codestyle/bsl/check/messages.properties | 2 +- .../src/com/e1c/v8codestyle/bsl/check/messages_ru.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages.properties b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages.properties index a3fb333bb..4ba0a3240 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages.properties +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages.properties @@ -66,7 +66,7 @@ CodeAfterAsyncCallCheck_Description=Checks that the asynchronous method is not f CodeAfterAsyncCallCheck_Issue=The asynchronous method is followed by lines of code -CodeAfterAsyncCallCheck_Parameter=Only with the defined parameter NotifyDescription +CodeAfterAsyncCallCheck_Parameter=Only with the defined parameter NotifyDescription, if applicable CodeAfterAsyncCallCheck_Title=The code should not follow an asynchronous call diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages_ru.properties b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages_ru.properties index 2bd5614c7..f728404c8 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages_ru.properties +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages_ru.properties @@ -68,7 +68,7 @@ CodeAfterAsyncCallCheck_Issue=За асинхронным методом сле CodeAfterAsyncCallCheck_Title=Код не должен следовать за асинхронным вызовом -CodeAfterAsyncCallCheck_Parameter=Tолько с заданным параметром ОписаниеОповещения +CodeAfterAsyncCallCheck_Parameter=Tолько с заданным параметром ОписаниеОповещения, если применимо CommitTransactionCheck_Commit_transaction_must_be_in_try_catch = Вызов "ЗафиксироватьТранзакцию()" находится вне конструкции "Попытка... Исключение" From 824d3273c48fc559f4642afad4b059e8340648a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=BB=D1=8E=D1=85=D0=B8=D0=BD=20=D0=90=D1=80=D1=82?= =?UTF-8?q?=D0=B5=D0=BC=20=D0=92=D0=B0=D1=81=D0=B8=D0=BB=D1=8C=D0=B5=D0=B2?= =?UTF-8?q?=D0=B8=D1=87?= Date: Tue, 14 Mar 2023 10:18:57 +0300 Subject: [PATCH 15/23] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5?= =?UTF-8?q?=D1=80=D0=BA=D0=B8=20=D1=82=D0=B8=D0=BF=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bsl/check/CodeAfterAsyncCallCheck.java | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java index 311eaaf32..cf0145e8e 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java @@ -28,7 +28,6 @@ import com._1c.g5.v8.dt.bsl.model.BslPackage; import com._1c.g5.v8.dt.bsl.model.Conditional; import com._1c.g5.v8.dt.bsl.model.DynamicFeatureAccess; -import com._1c.g5.v8.dt.bsl.model.EmptyExpression; import com._1c.g5.v8.dt.bsl.model.EmptyStatement; import com._1c.g5.v8.dt.bsl.model.Expression; import com._1c.g5.v8.dt.bsl.model.FeatureAccess; @@ -42,7 +41,6 @@ import com._1c.g5.v8.dt.bsl.model.Statement; import com._1c.g5.v8.dt.bsl.model.StaticFeatureAccess; import com._1c.g5.v8.dt.bsl.model.TryExceptStatement; -import com._1c.g5.v8.dt.bsl.model.UndefinedLiteral; import com._1c.g5.v8.dt.bsl.resource.TypesComputer; import com._1c.g5.v8.dt.core.platform.IResourceLookup; import com._1c.g5.v8.dt.mcore.Environmental; @@ -77,6 +75,7 @@ public final class CodeAfterAsyncCallCheck private static final String CHECK_ID = "code-after-async-call"; //$NON-NLS-1$ private static final String DEFAULT_CHECK = Boolean.toString(Boolean.TRUE); private static final String PARAMETER_NAME = "NotifyDescriptionIsDefined"; //$NON-NLS-1$ + private static final String TYPE_NAME = "NotifyDescription"; //$NON-NLS-1$ private final IResourceLookup resourceLookup; private final IAsyncInvocationProvider asyncInvocationProvider; private final IRuntimeVersionSupport runtimeVersionSupport; @@ -127,7 +126,7 @@ protected void check(Object object, ResultAcceptor resultAceptor, ICheckParamete { Collection asyncMethodsNames = asyncInvocationProvider.getAsyncInvocationNames(version); if (asyncMethodsNames.contains(featureAccess.getName()) - && (parameters.getBoolean(PARAMETER_NAME) && isDefinedParam(inv) + && (parameters.getBoolean(PARAMETER_NAME) && isNotifyDescription(inv) || !parameters.getBoolean(PARAMETER_NAME))) { addIssue(resultAceptor, inv); @@ -160,13 +159,28 @@ else if (featureAccess instanceof DynamicFeatureAccess) } } - private boolean isDefinedParam(Invocation inv) + private boolean isNotifyDescription(Invocation inv) { for (Expression param : inv.getParams()) { - if (param instanceof EmptyExpression || param instanceof UndefinedLiteral) + Environmental environmental = EcoreUtil2.getContainerOfType(param, Environmental.class); + if (environmental == null) { - return true; + return false; + } + + List sourceTypes = typesComputer.computeTypes(param, environmental.environments()); + if (sourceTypes.isEmpty()) + { + return false; + } + + for (TypeItem typeItem : sourceTypes) + { + if (TYPE_NAME.equals(McoreUtil.getTypeName(typeItem))) + { + return true; + } } } return false; From b26b76e083b47c0c661faefd28a1cea402f33a33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=BB=D1=8E=D1=85=D0=B8=D0=BD=20=D0=90=D1=80=D1=82?= =?UTF-8?q?=D0=B5=D0=BC=20=D0=92=D0=B0=D1=81=D0=B8=D0=BB=D1=8C=D0=B5=D0=B2?= =?UTF-8?q?=D0=B8=D1=87?= Date: Tue, 14 Mar 2023 10:39:41 +0300 Subject: [PATCH 16/23] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=84=D0=BE=D1=80=D0=BC=D0=B0?= =?UTF-8?q?=D1=82=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java index cf0145e8e..17b69279c 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java @@ -129,7 +129,7 @@ protected void check(Object object, ResultAcceptor resultAceptor, ICheckParamete && (parameters.getBoolean(PARAMETER_NAME) && isNotifyDescription(inv) || !parameters.getBoolean(PARAMETER_NAME))) { - addIssue(resultAceptor, inv); + addIssue(resultAceptor, inv); } } else if (featureAccess instanceof DynamicFeatureAccess) From d4beb5ec906ae9a77da9dd390e8c1845e1d23c3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=BB=D1=8E=D1=85=D0=B8=D0=BD=20=D0=90=D1=80=D1=82?= =?UTF-8?q?=D0=B5=D0=BC=20=D0=92=D0=B0=D1=81=D0=B8=D0=BB=D1=8C=D0=B5=D0=B2?= =?UTF-8?q?=D0=B8=D1=87?= Date: Wed, 15 Mar 2023 07:25:09 +0300 Subject: [PATCH 17/23] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=82=D0=B5=D1=81=D1=82=D0=BE?= =?UTF-8?q?=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bsl/check/CodeAfterAsyncCallCheck.java | 2 +- .../check/itests/CodeAfterAsyncCallCheckTest.java | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java index 17b69279c..cfa2b81bb 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java @@ -240,7 +240,7 @@ private boolean isPreviousStatementAwait(Statement statement) } } - return awaitStatement != null; + return false; } } } diff --git a/tests/com.e1c.v8codestyle.bsl.itests/src/com/e1c/v8codestyle/bsl/check/itests/CodeAfterAsyncCallCheckTest.java b/tests/com.e1c.v8codestyle.bsl.itests/src/com/e1c/v8codestyle/bsl/check/itests/CodeAfterAsyncCallCheckTest.java index 6dbf30e28..d3b9b5362 100644 --- a/tests/com.e1c.v8codestyle.bsl.itests/src/com/e1c/v8codestyle/bsl/check/itests/CodeAfterAsyncCallCheckTest.java +++ b/tests/com.e1c.v8codestyle.bsl.itests/src/com/e1c/v8codestyle/bsl/check/itests/CodeAfterAsyncCallCheckTest.java @@ -16,11 +16,18 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import java.util.Collections; + +import org.eclipse.core.resources.IProject; import org.junit.Test; +import com._1c.g5.v8.dt.core.platform.IDtProject; 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.v8codestyle.bsl.check.CodeAfterAsyncCallCheck; +import com.e1c.v8codestyle.internal.bsl.BslPlugin; /** * Tests for {@link CodeAfterAsyncCallCheck} check. @@ -31,6 +38,7 @@ public class CodeAfterAsyncCallCheckTest extends AbstractSingleModuleTestBase { private static final String CHECK_ID = "code-after-async-call"; //$NON-NLS-1$ + private static final String PARAMETER_NAME = "NotifyDescriptionIsDefined"; //$NON-NLS-1$ /** * Instantiates a new code after async call check test. @@ -43,6 +51,13 @@ public CodeAfterAsyncCallCheckTest() @Test public void testCodeAfterExistence() throws Exception { + IDtProject dtProject = getProject(); + IProject project = dtProject.getWorkspaceProject(); + ICheckSettings settings = checkRepository.getSettings(new CheckUid(CHECK_ID, BslPlugin.PLUGIN_ID), project); + settings.getParameters().get(PARAMETER_NAME).setValue(Boolean.toString(Boolean.FALSE)); + checkRepository.applyChanges(Collections.singleton(settings), project); + waitForDD(dtProject); + updateModule(FOLDER_RESOURCE + "code-after-async-call-existence.bsl"); Marker marker = getFirstMarker(CHECK_ID, getModuleId(), getProject()); From f42d46a3d70c6caa388ffc1e55d7453cb7c434c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=BB=D1=8E=D1=85=D0=B8=D0=BD=20=D0=90=D1=80=D1=82?= =?UTF-8?q?=D0=B5=D0=BC=20=D0=92=D0=B0=D1=81=D0=B8=D0=BB=D1=8C=D0=B5=D0=B2?= =?UTF-8?q?=D0=B8=D1=87?= Date: Wed, 15 Mar 2023 09:23:03 +0300 Subject: [PATCH 18/23] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B4=D1=83=D0=B1=D0=BB=D0=B5?= =?UTF-8?q?=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bsl/check/CodeAfterAsyncCallCheck.java | 36 +++++++------------ 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java index cfa2b81bb..3955de29c 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java @@ -138,18 +138,7 @@ else if (featureAccess instanceof DynamicFeatureAccess) if (names.containsKey(featureAccess.getName())) { Expression source = ((DynamicFeatureAccess)featureAccess).getSource(); - Environmental environmental = EcoreUtil2.getContainerOfType(source, Environmental.class); - if (environmental == null) - { - return; - } - - List sourceTypes = typesComputer.computeTypes(source, environmental.environments()); - if (sourceTypes.isEmpty()) - { - return; - } - + List sourceTypes = computeTypes(source); if (names.get(featureAccess.getName()) .containsAll(sourceTypes.stream().map(McoreUtil::getTypeName).collect(Collectors.toSet()))) { @@ -163,18 +152,7 @@ private boolean isNotifyDescription(Invocation inv) { for (Expression param : inv.getParams()) { - Environmental environmental = EcoreUtil2.getContainerOfType(param, Environmental.class); - if (environmental == null) - { - return false; - } - - List sourceTypes = typesComputer.computeTypes(param, environmental.environments()); - if (sourceTypes.isEmpty()) - { - return false; - } - + List sourceTypes = computeTypes(param); for (TypeItem typeItem : sourceTypes) { if (TYPE_NAME.equals(McoreUtil.getTypeName(typeItem))) @@ -186,6 +164,16 @@ private boolean isNotifyDescription(Invocation inv) return false; } + private List computeTypes(Expression expression) + { + Environmental environmental = EcoreUtil2.getContainerOfType(expression, Environmental.class); + if (environmental != null) + { + return typesComputer.computeTypes(expression, environmental.environments()); + } + return List.of(); + } + private void addIssue(ResultAcceptor resultAceptor, Invocation inv) { Statement statement = getStatementFromInvoc(inv); From 64ae81beee8bdcd2e5e5b7b3a6ff10e2348eb01a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=BB=D1=8E=D1=85=D0=B8=D0=BD=20=D0=90=D1=80=D1=82?= =?UTF-8?q?=D0=B5=D0=BC=20=D0=92=D0=B0=D1=81=D0=B8=D0=BB=D1=8C=D0=B5=D0=B2?= =?UTF-8?q?=D0=B8=D1=87?= Date: Wed, 15 Mar 2023 10:45:38 +0300 Subject: [PATCH 19/23] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B8=D0=BC=D0=B5=D0=BD=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bsl/check/CodeAfterAsyncCallCheck.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java index 3955de29c..28e3f42e7 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java @@ -260,32 +260,32 @@ private Statement getNextStatement(Statement statement) private List getContainer(EObject container) { - List st = null; + List statements = null; if (container instanceof LoopStatement) { - st = ((LoopStatement)container).getStatements(); + statements = ((LoopStatement)container).getStatements(); } else if (container instanceof Conditional) { - st = ((Conditional)container).getStatements(); + statements = ((Conditional)container).getStatements(); } else if (container instanceof IfStatement) { - st = ((IfStatement)container).getElseStatements(); + statements = ((IfStatement)container).getElseStatements(); } else if (container instanceof TryExceptStatement) { - st = getStatementsFromContainer((TryExceptStatement)container); + statements = getStatementsFromContainer((TryExceptStatement)container); } else if (container instanceof PreprocessorItemStatements) { - st = ((PreprocessorItemStatements)container).getStatements(); + statements = ((PreprocessorItemStatements)container).getStatements(); } else { - st = getStatementsFromContainer(container); + statements = getStatementsFromContainer(container); } - return st; + return statements; } private List getStatementsFromContainer(TryExceptStatement container) From fbbb6ba17346c206f75b493cb11823ce48c18bec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=BB=D1=8E=D1=85=D0=B8=D0=BD=20=D0=90=D1=80=D1=82?= =?UTF-8?q?=D0=B5=D0=BC=20=D0=92=D0=B0=D1=81=D0=B8=D0=BB=D1=8C=D0=B5=D0=B2?= =?UTF-8?q?=D0=B8=D1=87?= Date: Mon, 20 Mar 2023 10:02:32 +0300 Subject: [PATCH 20/23] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BF=D0=BE=20cr?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/com/e1c/v8codestyle/bsl/IAsyncInvocationProvider.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/IAsyncInvocationProvider.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/IAsyncInvocationProvider.java index 97a374d45..113e1fbfe 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/IAsyncInvocationProvider.java +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/IAsyncInvocationProvider.java @@ -28,7 +28,7 @@ public interface IAsyncInvocationProvider /** * Global context methods. * - * @param version the version of platform + * @param version the version of platform, cannot be {@code null} * @return the asynchronous invocation names */ Collection getAsyncInvocationNames(Version version); @@ -36,7 +36,7 @@ public interface IAsyncInvocationProvider /** * Methods with a list of types in which they are used. * - * @param version the version of platform + * @param version the version of platform, cannot be {@code null} * @return the asynchronous type method names */ Map> getAsyncTypeMethodNames(Version version); From d6c0932c333f241eb7863b00681e1709deda0d1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=BB=D1=8E=D1=85=D0=B8=D0=BD=20=D0=90=D1=80=D1=82?= =?UTF-8?q?=D0=B5=D0=BC=20=D0=92=D0=B0=D1=81=D0=B8=D0=BB=D1=8C=D0=B5=D0=B2?= =?UTF-8?q?=D0=B8=D1=87?= Date: Wed, 22 Mar 2023 11:03:02 +0300 Subject: [PATCH 21/23] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BF=D0=BE=20=D0=B7=D0=B0?= =?UTF-8?q?=D0=BC=D0=B5=D1=87=D0=B0=D0=BD=D0=B8=D1=8F=D0=BC=20cr?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bsl/check/CodeAfterAsyncCallCheck.java | 65 ++++++--------- .../internal/bsl/AsyncInvocationProvider.java | 79 +++++++++---------- .../itests/CodeAfterAsyncCallCheckTest.java | 2 +- 3 files changed, 66 insertions(+), 80 deletions(-) diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java index 28e3f42e7..0494dcb91 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java @@ -20,7 +20,6 @@ import java.util.Map; import java.util.stream.Collectors; -import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.emf.ecore.EObject; import org.eclipse.xtext.EcoreUtil2; @@ -42,7 +41,6 @@ import com._1c.g5.v8.dt.bsl.model.StaticFeatureAccess; import com._1c.g5.v8.dt.bsl.model.TryExceptStatement; import com._1c.g5.v8.dt.bsl.resource.TypesComputer; -import com._1c.g5.v8.dt.core.platform.IResourceLookup; import com._1c.g5.v8.dt.mcore.Environmental; import com._1c.g5.v8.dt.mcore.TypeItem; import com._1c.g5.v8.dt.mcore.util.McoreUtil; @@ -74,19 +72,17 @@ public final class CodeAfterAsyncCallCheck private static final String STATEMENT_NAME = "Await"; //$NON-NLS-1$ private static final String CHECK_ID = "code-after-async-call"; //$NON-NLS-1$ private static final String DEFAULT_CHECK = Boolean.toString(Boolean.TRUE); - private static final String PARAMETER_NAME = "NotifyDescriptionIsDefined"; //$NON-NLS-1$ + private static final String PARAMETER_NAME = "notifyDescriptionIsDefined"; //$NON-NLS-1$ private static final String TYPE_NAME = "NotifyDescription"; //$NON-NLS-1$ - private final IResourceLookup resourceLookup; private final IAsyncInvocationProvider asyncInvocationProvider; private final IRuntimeVersionSupport runtimeVersionSupport; private final TypesComputer typesComputer; @Inject - public CodeAfterAsyncCallCheck(IResourceLookup resourceLookup, IRuntimeVersionSupport runtimeVersionSupport, + public CodeAfterAsyncCallCheck(IRuntimeVersionSupport runtimeVersionSupport, IAsyncInvocationProvider asyncInvocationProvider, TypesComputer typesComputer) { super(); - this.resourceLookup = resourceLookup; this.asyncInvocationProvider = asyncInvocationProvider; this.runtimeVersionSupport = runtimeVersionSupport; this.typesComputer = typesComputer; @@ -117,8 +113,7 @@ protected void configureCheck(CheckConfigurer builder) protected void check(Object object, ResultAcceptor resultAceptor, ICheckParameters parameters, IProgressMonitor monitor) { - IProject project = resourceLookup.getProject((EObject)object); - Version version = runtimeVersionSupport.getRuntimeVersion(project); + Version version = runtimeVersionSupport.getRuntimeVersionOrDefault((EObject)object, Version.LATEST); Invocation inv = (Invocation)object; FeatureAccess featureAccess = inv.getMethodAccess(); @@ -126,29 +121,29 @@ protected void check(Object object, ResultAcceptor resultAceptor, ICheckParamete { Collection asyncMethodsNames = asyncInvocationProvider.getAsyncInvocationNames(version); if (asyncMethodsNames.contains(featureAccess.getName()) - && (parameters.getBoolean(PARAMETER_NAME) && isNotifyDescription(inv) - || !parameters.getBoolean(PARAMETER_NAME))) + && (isNotifyDescriptionDefined(inv) || !parameters.getBoolean(PARAMETER_NAME))) { - addIssue(resultAceptor, inv); + checkNeighboringStatement(resultAceptor, inv); } } else if (featureAccess instanceof DynamicFeatureAccess) { Map> names = asyncInvocationProvider.getAsyncTypeMethodNames(version); - if (names.containsKey(featureAccess.getName())) + if (names.containsKey(featureAccess.getName()) + && (isNotifyDescriptionDefined(inv) || !parameters.getBoolean(PARAMETER_NAME))) { Expression source = ((DynamicFeatureAccess)featureAccess).getSource(); List sourceTypes = computeTypes(source); - if (names.get(featureAccess.getName()) - .containsAll(sourceTypes.stream().map(McoreUtil::getTypeName).collect(Collectors.toSet()))) + Collection collection = names.get(featureAccess.getName()); + if (collection.retainAll(sourceTypes.stream().map(McoreUtil::getTypeName).collect(Collectors.toSet()))) { - addIssue(resultAceptor, inv); + checkNeighboringStatement(resultAceptor, inv); } } } } - private boolean isNotifyDescription(Invocation inv) + private boolean isNotifyDescriptionDefined(Invocation inv) { for (Expression param : inv.getParams()) { @@ -174,7 +169,7 @@ private List computeTypes(Expression expression) return List.of(); } - private void addIssue(ResultAcceptor resultAceptor, Invocation inv) + private void checkNeighboringStatement(ResultAcceptor resultAceptor, Invocation inv) { Statement statement = getStatementFromInvoc(inv); if (statement != null && !isPreviousStatementAwait(statement)) @@ -200,36 +195,28 @@ private Statement getStatementFromInvoc(Invocation invocation) private boolean isPreviousStatementAwait(Statement statement) { - Iterator it = EcoreUtil2.getAllContainers(statement).iterator(); - while (it.hasNext()) + EObject container = statement.eContainer(); + List st = getContainer(container); + if (st != null) { - EObject container = it.next(); - if (container instanceof PreprocessorConditional) - { - continue; - } - List st = getContainer(container); - if (st != null) + int index = st.indexOf(statement); + if (index > 0 && index - 1 < st.size()) { - int index = st.indexOf(statement); - if (index > 0 && index - 1 < st.size()) + Statement awaitStatement = st.get(index - 1); + if (awaitStatement instanceof SimpleStatement) { - Statement awaitStatement = st.get(index - 1); - if (awaitStatement instanceof SimpleStatement) + Expression left = ((SimpleStatement)awaitStatement).getLeft(); + if (left instanceof StaticFeatureAccess) { - Expression left = ((SimpleStatement)awaitStatement).getLeft(); - if (left instanceof StaticFeatureAccess) + String name = ((StaticFeatureAccess)left).getName(); + if (STATEMENT_NAME.equalsIgnoreCase(name) || STATEMENT_NAME_RU.equalsIgnoreCase(name)) { - String name = ((StaticFeatureAccess)left).getName(); - if (STATEMENT_NAME.equalsIgnoreCase(name) || STATEMENT_NAME_RU.equalsIgnoreCase(name)) - { - return true; - } + return true; } } - - return false; } + + return false; } } return false; diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/AsyncInvocationProvider.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/AsyncInvocationProvider.java index 806f0c894..488f0d54a 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/AsyncInvocationProvider.java +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/AsyncInvocationProvider.java @@ -15,6 +15,7 @@ import java.util.Collection; import java.util.Iterator; import java.util.Map; +import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; import java.util.concurrent.ConcurrentHashMap; @@ -35,6 +36,7 @@ import com._1c.g5.v8.dt.mcore.Type; import com._1c.g5.v8.dt.mcore.TypeItem; import com._1c.g5.v8.dt.mcore.TypeSet; +import com._1c.g5.v8.dt.mcore.util.Environment; import com._1c.g5.v8.dt.mcore.util.McoreUtil; import com._1c.g5.v8.dt.platform.IEObjectProvider; import com._1c.g5.v8.dt.platform.version.Version; @@ -50,13 +52,14 @@ public class AsyncInvocationProvider implements IAsyncInvocationProvider { - private static final String POSTFIX = "Async"; //$NON-NLS-1$ + private static final String RET_TYPE_NAME = "Promise"; //$NON-NLS-1$ private static final String EXEPTION_NAME = "RunCallback"; //$NON-NLS-1$ private static final String TYPE_NAME = "NotifyDescription"; //$NON-NLS-1$ private final Map> cashNames; private final Map>> cashTypesMethodNames; private final IV8ProjectManager v8ProjectManager; private final BmAwareResourceSetProvider resourceSetProvider; + private final Set clientEnv; @Inject public AsyncInvocationProvider(IV8ProjectManager v8ProjectManager, BmAwareResourceSetProvider resourceSetProvider) @@ -66,43 +69,23 @@ public AsyncInvocationProvider(IV8ProjectManager v8ProjectManager, BmAwareResour this.resourceSetProvider = resourceSetProvider; this.cashNames = new ConcurrentHashMap<>(); this.cashTypesMethodNames = new ConcurrentHashMap<>(); + this.clientEnv = Set.of(Environment.CLIENT, Environment.MNG_CLIENT, Environment.MOBILE_CLIENT, + Environment.MOBILE_THIN_CLIENT, Environment.THIN_CLIENT, Environment.WEB_CLIENT); } @Override public Collection getAsyncInvocationNames(Version version) { - if (cashNames.get(version) == null) - { - synchronized (this) - { - if (cashNames.get(version) != null) - { - return cashNames.get(version); - } - collect(version); - } - } - return cashNames.get(version); + return cashNames.computeIfAbsent(version, this::collectGlobalAsyncMethods); } @Override public Map> getAsyncTypeMethodNames(Version version) { - if (cashTypesMethodNames.get(version) == null) - { - synchronized (this) - { - if (cashTypesMethodNames.get(version) != null) - { - return cashTypesMethodNames.get(version); - } - process(version); - } - } - return cashTypesMethodNames.get(version); + return cashTypesMethodNames.computeIfAbsent(version, this::collectAsyncMethods); } - private void collect(Version version) + private Collection collectGlobalAsyncMethods(Version version) { Collection asyncMethodsNames = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); Iterator iterator = v8ProjectManager.getProjects().iterator(); @@ -116,14 +99,14 @@ private void collect(Version version) EObject object = EcoreUtil.resolve(item.getEObjectOrProxy(), context); if (object instanceof Method) { - collectMethods(asyncMethodsNames, object); + collectMethod(asyncMethodsNames, (Method)object); } } } - cashNames.put(version, asyncMethodsNames); + return asyncMethodsNames; } - private Map> process(Version version) + private Map> collectAsyncMethods(Version version) { Map> asyncMethodsNames = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); Iterator iterator = v8ProjectManager.getProjects().iterator(); @@ -153,8 +136,6 @@ else if (object instanceof TypeSet) } } - cashTypesMethodNames.put(version, asyncMethodsNames); - return asyncMethodsNames; } @@ -173,7 +154,7 @@ private void process(Map> asyncMethodsNames, Type typ for (Method method : contextDef.allMethods()) { - if (method.getName().endsWith(POSTFIX)) + if (isClient(method) && isRetTypePromise(method)) { if (asyncMethodsNames.get(method.getName()) == null) { @@ -188,14 +169,8 @@ private void process(Map> asyncMethodsNames, Type typ } } - private void collectMethods(Collection asyncMethodsNames, EObject object) + private void collectMethod(Collection asyncMethodsNames, Method method) { - if (!(object instanceof Method)) - { - return; - } - - Method method = (Method)object; if (EXEPTION_NAME.equals(method.getName())) { return; @@ -210,7 +185,7 @@ private void collectMethods(Collection asyncMethodsNames, EObject object private boolean isMethodAsync(Method method) { - if (method.getName().endsWith(POSTFIX)) + if (isClient(method) && isRetTypePromise(method)) { return true; } @@ -228,6 +203,30 @@ private boolean isMethodAsync(Method method) return false; } + private boolean isClient(Method method) + { + for (Environment env : method.environments().toArray()) + { + if (!clientEnv.contains(env)) + { + return false; + } + } + return true; + } + + private boolean isRetTypePromise(Method method) + { + for (TypeItem type : method.getRetValType()) + { + if (RET_TYPE_NAME.equals(McoreUtil.getTypeName(type))) + { + return true; + } + } + return false; + } + private boolean isCallbackDescription(Parameter param) { for (TypeItem type : param.getType()) diff --git a/tests/com.e1c.v8codestyle.bsl.itests/src/com/e1c/v8codestyle/bsl/check/itests/CodeAfterAsyncCallCheckTest.java b/tests/com.e1c.v8codestyle.bsl.itests/src/com/e1c/v8codestyle/bsl/check/itests/CodeAfterAsyncCallCheckTest.java index d3b9b5362..f34b40db9 100644 --- a/tests/com.e1c.v8codestyle.bsl.itests/src/com/e1c/v8codestyle/bsl/check/itests/CodeAfterAsyncCallCheckTest.java +++ b/tests/com.e1c.v8codestyle.bsl.itests/src/com/e1c/v8codestyle/bsl/check/itests/CodeAfterAsyncCallCheckTest.java @@ -38,7 +38,7 @@ public class CodeAfterAsyncCallCheckTest extends AbstractSingleModuleTestBase { private static final String CHECK_ID = "code-after-async-call"; //$NON-NLS-1$ - private static final String PARAMETER_NAME = "NotifyDescriptionIsDefined"; //$NON-NLS-1$ + private static final String PARAMETER_NAME = "notifyDescriptionIsDefined"; //$NON-NLS-1$ /** * Instantiates a new code after async call check test. From 24ad506e9e5edc311688b0f7f2c5d17fc98ebdf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=BB=D1=8E=D1=85=D0=B8=D0=BD=20=D0=90=D1=80=D1=82?= =?UTF-8?q?=D0=B5=D0=BC=20=D0=92=D0=B0=D1=81=D0=B8=D0=BB=D1=8C=D0=B5=D0=B2?= =?UTF-8?q?=D0=B8=D1=87?= Date: Wed, 22 Mar 2023 11:33:51 +0300 Subject: [PATCH 22/23] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B7=D0=B0=D0=BC=D0=B5=D1=87?= =?UTF-8?q?=D0=B0=D0=BD=D0=B8=D0=B9=20=D0=B8=20=D0=B4=D0=BE=D0=B1=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=82=D0=B5=D1=81=D1=82?= =?UTF-8?q?=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bsl/check/CodeAfterAsyncCallCheck.java | 37 ++----------- .../resources/async-call-promise.bsl | 12 ++--- .../resources/async-call-promise2.bsl | 8 +++ .../resources/async-call-promise3.bsl | 6 +++ .../resources/async-call-promise4.bsl | 7 +++ .../itests/CodeAfterAsyncCallCheckTest.java | 52 ++++++++++++++++--- 6 files changed, 75 insertions(+), 47 deletions(-) create mode 100644 tests/com.e1c.v8codestyle.bsl.itests/resources/async-call-promise2.bsl create mode 100644 tests/com.e1c.v8codestyle.bsl.itests/resources/async-call-promise3.bsl create mode 100644 tests/com.e1c.v8codestyle.bsl.itests/resources/async-call-promise4.bsl diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java index 0494dcb91..7274b0122 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/CodeAfterAsyncCallCheck.java @@ -24,6 +24,7 @@ import org.eclipse.emf.ecore.EObject; import org.eclipse.xtext.EcoreUtil2; +import com._1c.g5.v8.dt.bsl.model.AwaitStatement; import com._1c.g5.v8.dt.bsl.model.BslPackage; import com._1c.g5.v8.dt.bsl.model.Conditional; import com._1c.g5.v8.dt.bsl.model.DynamicFeatureAccess; @@ -36,7 +37,6 @@ import com._1c.g5.v8.dt.bsl.model.PreprocessorConditional; import com._1c.g5.v8.dt.bsl.model.PreprocessorItemStatements; import com._1c.g5.v8.dt.bsl.model.ReturnStatement; -import com._1c.g5.v8.dt.bsl.model.SimpleStatement; import com._1c.g5.v8.dt.bsl.model.Statement; import com._1c.g5.v8.dt.bsl.model.StaticFeatureAccess; import com._1c.g5.v8.dt.bsl.model.TryExceptStatement; @@ -68,8 +68,6 @@ public final class CodeAfterAsyncCallCheck extends BasicCheck { - private static final String STATEMENT_NAME_RU = "Ждать"; //$NON-NLS-1$ - private static final String STATEMENT_NAME = "Await"; //$NON-NLS-1$ private static final String CHECK_ID = "code-after-async-call"; //$NON-NLS-1$ private static final String DEFAULT_CHECK = Boolean.toString(Boolean.TRUE); private static final String PARAMETER_NAME = "notifyDescriptionIsDefined"; //$NON-NLS-1$ @@ -172,11 +170,11 @@ private List computeTypes(Expression expression) private void checkNeighboringStatement(ResultAcceptor resultAceptor, Invocation inv) { Statement statement = getStatementFromInvoc(inv); - if (statement != null && !isPreviousStatementAwait(statement)) + if (statement != null && !(statement instanceof AwaitStatement)) { statement = getNextStatement(statement); if (statement != null && !(statement instanceof ReturnStatement) - && !(statement instanceof EmptyStatement)) + && !(statement instanceof EmptyStatement) && !(statement instanceof AwaitStatement)) { resultAceptor.addIssue(Messages.CodeAfterAsyncCallCheck_Issue, statement); } @@ -193,35 +191,6 @@ private Statement getStatementFromInvoc(Invocation invocation) return container instanceof Statement ? (Statement)container : null; } - private boolean isPreviousStatementAwait(Statement statement) - { - EObject container = statement.eContainer(); - List st = getContainer(container); - if (st != null) - { - int index = st.indexOf(statement); - if (index > 0 && index - 1 < st.size()) - { - Statement awaitStatement = st.get(index - 1); - if (awaitStatement instanceof SimpleStatement) - { - Expression left = ((SimpleStatement)awaitStatement).getLeft(); - if (left instanceof StaticFeatureAccess) - { - String name = ((StaticFeatureAccess)left).getName(); - if (STATEMENT_NAME.equalsIgnoreCase(name) || STATEMENT_NAME_RU.equalsIgnoreCase(name)) - { - return true; - } - } - } - - return false; - } - } - return false; - } - private Statement getNextStatement(Statement statement) { Iterator it = EcoreUtil2.getAllContainers(statement).iterator(); diff --git a/tests/com.e1c.v8codestyle.bsl.itests/resources/async-call-promise.bsl b/tests/com.e1c.v8codestyle.bsl.itests/resources/async-call-promise.bsl index c708618e3..acfeb509c 100644 --- a/tests/com.e1c.v8codestyle.bsl.itests/resources/async-call-promise.bsl +++ b/tests/com.e1c.v8codestyle.bsl.itests/resources/async-call-promise.bsl @@ -1,9 +1,7 @@ -&НаКлиенте -Процедура Тест() - - Текст = "Текст предупреждения"; - Ждать ПредупреждениеАсинх(Текст); - Сообщить("Закрыли предупреждение"); - +Асинх Процедура Тест1(Параметры) + + Ждать ВопросАсинх(Параметры,); + Сообщить("Закрыли предупреждение"); + КонецПроцедуры \ No newline at end of file diff --git a/tests/com.e1c.v8codestyle.bsl.itests/resources/async-call-promise2.bsl b/tests/com.e1c.v8codestyle.bsl.itests/resources/async-call-promise2.bsl new file mode 100644 index 000000000..64638c9ec --- /dev/null +++ b/tests/com.e1c.v8codestyle.bsl.itests/resources/async-call-promise2.bsl @@ -0,0 +1,8 @@ + +Асинх Процедура Тест2(Параметры) + + Обещание = ПредупреждениеАсинх(Параметры); + Ждать Обещание; + Сообщить("Закрыли предупреждение"); + +КонецПроцедуры \ No newline at end of file diff --git a/tests/com.e1c.v8codestyle.bsl.itests/resources/async-call-promise3.bsl b/tests/com.e1c.v8codestyle.bsl.itests/resources/async-call-promise3.bsl new file mode 100644 index 000000000..05f172745 --- /dev/null +++ b/tests/com.e1c.v8codestyle.bsl.itests/resources/async-call-promise3.bsl @@ -0,0 +1,6 @@ + +Асинх Функция Тест3(Параметры) + + Возврат Ждать ПредупреждениеАсинх(Параметры); + +КонецФункции \ No newline at end of file diff --git a/tests/com.e1c.v8codestyle.bsl.itests/resources/async-call-promise4.bsl b/tests/com.e1c.v8codestyle.bsl.itests/resources/async-call-promise4.bsl new file mode 100644 index 000000000..49e79a2c5 --- /dev/null +++ b/tests/com.e1c.v8codestyle.bsl.itests/resources/async-call-promise4.bsl @@ -0,0 +1,7 @@ + +Асинх Функция Тест4(Параметры) + + Обещание = ПредупреждениеАсинх(Параметры); + Возврат Ждать Обещание; + +КонецФункции \ No newline at end of file diff --git a/tests/com.e1c.v8codestyle.bsl.itests/src/com/e1c/v8codestyle/bsl/check/itests/CodeAfterAsyncCallCheckTest.java b/tests/com.e1c.v8codestyle.bsl.itests/src/com/e1c/v8codestyle/bsl/check/itests/CodeAfterAsyncCallCheckTest.java index f34b40db9..6789b20a0 100644 --- a/tests/com.e1c.v8codestyle.bsl.itests/src/com/e1c/v8codestyle/bsl/check/itests/CodeAfterAsyncCallCheckTest.java +++ b/tests/com.e1c.v8codestyle.bsl.itests/src/com/e1c/v8codestyle/bsl/check/itests/CodeAfterAsyncCallCheckTest.java @@ -51,12 +51,7 @@ public CodeAfterAsyncCallCheckTest() @Test public void testCodeAfterExistence() throws Exception { - IDtProject dtProject = getProject(); - IProject project = dtProject.getWorkspaceProject(); - ICheckSettings settings = checkRepository.getSettings(new CheckUid(CHECK_ID, BslPlugin.PLUGIN_ID), project); - settings.getParameters().get(PARAMETER_NAME).setValue(Boolean.toString(Boolean.FALSE)); - checkRepository.applyChanges(Collections.singleton(settings), project); - waitForDD(dtProject); + setParameterValue(Boolean.FALSE); updateModule(FOLDER_RESOURCE + "code-after-async-call-existence.bsl"); @@ -77,12 +72,47 @@ public void testCallBackDescriptionCompliant() throws Exception @Test public void testPromiseCompliant() throws Exception { + setParameterValue(Boolean.FALSE); + updateModule(FOLDER_RESOURCE + "async-call-promise.bsl"); Marker marker = getFirstMarker(CHECK_ID, getModuleId(), getProject()); assertNull(marker); } + @Test + public void testPromiseCompliant2() throws Exception + { + setParameterValue(Boolean.FALSE); + + updateModule(FOLDER_RESOURCE + "async-call-promise2.bsl"); + + Marker marker = getFirstMarker(CHECK_ID, getModuleId(), getProject()); + assertNull(marker); + } + + @Test + public void testPromiseCompliant3() throws Exception + { + setParameterValue(Boolean.FALSE); + + updateModule(FOLDER_RESOURCE + "async-call-promise3.bsl"); + + Marker marker = getFirstMarker(CHECK_ID, getModuleId(), getProject()); + assertNull(marker); + } + + @Test + public void testPromiseComplian4() throws Exception + { + setParameterValue(Boolean.FALSE); + + updateModule(FOLDER_RESOURCE + "async-call-promise4.bsl"); + + Marker marker = getFirstMarker(CHECK_ID, getModuleId(), getProject()); + assertNull(marker); + } + @Test public void testSpreadsheetDocumentNonCompliant() throws Exception { @@ -92,4 +122,14 @@ public void testSpreadsheetDocumentNonCompliant() throws Exception assertNotNull(marker); assertEquals("8", marker.getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_LINE_KEY)); } + + private void setParameterValue(Boolean value) + { + IDtProject dtProject = getProject(); + IProject project = dtProject.getWorkspaceProject(); + ICheckSettings settings = checkRepository.getSettings(new CheckUid(CHECK_ID, BslPlugin.PLUGIN_ID), project); + settings.getParameters().get(PARAMETER_NAME).setValue(Boolean.toString(value)); + checkRepository.applyChanges(Collections.singleton(settings), project); + waitForDD(dtProject); + } } From 600bc10d48c8d78005c2e4b192abeb9d9f793655 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=BB=D1=8E=D1=85=D0=B8=D0=BD=20=D0=90=D1=80=D1=82?= =?UTF-8?q?=D0=B5=D0=BC=20=D0=92=D0=B0=D1=81=D0=B8=D0=BB=D1=8C=D0=B5=D0=B2?= =?UTF-8?q?=D0=B8=D1=87?= Date: Wed, 22 Mar 2023 11:37:17 +0300 Subject: [PATCH 23/23] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=84=D0=BE=D1=80=D0=BC=D0=B0?= =?UTF-8?q?=D1=82=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=20=D1=84?= =?UTF-8?q?=D0=B0=D0=B9=D0=BB=D0=B0=20=D1=81=D0=B2=D0=BE=D0=B9=D1=81=D1=82?= =?UTF-8?q?=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../v8codestyle/bsl/check/messages.properties | 34 +++++++++---------- .../bsl/check/messages_ru.properties | 22 ++++++------ 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages.properties b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages.properties index 138767231..e751b369d 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages.properties +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages.properties @@ -62,13 +62,13 @@ ChangeAndValidateInsteadOfAroundCheck_description = Checks that pragma &ChangeAn ChangeAndValidateInsteadOfAroundCheck_title = Use pragma &ChangeAndValidate instead of &Around -CodeAfterAsyncCallCheck_Description=Checks that the asynchronous method is not followed by lines of code, since in this case the specified lines of code are executed immediately, without waiting for the asynchronous method to execute +CodeAfterAsyncCallCheck_Description = Checks that the asynchronous method is not followed by lines of code, since in this case the specified lines of code are executed immediately, without waiting for the asynchronous method to execute -CodeAfterAsyncCallCheck_Issue=The asynchronous method is followed by lines of code +CodeAfterAsyncCallCheck_Issue = The asynchronous method is followed by lines of code -CodeAfterAsyncCallCheck_Parameter=Only with the defined parameter NotifyDescription, if applicable +CodeAfterAsyncCallCheck_Parameter = Only with the defined parameter NotifyDescription, if applicable -CodeAfterAsyncCallCheck_Title=The code should not follow an asynchronous call +CodeAfterAsyncCallCheck_Title = The code should not follow an asynchronous call CommitTransactionCheck_Commit_transaction_must_be_in_try_catch = Commit transaction must be in a try-catch @@ -154,6 +154,12 @@ ExportMethodInCommandModule_Do_not_emded_export_method_in_modules_of_command_res ExportMethodInCommandModule_Do_not_use_export_method_in_commands_module = Restrictions on the use of export procedures and functions +ExportProcedureMissingCommentCheck_Export_procedure_missing_comment = Export procedure (function) "{0}" should be described by adding comment + +ExportProcedureMissingCommentCheck_description = Export procedure (function) should be described by adding comment + +ExportProcedureMissingCommentCheck_title = Export procedure (function) should be described by adding comment + ExportVariableInObjectModuleCheck_Description = Use of an export variable is not recommended ExportVariableInObjectModuleCheck_Issue = It's not recommended to use the export variable in the object module @@ -164,12 +170,6 @@ ExtensionMethodPrefixCheck_Description = The procedure (function) in the module ExtensionMethodPrefixCheck_Ext_method__0__should_have__1__prefix = The method "{0}" should have "{1}" prefix -ExportProcedureMissingCommentCheck_description=Export procedure (function) should be described by adding comment - -ExportProcedureMissingCommentCheck_Export_procedure_missing_comment=Export procedure (function) "{0}" should be described by adding comment - -ExportProcedureMissingCommentCheck_title=Export procedure (function) should be described by adding comment - ExtensionMethodPrefixCheck_Title = Extension method does not have extension prefix ExtensionVariablePrefixCheck_Description = The variable in the module of the extension object does not have a prefix corresponding to the prefix of the extension itself @@ -472,16 +472,16 @@ UseNonRecommendedMethods_parameter = List of non-recommended methods UseNonRecommendedMethods_title = Using non-recommended methods -VariableNameInvalidCheck_description=Variable name is invalid +VariableNameInvalidCheck_description = Variable name is invalid -VariableNameInvalidCheck_message_variable_length_is_less_than=variable length is less than {0} +VariableNameInvalidCheck_message_variable_length_is_less_than = variable length is less than {0} -VariableNameInvalidCheck_param_MIN_NAME_LENGTH_PARAM_title=Min. lenght of variable name +VariableNameInvalidCheck_param_MIN_NAME_LENGTH_PARAM_title = Min. lenght of variable name -VariableNameInvalidCheck_title=Variable name is invalid +VariableNameInvalidCheck_title = Variable name is invalid -VariableNameInvalidCheck_variable_name_is_invalid=Variable name {0} is invalid: {1} +VariableNameInvalidCheck_variable_name_is_invalid = Variable name {0} is invalid: {1} -VariableNameInvalidCheck_variable_name_must_start_with_a_capital_letter=variable name must start with a capital letter +VariableNameInvalidCheck_variable_name_must_start_with_a_capital_letter = variable name must start with a capital letter -VariableNameInvalidCheck_variable_name_starts_with_an_underline=variable name starts with an underline \ No newline at end of file +VariableNameInvalidCheck_variable_name_starts_with_an_underline = variable name starts with an underline diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages_ru.properties b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages_ru.properties index 970cf6b87..cad31d2a2 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages_ru.properties +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages_ru.properties @@ -62,13 +62,13 @@ ChangeAndValidateInsteadOfAroundCheck_description = Проверяет, что ChangeAndValidateInsteadOfAroundCheck_title = Используется аннотация &ИзменениеИКонтроль вместо &Вместо -CodeAfterAsyncCallCheck_Description=Проверяет, что за асинхронным методом не следуют строки кода, поскольку в этом случае указанные строки кода выполняются немедленно, не дожидаясь выполнения асинхронного метода +CodeAfterAsyncCallCheck_Description = Проверяет, что за асинхронным методом не следуют строки кода, поскольку в этом случае указанные строки кода выполняются немедленно, не дожидаясь выполнения асинхронного метода -CodeAfterAsyncCallCheck_Issue=За асинхронным методом следуют строки кода +CodeAfterAsyncCallCheck_Issue = За асинхронным методом следуют строки кода -CodeAfterAsyncCallCheck_Title=Код не должен следовать за асинхронным вызовом +CodeAfterAsyncCallCheck_Parameter = Tолько с заданным параметром ОписаниеОповещения, если применимо -CodeAfterAsyncCallCheck_Parameter=Tолько с заданным параметром ОписаниеОповещения, если применимо +CodeAfterAsyncCallCheck_Title = Код не должен следовать за асинхронным вызовом CommitTransactionCheck_Commit_transaction_must_be_in_try_catch = Вызов "ЗафиксироватьТранзакцию()" находится вне конструкции "Попытка... Исключение" @@ -154,6 +154,12 @@ ExportMethodInCommandModule_Do_not_emded_export_method_in_modules_of_command_res ExportMethodInCommandModule_Do_not_use_export_method_in_commands_module = Ограничения на использование экспортных процедур и функций +ExportProcedureMissingCommentCheck_Export_procedure_missing_comment = Отсутствует комментарий к экспортной процедуре (функции) "{0}" + +ExportProcedureMissingCommentCheck_description = Отсутствует комментарий к экспортной процедуре (функции) + +ExportProcedureMissingCommentCheck_title = Отсутствует комментарий к экспортной процедуре (функции) + ExportVariableInObjectModuleCheck_Description = Использование экспортной переменной не рекомендовано ExportVariableInObjectModuleCheck_Issue = Не рекомендуется использовать экспортную переменную в модуле объекта @@ -170,12 +176,6 @@ ExtensionVariablePrefixCheck_Description = Переменная модуля р ExtensionVariablePrefixCheck_Title = Переменная расширения должна содержать в имени префикс расширения -ExportProcedureMissingCommentCheck_description=Отсутствует комментарий к экспортной процедуре (функции) - -ExportProcedureMissingCommentCheck_Export_procedure_missing_comment=Отсутствует комментарий к экспортной процедуре (функции) "{0}" - -ExportProcedureMissingCommentCheck_title=Отсутствует комментарий к экспортной процедуре (функции) - ExtensionVariablePrefixCheck_Variable_0_should_have_1_prefix = Переменная "{0}" должна иметь префикс "{1}" FormDataToValueCheck_Description = Использование ДанныеФормыВЗначение вместо РеквизитФормыВЗначение @@ -484,4 +484,4 @@ VariableNameInvalidCheck_variable_name_is_invalid = Имя переменной VariableNameInvalidCheck_variable_name_must_start_with_a_capital_letter = имя переменной должно начинаться с заглавной буквы -VariableNameInvalidCheck_variable_name_starts_with_an_underline = имя переменной начинается с символа подчеркивания \ No newline at end of file +VariableNameInvalidCheck_variable_name_starts_with_an_underline = имя переменной начинается с символа подчеркивания