Skip to content

Commit

Permalink
Add operator overrides for public IComparable types, #683 (#1056)
Browse files Browse the repository at this point in the history
* Add operator overrides for IComparable types, #683
  • Loading branch information
paulirwin authored Dec 15, 2024
1 parent 9c88340 commit 3d489a6
Show file tree
Hide file tree
Showing 16 changed files with 483 additions and 50 deletions.
1 change: 1 addition & 0 deletions Lucene.Net.sln.DotSettings
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/UserDictionary/Words/=Coord/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=csharpsquid/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=LUCENENET/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=testsettings/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
71 changes: 53 additions & 18 deletions src/Lucene.Net.Benchmark/Quality/QualityQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Globalization;
#nullable enable

namespace Lucene.Net.Benchmarks.Quality
{
Expand All @@ -28,13 +29,13 @@ namespace Lucene.Net.Benchmarks.Quality
/// <para/>
/// The ID allows to map the quality query with its judgements.
/// <para/>
/// The name-value pairs are used by a
/// The name-value pairs are used by a
/// <see cref="IQualityQueryParser"/>
/// to create a Lucene <see cref="Search.Query"/>.
/// <para/>
/// It is very likely that name-value-pairs would be mapped into fields in a Lucene query,
/// but it is up to the QualityQueryParser how to map - e.g. all values in a single field,
/// or each pair as its own field, etc., - and this of course must match the way the
/// or each pair as its own field, etc., - and this of course must match the way the
/// searched index was constructed.
/// </summary>
public class QualityQuery : IComparable<QualityQuery>
Expand All @@ -49,8 +50,8 @@ public class QualityQuery : IComparable<QualityQuery>
/// <param name="nameValPairs">The contents of this quality query.</param>
public QualityQuery(string queryID, IDictionary<string, string> nameValPairs)
{
this.queryID = queryID;
this.nameValPairs = nameValPairs;
this.queryID = queryID ?? throw new ArgumentNullException(nameof(queryID));
this.nameValPairs = nameValPairs ?? throw new ArgumentNullException(nameof(nameValPairs));
}

/// <summary>
Expand All @@ -66,10 +67,9 @@ public virtual string[] GetNames()
/// </summary>
/// <param name="name">The name whose value should be returned.</param>
/// <returns></returns>
public virtual string GetValue(string name)
public virtual string? GetValue(string name)
{
nameValPairs.TryGetValue(name, out string result);
return result;
return nameValPairs.TryGetValue(name, out string? result) ? result : null;
}

/// <summary>
Expand All @@ -82,22 +82,57 @@ public virtual string GetValue(string name)
/// For a nicer sort of input queries before running them.
/// Try first as ints, fall back to string if not int.
/// </summary>
/// <param name="other"></param>
/// <returns></returns>
public virtual int CompareTo(QualityQuery other)
/// <param name="other">The other <see cref="QualityQuery"/> to compare to.</param>
/// <returns>0 if equal, a negative value if smaller, a positive value if larger.</returns>
public virtual int CompareTo(QualityQuery? other)
{
try
if (other is null)
{
// compare as ints when ids ints
int n = int.Parse(queryID, CultureInfo.InvariantCulture);
int nOther = int.Parse(other.queryID, CultureInfo.InvariantCulture);
return n - nOther;
return 1;
}
catch (Exception e) when (e.IsNumberFormatException())

if (int.TryParse(queryID, NumberStyles.Integer, CultureInfo.InvariantCulture, out int n)
&& int.TryParse(other.queryID, NumberStyles.Integer, CultureInfo.InvariantCulture, out int nOther))
{
// fall back to string comparison
return queryID.CompareToOrdinal(other.queryID);
return n - nOther;
}

// fall back to string comparison
return queryID.CompareToOrdinal(other.queryID);
}

// LUCENENET specific - provide Equals and GetHashCode due to providing operator overrides
public override bool Equals(object? obj)
{
if (obj is null) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != GetType()) return false;
return queryID == ((QualityQuery)obj).queryID;
}

public override int GetHashCode() => queryID.GetHashCode();

#region Operator overrides
// LUCENENET specific - per csharpsquid:S1210, IComparable<T> should override comparison operators

public static bool operator <(QualityQuery? left, QualityQuery? right)
=> left is null ? right is not null : left.CompareTo(right) < 0;

public static bool operator <=(QualityQuery? left, QualityQuery? right)
=> left is null || left.CompareTo(right) <= 0;

public static bool operator >(QualityQuery? left, QualityQuery? right)
=> left is not null && left.CompareTo(right) > 0;

public static bool operator >=(QualityQuery? left, QualityQuery? right)
=> left is null ? right is null : left.CompareTo(right) >= 0;

public static bool operator ==(QualityQuery? left, QualityQuery? right)
=> left?.Equals(right) ?? right is null;

public static bool operator !=(QualityQuery? left, QualityQuery? right)
=> !(left == right);

#endregion
}
}
55 changes: 53 additions & 2 deletions src/Lucene.Net.Highlighter/VectorHighlight/FieldPhraseList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@ public override int GetHashCode()

public override bool Equals(object obj)
{
if (this == obj)
if (ReferenceEquals(this, obj))
{
return true;
}
Expand Down Expand Up @@ -470,6 +470,31 @@ public override bool Equals(object obj)
return true;
}

#region Operator overrides
#nullable enable
// LUCENENET specific - per csharpsquid:S1210, IComparable<T> should override comparison operators

public static bool operator <(WeightedPhraseInfo? left, WeightedPhraseInfo? right)
=> left is null ? right is not null : left.CompareTo(right) < 0;

public static bool operator <=(WeightedPhraseInfo? left, WeightedPhraseInfo? right)
=> left is null || left.CompareTo(right) <= 0;

public static bool operator >(WeightedPhraseInfo? left, WeightedPhraseInfo? right)
=> left is not null && left.CompareTo(right) > 0;

public static bool operator >=(WeightedPhraseInfo? left, WeightedPhraseInfo? right)
=> left is null ? right is null : left.CompareTo(right) >= 0;

public static bool operator ==(WeightedPhraseInfo? left, WeightedPhraseInfo? right)
=> left?.Equals(right) ?? right is null;

public static bool operator !=(WeightedPhraseInfo? left, WeightedPhraseInfo? right)
=> !(left == right);

#nullable restore
#endregion

/// <summary>
/// Term offsets (start + end)
/// </summary>
Expand Down Expand Up @@ -512,7 +537,7 @@ public override int GetHashCode()

public override bool Equals(object obj)
{
if (this == obj)
if (ReferenceEquals(this, obj))
{
return true;
}
Expand All @@ -535,12 +560,38 @@ public override bool Equals(object obj)
}
return true;
}

public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.Append('(').Append(startOffset).Append(',').Append(endOffset).Append(')');
return sb.ToString();
}

#region Operator overrides
#nullable enable
// LUCENENET specific - per csharpsquid:S1210, IComparable<T> should override comparison operators

public static bool operator <(Toffs? left, Toffs? right)
=> left is null ? right is not null : left.CompareTo(right) < 0;

public static bool operator <=(Toffs? left, Toffs? right)
=> left is null || left.CompareTo(right) <= 0;

public static bool operator >(Toffs? left, Toffs? right)
=> left is not null && left.CompareTo(right) > 0;

public static bool operator >=(Toffs? left, Toffs? right)
=> left is null ? right is null : left.CompareTo(right) >= 0;

public static bool operator ==(Toffs? left, Toffs? right)
=> left?.Equals(right) ?? right is null;

public static bool operator !=(Toffs? left, Toffs? right)
=> !(left == right);

#nullable restore
#endregion
}
}
}
Expand Down
27 changes: 26 additions & 1 deletion src/Lucene.Net.Highlighter/VectorHighlight/FieldTermStack.cs
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ public override int GetHashCode()

public override bool Equals(object obj)
{
if (this == obj)
if (ReferenceEquals(this, obj))
{
return true;
}
Expand All @@ -284,6 +284,31 @@ public override bool Equals(object obj)
}
return true;
}

#region Operator overrides
#nullable enable
// LUCENENET specific - per csharpsquid:S1210, IComparable<T> should override comparison operators

public static bool operator <(TermInfo? left, TermInfo? right)
=> left is null ? right is not null : left.CompareTo(right) < 0;

public static bool operator <=(TermInfo? left, TermInfo? right)
=> left is null || left.CompareTo(right) <= 0;

public static bool operator >(TermInfo? left, TermInfo? right)
=> left is not null && left.CompareTo(right) > 0;

public static bool operator >=(TermInfo? left, TermInfo? right)
=> left is null ? right is null : left.CompareTo(right) >= 0;

public static bool operator ==(TermInfo? left, TermInfo? right)
=> left?.Equals(right) ?? right is null;

public static bool operator !=(TermInfo? left, TermInfo? right)
=> !(left == right);

#nullable restore
#endregion
}
}
}
34 changes: 32 additions & 2 deletions src/Lucene.Net.QueryParser/Surround/Query/SimpleTerm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Lucene.Net.Index;
using System;
using System.Text;
#pragma warning disable CS0660, CS0661 // CompareTo is deprecated, so skipping implementing equality members (lucenenet#683)

namespace Lucene.Net.QueryParsers.Surround.Query
{
Expand All @@ -28,8 +29,8 @@ namespace Lucene.Net.QueryParsers.Surround.Query
public abstract class SimpleTerm : SrndQuery, IDistanceSubQuery, IComparable<SimpleTerm>
{
protected SimpleTerm(bool quoted) // LUCENENET: CA1012: Abstract types should not have constructors (marked protected)
{
this.quoted = quoted;
{
this.quoted = quoted;
}

private readonly bool quoted; // LUCENENET: marked readonly
Expand Down Expand Up @@ -115,5 +116,34 @@ public override Search.Query MakeLuceneQueryFieldNoBoost(string fieldName, Basic
{
return new SimpleTermRewriteQuery(this, fieldName, qf);
}

#region Operator overrides
#nullable enable
// LUCENENET specific - per csharpsquid:S1210, IComparable<T> should override comparison operators
// NOTE: The CompareTo method is marked as obsolete, but we still need to implement the comparison operators
// since this is public in 4.8. Suppressing the obsolete warning here.

#pragma warning disable CS0618 // Type or member is obsolete
public static bool operator <(SimpleTerm? left, SimpleTerm? right)
=> left is null ? right is not null : left.CompareTo(right) < 0;

public static bool operator <=(SimpleTerm? left, SimpleTerm? right)
=> left is null || left.CompareTo(right) <= 0;

public static bool operator >(SimpleTerm? left, SimpleTerm? right)
=> left is not null && left.CompareTo(right) > 0;

public static bool operator >=(SimpleTerm? left, SimpleTerm? right)
=> left is null ? right is null : left.CompareTo(right) >= 0;
#pragma warning restore CS0618 // Type or member is obsolete

public static bool operator ==(SimpleTerm? left, SimpleTerm? right)
=> left?.Equals(right) ?? right is null;

public static bool operator !=(SimpleTerm? left, SimpleTerm? right)
=> !(left == right);

#nullable restore
#endregion
}
}
36 changes: 29 additions & 7 deletions src/Lucene.Net.Spatial/Prefix/Tree/Cell.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ namespace Lucene.Net.Spatial.Prefix.Tree
/// <summary>
/// Represents a grid cell. These are not necessarily thread-safe, although new
/// Cell("") (world cell) must be.
///
///
/// @lucene.experimental
/// </summary>
public abstract class Cell : IComparable<Cell>
{
/// <summary>
/// LUCENENET specific - we need to set the SpatialPrefixTree before calling overridden
/// LUCENENET specific - we need to set the SpatialPrefixTree before calling overridden
/// members of this class, just in case those overridden members require it. This is
/// not possible from the subclass because the constructor of the base class runs first.
/// So we need to move the reference here and also set it before running the normal constructor
Expand Down Expand Up @@ -90,7 +90,7 @@ protected Cell(SpatialPrefixTree spatialPrefixTree, string token)
{
this.token = token.Substring(0, (token.Length - 1) - 0);
// LUCENENET specific - calling private instead of virtual to avoid initialization issues
SetLeafInternal();
SetLeafInternal();
}
if (Level == 0)
{
Expand Down Expand Up @@ -178,8 +178,8 @@ private void B_fixLeaf()
public virtual bool IsLeaf => m_leaf;

/// <summary>Note: not supported at level 0.
///
/// NOTE: When overriding this method, be aware that the constructor of this class calls
///
/// NOTE: When overriding this method, be aware that the constructor of this class calls
/// a private method and not this virtual method. So if you need to override
/// the behavior during the initialization, call your own private method from the constructor
/// with whatever custom behavior you need.
Expand Down Expand Up @@ -232,7 +232,7 @@ public virtual byte[] GetTokenBytes()
//public Cell getParent();
/// <summary>
/// Like <see cref="GetSubCells()">GetSubCells()</see> but with the results filtered by a shape. If
/// that shape is a <see cref="IPoint"/> then it must call
/// that shape is a <see cref="IPoint"/> then it must call
/// <see cref="GetSubCell(IPoint)"/>. The returned cells
/// should have <see cref="ShapeRel">ShapeRel</see> set to their relation with
/// <paramref name="shapeFilter"/>. In addition, <see cref="IsLeaf"/>
Expand Down Expand Up @@ -337,5 +337,27 @@ public override string ToString()

#endregion

#region Operator overrides
// LUCENENET specific - per csharpsquid:S1210, IComparable<T> should override comparison operators

public static bool operator <(Cell? left, Cell? right)
=> left is null ? right is not null : left.CompareTo(right) < 0;

public static bool operator <=(Cell? left, Cell? right)
=> left is null || left.CompareTo(right) <= 0;

public static bool operator >(Cell? left, Cell? right)
=> left is not null && left.CompareTo(right) > 0;

public static bool operator >=(Cell? left, Cell? right)
=> left is null ? right is null : left.CompareTo(right) >= 0;

public static bool operator ==(Cell? left, Cell? right)
=> left?.Equals(right) ?? right is null;

public static bool operator !=(Cell? left, Cell? right)
=> !(left == right);

#endregion
}
}
}
Loading

0 comments on commit 3d489a6

Please sign in to comment.