Skip to content

Commit 3845405

Browse files
authored
fix EvilBeaver#1577: сортировка неупорядочиваемых типов +тест
2 parents 14fb358 + 15235dc commit 3845405

File tree

3 files changed

+112
-9
lines changed

3 files changed

+112
-9
lines changed

src/OneScript.StandardLibrary/Collections/ValueTable/ValueTable.cs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -636,14 +636,15 @@ private class RowComparator : IComparer<ValueTableRow>
636636
{
637637
readonly List<ValueTableSortRule> Rules;
638638

639-
readonly GenericIValueComparer _comparer = new GenericIValueComparer();
639+
readonly GenericIValueComparer _comparer;
640640

641-
public RowComparator(List<ValueTableSortRule> Rules)
641+
public RowComparator(IBslProcess process, List<ValueTableSortRule> Rules)
642642
{
643-
if (Rules.Count() == 0)
643+
if (Rules.Count == 0)
644644
throw RuntimeException.InvalidArgumentValue();
645645

646646
this.Rules = Rules;
647+
_comparer = new GenericIValueComparer(process);
647648
}
648649

649650
private int OneCompare(ValueTableRow x, ValueTableRow y, ValueTableSortRule Rule)
@@ -661,7 +662,7 @@ public int Compare(ValueTableRow x, ValueTableRow y)
661662
int i = 0, r;
662663
while ((r = OneCompare(x, y, Rules[i])) == 0)
663664
{
664-
if (++i >= Rules.Count())
665+
if (++i >= Rules.Count)
665666
return 0;
666667
}
667668

@@ -678,9 +679,9 @@ public int Compare(ValueTableRow x, ValueTableRow y)
678679
/// </param>
679680
/// <param name="comparator">СравнениеЗначений - правила сравнения значений при наличии различных типов данных в колонке.</param>
680681
[ContextMethod("Сортировать", "Sort")]
681-
public void Sort(string columns, IValue comparator = null)
682+
public void Sort(IBslProcess process, string columns, IValue comparator = null)
682683
{
683-
_rows.Sort(new RowComparator(GetSortRules(columns)));
684+
_rows.Sort(new RowComparator(process, GetSortRules(columns)));
684685
}
685686

686687
/// <summary>

src/ScriptEngine/Machine/GenericIValueComparer.cs

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,29 @@ This Source Code Form is subject to the terms of the
55
at http://mozilla.org/MPL/2.0/.
66
----------------------------------------------------------*/
77

8+
using System;
89
using System.Collections.Generic;
910
using OneScript.Values;
1011
using ScriptEngine.Machine.Contexts;
12+
using OneScript.Execution;
1113

1214
namespace ScriptEngine.Machine
1315
{
1416
public class GenericIValueComparer : IEqualityComparer<IValue>, IComparer<IValue>
1517
{
18+
private readonly IBslProcess _process;
19+
private readonly Func<IValue, IValue, int> _comparer;
20+
21+
public GenericIValueComparer()
22+
{
23+
_comparer = CompareAsStrings;
24+
}
25+
26+
public GenericIValueComparer(IBslProcess proc)
27+
{
28+
_process = proc;
29+
_comparer = CompareByPresentations;
30+
}
1631

1732
public bool Equals(IValue x, IValue y)
1833
{
@@ -37,15 +52,25 @@ public int GetHashCode(IValue obj)
3752
return CLR_obj.GetHashCode();
3853
}
3954

55+
private int CompareAsStrings(IValue x, IValue y)
56+
{
57+
return x.ToString().CompareTo(y.ToString());
58+
}
59+
60+
private int CompareByPresentations(IValue x, IValue y)
61+
{
62+
return ((BslValue)x).ToString(_process).CompareTo(((BslValue)y).ToString(_process));
63+
}
64+
4065
public int Compare(IValue x, IValue y)
4166
{
42-
if (ReferenceEquals(x, default) && ReferenceEquals(y, default))
67+
if (ReferenceEquals(x, y))
4368
return 0;
4469

45-
if (x.SystemType == y.SystemType)
70+
if (x is IComparable && x.SystemType == y.SystemType )
4671
return x.CompareTo(y);
4772
else
48-
return x.ToString().CompareTo(y.ToString());
73+
return _comparer(x,y);
4974
}
5075
}
5176
}

tests/valuetable.os

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@
4343
ВсеТесты.Добавить("ТестДолжен_ПроверитьСверткуПоКолонкамСуммированияСРазнымиТипами");
4444
ВсеТесты.Добавить("ТестДолжен_ПроверитьСверткуПоОднойКолонкеСРазнымиТипами");
4545

46+
ВсеТесты.Добавить("ТестДолжен_ПроверитьСортировкуНеупорядочиваемыхТипов");
47+
ВсеТесты.Добавить("ТестДолжен_ПроверитьСортировкуРазныхТипов");
48+
ВсеТесты.Добавить("ТестДолжен_ПроверитьСортировкуПоПредставлению");
4649
Возврат ВсеТесты;
4750

4851
КонецФункции
@@ -779,3 +782,77 @@
779782
юТест.ПроверитьРавенство( СтрТЗ2[КолонкаСуммы], Количество,
780783
СтрШаблон("Сумма колонки %1 для значения %2 типа %3", КолонкаСуммы, Значение, ТипЗнч(Значение)) );
781784
КонецПроцедуры
785+
786+
// к issue #1577
787+
Процедура ТестДолжен_ПроверитьСортировкуНеупорядочиваемыхТипов() Экспорт
788+
ТЗ = Новый ТаблицаЗначений();
789+
ТЗ.Колонки.Добавить("Тест");
790+
791+
ТЗ.Добавить().Тест = Неопределено;
792+
ТЗ.Добавить().Тест = Неопределено;
793+
794+
ТЗ.Сортировать("Тест"); // не должно упасть
795+
796+
юТест.ПроверитьРавенство(ТЗ[0].Тест, Неопределено);
797+
юТест.ПроверитьРавенство(ТЗ[1].Тест, Неопределено);
798+
КонецПроцедуры
799+
800+
Процедура ТестДолжен_ПроверитьСортировкуРазныхТипов() Экспорт
801+
ТЗ = Новый ТаблицаЗначений();
802+
ТЗ.Колонки.Добавить("Тест");
803+
804+
ТЗ.Добавить().Тест = Тип("Строка");
805+
ТЗ.Добавить().Тест = "Стр2";
806+
ТЗ.Добавить().Тест = "СтрЪ";
807+
ТЗ.Добавить().Тест = Новый Структура;
808+
ТЗ.Добавить().Тест = null;
809+
ТЗ.Добавить().Тест = Тип("Булево");
810+
811+
ТЗ.Сортировать("Тест"); // не должно упасть
812+
813+
юТест.ПроверитьРавенство(ТЗ[0].Тест, Null);
814+
юТест.ПроверитьРавенство(ТЗ[1].Тест, Тип("Булево"));
815+
юТест.ПроверитьРавенство(ТЗ[2].Тест, "Стр2");
816+
юТест.ПроверитьРавенство(ТЗ[3].Тест, Тип("Строка"));
817+
юТест.ПроверитьРавенство(ТипЗнч(ТЗ[4].Тест), Тип("Структура"));
818+
юТест.ПроверитьРавенство(ТЗ[5].Тест, "СтрЪ");
819+
КонецПроцедуры
820+
821+
Процедура ТестДолжен_ПроверитьСортировкуПоПредставлению() Экспорт
822+
ТЗ = Новый ТаблицаЗначений();
823+
ТЗ.Колонки.Добавить("Тест");
824+
825+
ТекстКласса =
826+
"Процедура ОбработкаПолученияПредставления(Представление, СтандартнаяОбработка)
827+
| СтандартнаяОбработка = Ложь;
828+
| Представление = ""Представление0"";
829+
|КонецПроцедуры";
830+
КлассИзСтроки0 = ЗагрузитьСценарийИзСтроки(ТекстКласса);
831+
832+
ТекстКласса =
833+
"Процедура ОбработкаПолученияПредставления(Представление, СтандартнаяОбработка)
834+
| СтандартнаяОбработка = Ложь;
835+
| Представление = ""Представление1"";
836+
|КонецПроцедуры";
837+
КлассИзСтроки1 = ЗагрузитьСценарийИзСтроки(ТекстКласса);
838+
839+
ТекстКласса =
840+
"Процедура ОбработкаПолученияПредставления(Представление, СтандартнаяОбработка)
841+
| СтандартнаяОбработка = Ложь;
842+
| Представление = ""Представление3"";
843+
|КонецПроцедуры";
844+
КлассИзСтроки3 = ЗагрузитьСценарийИзСтроки(ТекстКласса);
845+
846+
ТЗ.Добавить().Тест = КлассИзСтроки3;
847+
ТЗ.Добавить().Тест = "Представление2";
848+
ТЗ.Добавить().Тест = КлассИзСтроки0;
849+
ТЗ.Добавить().Тест = КлассИзСтроки1;
850+
851+
ТЗ.Сортировать("Тест");
852+
юТест.ПроверитьРавенство(Строка(ТЗ[0].Тест), "Представление0");
853+
юТест.ПроверитьРавенство(Строка(ТЗ[1].Тест), "Представление1");
854+
юТест.ПроверитьРавенство(ТЗ[2].Тест, "Представление2");
855+
юТест.ПроверитьРавенство(Строка(ТЗ[3].Тест), "Представление3");
856+
857+
КонецПроцедуры
858+

0 commit comments

Comments
 (0)