From 6e7b032e95474ee6739369f4bf31c77988f3d641 Mon Sep 17 00:00:00 2001 From: Mr-Rm Date: Tue, 14 Jul 2026 12:03:23 +0400 Subject: [PATCH 01/10] =?UTF-8?q?=D0=BD=D0=B5=D0=B4=D0=BE=D1=81=D1=82?= =?UTF-8?q?=D0=B0=D1=8E=D1=89=D0=B8=D0=B5=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5?= =?UTF-8?q?=D1=80=D0=BA=D0=B8=20=D0=B8=D0=BD=D0=B4=D0=B5=D0=BA=D1=81=D0=B0?= =?UTF-8?q?=20+=D1=82=D0=B5=D1=81=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Collections/ValueList/ValueListImpl.cs | 18 ++++++------ tests/value-list.os | 28 +++++++++++++++++++ 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs b/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs index 6f3c1b288..ccb599cf9 100644 --- a/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs +++ b/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs @@ -30,13 +30,7 @@ public ValueListImpl() _items = new List(); } - public override bool IsIndexed - { - get - { - return true; - } - } + public override bool IsIndexed => true; public override IValue GetIndexedValue(IValue index) { @@ -71,6 +65,9 @@ public override void SetIndexedValue(IValue index, IValue val) public ValueListItem GetValue(IValue index) { int numericIndex = (int)index.AsNumber(); + if (numericIndex < 0 || numericIndex >= _items.Count) + throw RuntimeException.IndexOutOfRange(); + return _items[numericIndex]; } @@ -103,6 +100,9 @@ public ValueListItem Add(IValue value = null, string presentation = null, bool c [ContextMethod("Вставить", "Insert")] public ValueListItem Insert(int index, IValue value = null, string presentation = null, bool check = false, IValue picture = null) { + if (index < 0 || index > _items.Count) + throw RuntimeException.IndexOutOfRange(); + var newItem = CreateNewListItem(value, presentation, check, picture); _items.Insert(index, newItem); @@ -211,7 +211,7 @@ private int IndexByValue(BslValue item) throw RuntimeException.InvalidArgumentType(); } - if (index < 0 || index >= _items.Count()) + if (index < 0 || index >= _items.Count) throw RuntimeException.IndexOutOfRange(); } @@ -233,7 +233,7 @@ public void Move(BslValue item, int offset) int index_dest = index_source + offset; - if (index_dest < 0 || index_dest >= _items.Count()) + if (index_dest < 0 || index_dest >= _items.Count) throw RuntimeException.InvalidNthArgumentValue(2); ValueListItem itemObject = _items[index_source]; diff --git a/tests/value-list.os b/tests/value-list.os index 2dbf03562..135ba3fe5 100644 --- a/tests/value-list.os +++ b/tests/value-list.os @@ -20,6 +20,8 @@ ВсеТесты.Добавить("ТестДолжен_ПроверитьМетодНайтиСпискаЗначений"); ВсеТесты.Добавить("ТестДолжен_ПроверитьМетодУдалитьСпискаЗначений"); ВсеТесты.Добавить("ТестДолжен_ПроверитьПреобразованиеЭлементаСпискаВСтроку"); + + ВсеТесты.Добавить("ТестДолжен_ПроверитьОшибкуМетодаПолучитьСпискаЗначений"); Возврат ВсеТесты; КонецФункции @@ -148,6 +150,32 @@ юТест.ПроверитьРавенство(СЗ.Индекс(Э3), 2, "Метод Вставить() списка значений"); юТест.ПроверитьРавенство(СЗ.Индекс(Э4), 3, "Метод Вставить() списка значений"); + // Проверим ошибки + Ошибка = "Вставить с неверным индексом"; + Попытка + СЗ.Вставить(10, 9); + Исключение + Ошибка = ИнформацияОбОшибке().Описание; + КонецПопытки; + юТест.ПроверитьРавенство(Ошибка, "Значение индекса выходит за пределы диапазона"); + +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьОшибкуМетодаПолучитьСпискаЗначений() Экспорт + + СЗ = Новый СписокЗначений; + СЗ.Добавить("Один"); + СЗ.Добавить("Два"); + + // Проверим ошибки + Ошибка = "Получить с неверным индексом"; + Попытка + СЗ.Получить(10); + Исключение + Ошибка = ИнформацияОбОшибке().Описание; + КонецПопытки; + юТест.ПроверитьРавенство(Ошибка, "Значение индекса выходит за пределы диапазона"); + КонецПроцедуры Процедура ТестДолжен_ПроверитьМетодУдалитьСпискаЗначений() Экспорт From 01db884e232b089a9abc98a1c4c3a405d9535aa6 Mon Sep 17 00:00:00 2001 From: Mr-Rm Date: Tue, 14 Jul 2026 15:13:58 +0400 Subject: [PATCH 02/10] =?UTF-8?q?=D0=B2=D1=8B=D0=BD=D0=B5=D1=81=D0=B5?= =?UTF-8?q?=D0=BD=D1=8B=20=D0=B8=D1=81=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Collections/ValueList/ValueListImpl.cs | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs b/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs index ccb599cf9..657d04573 100644 --- a/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs +++ b/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs @@ -47,13 +47,9 @@ public override IValue GetIndexedValue(IValue index) public override void SetIndexedValue(IValue index, IValue val) { if (index.SystemType == BasicTypes.Number) - { - throw new RuntimeException("Индексированное значение доступно только для чтения"); - } - else - { - base.SetIndexedValue(index, val); - } + throw IndexedIsReadonlyException(); + + base.SetIndexedValue(index, val); } /// @@ -194,11 +190,11 @@ private int IndexByValue(BslValue item) { int index; - if (item is ValueListItem) + if (item is ValueListItem listItem) { - index = IndexOf(item as ValueListItem); + index = IndexOf(listItem); if (index == -1) - throw new RuntimeException("Элемент не принадлежит списку значений"); + throw ElementDoesntBelongException(); } else { @@ -347,7 +343,17 @@ public override IEnumerator GetEnumerator() public static ValueListImpl Constructor() { return new ValueListImpl(); + } + + public static RuntimeException IndexedIsReadonlyException() + { + return new("Индексированное значение доступно только для чтения", "Indexed value is read-only"); } + public static RuntimeException ElementDoesntBelongException() + { + return new("Элемент не принадлежит списку значений", "Element does not belong to values list"); + } + } } From c150b55d96a94f80535cfd4c21eddc7ccf5d20e0 Mon Sep 17 00:00:00 2001 From: Mr-Rm Date: Tue, 14 Jul 2026 17:18:26 +0400 Subject: [PATCH 03/10] =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=BE=20=D1=81=D0=B2=D0=BE=D0=B9=D1=81=D1=82=D0=B2?= =?UTF-8?q?=D0=BE=20=D0=A2=D0=B8=D0=BF=D0=97=D0=BD=D0=B0=D1=87=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Collections/ValueList/ValueListImpl.cs | 20 ++++++++++++++----- .../Collections/ValueList/ValueListItem.cs | 2 +- .../TypeDescriptions/TypeDescription.cs | 13 ++++++++---- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs b/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs index 657d04573..95a6bf83e 100644 --- a/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs +++ b/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs @@ -13,6 +13,7 @@ This Source Code Form is subject to the terms of the using OneScript.Execution; using OneScript.Types; using OneScript.Values; +using OneScript.StandardLibrary.TypeDescriptions; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; @@ -25,6 +26,7 @@ namespace OneScript.StandardLibrary.Collections.ValueList public class ValueListImpl : AutoCollectionContext { readonly List _items; + public ValueListImpl() { _items = new List(); @@ -50,7 +52,14 @@ public override void SetIndexedValue(IValue index, IValue val) throw IndexedIsReadonlyException(); base.SetIndexedValue(index, val); - } + } + + /// + /// Определяет тип для значений, которые могут храниться в элементах данного списка значений + /// + /// ОписаниеТипов + [ContextProperty("ТипЗначения", "ValueType")] + public TypeDescription ListValueType { get; set; } = new(); /// /// Получить элемент по индексу @@ -105,16 +114,17 @@ public ValueListItem Insert(int index, IValue value = null, string presentation return newItem; } - private static ValueListItem CreateNewListItem(IValue value, string presentation, bool check, IValue picture) + private ValueListItem CreateNewListItem(IValue value, string presentation, bool check, IValue picture) { - var newItem = new ValueListItem + var adjValue = ListValueType.AdjustValue(value); + + return new ValueListItem { - Value = value ?? BslUndefinedValue.Instance, + Value = adjValue, Presentation = presentation, Check = check, Picture = picture }; - return newItem; } /// diff --git a/src/OneScript.StandardLibrary/Collections/ValueList/ValueListItem.cs b/src/OneScript.StandardLibrary/Collections/ValueList/ValueListItem.cs index c015ee277..f935f0b34 100644 --- a/src/OneScript.StandardLibrary/Collections/ValueList/ValueListItem.cs +++ b/src/OneScript.StandardLibrary/Collections/ValueList/ValueListItem.cs @@ -21,7 +21,7 @@ public class ValueListItem : AutoContext private string _presentationHolder; private IValue _pictureHolder; - public ValueListItem() + internal ValueListItem() { _pictureHolder = ValueFactory.Create(); _presentationHolder = String.Empty; diff --git a/src/OneScript.StandardLibrary/TypeDescriptions/TypeDescription.cs b/src/OneScript.StandardLibrary/TypeDescriptions/TypeDescription.cs index 9e91465bb..c14c2223c 100644 --- a/src/OneScript.StandardLibrary/TypeDescriptions/TypeDescription.cs +++ b/src/OneScript.StandardLibrary/TypeDescriptions/TypeDescription.cs @@ -5,7 +5,9 @@ This Source Code Form is subject to the terms of the at http://mozilla.org/MPL/2.0/. ----------------------------------------------------------*/ +using System; using System.Collections.Generic; +using System.Text; using OneScript.Contexts; using OneScript.Exceptions; using OneScript.StandardLibrary.Collections; @@ -329,10 +331,13 @@ private static void CheckAndAddOneQualifier(TypeDescriptionBuilder builder, IVal default: throw RuntimeException.InvalidNthArgumentType(nParam); } - } - } - - internal class UndefinedTypeAdjuster : IValueAdjuster + } + + public override string ToString() => string.Join(", ", _types); + } + + + internal class UndefinedTypeAdjuster : IValueAdjuster { public IValue Adjust(IValue value) { From 02c147dc884f8a03d4886d9e6c5986c463551031 Mon Sep 17 00:00:00 2001 From: Mr-Rm Date: Wed, 15 Jul 2026 16:54:38 +0400 Subject: [PATCH 04/10] =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=BE=20=D1=81=D0=B2=D0=BE=D0=B9=D1=81=D1=82=D0=B2?= =?UTF-8?q?=D0=BE=20=D0=94=D0=BE=D1=81=D1=82=D1=83=D0=BF=D0=BD=D1=8B=D0=B5?= =?UTF-8?q?=D0=97=D0=BD=D0=B0=D1=87=D0=B5=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Collections/ValueList/ValueListImpl.cs | 48 +++++++++++++++++-- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs b/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs index 95a6bf83e..76604fa30 100644 --- a/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs +++ b/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs @@ -59,8 +59,48 @@ public override void SetIndexedValue(IValue index, IValue val) /// /// ОписаниеТипов [ContextProperty("ТипЗначения", "ValueType")] - public TypeDescription ListValueType { get; set; } = new(); + public TypeDescription ListValueType { get; set; } = new(); + + + ValueListImpl _availableValues; + + /// + /// Ограничивает допустимые значения для элементов данного списка значений. + /// Возможные значения: Неопределено - ограничения отсутствуют, + /// СписокЗначений - список допустимых значений + /// + /// + /// Проверка допустимости добавляемых значений производится после приведения к указанным в ТипЗначения (если есть) + /// + /// СписокЗначений или Неопределено + [ContextProperty("ДоступныеЗначения", "AvailableValues")] + public IValue AvailableValues + { + get + { + if (_availableValues != null) + return _availableValues; + + return BslUndefinedValue.Instance; + } + set + { + switch (value) + { + case BslUndefinedValue: + _availableValues = null; + break; + + case ValueListImpl vl: + _availableValues = vl; + break; + + default: throw RuntimeException.InvalidArgumentType(); + } + } + } + /// /// Получить элемент по индексу /// @@ -116,11 +156,13 @@ public ValueListItem Insert(int index, IValue value = null, string presentation private ValueListItem CreateNewListItem(IValue value, string presentation, bool check, IValue picture) { - var adjValue = ListValueType.AdjustValue(value); + var newValue = ListValueType.AdjustValue(value); + if (_availableValues is not null) + newValue = _availableValues.FindByValue(newValue); return new ValueListItem { - Value = adjValue, + Value = newValue, Presentation = presentation, Check = check, Picture = picture From 63c558b6f3e10768f66c29453fbd6b040915b5fc Mon Sep 17 00:00:00 2001 From: Mr-Rm Date: Wed, 15 Jul 2026 18:21:02 +0400 Subject: [PATCH 05/10] =?UTF-8?q?=D0=B8=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=20=D0=BF=D0=BE=D0=B8=D1=81=D0=BA=20=D0=B4?= =?UTF-8?q?=D0=BE=D0=BF=D1=83=D1=81=D1=82=D0=B8=D0=BC=D1=8B=D1=85=20=D0=B7?= =?UTF-8?q?=D0=BD=D0=B0=D1=87=D0=B5=D0=BD=D0=B8=D0=B9=20+=20=D1=82=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Collections/ValueList/ValueListImpl.cs | 7 +- tests/value-list.os | 66 ++++++++++++++++++- 2 files changed, 70 insertions(+), 3 deletions(-) diff --git a/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs b/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs index 76604fa30..595c90937 100644 --- a/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs +++ b/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs @@ -157,8 +157,11 @@ public ValueListItem Insert(int index, IValue value = null, string presentation private ValueListItem CreateNewListItem(IValue value, string presentation, bool check, IValue picture) { var newValue = ListValueType.AdjustValue(value); - if (_availableValues is not null) - newValue = _availableValues.FindByValue(newValue); + if (_availableValues is not null) + { + var foundItem = _availableValues.FindByValue(newValue); + newValue = foundItem is ValueListItem li ? li.Value : ListValueType.AdjustValue(); + } return new ValueListItem { diff --git a/tests/value-list.os b/tests/value-list.os index 135ba3fe5..182d5ccec 100644 --- a/tests/value-list.os +++ b/tests/value-list.os @@ -22,6 +22,9 @@ ВсеТесты.Добавить("ТестДолжен_ПроверитьПреобразованиеЭлементаСпискаВСтроку"); ВсеТесты.Добавить("ТестДолжен_ПроверитьОшибкуМетодаПолучитьСпискаЗначений"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьСвойствоТипЗначения"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьСвойствоДоступныеЗначения_Без_ТипЗначения"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьСвойствоДоступныеЗначения_С_ТипЗначения"); Возврат ВсеТесты; КонецФункции @@ -438,4 +441,65 @@ юТест.ПроверитьРавенство(" ", Строка(СЗ[3]), "Строка, пробел"); юТест.ПроверитьРавенство(" ", СЗ[3].Представление, "Представление, пробел"); -КонецПроцедуры \ No newline at end of file +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьСвойствоТипЗначения() Экспорт + Описание = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(2)); + СЗ = Новый СписокЗначений; + СЗ.ТипЗначения = Описание; + СЗ.Добавить(12); + СЗ.Добавить(22); + СЗ.Добавить(122); + СЗ.Добавить("23"); + СЗ.Добавить("*3"); + + юТест.ПроверитьРавенство(12, СЗ[0].Значение); + юТест.ПроверитьРавенство(22, СЗ[1].Значение); + юТест.ПроверитьРавенство(99, СЗ[2].Значение); + юТест.ПроверитьТип(СЗ[3].Значение,"Число"); + юТест.ПроверитьРавенство(23, СЗ[3].Значение); + юТест.ПроверитьРавенство(0, СЗ[4].Значение); +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьСвойствоДоступныеЗначения_Без_ТипЗначения() Экспорт + ДЗ = Новый СписокЗначений; + ДЗ.Добавить(11); + ДЗ.Добавить(12); + ДЗ.Добавить(99); + + СЗ = Новый СписокЗначений; + СЗ.ДоступныеЗначения = ДЗ; + СЗ.Добавить(12); + СЗ.Добавить(22); + СЗ.Добавить("11"); + + юТест.ПроверитьТип(СЗ[0].Значение,"Число"); + юТест.ПроверитьРавенство(12, СЗ[0].Значение, "Допустимое значение"); + юТест.ПроверитьРавенство( Неопределено, СЗ[1].Значение, "Недопустимое значение"); + юТест.ПроверитьРавенство( Неопределено, СЗ[2].Значение, "Без приведения типа"); +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьСвойствоДоступныеЗначения_С_ТипЗначения() Экспорт + ДЗ = Новый СписокЗначений; + ДЗ.Добавить(11); + ДЗ.Добавить(12); + ДЗ.Добавить(99); + + Описание = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(2)); + + СЗ = Новый СписокЗначений; + СЗ.ТипЗначения = Описание; + СЗ.ДоступныеЗначения = ДЗ; + СЗ.Добавить(12); + СЗ.Добавить(22); + СЗ.Добавить("11"); // приведение типа + СЗ.Добавить(123); // переполнение + + юТест.ПроверитьТип(СЗ[0].Значение,"Число"); + юТест.ПроверитьРавенство(12, СЗ[0].Значение, "Допустимое значение"); + юТест.ПроверитьРавенство( 0, СЗ[1].Значение, "Недопустимое значение с приведением типа"); + юТест.ПроверитьТип(СЗ[2].Значение,"Число"); + юТест.ПроверитьРавенство( 11, СЗ[2].Значение, "Допустимое значение с приведением типа"); + юТест.ПроверитьРавенство( 99, СЗ[3].Значение, "Приведение с переполнением и допустимое значение"); +КонецПроцедуры + From b5275e70efaae166ae60adf0977e38c7cf140c4c Mon Sep 17 00:00:00 2001 From: Mr-Rm Date: Thu, 16 Jul 2026 11:21:57 +0400 Subject: [PATCH 06/10] =?UTF-8?q?=D0=BF=D1=80=D0=B5=D0=BE=D0=B1=D1=80?= =?UTF-8?q?=D0=B0=D0=B7=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=B2=20?= =?UTF-8?q?=D1=81=D1=82=D1=80=D0=BE=D0=BA=D1=83=20=D1=81=20=D1=83=D1=87?= =?UTF-8?q?=D0=B5=D1=82=D0=BE=D0=BC=20=D0=BF=D1=83=D1=81=D1=82=D1=8B=D1=85?= =?UTF-8?q?=20=D1=8D=D0=BB=D0=B5=D0=BC=D0=B5=D0=BD=D1=82=D0=BE=D0=B2;=20?= =?UTF-8?q?=D1=82=D0=B5=D1=81=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Collections/ValueList/ValueListImpl.cs | 2 ++ .../Collections/ValueList/ValueListItem.cs | 8 ++++++- tests/value-list.os | 24 +++++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs b/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs index 595c90937..8043b3aaf 100644 --- a/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs +++ b/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs @@ -394,6 +394,8 @@ public override IEnumerator GetEnumerator() #endregion + public override string ToString() => string.Join("; ", _items); + [ScriptConstructor] public static ValueListImpl Constructor() { diff --git a/src/OneScript.StandardLibrary/Collections/ValueList/ValueListItem.cs b/src/OneScript.StandardLibrary/Collections/ValueList/ValueListItem.cs index f935f0b34..49ec78a65 100644 --- a/src/OneScript.StandardLibrary/Collections/ValueList/ValueListItem.cs +++ b/src/OneScript.StandardLibrary/Collections/ValueList/ValueListItem.cs @@ -7,6 +7,8 @@ This Source Code Form is subject to the terms of the using System; using OneScript.Contexts; +using OneScript.Localization; +using OneScript.Values; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; @@ -18,6 +20,8 @@ namespace OneScript.StandardLibrary.Collections.ValueList [ContextClass("ЭлементСпискаЗначений", "ValueListItem")] public class ValueListItem : AutoContext { + static readonly BilingualString EMPTY_VALUE_STRING = new("<Пустое значение>", ""); + private string _presentationHolder; private IValue _pictureHolder; @@ -48,6 +52,8 @@ public IValue Picture } public override string ToString() - => !String.IsNullOrEmpty(_presentationHolder) ? _presentationHolder : Value.ToString(); + => !String.IsNullOrEmpty(_presentationHolder) ? _presentationHolder + : Value is BslUndefinedValue ? EMPTY_VALUE_STRING + : Value.ToString(); } } diff --git a/tests/value-list.os b/tests/value-list.os index 182d5ccec..1e182689c 100644 --- a/tests/value-list.os +++ b/tests/value-list.os @@ -25,6 +25,7 @@ ВсеТесты.Добавить("ТестДолжен_ПроверитьСвойствоТипЗначения"); ВсеТесты.Добавить("ТестДолжен_ПроверитьСвойствоДоступныеЗначения_Без_ТипЗначения"); ВсеТесты.Добавить("ТестДолжен_ПроверитьСвойствоДоступныеЗначения_С_ТипЗначения"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьПреобразованиеСпискаВСтроку"); Возврат ВсеТесты; КонецФункции @@ -431,6 +432,8 @@ СЗ.Добавить(1, ""); СЗ.Добавить(2, Неопределено); СЗ.Добавить(3, " "); + СЗ.Добавить(Неопределено); + СЗ.Добавить(Неопределено,"(неопр.)"); юТест.ПроверитьРавенство("0", Строка(СЗ[0]), "Строка, без указания"); юТест.ПроверитьРавенство("", СЗ[0].Представление, "Представление, без указания"); @@ -440,6 +443,11 @@ юТест.ПроверитьРавенство("", СЗ[2].Представление, "Представление, Неопределено"); юТест.ПроверитьРавенство(" ", Строка(СЗ[3]), "Строка, пробел"); юТест.ПроверитьРавенство(" ", СЗ[3].Представление, "Представление, пробел"); + + юТест.ПроверитьРавенство("<Пустое значение>", Строка(СЗ[4]), "Неопределено, без указания"); + юТест.ПроверитьРавенство("", СЗ[4].Представление, "Неопределено, без представления"); + юТест.ПроверитьРавенство("(неопр.)", Строка(СЗ[5]), "Неопределено, с указанием"); + юТест.ПроверитьРавенство("(неопр.)", СЗ[5].Представление, "Неопределено, с представлением"); КонецПроцедуры @@ -503,3 +511,19 @@ юТест.ПроверитьРавенство( 99, СЗ[3].Значение, "Приведение с переполнением и допустимое значение"); КонецПроцедуры +Процедура ТестДолжен_ПроверитьПреобразованиеСпискаВСтроку() Экспорт + + СЗ = Новый СписокЗначений; + СЗ.Добавить(11); + СЗ.Добавить(12,"двенадцать"); + СЗ.Добавить("абв"); + СЗ.Добавить("фыв",""); + СЗ.Добавить("пробел"," "); + СЗ.Добавить("йцу","Йцу!"); + СЗ.Добавить(Неопределено); + СЗ.Добавить(Неопределено,"(неопр.)"); + + Строка = Строка(СЗ); + + юТест.ПроверитьРавенство(Строка, "11; двенадцать; абв; фыв; ; Йцу!; <Пустое значение>; (неопр.)"); +КонецПроцедуры From 6bd24f15a603c669b4f97264be1edd04eb52cf07 Mon Sep 17 00:00:00 2001 From: Mr-Rm Date: Thu, 16 Jul 2026 11:44:11 +0400 Subject: [PATCH 07/10] =?UTF-8?q?=D0=B7=D0=B0=D0=B1=D1=8B=D1=82=D1=8B?= =?UTF-8?q?=D0=B9=20NULL?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Collections/ValueList/ValueListItem.cs | 2 +- tests/value-list.os | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/OneScript.StandardLibrary/Collections/ValueList/ValueListItem.cs b/src/OneScript.StandardLibrary/Collections/ValueList/ValueListItem.cs index 49ec78a65..d5f8040c3 100644 --- a/src/OneScript.StandardLibrary/Collections/ValueList/ValueListItem.cs +++ b/src/OneScript.StandardLibrary/Collections/ValueList/ValueListItem.cs @@ -53,7 +53,7 @@ public IValue Picture public override string ToString() => !String.IsNullOrEmpty(_presentationHolder) ? _presentationHolder - : Value is BslUndefinedValue ? EMPTY_VALUE_STRING + : Value is BslUndefinedValue or BslNullValue? EMPTY_VALUE_STRING : Value.ToString(); } } diff --git a/tests/value-list.os b/tests/value-list.os index 1e182689c..de31f91ce 100644 --- a/tests/value-list.os +++ b/tests/value-list.os @@ -434,6 +434,8 @@ СЗ.Добавить(3, " "); СЗ.Добавить(Неопределено); СЗ.Добавить(Неопределено,"(неопр.)"); + СЗ.Добавить(NULL); + СЗ.Добавить(NULL,"(null)"); юТест.ПроверитьРавенство("0", Строка(СЗ[0]), "Строка, без указания"); юТест.ПроверитьРавенство("", СЗ[0].Представление, "Представление, без указания"); @@ -449,6 +451,12 @@ юТест.ПроверитьРавенство("(неопр.)", Строка(СЗ[5]), "Неопределено, с указанием"); юТест.ПроверитьРавенство("(неопр.)", СЗ[5].Представление, "Неопределено, с представлением"); + юТест.ПроверитьРавенство("<Пустое значение>", Строка(СЗ[6]), "NULL, без указания"); + юТест.ПроверитьРавенство("", СЗ[6].Представление, "NULL, без представления"); + юТест.ПроверитьРавенство("(null)", Строка(СЗ[7]), "NULL, с указанием"); + юТест.ПроверитьРавенство("(null)", СЗ[7].Представление, "NULL, с представлением"); + + КонецПроцедуры Процедура ТестДолжен_ПроверитьСвойствоТипЗначения() Экспорт From a98bb3f9490b72d0d05ec03a08204c316a086c6d Mon Sep 17 00:00:00 2001 From: Mr-Rm Date: Thu, 16 Jul 2026 12:36:10 +0400 Subject: [PATCH 08/10] =?UTF-8?q?=D1=81=D0=BE=D1=80=D1=82=D0=B8=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=BA=D0=B0=20=D0=BF=D0=BE=20=D0=B7=D0=BD=D0=B0?= =?UTF-8?q?=D1=87=D0=B5=D0=BD=D0=B8=D1=8E=20=D1=81=20=D1=83=D1=87=D0=B5?= =?UTF-8?q?=D1=82=D0=BE=D0=BC=20=D1=82=D0=B8=D0=BF=D0=BE=D0=B2=20+=D1=82?= =?UTF-8?q?=D0=B5=D1=81=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Collections/ValueList/ValueListImpl.cs | 25 +++++----- tests/value-list.os | 47 +++++++++++++++++++ 2 files changed, 58 insertions(+), 14 deletions(-) diff --git a/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs b/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs index 8043b3aaf..707f55647 100644 --- a/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs +++ b/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs @@ -324,26 +324,23 @@ public ValueListImpl Copy() [ContextMethod("СортироватьПоЗначению", "SortByValue")] public void SortByValue(IBslProcess process, SortDirectionEnum? direction = null) { - if (direction == null || direction == SortDirectionEnum.Asc) - { - _items.Sort((x, y) => SafeCompare(process, x.Value, y.Value)); - } - else - { - _items.Sort((x, y) => SafeCompare(process, y.Value, x.Value)); - } + _items.Sort( new ItemComparator(process, direction == null || direction == SortDirectionEnum.Asc) ); } - private int SafeCompare(IBslProcess p, IValue x, IValue y) + private class ItemComparator : IComparer { - try + readonly GenericIValueComparer _comparer; + readonly int _direction; + + public ItemComparator(IBslProcess process, bool ascending = true) { - return x.CompareTo(y); + _comparer = new GenericIValueComparer(process); + _direction = ascending ? 1 : -1; } - catch(RuntimeException) + + public int Compare(ValueListItem x, ValueListItem y) { - // Сравнение типов не поддерживается - return string.Compare(x?.AsString(p), y?.AsString(p), StringComparison.Ordinal); + return _comparer.Compare(x.Value, y.Value) * _direction; } } diff --git a/tests/value-list.os b/tests/value-list.os index de31f91ce..4b3ce4dfc 100644 --- a/tests/value-list.os +++ b/tests/value-list.os @@ -17,6 +17,9 @@ ВсеТесты.Добавить("ТестДолжен_ПроверитьМетодСдвинутьСпискаЗначений"); ВсеТесты.Добавить("ТестДолжен_ПроверитьМетодСортироватьПоЗначениюСпискаЗначений"); ВсеТесты.Добавить("ТестДолжен_ПроверитьМетодСортироватьПоПредставлениюСпискаЗначений"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьСортировкуПоЗначениюРазныхТипов"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьСортировкуНеупорядочиваемыхТипов"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьМетодНайтиСпискаЗначений"); ВсеТесты.Добавить("ТестДолжен_ПроверитьМетодУдалитьСпискаЗначений"); ВсеТесты.Добавить("ТестДолжен_ПроверитьПреобразованиеЭлементаСпискаВСтроку"); @@ -386,6 +389,50 @@ КонецПроцедуры +Процедура ТестДолжен_ПроверитьСортировкуПоЗначениюРазныхТипов() Экспорт + СЗ = Новый СписокЗначений; + + СЗ.Добавить(Тип("Строка")); + СЗ.Добавить("Стр2"); + СЗ.Добавить("СтрЪ"); + СЗ.Добавить(); + СЗ.Добавить(Новый Структура); + СЗ.Добавить(Новый Массив); + СЗ.Добавить(null); + СЗ.Добавить(Тип("Булево")); + СЗ.Добавить(Тип("Массив")); + СЗ.Добавить(Тип("ЗаписьXML")); + СЗ.Добавить(Новый ЧтениеJSON); + СЗ.Добавить(Новый ЗаписьXML); + + СЗ.СортироватьПоЗначению(); + + юТест.ПроверитьРавенство(СЗ[0].Значение, Неопределено); + юТест.ПроверитьРавенство(СЗ[1].Значение, null); + юТест.ПроверитьРавенство(СЗ[2].Значение, "Стр2"); + юТест.ПроверитьРавенство(СЗ[3].Значение, "СтрЪ"); + юТест.ПроверитьТип(СЗ[4].Значение, Тип("ЗаписьXML")); + юТест.ПроверитьТип(СЗ[5].Значение, Тип("Массив")); + юТест.ПроверитьТип(СЗ[6].Значение, Тип("Структура")); + юТест.ПроверитьТип(СЗ[7].Значение, Тип("ЧтениеJSON")); + юТест.ПроверитьРавенство(СЗ[8].Значение, Тип("Булево")); + юТест.ПроверитьРавенство(СЗ[9].Значение, Тип("ЗаписьXML")); + юТест.ПроверитьРавенство(СЗ[10].Значение, Тип("Массив")); + юТест.ПроверитьРавенство(СЗ[11].Значение, Тип("Строка")); +КонецПроцедуры + +// см. issue #1577 +Процедура ТестДолжен_ПроверитьСортировкуНеупорядочиваемыхТипов() Экспорт + СЗ = Новый СписокЗначений; + + СЗ.Добавить(Неопределено); + СЗ.Добавить(Неопределено); + + СЗ.СортироватьПоЗначению(); // не должно упасть + + юТест.ПроверитьРавенство(СЗ[0].Значение, Неопределено); + юТест.ПроверитьРавенство(СЗ[1].Значение, Неопределено); +КонецПроцедуры Процедура ТестДолжен_ПроверитьМетодСортироватьПоПредставлениюСпискаЗначений() Экспорт From 6e8c9d80ad8f1eea6a316f01ff7cfa070cd1f6a6 Mon Sep 17 00:00:00 2001 From: Mr-Rm Date: Thu, 16 Jul 2026 15:06:40 +0400 Subject: [PATCH 09/10] =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=20=D0=9F=D0=BE?= =?UTF-8?q?=D0=BB=D1=83=D1=87=D0=B8=D1=82=D1=8C=D0=98=D0=B4=D0=B5=D0=BD?= =?UTF-8?q?=D1=82=D0=B8=D1=84=D0=B8=D0=BA=D0=B0=D1=82=D0=BE=D1=80=20+?= =?UTF-8?q?=D1=82=D0=B5=D1=81=D1=82;=20=D0=BE=D0=BF=D0=B8=D1=81=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=20=D0=B4=D0=BB=D1=8F=20=D0=AD=D0=BB=D0=B5?= =?UTF-8?q?=D0=BC=D0=B5=D0=BD=D1=82=D0=A1=D0=BF=D0=B8=D1=81=D0=BA=D0=B0?= =?UTF-8?q?=D0=97=D0=BD=D0=B0=D1=87=D0=B5=D0=BD=D0=B8=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Collections/ValueList/ValueListImpl.cs | 5 +-- .../Collections/ValueList/ValueListItem.cs | 34 +++++++++++++++---- tests/value-list.os | 28 +++++++++++++++ 3 files changed, 59 insertions(+), 8 deletions(-) diff --git a/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs b/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs index 707f55647..bbdcb4d30 100644 --- a/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs +++ b/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs @@ -26,6 +26,7 @@ namespace OneScript.StandardLibrary.Collections.ValueList public class ValueListImpl : AutoCollectionContext { readonly List _items; + ulong _maxId; public ValueListImpl() { @@ -163,7 +164,7 @@ private ValueListItem CreateNewListItem(IValue value, string presentation, bool newValue = foundItem is ValueListItem li ? li.Value : ListValueType.AdjustValue(); } - return new ValueListItem + return new ValueListItem(_maxId++) { Value = newValue, Presentation = presentation, @@ -190,7 +191,7 @@ public ArrayImpl UnloadValues() public void LoadValues(ArrayImpl source) { Clear(); - _items.AddRange(source.Select(x => new ValueListItem() { Value = x })); + _items.AddRange(source.Select(x => new ValueListItem(_maxId++) { Value = x })); } /// diff --git a/src/OneScript.StandardLibrary/Collections/ValueList/ValueListItem.cs b/src/OneScript.StandardLibrary/Collections/ValueList/ValueListItem.cs index d5f8040c3..e394bacec 100644 --- a/src/OneScript.StandardLibrary/Collections/ValueList/ValueListItem.cs +++ b/src/OneScript.StandardLibrary/Collections/ValueList/ValueListItem.cs @@ -24,16 +24,25 @@ public class ValueListItem : AutoContext private string _presentationHolder; private IValue _pictureHolder; + private readonly ulong _id; - internal ValueListItem() + internal ValueListItem(ulong id) { + _id = id; _pictureHolder = ValueFactory.Create(); _presentationHolder = String.Empty; - } - + } + + /// + /// Хранимое элементом списка значение произвольного типа + /// [ContextProperty("Значение", "Value")] public IValue Value { get; set; } + /// + /// Строковое представление элемента списка значений. + /// Если не задано или указана пустая строка, то соответствует представлению значения. + /// [ContextProperty("Представление", "Presentation")] public string Presentation { @@ -41,15 +50,28 @@ public string Presentation set => _presentationHolder = value ?? String.Empty; } + /// + /// Связанное с элементом списка значение пометки. Тип: Булево + /// [ContextProperty("Пометка", "Check")] - public bool Check { get; set; } - + public bool Check { get; set; } + + /// + /// Картинка, связанная с элементом списка значений. + /// + /// Сейчас может содержать произвольное значение, не используется [ContextProperty("Картинка", "Picture")] public IValue Picture { get => _pictureHolder; set => _pictureHolder = value ?? ValueFactory.Create(); - } + } + + /// + /// Получает идентификатор для элемента списка значений, не привязанный к позиции элемента в списке + /// + [ContextMethod("ПолучитьИдентификатор", "GetID")] + public ulong GetID() => _id; public override string ToString() => !String.IsNullOrEmpty(_presentationHolder) ? _presentationHolder diff --git a/tests/value-list.os b/tests/value-list.os index 4b3ce4dfc..edbfaf38c 100644 --- a/tests/value-list.os +++ b/tests/value-list.os @@ -29,6 +29,7 @@ ВсеТесты.Добавить("ТестДолжен_ПроверитьСвойствоДоступныеЗначения_Без_ТипЗначения"); ВсеТесты.Добавить("ТестДолжен_ПроверитьСвойствоДоступныеЗначения_С_ТипЗначения"); ВсеТесты.Добавить("ТестДолжен_ПроверитьПреобразованиеСпискаВСтроку"); + ВсеТесты.Добавить("ТестТестДолжен_ПроверитьМетодПолучитьИдентификатор"); Возврат ВсеТесты; КонецФункции @@ -582,3 +583,30 @@ юТест.ПроверитьРавенство(Строка, "11; двенадцать; абв; фыв; ; Йцу!; <Пустое значение>; (неопр.)"); КонецПроцедуры + +Процедура ТестТестДолжен_ПроверитьМетодПолучитьИдентификатор() Экспорт + СЗ = Новый СписокЗначений; + + СЗ.Добавить(1); + СЗ.Добавить(-2); + СЗ.Добавить(3); + СЗ.Добавить(-4); + + СЗ.Удалить(2); + СЗ.Добавить(0); + + СЗ.СортироватьПоЗначению(); + + юТест.ПроверитьРавенство(-4, СЗ[0].Значение); + юТест.ПроверитьРавенство(3, СЗ[0].ПолучитьИдентификатор()); + + юТест.ПроверитьРавенство(-2, СЗ[1].Значение); + юТест.ПроверитьРавенство(1, СЗ[1].ПолучитьИдентификатор()); + + юТест.ПроверитьРавенство(0, СЗ[2].Значение); + юТест.ПроверитьРавенство(4, СЗ[2].ПолучитьИдентификатор()); + + юТест.ПроверитьРавенство(1, СЗ[3].Значение); + юТест.ПроверитьРавенство(0, СЗ[3].ПолучитьИдентификатор()); + +КонецПроцедуры \ No newline at end of file From 3e9c00e447d098d5cec65160fcbcfb8c42268f81 Mon Sep 17 00:00:00 2001 From: Mr-Rm Date: Thu, 16 Jul 2026 15:37:43 +0400 Subject: [PATCH 10/10] =?UTF-8?q?=D0=BC=D0=B5=D0=BB=D0=BA=D0=B8=D0=B9=20?= =?UTF-8?q?=D1=80=D0=B5=D1=84=D0=B0=D0=BA=D1=82=D0=BE=D1=80=D0=B8=D0=BD?= =?UTF-8?q?=D0=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Collections/ValueList/ValueListImpl.cs | 43 +++---------------- 1 file changed, 7 insertions(+), 36 deletions(-) diff --git a/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs b/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs index bbdcb4d30..d4d271104 100644 --- a/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs +++ b/src/OneScript.StandardLibrary/Collections/ValueList/ValueListImpl.cs @@ -37,14 +37,7 @@ public ValueListImpl() public override IValue GetIndexedValue(IValue index) { - if (index.SystemType == BasicTypes.Number) - { - return GetValue(index); - } - else - { - return base.GetIndexedValue(index); - } + return index is BslNumericValue ? GetValue(index) : base.GetIndexedValue(index); } public override void SetIndexedValue(IValue index, IValue val) @@ -62,7 +55,6 @@ public override void SetIndexedValue(IValue index, IValue val) [ContextProperty("ТипЗначения", "ValueType")] public TypeDescription ListValueType { get; set; } = new(); - ValueListImpl _availableValues; /// @@ -178,10 +170,7 @@ private ValueListItem CreateNewListItem(IValue value, string presentation, bool /// /// Массив [ContextMethod("ВыгрузитьЗначения", "UnloadValues")] - public ArrayImpl UnloadValues() - { - return new ArrayImpl(_items.Select(x=>x.Value)); - } + public ArrayImpl UnloadValues() => new ArrayImpl(_items.Select(x => x.Value)); /// /// Загружает значения из массива @@ -198,10 +187,7 @@ public void LoadValues(ArrayImpl source) /// Удаляет все элементы из списка. /// [ContextMethod("Очистить", "Clear")] - public void Clear() - { - _items.Clear(); - } + public void Clear() => _items.Clear(); /// /// Устанавливает значение пометки у всех элементов списка значений @@ -222,10 +208,7 @@ public void FillChecks(bool check) /// ЭлементСпискаЗначений - Элемент списка значений, для которого необходимо определить индекс /// Число - Индекс в списке, если не найдено возвращает -1 [ContextMethod("Индекс", "IndexOf")] - public int IndexOf(ValueListItem item) - { - return _items.IndexOf(item); - } + public int IndexOf(ValueListItem item) => _items.IndexOf(item); /// /// Осуществляет поиск значения в списке @@ -282,7 +265,6 @@ private int IndexByValue(BslValue item) public void Move(BslValue item, int offset) { int index_source = IndexByValue(item); - int index_dest = index_source + offset; if (index_dest < 0 || index_dest >= _items.Count) @@ -370,25 +352,14 @@ public void SortByPresentation(SortDirectionEnum? direction = null) /// Число - Индекс удаляемого элемента /// [ContextMethod("Удалить", "Delete")] - public void Delete(BslValue item) - { - int indexSource = IndexByValue(item); - - _items.RemoveAt(indexSource); - } + public void Delete(BslValue item) => _items.RemoveAt(IndexByValue(item)); #region Collection Context [ContextMethod("Количество", "Count")] - public override int Count() - { - return _items.Count; - } + public override int Count() => _items.Count; - public override IEnumerator GetEnumerator() - { - return _items.GetEnumerator(); - } + public override IEnumerator GetEnumerator() => _items.GetEnumerator(); #endregion