bsl-language-server icon indicating copy to clipboard operation
bsl-language-server copied to clipboard

Изменение параметра сслычного типа переданного по значению

Open asosnoviy opened this issue 5 years ago • 9 comments

Нельзя

Функция СвернутаяТз(Знач Тз)
    Тз.Свернуть();
    Возврат Тз;
КонецФункции

Нужно

Функция СвернутаяТз(Знач Тз)
  СвернутаяТз = Тз.Скопировать();
  СвернутаяТз.Свернуть();
  Возврат СвернутаяТз;
КонецФункции

А теперь как это угадать без базы контекстов... Или что можно\Нельзя делать по Знач

asosnoviy avatar Jun 25 '19 09:06 asosnoviy

Для @stepa86 можно сделать отдельное. "Нельзя присваивать по знач"

asosnoviy avatar Jun 25 '19 09:06 asosnoviy

Пример не очень правильный, т.к. Свернуть() это процедура, а не функция.

Stepa86 avatar Jun 25 '19 09:06 Stepa86

Простейший вариант со Знач

Функция ЧтоТоПосчитать( Знач НекоторыйПараметр )

    НекоторыйПараметр = ЧтоТоСделать( НекоторыйПараметр );  // Тут ругаться на присвоение параметру
    ЧтоТоЕщеПоделать( НекоторыйПараметр );  // Тут ругаться, т.к. параметр в процедуре указан не как Знач
    новаяПеременная = ЧтоТоДополнительноПолучитьПравильно( НекоторыйПараметр );

    Возврат новаяПеременная;

КонецФункции

Функция ЧтоТоСделать( Знач НекоторыйПараметр )
    НекоторыйПараметр  = НекоторыйПараметр  + 1; // Тут ругаться на присвоение параметру
    Возврат НекоторыйПараметр;
КонецФункции

Процедура ЧтоТоЕщеПоделать( НекоторыйПараметр )
    НекоторыйПараметр  = НекоторыйПараметр  - 5;
КонецПроцедуры

Функция ЧтоТоДополнительноПолучитьПравильно( Знач НекоторыйПараметр )
    Возврат НекоторыйПараметр  + 100500;
КонецФункции

Stepa86 avatar Jun 25 '19 10:06 Stepa86

Пример не очень правильный, т.к. Свернуть() это процедура, а не функция.

Да, спасибо исправил

asosnoviy avatar Jun 25 '19 11:06 asosnoviy

Простейший вариант со Знач

Функция ЧтоТоПосчитать( Знач НекоторыйПараметр )

    НекоторыйПараметр = ЧтоТоСделать( НекоторыйПараметр );  // Тут ругаться на присвоение параметру
    ЧтоТоЕщеПоделать( НекоторыйПараметр );  // Тут ругаться, т.к. параметр в процедуре указан не как Знач
    новаяПеременная = ЧтоТоДополнительноПолучитьПравильно( НекоторыйПараметр );

    Возврат новаяПеременная;

КонецФункции

Функция ЧтоТоСделать( Знач НекоторыйПараметр )
    НекоторыйПараметр  = НекоторыйПараметр  + 1; // Тут ругаться на присвоение параметру
    Возврат НекоторыйПараметр;
КонецФункции

Процедура ЧтоТоЕщеПоделать( НекоторыйПараметр )
    НекоторыйПараметр  = НекоторыйПараметр  - 5;
КонецПроцедуры

Функция ЧтоТоДополнительноПолучитьПравильно( Знач НекоторыйПараметр )
    Возврат НекоторыйПараметр  + 100500;
КонецФункции

к сожалению, ВСЕ варианты, указанные в этом примере, это ложные срабатывания. практически во всех вариантах идет изменение переданного параметра значением, рассчитанным из этого же параметра.

а это не является ошибкой, а довольно часто делается в коде.

Например,

Процедура Метод(Знач Строка)
  Строка = СокрЛП(Строка); // не является ошибкой
КонецПроцедуры

Правильно учитывать только те случаи, когда параметр меняется на выражение, которое не зависит от этого параметра.

Процедура Метод(Знач Строка)
  Строка = СокрЛП(ДругаяСтрока); // вот тут явно подозрительно
КонецПроцедуры

@Stepa86 @asosnoviy @theshadowco @nixel2007 что скажете?

artbear avatar Apr 20 '20 13:04 artbear

Какая разница из-за чего меняется параметр, если он не должен меняться?

Вот в этом примере есть ошибка или нет? А когда речь заходит про коллекции? А когда речь заходит про клиент-серверное взаимодействие?

&НаКлиенте
Процедура Команда1(Команда)
	
	текСтр = "123";
	Метод(текСтр);
	Сообщить(текСтр);
	
КонецПроцедуры

Процедура Метод(Знач Строка)
	
	Строка = Строка + Строка;
	
КонецПроцедуры

Мое мнение - если параметр пришел со Знач - нехер его трогать. Безопаснее и предсказуемее будет.

Stepa86 avatar Apr 20 '20 13:04 Stepa86

@Stepa86 в указанном тобой коде, конечно, ошибка, но заставляя диагностировать любое изменение Знач-параметра ты просто поймаешь кучу ФП

я зря не расширил свой пример. исправляюсь

Процедура Метод(Знач Строка)
  Строка = СокрЛП(Строка); // не является ошибкой, т.к. далее переиспользование этого значения
  ИспользованиеСтрокиБезПробелов ( Строка );
КонецПроцедуры

вот такой код часто-часто можно встретить. многие так пишут, это как раз и удобно при использовании Знач-параметра. заводить новую переменную - оверхед ИМХО.

artbear avatar Apr 20 '20 14:04 artbear

ну и раз есть расхождения, значит, правило точно должно быть параметризуемым.

например, параметр булевый "Ловить любое исправление Знач-параметра" - по умолчанию Ложь

если Истина, ловим любое, как ты предлагаешь если Ложь, ловим изменение параметра выражением, которое не зависит от этого же параметра.

зы на всякий случай - у меня есть опыт использования моего вариант правила, ловятся действительно подозрительные места.

artbear avatar Apr 20 '20 14:04 artbear

@Stepa86 Я реализовал соседний ишью #1834

  • ПР https://github.com/1c-syntax/bsl-language-server/pull/2810
  • выдаются замечания на изменение параметра, передаваемого по значению
    • есть отличие от обсуждаемого в текущем ишузе варианта - изменение вида Параметр = Выражение(Параметр) пропускаются,
      • т.к. я уже писал, что это довольно обычная практика и будет многовато ФП.

artbear avatar Jun 12 '22 18:06 artbear