using System; using System.Collections.Immutable; using System.Linq; namespace Microsoft.VisualStudio.Text.PatternMatching { public struct PatternMatch : IComparable { /// /// True if this was a case sensitive match. /// public bool IsCaseSensitive { get; } /// /// The type of match that occurred. /// public PatternMatchKind Kind { get; } /// /// The spans in the original text that were matched. Only returned if the /// pattern matcher is asked to collect these spans. /// public ImmutableArray MatchedSpans { get; } /// /// True if punctuation was removed for this match. /// public bool IsPunctuationStripped { get; } /// /// Creates a PatternMatch object with an optional single span. /// /// How is this match categorized? /// Was punctuation removed? /// Was this a case sensitive match? public PatternMatch( PatternMatchKind resultType, bool punctuationStripped, bool isCaseSensitive) : this(resultType, punctuationStripped, isCaseSensitive, ImmutableArray.Empty) { } /// /// Creates a PatternMatch object with a set of spans /// /// How is this match categorized? /// Was punctuation removed? /// Was this a case sensitive match? /// What spans of the candidate were matched? An empty array signifies no span information is given. public PatternMatch( PatternMatchKind resultType, bool punctuationStripped, bool isCaseSensitive, ImmutableArray matchedSpans) : this() { this.Kind = resultType; this.IsCaseSensitive = isCaseSensitive; this.MatchedSpans = matchedSpans; this.IsPunctuationStripped = punctuationStripped; } /// /// Get a PatternMatch object with additional spans added to it. This is an optimization to avoid having to call the whole constructor. /// /// Spans to associate with this PatternMatch. /// A new instance of a PatternMatch with the specified spans. public PatternMatch WithMatchedSpans(ImmutableArray matchedSpans) => new PatternMatch(Kind, IsPunctuationStripped, IsCaseSensitive, matchedSpans); /// /// Compares two PatternMatch objects. /// public int CompareTo(PatternMatch other) => CompareTo(other, ignoreCase: false); /// /// Compares two PatternMatch objects with the specified behavior for ignoring capitalization. /// /// Should case be ignored? public int CompareTo(PatternMatch other, bool ignoreCase) { int diff; if ((diff = CompareType(this, other)) != 0 || (diff = CompareCase(this, other, ignoreCase)) != 0 || (diff = ComparePunctuation(this, other)) != 0) { return diff; } return 0; } private static int ComparePunctuation(PatternMatch result1, PatternMatch result2) { // Consider a match to be better if it was successful without stripping punctuation // versus a match that had to strip punctuation to succeed. if (result1.IsPunctuationStripped != result2.IsPunctuationStripped) { return result1.IsPunctuationStripped ? 1 : -1; } return 0; } private static int CompareCase(PatternMatch result1, PatternMatch result2, bool ignoreCase) { if (!ignoreCase) { if (result1.IsCaseSensitive != result2.IsCaseSensitive) { return result1.IsCaseSensitive ? -1 : 1; } } return 0; } private static int CompareType(PatternMatch result1, PatternMatch result2) => result1.Kind.CompareTo(result2.Kind); } }