mirror of
https://github.com/1C-Company/v8-code-style.git
synced 2024-11-28 09:33:06 +02:00
parent
926daee909
commit
dcf348df9d
12
CHANGELOG.md
12
CHANGELOG.md
@ -33,10 +33,22 @@
|
||||
- Проверка конструктора структуры содержащего больше 3х ключей
|
||||
- Выполнение запроса в цикле с учетом локальных вызовов в модуле
|
||||
- Проверка ОбменДанными.Загрузка в обработчике события
|
||||
- Система строгой типизации кода:
|
||||
- Переменная имеет тип значения
|
||||
- Параметр метода имеет тип
|
||||
- Функция возвращает типизированное значение
|
||||
- Утверждение меняет тип
|
||||
- Типизация значений в конструкторе структуры
|
||||
- Вызываеемый тип пересекается с типом параметра
|
||||
- Секция возвращаемого значения функции-конструктора данных
|
||||
- Свойство объекта имеет тип возвращаемого значения
|
||||
- Метод в объекте не найден
|
||||
- Поле документирующего комментария имеет описание типа
|
||||
- Конструкция "Попытка...Исключение...КонецПопытки" не содержит кода в исключении
|
||||
- Аннотация для метода написана канонически
|
||||
- Используется аннотация &ИзменениеИКонтроль вместо &Вместо
|
||||
|
||||
|
||||
#### Запросы
|
||||
|
||||
- Временная таблица должна содержать индексы
|
||||
|
@ -15,12 +15,16 @@ 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.bsl.comment;version="[3.0.0,4.0.0)",
|
||||
com._1c.g5.v8.dt.bsl.common;version="[6.0.0,7.0.0)",
|
||||
com._1c.g5.v8.dt.bsl.documentation.comment;version="[3.0.0,4.0.0)",
|
||||
com._1c.g5.v8.dt.bsl.model;version="[4.0.0,5.0.0)",
|
||||
com._1c.g5.v8.dt.bsl.model.util;version="[4.6.0,5.0.0)",
|
||||
com._1c.g5.v8.dt.bsl.model.util;version="[4.0.0,5.0.0)",
|
||||
com._1c.g5.v8.dt.bsl.resource;version="[13.0.0,14.0.0)",
|
||||
com._1c.g5.v8.dt.bsl.typesystem;version="[9.0.0,10.0.0)",
|
||||
com._1c.g5.v8.dt.bsl.typesystem.util;version="[9.0.0,10.0.0)",
|
||||
com._1c.g5.v8.dt.bsl.util;version="[7.0.0,8.0.0)",
|
||||
com._1c.g5.v8.dt.core.platform;version="[10.0.0,11.0.0)",
|
||||
com._1c.g5.v8.dt.lcore.util;version="[2.0.0,3.0.0)",
|
||||
com._1c.g5.v8.dt.mcore;version="[6.0.0,7.0.0)",
|
||||
com._1c.g5.v8.dt.mcore.util;version="[3.6.0,4.0.0)",
|
||||
@ -33,3 +37,4 @@ Import-Package: com._1c.g5.v8.bm.core;version="[7.0.0,8.0.0)",
|
||||
com.e1c.g5.v8.dt.check;version="[1.0.0,2.0.0)",
|
||||
com.e1c.g5.v8.dt.check.components;version="[1.0.0,2.0.0)",
|
||||
com.e1c.g5.v8.dt.check.settings;version="[1.0.0,2.0.0)"
|
||||
Export-Package: com.e1c.v8codestyle.bsl.strict;version="0.1.0"
|
||||
|
@ -0,0 +1,10 @@
|
||||
# Data constructor function return section
|
||||
|
||||
Check of module strict types system that return statements of function equals documentation comment return section types
|
||||
|
||||
## Noncompliant Code Example
|
||||
|
||||
## Compliant Solution
|
||||
|
||||
## See
|
||||
|
@ -0,0 +1,10 @@
|
||||
# Documentation comment Field has no type defenition
|
||||
|
||||
Check of module strict types system that documentation comment field has section with types
|
||||
|
||||
## Noncompliant Code Example
|
||||
|
||||
## Compliant Solution
|
||||
|
||||
## See
|
||||
|
@ -0,0 +1,10 @@
|
||||
# Method not found in accessed object
|
||||
|
||||
Check that dynamicly accessed method exist in the object
|
||||
|
||||
## Noncompliant Code Example
|
||||
|
||||
## Compliant Solution
|
||||
|
||||
## See
|
||||
|
@ -0,0 +1,10 @@
|
||||
# Function reuturns typed value
|
||||
|
||||
Check of module strict types system that every function has return value type
|
||||
|
||||
## Noncompliant Code Example
|
||||
|
||||
## Compliant Solution
|
||||
|
||||
## See
|
||||
|
@ -0,0 +1,10 @@
|
||||
# Invocation parameter types intersects
|
||||
|
||||
Check of module strict types system that invocation expression has intercection with invocation parameter type
|
||||
|
||||
## Noncompliant Code Example
|
||||
|
||||
## Compliant Solution
|
||||
|
||||
## See
|
||||
|
@ -0,0 +1,10 @@
|
||||
# Method parameter has value type
|
||||
|
||||
Check of module strict types system that every method parameter has value type
|
||||
|
||||
## Noncompliant Code Example
|
||||
|
||||
## Compliant Solution
|
||||
|
||||
## See
|
||||
|
@ -0,0 +1,10 @@
|
||||
# Object property has return value type
|
||||
|
||||
Check of module strict types system that dynamicly accessed object property has reutun type
|
||||
|
||||
## Noncompliant Code Example
|
||||
|
||||
## Compliant Solution
|
||||
|
||||
## See
|
||||
|
@ -0,0 +1,10 @@
|
||||
# Секция возвращаемого значения функции-конструктора данных
|
||||
|
||||
Система строгой типизации кода проверяет что поле документирующего комментария имеет описание типа
|
||||
|
||||
## Неправильно
|
||||
|
||||
## Правильно
|
||||
|
||||
## См.
|
||||
|
@ -0,0 +1,10 @@
|
||||
# Поле документирующего комментария имеет описание типа
|
||||
|
||||
Система строгой типизации кода проверяет что поле документирующего комментария имеет описание типа
|
||||
|
||||
## Неправильно
|
||||
|
||||
## Правильно
|
||||
|
||||
## См.
|
||||
|
@ -0,0 +1,10 @@
|
||||
# Метод в объекте не найден
|
||||
|
||||
Система строгой типизации кода проверяет что динамически вызываемый метод существует в объекте
|
||||
|
||||
## Неправильно
|
||||
|
||||
## Правильно
|
||||
|
||||
## См.
|
||||
|
@ -0,0 +1,10 @@
|
||||
# Функция возвращает типизированное значение
|
||||
|
||||
Система строгой типизации кода проверяет что каждая функция возвращает типизированное значение
|
||||
|
||||
## Неправильно
|
||||
|
||||
## Правильно
|
||||
|
||||
## См.
|
||||
|
@ -0,0 +1,10 @@
|
||||
# Вызываеемый тип пересекается с типом параметра
|
||||
|
||||
Система строгой типизации кода проверяет что тип вызываемого выражения пересекается с типом параметра вызываемого метода
|
||||
|
||||
## Неправильно
|
||||
|
||||
## Правильно
|
||||
|
||||
## См.
|
||||
|
@ -0,0 +1,10 @@
|
||||
# Параметр метода имеет тип
|
||||
|
||||
Система строгой типизации кода проверяет что каждый параметр метода имеет тип значения
|
||||
|
||||
## Неправильно
|
||||
|
||||
## Правильно
|
||||
|
||||
## См.
|
||||
|
@ -0,0 +1,10 @@
|
||||
# Свойство объекта имеет тип возвращаемого значения
|
||||
|
||||
Система строгой типизации кода проверяет что динамическое свойство объекта имеет тип возвращаемого значения
|
||||
|
||||
## Неправильно
|
||||
|
||||
## Правильно
|
||||
|
||||
## См.
|
||||
|
@ -0,0 +1,10 @@
|
||||
# Утверждение меняет тип
|
||||
|
||||
Система строгой типизации кода проверяет что утверждение (строка присвоения значения) меняет тип
|
||||
|
||||
## Неправильно
|
||||
|
||||
## Правильно
|
||||
|
||||
## См.
|
||||
|
@ -0,0 +1,45 @@
|
||||
# Типизация значений в конструкторе структуры
|
||||
|
||||
Проверяет строковый литерал в конструкторе структуры что каждый ключ имеет типзированное значение.
|
||||
|
||||
## Неправильно
|
||||
|
||||
Ключи структуры инициализируются без какого-либо значения по умолчанию что устанавливает пустой тип значения для ключа структуры на всё время жизни.
|
||||
|
||||
```bsl
|
||||
// @strict-types
|
||||
|
||||
Процедура Тест() Экспорт
|
||||
|
||||
Параметры = новый Структура("Ключ1, Ключ2, Ключ3");
|
||||
// некоторый код...
|
||||
|
||||
Параметры.Ключ1 = 1345;
|
||||
Параметры.Ключ2 = "New vlaue";
|
||||
Параметры.Ключ3 = Справочники.Товары.Service;
|
||||
|
||||
КонецПроцедуры
|
||||
```
|
||||
|
||||
## Правильно
|
||||
|
||||
Инициализируйте ключи структуры с типизированным значением по умолчанию в конструкторе или вставляйте новый ключ с типизированным значением по умолчанию.
|
||||
|
||||
```bsl
|
||||
// @strict-types
|
||||
|
||||
Процедура Тест() Экспорт
|
||||
|
||||
Параметры = новый Структура("Ключ1, Ключ2", 0, "");
|
||||
Параметры.Вставить("Ключ3", Справочники.Товары.ПустаяСсылка());
|
||||
// некоторый код...
|
||||
|
||||
Параметры.Ключ1 = 1345;
|
||||
Параметры.Ключ2 = "New vlaue";
|
||||
Параметры.Ключ3 = Справочники.Товары.Услуга;
|
||||
|
||||
КонецПроцедуры
|
||||
```
|
||||
|
||||
## См.
|
||||
|
@ -0,0 +1,105 @@
|
||||
# Переменная имеет тип значения
|
||||
|
||||
Система строгой типизации кода проверяет что каждая переменная имеет тип значения
|
||||
|
||||
## Неправильно
|
||||
|
||||
Обявляемая локальная переменная в методе:
|
||||
|
||||
```bsl
|
||||
// @strict-types
|
||||
|
||||
Процедура Тест() Экспорт
|
||||
Перем ТестПеременная;
|
||||
|
||||
// здесь код
|
||||
КонецПроцедуры
|
||||
```
|
||||
|
||||
Объявляемая переменная в модуле объекта и скрытая инициализация в каком-то методе:
|
||||
|
||||
```bsl
|
||||
// @strict-types
|
||||
|
||||
Перем ПараметрыОбъекта;
|
||||
|
||||
Процедура ПередЗаписью(Отказ)
|
||||
|
||||
Если ОбменДанными.Загрузка Тогда
|
||||
Возврат;
|
||||
КонецЕсли;
|
||||
|
||||
ПараметрыОбъекта = НовыеПараметрыОбъекта();
|
||||
|
||||
Если ЗначениеЗаполнено(ПараметрыОбъекта.Парам1) Тогда
|
||||
// здесь код
|
||||
КонецЕсли;
|
||||
|
||||
КонецПроцедуры
|
||||
|
||||
// Возвращаемое значение:
|
||||
// Структура:
|
||||
// * Парам1 - Строка -
|
||||
Функция НовыеПараметрыОбъекта()
|
||||
|
||||
Параметры = Новый Структура();
|
||||
Параметры.Вставить("Парам1", "Строковое значение");
|
||||
|
||||
Возврат Параметры;
|
||||
|
||||
КонецФункции
|
||||
```
|
||||
|
||||
## Правильно
|
||||
|
||||
Инициализируйте локальную переменную с пустым значением по умолчанию:
|
||||
|
||||
```bsl
|
||||
// @strict-types
|
||||
|
||||
Процедура Тест() Экспорт
|
||||
ТестПеременная = 0;
|
||||
|
||||
// code here
|
||||
КонецПроцедуры
|
||||
```
|
||||
|
||||
Инициализируйте переменную модуля значением по умоланию в коде модуля и типизируйте строчным типизирующим комментарим в месте определения переменной.
|
||||
|
||||
```bsl
|
||||
// @strict-types
|
||||
|
||||
Перем ПараметрыОбъекта; // См. НовыеПараметрыОбъекта
|
||||
|
||||
|
||||
Процедура ПередЗаписью(Отказ)
|
||||
|
||||
Если ОбменДанными.Загрузка Тогда
|
||||
Возврат;
|
||||
КонецЕсли;
|
||||
|
||||
Если ЗначениеЗаполнено(ПараметрыОбъекта.Парам1) Тогда
|
||||
// code here
|
||||
КонецЕсли;
|
||||
|
||||
КонецПроцедуры
|
||||
|
||||
|
||||
// Возвращаемое значение:
|
||||
// Структура:
|
||||
// * Парам1 - Строка -
|
||||
Функция НовыеПараметрыОбъекта()
|
||||
|
||||
Параметры = Новый Структура();
|
||||
Параметры.Вставить("Парам1", "String value");
|
||||
|
||||
Возврат Параметры;
|
||||
|
||||
КонецФункции
|
||||
|
||||
// Обязательная инициализация значения в коде модуля
|
||||
ПараметрыОбъекта = НовыеПараметрыОбъекта();
|
||||
```
|
||||
|
||||
## См.
|
||||
|
@ -0,0 +1,10 @@
|
||||
# Statement type change
|
||||
|
||||
Check of module strict types system that statement does not change type
|
||||
|
||||
## Noncompliant Code Example
|
||||
|
||||
## Compliant Solution
|
||||
|
||||
## See
|
||||
|
@ -0,0 +1,45 @@
|
||||
# Structure contstructor value types
|
||||
|
||||
Checks Structure constructor string literal that each key has typed value.
|
||||
|
||||
## Noncompliant Code Example
|
||||
|
||||
Structure keys initalizing without any default value that set empty types for the structure key for lifetime.
|
||||
|
||||
```bsl
|
||||
// @strict-types
|
||||
|
||||
Procedure Test() Export
|
||||
|
||||
Params = new Structure("Key1, Key2, Key3");
|
||||
// some code...
|
||||
|
||||
Params.Key1 = 1345;
|
||||
Params.Key2 = "New vlaue";
|
||||
Params.Key3 = Catalogs.Products.Service;
|
||||
|
||||
EndProcedure
|
||||
```
|
||||
|
||||
## Compliant Solution
|
||||
|
||||
Initialize structure keys with default typed values in the constructor or insert new key with default typed value.
|
||||
|
||||
```bsl
|
||||
// @strict-types
|
||||
|
||||
Procedure Test() Export
|
||||
|
||||
Params = new Structure("Key1, Key2", 0, "");
|
||||
Params.Insert("Key3", Catalogs.Products.EmptyRef());
|
||||
// some code...
|
||||
|
||||
Params.Key1 = 1345;
|
||||
Params.Key2 = "New vlaue";
|
||||
Params.Key3 = Catalogs.Products.Service;
|
||||
|
||||
EndProcedure
|
||||
```
|
||||
|
||||
## See
|
||||
|
105
bundles/com.e1c.v8codestyle.bsl/markdown/variable-value-type.md
Normal file
105
bundles/com.e1c.v8codestyle.bsl/markdown/variable-value-type.md
Normal file
@ -0,0 +1,105 @@
|
||||
# Variable has value type
|
||||
|
||||
Check of module strict types system that every variable has value type
|
||||
|
||||
## Noncompliant Code Example
|
||||
|
||||
Declared local variable in method:
|
||||
|
||||
```bsl
|
||||
// @strict-types
|
||||
|
||||
Procedure Test() Export
|
||||
Var TestVar;
|
||||
|
||||
// code here
|
||||
EndProcedure
|
||||
```
|
||||
|
||||
Declared variable in object module and hidden initialization in some method:
|
||||
|
||||
```bsl
|
||||
// @strict-types
|
||||
|
||||
Var ObjectParameters;
|
||||
|
||||
Procedure BeforeWrite(Cancel)
|
||||
|
||||
If DataExchange.Load Then
|
||||
Return;
|
||||
EndIf;
|
||||
|
||||
ObjectParameters = NewObjectParameters();
|
||||
|
||||
If ValueIsFilled(ObjectParameters.Param1) Then
|
||||
// code here
|
||||
EndIf;
|
||||
|
||||
EndProcedure
|
||||
|
||||
// Returns:
|
||||
// Structure:
|
||||
// * Param1 - String -
|
||||
Function NewObjectParameters()
|
||||
|
||||
Params = New Structure();
|
||||
Params.Insert("Param1", "String value");
|
||||
|
||||
return Params;
|
||||
|
||||
EndFunction
|
||||
```
|
||||
|
||||
## Compliant Solution
|
||||
|
||||
Initialize local variable with default empty value:
|
||||
|
||||
```bsl
|
||||
// @strict-types
|
||||
|
||||
Procedure Test() Export
|
||||
TestVar = 0;
|
||||
|
||||
// code here
|
||||
EndProcedure
|
||||
```
|
||||
|
||||
Initialize module variable with default value in module statements and add typed in-line documentation comments for variable declaration.
|
||||
|
||||
```bsl
|
||||
// @strict-types
|
||||
|
||||
Var ObjectParameters; // see NewObjectParameters
|
||||
|
||||
|
||||
Procedure BeforeWrite(Cancel)
|
||||
|
||||
If DataExchange.Load Then
|
||||
Return;
|
||||
EndIf;
|
||||
|
||||
If ValueIsFilled(ObjectParameters.Param1) Then
|
||||
// code here
|
||||
EndIf;
|
||||
|
||||
EndProcedure
|
||||
|
||||
|
||||
// Returns:
|
||||
// Structure:
|
||||
// * Param1 - String -
|
||||
Function NewObjectParameters()
|
||||
|
||||
Params = New Structure();
|
||||
Params.Insert("Param1", "String value");
|
||||
|
||||
Return Params;
|
||||
|
||||
EndFunction
|
||||
|
||||
// Explicitly initialize value in module statements
|
||||
ObjectParameters = NewObjectParameters();
|
||||
```
|
||||
|
||||
## See
|
||||
|
@ -15,4 +15,6 @@ providerName = 1C-Soft LLC
|
||||
pluginName = 1C:Code style V8 Bsl plugin
|
||||
|
||||
category.bsl.title = Built-in script language
|
||||
category.bls.description = Checks of 1C:Enterprise build-in module language by 1C:Development standard (code style)
|
||||
category.bsl.description = Checks of 1C:Enterprise build-in module language by 1C:Development standard (code style)
|
||||
category.bsl.strict.title = Strict types system
|
||||
category.bsl.strict.description = Checks of 1C:Enterprise build-in module language that each object strictly typed
|
||||
|
@ -20,11 +20,16 @@
|
||||
|
||||
<category
|
||||
category="com.e1c.v8codestyle"
|
||||
description="%category.bls.description"
|
||||
description="%category.bsl.description"
|
||||
id="com.e1c.v8codestyle.bsl"
|
||||
title="%category.bsl.title">
|
||||
</category>
|
||||
|
||||
<category
|
||||
category="com.e1c.v8codestyle.bsl"
|
||||
description="%category.bsl.strict.description"
|
||||
id="com.e1c.v8codestyle.bsl.strict"
|
||||
title="%category.bsl.strict.title">
|
||||
</category>
|
||||
<check
|
||||
category="com.e1c.v8codestyle.bsl"
|
||||
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.check.StructureCtorTooManyKeysCheck">
|
||||
@ -49,6 +54,48 @@
|
||||
category="com.e1c.v8codestyle.bsl"
|
||||
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.check.ChangeAndValidateInsteadOfAroundCheck">
|
||||
</check>
|
||||
<check
|
||||
category="com.e1c.v8codestyle.bsl.strict"
|
||||
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.strict.check.MethodParamTypeCheck">
|
||||
</check>
|
||||
<check
|
||||
category="com.e1c.v8codestyle.bsl.strict"
|
||||
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.strict.check.VariableTypeCheck">
|
||||
</check>
|
||||
<check
|
||||
category="com.e1c.v8codestyle.bsl.strict"
|
||||
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.strict.check.DynamicFeatureAccessTypeCheck">
|
||||
</check>
|
||||
<check
|
||||
category="com.e1c.v8codestyle.bsl.strict"
|
||||
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.strict.check.DynamicFeatureAccessMethodNotFoundCheck">
|
||||
</check>
|
||||
<check
|
||||
category="com.e1c.v8codestyle.bsl.strict"
|
||||
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.strict.check.SimpleStatementTypeCheck">
|
||||
</check>
|
||||
<check
|
||||
category="com.e1c.v8codestyle.bsl.strict"
|
||||
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.strict.check.InvocationParamIntersectionCheck">
|
||||
</check>
|
||||
<check
|
||||
category="com.e1c.v8codestyle.bsl.strict"
|
||||
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.strict.check.FunctionReturnTypeCheck">
|
||||
</check>
|
||||
<!-- Disabled untill release 2021.2.6+
|
||||
<check
|
||||
category="com.e1c.v8codestyle.bsl.strict"
|
||||
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.strict.check.FunctionCtorReturnSectionCheck">
|
||||
</check>
|
||||
-->
|
||||
<check
|
||||
category="com.e1c.v8codestyle.bsl.strict"
|
||||
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.strict.check.DocCommentFieldTypeCheck">
|
||||
</check>
|
||||
<check
|
||||
category="com.e1c.v8codestyle.bsl.strict"
|
||||
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.strict.check.StructureCtorValueTypeCheck">
|
||||
</check>
|
||||
|
||||
</extension>
|
||||
|
||||
|
@ -13,8 +13,10 @@
|
||||
###############################################################################
|
||||
#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/)
|
||||
|
||||
category.bls.description = Проверки встроенного языка исполнения 1С:Предприятия по Старндартам разработки
|
||||
category.bsl.title = Встроенный язык исполнения
|
||||
category.bsl.description = Проверки встроенного языка исполнения 1С:Предприятия по Старндартам разработки
|
||||
category.bsl.strict.description = Проверки встроенного языка исполнения 1С:Предприятия, что каждый объект строго типизирован
|
||||
category.bsl.strict.title = Система строгой типизации
|
||||
category.bsl.title = Встроенный язык исполнения
|
||||
|
||||
pluginName = 1С:Стандарты разработки V8 плагин Встроенного языка
|
||||
|
||||
|
@ -0,0 +1,141 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2021, 1C-Soft LLC and others.
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* 1C-Soft LLC - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.e1c.v8codestyle.bsl.strict;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
import org.eclipse.core.resources.IFile;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.xtext.EcoreUtil2;
|
||||
import org.eclipse.xtext.nodemodel.ICompositeNode;
|
||||
import org.eclipse.xtext.nodemodel.ILeafNode;
|
||||
import org.eclipse.xtext.nodemodel.INode;
|
||||
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
|
||||
|
||||
import com._1c.g5.v8.dt.bsl.documentation.comment.BslCommentUtils;
|
||||
import com._1c.g5.v8.dt.bsl.documentation.comment.IBslCommentToken;
|
||||
import com._1c.g5.v8.dt.bsl.model.Module;
|
||||
|
||||
/**
|
||||
* The utility class for strict-types system.
|
||||
*
|
||||
* @author Dmitriy Marmyshev
|
||||
*/
|
||||
public final class StrictTypeUtil
|
||||
{
|
||||
|
||||
/** The strict-types annotation using in module header to activate checks */
|
||||
public static final String STRICT_TYPE_ANNOTATION = "@strict-types"; //$NON-NLS-1$
|
||||
|
||||
public static final String BSL_FILE_EXTENSION = "bsl"; //$NON-NLS-1$
|
||||
|
||||
private static final int COMMENT_LENGTH = IBslCommentToken.LINE_STARTER.length();
|
||||
|
||||
/**
|
||||
* Checks for {@code @strict-types} annotation in BSL module file.
|
||||
*
|
||||
* @param file the file of BSL module, cannot be {@code null}.
|
||||
* @return true, if the module has {@code @strict-types} annotation in module header
|
||||
* @throws CoreException the core exception
|
||||
* @throws IOException Signals that an I/O exception has occurred.
|
||||
*/
|
||||
public static boolean hasStrictTypeAnnotation(IFile file) throws CoreException, IOException
|
||||
{
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(file.getContents(), file.getCharset())))
|
||||
{
|
||||
|
||||
String line = reader.readLine();
|
||||
while (line != null)
|
||||
{
|
||||
line = line.trim();
|
||||
if (!line.isEmpty() && !line.startsWith(IBslCommentToken.LINE_STARTER))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (line.length() > 0 && line.substring(COMMENT_LENGTH).trim().startsWith(STRICT_TYPE_ANNOTATION))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
line = reader.readLine();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for {@code @strict-types} annotation in module description.
|
||||
*
|
||||
* @param object the object of BSL module, cannot be {@code null}.
|
||||
* @return true, if module has annotation in header
|
||||
*/
|
||||
public static boolean hasStrictTypeAnnotation(EObject object)
|
||||
{
|
||||
Module module = EcoreUtil2.getContainerOfType(object, Module.class);
|
||||
if (module == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return hasStrictTypeAnnotation(module);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for {@code @strict-types} annotation in module description.
|
||||
*
|
||||
* @param module the module, cannot be {@code null}.
|
||||
* @return true, if module has annotation in header
|
||||
*/
|
||||
public static boolean hasStrictTypeAnnotation(Module module)
|
||||
{
|
||||
ICompositeNode node = NodeModelUtils.getNode(module);
|
||||
node = node.getRootNode();
|
||||
|
||||
return hasStrictTypeAnnotation(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for {@code @strict-types} annotation in module description.
|
||||
*
|
||||
* @param root the root, cannot be {@code null}.
|
||||
* @return true, if module has annotation in header
|
||||
*/
|
||||
public static boolean hasStrictTypeAnnotation(INode root)
|
||||
{
|
||||
for (ILeafNode node : root.getLeafNodes())
|
||||
{
|
||||
if (!node.isHidden())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (BslCommentUtils.isCommentNode(node)
|
||||
&& node.getText().substring(COMMENT_LENGTH).trim().startsWith(STRICT_TYPE_ANNOTATION))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private StrictTypeUtil()
|
||||
{
|
||||
throw new IllegalAccessError();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,328 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2021, 1C-Soft LLC and others.
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* 1C-Soft LLC - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.e1c.v8codestyle.bsl.strict.check;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.emf.common.util.URI;
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.emf.ecore.util.EcoreUtil;
|
||||
import org.eclipse.xtext.EcoreUtil2;
|
||||
import org.eclipse.xtext.naming.IQualifiedNameConverter;
|
||||
import org.eclipse.xtext.resource.IResourceServiceProvider;
|
||||
import org.eclipse.xtext.scoping.IScope;
|
||||
import org.eclipse.xtext.scoping.IScopeProvider;
|
||||
|
||||
import com._1c.g5.v8.dt.bsl.common.IBslPreferences;
|
||||
import com._1c.g5.v8.dt.bsl.documentation.comment.BslMultiLineCommentDocumentationProvider;
|
||||
import com._1c.g5.v8.dt.bsl.model.DynamicFeatureAccess;
|
||||
import com._1c.g5.v8.dt.bsl.model.ExplicitVariable;
|
||||
import com._1c.g5.v8.dt.bsl.model.FeatureAccess;
|
||||
import com._1c.g5.v8.dt.bsl.resource.DynamicFeatureAccessComputer;
|
||||
import com._1c.g5.v8.dt.bsl.resource.TypesComputer;
|
||||
import com._1c.g5.v8.dt.bsl.typesystem.util.TypeSystemUtil;
|
||||
import com._1c.g5.v8.dt.core.platform.IResourceLookup;
|
||||
import com._1c.g5.v8.dt.mcore.Environmental;
|
||||
import com._1c.g5.v8.dt.mcore.McorePackage;
|
||||
import com._1c.g5.v8.dt.mcore.Type;
|
||||
import com._1c.g5.v8.dt.mcore.TypeItem;
|
||||
import com._1c.g5.v8.dt.mcore.TypeSet;
|
||||
import com._1c.g5.v8.dt.mcore.util.Environments;
|
||||
import com._1c.g5.v8.dt.mcore.util.McoreUtil;
|
||||
import com._1c.g5.v8.dt.platform.IEObjectDynamicTypeNames;
|
||||
import com._1c.g5.v8.dt.platform.IEObjectTypeNames;
|
||||
import com.e1c.g5.v8.dt.check.components.BasicCheck;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
/**
|
||||
* Abstract check of types in module objects. Allows to compute types respecting system enums,
|
||||
* compare intersections of type collections and etc.
|
||||
*
|
||||
* @author Dmitriy Marmyshev
|
||||
*/
|
||||
public abstract class AbstractTypeCheck
|
||||
extends BasicCheck
|
||||
{
|
||||
|
||||
private static final Collection<String> ALL_REF_TYPE_SET_PARENT_TYPE_NAMES =
|
||||
Set.of(IEObjectDynamicTypeNames.CATALOG_REF_TYPE_NAME, IEObjectDynamicTypeNames.DOCUMENT_REF_TYPE_NAME,
|
||||
IEObjectDynamicTypeNames.ENUM_REF_TYPE_NAME, IEObjectDynamicTypeNames.COC_REF_TYPE_NAME,
|
||||
IEObjectDynamicTypeNames.COA_REF_TYPE_NAME, IEObjectDynamicTypeNames.CALCULATION_TYPE_REF_TYPE_NAME,
|
||||
IEObjectDynamicTypeNames.BP_REF_TYPE_NAME, IEObjectDynamicTypeNames.BP_ROUTEPOINT_TYPE_NAME,
|
||||
IEObjectDynamicTypeNames.TASK_REF_TYPE_NAME, IEObjectDynamicTypeNames.EXCHANGE_PLAN_REF_TYPE_NAME);
|
||||
|
||||
protected final IResourceLookup resourceLookup;
|
||||
|
||||
protected final IBslPreferences bslPreferences;
|
||||
|
||||
protected final TypesComputer typeComputer;
|
||||
|
||||
protected final DynamicFeatureAccessComputer dynamicFeatureAccessComputer;
|
||||
|
||||
private final IScopeProvider scopeProvider;
|
||||
|
||||
private final IQualifiedNameConverter qualifiedNameConverter;
|
||||
|
||||
private final BslMultiLineCommentDocumentationProvider commentProvider;
|
||||
|
||||
/**
|
||||
* Instantiates a new abstract type check.
|
||||
*
|
||||
* @param resourceLookup the resource lookup service, cannot be {@code null}.
|
||||
* @param bslPreferences the BSL preferences service, cannot be {@code null}.
|
||||
* @param qualifiedNameConverter the qualified name converter service, cannot be {@code null}.
|
||||
*/
|
||||
protected AbstractTypeCheck(IResourceLookup resourceLookup, IBslPreferences bslPreferences,
|
||||
IQualifiedNameConverter qualifiedNameConverter)
|
||||
{
|
||||
super();
|
||||
this.resourceLookup = resourceLookup;
|
||||
this.bslPreferences = bslPreferences;
|
||||
IResourceServiceProvider rsp =
|
||||
IResourceServiceProvider.Registry.INSTANCE.getResourceServiceProvider(URI.createURI("*.bsl")); //$NON-NLS-1$
|
||||
this.typeComputer = rsp.get(TypesComputer.class);
|
||||
this.dynamicFeatureAccessComputer = rsp.get(DynamicFeatureAccessComputer.class);
|
||||
this.scopeProvider = rsp.get(IScopeProvider.class);
|
||||
this.commentProvider = rsp.get(BslMultiLineCommentDocumentationProvider.class);
|
||||
this.qualifiedNameConverter = qualifiedNameConverter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the object has empty types.
|
||||
*
|
||||
* @param object the object, cannot be {@code null}.
|
||||
* @return true, if the object has empty types
|
||||
*/
|
||||
protected boolean isEmptyTypes(EObject object)
|
||||
{
|
||||
Environmental envs = EcoreUtil2.getContainerOfType(object, Environmental.class);
|
||||
if (envs == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
Environments actualEnvs = bslPreferences.getLoadEnvs(object).intersect(envs.environments());
|
||||
if (actualEnvs.isEmpty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
List<TypeItem> types = computeTypes(object, actualEnvs);
|
||||
|
||||
if (types.isEmpty() && object instanceof ExplicitVariable)
|
||||
{
|
||||
IScope typeScope = scopeProvider.getScope(object, McorePackage.Literals.TYPE_DESCRIPTION__TYPES);
|
||||
IProject project = resourceLookup.getProject(object);
|
||||
boolean oldFormatComment = bslPreferences.getDocumentCommentProperties(project).oldCommentFormat();
|
||||
Collection<TypeItem> commentTypes = TypeSystemUtil.computeCommentTypes(object, typeScope, scopeProvider,
|
||||
qualifiedNameConverter, commentProvider, oldFormatComment);
|
||||
return commentTypes.isEmpty();
|
||||
}
|
||||
|
||||
return types.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute types with respect to system enumeration.
|
||||
*
|
||||
* @param object the object, cannot be {@code null}.
|
||||
* @param envs the environments, cannot be {@code null}.
|
||||
* @return the list of types, cannot return {@code null}.
|
||||
*/
|
||||
protected List<TypeItem> computeTypes(EObject object, Environments envs)
|
||||
{
|
||||
List<TypeItem> types = typeComputer.computeTypes(object, envs);
|
||||
|
||||
if (types.isEmpty() && object instanceof DynamicFeatureAccess
|
||||
&& ((DynamicFeatureAccess)object).getSource() instanceof FeatureAccess)
|
||||
{
|
||||
// Bypass system enum types with property without type
|
||||
DynamicFeatureAccess dfa = (DynamicFeatureAccess)object;
|
||||
FeatureAccess fa = (FeatureAccess)dfa.getSource();
|
||||
List<TypeItem> sourceTypes = typeComputer.computeTypes(fa, envs);
|
||||
if (sourceTypes.size() == 1)
|
||||
{
|
||||
String typeName = fa.getName();
|
||||
String propertyName = dfa.getName();
|
||||
TypeItem type = sourceTypes.get(0);
|
||||
if ((typeName.equalsIgnoreCase(McoreUtil.getTypeNameRu(type))
|
||||
|| typeName.equalsIgnoreCase(McoreUtil.getTypeName(type)))
|
||||
&& dynamicFeatureAccessComputer.getAllProperties(sourceTypes, object.eResource())
|
||||
.stream()
|
||||
.flatMap(e -> e.getFirst().stream())
|
||||
.anyMatch(p -> propertyName.equalsIgnoreCase(p.getNameRu())
|
||||
|| propertyName.equalsIgnoreCase(p.getName())))
|
||||
{
|
||||
return sourceTypes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return types;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that collections of {@link TypeItem} have common item
|
||||
* @param expectedTypes expected collection of {@link TypeItem}, cannot be <code>null</code>
|
||||
* @param realTypes real collection of {@link TypeItem}, cannot be <code>null</code>
|
||||
* @param context {@link EObject} for resolving proxy checking types, cannot be <code>null</code>
|
||||
* @return <code>true</code> if intersection was detected
|
||||
*/
|
||||
protected static boolean intersectTypeItem(List<TypeItem> expectedTypes, List<TypeItem> realTypes, EObject context)
|
||||
{
|
||||
if (expectedTypes.isEmpty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
List<TypeItem> parentTypes = getParentTypes(expectedTypes);
|
||||
parentTypes.addAll(expectedTypes);
|
||||
Collection<String> expectedTypesNames = getTypeNames(parentTypes, context);
|
||||
expectedTypesNames.addAll(getCastingType(expectedTypesNames));
|
||||
expectedTypesNames = Sets.newLinkedHashSet(expectedTypesNames);
|
||||
if (expectedTypesNames.contains(IEObjectTypeNames.ARBITRARY)
|
||||
|| expectedTypesNames.contains(IEObjectTypeNames.UNDEFINED)
|
||||
|| expectedTypesNames.contains(IEObjectTypeNames.REFERENCE_TO_OBJECT_OF_INFORMATION_BASE)
|
||||
|| expectedTypesNames.contains(IEObjectTypeNames.XDTO_DATA_VALUE)
|
||||
|| expectedTypesNames.contains(IEObjectTypeNames.XDTO_DATA_OBJECT))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (realTypes.isEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
parentTypes = getParentTypes(realTypes);
|
||||
parentTypes.addAll(realTypes);
|
||||
Collection<String> realTypesNames = getTypeNames(parentTypes, context);
|
||||
|
||||
if (!expectedTypesNames.isEmpty() && !realTypesNames.isEmpty())
|
||||
{
|
||||
expectedTypesNames.retainAll(realTypesNames);
|
||||
return !expectedTypesNames.isEmpty();
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static Collection<? extends String> getCastingType(Collection<String> expectedTypesNames)
|
||||
{
|
||||
List<String> castTypeNames = new ArrayList<>();
|
||||
for (String typeName : expectedTypesNames)
|
||||
{
|
||||
if (IEObjectTypeNames.STRUCTURE.equals(typeName))
|
||||
{
|
||||
castTypeNames.add(IEObjectTypeNames.FIXED_STRUCTURE);
|
||||
}
|
||||
}
|
||||
return castTypeNames;
|
||||
}
|
||||
|
||||
private static List<TypeItem> getParentTypes(List<TypeItem> theFirstCollectionTypes)
|
||||
{
|
||||
List<TypeItem> types = new ArrayList<>(theFirstCollectionTypes);
|
||||
List<TypeItem> parentTypes = new ArrayList<>();
|
||||
Iterator<TypeItem> iterator = types.iterator();
|
||||
while (iterator.hasNext())
|
||||
{
|
||||
TypeItem type = iterator.next();
|
||||
while (type instanceof Type && ((Type)type).getParentType() != null)
|
||||
{
|
||||
parentTypes.add(((Type)type).getParentType());
|
||||
type = ((Type)type).getParentType();
|
||||
}
|
||||
}
|
||||
return parentTypes;
|
||||
}
|
||||
|
||||
private static Collection<String> getTypeNames(List<TypeItem> parentTypes, EObject context)
|
||||
{
|
||||
Set<String> typeNames = new HashSet<>();
|
||||
for (TypeItem type : parentTypes)
|
||||
{
|
||||
String typeName = McoreUtil.getTypeName(type);
|
||||
String[] parts = typeName.split("\\."); //$NON-NLS-1$
|
||||
if (parts.length == 2)
|
||||
{
|
||||
typeNames.add(parts[0]);
|
||||
if (type.eIsProxy() && (IEObjectTypeNames.DEFINED_TYPE.equals(parts[0])
|
||||
|| IEObjectTypeNames.CHARACTERISTIC.equals(parts[0])))
|
||||
{
|
||||
type = (TypeItem)EcoreUtil.resolve(type, context);
|
||||
}
|
||||
}
|
||||
typeNames.add(typeName);
|
||||
if (type instanceof TypeSet)
|
||||
{
|
||||
if (parts.length == 2)
|
||||
{
|
||||
typeNames.addAll(((TypeSet)type).getTypes()
|
||||
.stream()
|
||||
.map(typeItem -> McoreUtil.getTypeName(typeItem))
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
else if (IEObjectTypeNames.ANY_REF.equals(typeName))
|
||||
{
|
||||
typeNames.addAll(ALL_REF_TYPE_SET_PARENT_TYPE_NAMES);
|
||||
}
|
||||
else
|
||||
{
|
||||
String parentTypeName = getTypeSetItemParentTypeName(typeName);
|
||||
if (parentTypeName != null)
|
||||
{
|
||||
typeNames.add(parentTypeName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return typeNames;
|
||||
}
|
||||
|
||||
private static String getTypeSetItemParentTypeName(String typeName)
|
||||
{
|
||||
switch (typeName)
|
||||
{
|
||||
case IEObjectTypeNames.CATALOG_REF:
|
||||
return IEObjectDynamicTypeNames.CATALOG_REF_TYPE_NAME;
|
||||
case IEObjectTypeNames.DOCUMENT_REF:
|
||||
return IEObjectDynamicTypeNames.DOCUMENT_REF_TYPE_NAME;
|
||||
case IEObjectTypeNames.ENUM_REF:
|
||||
return IEObjectDynamicTypeNames.ENUM_REF_TYPE_NAME;
|
||||
case IEObjectTypeNames.CHART_OF_CHARACTERISTIC_TYPES_REF:
|
||||
return IEObjectDynamicTypeNames.COC_REF_TYPE_NAME;
|
||||
case IEObjectTypeNames.CHART_OF_ACCOUNTS_REF:
|
||||
return IEObjectDynamicTypeNames.COA_REF_TYPE_NAME;
|
||||
case IEObjectTypeNames.CHART_OF_CALCULATION_TYPES_REF:
|
||||
return IEObjectDynamicTypeNames.CALCULATION_TYPE_REF_TYPE_NAME;
|
||||
case IEObjectTypeNames.BUSINESS_PROCESS_REF:
|
||||
return IEObjectDynamicTypeNames.BP_REF_TYPE_NAME;
|
||||
case IEObjectTypeNames.BUSINESS_PROCESS_ROUTE_POINT_REF:
|
||||
return IEObjectDynamicTypeNames.BP_ROUTEPOINT_TYPE_NAME;
|
||||
case IEObjectTypeNames.TASK_REF:
|
||||
return IEObjectDynamicTypeNames.TASK_REF_TYPE_NAME;
|
||||
case IEObjectTypeNames.EXCHANGE_PLAN_REF:
|
||||
return IEObjectDynamicTypeNames.EXCHANGE_PLAN_REF_TYPE_NAME;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,123 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2021, 1C-Soft LLC and others.
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* 1C-Soft LLC - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.e1c.v8codestyle.bsl.strict.check;
|
||||
|
||||
import static com.e1c.v8codestyle.bsl.strict.check.StrictTypeAnnotationCheckExtension.PARAM_CHECK_ANNOTATION_IN_MODULE_DESCRIPTION;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
|
||||
import com._1c.g5.v8.dt.bsl.documentation.comment.BslDocumentationComment;
|
||||
import com._1c.g5.v8.dt.bsl.documentation.comment.IDescriptionPart;
|
||||
import com._1c.g5.v8.dt.bsl.documentation.comment.LinkPart;
|
||||
import com._1c.g5.v8.dt.bsl.documentation.comment.TextPart;
|
||||
import com._1c.g5.v8.dt.bsl.documentation.comment.TypeSection.FieldDefinition;
|
||||
import com.e1c.g5.v8.dt.bsl.check.DocumentationCommentBasicDelegateCheck;
|
||||
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.StrictTypeUtil;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
/**
|
||||
* Checks the documentation comment {@link FieldDefinition field} that has section with types definition.
|
||||
* By default it not respect {@code //@strict-types} annotation in module header.
|
||||
*
|
||||
* @author Dmitriy Marmyshev
|
||||
*/
|
||||
public class DocCommentFieldTypeCheck
|
||||
extends DocumentationCommentBasicDelegateCheck
|
||||
{
|
||||
|
||||
private static final String CHECK_ID = "doc-comment-field-type"; //$NON-NLS-1$
|
||||
|
||||
@Override
|
||||
public String getCheckId()
|
||||
{
|
||||
return CHECK_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureCheck(CheckConfigurer builder)
|
||||
{
|
||||
builder.title(Messages.DocCommentFieldTypeCheck_title)
|
||||
.description(Messages.DocCommentFieldTypeCheck_description)
|
||||
.complexity(CheckComplexity.NORMAL)
|
||||
.severity(IssueSeverity.MINOR)
|
||||
.issueType(IssueType.CODE_STYLE)
|
||||
.delegate(FieldDefinition.class);
|
||||
builder.parameter(PARAM_CHECK_ANNOTATION_IN_MODULE_DESCRIPTION, Boolean.class, Boolean.FALSE.toString(),
|
||||
Messages.StrictTypeAnnotationCheckExtension_Check__strict_types_annotation_in_module_desctioption);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void checkDocumentationCommentObject(IDescriptionPart object, BslDocumentationComment root,
|
||||
DocumentationCommentResultAcceptor resultAceptor, ICheckParameters parameters, IProgressMonitor monitor)
|
||||
{
|
||||
if (monitor.isCanceled() || parameters.getBoolean(PARAM_CHECK_ANNOTATION_IN_MODULE_DESCRIPTION)
|
||||
&& !StrictTypeUtil.hasStrictTypeAnnotation(root.getModule()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FieldDefinition fieldDef = (FieldDefinition)object;
|
||||
|
||||
if (isFieldTypeEmpty(fieldDef))
|
||||
{
|
||||
String message = MessageFormat.format(Messages.DocCommentFieldTypeCheck_Field__N__has_no_type_definition,
|
||||
fieldDef.getName());
|
||||
|
||||
resultAceptor.addIssue(message, fieldDef.getName().length());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isFieldTypeEmpty(FieldDefinition fieldDef)
|
||||
{
|
||||
if (!fieldDef.getTypeSections().isEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
List<IDescriptionPart> parts = fieldDef.getDescription().getParts();
|
||||
Collection<LinkPart> linkParts = Lists.newArrayListWithCapacity(parts.size());
|
||||
int lastLine = -1;
|
||||
for (IDescriptionPart part : parts)
|
||||
{
|
||||
if (part instanceof LinkPart && lastLine != part.getLineNumber())
|
||||
{
|
||||
linkParts.add((LinkPart)part);
|
||||
lastLine = part.getLineNumber();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (part instanceof TextPart)
|
||||
{
|
||||
String text = ((TextPart)part).getText();
|
||||
if (text != null
|
||||
&& (".".equals(text.trim()) || "-".equals(text.trim()) && lastLine != part.getLineNumber())) //$NON-NLS-1$ //$NON-NLS-2$
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return linkParts.isEmpty();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,128 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2021, 1C-Soft LLC and others.
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* 1C-Soft LLC - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.e1c.v8codestyle.bsl.strict.check;
|
||||
|
||||
import static com._1c.g5.v8.dt.bsl.model.BslPackage.Literals.DYNAMIC_FEATURE_ACCESS;
|
||||
import static com._1c.g5.v8.dt.bsl.model.BslPackage.Literals.FEATURE_ACCESS__NAME;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
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.DynamicFeatureAccess;
|
||||
import com._1c.g5.v8.dt.bsl.model.FeatureEntry;
|
||||
import com._1c.g5.v8.dt.bsl.model.util.BslUtil;
|
||||
import com._1c.g5.v8.dt.core.platform.IResourceLookup;
|
||||
import com._1c.g5.v8.dt.mcore.Environmental;
|
||||
import com._1c.g5.v8.dt.mcore.util.Environments;
|
||||
import com.e1c.g5.v8.dt.check.CheckComplexity;
|
||||
import com.e1c.g5.v8.dt.check.ICheckParameters;
|
||||
import com.e1c.g5.v8.dt.check.components.ModuleTopObjectNameFilterExtension;
|
||||
import com.e1c.g5.v8.dt.check.settings.IssueSeverity;
|
||||
import com.e1c.g5.v8.dt.check.settings.IssueType;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
* Checks that {@link DynamicFeatureAccess dynamic method} exists in accessed object.
|
||||
*
|
||||
* @author Dmitriy Marmyshev
|
||||
*/
|
||||
public class DynamicFeatureAccessMethodNotFoundCheck
|
||||
extends AbstractTypeCheck
|
||||
{
|
||||
|
||||
private static final String CHECK_ID = "dynamic-access-method-not-found"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Instantiates a new dynamic feature access method not found check.
|
||||
*
|
||||
* @param resourceLookup the resource lookup service, cannot be {@code null}.
|
||||
* @param bslPreferences the BSL preferences service, cannot be {@code null}.
|
||||
* @param qualifiedNameConverter the qualified name converter service, cannot be {@code null}.
|
||||
*/
|
||||
@Inject
|
||||
public DynamicFeatureAccessMethodNotFoundCheck(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.DynamicFeatureAccessMethodNotFoundCheck_title)
|
||||
.description(Messages.DynamicFeatureAccessMethodNotFoundCheck_description)
|
||||
.complexity(CheckComplexity.NORMAL)
|
||||
.severity(IssueSeverity.MAJOR)
|
||||
.issueType(IssueType.CODE_STYLE)
|
||||
.extension(new ModuleTopObjectNameFilterExtension())
|
||||
.extension(new StrictTypeAnnotationCheckExtension())
|
||||
.module()
|
||||
.checkedObjectType(DYNAMIC_FEATURE_ACCESS);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void check(Object object, ResultAcceptor resultAceptor, ICheckParameters parameters,
|
||||
IProgressMonitor monitor)
|
||||
{
|
||||
if (monitor.isCanceled() || !(object instanceof EObject))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DynamicFeatureAccess fa = (DynamicFeatureAccess)object;
|
||||
if (fa.getName() == null || fa.getName().isBlank())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
boolean isMethod = BslUtil.getInvocation(fa) != null;
|
||||
if (isMethod && isEmptySource(fa))
|
||||
{
|
||||
String message = MessageFormat
|
||||
.format(Messages.DynamicFeatureAccessTypeCheck_Method_M_not_found_in_accessed_object, fa.getName());
|
||||
|
||||
resultAceptor.addIssue(message, FEATURE_ACCESS__NAME);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private boolean isEmptySource(DynamicFeatureAccess object)
|
||||
{
|
||||
Environmental envs = EcoreUtil2.getContainerOfType(object, Environmental.class);
|
||||
if (envs == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
Environments actualEnvs = bslPreferences.getLoadEnvs(object).intersect(envs.environments());
|
||||
if (actualEnvs.isEmpty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
List<FeatureEntry> objects = dynamicFeatureAccessComputer.getLastObject(object, actualEnvs);
|
||||
return objects.isEmpty();
|
||||
}
|
||||
}
|
@ -0,0 +1,104 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2021, 1C-Soft LLC and others.
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* 1C-Soft LLC - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.e1c.v8codestyle.bsl.strict.check;
|
||||
|
||||
import static com._1c.g5.v8.dt.bsl.model.BslPackage.Literals.DYNAMIC_FEATURE_ACCESS;
|
||||
import static com._1c.g5.v8.dt.bsl.model.BslPackage.Literals.FEATURE_ACCESS__NAME;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.xtext.naming.IQualifiedNameConverter;
|
||||
|
||||
import com._1c.g5.v8.dt.bsl.common.IBslPreferences;
|
||||
import com._1c.g5.v8.dt.bsl.model.DynamicFeatureAccess;
|
||||
import com._1c.g5.v8.dt.bsl.model.FeatureAccess;
|
||||
import com._1c.g5.v8.dt.bsl.model.util.BslUtil;
|
||||
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.components.ModuleTopObjectNameFilterExtension;
|
||||
import com.e1c.g5.v8.dt.check.settings.IssueSeverity;
|
||||
import com.e1c.g5.v8.dt.check.settings.IssueType;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
* Checks {@link DynamicFeatureAccess dynamic property} has return types.
|
||||
*
|
||||
* @author Dmitriy Marmyshev
|
||||
*/
|
||||
public class DynamicFeatureAccessTypeCheck
|
||||
extends AbstractTypeCheck
|
||||
{
|
||||
private static final String CHECK_ID = "property-return-type"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Instantiates a new dynamic feature access type check.
|
||||
*
|
||||
* @param resourceLookup the resource lookup service, cannot be {@code null}.
|
||||
* @param bslPreferences the BSL preferences service, cannot be {@code null}.
|
||||
* @param qualifiedNameConverter the qualified name converter service, cannot be {@code null}.
|
||||
*/
|
||||
@Inject
|
||||
public DynamicFeatureAccessTypeCheck(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.DynamicFeatureAccessTypeCheck_title)
|
||||
.description(Messages.DynamicFeatureAccessTypeCheck_description)
|
||||
.complexity(CheckComplexity.NORMAL)
|
||||
.severity(IssueSeverity.MAJOR)
|
||||
.issueType(IssueType.CODE_STYLE)
|
||||
.extension(new ModuleTopObjectNameFilterExtension())
|
||||
.extension(new StrictTypeAnnotationCheckExtension())
|
||||
.module()
|
||||
.checkedObjectType(DYNAMIC_FEATURE_ACCESS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void check(Object object, ResultAcceptor resultAceptor, ICheckParameters parameters,
|
||||
IProgressMonitor monitor)
|
||||
{
|
||||
if (monitor.isCanceled() || !(object instanceof EObject))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FeatureAccess fa = (FeatureAccess)object;
|
||||
if (fa.getName() == null || fa.getName().isBlank())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
boolean isMethod = BslUtil.getInvocation(fa) != null;
|
||||
if (!isMethod && isEmptyTypes((EObject)object))
|
||||
{
|
||||
String message = MessageFormat
|
||||
.format(Messages.DynamicFeatureAccessTypeCheck_Feature_access_M_has_no_return_type, fa.getName());
|
||||
resultAceptor.addIssue(message, FEATURE_ACCESS__NAME);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,385 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2021, 1C-Soft LLC and others.
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* 1C-Soft LLC - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.e1c.v8codestyle.bsl.strict.check;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.emf.common.util.URI;
|
||||
import org.eclipse.emf.ecore.resource.Resource;
|
||||
import org.eclipse.xtext.naming.IQualifiedNameConverter;
|
||||
import org.eclipse.xtext.resource.IResourceServiceProvider;
|
||||
import org.eclipse.xtext.scoping.IScope;
|
||||
import org.eclipse.xtext.scoping.IScopeProvider;
|
||||
import org.eclipse.xtext.util.Pair;
|
||||
|
||||
import com._1c.g5.v8.dt.bsl.comment.DocumentationCommentProperties;
|
||||
import com._1c.g5.v8.dt.bsl.common.IBslPreferences;
|
||||
import com._1c.g5.v8.dt.bsl.documentation.comment.BslDocumentationComment;
|
||||
import com._1c.g5.v8.dt.bsl.documentation.comment.BslDocumentationComment.ReturnSection;
|
||||
import com._1c.g5.v8.dt.bsl.documentation.comment.BslMultiLineCommentDocumentationProvider;
|
||||
import com._1c.g5.v8.dt.bsl.documentation.comment.IDescriptionPart;
|
||||
import com._1c.g5.v8.dt.bsl.model.BslPackage.Literals;
|
||||
import com._1c.g5.v8.dt.bsl.model.Function;
|
||||
import com._1c.g5.v8.dt.bsl.model.ReturnStatement;
|
||||
import com._1c.g5.v8.dt.bsl.resource.DynamicFeatureAccessComputer;
|
||||
import com._1c.g5.v8.dt.bsl.resource.TypesComputer;
|
||||
import com._1c.g5.v8.dt.core.platform.IResourceLookup;
|
||||
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.McorePackage;
|
||||
import com._1c.g5.v8.dt.mcore.Property;
|
||||
import com._1c.g5.v8.dt.mcore.TypeItem;
|
||||
import com._1c.g5.v8.dt.mcore.util.McoreUtil;
|
||||
import com._1c.g5.v8.dt.metadata.mdclass.ScriptVariant;
|
||||
import com._1c.g5.v8.dt.platform.IEObjectTypeNames;
|
||||
import com.e1c.g5.v8.dt.bsl.check.DocumentationCommentBasicDelegateCheck;
|
||||
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.StrictTypeUtil;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
* Documenting comment validator.
|
||||
* Validate user's data types of function constructor in return types specified in documenting comments.
|
||||
*
|
||||
* @author Dmitriy Marmyshev
|
||||
*
|
||||
*/
|
||||
public class FunctionCtorReturnSectionCheck
|
||||
extends DocumentationCommentBasicDelegateCheck
|
||||
{
|
||||
|
||||
private static final String CHECK_ID = "constructor-function-return-section"; //$NON-NLS-1$
|
||||
|
||||
private static final String PARAM_CHECK_TYPES = "checkTypes"; //$NON-NLS-1$
|
||||
|
||||
private static final Set<String> DEFAULT_CHECK_TYPES = Set.of(IEObjectTypeNames.STRUCTURE,
|
||||
IEObjectTypeNames.FIXED_STRUCTURE, IEObjectTypeNames.VALUE_TABLE, IEObjectTypeNames.VALUE_TREE);
|
||||
|
||||
private final TypesComputer typesComputer;
|
||||
|
||||
private final DynamicFeatureAccessComputer dynamicComputer;
|
||||
|
||||
private final IScopeProvider scopeProvider;
|
||||
|
||||
private final IQualifiedNameConverter qualifiedNameConverter;
|
||||
|
||||
private final BslMultiLineCommentDocumentationProvider commentProvider;
|
||||
|
||||
private final IResourceLookup resourceLookup;
|
||||
|
||||
private final IV8ProjectManager v8ProjectManager;
|
||||
|
||||
private final IBslPreferences bslPreferences;
|
||||
|
||||
/**
|
||||
* Instantiates a new function constructor documentation comment return section check.
|
||||
*
|
||||
* @param resourceLookup the resource lookup service, cannot be {@code null}.
|
||||
* @param v8ProjectManager the v8 project manager service, cannot be {@code null}.
|
||||
* @param qualifiedNameConverter the qualified name converter service, cannot be {@code null}.
|
||||
* @param bslPreferences the BSL preferences service, cannot be {@code null}.
|
||||
*/
|
||||
@Inject
|
||||
public FunctionCtorReturnSectionCheck(IResourceLookup resourceLookup, IV8ProjectManager v8ProjectManager,
|
||||
IQualifiedNameConverter qualifiedNameConverter, IBslPreferences bslPreferences)
|
||||
{
|
||||
super();
|
||||
IResourceServiceProvider rsp =
|
||||
IResourceServiceProvider.Registry.INSTANCE.getResourceServiceProvider(URI.createURI("*.bsl")); //$NON-NLS-1$
|
||||
this.typesComputer = rsp.get(TypesComputer.class);
|
||||
this.dynamicComputer = rsp.get(DynamicFeatureAccessComputer.class);
|
||||
this.scopeProvider = rsp.get(IScopeProvider.class);
|
||||
this.commentProvider = rsp.get(BslMultiLineCommentDocumentationProvider.class);
|
||||
this.qualifiedNameConverter = qualifiedNameConverter;
|
||||
this.resourceLookup = resourceLookup;
|
||||
this.v8ProjectManager = v8ProjectManager;
|
||||
this.bslPreferences = bslPreferences;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCheckId()
|
||||
{
|
||||
return CHECK_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureCheck(CheckConfigurer builder)
|
||||
{
|
||||
builder.title(Messages.FunctionCtorReturnSectionCheck_title)
|
||||
.description(Messages.FunctionCtorReturnSectionCheck_description)
|
||||
.complexity(CheckComplexity.NORMAL)
|
||||
.severity(IssueSeverity.MAJOR)
|
||||
.issueType(IssueType.CODE_STYLE)
|
||||
.delegate(ReturnSection.class);
|
||||
builder.parameter(PARAM_CHECK_TYPES, String.class, String.join(",", DEFAULT_CHECK_TYPES), //$NON-NLS-1$
|
||||
Messages.FunctionCtorReturnSectionCheck_User_extandable_Data_type_list_comma_separated);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void checkDocumentationCommentObject(IDescriptionPart object, BslDocumentationComment root,
|
||||
DocumentationCommentResultAcceptor resultAceptor, ICheckParameters parameters, IProgressMonitor monitor)
|
||||
{
|
||||
if (monitor.isCanceled()
|
||||
|| !(root.getMethod() instanceof Function) && !StrictTypeUtil.hasStrictTypeAnnotation(root.getModule()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ReturnSection returnSection = (ReturnSection)object;
|
||||
|
||||
Function method = (Function)root.getMethod();
|
||||
|
||||
IScope typeScope = scopeProvider.getScope(method, McorePackage.Literals.TYPE_DESCRIPTION__TYPES);
|
||||
|
||||
IProject project = resourceLookup.getProject(root.getModule());
|
||||
|
||||
boolean isRussianScript = isRussianScriptVariantProject(project);
|
||||
|
||||
DocumentationCommentProperties props = bslPreferences.getDocumentCommentProperties(project);
|
||||
|
||||
boolean oldFormat = props.oldCommentFormat();
|
||||
|
||||
Collection<TypeItem> computedReturnTypes = root.computeReturnTypes(typeScope, scopeProvider,
|
||||
qualifiedNameConverter, commentProvider, oldFormat, method);
|
||||
|
||||
Set<String> checkTypes = getCheckTypes(parameters);
|
||||
|
||||
List<String> computedReturnTypeNames =
|
||||
computedReturnTypes.stream().map(McoreUtil::getTypeName).collect(Collectors.toList());
|
||||
if (isUserDataTypes(computedReturnTypeNames, checkTypes))
|
||||
{
|
||||
|
||||
//@formatter:off
|
||||
List<ReturnStatement> returns = method.allStatements()
|
||||
.stream()
|
||||
.filter(ReturnStatement.class::isInstance)
|
||||
.map(ReturnStatement.class::cast)
|
||||
.collect(Collectors.toList());
|
||||
//@formatter:on
|
||||
|
||||
Resource res = method.eResource();
|
||||
|
||||
Collection<Pair<Collection<Property>, TypeItem>> coputedProperties =
|
||||
dynamicComputer.getAllProperties(computedReturnTypes, res);
|
||||
|
||||
for (ReturnStatement statment : returns)
|
||||
{
|
||||
List<TypeItem> returnTypes =
|
||||
typesComputer.computeTypes(statment.getExpression(), method.environments());
|
||||
|
||||
Collection<Pair<Collection<Property>, TypeItem>> properties =
|
||||
dynamicComputer.getAllProperties(returnTypes, res);
|
||||
|
||||
for (TypeItem returnType : returnTypes)
|
||||
{
|
||||
String returnTypeName = McoreUtil.getTypeName(returnType);
|
||||
if (computedReturnTypeNames.contains(returnTypeName))
|
||||
{
|
||||
if (isUserDataTypes(List.of(returnTypeName), checkTypes))
|
||||
{
|
||||
Optional<Pair<Collection<Property>, TypeItem>> declaredProperties =
|
||||
coputedProperties.stream()
|
||||
.filter(t -> McoreUtil.getTypeName(t.getSecond()).equals(returnTypeName))
|
||||
.findAny();
|
||||
Optional<Pair<Collection<Property>, TypeItem>> typeProperties = properties.stream()
|
||||
.filter(t -> McoreUtil.getTypeName(t.getSecond()).equals(returnTypeName))
|
||||
.findAny();
|
||||
|
||||
checkTypeProperties(method, statment, isRussianScript, returnType, declaredProperties.get(),
|
||||
typeProperties.get(), resultAceptor);
|
||||
}
|
||||
}
|
||||
else if (isWarningReturnNonDeclaredType(method, returnSection, returnType, computedReturnTypes))
|
||||
{
|
||||
addWarningReturnNonDeclaredType(statment, isRussianScript, returnType, returnTypeName,
|
||||
resultAceptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Set<String> getCheckTypes(ICheckParameters parameters)
|
||||
{
|
||||
String[] types = parameters.getString(PARAM_CHECK_TYPES).replace(" ", " ").split(","); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||
|
||||
Set<String> checkTypes = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
|
||||
checkTypes.addAll(Set.of(types));
|
||||
return checkTypes;
|
||||
}
|
||||
|
||||
private void checkTypeProperties(Function function, ReturnStatement statment, boolean useRussianScript,
|
||||
TypeItem returnType, Pair<Collection<Property>, TypeItem> declaredProperties,
|
||||
Pair<Collection<Property>, TypeItem> typeProperties, DocumentationCommentResultAcceptor resultAceptor)
|
||||
{
|
||||
if (declaredProperties == null || typeProperties == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> declaredProertyNames = new ArrayList<>();
|
||||
|
||||
// check declared properties and types
|
||||
for (Property declaredProperty : declaredProperties.getFirst())
|
||||
{
|
||||
String propertyName = useRussianScript ? declaredProperty.getNameRu() : declaredProperty.getName();
|
||||
declaredProertyNames.add(propertyName);
|
||||
List<String> declaredType =
|
||||
declaredProperty.getTypes().stream().map(McoreUtil::getTypeName).collect(Collectors.toList());
|
||||
if (declaredType.isEmpty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
List<TypeItem> types = typeProperties.getFirst()
|
||||
.stream()
|
||||
.filter(p -> useRussianScript ? p.getNameRu().equals(declaredProperty.getNameRu())
|
||||
: p.getName().equals(declaredProperty.getName()))
|
||||
.flatMap(p -> p.getTypes().stream())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<TypeItem> types2 = types.stream()
|
||||
.filter(t -> !declaredType.contains(McoreUtil.getTypeName(t)))
|
||||
.collect(Collectors.toList());
|
||||
if (types.isEmpty())
|
||||
{
|
||||
addWarningDeclaredNonReturningProperty(statment, useRussianScript, declaredProperty, resultAceptor);
|
||||
}
|
||||
else if (!types2.isEmpty())
|
||||
{
|
||||
addWarningDeclaredNonReturningPropertyType(statment, useRussianScript, declaredProperty, types2,
|
||||
resultAceptor);
|
||||
}
|
||||
}
|
||||
|
||||
// check for non declared properties
|
||||
if (isWarningReturnNonDeclaredProperty(function, statment, declaredProperties.getFirst()))
|
||||
{
|
||||
List<String> nonDeclaredProperties = typeProperties.getFirst()
|
||||
.stream()
|
||||
.map(useRussianScript ? Property::getNameRu : Property::getName)
|
||||
.filter(Predicates.not(declaredProertyNames::contains))
|
||||
.collect(Collectors.toList());
|
||||
if (!nonDeclaredProperties.isEmpty())
|
||||
{
|
||||
addWarningNonDeclaredReturningProperty(statment, useRussianScript, nonDeclaredProperties,
|
||||
resultAceptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addWarningReturnNonDeclaredType(ReturnStatement statment, boolean isRussianScript, TypeItem returnType,
|
||||
String returnTypeName, DocumentationCommentResultAcceptor resultAceptor)
|
||||
{
|
||||
final String message = MessageFormat.format(Messages.FunctionCtorReturnSectionCheck_Return_non_declared_type__T,
|
||||
isRussianScript ? McoreUtil.getTypeNameRu(returnType) : returnTypeName);
|
||||
|
||||
resultAceptor.addIssue(message, statment, Literals.RETURN_STATEMENT__EXPRESSION);
|
||||
}
|
||||
|
||||
private boolean isWarningReturnNonDeclaredType(Function function, ReturnSection returnSection, TypeItem returnType,
|
||||
Collection<TypeItem> computedReturnTypes)
|
||||
{
|
||||
return function.isExport();
|
||||
}
|
||||
|
||||
private boolean isUserDataTypes(List<String> computedReturnTypeNames, Set<String> checkTypes)
|
||||
{
|
||||
if (computedReturnTypeNames.isEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (String typeName : computedReturnTypeNames)
|
||||
{
|
||||
if (checkTypes.contains(typeName))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void addWarningDeclaredNonReturningProperty(ReturnStatement statment, boolean useRussianScript,
|
||||
Property property, DocumentationCommentResultAcceptor resultAceptor)
|
||||
{
|
||||
final String message = MessageFormat.format(
|
||||
Messages.FunctionCtorReturnSectionCheck_Declared_property__N__with_type__T__not_returning,
|
||||
useRussianScript ? property.getNameRu() : property.getName(), String.join(", ", //$NON-NLS-1$
|
||||
property.getTypes()
|
||||
.stream()
|
||||
.map(useRussianScript ? McoreUtil::getTypeNameRu : McoreUtil::getTypeName)
|
||||
.collect(Collectors.toList())));
|
||||
|
||||
resultAceptor.addIssue(message, statment, Literals.RETURN_STATEMENT__EXPRESSION);
|
||||
}
|
||||
|
||||
private void addWarningDeclaredNonReturningPropertyType(ReturnStatement statment, boolean useRussianScript,
|
||||
Property property, List<TypeItem> missingTypes, DocumentationCommentResultAcceptor resultAceptor)
|
||||
{
|
||||
final String message = MessageFormat.format(
|
||||
Messages.FunctionCtorReturnSectionCheck_Declared_property__N__with_type__T__missing_returning_types__M,
|
||||
useRussianScript ? property.getNameRu() : property.getName(), String.join(", ", //$NON-NLS-1$
|
||||
property.getTypes()
|
||||
.stream()
|
||||
.map(useRussianScript ? McoreUtil::getTypeNameRu : McoreUtil::getTypeName)
|
||||
.collect(Collectors.toList())),
|
||||
String.join(", ", //$NON-NLS-1$
|
||||
missingTypes.stream()
|
||||
.map(useRussianScript ? McoreUtil::getTypeNameRu : McoreUtil::getTypeName)
|
||||
.collect(Collectors.toList())));
|
||||
|
||||
resultAceptor.addIssue(message, statment, Literals.RETURN_STATEMENT__EXPRESSION);
|
||||
|
||||
}
|
||||
|
||||
private boolean isWarningReturnNonDeclaredProperty(Function function, ReturnStatement statment,
|
||||
Collection<Property> computedReturnProperties)
|
||||
{
|
||||
return function.isExport();
|
||||
}
|
||||
|
||||
private void addWarningNonDeclaredReturningProperty(ReturnStatement statment, boolean useRussianScript,
|
||||
Collection<String> properties, DocumentationCommentResultAcceptor resultAceptor)
|
||||
{
|
||||
|
||||
final String message = MessageFormat.format(
|
||||
Messages.FunctionCtorReturnSectionCheck_Return_non_declared_propertes__N, String.join(", ", properties)); //$NON-NLS-1$
|
||||
|
||||
resultAceptor.addIssue(message, statment, Literals.RETURN_STATEMENT__EXPRESSION);
|
||||
|
||||
}
|
||||
|
||||
private boolean isRussianScriptVariantProject(IProject project)
|
||||
{
|
||||
IV8Project v8Project = v8ProjectManager.getProject(project);
|
||||
|
||||
return (v8Project != null) && (v8Project.getScriptVariant() == ScriptVariant.RUSSIAN);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2021, 1C-Soft LLC and others.
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* 1C-Soft LLC - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.e1c.v8codestyle.bsl.strict.check;
|
||||
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
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.core.platform.IResourceLookup;
|
||||
import com._1c.g5.v8.dt.mcore.McorePackage;
|
||||
import com.e1c.g5.v8.dt.check.CheckComplexity;
|
||||
import com.e1c.g5.v8.dt.check.ICheckParameters;
|
||||
import com.e1c.g5.v8.dt.check.components.ModuleTopObjectNameFilterExtension;
|
||||
import com.e1c.g5.v8.dt.check.settings.IssueSeverity;
|
||||
import com.e1c.g5.v8.dt.check.settings.IssueType;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
* Checks function has return value types either computed from code or declared in documentation comment.
|
||||
*
|
||||
* @author Dmitriy Marmyshev
|
||||
*/
|
||||
public class FunctionReturnTypeCheck
|
||||
extends AbstractTypeCheck
|
||||
{
|
||||
private static final String CHECK_ID = "function-return-value-type"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Instantiates a new function return type check.
|
||||
*
|
||||
* @param resourceLookup the resource lookup service, cannot be {@code null}.
|
||||
* @param bslPreferences the BSL preferences service, cannot be {@code null}.
|
||||
* @param qualifiedNameConverter the qualified name converter service, cannot be {@code null}.
|
||||
*/
|
||||
@Inject
|
||||
public FunctionReturnTypeCheck(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.FunctionReturnTypeCheck_title)
|
||||
.description(Messages.FunctionReturnTypeCheck_description)
|
||||
.complexity(CheckComplexity.NORMAL)
|
||||
.severity(IssueSeverity.MAJOR)
|
||||
.issueType(IssueType.CODE_STYLE)
|
||||
.extension(new ModuleTopObjectNameFilterExtension())
|
||||
.extension(new StrictTypeAnnotationCheckExtension())
|
||||
.module()
|
||||
.checkedObjectType(BslPackage.Literals.FUNCTION);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void check(Object object, ResultAcceptor resultAceptor, ICheckParameters parameters,
|
||||
IProgressMonitor monitor)
|
||||
{
|
||||
if (monitor.isCanceled() || !(object instanceof EObject))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (isEmptyTypes((EObject)object))
|
||||
{
|
||||
resultAceptor.addIssue(Messages.FunctionReturnTypeCheck_Function_has_no_return_value_type,
|
||||
McorePackage.Literals.NAMED_ELEMENT__NAME);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,305 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2021, 1C-Soft LLC and others.
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* 1C-Soft LLC - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.e1c.v8codestyle.bsl.strict.check;
|
||||
|
||||
import static com._1c.g5.v8.dt.bsl.model.BslPackage.Literals.DYNAMIC_FEATURE_ACCESS;
|
||||
import static com._1c.g5.v8.dt.bsl.model.BslPackage.Literals.STATIC_FEATURE_ACCESS;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.emf.common.util.URI;
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.xtext.EcoreUtil2;
|
||||
import org.eclipse.xtext.naming.IQualifiedNameConverter;
|
||||
import org.eclipse.xtext.resource.IResourceServiceProvider;
|
||||
|
||||
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.Expression;
|
||||
import com._1c.g5.v8.dt.bsl.model.FeatureAccess;
|
||||
import com._1c.g5.v8.dt.bsl.model.FeatureEntry;
|
||||
import com._1c.g5.v8.dt.bsl.model.FormalParam;
|
||||
import com._1c.g5.v8.dt.bsl.model.Invocation;
|
||||
import com._1c.g5.v8.dt.bsl.model.Method;
|
||||
import com._1c.g5.v8.dt.bsl.model.UndefinedLiteral;
|
||||
import com._1c.g5.v8.dt.bsl.model.util.BslUtil;
|
||||
import com._1c.g5.v8.dt.bsl.typesystem.ExportMethodTypeProvider;
|
||||
import com._1c.g5.v8.dt.core.platform.IResourceLookup;
|
||||
import com._1c.g5.v8.dt.mcore.Environmental;
|
||||
import com._1c.g5.v8.dt.mcore.ParamSet;
|
||||
import com._1c.g5.v8.dt.mcore.Parameter;
|
||||
import com._1c.g5.v8.dt.mcore.TypeItem;
|
||||
import com._1c.g5.v8.dt.mcore.util.Environments;
|
||||
import com._1c.g5.v8.dt.mcore.util.McoreUtil;
|
||||
import com._1c.g5.v8.dt.platform.IEObjectTypeNames;
|
||||
import com.e1c.g5.v8.dt.check.CheckComplexity;
|
||||
import com.e1c.g5.v8.dt.check.ICheckParameters;
|
||||
import com.e1c.g5.v8.dt.check.components.ModuleTopObjectNameFilterExtension;
|
||||
import com.e1c.g5.v8.dt.check.settings.IssueSeverity;
|
||||
import com.e1c.g5.v8.dt.check.settings.IssueType;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
* Checks invokable method parameter types intersects with types of invocation expression.
|
||||
*
|
||||
* @author Dmitriy Marmyshev
|
||||
*/
|
||||
public class InvocationParamIntersectionCheck
|
||||
extends AbstractTypeCheck
|
||||
{
|
||||
|
||||
private static final String CHECK_ID = "invocation-parameter-type-intersect"; //$NON-NLS-1$
|
||||
|
||||
private final ExportMethodTypeProvider exportMethodTypeProvider;
|
||||
|
||||
/**
|
||||
* Instantiates a new invocation param intersection check.
|
||||
*
|
||||
* @param resourceLookup the resource lookup service, cannot be {@code null}.
|
||||
* @param bslPreferences the BSL preferences service, cannot be {@code null}.
|
||||
* @param qualifiedNameConverter the qualified name converter service, cannot be {@code null}.
|
||||
*/
|
||||
@Inject
|
||||
public InvocationParamIntersectionCheck(IResourceLookup resourceLookup, IBslPreferences bslPreferences,
|
||||
IQualifiedNameConverter qualifiedNameConverter)
|
||||
{
|
||||
super(resourceLookup, bslPreferences, qualifiedNameConverter);
|
||||
|
||||
IResourceServiceProvider rsp =
|
||||
IResourceServiceProvider.Registry.INSTANCE.getResourceServiceProvider(URI.createURI("*.bsl")); //$NON-NLS-1$
|
||||
this.exportMethodTypeProvider = rsp.get(ExportMethodTypeProvider.class);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCheckId()
|
||||
{
|
||||
return CHECK_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureCheck(CheckConfigurer builder)
|
||||
{
|
||||
builder.title(Messages.InvocationParamIntersectionCheck_title)
|
||||
.description(Messages.InvocationParamIntersectionCheck_description)
|
||||
.complexity(CheckComplexity.NORMAL)
|
||||
.severity(IssueSeverity.MAJOR)
|
||||
.issueType(IssueType.CODE_STYLE)
|
||||
.extension(new ModuleTopObjectNameFilterExtension())
|
||||
.extension(new StrictTypeAnnotationCheckExtension())
|
||||
.module()
|
||||
.checkedObjectType(STATIC_FEATURE_ACCESS, DYNAMIC_FEATURE_ACCESS);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void check(Object object, ResultAcceptor resultAceptor, ICheckParameters parameters,
|
||||
IProgressMonitor monitor)
|
||||
{
|
||||
if (monitor.isCanceled() || !(object instanceof EObject))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FeatureAccess fa = (FeatureAccess)object;
|
||||
|
||||
Invocation inv = BslUtil.getInvocation(fa);
|
||||
if (inv == null || inv.getParams().isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
EObject source = getSourceMethod(fa);
|
||||
if (source instanceof Method)
|
||||
{
|
||||
checkParamTypesIntersect(inv, (Method)source, resultAceptor, monitor);
|
||||
}
|
||||
else if (source instanceof com._1c.g5.v8.dt.mcore.Method)
|
||||
{
|
||||
checkParamTypesIntersect(inv, (com._1c.g5.v8.dt.mcore.Method)source, resultAceptor, monitor);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkParamTypesIntersect(Invocation inv, com._1c.g5.v8.dt.mcore.Method method,
|
||||
ResultAcceptor resultAceptor, IProgressMonitor monitor)
|
||||
{
|
||||
if (method.getParamSet().isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
List<ParamSet> paramSets = actualParamSet(method, inv.getParams().size());
|
||||
if (paramSets.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Environments actualEnvs = getActualEnvironments(inv);
|
||||
|
||||
for (int i = 0; i < inv.getParams().size(); i++)
|
||||
{
|
||||
if (monitor.isCanceled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Expression param = inv.getParams().get(i);
|
||||
List<TypeItem> sorceTypes = computeTypes(param, actualEnvs);
|
||||
boolean isUndefined = param == null || param instanceof UndefinedLiteral || isUndefinedType(sorceTypes);
|
||||
|
||||
List<TypeItem> targetTypes = Collections.emptyList();
|
||||
boolean isIntersect = false;
|
||||
for (Iterator<ParamSet> iterator = paramSets.iterator(); iterator.hasNext();)
|
||||
{
|
||||
ParamSet paramSet = iterator.next();
|
||||
|
||||
List<Parameter> targetParams = paramSet.getParams();
|
||||
if (targetParams.size() <= i)
|
||||
{
|
||||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
boolean isDefaultValue = targetParams.get(i).isDefaultValue();
|
||||
|
||||
if (isDefaultValue && isUndefined)
|
||||
{
|
||||
isIntersect = true;
|
||||
break;
|
||||
}
|
||||
|
||||
targetTypes = exportMethodTypeProvider.getMethodParamType(method, paramSet, i);
|
||||
if (targetTypes.isEmpty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
isIntersect = intersectTypeItem(targetTypes, sorceTypes, inv);
|
||||
if (isIntersect)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isIntersect && !targetTypes.isEmpty())
|
||||
{
|
||||
markInvalidSourceTypeNoIntercection(param, i, resultAceptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isUndefinedType(List<TypeItem> types)
|
||||
{
|
||||
if (types.size() == 1)
|
||||
{
|
||||
return IEObjectTypeNames.UNDEFINED.equals(McoreUtil.getTypeName(types.get(0)));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void checkParamTypesIntersect(Invocation inv, Method method, ResultAcceptor resultAceptor,
|
||||
IProgressMonitor monitor)
|
||||
{
|
||||
|
||||
Environments actualEnvs = getActualEnvironments(inv);
|
||||
|
||||
List<FormalParam> targetParams = method.getFormalParams();
|
||||
for (int i = 0; i < inv.getParams().size(); i++)
|
||||
{
|
||||
if (monitor.isCanceled() || targetParams.size() <= i)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
List<TypeItem> targetTypes = computeTypes(targetParams.get(i), actualEnvs);
|
||||
|
||||
if (targetTypes.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Expression param = inv.getParams().get(i);
|
||||
|
||||
List<TypeItem> sorceTypes = computeTypes(param, actualEnvs);
|
||||
|
||||
if (!intersectTypeItem(targetTypes, sorceTypes, inv))
|
||||
{
|
||||
markInvalidSourceTypeNoIntercection(param, i, resultAceptor);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void markInvalidSourceTypeNoIntercection(Expression param, int index, ResultAcceptor resultAceptor)
|
||||
{
|
||||
String message = MessageFormat.format(
|
||||
Messages.StrictModuleInvocationCheck_Type_of_N_parameter_not_intersect_with_invocation_type, index + 1);
|
||||
resultAceptor.addIssue(message, param, BslPackage.Literals.EXPRESSION__TYPES);
|
||||
}
|
||||
|
||||
private EObject getSourceMethod(FeatureAccess object)
|
||||
{
|
||||
Environments actualEnvs = getActualEnvironments(object);
|
||||
if (actualEnvs.isEmpty())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
List<FeatureEntry> objects = dynamicFeatureAccessComputer.resolveObject(object, actualEnvs);
|
||||
for (FeatureEntry entry : objects)
|
||||
{
|
||||
EObject source = entry.getFeature();
|
||||
if (source instanceof Method || (source instanceof com._1c.g5.v8.dt.mcore.Method))
|
||||
{
|
||||
return source;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Environments getActualEnvironments(EObject object)
|
||||
{
|
||||
Environmental envs = EcoreUtil2.getContainerOfType(object, Environmental.class);
|
||||
if (envs == null)
|
||||
{
|
||||
return Environments.EMPTY;
|
||||
}
|
||||
|
||||
return bslPreferences.getLoadEnvs(object).intersect(envs.environments());
|
||||
}
|
||||
|
||||
private List<ParamSet> actualParamSet(com._1c.g5.v8.dt.mcore.Method method, int numParam)
|
||||
{
|
||||
List<ParamSet> result = new ArrayList<>();
|
||||
List<ParamSet> paramSets = method.getParamSet();
|
||||
for (ParamSet paramSet : paramSets)
|
||||
{
|
||||
if (numParam >= paramSet.getMinParams()
|
||||
|| numParam <= paramSet.getMaxParams() && paramSet.getMaxParams() != -1)
|
||||
{
|
||||
result.add(paramSet);
|
||||
}
|
||||
}
|
||||
if (result.isEmpty() && numParam > 0 && !paramSets.isEmpty())
|
||||
{
|
||||
result.addAll(paramSets);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2021, 1C-Soft LLC and others.
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* 1C-Soft LLC - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.e1c.v8codestyle.bsl.strict.check;
|
||||
|
||||
import org.eclipse.osgi.util.NLS;
|
||||
|
||||
/**
|
||||
* @author Dmitriy Marmyshev
|
||||
*
|
||||
*/
|
||||
final class Messages
|
||||
extends NLS
|
||||
{
|
||||
private static final String BUNDLE_NAME = "com.e1c.v8codestyle.bsl.strict.check.messages"; //$NON-NLS-1$
|
||||
public static String DocCommentFieldTypeCheck_description;
|
||||
public static String DocCommentFieldTypeCheck_Field__N__has_no_type_definition;
|
||||
public static String DocCommentFieldTypeCheck_title;
|
||||
public static String DynamicFeatureAccessMethodNotFoundCheck_description;
|
||||
public static String DynamicFeatureAccessMethodNotFoundCheck_title;
|
||||
public static String DynamicFeatureAccessTypeCheck_description;
|
||||
public static String DynamicFeatureAccessTypeCheck_title;
|
||||
public static String DynamicFeatureAccessTypeCheck_Feature_access_M_has_no_return_type;
|
||||
public static String DynamicFeatureAccessTypeCheck_Method_M_not_found_in_accessed_object;
|
||||
public static String FunctionCtorReturnSectionCheck_description;
|
||||
public static String FunctionCtorReturnSectionCheck_title;
|
||||
public static String FunctionCtorReturnSectionCheck_User_extandable_Data_type_list_comma_separated;
|
||||
public static String FunctionCtorReturnSectionCheck_Declared_property__N__with_type__T__missing_returning_types__M;
|
||||
public static String FunctionCtorReturnSectionCheck_Declared_property__N__with_type__T__not_returning;
|
||||
public static String FunctionCtorReturnSectionCheck_Return_non_declared_propertes__N;
|
||||
public static String FunctionCtorReturnSectionCheck_Return_non_declared_type__T;
|
||||
public static String FunctionReturnTypeCheck_description;
|
||||
public static String FunctionReturnTypeCheck_title;
|
||||
public static String FunctionReturnTypeCheck_Function_has_no_return_value_type;
|
||||
public static String InvocationParamIntersectionCheck_description;
|
||||
public static String InvocationParamIntersectionCheck_title;
|
||||
public static String MethodParamTypeCheck_description;
|
||||
public static String MethodParamTypeCheck_title;
|
||||
public static String MethodParamTypeCheck_Method_param_N_has_no_value_type;
|
||||
public static String SimpleStatementTypeCheck_Allow_local_Variable_reset_to_Undefined_type;
|
||||
public static String SimpleStatementTypeCheck_description;
|
||||
public static String SimpleStatementTypeCheck_title;
|
||||
public static String SimpleStatementTypeCheck_Value_type_N_changed_to_M;
|
||||
public static String StrictModuleInvocationCheck_Type_of_N_parameter_not_intersect_with_invocation_type;
|
||||
public static String StrictTypeAnnotationCheckExtension_Check__strict_types_annotation_in_module_desctioption;
|
||||
public static String StructureCtorValueTypeCheck_description;
|
||||
public static String StructureCtorValueTypeCheck_Structure_key__N__K__has_no_default_value_initializer;
|
||||
public static String StructureCtorValueTypeCheck_Structure_key__N__K__value_initialized_with_empty_types;
|
||||
public static String StructureCtorValueTypeCheck_title;
|
||||
public static String VariableTypeCheck_description;
|
||||
public static String VariableTypeCheck_title;
|
||||
public static String VariableTypeCheck_Variable_M_has_no_value_type;
|
||||
static
|
||||
{
|
||||
// initialize resource bundle
|
||||
NLS.initializeMessages(BUNDLE_NAME, Messages.class);
|
||||
}
|
||||
|
||||
private Messages()
|
||||
{
|
||||
}
|
||||
}
|
@ -0,0 +1,99 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2021, 1C-Soft LLC and others.
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* 1C-Soft LLC - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.e1c.v8codestyle.bsl.strict.check;
|
||||
|
||||
import static com._1c.g5.v8.dt.bsl.model.BslPackage.Literals.FORMAL_PARAM;
|
||||
import static com._1c.g5.v8.dt.mcore.McorePackage.Literals.NAMED_ELEMENT__NAME;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.xtext.naming.IQualifiedNameConverter;
|
||||
|
||||
import com._1c.g5.v8.dt.bsl.common.IBslPreferences;
|
||||
import com._1c.g5.v8.dt.bsl.model.FormalParam;
|
||||
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.components.ModuleTopObjectNameFilterExtension;
|
||||
import com.e1c.g5.v8.dt.check.settings.IssueSeverity;
|
||||
import com.e1c.g5.v8.dt.check.settings.IssueType;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
* Checks method formal parameter has type either computed or declared in documentation comment.
|
||||
*
|
||||
* @author Dmitriy Marmyshev
|
||||
*/
|
||||
public class MethodParamTypeCheck
|
||||
extends AbstractTypeCheck
|
||||
{
|
||||
|
||||
private static final String CHECK_ID = "method-param-value-type"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Instantiates a new method formal parameter type check.
|
||||
*
|
||||
* @param resourceLookup the resource lookup service, cannot be {@code null}.
|
||||
* @param bslPreferences the BSL preferences service, cannot be {@code null}.
|
||||
* @param qualifiedNameConverter the qualified name converter service, cannot be {@code null}.
|
||||
*/
|
||||
@Inject
|
||||
public MethodParamTypeCheck(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.MethodParamTypeCheck_title)
|
||||
.description(Messages.MethodParamTypeCheck_description)
|
||||
.complexity(CheckComplexity.NORMAL)
|
||||
.severity(IssueSeverity.MAJOR)
|
||||
.issueType(IssueType.CODE_STYLE)
|
||||
.extension(new ModuleTopObjectNameFilterExtension())
|
||||
.extension(new StrictTypeAnnotationCheckExtension())
|
||||
.module()
|
||||
.checkedObjectType(FORMAL_PARAM);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void check(Object object, ResultAcceptor resultAceptor, ICheckParameters parameters,
|
||||
IProgressMonitor monitor)
|
||||
{
|
||||
if (monitor.isCanceled() || !(object instanceof EObject))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FormalParam param = (FormalParam)object;
|
||||
|
||||
if (isEmptyTypes(param))
|
||||
{
|
||||
String message =
|
||||
MessageFormat.format(Messages.MethodParamTypeCheck_Method_param_N_has_no_value_type, param.getName());
|
||||
|
||||
resultAceptor.addIssue(message, NAMED_ELEMENT__NAME);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,214 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2021, 1C-Soft LLC and others.
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* 1C-Soft LLC - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.e1c.v8codestyle.bsl.strict.check;
|
||||
|
||||
import static com._1c.g5.v8.dt.bsl.model.BslPackage.Literals.SIMPLE_STATEMENT;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
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.Expression;
|
||||
import com._1c.g5.v8.dt.bsl.model.FeatureAccess;
|
||||
import com._1c.g5.v8.dt.bsl.model.FeatureEntry;
|
||||
import com._1c.g5.v8.dt.bsl.model.ImplicitVariable;
|
||||
import com._1c.g5.v8.dt.bsl.model.SimpleStatement;
|
||||
import com._1c.g5.v8.dt.bsl.model.StaticFeatureAccess;
|
||||
import com._1c.g5.v8.dt.bsl.util.BslUtil;
|
||||
import com._1c.g5.v8.dt.core.platform.IResourceLookup;
|
||||
import com._1c.g5.v8.dt.core.platform.IV8ProjectManager;
|
||||
import com._1c.g5.v8.dt.mcore.Environmental;
|
||||
import com._1c.g5.v8.dt.mcore.TypeItem;
|
||||
import com._1c.g5.v8.dt.mcore.util.Environments;
|
||||
import com._1c.g5.v8.dt.mcore.util.McoreUtil;
|
||||
import com._1c.g5.v8.dt.platform.IEObjectTypeNames;
|
||||
import com.e1c.g5.v8.dt.check.CheckComplexity;
|
||||
import com.e1c.g5.v8.dt.check.ICheckParameters;
|
||||
import com.e1c.g5.v8.dt.check.components.ModuleTopObjectNameFilterExtension;
|
||||
import com.e1c.g5.v8.dt.check.settings.IssueSeverity;
|
||||
import com.e1c.g5.v8.dt.check.settings.IssueType;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
* Checks all simple statements that changes type from one to another, that should not do.
|
||||
* Implicit variable allowed to reset to {@code Undefined} type by parameter.
|
||||
*
|
||||
* @author Dmitriy Marmyshev
|
||||
*/
|
||||
public class SimpleStatementTypeCheck
|
||||
extends AbstractTypeCheck
|
||||
{
|
||||
private static final String CHECK_ID = "statement-type-change"; //$NON-NLS-1$
|
||||
|
||||
private static final String PARAM_ALLOW_IMPLICIT_VAR_RESET_TO_UNDEFINED = "allowImplicitVariableResetToUndefined"; //$NON-NLS-1$
|
||||
|
||||
private static final String DEFAULT_ALLOW_IMPLICIT_VAR_RESET_TO_UNDEFINED = Boolean.TRUE.toString();
|
||||
|
||||
private final IV8ProjectManager v8ProjectManager;
|
||||
|
||||
/**
|
||||
* Instantiates a new simple statement change type check.
|
||||
*
|
||||
* @param resourceLookup the resource lookup service, cannot be {@code null}.
|
||||
* @param bslPreferences the BSL preferences service, cannot be {@code null}.
|
||||
* @param v8ProjectManager the v8 project manager service, cannot be {@code null}.
|
||||
* @param qualifiedNameConverter the qualified name converter service, cannot be {@code null}.
|
||||
*/
|
||||
@Inject
|
||||
public SimpleStatementTypeCheck(IResourceLookup resourceLookup, IBslPreferences bslPreferences,
|
||||
IV8ProjectManager v8ProjectManager, IQualifiedNameConverter qualifiedNameConverter)
|
||||
{
|
||||
super(resourceLookup, bslPreferences, qualifiedNameConverter);
|
||||
this.v8ProjectManager = v8ProjectManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCheckId()
|
||||
{
|
||||
return CHECK_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureCheck(CheckConfigurer builder)
|
||||
{
|
||||
builder.title(Messages.SimpleStatementTypeCheck_title)
|
||||
.description(Messages.SimpleStatementTypeCheck_description)
|
||||
.complexity(CheckComplexity.NORMAL)
|
||||
.severity(IssueSeverity.MAJOR)
|
||||
.issueType(IssueType.CODE_STYLE)
|
||||
.extension(new ModuleTopObjectNameFilterExtension())
|
||||
.extension(new StrictTypeAnnotationCheckExtension())
|
||||
.module()
|
||||
.checkedObjectType(SIMPLE_STATEMENT)
|
||||
.parameter(PARAM_ALLOW_IMPLICIT_VAR_RESET_TO_UNDEFINED, Boolean.class,
|
||||
DEFAULT_ALLOW_IMPLICIT_VAR_RESET_TO_UNDEFINED,
|
||||
Messages.SimpleStatementTypeCheck_Allow_local_Variable_reset_to_Undefined_type);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void check(Object object, ResultAcceptor resultAceptor, ICheckParameters parameters,
|
||||
IProgressMonitor monitor)
|
||||
{
|
||||
if (monitor.isCanceled() || !(object instanceof EObject))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SimpleStatement statment = (SimpleStatement)object;
|
||||
|
||||
Expression left = statment.getLeft();
|
||||
if (left instanceof StaticFeatureAccess && ((StaticFeatureAccess)left).getImplicitVariable() != null)
|
||||
{
|
||||
// check new variable type exist in VariableTypeCheck
|
||||
return;
|
||||
}
|
||||
|
||||
if (left == null || statment.getRight() == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Environmental envs = EcoreUtil2.getContainerOfType(statment, Environmental.class);
|
||||
|
||||
Environments actualEnvs = bslPreferences.getLoadEnvs(statment).intersect(envs.environments());
|
||||
if (actualEnvs.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
List<TypeItem> types = computeTypes(left, actualEnvs);
|
||||
if (monitor.isCanceled() || types.isEmpty())
|
||||
{
|
||||
// empty previous types will be warned in upper code of module
|
||||
return;
|
||||
}
|
||||
|
||||
boolean allowImplicitVarResetToUndefined = parameters.getBoolean(PARAM_ALLOW_IMPLICIT_VAR_RESET_TO_UNDEFINED);
|
||||
|
||||
boolean canResetToUndefined = allowImplicitVarResetToUndefined && isImplicitVariableSource(left, actualEnvs);
|
||||
|
||||
List<TypeItem> newTypes = computeTypes(statment.getRight(), actualEnvs);
|
||||
if (!monitor.isCanceled() && !hasTypeIntersection(types, newTypes, statment, canResetToUndefined))
|
||||
{
|
||||
boolean isRussian = com._1c.g5.v8.dt.bsl.util.BslUtil.isRussian(statment, this.v8ProjectManager);
|
||||
|
||||
String message = MessageFormat.format(Messages.SimpleStatementTypeCheck_Value_type_N_changed_to_M,
|
||||
getTypesPresentation(types, isRussian), getTypesPresentation(newTypes, isRussian));
|
||||
|
||||
resultAceptor.addIssue(message, BslPackage.Literals.SIMPLE_STATEMENT__LEFT);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isImplicitVariableSource(Expression expression, Environments actualEnvs)
|
||||
{
|
||||
if (expression instanceof StaticFeatureAccess)
|
||||
{
|
||||
List<FeatureEntry> features =
|
||||
dynamicFeatureAccessComputer.resolveObject((FeatureAccess)expression, actualEnvs);
|
||||
|
||||
for (FeatureEntry feature : features)
|
||||
{
|
||||
if (feature.getFeature() instanceof ImplicitVariable)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean hasTypeIntersection(List<TypeItem> source, List<TypeItem> target, EObject context,
|
||||
boolean canResetToUndefined)
|
||||
{
|
||||
if (target.isEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Set<String> targetNames = Sets.newLinkedHashSet(BslUtil.transform(target, BslUtil.TYPE_NAME));
|
||||
|
||||
if (canResetToUndefined && targetNames.contains(IEObjectTypeNames.UNDEFINED) && targetNames.size() == 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return intersectTypeItem(source, target, context);
|
||||
}
|
||||
|
||||
private String getTypesPresentation(List<TypeItem> types, boolean isRussian)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
for (TypeItem type : types)
|
||||
{
|
||||
if (sb.length() > 0)
|
||||
{
|
||||
sb.append(", "); //$NON-NLS-1$
|
||||
}
|
||||
sb.append(isRussian ? McoreUtil.getTypeNameRu(type) : McoreUtil.getTypeName(type));
|
||||
}
|
||||
return sb.toString();
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2021, 1C-Soft LLC and others.
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* 1C-Soft LLC - initial API and implementation
|
||||
*******************************************************************************/
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package com.e1c.v8codestyle.bsl.strict.check;
|
||||
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.xtext.EcoreUtil2;
|
||||
|
||||
import com._1c.g5.v8.dt.bsl.model.Module;
|
||||
import com.e1c.g5.v8.dt.check.CheckParameterDefinition;
|
||||
import com.e1c.g5.v8.dt.check.ICheckDefinition;
|
||||
import com.e1c.g5.v8.dt.check.ICheckParameters;
|
||||
import com.e1c.g5.v8.dt.check.components.IBasicCheckExtension;
|
||||
import com.e1c.v8codestyle.bsl.strict.StrictTypeUtil;
|
||||
|
||||
/**
|
||||
* The check extension adds parameter allows to skip search for annotation in module header.
|
||||
* The extension also pre-check that that annotation exist.
|
||||
*
|
||||
* @author Dmitriy Marmyshev
|
||||
*/
|
||||
public class StrictTypeAnnotationCheckExtension
|
||||
implements IBasicCheckExtension
|
||||
{
|
||||
|
||||
protected static final String PARAM_CHECK_ANNOTATION_IN_MODULE_DESCRIPTION = "checkAnnotationInModuleDescription"; //$NON-NLS-1$
|
||||
|
||||
protected static final String DEFAULT_CHECK_ANNOTATION_IN_MODULE_DESCRIPTION = Boolean.TRUE.toString();
|
||||
|
||||
@Override
|
||||
public void configureContextCollector(ICheckDefinition definition)
|
||||
{
|
||||
CheckParameterDefinition paramDef = new CheckParameterDefinition(PARAM_CHECK_ANNOTATION_IN_MODULE_DESCRIPTION,
|
||||
Boolean.class, DEFAULT_CHECK_ANNOTATION_IN_MODULE_DESCRIPTION,
|
||||
Messages.StrictTypeAnnotationCheckExtension_Check__strict_types_annotation_in_module_desctioption);
|
||||
definition.addParameterDefinition(paramDef);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean preCheck(Object object, ICheckParameters parameters, IProgressMonitor monitor)
|
||||
{
|
||||
if (monitor.isCanceled() || !(object instanceof EObject))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean checkAnnotation = parameters.getBoolean(PARAM_CHECK_ANNOTATION_IN_MODULE_DESCRIPTION);
|
||||
if (!checkAnnotation)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
Module module = EcoreUtil2.getContainerOfType((EObject)object, Module.class);
|
||||
|
||||
if (monitor.isCanceled() || module == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return StrictTypeUtil.hasStrictTypeAnnotation(module);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,131 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2021, 1C-Soft LLC and others.
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* 1C-Soft LLC - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.e1c.v8codestyle.bsl.strict.check;
|
||||
|
||||
import static com._1c.g5.v8.dt.bsl.model.BslPackage.Literals.OPERATOR_STYLE_CREATOR;
|
||||
import static com._1c.g5.v8.dt.bsl.model.BslPackage.Literals.STRING_LITERAL__LINES;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.xtext.naming.IQualifiedNameConverter;
|
||||
|
||||
import com._1c.g5.v8.dt.bsl.common.IBslPreferences;
|
||||
import com._1c.g5.v8.dt.bsl.model.EmptyExpression;
|
||||
import com._1c.g5.v8.dt.bsl.model.Expression;
|
||||
import com._1c.g5.v8.dt.bsl.model.OperatorStyleCreator;
|
||||
import com._1c.g5.v8.dt.bsl.model.StringLiteral;
|
||||
import com._1c.g5.v8.dt.core.platform.IResourceLookup;
|
||||
import com._1c.g5.v8.dt.mcore.util.McoreUtil;
|
||||
import com._1c.g5.v8.dt.platform.IEObjectTypeNames;
|
||||
import com.e1c.g5.v8.dt.check.CheckComplexity;
|
||||
import com.e1c.g5.v8.dt.check.ICheckParameters;
|
||||
import com.e1c.g5.v8.dt.check.components.ModuleTopObjectNameFilterExtension;
|
||||
import com.e1c.g5.v8.dt.check.settings.IssueSeverity;
|
||||
import com.e1c.g5.v8.dt.check.settings.IssueType;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
* Checks Structure constructor string literal that each key has typed value.
|
||||
*
|
||||
* @author Dmitriy Marmyshev
|
||||
*/
|
||||
public class StructureCtorValueTypeCheck
|
||||
extends AbstractTypeCheck
|
||||
{
|
||||
|
||||
private static final String CHECK_ID = "structure-consructor-value-type"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Instantiates a new structure constructor value type check.
|
||||
*
|
||||
* @param resourceLookup the resource lookup service, cannot be {@code null}.
|
||||
* @param bslPreferences the BSL preferences service, cannot be {@code null}.
|
||||
* @param qualifiedNameConverter the qualified name converter service, cannot be {@code null}.
|
||||
*/
|
||||
@Inject
|
||||
public StructureCtorValueTypeCheck(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.StructureCtorValueTypeCheck_title)
|
||||
.description(Messages.StructureCtorValueTypeCheck_description)
|
||||
.complexity(CheckComplexity.NORMAL)
|
||||
.severity(IssueSeverity.MAJOR)
|
||||
.issueType(IssueType.CODE_STYLE)
|
||||
.extension(new ModuleTopObjectNameFilterExtension())
|
||||
.extension(new StrictTypeAnnotationCheckExtension())
|
||||
.module()
|
||||
.checkedObjectType(OPERATOR_STYLE_CREATOR);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void check(Object object, ResultAcceptor resultAceptor, ICheckParameters parameters,
|
||||
IProgressMonitor monitor)
|
||||
{
|
||||
OperatorStyleCreator osc = (OperatorStyleCreator)object;
|
||||
if (monitor.isCanceled() || osc.getParams().isEmpty()
|
||||
|| !IEObjectTypeNames.STRUCTURE.equals(McoreUtil.getTypeName(osc.getType()))
|
||||
|| !(osc.getParams().get(0) instanceof StringLiteral))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
StringLiteral literal = (StringLiteral)osc.getParams().get(0);
|
||||
|
||||
String content = String.join("", literal.lines(true)); //$NON-NLS-1$
|
||||
String[] keys = content.replace(" ", "").split(","); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||
|
||||
int totalParams = osc.getParams().size() - 1;
|
||||
for (int i = 0; i < keys.length; i++)
|
||||
{
|
||||
if (monitor.isCanceled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
String key = keys[i];
|
||||
if (totalParams > i && osc.getParams().get(i + 1) != null)
|
||||
{
|
||||
Expression param = osc.getParams().get(i + 1);
|
||||
if (isEmptyTypes(param))
|
||||
{
|
||||
param = param instanceof EmptyExpression ? literal : param;
|
||||
String message = MessageFormat.format(
|
||||
Messages.StructureCtorValueTypeCheck_Structure_key__N__K__value_initialized_with_empty_types,
|
||||
i + 1, key);
|
||||
resultAceptor.addIssue(message, param);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
String message = MessageFormat.format(
|
||||
Messages.StructureCtorValueTypeCheck_Structure_key__N__K__has_no_default_value_initializer, i + 1,
|
||||
key);
|
||||
resultAceptor.addIssue(message, literal, STRING_LITERAL__LINES);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,131 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2021, 1C-Soft LLC and others.
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* 1C-Soft LLC - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.e1c.v8codestyle.bsl.strict.check;
|
||||
|
||||
import static com._1c.g5.v8.dt.bsl.model.BslPackage.Literals.DECLARE_STATEMENT;
|
||||
import static com._1c.g5.v8.dt.bsl.model.BslPackage.Literals.EXPLICIT_VARIABLE;
|
||||
import static com._1c.g5.v8.dt.bsl.model.BslPackage.Literals.IMPLICIT_VARIABLE;
|
||||
import static com._1c.g5.v8.dt.bsl.model.BslPackage.Literals.SIMPLE_STATEMENT;
|
||||
import static com._1c.g5.v8.dt.mcore.McorePackage.Literals.NAMED_ELEMENT__NAME;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.xtext.naming.IQualifiedNameConverter;
|
||||
|
||||
import com._1c.g5.v8.dt.bsl.common.IBslPreferences;
|
||||
import com._1c.g5.v8.dt.bsl.model.DeclareStatement;
|
||||
import com._1c.g5.v8.dt.bsl.model.ExplicitVariable;
|
||||
import com._1c.g5.v8.dt.bsl.model.ImplicitVariable;
|
||||
import com._1c.g5.v8.dt.bsl.model.SimpleStatement;
|
||||
import com._1c.g5.v8.dt.bsl.model.StaticFeatureAccess;
|
||||
import com._1c.g5.v8.dt.bsl.model.Variable;
|
||||
import com._1c.g5.v8.dt.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.components.ModuleTopObjectNameFilterExtension;
|
||||
import com.e1c.g5.v8.dt.check.settings.IssueSeverity;
|
||||
import com.e1c.g5.v8.dt.check.settings.IssueType;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
* Checks variable of the module has value type.
|
||||
*
|
||||
* @author Dmitriy Marmyshev
|
||||
*/
|
||||
public class VariableTypeCheck
|
||||
extends AbstractTypeCheck
|
||||
{
|
||||
|
||||
private static final String CHECK_ID = "variable-value-type"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Instantiates a new variable type check.
|
||||
*
|
||||
* @param resourceLookup the resource lookup service, cannot be {@code null}.
|
||||
* @param bslPreferences the BSL preferences service, cannot be {@code null}.
|
||||
* @param qualifiedNameConverter the qualified name converter service, cannot be {@code null}.
|
||||
*/
|
||||
@Inject
|
||||
public VariableTypeCheck(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.VariableTypeCheck_title)
|
||||
.description(Messages.VariableTypeCheck_description)
|
||||
.complexity(CheckComplexity.NORMAL)
|
||||
.severity(IssueSeverity.MAJOR)
|
||||
.issueType(IssueType.CODE_STYLE)
|
||||
.extension(new ModuleTopObjectNameFilterExtension())
|
||||
.extension(new StrictTypeAnnotationCheckExtension())
|
||||
.module()
|
||||
.checkedObjectType(IMPLICIT_VARIABLE, EXPLICIT_VARIABLE, SIMPLE_STATEMENT, DECLARE_STATEMENT);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void check(Object object, ResultAcceptor resultAceptor, ICheckParameters parameters,
|
||||
IProgressMonitor monitor)
|
||||
{
|
||||
if (monitor.isCanceled() || !(object instanceof EObject))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (object instanceof ImplicitVariable || object instanceof ExplicitVariable)
|
||||
{
|
||||
checkVariable((Variable)object, (EObject)object, resultAceptor, monitor);
|
||||
}
|
||||
else if (object instanceof SimpleStatement && ((SimpleStatement)object).getLeft() instanceof StaticFeatureAccess
|
||||
&& ((StaticFeatureAccess)((SimpleStatement)object).getLeft()).getImplicitVariable() != null)
|
||||
{
|
||||
EObject checkType = ((SimpleStatement)object).getRight();
|
||||
Variable variable = ((StaticFeatureAccess)((SimpleStatement)object).getLeft()).getImplicitVariable();
|
||||
checkVariable(variable, checkType, resultAceptor, monitor);
|
||||
}
|
||||
else if (object instanceof DeclareStatement)
|
||||
{
|
||||
DeclareStatement declare = (DeclareStatement)object;
|
||||
for (Variable variable : declare.getVariables())
|
||||
{
|
||||
checkVariable(variable, variable, resultAceptor, monitor);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void checkVariable(Variable variable, EObject checkObject, ResultAcceptor resultAceptor,
|
||||
IProgressMonitor monitor)
|
||||
{
|
||||
if (!monitor.isCanceled() && checkObject != null && variable != null && isEmptyTypes(checkObject))
|
||||
{
|
||||
String message =
|
||||
MessageFormat.format(Messages.VariableTypeCheck_Variable_M_has_no_value_type, variable.getName());
|
||||
|
||||
resultAceptor.addIssue(message, variable, NAMED_ELEMENT__NAME);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/)
|
||||
###############################################################################
|
||||
# Copyright (C) 2021, 1C-Soft LLC and others.
|
||||
#
|
||||
# This program and the accompanying materials are made
|
||||
# available under the terms of the Eclipse Public License 2.0
|
||||
# which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
#
|
||||
# SPDX-License-Identifier: EPL-2.0
|
||||
#
|
||||
# Contributors:
|
||||
# 1C-Soft LLC - initial API and implementation
|
||||
###############################################################################
|
||||
|
||||
DocCommentFieldTypeCheck_Field__N__has_no_type_definition = Field "{0}" has no type definition
|
||||
|
||||
DocCommentFieldTypeCheck_description = Check of module strict types system that documentation comment field has section with types
|
||||
|
||||
DocCommentFieldTypeCheck_title = Documentation comment Field has no type definition
|
||||
|
||||
DynamicFeatureAccessMethodNotFoundCheck_description = Check of module strict types system that dynamically accessed method exist in the object
|
||||
|
||||
DynamicFeatureAccessMethodNotFoundCheck_title = Method not found in accessed object
|
||||
|
||||
DynamicFeatureAccessTypeCheck_Feature_access_M_has_no_return_type = Feature access "{0}" has no return type
|
||||
|
||||
DynamicFeatureAccessTypeCheck_Method_M_not_found_in_accessed_object = Method "{0}" not found in accessed object
|
||||
|
||||
DynamicFeatureAccessTypeCheck_description = Check of module strict types system that dynamically accessed object property has return type
|
||||
|
||||
DynamicFeatureAccessTypeCheck_title = Object property has return value type
|
||||
|
||||
FunctionCtorReturnSectionCheck_Declared_property__N__with_type__T__missing_returning_types__M = Declared property "{0}" with type: "{1}" missing returning types "{2}"
|
||||
|
||||
FunctionCtorReturnSectionCheck_Declared_property__N__with_type__T__not_returning = Declared property "{0}" with type: "{1}" not returning
|
||||
|
||||
FunctionCtorReturnSectionCheck_Return_non_declared_propertes__N = Return non declared properties: "{0}"
|
||||
|
||||
FunctionCtorReturnSectionCheck_Return_non_declared_type__T = Return non-declared type: {0}
|
||||
|
||||
FunctionCtorReturnSectionCheck_User_extandable_Data_type_list_comma_separated = User-extendable Data type list, comma separated
|
||||
|
||||
FunctionCtorReturnSectionCheck_description = Check of module strict types system that return statements of function equals documentation comment return section types
|
||||
|
||||
FunctionCtorReturnSectionCheck_title = Data constructor function return section
|
||||
|
||||
FunctionReturnTypeCheck_Function_has_no_return_value_type = Function has no return value type
|
||||
|
||||
FunctionReturnTypeCheck_description = Check of module strict types system that every function has return value type
|
||||
|
||||
FunctionReturnTypeCheck_title = Function returns typed value
|
||||
|
||||
InvocationParamIntersectionCheck_description = Check of module strict types system that invocation expression has intersection with invocation parameter type
|
||||
|
||||
InvocationParamIntersectionCheck_title = Invocation parameter types intersects
|
||||
|
||||
MethodParamTypeCheck_Method_param_N_has_no_value_type = Method parameter "{0}" has no value type
|
||||
|
||||
MethodParamTypeCheck_description = Check of module strict types system that every method parameter has value type
|
||||
|
||||
MethodParamTypeCheck_title = Method parameter has value type
|
||||
|
||||
SimpleStatementTypeCheck_Allow_local_Variable_reset_to_Undefined_type = Allow local Variable reset to Undefined type
|
||||
|
||||
SimpleStatementTypeCheck_Value_type_N_changed_to_M = Value type "{0}" changed to "{1}"
|
||||
|
||||
SimpleStatementTypeCheck_description = Check of module strict types system that statement does not change type
|
||||
|
||||
SimpleStatementTypeCheck_title = Statement type change
|
||||
|
||||
StrictModuleInvocationCheck_Type_of_N_parameter_not_intersect_with_invocation_type = Type of "{0}" parameter not intersect with invocation type
|
||||
|
||||
StrictTypeAnnotationCheckExtension_Check__strict_types_annotation_in_module_desctioption = Check @strict-types annotation in module description
|
||||
|
||||
StructureCtorValueTypeCheck_Structure_key__N__K__has_no_default_value_initializer = Structure key {0} "{1}" has no default value initializer
|
||||
|
||||
StructureCtorValueTypeCheck_Structure_key__N__K__value_initialized_with_empty_types = Structure key {0} "{1}" value initialized with empty types
|
||||
|
||||
StructureCtorValueTypeCheck_description = Checks Structure constructor string literal that each key has typed value.
|
||||
|
||||
StructureCtorValueTypeCheck_title = Structure constructor value types
|
||||
|
||||
VariableTypeCheck_Variable_M_has_no_value_type = Variable "{0}" has no value type
|
||||
|
||||
VariableTypeCheck_description = Check of module strict types system that every variable has value type
|
||||
|
||||
VariableTypeCheck_title = Variable has value type
|
@ -0,0 +1,87 @@
|
||||
#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/)
|
||||
###############################################################################
|
||||
# Copyright (C) 2021, 1C-Soft LLC and others.
|
||||
#
|
||||
# This program and the accompanying materials are made
|
||||
# available under the terms of the Eclipse Public License 2.0
|
||||
# which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
#
|
||||
# SPDX-License-Identifier: EPL-2.0
|
||||
#
|
||||
# Contributors:
|
||||
# 1C-Soft LLC - initial API and implementation
|
||||
###############################################################################
|
||||
|
||||
DocCommentFieldTypeCheck_Field__N__has_no_type_definition = Поле "{0}" не имеет описания типа
|
||||
|
||||
DocCommentFieldTypeCheck_description = Система строгой типизации кода проверяет что поле документирующего комментария имеет описание типа
|
||||
|
||||
DocCommentFieldTypeCheck_title = Поле документирующего комментария имеет описание типа
|
||||
|
||||
DynamicFeatureAccessMethodNotFoundCheck_description = Система строгой типизации кода проверяет что динамически вызываемый метод существует в объекте
|
||||
|
||||
DynamicFeatureAccessMethodNotFoundCheck_title = Метод в объекте не найден
|
||||
|
||||
DynamicFeatureAccessTypeCheck_Feature_access_M_has_no_return_type = Свойство "{0}" не имеет типа возвращаемого значения
|
||||
|
||||
DynamicFeatureAccessTypeCheck_Method_M_not_found_in_accessed_object = Метод "{0}" не найден в исходном объекте
|
||||
|
||||
DynamicFeatureAccessTypeCheck_description = Система строгой типизации кода проверяет что динамическое свойство объекта имеет тип возвращаемого значения
|
||||
|
||||
DynamicFeatureAccessTypeCheck_title = Свойство объекта имеет тип возвращаемого значения
|
||||
|
||||
FunctionCtorReturnSectionCheck_Declared_property__N__with_type__T__missing_returning_types__M = Декларируемое свойство "{0}" с типом: "{1}" не содержит возвращемые типы "{2}"
|
||||
|
||||
FunctionCtorReturnSectionCheck_Declared_property__N__with_type__T__not_returning = Декларируемое свойство "{0}" с типом: "{1}" не возвращается
|
||||
|
||||
FunctionCtorReturnSectionCheck_Return_non_declared_propertes__N = Возвращается не декларируемое свойство: "{0}"
|
||||
|
||||
FunctionCtorReturnSectionCheck_Return_non_declared_type__T = Возвращается не декларированный тип: {0}
|
||||
|
||||
FunctionCtorReturnSectionCheck_User_extandable_Data_type_list_comma_separated = Список типов данных расширяемых пользователем, через запятую
|
||||
|
||||
FunctionCtorReturnSectionCheck_description = Система строгой типизации кода проверяет что возвращаемые значения функции эквивалентны секции возвращаемого значения документирующего комментария
|
||||
|
||||
FunctionCtorReturnSectionCheck_title = Секция возвращаемого значения функции-конструктора данных
|
||||
|
||||
FunctionReturnTypeCheck_Function_has_no_return_value_type = Функция не имеет типа возвращаемого значения
|
||||
|
||||
FunctionReturnTypeCheck_description = Система строгой типизации кода проверяет что каждая функция возвращает типизированное значение
|
||||
|
||||
FunctionReturnTypeCheck_title = Функция возвращает типизированное значение
|
||||
|
||||
InvocationParamIntersectionCheck_description = Система строгой типизации кода проверяет что тип вызываемого выражения пересекается с типом параметра вызываемого метода
|
||||
|
||||
InvocationParamIntersectionCheck_title = Вызываеемый тип пересекается с типом параметра
|
||||
|
||||
MethodParamTypeCheck_Method_param_N_has_no_value_type = Параметр метода "{0}" не имеет типа значения
|
||||
|
||||
MethodParamTypeCheck_description = Система строгой типизации кода проверяет что каждый параметр метода имеет тип значения
|
||||
|
||||
MethodParamTypeCheck_title = Параметр метода имеет тип
|
||||
|
||||
SimpleStatementTypeCheck_Allow_local_Variable_reset_to_Undefined_type = Разрешить сбрасывать тип локальных переменных в Неопределено
|
||||
|
||||
SimpleStatementTypeCheck_Value_type_N_changed_to_M = Тип значения "{0}" заменен на "{1}"
|
||||
|
||||
SimpleStatementTypeCheck_description = Система строгой типизации кода проверяет что утверждение (строка присвоения значения) меняет тип
|
||||
|
||||
SimpleStatementTypeCheck_title = Утверждение меняет тип
|
||||
|
||||
StrictModuleInvocationCheck_Type_of_N_parameter_not_intersect_with_invocation_type = Тип "{0}" параметра не пересекается с вызываемым типом
|
||||
|
||||
StrictTypeAnnotationCheckExtension_Check__strict_types_annotation_in_module_desctioption = Проверять аннотацию @strict-types в заголовке модуля
|
||||
|
||||
StructureCtorValueTypeCheck_Structure_key__N__K__has_no_default_value_initializer = Ключ {0} "{1}" Структуры не имеет инициализатора значения по умолчанию
|
||||
|
||||
StructureCtorValueTypeCheck_Structure_key__N__K__value_initialized_with_empty_types = Ключ {0} "{1}" Структуры инициализируется с пустым типом
|
||||
|
||||
StructureCtorValueTypeCheck_description = Проверяет строковый литерал в конструкторе структуры что каждый ключ имеет типзированное значение
|
||||
|
||||
StructureCtorValueTypeCheck_title = Типизация значений в конструкторе структуры
|
||||
|
||||
VariableTypeCheck_Variable_M_has_no_value_type = Переменная "{0}" не имеет типа
|
||||
|
||||
VariableTypeCheck_description = Система строгой типизации кода проверяет что каждая переменная имеет тип значения
|
||||
|
||||
VariableTypeCheck_title = Переменная имеет тип значения
|
@ -14,7 +14,11 @@
|
||||
package com.e1c.v8codestyle.internal.bsl;
|
||||
|
||||
import org.eclipse.core.runtime.Plugin;
|
||||
import org.eclipse.xtext.naming.IQualifiedNameConverter;
|
||||
|
||||
import com._1c.g5.v8.dt.bsl.common.IBslPreferences;
|
||||
import com._1c.g5.v8.dt.core.platform.IResourceLookup;
|
||||
import com._1c.g5.v8.dt.core.platform.IV8ProjectManager;
|
||||
import com._1c.g5.v8.dt.platform.version.IRuntimeVersionSupport;
|
||||
import com._1c.g5.wiring.AbstractServiceAwareModule;
|
||||
|
||||
@ -34,7 +38,11 @@ class ExternalDependenciesModule
|
||||
@Override
|
||||
protected void doConfigure()
|
||||
{
|
||||
bind(IResourceLookup.class).toService();
|
||||
bind(IRuntimeVersionSupport.class).toService();
|
||||
bind(IV8ProjectManager.class).toService();
|
||||
bind(IBslPreferences.class).toService();
|
||||
bind(IQualifiedNameConverter.class).toService();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -10,6 +10,6 @@ Bundle-RequiredExecutionEnvironment: JavaSE-11
|
||||
Bundle-Localization: fragment
|
||||
Import-Package: com._1c.g5.v8.dt.core.platform;version="10.4.0",
|
||||
com._1c.g5.v8.dt.testing;version="[3.1.0,4.0.0)",
|
||||
com._1c.g5.v8.dt.validation.marker;version="4.0.0",
|
||||
com._1c.g5.v8.dt.validation.marker;version="[4.0.0,5.0.0)",
|
||||
com.e1c.g5.v8.dt.testing.check;version="[1.0.0,2.0.0)",
|
||||
org.junit;version="[4.13.0,5.0.0)"
|
||||
|
@ -15,4 +15,5 @@ output.. = bin/
|
||||
bin.includes = META-INF/,\
|
||||
.,\
|
||||
fragment.properties,\
|
||||
workspace/
|
||||
workspace/,\
|
||||
resources/
|
||||
|
@ -0,0 +1,22 @@
|
||||
// @strict-types
|
||||
|
||||
// Returns:
|
||||
// Structure - Non complaint:
|
||||
// * Key1 - Number -
|
||||
// * Key3 - Number -
|
||||
Function NonComplaint() Export
|
||||
|
||||
return new Structure("Key1, Key2", 10, "");
|
||||
|
||||
EndFunction
|
||||
|
||||
// Returns:
|
||||
// Structure - Non complaint:
|
||||
// * Key1 - Number -
|
||||
// * Key2 - String -
|
||||
Function Complaint() Export
|
||||
|
||||
return new Structure("Key1, Key2", 10, "");
|
||||
|
||||
EndFunction
|
||||
|
@ -0,0 +1,15 @@
|
||||
// @strict-types
|
||||
|
||||
// Parameters:
|
||||
// Parameters - Structure:
|
||||
// * Key1 - has not type for key
|
||||
Procedure NonComplaint(Parameters) Export
|
||||
// empty
|
||||
EndProcedure
|
||||
|
||||
// Parameters:
|
||||
// Parameters - Structure:
|
||||
// * Key1 - Number - has type for key
|
||||
Procedure Complaint(Parameters) Export
|
||||
// empty
|
||||
EndProcedure
|
@ -0,0 +1,19 @@
|
||||
// @strict-types
|
||||
|
||||
Procedure NonComplaint(Module) Export
|
||||
|
||||
Module.CostomAction();
|
||||
|
||||
EndProcedure
|
||||
|
||||
Procedure Complaint() Export
|
||||
|
||||
ThisObject.CostomAction();
|
||||
|
||||
EndProcedure
|
||||
|
||||
|
||||
Procedure CostomAction() Export
|
||||
|
||||
|
||||
EndProcedure
|
@ -0,0 +1,15 @@
|
||||
// @strict-types
|
||||
|
||||
Function NonComplaint() Export
|
||||
// empty
|
||||
EndFunction
|
||||
|
||||
Function Complaint()
|
||||
Return 0;
|
||||
EndFunction
|
||||
|
||||
// Returns:
|
||||
// String - returning value
|
||||
Function Complaint() Export
|
||||
// empty
|
||||
EndFunction
|
@ -0,0 +1,17 @@
|
||||
// @strict-types
|
||||
|
||||
Procedure NonComplaint(Strings) Export
|
||||
|
||||
Result = StrConcat(Strings, "1");
|
||||
|
||||
EndProcedure
|
||||
|
||||
|
||||
// Parameters:
|
||||
// Strings - Array
|
||||
Procedure Complaint(Strings) Export
|
||||
|
||||
Result = StrConcat(Strings, "1");
|
||||
|
||||
EndProcedure
|
||||
|
@ -0,0 +1,11 @@
|
||||
// @strict-types
|
||||
|
||||
Procedure NonComplaint(Parameters) Export
|
||||
// empty
|
||||
EndProcedure
|
||||
|
||||
// Parameters:
|
||||
// Parameters - String
|
||||
Procedure Complaint(Parameters) Export
|
||||
// empty
|
||||
EndProcedure
|
@ -0,0 +1,26 @@
|
||||
// @strict-types
|
||||
|
||||
Procedure NonComplaint(Module) Export
|
||||
|
||||
Key1 = CustomAction().Key1;
|
||||
|
||||
EndProcedure
|
||||
|
||||
Procedure Complaint() Export
|
||||
|
||||
Key1 = CustomAction2().Key1;
|
||||
|
||||
EndProcedure
|
||||
|
||||
|
||||
Function CustomAction() Export
|
||||
|
||||
return new Structure("Key1");
|
||||
|
||||
EndFunction
|
||||
|
||||
Function CustomAction2() Export
|
||||
|
||||
return new Structure("Key1", 10);
|
||||
|
||||
EndFunction
|
@ -0,0 +1,13 @@
|
||||
// @strict-types
|
||||
|
||||
// Parameters:
|
||||
// Parameters - String
|
||||
Procedure NonComplaint(Parameters) Export
|
||||
Parameters = 1;
|
||||
EndProcedure
|
||||
|
||||
// Parameters:
|
||||
// Parameters - String
|
||||
Procedure Complaint(Parameters) Export
|
||||
Parameters = "1";
|
||||
EndProcedure
|
@ -0,0 +1,15 @@
|
||||
// @strict-types
|
||||
|
||||
Procedure NonComplaint() Export
|
||||
|
||||
Params = new Structure("Key1,
|
||||
|Key2, Key3", , 1);
|
||||
|
||||
EndProcedure
|
||||
|
||||
Procedure Complaint() Export
|
||||
|
||||
Params = new Structure("Key1, Key2", 0, "");
|
||||
Params.Insert("Key3", "");
|
||||
|
||||
EndProcedure
|
@ -0,0 +1,11 @@
|
||||
// @strict-types
|
||||
|
||||
Procedure NonComplaint() Export
|
||||
Var TestVar;
|
||||
// empty
|
||||
EndProcedure
|
||||
|
||||
Procedure Complaint() Export
|
||||
Var TestVar; // Number
|
||||
// empty
|
||||
EndProcedure
|
@ -0,0 +1,423 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2021, 1C-Soft LLC and others.
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* 1C-Soft LLC - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.e1c.v8codestyle.bsl.strict.check.itests;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.core.resources.IFile;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.NullProgressMonitor;
|
||||
import org.eclipse.emf.ecore.util.EcoreUtil;
|
||||
import org.eclipse.xtext.EcoreUtil2;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import com._1c.g5.v8.bm.core.IBmObject;
|
||||
import com._1c.g5.v8.dt.bsl.model.DynamicFeatureAccess;
|
||||
import com._1c.g5.v8.dt.bsl.model.Function;
|
||||
import com._1c.g5.v8.dt.bsl.model.Method;
|
||||
import com._1c.g5.v8.dt.bsl.model.Module;
|
||||
import com._1c.g5.v8.dt.bsl.model.SimpleStatement;
|
||||
import com._1c.g5.v8.dt.bsl.model.StaticFeatureAccess;
|
||||
import com._1c.g5.v8.dt.bsl.model.StringLiteral;
|
||||
import com._1c.g5.v8.dt.bsl.model.Variable;
|
||||
import com._1c.g5.v8.dt.metadata.mdclass.CommonModule;
|
||||
import com._1c.g5.v8.dt.validation.marker.Marker;
|
||||
import com.e1c.g5.v8.dt.testing.check.SingleProjectReadOnlyCheckTestBase;
|
||||
import com.e1c.v8codestyle.bsl.strict.check.DocCommentFieldTypeCheck;
|
||||
import com.e1c.v8codestyle.bsl.strict.check.DynamicFeatureAccessMethodNotFoundCheck;
|
||||
import com.e1c.v8codestyle.bsl.strict.check.DynamicFeatureAccessTypeCheck;
|
||||
import com.e1c.v8codestyle.bsl.strict.check.FunctionCtorReturnSectionCheck;
|
||||
import com.e1c.v8codestyle.bsl.strict.check.FunctionReturnTypeCheck;
|
||||
import com.e1c.v8codestyle.bsl.strict.check.InvocationParamIntersectionCheck;
|
||||
import com.e1c.v8codestyle.bsl.strict.check.MethodParamTypeCheck;
|
||||
import com.e1c.v8codestyle.bsl.strict.check.SimpleStatementTypeCheck;
|
||||
import com.e1c.v8codestyle.bsl.strict.check.StructureCtorValueTypeCheck;
|
||||
import com.e1c.v8codestyle.bsl.strict.check.VariableTypeCheck;
|
||||
|
||||
/**
|
||||
* Tests of strict types system in BSL module.
|
||||
*
|
||||
* @author Dmitriy Marmyshev
|
||||
*/
|
||||
public class CommonModuleStrictTypesTest
|
||||
extends SingleProjectReadOnlyCheckTestBase
|
||||
{
|
||||
|
||||
private static final String PROJECT_NAME = "CommonModule";
|
||||
|
||||
private static final String FQN = "CommonModule.CommonModule";
|
||||
|
||||
private static final String FOLDER = "/resources/strict/";
|
||||
|
||||
private static final String COMMON_MODULE_FILE_NAME = "/src/CommonModules/CommonModule/Module.bsl";
|
||||
|
||||
@Override
|
||||
protected String getTestConfigurationName()
|
||||
{
|
||||
return PROJECT_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of {@link StructureCtorValueTypeCheck} structure constructor value has returning type.
|
||||
*
|
||||
* @throws Exception the exception
|
||||
*/
|
||||
@Test
|
||||
public void testStructureCtorValueTypeCheck() throws Exception
|
||||
{
|
||||
|
||||
String checkId = "structure-consructor-value-type";
|
||||
|
||||
Module module = updateAndGetModule(checkId);
|
||||
|
||||
List<StringLiteral> literals = EcoreUtil2.eAllOfType(module, StringLiteral.class);
|
||||
assertEquals(5, literals.size());
|
||||
|
||||
List<Marker> markers = getMarters(checkId, module);
|
||||
|
||||
assertEquals(2, markers.size());
|
||||
|
||||
String uriToProblem = EcoreUtil.getURI(literals.get(0)).toString();
|
||||
|
||||
Marker marker = markers.get(0);
|
||||
|
||||
assertEquals("5", marker.getExtraInfo().get("line"));
|
||||
assertEquals(uriToProblem, marker.getExtraInfo().get("uriToProblem"));
|
||||
|
||||
marker = markers.get(1);
|
||||
|
||||
assertEquals("5", marker.getExtraInfo().get("line"));
|
||||
assertEquals(uriToProblem, marker.getExtraInfo().get("uriToProblem"));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of {@link VariableTypeCheck} that each variable has value type.
|
||||
*
|
||||
* @throws Exception the exception
|
||||
*/
|
||||
@Test
|
||||
public void testVariableTypeCheck() throws Exception
|
||||
{
|
||||
|
||||
String checkId = "variable-value-type";
|
||||
|
||||
Module module = updateAndGetModule(checkId);
|
||||
|
||||
List<Variable> variables = EcoreUtil2.eAllOfType(module, Variable.class);
|
||||
assertEquals(2, variables.size());
|
||||
|
||||
List<Marker> markers = getMarters(checkId, module);
|
||||
|
||||
assertEquals(1, markers.size());
|
||||
|
||||
String uriToProblem = EcoreUtil.getURI(variables.get(0)).toString();
|
||||
|
||||
Marker marker = markers.get(0);
|
||||
|
||||
assertEquals("4", marker.getExtraInfo().get("line"));
|
||||
assertEquals(uriToProblem, marker.getExtraInfo().get("uriToProblem"));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of {@link DocCommentFieldTypeCheck} that each field in documentation comment has defined type.
|
||||
*
|
||||
* @throws Exception the exception
|
||||
*/
|
||||
@Test
|
||||
@Ignore // FIXME check-system fails on issue add
|
||||
public void testDocCommentFieldTypeCheck() throws Exception
|
||||
{
|
||||
|
||||
String checkId = "doc-comment-field-type";
|
||||
|
||||
Module module = updateAndGetModule(checkId);
|
||||
|
||||
List<Method> methods = module.allMethods();
|
||||
assertEquals(2, methods.size());
|
||||
|
||||
List<Marker> markers = getMarters(checkId, module);
|
||||
|
||||
assertEquals(1, markers.size());
|
||||
|
||||
String uriToProblem = EcoreUtil.getURI(methods.get(0)).toString();
|
||||
|
||||
Marker marker = markers.get(0);
|
||||
|
||||
assertEquals("5", marker.getExtraInfo().get("line"));
|
||||
assertEquals(uriToProblem, marker.getExtraInfo().get("uriToProblem"));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of {@link FunctionReturnTypeCheck} that function has returning type.
|
||||
*
|
||||
* @throws Exception the exception
|
||||
*/
|
||||
@Test
|
||||
public void testFunctionReturnTypeCheck() throws Exception
|
||||
{
|
||||
|
||||
String checkId = "function-return-value-type";
|
||||
|
||||
Module module = updateAndGetModule(checkId);
|
||||
|
||||
List<Method> methods = module.allMethods();
|
||||
assertEquals(3, methods.size());
|
||||
|
||||
List<Marker> markers = getMarters(checkId, module);
|
||||
|
||||
// FIXME check-system duplicates issues
|
||||
assertEquals(2, markers.size());
|
||||
|
||||
String uriToProblem = EcoreUtil.getURI(methods.get(0)).toString();
|
||||
|
||||
Marker marker = markers.get(0);
|
||||
assertEquals("3", marker.getExtraInfo().get("line"));
|
||||
assertEquals(uriToProblem, marker.getExtraInfo().get("uriToProblem"));
|
||||
|
||||
marker = markers.get(1);
|
||||
assertEquals("3", marker.getExtraInfo().get("line"));
|
||||
assertEquals(uriToProblem, marker.getExtraInfo().get("uriToProblem"));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of {@link MethodParamTypeCheck} that each method's parameter has defined or computed type.
|
||||
*
|
||||
* @throws Exception the exception
|
||||
*/
|
||||
@Test
|
||||
public void testMethodParamTypeCheckk() throws Exception
|
||||
{
|
||||
|
||||
String checkId = "method-param-value-type";
|
||||
|
||||
Module module = updateAndGetModule(checkId);
|
||||
|
||||
List<Method> methods = module.allMethods();
|
||||
assertEquals(2, methods.size());
|
||||
|
||||
|
||||
List<Marker> markers = getMarters(checkId, module);
|
||||
|
||||
// FIXME check-system duplicates issues
|
||||
assertEquals(2, markers.size());
|
||||
|
||||
String uriToProblem = EcoreUtil.getURI(methods.get(0).getFormalParams().get(0)).toString();
|
||||
|
||||
Marker marker = markers.get(0);
|
||||
assertEquals("3", marker.getExtraInfo().get("line"));
|
||||
assertEquals(uriToProblem, marker.getExtraInfo().get("uriToProblem"));
|
||||
|
||||
marker = markers.get(1);
|
||||
assertEquals("3", marker.getExtraInfo().get("line"));
|
||||
assertEquals(uriToProblem, marker.getExtraInfo().get("uriToProblem"));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of {@link DynamicFeatureAccessMethodNotFoundCheck} that dynamic method exist in the object.
|
||||
*
|
||||
* @throws Exception the exception
|
||||
*/
|
||||
@Test
|
||||
public void testDynamicFeatureAccessMethodNotFoundCheck() throws Exception
|
||||
{
|
||||
|
||||
String checkId = "dynamic-access-method-not-found";
|
||||
|
||||
Module module = updateAndGetModule(checkId);
|
||||
|
||||
List<DynamicFeatureAccess> dynamicMethods = EcoreUtil2.eAllOfType(module, DynamicFeatureAccess.class);
|
||||
assertEquals(2, dynamicMethods.size());
|
||||
|
||||
List<Marker> markers = getMarters(checkId, module);
|
||||
|
||||
// FIXME check-system duplicates issues
|
||||
assertEquals(2, markers.size());
|
||||
|
||||
String uriToProblem = EcoreUtil.getURI(dynamicMethods.get(0)).toString();
|
||||
|
||||
Marker marker = markers.get(0);
|
||||
assertEquals("5", marker.getExtraInfo().get("line"));
|
||||
assertEquals(uriToProblem, marker.getExtraInfo().get("uriToProblem"));
|
||||
|
||||
marker = markers.get(0);
|
||||
assertEquals("5", marker.getExtraInfo().get("line"));
|
||||
assertEquals(uriToProblem, marker.getExtraInfo().get("uriToProblem"));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of {@link DynamicFeatureAccessTypeCheck} that dynamic property exist and has return type.
|
||||
*
|
||||
* @throws Exception the exception
|
||||
*/
|
||||
@Test
|
||||
public void testDynamicFeatureAccessTypeCheck() throws Exception
|
||||
{
|
||||
|
||||
String checkId = "property-return-type";
|
||||
|
||||
Module module = updateAndGetModule(checkId);
|
||||
|
||||
List<DynamicFeatureAccess> dynamicProperties = EcoreUtil2.eAllOfType(module, DynamicFeatureAccess.class);
|
||||
assertEquals(2, dynamicProperties.size());
|
||||
|
||||
List<Marker> markers = getMarters(checkId, module);
|
||||
|
||||
// FIXME check-system duplicates issues
|
||||
assertEquals(2, markers.size());
|
||||
|
||||
String uriToProblem = EcoreUtil.getURI(dynamicProperties.get(0)).toString();
|
||||
|
||||
Marker marker = markers.get(0);
|
||||
assertEquals("5", marker.getExtraInfo().get("line"));
|
||||
assertEquals(uriToProblem, marker.getExtraInfo().get("uriToProblem"));
|
||||
|
||||
marker = markers.get(0);
|
||||
assertEquals("5", marker.getExtraInfo().get("line"));
|
||||
assertEquals(uriToProblem, marker.getExtraInfo().get("uriToProblem"));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of {@link SimpleStatementTypeCheck} that the statement change type of existing object type.
|
||||
*
|
||||
* @throws Exception the exception
|
||||
*/
|
||||
@Test
|
||||
public void testSimpleStatementTypeCheck() throws Exception
|
||||
{
|
||||
|
||||
String checkId = "statement-type-change";
|
||||
|
||||
Module module = updateAndGetModule(checkId);
|
||||
|
||||
List<SimpleStatement> statements = EcoreUtil2.eAllOfType(module, SimpleStatement.class);
|
||||
assertEquals(2, statements.size());
|
||||
|
||||
List<Marker> markers = getMarters(checkId, module);
|
||||
|
||||
// FIXME check-system duplicates issues
|
||||
assertEquals(2, markers.size());
|
||||
|
||||
String uriToProblem = EcoreUtil.getURI(statements.get(0)).toString();
|
||||
|
||||
Marker marker = markers.get(0);
|
||||
assertEquals("6", marker.getExtraInfo().get("line"));
|
||||
assertEquals(uriToProblem, marker.getExtraInfo().get("uriToProblem"));
|
||||
|
||||
marker = markers.get(0);
|
||||
assertEquals("6", marker.getExtraInfo().get("line"));
|
||||
assertEquals(uriToProblem, marker.getExtraInfo().get("uriToProblem"));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of {@link FunctionCtorReturnSectionCheck} that the statement change type of existing object type.
|
||||
*
|
||||
* @throws Exception the exception
|
||||
*/
|
||||
@Test
|
||||
@Ignore // FIXME check-system fails on issue add
|
||||
public void testFunctionCtorReturnSectionCheck() throws Exception
|
||||
{
|
||||
|
||||
String checkId = "constructor-function-return-section";
|
||||
|
||||
Module module = updateAndGetModule(checkId);
|
||||
|
||||
List<Function> finctions = EcoreUtil2.eAllOfType(module, Function.class);
|
||||
assertEquals(2, finctions.size());
|
||||
|
||||
List<Marker> markers = getMarters(checkId, module);
|
||||
|
||||
assertEquals(1, markers.size());
|
||||
|
||||
String uriToProblem = EcoreUtil.getURI(finctions.get(0)).toString();
|
||||
|
||||
Marker marker = markers.get(0);
|
||||
assertEquals("6", marker.getExtraInfo().get("line"));
|
||||
assertEquals(uriToProblem, marker.getExtraInfo().get("uriToProblem"));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of {@link InvocationParamIntersectionCheck} that invokable method parameter type intersects
|
||||
* with caller type.
|
||||
*
|
||||
* @throws Exception the exception
|
||||
*/
|
||||
@Test
|
||||
public void testInvocationParamIntersectionCheck() throws Exception
|
||||
{
|
||||
|
||||
String checkId = "invocation-parameter-type-intersect";
|
||||
|
||||
Module module = updateAndGetModule(checkId);
|
||||
|
||||
List<StaticFeatureAccess> statements = EcoreUtil2.eAllOfType(module, StaticFeatureAccess.class);
|
||||
assertEquals(6, statements.size());
|
||||
|
||||
List<Marker> markers = getMarters(checkId, module);
|
||||
|
||||
assertEquals(1, markers.size());
|
||||
|
||||
String uriToProblem = EcoreUtil.getURI(statements.get(2)).toString();
|
||||
|
||||
Marker marker = markers.get(0);
|
||||
assertEquals("5", marker.getExtraInfo().get("line"));
|
||||
assertEquals(uriToProblem, marker.getExtraInfo().get("uriToProblem"));
|
||||
|
||||
}
|
||||
|
||||
private List<Marker> getMarters(String checkId, Module module)
|
||||
{
|
||||
String id = module.eResource().getURI().toPlatformString(true);
|
||||
List<Marker> markers =
|
||||
new ArrayList<>(Arrays.asList(markerManager.getMarkers(getProject().getWorkspaceProject(), id)));
|
||||
|
||||
markers.removeIf(m -> !checkId.equals(getCheckIdFromMarker(m, getProject())));
|
||||
return markers;
|
||||
}
|
||||
|
||||
private Module updateAndGetModule(String checkId) throws CoreException, IOException
|
||||
{
|
||||
try (InputStream in = getClass().getResourceAsStream(FOLDER + checkId + ".bsl"))
|
||||
{
|
||||
IFile file = getProject().getWorkspaceProject().getFile(COMMON_MODULE_FILE_NAME);
|
||||
file.setContents(in, true, true, new NullProgressMonitor());
|
||||
}
|
||||
testingWorkspace.waitForBuildCompletion();
|
||||
waitForDD(getProject());
|
||||
|
||||
IBmObject mdObject = getTopObjectByFqn(FQN, getProject());
|
||||
assertTrue(mdObject instanceof CommonModule);
|
||||
Module module = ((CommonModule)mdObject).getModule();
|
||||
assertNotNull(module);
|
||||
return module;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>CommonModule</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.xtext.ui.shared.xtextBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.xtext.ui.shared.xtextNature</nature>
|
||||
<nature>com._1c.g5.v8.dt.core.V8ConfigurationNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
@ -0,0 +1,2 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding/<project>=UTF-8
|
@ -0,0 +1,2 @@
|
||||
Manifest-Version: 1.0
|
||||
Runtime-Version: 8.3.19
|
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<mdclass:CommonModule xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass" uuid="cb364877-7f3a-44d9-8bc3-70387044034b">
|
||||
<name>CommonModule</name>
|
||||
<synonym>
|
||||
<key>en</key>
|
||||
<value>Common module</value>
|
||||
</synonym>
|
||||
<server>true</server>
|
||||
<externalConnection>true</externalConnection>
|
||||
<clientOrdinaryApplication>true</clientOrdinaryApplication>
|
||||
</mdclass:CommonModule>
|
@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<cmi:CommandInterface xmlns:cmi="http://g5.1c.ru/v8/dt/cmi"/>
|
@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<mdclass:Configuration xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass" uuid="41e0d07d-ece6-42b2-bfbf-686d364ed4fd">
|
||||
<name>CommonModule</name>
|
||||
<synonym>
|
||||
<key>en</key>
|
||||
<value>Common module</value>
|
||||
</synonym>
|
||||
<containedObjects classId="9cd510cd-abfc-11d4-9434-004095e12fc7" objectId="6c1e7aa2-b0dc-40a6-9666-92dc3ee3eee8"/>
|
||||
<containedObjects classId="9fcd25a0-4822-11d4-9414-008048da11f9" objectId="23a1191a-d0c7-4384-92b6-1c0af1530860"/>
|
||||
<containedObjects classId="e3687481-0a87-462c-a166-9f34594f9bba" objectId="2e16e60c-a924-457f-806e-e24b71ccd04b"/>
|
||||
<containedObjects classId="9de14907-ec23-4a07-96f0-85521cb6b53b" objectId="5c2b531d-3b51-4e77-99c5-1b3a36046623"/>
|
||||
<containedObjects classId="51f2d5d8-ea4d-4064-8892-82951750031e" objectId="0b85a612-279e-4922-8f22-838ada8729f6"/>
|
||||
<containedObjects classId="e68182ea-4237-4383-967f-90c1e3370bc7" objectId="1a856b15-b18e-43c7-8608-d37f533898a6"/>
|
||||
<containedObjects classId="fb282519-d103-4dd3-bc12-cb271d631dfc" objectId="16633a11-1ecd-48ba-ab9b-fe39c9b63e9e"/>
|
||||
<configurationExtensionCompatibilityMode>8.3.19</configurationExtensionCompatibilityMode>
|
||||
<defaultRunMode>ManagedApplication</defaultRunMode>
|
||||
<usePurposes>PersonalComputer</usePurposes>
|
||||
<usedMobileApplicationFunctionalities>
|
||||
<functionality>
|
||||
<use>true</use>
|
||||
</functionality>
|
||||
<functionality>
|
||||
<functionality>OSBackup</functionality>
|
||||
<use>true</use>
|
||||
</functionality>
|
||||
</usedMobileApplicationFunctionalities>
|
||||
<defaultLanguage>Language.English</defaultLanguage>
|
||||
<dataLockControlMode>Managed</dataLockControlMode>
|
||||
<objectAutonumerationMode>NotAutoFree</objectAutonumerationMode>
|
||||
<modalityUseMode>DontUse</modalityUseMode>
|
||||
<synchronousPlatformExtensionAndAddInCallUseMode>DontUse</synchronousPlatformExtensionAndAddInCallUseMode>
|
||||
<compatibilityMode>8.3.19</compatibilityMode>
|
||||
<languages uuid="6d6f56cc-2157-41a6-aa5c-a2ca5b24e90c">
|
||||
<name>English</name>
|
||||
<synonym>
|
||||
<key>en</key>
|
||||
<value>English</value>
|
||||
</synonym>
|
||||
<languageCode>en</languageCode>
|
||||
</languages>
|
||||
<commonModules>CommonModule.CommonModule</commonModules>
|
||||
</mdclass:Configuration>
|
@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<cmi:CommandInterface xmlns:cmi="http://g5.1c.ru/v8/dt/cmi"/>
|
Loading…
Reference in New Issue
Block a user