diff --git a/src/OneScript.Core/Exceptions/ComparisonException.cs b/src/OneScript.Core/Exceptions/ComparisonException.cs new file mode 100644 index 000000000..482abfd4c --- /dev/null +++ b/src/OneScript.Core/Exceptions/ComparisonException.cs @@ -0,0 +1,40 @@ +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ + +using System; +using OneScript.Localization; + +namespace OneScript.Exceptions +{ + public class ComparisonException : RuntimeException + { + public ComparisonException(BilingualString message) : base(message) + { + } + + public static ComparisonException NotSupported() + { + return new ComparisonException(new BilingualString( + $"Сравнение на больше/меньше для данного типа не поддерживается", + $"Greater-than/Less-than comparison operations are not supported")); + } + + public static ComparisonException NotSupported(string type) + { + return new ComparisonException(new BilingualString( + $"Сравнение на больше/меньше для типа '{type}' не поддерживается", + $"Greater-than/Less-than comparison operations are not supported for '{type}'")); + } + + public static ComparisonException NotSupported(string type1, string type2) + { + return new ComparisonException(new BilingualString( + $"Сравнение на больше/меньше типов '{type1}' и '{type2}' не поддерживается", + $"Greater-than/Less-than comparison operations are not supported for '{type1}' and '{type2}'")); + } + } +} \ No newline at end of file diff --git a/src/OneScript.Core/Exceptions/RuntimeException.cs b/src/OneScript.Core/Exceptions/RuntimeException.cs index c47be307b..f5819b957 100644 --- a/src/OneScript.Core/Exceptions/RuntimeException.cs +++ b/src/OneScript.Core/Exceptions/RuntimeException.cs @@ -118,20 +118,6 @@ public static RuntimeException InvalidNthArgumentValue(int argNum) $"Invalid value for argument number {argNum}"); } - public static RuntimeException ComparisonNotSupportedException() - { - return new RuntimeException( - "Сравнение на больше/меньше для данного типа не поддерживается", - "Greater-than/Less-than comparison operations are not supported"); - } - - public static RuntimeException ComparisonNotSupportedException(string type1, string type2) - { - return new RuntimeException( - $"Сравнение на больше/меньше для данного типа не поддерживается {type1} <-> {type2}", - $"Greater-than/Less-than comparison operations are not supported for {type1} <-> {type2}"); - } - public static RuntimeException IndexedAccessIsNotSupportedException() { return new RuntimeException( diff --git a/src/OneScript.Core/Values/BslBooleanValue.cs b/src/OneScript.Core/Values/BslBooleanValue.cs index 4963cd83f..c87ccd889 100644 --- a/src/OneScript.Core/Values/BslBooleanValue.cs +++ b/src/OneScript.Core/Values/BslBooleanValue.cs @@ -12,7 +12,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.Values { - public sealed class BslBooleanValue : BslPrimitiveValue + public sealed class BslBooleanValue : BslPrimitiveValue, IBslComparable { public static readonly BslBooleanValue True = new BslBooleanValue(true); public static readonly BslBooleanValue False = new BslBooleanValue(false); @@ -57,7 +57,6 @@ public override string ToString() public override bool Equals(BslValue other) { - if (other is null) return false; if (ReferenceEquals(this, other)) return true; return other switch diff --git a/src/OneScript.Core/Values/BslDateValue.cs b/src/OneScript.Core/Values/BslDateValue.cs index 79bb70161..6023afce0 100644 --- a/src/OneScript.Core/Values/BslDateValue.cs +++ b/src/OneScript.Core/Values/BslDateValue.cs @@ -12,7 +12,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.Values { - public sealed class BslDateValue : BslPrimitiveValue + public sealed class BslDateValue : BslPrimitiveValue, IBslComparable { private readonly DateTime _value; @@ -25,9 +25,6 @@ private BslDateValue(DateTime value) public override int CompareTo(BslValue other) { - if (ReferenceEquals(null, other)) - return -1; - if(other is BslDateValue d) return _value.CompareTo(d._value); diff --git a/src/OneScript.Core/Values/BslNumericValue.cs b/src/OneScript.Core/Values/BslNumericValue.cs index 2bfb57a55..8d3464fd0 100644 --- a/src/OneScript.Core/Values/BslNumericValue.cs +++ b/src/OneScript.Core/Values/BslNumericValue.cs @@ -14,7 +14,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.Values { - public sealed class BslNumericValue : BslPrimitiveValue, IEquatable + public sealed class BslNumericValue : BslPrimitiveValue, IEquatable, IBslComparable { private static readonly BslNumericValue[] _popularValues = new BslNumericValue[10]; static BslNumericValue() @@ -84,7 +84,6 @@ public bool Equals(BslNumericValue other) public override bool Equals(BslValue other) { - if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return other switch diff --git a/src/OneScript.Core/Values/BslObjectValue.cs b/src/OneScript.Core/Values/BslObjectValue.cs index 10226630d..610b28be8 100644 --- a/src/OneScript.Core/Values/BslObjectValue.cs +++ b/src/OneScript.Core/Values/BslObjectValue.cs @@ -12,14 +12,6 @@ namespace OneScript.Values { public abstract class BslObjectValue : BslValue { - public override int CompareTo(BslValue other) - { - var msg = new BilingualString("Сравнение на больше/меньше для данного типа не поддерживается", - "Comparison for less/greater is not supported for this type"); - - throw new RuntimeException(msg); - } - public override bool Equals(BslValue other) { return ReferenceEquals(this, other); diff --git a/src/OneScript.Core/Values/BslPrimitiveValue.cs b/src/OneScript.Core/Values/BslPrimitiveValue.cs index 24bc8000d..33a990ade 100644 --- a/src/OneScript.Core/Values/BslPrimitiveValue.cs +++ b/src/OneScript.Core/Values/BslPrimitiveValue.cs @@ -5,35 +5,10 @@ This Source Code Form is subject to the terms of the at http://mozilla.org/MPL/2.0/. ----------------------------------------------------------*/ -using System; -using OneScript.Exceptions; - namespace OneScript.Values { public abstract class BslPrimitiveValue : BslValue { - public override int CompareTo(BslValue other) - { - if (other == null) - return -1; - - string typeOfThis = null; - string typeOfOther = null; - - try - { - typeOfThis = this.SystemType.Name; - typeOfOther = other.SystemType.Name; - } - catch (InvalidOperationException) // если тип не зарегистрирован - { - typeOfThis ??= GetType().ToString(); - typeOfOther ??= GetType().ToString(); - } - - throw RuntimeException.ComparisonNotSupportedException(typeOfThis, typeOfOther); - } - public override bool Equals(BslValue other) => false; } } \ No newline at end of file diff --git a/src/OneScript.Core/Values/BslStringValue.cs b/src/OneScript.Core/Values/BslStringValue.cs index 99c8ac1ea..ab2d11078 100644 --- a/src/OneScript.Core/Values/BslStringValue.cs +++ b/src/OneScript.Core/Values/BslStringValue.cs @@ -10,7 +10,7 @@ This Source Code Form is subject to the terms of the namespace OneScript.Values { - public sealed class BslStringValue : BslPrimitiveValue + public sealed class BslStringValue : BslPrimitiveValue, IBslComparable { private readonly string _value; @@ -49,8 +49,8 @@ public override bool Equals(BslValue other) public override int CompareTo(BslValue other) { - if (ReferenceEquals(null, other)) - return -1; + if (ReferenceEquals(this, other)) + return 0; if (other is BslStringValue s) return String.Compare(_value, s._value, StringComparison.CurrentCulture); diff --git a/src/OneScript.Core/Values/BslValue.cs b/src/OneScript.Core/Values/BslValue.cs index 092cfdf24..14d1596b9 100644 --- a/src/OneScript.Core/Values/BslValue.cs +++ b/src/OneScript.Core/Values/BslValue.cs @@ -27,7 +27,30 @@ public virtual string ToString(IBslProcess process) return ToString(); } - public abstract int CompareTo(BslValue other); + public virtual int CompareTo(BslValue other) + { + if (other is null) + return -1; + + string typeOfThis = null; + string typeOfOther = null; + + try + { + typeOfThis = this.SystemType.Name; + typeOfOther = other.SystemType.Name; + } + catch (InvalidOperationException) // если тип не зарегистрирован + { + typeOfThis ??= this.GetType().ToString(); + typeOfOther ??= other.GetType().ToString(); + } + + if (typeOfThis == typeOfOther) + throw ComparisonException.NotSupported(typeOfThis); + else + throw ComparisonException.NotSupported(typeOfThis, typeOfOther); + } public abstract bool Equals(BslValue other); @@ -76,7 +99,7 @@ public static explicit operator DateTime(BslValue target) => public virtual IValue GetRawValue() => this; - private BslValue UnwrapReference(IValue v) + private static BslValue UnwrapReference(IValue v) { if (v is IValueReference r) return r.BslValue; diff --git a/src/OneScript.Core/Values/EnumerationValue.cs b/src/OneScript.Core/Values/EnumerationValue.cs index 4d91d31bb..7d5da02be 100644 --- a/src/OneScript.Core/Values/EnumerationValue.cs +++ b/src/OneScript.Core/Values/EnumerationValue.cs @@ -46,11 +46,6 @@ public override string ToString() public override IValue GetRawValue() => this; - public override int CompareTo(BslValue other) - { - throw RuntimeException.ComparisonNotSupportedException(); - } - public override bool Equals(BslValue other) { return ReferenceEquals(other?.GetRawValue(), this); diff --git a/src/OneScript.Core/Values/IBslComparable.cs b/src/OneScript.Core/Values/IBslComparable.cs new file mode 100644 index 000000000..4075a214b --- /dev/null +++ b/src/OneScript.Core/Values/IBslComparable.cs @@ -0,0 +1,17 @@ +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ + +namespace OneScript.Values +{ + /// + /// Интерфейс-маркер для примитивных типов, допускающих сравнение на больше/меньше. + /// Используется GenericIValueComparer для определения возможности сравнения. + /// + public interface IBslComparable + { + } +} \ No newline at end of file diff --git a/src/OneScript.StandardLibrary/Collections/Exceptions/ColumnException.cs b/src/OneScript.StandardLibrary/Collections/Exceptions/ColumnException.cs new file mode 100644 index 000000000..7867f1015 --- /dev/null +++ b/src/OneScript.StandardLibrary/Collections/Exceptions/ColumnException.cs @@ -0,0 +1,54 @@ +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using System; +using OneScript.Exceptions; +using OneScript.Localization; + +namespace OneScript.StandardLibrary.Collections.Exceptions +{ + public class ColumnException : RuntimeException + { + public ColumnException(BilingualString message, Exception innerException) : base(message, + innerException) + { + } + + public ColumnException(BilingualString message) : base(message) + { + } + + public static ColumnException WrongColumnName() + { + return new ColumnException(new BilingualString( + "Неверное имя колонки", + "Wrong column name")); + } + + public static ColumnException WrongColumnName(string columnName) + { + return new ColumnException(new BilingualString( + $"Неверное имя колонки '{columnName}'", + $"Wrong column name '{columnName}'")); + } + + public static ColumnException DuplicatedColumnName(string columnName) + { + return new ColumnException(new BilingualString( + $"Колонка '{columnName}' уже есть", + $"Column '{columnName}' already exists")); + } + + + public static ColumnException ColumnsMixed(string columnName) + { + return new ColumnException(new BilingualString( + $"Колонка '{columnName}' не может одновременно быть колонкой группировки и колонкой суммирования", + $"Column '{columnName}' cannot be both grouping column and summation column")); + } + + } +} \ No newline at end of file diff --git a/src/OneScript.StandardLibrary/Collections/ValueTable/CollectionIndexes.cs b/src/OneScript.StandardLibrary/Collections/ValueTable/CollectionIndexes.cs index 1167a76ff..51913d45b 100644 --- a/src/OneScript.StandardLibrary/Collections/ValueTable/CollectionIndexes.cs +++ b/src/OneScript.StandardLibrary/Collections/ValueTable/CollectionIndexes.cs @@ -10,12 +10,12 @@ This Source Code Form is subject to the terms of the using System.Linq; using OneScript.Contexts; using OneScript.Exceptions; +using OneScript.StandardLibrary.Collections.Exceptions; using OneScript.StandardLibrary.Collections.Indexes; using OneScript.Types; using OneScript.Values; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; -using ScriptEngine.Types; namespace OneScript.StandardLibrary.Collections.ValueTable { @@ -143,7 +143,7 @@ private static IList BuildFieldList(IIndexCollectionSource source, strin var field = source.GetField(fieldName.Trim()); if (field == null) { - throw new ColumnNotFoundException(fieldName); + throw ColumnException.WrongColumnName(fieldName); } fields.Add(field); } diff --git a/src/OneScript.StandardLibrary/Collections/ValueTable/ColumnNotFoundException.cs b/src/OneScript.StandardLibrary/Collections/ValueTable/ColumnNotFoundException.cs deleted file mode 100644 index 84d11bffe..000000000 --- a/src/OneScript.StandardLibrary/Collections/ValueTable/ColumnNotFoundException.cs +++ /dev/null @@ -1,29 +0,0 @@ -/*---------------------------------------------------------- -This Source Code Form is subject to the terms of the -Mozilla Public License, v.2.0. If a copy of the MPL -was not distributed with this file, You can obtain one -at http://mozilla.org/MPL/2.0/. -----------------------------------------------------------*/ -using System; -using OneScript.Exceptions; -using OneScript.Localization; - -namespace OneScript.StandardLibrary.Collections.ValueTable -{ - public class ColumnNotFoundException : RuntimeException - { - public ColumnNotFoundException(BilingualString message, Exception innerException) : base(message, - innerException) - { - } - - public ColumnNotFoundException(BilingualString message) : base(message) - { - } - - public ColumnNotFoundException(string columnName) : base($"Неверное имя колонки {columnName}") - { - } - - } -} \ No newline at end of file diff --git a/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTable.cs b/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTable.cs index 0c3cdb7d3..5c59332c9 100644 --- a/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTable.cs +++ b/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTable.cs @@ -16,6 +16,7 @@ This Source Code Form is subject to the terms of the using OneScript.Values; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; +using OneScript.StandardLibrary.Collections.Exceptions; namespace OneScript.StandardLibrary.Collections.ValueTable { @@ -166,7 +167,7 @@ private List GetProcessingColumnList(string ColumnNames, bool var Column = Columns.FindColumnByName(name); if (Column == null) - throw WrongColumnNameException(name); + throw ColumnException.WrongColumnName(name); if (processing_list.Find( x=> x.Name==name ) == null) processing_list.Add(Column); @@ -271,7 +272,7 @@ private bool CheckFilterCriteria(ValueTableRow Row, StructureImpl Filter) { var Column = Columns.FindColumnByName(kv.Key.ToString()); if (Column == null) - throw WrongColumnNameException(kv.Key.ToString()); + throw ColumnException.WrongColumnName(kv.Key.ToString()); IValue current = Row.Get(Column); if (!current.StrictEquals(kv.Value)) @@ -374,7 +375,7 @@ public void GroupBy(IBslProcess process, string groupColumnNames, string aggrega } } - _rows.RemoveRange(new_idx, _rows.Count()-new_idx); + _rows.RemoveRange(new_idx, _rows.Count - new_idx); int i = 0; while (i < Columns.Count()) @@ -391,7 +392,7 @@ private static void CheckMixedColumns(List groupColumns, List< { foreach (var groupColumn in groupColumns ) if ( aggregateColumns.Find(x => x.Name==groupColumn.Name)!=null ) - throw ColumnsMixedException(groupColumn.Name); + throw ColumnException.ColumnsMixed(groupColumn.Name); } private static void CopyRowData(ValueTableRow source, ValueTableRow dest, IEnumerable columns) @@ -467,7 +468,7 @@ private int IndexByValue(BslValue item) throw RuntimeException.InvalidArgumentType(); } - if (index < 0 || index >= _rows.Count()) + if (index < 0 || index >= _rows.Count) throw new RuntimeException("Значение индекса выходит за пределы диапазона"); } @@ -489,7 +490,7 @@ public void Move(BslValue row, int offset) int index_dest = index_source + offset; - if (index_dest < 0 || index_dest >= _rows.Count()) + if (index_dest < 0 || index_dest >= _rows.Count) throw RuntimeException.InvalidNthArgumentValue(2); ValueTableRow tmp = _rows[index_source]; @@ -610,13 +611,13 @@ private List GetSortRules(string Columns) foreach (string column in a_columns) { string[] description = column.Trim().Split(' '); - if (description.Count() == 0) - throw WrongColumnNameException(); + if (description.Length == 0) + throw ColumnException.WrongColumnName(); ValueTableSortRule Desc = new ValueTableSortRule(); Desc.Column = this.Columns.FindColumnByName(description[0]); - if (description.Count() > 1) + if (description.Length > 1) { if (String.Compare(description[1], "DESC", true) == 0 || String.Compare(description[1], "УБЫВ", true) == 0) Desc.direction = -1; @@ -719,22 +720,6 @@ public static ValueTable Constructor() return new ValueTable(); } - - private static RuntimeException WrongColumnNameException() - { - return new RuntimeException("Неверное имя колонки"); - } - - private static RuntimeException WrongColumnNameException(string columnName) - { - return new RuntimeException(string.Format("Неверное имя колонки '{0}'", columnName)); - } - - private static RuntimeException ColumnsMixedException(string columnName) - { - return new RuntimeException(string.Format("Колонка '{0}' не может одновременно быть колонкой группировки и колонкой суммирования", columnName)); - } - public string GetName(IValue field) { if (field is ValueTableColumn column) diff --git a/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTableColumn.cs b/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTableColumn.cs index 7af592fd2..516a9e13b 100644 --- a/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTableColumn.cs +++ b/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTableColumn.cs @@ -7,7 +7,7 @@ This Source Code Form is subject to the terms of the using System; using OneScript.Contexts; -using OneScript.Exceptions; +using OneScript.StandardLibrary.Collections.Exceptions; using OneScript.StandardLibrary.TypeDescriptions; using OneScript.Types; using ScriptEngine.Machine.Contexts; @@ -61,7 +61,7 @@ public string Name { ValueTableColumnCollection Owner = _owner.Target as ValueTableColumnCollection; if (Owner.FindColumnByName(value) != null) - throw new RuntimeException("Неверное имя колонки!"); + throw ColumnException.WrongColumnName(); if (_title == _name) _title = value; diff --git a/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTableColumnCollection.cs b/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTableColumnCollection.cs index 8427df725..aaeb48e78 100644 --- a/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTableColumnCollection.cs +++ b/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTableColumnCollection.cs @@ -12,11 +12,11 @@ This Source Code Form is subject to the terms of the using OneScript.Contexts; using OneScript.Exceptions; using OneScript.Execution; +using OneScript.StandardLibrary.Collections.Exceptions; using OneScript.StandardLibrary.TypeDescriptions; using OneScript.Types; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; -using ScriptEngine.Types; namespace OneScript.StandardLibrary.Collections.ValueTable { @@ -48,7 +48,7 @@ public ValueTableColumnCollection(ValueTable owner) public ValueTableColumn Add(string name, TypeDescription type = null, string title = null, int width = 0) { if (FindColumnByName(name) != null) - throw new RuntimeException("Неверное имя колонки " + name); + throw ColumnException.DuplicatedColumnName(name); var column = new ValueTableColumn(this, ++maxColumnId, name, title, type, width); _columns.Add(column); @@ -69,7 +69,7 @@ public ValueTableColumn Add(string name, TypeDescription type = null, string tit public ValueTableColumn Insert(int index, string name, TypeDescription type = null, string title = null, int width = 0) { if (FindColumnByName(name) != null) - throw new RuntimeException("Неверное имя колонки " + name); + throw ColumnException.DuplicatedColumnName(name); ValueTableColumn column = new ValueTableColumn(this, ++maxColumnId, name, title, type, width); _columns.Insert(index, column); diff --git a/src/OneScript.StandardLibrary/Collections/ValueTree/ValueTreeColumn.cs b/src/OneScript.StandardLibrary/Collections/ValueTree/ValueTreeColumn.cs index 8e322af3d..494d423f3 100644 --- a/src/OneScript.StandardLibrary/Collections/ValueTree/ValueTreeColumn.cs +++ b/src/OneScript.StandardLibrary/Collections/ValueTree/ValueTreeColumn.cs @@ -6,7 +6,7 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using OneScript.Contexts; -using OneScript.Exceptions; +using OneScript.StandardLibrary.Collections.Exceptions; using OneScript.StandardLibrary.TypeDescriptions; using OneScript.Types; using ScriptEngine.Machine.Contexts; @@ -60,7 +60,7 @@ public string Name set { if (_owner.FindColumnByName(value) != null) - throw new RuntimeException("Неверное имя колонки!"); + throw ColumnException.WrongColumnName(); if (_title == _name) _title = value; diff --git a/src/OneScript.StandardLibrary/Collections/ValueTree/ValueTreeColumnCollection.cs b/src/OneScript.StandardLibrary/Collections/ValueTree/ValueTreeColumnCollection.cs index 6697844cf..fcb66fa3c 100644 --- a/src/OneScript.StandardLibrary/Collections/ValueTree/ValueTreeColumnCollection.cs +++ b/src/OneScript.StandardLibrary/Collections/ValueTree/ValueTreeColumnCollection.cs @@ -11,12 +11,12 @@ This Source Code Form is subject to the terms of the using OneScript.Contexts; using OneScript.Exceptions; using OneScript.Execution; +using OneScript.StandardLibrary.Collections.Exceptions; using OneScript.StandardLibrary.TypeDescriptions; using OneScript.Types; using OneScript.Values; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; -using ScriptEngine.Types; namespace OneScript.StandardLibrary.Collections.ValueTree { @@ -40,7 +40,7 @@ public class ValueTreeColumnCollection : AutoContext, public ValueTreeColumn Add(string name, TypeDescription type = null, string title = null, int width = 0) { if (FindColumnByName(name) != null) - throw new RuntimeException("Неверное имя колонки " + name); + throw ColumnException.DuplicatedColumnName(name); ValueTreeColumn column = new ValueTreeColumn(this, name, title, type, width); _columns.Add(column); @@ -61,7 +61,7 @@ public ValueTreeColumn Add(string name, TypeDescription type = null, string titl public ValueTreeColumn Insert(int index, string name, TypeDescription type = null, string title = null, int width = 0) { if (FindColumnByName(name) != null) - throw new RuntimeException("Неверное имя колонки " + name); + throw ColumnException.DuplicatedColumnName(name); ValueTreeColumn column = new ValueTreeColumn(this, name, title, type, width); _columns.Insert(index, column); diff --git a/src/OneScript.StandardLibrary/Collections/ValueTree/ValueTreeRowCollection.cs b/src/OneScript.StandardLibrary/Collections/ValueTree/ValueTreeRowCollection.cs index a980670ba..10a1c8259 100644 --- a/src/OneScript.StandardLibrary/Collections/ValueTree/ValueTreeRowCollection.cs +++ b/src/OneScript.StandardLibrary/Collections/ValueTree/ValueTreeRowCollection.cs @@ -7,14 +7,14 @@ This Source Code Form is subject to the terms of the using System; using System.Collections.Generic; -using System.Linq; using OneScript.Contexts; using OneScript.Exceptions; +using OneScript.Execution; +using OneScript.StandardLibrary.Collections.Exceptions; using OneScript.Types; using OneScript.Values; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; -using ScriptEngine.Types; namespace OneScript.StandardLibrary.Collections.ValueTree { @@ -72,7 +72,7 @@ public ValueTree Owner() [ContextMethod("Количество", "Count")] public override int Count() { - return _rows.Count(); + return _rows.Count; } /// @@ -323,12 +323,12 @@ public void Move(BslValue row, int offset) else throw RuntimeException.InvalidArgumentType(); - if (indexSource < 0 || indexSource >= _rows.Count()) + if (indexSource < 0 || indexSource >= _rows.Count) throw RuntimeException.InvalidArgumentValue(); - int indexDestination = (indexSource + offset) % _rows.Count(); + int indexDestination = (indexSource + offset) % _rows.Count; while (indexDestination < 0) - indexDestination += _rows.Count(); + indexDestination += _rows.Count; ValueTreeRow tmp = _rows[indexSource]; @@ -361,15 +361,15 @@ private List GetSortRules(string columns) foreach (string column in aColumns) { string[] description = column.Trim().Split(' '); - if (description.Count() == 0) - throw PropertyAccessException.PropNotFoundException(""); // TODO: WrongColumnNameException + if (description.Length == 0) + throw ColumnException.WrongColumnName(); ValueTreeSortRule desc = new ValueTreeSortRule(); desc.Column = this.Columns.FindColumnByName(description[0]); if (desc.Column == null) - throw PropertyAccessException.PropNotFoundException(description[0]); + throw ColumnException.WrongColumnName(description[0]); - if (description.Count() > 1) + if (description.Length > 1) { if (String.Compare(description[1], "DESC", true) == 0 || String.Compare(description[1], "УБЫВ", true) == 0) desc.direction = -1; @@ -389,14 +389,15 @@ private class RowComparator : IComparer { readonly List _rules; - readonly GenericIValueComparer _comparer = new GenericIValueComparer(); + readonly GenericIValueComparer _comparer; - public RowComparator(List rules) + public RowComparator(IBslProcess process, List rules) { - if (rules.Count() == 0) + if (rules.Count == 0) throw RuntimeException.InvalidArgumentValue(); this._rules = rules; + _comparer = new GenericIValueComparer(process); } private int OneCompare(ValueTreeRow x, ValueTreeRow y, ValueTreeSortRule rule) @@ -414,7 +415,7 @@ public int Compare(ValueTreeRow x, ValueTreeRow y) int i = 0, r; while ((r = OneCompare(x, y, _rules[i])) == 0) { - if (++i >= _rules.Count()) + if (++i >= _rules.Count) return 0; } @@ -430,12 +431,12 @@ public int Compare(ValueTreeRow x, ValueTreeRow y) /// Булево. Если Истина, сортировка будет применена также к вложенным строкам. /// СравнениеЗначений. Не используется. [ContextMethod("Сортировать", "Sort")] - public void Sort(string columns, bool sortChildren = false, IValue comparator = null) + public void Sort(IBslProcess process, string columns, bool sortChildren = false, IValue comparator = null) { - Sort(new RowComparator(GetSortRules(columns)), sortChildren); + Sort(process, new RowComparator(process, GetSortRules(columns)), sortChildren); } - private void Sort(RowComparator comparator, bool sortChildren) + private void Sort(IBslProcess process, RowComparator comparator, bool sortChildren) { _rows.Sort(comparator); @@ -443,7 +444,7 @@ private void Sort(RowComparator comparator, bool sortChildren) { foreach (var row in _rows) { - row.Rows.Sort(comparator, sortChildren); + row.Rows.Sort(process, comparator, sortChildren); } } } @@ -486,6 +487,6 @@ public override IEnumerator GetEnumerator() public override IValue GetIndexedValue(IValue index) { return Get((int)index.AsNumber()); - } + } } } diff --git a/src/OneScript.StandardLibrary/GuidWrapper.cs b/src/OneScript.StandardLibrary/GuidWrapper.cs index 5054a0640..b892e5021 100644 --- a/src/OneScript.StandardLibrary/GuidWrapper.cs +++ b/src/OneScript.StandardLibrary/GuidWrapper.cs @@ -62,7 +62,7 @@ public override int CompareTo(BslValue other) { GuidWrapper otherUuid = other.GetRawValue() as GuidWrapper; if (otherUuid == null) - throw RuntimeException.ComparisonNotSupportedException(); + throw ComparisonException.NotSupported(); return _value.CompareTo(otherUuid._value); } diff --git a/src/ScriptEngine/Machine/Contexts/ContextIValueImpl.cs b/src/ScriptEngine/Machine/Contexts/ContextIValueImpl.cs index e3eaec6ef..e8d8d07ac 100644 --- a/src/ScriptEngine/Machine/Contexts/ContextIValueImpl.cs +++ b/src/ScriptEngine/Machine/Contexts/ContextIValueImpl.cs @@ -58,15 +58,6 @@ public override TypeDescriptor SystemType #endregion - #region IComparable Members - - public override int CompareTo(BslValue other) - { - throw RuntimeException.ComparisonNotSupportedException(); - } - - #endregion - #region IEquatable Members public override bool Equals(BslValue other) diff --git a/src/ScriptEngine/Machine/GenericIValueComparer.cs b/src/ScriptEngine/Machine/GenericIValueComparer.cs index 2cfbf9ca4..5d913a5dd 100644 --- a/src/ScriptEngine/Machine/GenericIValueComparer.cs +++ b/src/ScriptEngine/Machine/GenericIValueComparer.cs @@ -10,6 +10,7 @@ This Source Code Form is subject to the terms of the using OneScript.Values; using ScriptEngine.Machine.Contexts; using OneScript.Execution; +using OneScript.Types; namespace ScriptEngine.Machine { @@ -18,6 +19,12 @@ public class GenericIValueComparer : IEqualityComparer, IComparer _comparer; + static private readonly ListorderedTypes = new List + { BasicTypes.Undefined, BasicTypes.Null, BasicTypes.Boolean, + BasicTypes.Number, BasicTypes.String, BasicTypes.Date, BasicTypes.Type }; + + private const int INDEX_OF_TYPE = 6; + public GenericIValueComparer() { _comparer = CompareAsStrings; @@ -60,14 +67,40 @@ private int CompareAsStrings(IValue x, IValue y) private int CompareByPresentations(IValue x, IValue y) { return ((BslValue)x).ToString(_process).CompareTo(((BslValue)y).ToString(_process)); + } + + /// + /// Сравнение переменных разных типов. Правила сравнения соответствуют 1С v8.3.27: + /// Переменные типа "Тип" следуют за всеми прочими; + /// Другие примитивные типы предшествуют объектным типам; + /// Между собой примитивные типы упорядочиваются в последовательности, указанной в orderedTypes; + /// Объектные типы упорядочиваются по строковому представлению. + /// + private int CompareByTypes(IValue x, IValue y) + { + var ix = orderedTypes.IndexOf(x.SystemType); + var iy = orderedTypes.IndexOf(y.SystemType); + + if (ix >= 0) + if (iy >= 0) + return ix - iy; + else + return ix == INDEX_OF_TYPE ? 1 : -1; + else if (iy >= 0) + return iy == INDEX_OF_TYPE ? -1 : 1; + + return _comparer(x,y); } public int Compare(IValue x, IValue y) { if (ReferenceEquals(x, y)) return 0; - - if (x is IComparable && x.SystemType == y.SystemType ) + + if (x.SystemType != y.SystemType ) + return CompareByTypes(x,y); + + if (x is IBslComparable) return x.CompareTo(y); else return _comparer(x,y); diff --git a/src/Tests/OneScript.Core.Tests/ValuesTest.cs b/src/Tests/OneScript.Core.Tests/ValuesTest.cs index 3a06461ba..5e22c455a 100644 --- a/src/Tests/OneScript.Core.Tests/ValuesTest.cs +++ b/src/Tests/OneScript.Core.Tests/ValuesTest.cs @@ -177,8 +177,8 @@ public void Invalid_Comparison_Num_And_String() var num1 = ValueFactory.Create(1); var num2 = ValueFactory.Create("2"); - Assert.ThrowsAny(() => num1.CompareTo(num2)); - Assert.ThrowsAny(() => num2.CompareTo(num1)); + Assert.ThrowsAny(() => num1.CompareTo(num2)); + Assert.ThrowsAny(() => num2.CompareTo(num1)); } [Fact] @@ -187,8 +187,7 @@ public void Invalid_Comparison_Undefined() var v1 = ValueFactory.Create(); var v2 = ValueFactory.Create(true); - //TODO: типизировать исключение ComparisonNotSupportedException - Assert.ThrowsAny(() => v1.CompareTo(v2)); + Assert.ThrowsAny(() => v1.CompareTo(v2)); } [Fact] diff --git a/tests/engine-behaviors.os b/tests/engine-behaviors.os index f35fefe8a..7901869f1 100644 --- a/tests/engine-behaviors.os +++ b/tests/engine-behaviors.os @@ -51,7 +51,7 @@ ВсеТесты.Добавить("ТестДолжен_ПроверитьПродолжениеВложенныхПопыток"); ВсеТесты.Добавить("ТестДолжен_ПроверитьИнформацияОбОшибкеВнеИсключения"); ВсеТесты.Добавить("ТестДолжен_ПроверитьПередачуПараметровПоСсылке"); - ВсеТесты.Добавить("ТестДолжен_ПроверитьСравнениеНаБольшеМеньше"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьОшибкиСравненияНаБольшеМеньше"); ВсеТесты.Добавить("ТестДолжен_ПроверитьЧто_ЭтотОбъект_НедоступенДляЗаписи"); ВсеТесты.Добавить("ТестДолжен_ПроверитьОперацииСДатой_Сложение"); @@ -664,41 +664,46 @@ КонецПроцедуры -Процедура ТестДолжен_ПроверитьСравнениеНаБольшеМеньше() Экспорт +Процедура ТестДолжен_ПроверитьОшибкиСравненияНаБольшеМеньше() Экспорт - Ошибка = "Сравнение на больше/меньше для данного типа не поддерживается"; - + Ошибка = "Сравнение на больше/меньше для типа 'СтатусСообщения' не поддерживается"; юТест.ПроверитьКодСОшибкой( "Рез = (СтатусСообщения.БезСтатуса <= СтатусСообщения.БезСтатуса);", Ошибка, "Для одинаковых значений перечислений" ); + Ошибка = "Сравнение на больше/меньше типов 'ЦветКонсоли' и 'СтатусСообщения' не поддерживается"; юТест.ПроверитьКодСОшибкой( "Рез = (ЦветКонсоли.Черный < СтатусСообщения.БезСтатуса);", Ошибка, "Для значений перечислений разных типов" ); + Ошибка = "Сравнение на больше/меньше для типа 'ПеречислениеКодировкаТекста' не поддерживается"; юТест.ПроверитьКодСОшибкой( "Рез = (КодировкаТекста >= КодировкаТекста);", Ошибка, "Для одинаковых перечислений" ); + + Ошибка = "Сравнение на больше/меньше типов 'ПеречислениеХешФункция' и 'ПеречислениеСтатусСообщения' не поддерживается"; юТест.ПроверитьКодСОшибкой( "Рез = (ХешФункция > СтатусСообщения);", Ошибка, "Для перечислений разных типов" ); + Ошибка = "Сравнение на больше/меньше для типа 'Тип' не поддерживается"; юТест.ПроверитьКодСОшибкой( "Рез = (ТипЗнч(истина) > ТипЗнч(0));", Ошибка, "Для значений типа 'Тип'" ); - + + Ошибка = "Сравнение на больше/меньше типов 'Массив' и 'Структура' не поддерживается"; юТест.ПроверитьКодСОшибкой( "Массив = Новый Массив(1); |Структура = Новый Структура; |Рез = (Массив > Структура);", Ошибка, "Для объектов разных типов" ); + Ошибка = "Сравнение на больше/меньше для типа 'Массив' не поддерживается"; юТест.ПроверитьКодСОшибкой( "Массив = Новый Массив(1); |Массив2 = Новый Массив(1);; |Рез = (Массив <= Массив2);", Ошибка, "Для одинаковых объектов" ); - КонецПроцедуры Процедура ТестДолжен_ПроверитьЧто_ЭтотОбъект_НедоступенДляЗаписи() Экспорт diff --git a/tests/valuetable.os b/tests/valuetable.os index a637cd7f4..fed94d134 100644 --- a/tests/valuetable.os +++ b/tests/valuetable.os @@ -43,6 +43,11 @@ ВсеТесты.Добавить("ТестДолжен_ПроверитьСверткуПоКолонкамСуммированияСРазнымиТипами"); ВсеТесты.Добавить("ТестДолжен_ПроверитьСверткуПоОднойКолонкеСРазнымиТипами"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьСортировку_Чисел"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьСортировку_Булевых"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьСортировку_Дат"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьСортировку_Строк"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьСортировкуНеупорядочиваемыхТипов"); ВсеТесты.Добавить("ТестДолжен_ПроверитьСортировкуРазныхТипов"); ВсеТесты.Добавить("ТестДолжен_ПроверитьСортировкуПоПредставлению"); @@ -783,6 +788,73 @@ СтрШаблон("Сумма колонки %1 для значения %2 типа %3", КолонкаСуммы, Значение, ТипЗнч(Значение)) ); КонецПроцедуры +Процедура ТестДолжен_ПроверитьСортировку_Чисел() Экспорт + ТЗ = Новый ТаблицаЗначений(); + ТЗ.Колонки.Добавить("Тест"); + + ТЗ.Добавить().Тест = 5; + ТЗ.Добавить().Тест = 10; + ТЗ.Добавить().Тест = -2; + + ТЗ.Сортировать("Тест"); + + юТест.ПроверитьРавенство(ТЗ[0].Тест, -2, "ТЗ[0]"); + юТест.ПроверитьРавенство(ТЗ[1].Тест, 5, "ТЗ[1]"); + юТест.ПроверитьРавенство(ТЗ[2].Тест, 10, "ТЗ[2]"); +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьСортировку_Булевых() Экспорт + ТЗ = Новый ТаблицаЗначений(); + ТЗ.Колонки.Добавить("Тест"); + + ТЗ.Добавить().Тест = Истина; + ТЗ.Добавить().Тест = Ложь; + ТЗ.Добавить().Тест = Истина; + + ТЗ.Сортировать("Тест"); + + юТест.ПроверитьРавенство(ТЗ[0].Тест, Ложь, "ТЗ[0]"); + юТест.ПроверитьРавенство(ТЗ[1].Тест, Истина, "ТЗ[1]"); + юТест.ПроверитьРавенство(ТЗ[2].Тест, Истина, "ТЗ[2]"); +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьСортировку_Дат() Экспорт + ТЗ = Новый ТаблицаЗначений(); + ТЗ.Колонки.Добавить("Тест"); + + Сегодня = ТекущаяДата(); + Пустая = '0001-01-01 00:00'; + ТЗ.Добавить().Тест = Сегодня; + ТЗ.Добавить().Тест = Сегодня + 2; + ТЗ.Добавить().Тест = Сегодня - 2; + ТЗ.Добавить().Тест = Пустая; + + ТЗ.Сортировать("Тест"); + + юТест.ПроверитьРавенство(ТЗ[0].Тест, Пустая, "ТЗ[0]"); + юТест.ПроверитьРавенство(ТЗ[1].Тест, Сегодня - 2, "ТЗ[1]"); + юТест.ПроверитьРавенство(ТЗ[2].Тест, Сегодня, "ТЗ[2]"); + юТест.ПроверитьРавенство(ТЗ[3].Тест, Сегодня + 2, "ТЗ[3]"); +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьСортировку_Строк() Экспорт + ТЗ = Новый ТаблицаЗначений(); + ТЗ.Колонки.Добавить("Тест"); + + ТЗ.Добавить().Тест = "Ели"; + ТЗ.Добавить().Тест = "ежи"; + ТЗ.Добавить().Тест = "Ёлки"; + ТЗ.Добавить().Тест = "ёжики"; + + ТЗ.Сортировать("Тест"); + + юТест.ПроверитьРавенство(ТЗ[0].Тест, "ежи", "ТЗ[0]"); + юТест.ПроверитьРавенство(ТЗ[1].Тест, "ёжики", "ТЗ[1]"); + юТест.ПроверитьРавенство(ТЗ[2].Тест, "Ели", "ТЗ[2]"); + юТест.ПроверитьРавенство(ТЗ[3].Тест, "Ёлки", "ТЗ[3]"); +КонецПроцедуры + + // к issue #1577 Процедура ТестДолжен_ПроверитьСортировкуНеупорядочиваемыхТипов() Экспорт ТЗ = Новый ТаблицаЗначений(); @@ -805,17 +877,21 @@ ТЗ.Добавить().Тест = "Стр2"; ТЗ.Добавить().Тест = "СтрЪ"; ТЗ.Добавить().Тест = Новый Структура; + ТЗ.Добавить().Тест = Новый Массив; ТЗ.Добавить().Тест = null; ТЗ.Добавить().Тест = Тип("Булево"); + ТЗ.Добавить().Тест = Тип("Массив"); ТЗ.Сортировать("Тест"); // не должно упасть юТест.ПроверитьРавенство(ТЗ[0].Тест, Null); - юТест.ПроверитьРавенство(ТЗ[1].Тест, Тип("Булево")); - юТест.ПроверитьРавенство(ТЗ[2].Тест, "Стр2"); - юТест.ПроверитьРавенство(ТЗ[3].Тест, Тип("Строка")); + юТест.ПроверитьРавенство(ТЗ[1].Тест, "Стр2"); + юТест.ПроверитьРавенство(ТЗ[2].Тест, "СтрЪ"); + юТест.ПроверитьРавенство(ТипЗнч(ТЗ[3].Тест), Тип("Массив")); юТест.ПроверитьРавенство(ТипЗнч(ТЗ[4].Тест), Тип("Структура")); - юТест.ПроверитьРавенство(ТЗ[5].Тест, "СтрЪ"); + юТест.ПроверитьРавенство(ТЗ[5].Тест, Тип("Булево")); + юТест.ПроверитьРавенство(ТЗ[6].Тест, Тип("Массив")); + юТест.ПроверитьРавенство(ТЗ[7].Тест, Тип("Строка")); КонецПроцедуры Процедура ТестДолжен_ПроверитьСортировкуПоПредставлению() Экспорт @@ -849,10 +925,10 @@ ТЗ.Добавить().Тест = КлассИзСтроки1; ТЗ.Сортировать("Тест"); - юТест.ПроверитьРавенство(Строка(ТЗ[0].Тест), "Представление0"); - юТест.ПроверитьРавенство(Строка(ТЗ[1].Тест), "Представление1"); - юТест.ПроверитьРавенство(ТЗ[2].Тест, "Представление2"); - юТест.ПроверитьРавенство(Строка(ТЗ[3].Тест), "Представление3"); + юТест.ПроверитьРавенство(ТЗ[0].Тест, "Представление2", "строка"); + юТест.ПроверитьРавенство(Строка(ТЗ[1].Тест), "Представление0", "сценарий 0"); + юТест.ПроверитьРавенство(Строка(ТЗ[2].Тест), "Представление1", "сценарий 1"); + юТест.ПроверитьРавенство(Строка(ТЗ[3].Тест), "Представление3", "сценарий 3"); КонецПроцедуры