From c8129e3ddd857bff6d55ff957efc9ee3ebf49fa9 Mon Sep 17 00:00:00 2001 From: Nikolaj Brask-Nielsen Date: Fri, 18 Nov 2022 15:12:51 +0100 Subject: [PATCH 1/6] feat: Nullable enabled --- src/Directory.Build.props | 6 +- src/Examine.Core/BaseIndexProvider.cs | 8 +- src/Examine.Core/BaseSearchProvider.cs | 4 +- src/Examine.Core/Examine.Core.csproj | 2 + src/Examine.Core/ExamineExtensions.cs | 2 +- src/Examine.Core/ExamineManager.cs | 13 +- src/Examine.Core/FieldDefinition.cs | 2 +- src/Examine.Core/IExamineManager.cs | 13 +- src/Examine.Core/ISearchResult.cs | 2 +- src/Examine.Core/ISearcher.cs | 4 +- src/Examine.Core/IndexOptions.cs | 2 +- src/Examine.Core/IndexingErrorEventArgs.cs | 6 +- src/Examine.Core/OrderedDictionary.cs | 14 +- src/Examine.Core/Search/FacetResult.cs | 2 +- src/Examine.Core/Search/IFacetResult.cs | 4 +- src/Examine.Core/Search/INestedQuery.cs | 2 +- src/Examine.Core/Search/IQuery.cs | 2 +- src/Examine.Core/Search/IQueryExecutor.cs | 2 +- src/Examine.Core/SearchResult.cs | 6 +- src/Examine.Core/ValueSet.cs | 19 +-- src/Examine.Host/Examine.csproj | 2 + .../ServicesCollectionExtensions.cs | 34 ++--- .../CultureInvariantWhitespaceAnalyzer.cs | 2 +- .../Analyzers/PatternAnalyzer.cs | 4 +- .../SyncedFileSystemDirectoryFactory.cs | 2 +- src/Examine.Lucene/Examine.Lucene.csproj | 2 + src/Examine.Lucene/ExamineReplicator.cs | 10 +- src/Examine.Lucene/FacetExtensions.cs | 4 +- .../FieldValueTypeCollection.cs | 4 +- src/Examine.Lucene/Indexing/DateTimeType.cs | 2 +- src/Examine.Lucene/Indexing/DoubleType.cs | 2 +- src/Examine.Lucene/Indexing/FullTextType.cs | 8 +- .../Indexing/GenericAnalyzerFieldValueType.cs | 2 +- .../Indexing/IIndexFieldValueType.cs | 8 +- .../Indexing/IndexFieldValueTypeBase.cs | 41 +++++- src/Examine.Lucene/Indexing/Int32Type.cs | 2 +- src/Examine.Lucene/Indexing/Int64Type.cs | 2 +- src/Examine.Lucene/Indexing/SingleType.cs | 2 +- .../LuceneDirectoryIndexOptions.cs | 2 +- src/Examine.Lucene/LuceneIndexOptions.cs | 6 +- .../Providers/BaseLuceneSearcher.cs | 6 +- src/Examine.Lucene/Providers/LuceneIndex.cs | 127 +++++++++--------- .../Providers/MultiIndexSearcher.cs | 4 +- src/Examine.Lucene/Search/ISearchContext.cs | 2 +- src/Examine.Lucene/Search/LateBoundQuery.cs | 10 +- .../Search/LuceneBooleanOperation.cs | 2 +- .../Search/LuceneBooleanOperationBase.cs | 2 +- src/Examine.Lucene/Search/LuceneQuery.cs | 6 +- .../Search/LuceneSearchExecutor.cs | 19 +-- .../Search/LuceneSearchOptions.cs | 6 +- .../Search/LuceneSearchQuery.cs | 16 +-- .../Search/LuceneSearchQueryBase.cs | 28 ++-- .../Search/MultiSearchContext.cs | 4 +- .../Search/MultiSearchSearcherReference.cs | 2 +- src/Examine.Lucene/Search/SearchContext.cs | 2 +- .../Search/SearcherReference.cs | 2 +- .../ValueTypeFactoryCollection.cs | 9 +- 57 files changed, 293 insertions(+), 210 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index e1cac4b17..ade8d2262 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -24,5 +24,9 @@ net6.0;netstandard2.1;netstandard2.0 - + + + + $(NoWarn);nullable + diff --git a/src/Examine.Core/BaseIndexProvider.cs b/src/Examine.Core/BaseIndexProvider.cs index 303e9bec3..6ddb8e48c 100644 --- a/src/Examine.Core/BaseIndexProvider.cs +++ b/src/Examine.Core/BaseIndexProvider.cs @@ -43,7 +43,7 @@ protected BaseIndexProvider(ILoggerFactory loggerFactory, string name, /// /// A validator to validate a value set before it's indexed /// - public IValueSetValidator ValueSetValidator => _indexOptions.Validator; + public IValueSetValidator? ValueSetValidator => _indexOptions.Validator; /// /// Ensures that the node being indexed is of a correct type @@ -110,13 +110,13 @@ public void DeleteFromIndex(IEnumerable itemIds) #region Events /// - public event EventHandler IndexOperationComplete; + public event EventHandler? IndexOperationComplete; /// - public event EventHandler IndexingError; + public event EventHandler? IndexingError; /// - public event EventHandler TransformingIndexValues; + public event EventHandler? TransformingIndexValues; #endregion diff --git a/src/Examine.Core/BaseSearchProvider.cs b/src/Examine.Core/BaseSearchProvider.cs index ede6492bc..260427f27 100644 --- a/src/Examine.Core/BaseSearchProvider.cs +++ b/src/Examine.Core/BaseSearchProvider.cs @@ -19,10 +19,10 @@ protected BaseSearchProvider(string name) public string Name { get; } /// - public abstract ISearchResults Search(string searchText, QueryOptions options = null); + public abstract ISearchResults Search(string searchText, QueryOptions? options = null); /// - public abstract IQuery CreateQuery(string category = null, BooleanOperation defaultOperation = BooleanOperation.And); + public abstract IQuery CreateQuery(string? category = null, BooleanOperation defaultOperation = BooleanOperation.And); } } diff --git a/src/Examine.Core/Examine.Core.csproj b/src/Examine.Core/Examine.Core.csproj index 3b1069354..5f13a9bd5 100644 --- a/src/Examine.Core/Examine.Core.csproj +++ b/src/Examine.Core/Examine.Core.csproj @@ -6,6 +6,8 @@ Examine is an abstraction for indexing and search operations with implementations such as Lucene.Net examine search index True + enable + 9 diff --git a/src/Examine.Core/ExamineExtensions.cs b/src/Examine.Core/ExamineExtensions.cs index 93935e82e..6e8b7ea0a 100644 --- a/src/Examine.Core/ExamineExtensions.cs +++ b/src/Examine.Core/ExamineExtensions.cs @@ -37,7 +37,7 @@ public static T GetNamedOptions(this IOptionsMonitor optionsMonitor, strin /// public static IIndex GetIndex(this IExamineManager examineManager, string indexName) { - if (examineManager.TryGetIndex(indexName, out IIndex index)) + if (examineManager.TryGetIndex(indexName, out IIndex? index)) { return index; } diff --git a/src/Examine.Core/ExamineManager.cs b/src/Examine.Core/ExamineManager.cs index a922fa5d5..8b8ac3510 100644 --- a/src/Examine.Core/ExamineManager.cs +++ b/src/Examine.Core/ExamineManager.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; namespace Examine @@ -28,11 +29,19 @@ public ExamineManager(IEnumerable indexes, IEnumerable search private readonly ConcurrentDictionary _searchers = new ConcurrentDictionary(StringComparer.InvariantCultureIgnoreCase); /// - public bool TryGetSearcher(string searcherName, out ISearcher searcher) => + public bool TryGetSearcher(string searcherName, +#if !NETSTANDARD2_0 + [MaybeNullWhen(false)] +#endif + out ISearcher searcher) => (searcher = _searchers.TryGetValue(searcherName, out var s) ? s : null) != null; /// - public bool TryGetIndex(string indexName, out IIndex index) => + public bool TryGetIndex(string indexName, +#if !NETSTANDARD2_0 + [MaybeNullWhen(false)] +#endif + out IIndex index) => (index = _indexers.TryGetValue(indexName, out var i) ? i : null) != null; /// diff --git a/src/Examine.Core/FieldDefinition.cs b/src/Examine.Core/FieldDefinition.cs index 2d92b383e..3cf9ec7a5 100644 --- a/src/Examine.Core/FieldDefinition.cs +++ b/src/Examine.Core/FieldDefinition.cs @@ -34,7 +34,7 @@ public FieldDefinition(string name, string type) public bool Equals(FieldDefinition other) => string.Equals(Name, other.Name) && string.Equals(Type, other.Type); /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) return false; return obj is FieldDefinition definition && Equals(definition); diff --git a/src/Examine.Core/IExamineManager.cs b/src/Examine.Core/IExamineManager.cs index 994321f75..c2583f246 100644 --- a/src/Examine.Core/IExamineManager.cs +++ b/src/Examine.Core/IExamineManager.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; namespace Examine @@ -35,7 +36,11 @@ public interface IExamineManager /// /// /// true if the index was found by name - bool TryGetIndex(string indexName, out IIndex index); + bool TryGetIndex(string indexName, +#if !NETSTANDARD2_0 + [MaybeNullWhen(false)] +#endif + out IIndex index); /// /// Returns a searcher that was registered with AddExamineSearcher or via config @@ -45,7 +50,11 @@ public interface IExamineManager /// /// true if the searcher was found by name /// - bool TryGetSearcher(string searcherName, out ISearcher searcher); + bool TryGetSearcher(string searcherName, +#if !NETSTANDARD2_0 + [MaybeNullWhen(false)] +#endif + out ISearcher searcher); } } diff --git a/src/Examine.Core/ISearchResult.cs b/src/Examine.Core/ISearchResult.cs index 047da52f7..ceebf973c 100644 --- a/src/Examine.Core/ISearchResult.cs +++ b/src/Examine.Core/ISearchResult.cs @@ -50,6 +50,6 @@ public interface ISearchResult /// /// /// - string this[string key] { get; } + string? this[string key] { get; } } } diff --git a/src/Examine.Core/ISearcher.cs b/src/Examine.Core/ISearcher.cs index 9b6c7c482..3ad4e9982 100644 --- a/src/Examine.Core/ISearcher.cs +++ b/src/Examine.Core/ISearcher.cs @@ -18,7 +18,7 @@ public interface ISearcher /// The search text or a native query /// /// Search Results - ISearchResults Search(string searchText, QueryOptions options = null); + ISearchResults Search(string searchText, QueryOptions? options = null); /// /// Creates a search criteria instance as required by the implementation @@ -28,6 +28,6 @@ public interface ISearcher /// /// An instance of /// - IQuery CreateQuery(string category = null, BooleanOperation defaultOperation = BooleanOperation.And); + IQuery CreateQuery(string? category = null, BooleanOperation defaultOperation = BooleanOperation.And); } } diff --git a/src/Examine.Core/IndexOptions.cs b/src/Examine.Core/IndexOptions.cs index 75cfafc79..bb436909a 100644 --- a/src/Examine.Core/IndexOptions.cs +++ b/src/Examine.Core/IndexOptions.cs @@ -16,6 +16,6 @@ public class IndexOptions /// /// The validator for the /// - public IValueSetValidator Validator { get; set; } + public IValueSetValidator? Validator { get; set; } } } diff --git a/src/Examine.Core/IndexingErrorEventArgs.cs b/src/Examine.Core/IndexingErrorEventArgs.cs index 90c23534c..ab6f3204f 100644 --- a/src/Examine.Core/IndexingErrorEventArgs.cs +++ b/src/Examine.Core/IndexingErrorEventArgs.cs @@ -11,7 +11,7 @@ namespace Examine public class IndexingErrorEventArgs : EventArgs { /// - public IndexingErrorEventArgs(IIndex index, string message, string itemId, Exception exception) + public IndexingErrorEventArgs(IIndex index, string message, string? itemId, Exception? exception) { Index = index; ItemId = itemId; @@ -22,7 +22,7 @@ public IndexingErrorEventArgs(IIndex index, string message, string itemId, Excep /// /// The exception of the error /// - public Exception Exception { get; } + public Exception? Exception { get; } /// /// The message of the error @@ -37,6 +37,6 @@ public IndexingErrorEventArgs(IIndex index, string message, string itemId, Excep /// /// The item id /// - public string ItemId { get; } + public string? ItemId { get; } } } diff --git a/src/Examine.Core/OrderedDictionary.cs b/src/Examine.Core/OrderedDictionary.cs index 3b2b96010..59e0378ae 100644 --- a/src/Examine.Core/OrderedDictionary.cs +++ b/src/Examine.Core/OrderedDictionary.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Diagnostics.CodeAnalysis; using System.Linq; namespace Examine @@ -10,7 +11,7 @@ namespace Examine /// /// /// - public class OrderedDictionary : KeyedCollection>, IDictionary, IReadOnlyDictionary + public class OrderedDictionary : KeyedCollection>, IDictionary, IReadOnlyDictionary where TKey : notnull { /// public OrderedDictionary() @@ -64,7 +65,14 @@ public void Add(TKey key, TVal value) } /// - public bool TryGetValue(TKey key, out TVal value) +#pragma warning disable CS8767 // Nullability of reference types in type of parameter doesn't match implicitly implemented member (possibly because of nullability attributes). + // Justification for warning disabled: IDictionary is missing [MaybeNullWhen(false)] in Netstandard 2.1 + public bool TryGetValue(TKey key, +#pragma warning restore CS8767 // Nullability of reference types in type of parameter doesn't match implicitly implemented member (possibly because of nullability attributes). +#if !NETSTANDARD2_0 + [MaybeNullWhen(false)] +#endif + out TVal value) { if (base.Dictionary == null) { @@ -97,7 +105,7 @@ TVal IDictionary.this[TKey key] { return found.Value; } - return default(TVal); + return default(TVal); // TODO: should this throw instead } set { diff --git a/src/Examine.Core/Search/FacetResult.cs b/src/Examine.Core/Search/FacetResult.cs index 41f18804c..87bdec7ad 100644 --- a/src/Examine.Core/Search/FacetResult.cs +++ b/src/Examine.Core/Search/FacetResult.cs @@ -31,7 +31,7 @@ private void SetValuesDictionary() } /// - public IFacetValue Facet(string label) + public IFacetValue? Facet(string label) { SetValuesDictionary(); return _dictValues[label]; diff --git a/src/Examine.Core/Search/IFacetResult.cs b/src/Examine.Core/Search/IFacetResult.cs index a5af2362d..9ccd174a3 100644 --- a/src/Examine.Core/Search/IFacetResult.cs +++ b/src/Examine.Core/Search/IFacetResult.cs @@ -12,7 +12,7 @@ public interface IFacetResult : IEnumerable /// /// /// - IFacetValue Facet(string label); + IFacetValue? Facet(string label); /// /// Trys to get a facet value for a label @@ -20,6 +20,6 @@ public interface IFacetResult : IEnumerable /// /// /// - bool TryGetFacet(string label, out IFacetValue facetValue); + bool TryGetFacet(string label, out IFacetValue? facetValue); } } diff --git a/src/Examine.Core/Search/INestedQuery.cs b/src/Examine.Core/Search/INestedQuery.cs index 12c3fa141..3edef5dc6 100644 --- a/src/Examine.Core/Search/INestedQuery.cs +++ b/src/Examine.Core/Search/INestedQuery.cs @@ -86,7 +86,7 @@ public interface INestedQuery /// /// /// - INestedBooleanOperation ManagedQuery(string query, string[] fields = null); + INestedBooleanOperation ManagedQuery(string query, string[]? fields = null); /// /// Matches items as defined by the IIndexFieldValueType used for the fields specified. diff --git a/src/Examine.Core/Search/IQuery.cs b/src/Examine.Core/Search/IQuery.cs index 7fdfb630c..3a172e035 100644 --- a/src/Examine.Core/Search/IQuery.cs +++ b/src/Examine.Core/Search/IQuery.cs @@ -120,7 +120,7 @@ public interface IQuery /// /// /// - IBooleanOperation ManagedQuery(string query, string[] fields = null); + IBooleanOperation ManagedQuery(string query, string[]? fields = null); /// /// Matches items as defined by the IIndexFieldValueType used for the fields specified. diff --git a/src/Examine.Core/Search/IQueryExecutor.cs b/src/Examine.Core/Search/IQueryExecutor.cs index 7176d16a4..869e827bd 100644 --- a/src/Examine.Core/Search/IQueryExecutor.cs +++ b/src/Examine.Core/Search/IQueryExecutor.cs @@ -9,6 +9,6 @@ public interface IQueryExecutor /// /// Executes the query /// - ISearchResults Execute(QueryOptions options = null); + ISearchResults Execute(QueryOptions? options = null); } } diff --git a/src/Examine.Core/SearchResult.cs b/src/Examine.Core/SearchResult.cs index 1706f2c99..290565f9c 100644 --- a/src/Examine.Core/SearchResult.cs +++ b/src/Examine.Core/SearchResult.cs @@ -8,7 +8,7 @@ namespace Examine /// public class SearchResult : ISearchResult { - private OrderedDictionary _fields; + private OrderedDictionary? _fields; private readonly Lazy>> _fieldValues; /// @@ -98,14 +98,14 @@ public IEnumerable GetValues(string key) /// /// /// - public string this[string key] => Values.TryGetValue(key, out var single) ? single : null; + public string? this[string key] => Values.TryGetValue(key, out var single) ? single : null; /// /// Override this method so that the Distinct() operator works /// /// /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (obj == null || GetType() != obj.GetType()) return false; diff --git a/src/Examine.Core/ValueSet.cs b/src/Examine.Core/ValueSet.cs index e5fb2bbc4..1b642c36c 100644 --- a/src/Examine.Core/ValueSet.cs +++ b/src/Examine.Core/ValueSet.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Linq; @@ -19,17 +20,17 @@ public class ValueSet /// /// Used to categorize the item in the index (in umbraco terms this would be content vs media) /// - public string Category { get; } + public string? Category { get; } /// /// The item's node type (in umbraco terms this would be the doc type alias) /// - public string ItemType { get; } + public string? ItemType { get; } /// /// The values to be indexed /// - public IReadOnlyDictionary> Values { get; } + public IReadOnlyDictionary>? Values { get; } /// /// Constructor that only specifies an ID @@ -109,17 +110,17 @@ public ValueSet(string id, string category, IDictionary /// - public ValueSet(string id, string category, string itemType, IDictionary> values) + public ValueSet(string id, string? category, string? itemType, IDictionary> values) : this(id, category, itemType, values.ToDictionary(x => x.Key, x => (IReadOnlyList)x.Value.ToList())) { } - private ValueSet(string id, string category, string itemType, IReadOnlyDictionary> values) + private ValueSet(string id, string? category, string? itemType, IReadOnlyDictionary>? values) { Id = id; Category = category; ItemType = itemType; - Values = values.ToDictionary(x => x.Key, x => (IReadOnlyList)x.Value.ToList()); + Values = values?.ToDictionary(x => x.Key, x => (IReadOnlyList)x.Value.ToList()) ?? default; } /// @@ -129,7 +130,7 @@ private ValueSet(string id, string category, string itemType, IReadOnlyDictionar /// public IEnumerable GetValues(string key) { - return !Values.TryGetValue(key, out var values) ? Enumerable.Empty() : values; + return Values != null && Values.TryGetValue(key, out var values) ? values : Enumerable.Empty(); } /// @@ -139,9 +140,9 @@ public IEnumerable GetValues(string key) /// /// If there are multiple values, this will return the first /// - public object GetValue(string key) + public object? GetValue(string key) { - return !Values.TryGetValue(key, out var values) ? null : values.Count > 0 ? values[0] : null; + return Values != null && Values.TryGetValue(key, out var values) ? values.Count > 0 ? values[0] : null : null; } /// diff --git a/src/Examine.Host/Examine.csproj b/src/Examine.Host/Examine.csproj index c69365403..931e5eea8 100644 --- a/src/Examine.Host/Examine.csproj +++ b/src/Examine.Host/Examine.csproj @@ -4,6 +4,8 @@ A Lucene.Net search and indexing implementation for Examine examine lucene lucene.net lucenenet search index True + enable + 9 diff --git a/src/Examine.Host/ServicesCollectionExtensions.cs b/src/Examine.Host/ServicesCollectionExtensions.cs index ced98bea6..6e1cb6e27 100644 --- a/src/Examine.Host/ServicesCollectionExtensions.cs +++ b/src/Examine.Host/ServicesCollectionExtensions.cs @@ -25,11 +25,11 @@ public static class ServicesCollectionExtensions public static IServiceCollection AddExamineLuceneIndex( this IServiceCollection serviceCollection, string name, - FieldDefinitionCollection fieldDefinitions = null, - Analyzer analyzer = null, - IValueSetValidator validator = null, - IReadOnlyDictionary indexValueTypesFactory = null, - FacetsConfig facetsConfig = null) + FieldDefinitionCollection? fieldDefinitions = null, + Analyzer? analyzer = null, + IValueSetValidator? validator = null, + IReadOnlyDictionary? indexValueTypesFactory = null, + FacetsConfig? facetsConfig = null) => serviceCollection.AddExamineLuceneIndex(name, fieldDefinitions, analyzer, validator, indexValueTypesFactory, facetsConfig); /// @@ -38,11 +38,11 @@ public static IServiceCollection AddExamineLuceneIndex( public static IServiceCollection AddExamineLuceneIndex( this IServiceCollection serviceCollection, string name, - FieldDefinitionCollection fieldDefinitions = null, - Analyzer analyzer = null, - IValueSetValidator validator = null, - IReadOnlyDictionary indexValueTypesFactory = null, - FacetsConfig facetsConfig = null) + FieldDefinitionCollection? fieldDefinitions = null, + Analyzer? analyzer = null, + IValueSetValidator? validator = null, + IReadOnlyDictionary? indexValueTypesFactory = null, + FacetsConfig? facetsConfig = null) where TIndex : LuceneIndex => serviceCollection.AddExamineLuceneIndex(name, fieldDefinitions, analyzer, validator, indexValueTypesFactory, facetsConfig); @@ -52,11 +52,11 @@ public static IServiceCollection AddExamineLuceneIndex( public static IServiceCollection AddExamineLuceneIndex( this IServiceCollection serviceCollection, string name, - FieldDefinitionCollection fieldDefinitions = null, - Analyzer analyzer = null, - IValueSetValidator validator = null, - IReadOnlyDictionary indexValueTypesFactory = null, - FacetsConfig facetsConfig = null) + FieldDefinitionCollection? fieldDefinitions = null, + Analyzer? analyzer = null, + IValueSetValidator? validator = null, + IReadOnlyDictionary? indexValueTypesFactory = null, + FacetsConfig? facetsConfig = null) where TIndex : LuceneIndex where TDirectoryFactory : class, IDirectoryFactory { @@ -122,7 +122,7 @@ public static IServiceCollection AddExamineLuceneMultiSearcher( this IServiceCollection serviceCollection, string name, string[] indexNames, - Analyzer analyzer = null) + Analyzer? analyzer = null) => serviceCollection.AddExamineSearcher(name, s => { IEnumerable matchedIndexes = s.GetServices() @@ -147,7 +147,7 @@ public static IServiceCollection AddExamineLuceneMultiSearcher( /// /// /// - public static IServiceCollection AddExamine(this IServiceCollection services, DirectoryInfo appRootDirectory = null) + public static IServiceCollection AddExamine(this IServiceCollection services, DirectoryInfo? appRootDirectory = null) { services.TryAddSingleton(); services.TryAddSingleton(); diff --git a/src/Examine.Lucene/Analyzers/CultureInvariantWhitespaceAnalyzer.cs b/src/Examine.Lucene/Analyzers/CultureInvariantWhitespaceAnalyzer.cs index 3deb6df98..60e1b9e23 100644 --- a/src/Examine.Lucene/Analyzers/CultureInvariantWhitespaceAnalyzer.cs +++ b/src/Examine.Lucene/Analyzers/CultureInvariantWhitespaceAnalyzer.cs @@ -36,7 +36,7 @@ protected override TokenStreamComponents CreateComponents(string fieldName, Text { Tokenizer tokenizer = new LetterOrDigitTokenizer(reader); - TokenStream result = null; + TokenStream? result = null; if (_caseInsensitive) { diff --git a/src/Examine.Lucene/Analyzers/PatternAnalyzer.cs b/src/Examine.Lucene/Analyzers/PatternAnalyzer.cs index c5d31ab64..ed3e7d8f8 100644 --- a/src/Examine.Lucene/Analyzers/PatternAnalyzer.cs +++ b/src/Examine.Lucene/Analyzers/PatternAnalyzer.cs @@ -14,7 +14,7 @@ public class PatternAnalyzer : Analyzer { private readonly int _regexGroup; private readonly bool _lowercase; - private readonly CharArraySet _stopWords; + private readonly CharArraySet? _stopWords; private readonly Regex _pattern; /// @@ -24,7 +24,7 @@ public class PatternAnalyzer : Analyzer /// The regex group number to match. -1 to use as a split. /// Whether to lower case the tokens /// Any stop words that should be included - public PatternAnalyzer(string format, int regexGroup, bool lowercase = false, CharArraySet stopWords = null) + public PatternAnalyzer(string format, int regexGroup, bool lowercase = false, CharArraySet? stopWords = null) { _regexGroup = regexGroup; _lowercase = lowercase; diff --git a/src/Examine.Lucene/Directories/SyncedFileSystemDirectoryFactory.cs b/src/Examine.Lucene/Directories/SyncedFileSystemDirectoryFactory.cs index 4db702c9d..2f77f8f97 100644 --- a/src/Examine.Lucene/Directories/SyncedFileSystemDirectoryFactory.cs +++ b/src/Examine.Lucene/Directories/SyncedFileSystemDirectoryFactory.cs @@ -24,7 +24,7 @@ public class SyncedFileSystemDirectoryFactory : FileSystemDirectoryFactory { private readonly DirectoryInfo _localDir; private readonly ILoggerFactory _loggerFactory; - private ExamineReplicator _replicator; + private ExamineReplicator? _replicator; /// public SyncedFileSystemDirectoryFactory( diff --git a/src/Examine.Lucene/Examine.Lucene.csproj b/src/Examine.Lucene/Examine.Lucene.csproj index eee9bdfb2..3c48aff72 100644 --- a/src/Examine.Lucene/Examine.Lucene.csproj +++ b/src/Examine.Lucene/Examine.Lucene.csproj @@ -5,6 +5,8 @@ A Lucene.Net search and indexing implementation for Examine examine lucene lucene.net lucenenet search index True + enable + 9 diff --git a/src/Examine.Lucene/ExamineReplicator.cs b/src/Examine.Lucene/ExamineReplicator.cs index 7172aca83..144f6683f 100644 --- a/src/Examine.Lucene/ExamineReplicator.cs +++ b/src/Examine.Lucene/ExamineReplicator.cs @@ -125,12 +125,16 @@ public void StartIndexReplicationOnSchedule(int milliseconds) /// /// /// - private void SourceIndex_IndexCommitted(object sender, EventArgs e) + private void SourceIndex_IndexCommitted(object? sender, EventArgs e) { - var index = (LuceneIndex)sender; + var index = (LuceneIndex?)sender; if (_logger.IsEnabled(LogLevel.Debug)) { - _logger.LogDebug("{IndexName} committed", index.Name); + if(index == null) + { + _logger.LogWarning("Index is null in {method}", nameof(ExamineReplicator.SourceIndex_IndexCommitted)); + } + _logger.LogDebug("{IndexName} committed", index?.Name ?? $"({nameof(index)} is null)"); } var rev = new IndexRevision(_sourceIndex.IndexWriter.IndexWriter); _replicator.Publish(rev); diff --git a/src/Examine.Lucene/FacetExtensions.cs b/src/Examine.Lucene/FacetExtensions.cs index 646388076..381353e22 100644 --- a/src/Examine.Lucene/FacetExtensions.cs +++ b/src/Examine.Lucene/FacetExtensions.cs @@ -13,14 +13,14 @@ public static class FacetExtensions /// /// Get the values for a particular facet in the results /// - public static Examine.Search.IFacetResult GetFacet(this ISearchResults searchResults, string field) + public static Examine.Search.IFacetResult? GetFacet(this ISearchResults searchResults, string field) { if (!(searchResults is Examine.Search.IFacetResults facetResults)) { throw new NotSupportedException("Result does not support facets"); } - facetResults.Facets.TryGetValue(field, out Examine.Search.IFacetResult facet); + facetResults.Facets.TryGetValue(field, out Examine.Search.IFacetResult? facet); return facet; } diff --git a/src/Examine.Lucene/FieldValueTypeCollection.cs b/src/Examine.Lucene/FieldValueTypeCollection.cs index 4923b99ac..aa5267dea 100644 --- a/src/Examine.Lucene/FieldValueTypeCollection.cs +++ b/src/Examine.Lucene/FieldValueTypeCollection.cs @@ -27,7 +27,7 @@ public FieldValueTypeCollection( { ValueTypeFactories = new ValueTypeFactoryCollection(valueTypeFactories); - var fieldAnalyzers = new Dictionary(); + var fieldAnalyzers = new Dictionary(); //initializes the collection of field aliases to it's correct IIndexFieldValueType _resolvedValueTypes = new Lazy>(() => @@ -97,7 +97,7 @@ public IIndexFieldValueType GetValueType(string fieldName, IFieldValueTypeFactor /// public IIndexFieldValueType GetValueType(string fieldName) { - if (!_resolvedValueTypes.Value.TryGetValue(fieldName, out IIndexFieldValueType valueType)) + if (!_resolvedValueTypes.Value.TryGetValue(fieldName, out IIndexFieldValueType? valueType)) { throw new InvalidOperationException($"No {nameof(IIndexFieldValueType)} was found for field name {fieldName}"); } diff --git a/src/Examine.Lucene/Indexing/DateTimeType.cs b/src/Examine.Lucene/Indexing/DateTimeType.cs index 9c32b1e53..a04bada7c 100644 --- a/src/Examine.Lucene/Indexing/DateTimeType.cs +++ b/src/Examine.Lucene/Indexing/DateTimeType.cs @@ -72,7 +72,7 @@ protected long DateToLong(DateTime date) } /// - public override Query GetQuery(string query) + public override Query? GetQuery(string query) { if (!TryConvert(query, out DateTime parsedVal)) return null; diff --git a/src/Examine.Lucene/Indexing/DoubleType.cs b/src/Examine.Lucene/Indexing/DoubleType.cs index b37ede540..d8c55376f 100644 --- a/src/Examine.Lucene/Indexing/DoubleType.cs +++ b/src/Examine.Lucene/Indexing/DoubleType.cs @@ -52,7 +52,7 @@ protected override void AddSingleValue(Document doc, object value) } /// - public override Query GetQuery(string query) + public override Query? GetQuery(string query) { return !TryConvert(query, out double parsedVal) ? null : GetQuery(parsedVal, parsedVal); } diff --git a/src/Examine.Lucene/Indexing/FullTextType.cs b/src/Examine.Lucene/Indexing/FullTextType.cs index da73e9c4d..9ba51e264 100644 --- a/src/Examine.Lucene/Indexing/FullTextType.cs +++ b/src/Examine.Lucene/Indexing/FullTextType.cs @@ -57,7 +57,7 @@ public FullTextType(string fieldName, ILoggerFactory logger, bool sortable = fal /// Defaults to /// /// - public FullTextType(string fieldName, ILoggerFactory logger, Analyzer analyzer = null, bool sortable = false) + public FullTextType(string fieldName, ILoggerFactory logger, Analyzer? analyzer = null, bool sortable = false) : base(fieldName, logger, true) { _sortable = sortable; @@ -68,7 +68,7 @@ public FullTextType(string fieldName, ILoggerFactory logger, Analyzer analyzer = /// /// Can be sorted by a concatenated field name since to be sortable it cannot be analyzed /// - public override string SortableFieldName => _sortable ? ExamineFieldNames.SortedFieldNamePrefix + FieldName : null; + public override string? SortableFieldName => _sortable ? ExamineFieldNames.SortedFieldNamePrefix + FieldName : null; /// public override Analyzer Analyzer => _analyzer; @@ -103,7 +103,7 @@ protected override void AddSingleValue(Document doc, object value) /// /// /// - public static Query GenerateQuery(string fieldName, string query, Analyzer analyzer) + public static Query? GenerateQuery(string fieldName, string query, Analyzer analyzer) { if (query == null) { @@ -175,7 +175,7 @@ public static Query GenerateQuery(string fieldName, string query, Analyzer analy /// /// /// - public override Query GetQuery(string query) + public override Query? GetQuery(string query) { return GenerateQuery(FieldName, query, _analyzer); } diff --git a/src/Examine.Lucene/Indexing/GenericAnalyzerFieldValueType.cs b/src/Examine.Lucene/Indexing/GenericAnalyzerFieldValueType.cs index 4957737b4..b6760e8f5 100644 --- a/src/Examine.Lucene/Indexing/GenericAnalyzerFieldValueType.cs +++ b/src/Examine.Lucene/Indexing/GenericAnalyzerFieldValueType.cs @@ -26,7 +26,7 @@ public GenericAnalyzerFieldValueType(string fieldName, ILoggerFactory logger, An /// /// Can be sorted by a concatenated field name since to be sortable it cannot be analyzed /// - public override string SortableFieldName => _sortable ? ExamineFieldNames.SortedFieldNamePrefix + FieldName : null; + public override string? SortableFieldName => _sortable ? ExamineFieldNames.SortedFieldNamePrefix + FieldName : null; /// public override Analyzer Analyzer => _analyzer; diff --git a/src/Examine.Lucene/Indexing/IIndexFieldValueType.cs b/src/Examine.Lucene/Indexing/IIndexFieldValueType.cs index 243c08e79..de09fa5a8 100644 --- a/src/Examine.Lucene/Indexing/IIndexFieldValueType.cs +++ b/src/Examine.Lucene/Indexing/IIndexFieldValueType.cs @@ -19,7 +19,7 @@ public interface IIndexFieldValueType /// Returns the sortable field name or null if the value isn't sortable /// /// By default it will not be sortable - string SortableFieldName { get; } + string? SortableFieldName { get; } /// /// Should the value be stored @@ -29,21 +29,21 @@ public interface IIndexFieldValueType /// /// Returns the analyzer for this field type, or null to use the default /// - Analyzer Analyzer { get; } + Analyzer? Analyzer { get; } /// /// Adds a value to the document /// /// /// - void AddValue(Document doc, object value); + void AddValue(Document doc, object? value); /// /// Gets a query as /// /// /// - Query GetQuery(string query); + Query? GetQuery(string query); //IHighlighter GetHighlighter(Query query, Searcher searcher, FacetsLoader facetsLoader); diff --git a/src/Examine.Lucene/Indexing/IndexFieldValueTypeBase.cs b/src/Examine.Lucene/Indexing/IndexFieldValueTypeBase.cs index 4f4e843d5..14e3c803b 100644 --- a/src/Examine.Lucene/Indexing/IndexFieldValueTypeBase.cs +++ b/src/Examine.Lucene/Indexing/IndexFieldValueTypeBase.cs @@ -1,5 +1,6 @@ using System; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using Lucene.Net.Analysis; using Lucene.Net.Documents; using Lucene.Net.Index; @@ -15,7 +16,7 @@ public abstract class IndexFieldValueTypeBase : IIndexFieldValueType public string FieldName { get; } /// - public virtual string SortableFieldName => null; + public virtual string? SortableFieldName => null; /// public bool Store { get; } @@ -29,7 +30,7 @@ protected IndexFieldValueTypeBase(string fieldName, ILoggerFactory loggerFactory } /// - public virtual Analyzer Analyzer => null; + public virtual Analyzer? Analyzer => null; /// /// The logger @@ -37,9 +38,9 @@ protected IndexFieldValueTypeBase(string fieldName, ILoggerFactory loggerFactory public ILogger Logger { get; } /// - public virtual void AddValue(Document doc, object value) => AddSingleValueInternal(doc, value); + public virtual void AddValue(Document doc, object? value) => AddSingleValueInternal(doc, value); - private void AddSingleValueInternal(Document doc, object value) + private void AddSingleValueInternal(Document doc, object? value) { if (value != null) { @@ -60,7 +61,7 @@ private void AddSingleValueInternal(Document doc, object value) /// /// /// - public virtual Query GetQuery(string query) => new TermQuery(new Term(FieldName, query)); + public virtual Query? GetQuery(string query) => new TermQuery(new Term(FieldName, query)); //TODO: We shoud convert this to the TryConvertTo in the umb codebase! @@ -72,7 +73,11 @@ private void AddSingleValueInternal(Document doc, object value) /// /// /// - protected bool TryConvert(object val, out T parsedVal) + protected bool TryConvert(object val, +#if !NETSTANDARD2_0 + [MaybeNullWhen(false)] +#endif + out T parsedVal) { // TODO: This throws all the time and then logs! @@ -90,7 +95,19 @@ protected bool TryConvert(object val, out T parsedVal) if (typeof(T) == typeof(string)) { - parsedVal = (T)(object)val.ToString(); + var valString = val.ToString(); + if(valString == null) + { + parsedVal = default; + return false; + } + var valType = (T?)(object)valString; + if(valType == null) + { + parsedVal = default; + return false; + } + parsedVal = valType; return true; } @@ -100,6 +117,11 @@ protected bool TryConvert(object val, out T parsedVal) try { var converted = inputConverter.ConvertTo(val, typeof(T)); + if(converted == null) + { + parsedVal = default; + return false; + } parsedVal = (T) converted; return true; } @@ -120,6 +142,11 @@ protected bool TryConvert(object val, out T parsedVal) try { var converted = outputConverter.ConvertFrom(val); + if (converted == null) + { + parsedVal = default; + return false; + } parsedVal = (T)converted; return true; } diff --git a/src/Examine.Lucene/Indexing/Int32Type.cs b/src/Examine.Lucene/Indexing/Int32Type.cs index dc55820e5..d3343949a 100644 --- a/src/Examine.Lucene/Indexing/Int32Type.cs +++ b/src/Examine.Lucene/Indexing/Int32Type.cs @@ -52,7 +52,7 @@ protected override void AddSingleValue(Document doc, object value) } /// - public override Query GetQuery(string query) + public override Query? GetQuery(string query) { return !TryConvert(query, out int parsedVal) ? null : GetQuery(parsedVal, parsedVal); } diff --git a/src/Examine.Lucene/Indexing/Int64Type.cs b/src/Examine.Lucene/Indexing/Int64Type.cs index b2a1f9668..c4b709360 100644 --- a/src/Examine.Lucene/Indexing/Int64Type.cs +++ b/src/Examine.Lucene/Indexing/Int64Type.cs @@ -52,7 +52,7 @@ protected override void AddSingleValue(Document doc, object value) } /// - public override Query GetQuery(string query) + public override Query? GetQuery(string query) { return !TryConvert(query, out long parsedVal) ? null : GetQuery(parsedVal, parsedVal); } diff --git a/src/Examine.Lucene/Indexing/SingleType.cs b/src/Examine.Lucene/Indexing/SingleType.cs index 48651939a..f2d3c21b8 100644 --- a/src/Examine.Lucene/Indexing/SingleType.cs +++ b/src/Examine.Lucene/Indexing/SingleType.cs @@ -52,7 +52,7 @@ protected override void AddSingleValue(Document doc, object value) } /// - public override Query GetQuery(string query) + public override Query? GetQuery(string query) { return !TryConvert(query, out float parsedVal) ? null : GetQuery(parsedVal, parsedVal); } diff --git a/src/Examine.Lucene/LuceneDirectoryIndexOptions.cs b/src/Examine.Lucene/LuceneDirectoryIndexOptions.cs index eebf08dea..dec3212c3 100644 --- a/src/Examine.Lucene/LuceneDirectoryIndexOptions.cs +++ b/src/Examine.Lucene/LuceneDirectoryIndexOptions.cs @@ -12,7 +12,7 @@ public class LuceneDirectoryIndexOptions : LuceneIndexOptions /// /// Returns the directory factory to use /// - public IDirectoryFactory DirectoryFactory { get; set; } + public IDirectoryFactory? DirectoryFactory { get; set; } /// /// If true will force unlock the index on startup diff --git a/src/Examine.Lucene/LuceneIndexOptions.cs b/src/Examine.Lucene/LuceneIndexOptions.cs index 3dca41e83..7b41c1afe 100644 --- a/src/Examine.Lucene/LuceneIndexOptions.cs +++ b/src/Examine.Lucene/LuceneIndexOptions.cs @@ -16,12 +16,12 @@ public class LuceneIndexOptions : IndexOptions /// /// THe index deletion policy /// - public IndexDeletionPolicy IndexDeletionPolicy { get; set; } + public IndexDeletionPolicy? IndexDeletionPolicy { get; set; } /// /// The analyzer used in the index /// - public Analyzer Analyzer { get; set; } + public Analyzer? Analyzer { get; set; } /// /// Records per-dimension configuration. By default a @@ -36,6 +36,6 @@ public class LuceneIndexOptions : IndexOptions /// Specifies the index value types to use for this indexer, if this is not specified then the result of will be used. /// This is generally used to initialize any custom value types for your indexer since the value type collection cannot be modified at runtime. /// - public IReadOnlyDictionary IndexValueTypesFactory { get; set; } + public IReadOnlyDictionary? IndexValueTypesFactory { get; set; } } } diff --git a/src/Examine.Lucene/Providers/BaseLuceneSearcher.cs b/src/Examine.Lucene/Providers/BaseLuceneSearcher.cs index e540b97f7..5b2a4c252 100644 --- a/src/Examine.Lucene/Providers/BaseLuceneSearcher.cs +++ b/src/Examine.Lucene/Providers/BaseLuceneSearcher.cs @@ -41,7 +41,7 @@ protected BaseLuceneSearcher(string name, Analyzer analyzer, FacetsConfig facets public abstract ISearchContext GetSearchContext(); /// - public override IQuery CreateQuery(string category = null, BooleanOperation defaultOperation = BooleanOperation.And) + public override IQuery CreateQuery(string? category = null, BooleanOperation defaultOperation = BooleanOperation.And) => CreateQuery(category, defaultOperation, LuceneAnalyzer, new LuceneSearchOptions()); /// @@ -52,7 +52,7 @@ public override IQuery CreateQuery(string category = null, BooleanOperation defa /// /// /// - public IQuery CreateQuery(string category, BooleanOperation defaultOperation, Analyzer luceneAnalyzer, LuceneSearchOptions searchOptions) + public IQuery CreateQuery(string? category, BooleanOperation defaultOperation, Analyzer luceneAnalyzer, LuceneSearchOptions searchOptions) { if (luceneAnalyzer == null) throw new ArgumentNullException(nameof(luceneAnalyzer)); @@ -61,7 +61,7 @@ public IQuery CreateQuery(string category, BooleanOperation defaultOperation, An } /// - public override ISearchResults Search(string searchText, QueryOptions options = null) + public override ISearchResults Search(string searchText, QueryOptions? options = null) { var sc = CreateQuery().ManagedQuery(searchText); return sc.Execute(options); diff --git a/src/Examine.Lucene/Providers/LuceneIndex.cs b/src/Examine.Lucene/Providers/LuceneIndex.cs index afe0f847d..1bddb52c8 100644 --- a/src/Examine.Lucene/Providers/LuceneIndex.cs +++ b/src/Examine.Lucene/Providers/LuceneIndex.cs @@ -89,15 +89,17 @@ internal LuceneIndex( #endregion private readonly LuceneIndexOptions _options; - private PerFieldAnalyzerWrapper _fieldAnalyzer; - private ControlledRealTimeReopenThread _nrtReopenThread; + private PerFieldAnalyzerWrapper? _fieldAnalyzer; + private ControlledRealTimeReopenThread? _nrtReopenThread; private readonly ILogger _logger; - private readonly Lazy _directory; - private FileStream _logOutput; + private readonly Lazy? _directory; +#if FULLDEBUG + private FileStream? _logOutput; +#endif private bool _disposedValue; private readonly IndexCommiter _committer; - private volatile TrackingIndexWriter _writer; + private volatile TrackingIndexWriter? _writer; private int _activeWrites = 0; @@ -140,7 +142,7 @@ internal LuceneIndex( // tracks the latest Generation value of what has been indexed.This can be used to force update a searcher to this generation. private long? _latestGen; - #region Properties +#region Properties /// /// Returns the configured for this index @@ -180,23 +182,23 @@ internal LuceneIndex( [EditorBrowsable(EditorBrowsableState.Never)] protected bool IsCancellationRequested => _cancellationToken.IsCancellationRequested; - #endregion +#endregion - #region Events +#region Events /// /// Occurs when [document writing]. /// - public event EventHandler DocumentWriting; + public event EventHandler? DocumentWriting; /// /// Occurs when an index is commited /// - public event EventHandler IndexCommitted; + public event EventHandler? IndexCommitted; - #endregion +#endregion - #region Event handlers +#region Event handlers /// /// Called when an indexing error occurs @@ -221,9 +223,9 @@ protected override void OnIndexingError(IndexingErrorEventArgs e) protected virtual void OnDocumentWriting(DocumentWritingEventArgs docArgs) => DocumentWriting?.Invoke(this, docArgs); - #endregion +#endregion - #region Provider implementation +#region Provider implementation /// protected override void PerformIndexItems(IEnumerable values, Action onComplete) @@ -408,9 +410,9 @@ public void EnsureIndex(bool forceOverwrite) /// /// Used internally to create a brand new index, this is not thread safe /// - private void CreateNewIndex(Directory dir) + private void CreateNewIndex(Directory? dir) { - IndexWriter writer = null; + IndexWriter? writer = null; try { if (IsLocked(dir)) @@ -543,9 +545,9 @@ private int PerformDeleteFromIndexInternal(IEnumerable itemIds, Cancella return indexedNodes; } - #endregion +#endregion - #region Protected +#region Protected @@ -554,7 +556,7 @@ private int PerformDeleteFromIndexInternal(IEnumerable itemIds, Cancella /// /// /// - protected virtual FieldValueTypeCollection CreateFieldValueTypes(IReadOnlyDictionary indexValueTypesFactory = null) + protected virtual FieldValueTypeCollection CreateFieldValueTypes(IReadOnlyDictionary? indexValueTypesFactory = null) { //copy to writable dictionary var defaults = new Dictionary(); @@ -591,7 +593,7 @@ protected virtual FieldValueTypeCollection CreateFieldValueTypes(IReadOnlyDictio /// Check if the index is readable/healthy /// /// - public bool IsReadable(out Exception ex) + public bool IsReadable(out Exception? ex) { if (_writer != null) { @@ -659,7 +661,7 @@ private bool IndexExistsImpl() /// Boolean if it successfully deleted the term, or there were on errors private bool DeleteFromIndex(Term indexTerm, bool performCommit = true) { - string itemId = null; + string? itemId = null; if (indexTerm.Field == "id") { itemId = indexTerm.Text; @@ -717,43 +719,46 @@ protected virtual void AddDocument(Document doc, ValueSet valueSet) IIndexFieldValueType indexTypeValueType = FieldValueTypeCollection.GetValueType(ExamineFieldNames.ItemTypeFieldName, FieldValueTypeCollection.ValueTypeFactories.GetRequiredFactory(FieldDefinitionTypes.InvariantCultureIgnoreCase)); indexTypeValueType.AddValue(doc, valueSet.ItemType); - foreach (KeyValuePair> field in valueSet.Values) + if(valueSet.Values != null) { - //check if we have a defined one - if (FieldDefinitions.TryGetValue(field.Key, out FieldDefinition definedFieldDefinition)) + foreach (KeyValuePair> field in valueSet.Values) { - IIndexFieldValueType valueType = FieldValueTypeCollection.GetValueType( - definedFieldDefinition.Name, - FieldValueTypeCollection.ValueTypeFactories.TryGetFactory(definedFieldDefinition.Type, out var valTypeFactory) - ? valTypeFactory - : FieldValueTypeCollection.ValueTypeFactories.GetRequiredFactory(FieldDefinitionTypes.FullText)); - - foreach (var o in field.Value) + //check if we have a defined one + if (FieldDefinitions.TryGetValue(field.Key, out FieldDefinition definedFieldDefinition)) { - valueType.AddValue(doc, o); - } - } - else if (field.Key.StartsWith(ExamineFieldNames.SpecialFieldPrefix)) - { - //Check for the special field prefix, if this is the case it's indexed as an invariant culture value + IIndexFieldValueType valueType = FieldValueTypeCollection.GetValueType( + definedFieldDefinition.Name, + FieldValueTypeCollection.ValueTypeFactories.TryGetFactory(definedFieldDefinition.Type, out var valTypeFactory) + ? valTypeFactory + : FieldValueTypeCollection.ValueTypeFactories.GetRequiredFactory(FieldDefinitionTypes.FullText)); - IIndexFieldValueType valueType = FieldValueTypeCollection.GetValueType(field.Key, FieldValueTypeCollection.ValueTypeFactories.GetRequiredFactory(FieldDefinitionTypes.InvariantCultureIgnoreCase)); - foreach (var o in field.Value) + foreach (var o in field.Value) + { + valueType.AddValue(doc, o); + } + } + else if (field.Key.StartsWith(ExamineFieldNames.SpecialFieldPrefix)) { - valueType.AddValue(doc, o); + //Check for the special field prefix, if this is the case it's indexed as an invariant culture value + + IIndexFieldValueType valueType = FieldValueTypeCollection.GetValueType(field.Key, FieldValueTypeCollection.ValueTypeFactories.GetRequiredFactory(FieldDefinitionTypes.InvariantCultureIgnoreCase)); + foreach (var o in field.Value) + { + valueType.AddValue(doc, o); + } } - } - else - { - // wasn't specifically defined, use FullText as the default + else + { + // wasn't specifically defined, use FullText as the default - IIndexFieldValueType valueType = FieldValueTypeCollection.GetValueType( - field.Key, - FieldValueTypeCollection.ValueTypeFactories.GetRequiredFactory(FieldDefinitionTypes.FullText)); + IIndexFieldValueType valueType = FieldValueTypeCollection.GetValueType( + field.Key, + FieldValueTypeCollection.ValueTypeFactories.GetRequiredFactory(FieldDefinitionTypes.FullText)); - foreach (var o in field.Value) - { - valueType.AddValue(doc, o); + foreach (var o in field.Value) + { + valueType.AddValue(doc, o); + } } } } @@ -776,7 +781,7 @@ private class IndexCommiter : DisposableObjectSlim { private readonly LuceneIndex _index; private DateTime _timestamp; - private Timer _timer; + private Timer? _timer; private readonly object _locker = new object(); private const int WaitMilliseconds = 2000; @@ -905,15 +910,15 @@ private bool ProcessQueueItem(IndexOperation item) /// Returns the Lucene Directory used to store the index /// /// - public Directory GetLuceneDirectory() => _writer != null ? _writer.IndexWriter.Directory : _directory.Value; + public Directory? GetLuceneDirectory() => _writer != null ? _writer.IndexWriter.Directory : _directory?.Value; /// /// Used to create an index writer - this is called in GetIndexWriter (and therefore, GetIndexWriter should not be overridden) /// /// - private TrackingIndexWriter CreateIndexWriterInternal() + private TrackingIndexWriter? CreateIndexWriterInternal() { - Directory dir = GetLuceneDirectory(); + Directory? dir = GetLuceneDirectory(); // Unfortunatley if the appdomain is taken down this will remain locked, so we can // ensure that it's unlocked here in that case. @@ -947,7 +952,7 @@ private TrackingIndexWriter CreateIndexWriterInternal() /// /// /// - protected virtual IndexWriter CreateIndexWriter(Directory d) + protected virtual IndexWriter CreateIndexWriter(Directory? d) { if (d == null) { @@ -1025,13 +1030,13 @@ public TrackingIndexWriter IndexWriter } - return _writer; + return _writer; // TODO: should this throw when null } } - #endregion +#endregion - #region Private +#region Private private LuceneSearcher CreateSearcher() { @@ -1178,7 +1183,7 @@ private void QueueTask(Func op, Action onComplete, } } - #endregion +#endregion /// /// Blocks the calling thread until the internal searcher can see latest documents @@ -1268,7 +1273,7 @@ protected virtual void Dispose(bool disposing) { if (disposing) { - if (_nrtReopenThread != null) + if (_nrtReopenThread is not null) { _nrtReopenThread.Interrupt(); _nrtReopenThread.Dispose(); @@ -1321,7 +1326,9 @@ protected virtual void Dispose(bool disposing) _cancellationTokenSource.Dispose(); +#if FULLDEBUG _logOutput?.Close(); +#endif } _disposedValue = true; } diff --git a/src/Examine.Lucene/Providers/MultiIndexSearcher.cs b/src/Examine.Lucene/Providers/MultiIndexSearcher.cs index c490577ff..0bfebea23 100644 --- a/src/Examine.Lucene/Providers/MultiIndexSearcher.cs +++ b/src/Examine.Lucene/Providers/MultiIndexSearcher.cs @@ -23,7 +23,7 @@ public class MultiIndexSearcher : BaseLuceneSearcher /// /// Get the current by injecting or use new FacetsConfig() for an empty configuration /// - public MultiIndexSearcher(string name, IEnumerable indexes, FacetsConfig facetsConfig, Analyzer analyzer = null) + public MultiIndexSearcher(string name, IEnumerable indexes, FacetsConfig facetsConfig, Analyzer? analyzer = null) : base(name, analyzer ?? new StandardAnalyzer(LuceneInfo.CurrentVersion), facetsConfig) { _searchers = new Lazy>(() => indexes.Select(x => x.Searcher)); @@ -36,7 +36,7 @@ public MultiIndexSearcher(string name, IEnumerable indexes, FacetsConfig /// /// Get the current by injecting or use new FacetsConfig() for an empty configuration /// - public MultiIndexSearcher(string name, Lazy> searchers, FacetsConfig facetsConfig, Analyzer analyzer = null) + public MultiIndexSearcher(string name, Lazy> searchers, FacetsConfig facetsConfig, Analyzer? analyzer = null) : base(name, analyzer ?? new StandardAnalyzer(LuceneInfo.CurrentVersion), facetsConfig) { _searchers = searchers; diff --git a/src/Examine.Lucene/Search/ISearchContext.cs b/src/Examine.Lucene/Search/ISearchContext.cs index a3f4510bd..c5090e352 100644 --- a/src/Examine.Lucene/Search/ISearchContext.cs +++ b/src/Examine.Lucene/Search/ISearchContext.cs @@ -24,6 +24,6 @@ public interface ISearchContext /// /// /// - IIndexFieldValueType GetFieldValueType(string fieldName); + IIndexFieldValueType? GetFieldValueType(string fieldName); } } diff --git a/src/Examine.Lucene/Search/LateBoundQuery.cs b/src/Examine.Lucene/Search/LateBoundQuery.cs index 88f0b5721..d3be92f9b 100644 --- a/src/Examine.Lucene/Search/LateBoundQuery.cs +++ b/src/Examine.Lucene/Search/LateBoundQuery.cs @@ -13,7 +13,7 @@ public class LateBoundQuery : Query { private readonly Func _factory; - private Query _wrapped; + private Query? _wrapped; /// /// The wrapped query @@ -27,13 +27,13 @@ public LateBoundQuery(Func factory) } /// - public override object Clone() + public override object? Clone() { return Wrapped.Clone(); } /// - public override Weight CreateWeight(IndexSearcher searcher) + public override Weight? CreateWeight(IndexSearcher searcher) { return Wrapped.CreateWeight(searcher); } @@ -60,13 +60,13 @@ public override float Boost } /// - public override Query Rewrite(IndexReader reader) + public override Query? Rewrite(IndexReader reader) { return Wrapped.Rewrite(reader); } /// - public override string ToString(string field) + public override string? ToString(string field) { return Wrapped.ToString(field); } diff --git a/src/Examine.Lucene/Search/LuceneBooleanOperation.cs b/src/Examine.Lucene/Search/LuceneBooleanOperation.cs index ea53a010b..18a7a044e 100644 --- a/src/Examine.Lucene/Search/LuceneBooleanOperation.cs +++ b/src/Examine.Lucene/Search/LuceneBooleanOperation.cs @@ -47,7 +47,7 @@ public LuceneBooleanOperation(LuceneSearchQuery search) #endregion /// - public override ISearchResults Execute(QueryOptions options = null) => _search.Execute(options); + public override ISearchResults Execute(QueryOptions? options = null) => _search.Execute(options); #region IOrdering diff --git a/src/Examine.Lucene/Search/LuceneBooleanOperationBase.cs b/src/Examine.Lucene/Search/LuceneBooleanOperationBase.cs index b6b91ade8..e40ebe042 100644 --- a/src/Examine.Lucene/Search/LuceneBooleanOperationBase.cs +++ b/src/Examine.Lucene/Search/LuceneBooleanOperationBase.cs @@ -119,7 +119,7 @@ protected internal LuceneBooleanOperationBase Op( } /// - public abstract ISearchResults Execute(QueryOptions options = null); + public abstract ISearchResults Execute(QueryOptions? options = null); /// public abstract IOrdering OrderBy(params SortableField[] fields); diff --git a/src/Examine.Lucene/Search/LuceneQuery.cs b/src/Examine.Lucene/Search/LuceneQuery.cs index 588528da8..42757bf7d 100644 --- a/src/Examine.Lucene/Search/LuceneQuery.cs +++ b/src/Examine.Lucene/Search/LuceneQuery.cs @@ -68,7 +68,7 @@ public IBooleanOperation GroupedNot(IEnumerable fields, params IExamineV public IOrdering All() => _search.All(); /// - public IBooleanOperation ManagedQuery(string query, string[] fields = null) + public IBooleanOperation ManagedQuery(string query, string[]? fields = null) => _search.ManagedQueryInternal(query, fields, _occurrence); /// @@ -78,7 +78,7 @@ public IBooleanOperation RangeQuery(string[] fields, T? min, T? max, bool min /// /// The category of the query /// - public string Category => _search.Category; + public string? Category => _search.Category; /// public IBooleanOperation NativeQuery(string query) => _search.NativeQuery(query); @@ -131,7 +131,7 @@ INestedBooleanOperation INestedQuery.GroupedNot(IEnumerable fields, para => _search.GroupedNotInternal(fields.ToArray(), query); /// - INestedBooleanOperation INestedQuery.ManagedQuery(string query, string[] fields) + INestedBooleanOperation INestedQuery.ManagedQuery(string query, string[]? fields) => _search.ManagedQueryInternal(query, fields, _occurrence); /// diff --git a/src/Examine.Lucene/Search/LuceneSearchExecutor.cs b/src/Examine.Lucene/Search/LuceneSearchExecutor.cs index 9c00d7184..32ce486c0 100644 --- a/src/Examine.Lucene/Search/LuceneSearchExecutor.cs +++ b/src/Examine.Lucene/Search/LuceneSearchExecutor.cs @@ -21,12 +21,12 @@ public class LuceneSearchExecutor private readonly IEnumerable _sortField; private readonly ISearchContext _searchContext; private readonly Query _luceneQuery; - private readonly ISet _fieldsToLoad; + private readonly ISet? _fieldsToLoad; private readonly IEnumerable _facetFields; private int? _maxDoc; private readonly FacetsConfig _facetsConfig; - internal LuceneSearchExecutor(QueryOptions options, Query query, IEnumerable sortField, ISearchContext searchContext, ISet fieldsToLoad, IEnumerable facetFields, FacetsConfig facetsConfig) + internal LuceneSearchExecutor(QueryOptions? options, Query query, IEnumerable sortField, ISearchContext searchContext, ISet fieldsToLoad, IEnumerable facetFields, FacetsConfig facetsConfig) { _options = options ?? QueryOptions.Default; _luceneQuery = query ?? throw new ArgumentNullException(nameof(query)); @@ -104,7 +104,7 @@ public ISearchResults Execute() using (ISearcherReference searcher = _searchContext.GetSearcher()) { - FacetsCollector facetsCollector; + FacetsCollector? facetsCollector; if(_facetFields.Any()) { facetsCollector = new FacetsCollector(); @@ -132,7 +132,10 @@ public ISearchResults Execute() for (int i = 0; i < topDocs.ScoreDocs.Length; i++) { var result = GetSearchResult(i, topDocs, searcher.IndexSearcher); - results.Add(result); + if(result != null) + { + results.Add(result); + } } var facets = ExtractFacets(facetsCollector, searcher); @@ -141,7 +144,7 @@ public ISearchResults Execute() } } - private IReadOnlyDictionary ExtractFacets(FacetsCollector facetsCollector, ISearcherReference searcher) + private IReadOnlyDictionary ExtractFacets(FacetsCollector? facetsCollector, ISearcherReference searcher) { var facets = new Dictionary(StringComparer.InvariantCultureIgnoreCase); if (facetsCollector == null || !_facetFields.Any()) @@ -151,7 +154,7 @@ private IReadOnlyDictionary ExtractFacets(FacetsCollector var facetFields = _facetFields.OrderBy(field => field.FacetField); - SortedSetDocValuesReaderState sortedSetReaderState = null; + SortedSetDocValuesReaderState? sortedSetReaderState = null; foreach(var field in facetFields) { @@ -172,12 +175,12 @@ private IReadOnlyDictionary ExtractFacets(FacetsCollector return facets; } - private ISearchResult GetSearchResult(int index, TopDocs topDocs, IndexSearcher luceneSearcher) + private ISearchResult? GetSearchResult(int index, TopDocs topDocs, IndexSearcher luceneSearcher) { // I have seen IndexOutOfRangeException here which is strange as this is only called in one place // and from that one place "i" is always less than the size of this collection. // but we'll error check here anyways - if (topDocs?.ScoreDocs.Length < index) + if (topDocs.ScoreDocs.Length < index) { return null; } diff --git a/src/Examine.Lucene/Search/LuceneSearchOptions.cs b/src/Examine.Lucene/Search/LuceneSearchOptions.cs index 6435afe17..267c48b22 100644 --- a/src/Examine.Lucene/Search/LuceneSearchOptions.cs +++ b/src/Examine.Lucene/Search/LuceneSearchOptions.cs @@ -43,7 +43,7 @@ public class LuceneSearchOptions /// rewriting and the above points are not relevant then use this change the rewrite /// method. /// - public MultiTermQuery.RewriteMethod MultiTermRewriteMethod { get; set; } + public MultiTermQuery.RewriteMethod? MultiTermRewriteMethod { get; set; } /// /// Get or Set the prefix length for fuzzy queries. Default is 0. @@ -53,12 +53,12 @@ public class LuceneSearchOptions /// /// Get or Set locale used by date range parsing. /// - public CultureInfo Locale { get; set; } + public CultureInfo? Locale { get; set; } /// /// Gets or Sets the time zone. /// - public TimeZoneInfo TimeZone { get; set; } + public TimeZoneInfo? TimeZone { get; set; } /// /// Gets or Sets the default slop for phrases. If zero, then exact phrase matches diff --git a/src/Examine.Lucene/Search/LuceneSearchQuery.cs b/src/Examine.Lucene/Search/LuceneSearchQuery.cs index 9ee85b31c..42cbe0412 100644 --- a/src/Examine.Lucene/Search/LuceneSearchQuery.cs +++ b/src/Examine.Lucene/Search/LuceneSearchQuery.cs @@ -18,13 +18,13 @@ public class LuceneSearchQuery : LuceneSearchQueryBase, IQueryExecutor { private readonly ISearchContext _searchContext; private readonly FacetsConfig _facetsConfig; - private ISet _fieldsToLoad = null; + private ISet? _fieldsToLoad = null; private readonly IList _facetFields = new List(); /// public LuceneSearchQuery( ISearchContext searchContext, - string category, Analyzer analyzer, LuceneSearchOptions searchOptions, BooleanOperation occurance, FacetsConfig facetsConfig) + string? category, Analyzer analyzer, LuceneSearchOptions searchOptions, BooleanOperation occurance, FacetsConfig facetsConfig) : base(CreateQueryParser(searchContext, analyzer, searchOptions), category, searchOptions, occurance) { _searchContext = searchContext; @@ -101,7 +101,7 @@ public override IBooleanOperation Field(string fieldName, T fieldValue) => RangeQueryInternal(new[] { fieldName }, fieldValue, fieldValue, true, true, Occurrence); /// - public override IBooleanOperation ManagedQuery(string query, string[] fields = null) + public override IBooleanOperation ManagedQuery(string query, string[]? fields = null) => ManagedQueryInternal(query, fields, Occurrence); /// @@ -113,21 +113,21 @@ protected override INestedBooleanOperation FieldNested(string fieldName, T fi => RangeQueryInternal(new[] { fieldName }, fieldValue, fieldValue, true, true, Occurrence); /// - protected override INestedBooleanOperation ManagedQueryNested(string query, string[] fields = null) + protected override INestedBooleanOperation ManagedQueryNested(string query, string[]? fields = null) => ManagedQueryInternal(query, fields, Occurrence); /// protected override INestedBooleanOperation RangeQueryNested(string[] fields, T? min, T? max, bool minInclusive = true, bool maxInclusive = true) => RangeQueryInternal(fields, min, max, minInclusive, maxInclusive, Occurrence); - internal LuceneBooleanOperationBase ManagedQueryInternal(string query, string[] fields, Occur occurance) + internal LuceneBooleanOperationBase ManagedQueryInternal(string query, string[]? fields, Occur occurance) { Query.Add(new LateBoundQuery(() => { //if no fields are specified then use all fields fields = fields ?? AllFields; - var types = fields.Select(f => _searchContext.GetFieldValueType(f)).Where(t => t != null); + var types = fields.Select(f => _searchContext.GetFieldValueType(f)).OfType(); //Strangely we need an inner and outer query. If we don't do this then the lucene syntax returned is incorrect //since it doesn't wrap in parenthesis properly. I'm unsure if this is a lucene issue (assume so) since that is what @@ -213,12 +213,12 @@ internal LuceneBooleanOperationBase RangeQueryInternal(string[] fields, T? mi } /// - public ISearchResults Execute(QueryOptions options = null) => Search(options); + public ISearchResults Execute(QueryOptions? options = null) => Search(options); /// /// Performs a search with a maximum number of results /// - private ISearchResults Search(QueryOptions options) + private ISearchResults Search(QueryOptions? options) { // capture local var query = Query; diff --git a/src/Examine.Lucene/Search/LuceneSearchQueryBase.cs b/src/Examine.Lucene/Search/LuceneSearchQueryBase.cs index dc023755d..fb4439241 100644 --- a/src/Examine.Lucene/Search/LuceneSearchQueryBase.cs +++ b/src/Examine.Lucene/Search/LuceneSearchQueryBase.cs @@ -41,7 +41,7 @@ public abstract class LuceneSearchQueryBase : IQuery, INestedQuery /// protected LuceneSearchQueryBase(CustomMultiFieldQueryParser queryParser, - string category, LuceneSearchOptions searchOptions, BooleanOperation occurance) + string? category, LuceneSearchOptions searchOptions, BooleanOperation occurance) { Category = category; SearchOptions = searchOptions; @@ -72,7 +72,7 @@ public BooleanOperation BooleanOperation /// /// The category of the query /// - public string Category { get; } + public string? Category { get; } /// /// All the searchable fields of the query @@ -125,7 +125,7 @@ public LuceneBooleanOperationBase LuceneQuery(Query query, BooleanOperation? op public abstract IBooleanOperation Field(string fieldName, T fieldValue) where T : struct; /// - public abstract IBooleanOperation ManagedQuery(string query, string[] fields = null); + public abstract IBooleanOperation ManagedQuery(string query, string[]? fields = null); /// public abstract IBooleanOperation RangeQuery(string[] fields, T? min, T? max, bool minInclusive = true, bool maxInclusive = true) where T : struct; @@ -140,10 +140,10 @@ public IBooleanOperation Field(string fieldName, IExamineValue fieldValue) /// public IBooleanOperation GroupedAnd(IEnumerable fields, params string[] query) - => GroupedAnd(fields, query?.Select(f => new ExamineValue(Examineness.Explicit, f)).Cast().ToArray()); + => GroupedAnd(fields, query.Select(f => new ExamineValue(Examineness.Explicit, f)).Cast().ToArray()); /// - public IBooleanOperation GroupedAnd(IEnumerable fields, params IExamineValue[] fieldVals) + public IBooleanOperation GroupedAnd(IEnumerable fields, params IExamineValue[]? fieldVals) { if (fields == null) throw new ArgumentNullException(nameof(fields)); @@ -158,7 +158,7 @@ public IBooleanOperation GroupedOr(IEnumerable fields, params string[] q => GroupedOr(fields, query?.Select(f => new ExamineValue(Examineness.Explicit, f)).Cast().ToArray()); /// - public IBooleanOperation GroupedOr(IEnumerable fields, params IExamineValue[] query) + public IBooleanOperation GroupedOr(IEnumerable fields, params IExamineValue[]? query) { if (fields == null) throw new ArgumentNullException(nameof(fields)); @@ -202,7 +202,7 @@ public IBooleanOperation GroupedNot(IEnumerable fields, params IExamineV /// /// /// - protected abstract INestedBooleanOperation ManagedQueryNested(string query, string[] fields = null); + protected abstract INestedBooleanOperation ManagedQueryNested(string query, string[]? fields = null); /// /// Matches items as defined by the IIndexFieldValueType used for the fields specified. @@ -241,7 +241,7 @@ INestedBooleanOperation INestedQuery.GroupedNot(IEnumerable fields, para INestedBooleanOperation INestedQuery.GroupedNot(IEnumerable fields, params IExamineValue[] query) => GroupedNotInternal(fields == null ? s_emptyStringArray : fields.ToArray(), query); - INestedBooleanOperation INestedQuery.ManagedQuery(string query, string[] fields) => ManagedQueryNested(query, fields); + INestedBooleanOperation INestedQuery.ManagedQuery(string query, string[]? fields) => ManagedQueryNested(query, fields); INestedBooleanOperation INestedQuery.RangeQuery(string[] fields, T? min, T? max, bool minInclusive, bool maxInclusive) => RangeQueryNested(fields, min, max, minInclusive, maxInclusive); @@ -274,7 +274,7 @@ private LuceneBooleanOperationBase FieldInternal(string fieldName, IExamineValue } /// - protected internal LuceneBooleanOperationBase GroupedAndInternal(string[] fields, IExamineValue[] fieldVals, Occur occurrence) + protected internal LuceneBooleanOperationBase GroupedAndInternal(string[] fields, IExamineValue[]? fieldVals, Occur occurrence) { if (fields == null) throw new ArgumentNullException(nameof(fields)); @@ -327,7 +327,7 @@ protected internal LuceneBooleanOperationBase GroupedNotInternal(string[] fields } /// - protected internal LuceneBooleanOperationBase GroupedOrInternal(string[] fields, IExamineValue[] fieldVals, Occur occurrence) + protected internal LuceneBooleanOperationBase GroupedOrInternal(string[] fields, IExamineValue[]? fieldVals, Occur occurrence) { if (fields == null) throw new ArgumentNullException(nameof(fields)); @@ -409,10 +409,10 @@ protected virtual Query GetFieldInternalQuery(string fieldName, IExamineValue fi if (useQueryParser) { queryToAdd = _queryParser.GetFieldQueryInternal(fieldName, fieldValue.Value); - if (queryToAdd != null) - { + //if (queryToAdd != null) // TODO: Does this ever happen? Then the method should be made with a nullable return + //{ queryToAdd.Boost = fieldValue.Level; - } + //} } else { @@ -422,7 +422,7 @@ protected virtual Query GetFieldInternalQuery(string fieldName, IExamineValue fi } break; case Examineness.Proximity: - int proximity = Convert.ToInt32(fieldValue.Level); + int proximity = Convert.ToInt32(fieldValue.Level); if (useQueryParser) { queryToAdd = _queryParser.GetProximityQueryInternal(fieldName, fieldValue.Value, proximity); diff --git a/src/Examine.Lucene/Search/MultiSearchContext.cs b/src/Examine.Lucene/Search/MultiSearchContext.cs index 9452f6e87..801604aae 100644 --- a/src/Examine.Lucene/Search/MultiSearchContext.cs +++ b/src/Examine.Lucene/Search/MultiSearchContext.cs @@ -11,7 +11,7 @@ public class MultiSearchContext : ISearchContext { private readonly ISearchContext[] _inner; - private string[] _fields; + private string[]? _fields; /// public MultiSearchContext(ISearchContext[] inner) => _inner = inner; @@ -24,7 +24,7 @@ public ISearcherReference GetSearcher() public string[] SearchableFields => _fields ?? (_fields = _inner.SelectMany(x => x.SearchableFields).Distinct().ToArray()); /// - public IIndexFieldValueType GetFieldValueType(string fieldName) + public IIndexFieldValueType? GetFieldValueType(string fieldName) => _inner.Select(cc => cc.GetFieldValueType(fieldName)).FirstOrDefault(type => type != null); } diff --git a/src/Examine.Lucene/Search/MultiSearchSearcherReference.cs b/src/Examine.Lucene/Search/MultiSearchSearcherReference.cs index 77fecf96d..64c40161b 100644 --- a/src/Examine.Lucene/Search/MultiSearchSearcherReference.cs +++ b/src/Examine.Lucene/Search/MultiSearchSearcherReference.cs @@ -12,7 +12,7 @@ public class MultiSearchSearcherReference : ISearcherReference public MultiSearchSearcherReference(ISearcherReference[] inner) => _inner = inner; private bool _disposedValue; - private IndexSearcher _searcher; + private IndexSearcher? _searcher; private readonly ISearcherReference[] _inner; /// diff --git a/src/Examine.Lucene/Search/SearchContext.cs b/src/Examine.Lucene/Search/SearchContext.cs index 494c8c5c2..725e9f62f 100644 --- a/src/Examine.Lucene/Search/SearchContext.cs +++ b/src/Examine.Lucene/Search/SearchContext.cs @@ -13,7 +13,7 @@ public class SearchContext : ISearchContext { private readonly SearcherManager _searcherManager; private readonly FieldValueTypeCollection _fieldValueTypeCollection; - private string[] _searchableFields; + private string[]? _searchableFields; /// public SearchContext(SearcherManager searcherManager, FieldValueTypeCollection fieldValueTypeCollection) diff --git a/src/Examine.Lucene/Search/SearcherReference.cs b/src/Examine.Lucene/Search/SearcherReference.cs index e9a48d272..3f8f40a79 100644 --- a/src/Examine.Lucene/Search/SearcherReference.cs +++ b/src/Examine.Lucene/Search/SearcherReference.cs @@ -8,7 +8,7 @@ public class SearcherReference : ISearcherReference { private bool _disposedValue; private readonly SearcherManager _searcherManager; - private IndexSearcher _searcher; + private IndexSearcher? _searcher; /// public SearcherReference(SearcherManager searcherManager) diff --git a/src/Examine.Lucene/ValueTypeFactoryCollection.cs b/src/Examine.Lucene/ValueTypeFactoryCollection.cs index d4a2dd4a3..d7289e59d 100644 --- a/src/Examine.Lucene/ValueTypeFactoryCollection.cs +++ b/src/Examine.Lucene/ValueTypeFactoryCollection.cs @@ -2,6 +2,7 @@ using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using Examine.Lucene.Analyzers; using Examine.Lucene.Indexing; @@ -33,7 +34,11 @@ public ValueTypeFactoryCollection(IReadOnlyDictionary /// /// - public bool TryGetFactory(string valueTypeName, out IFieldValueTypeFactory fieldValueTypeFactory) + public bool TryGetFactory(string valueTypeName, +#if !NETSTANDARD2_0 + [MaybeNullWhen(false)] +#endif + out IFieldValueTypeFactory fieldValueTypeFactory) => _valueTypeFactories.TryGetValue(valueTypeName, out fieldValueTypeFactory); /// @@ -61,7 +66,7 @@ public IFieldValueTypeFactory GetRequiredFactory(string valueTypeName) public static IReadOnlyDictionary GetDefaultValueTypes(ILoggerFactory loggerFactory, Analyzer defaultAnalyzer) => GetDefaults(loggerFactory, defaultAnalyzer).ToDictionary(x => x.Key, x => (IFieldValueTypeFactory)new DelegateFieldValueTypeFactory(x.Value)); - private static IReadOnlyDictionary> GetDefaults(ILoggerFactory loggerFactory, Analyzer defaultAnalyzer = null) => + private static IReadOnlyDictionary> GetDefaults(ILoggerFactory loggerFactory, Analyzer? defaultAnalyzer = null) => new Dictionary>(StringComparer.InvariantCultureIgnoreCase) //case insensitive { {"number", name => new Int32Type(name, loggerFactory)}, From c92654b4c6e44c0a8ac2c93ceacafe260e4f908b Mon Sep 17 00:00:00 2001 From: Nikolaj Brask-Nielsen Date: Fri, 16 Dec 2022 08:29:47 +0100 Subject: [PATCH 2/6] chore: Test project is not nullable - Remove ? --- src/Examine.Test/ExamineBaseTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Examine.Test/ExamineBaseTest.cs b/src/Examine.Test/ExamineBaseTest.cs index 8128c4d53..0e79d2803 100644 --- a/src/Examine.Test/ExamineBaseTest.cs +++ b/src/Examine.Test/ExamineBaseTest.cs @@ -21,7 +21,7 @@ public virtual void Setup() loggerFactory.CreateLogger(typeof(ExamineBaseTest)).LogDebug("Initializing test"); } - public TestIndex GetTestIndex(Directory d, Analyzer analyzer, FieldDefinitionCollection fieldDefinitions = null, IndexDeletionPolicy indexDeletionPolicy = null, IReadOnlyDictionary indexValueTypesFactory = null, FacetsConfig? facetsConfig = null) + public TestIndex GetTestIndex(Directory d, Analyzer analyzer, FieldDefinitionCollection? fieldDefinitions = null, IndexDeletionPolicy? indexDeletionPolicy = null, IReadOnlyDictionary? indexValueTypesFactory = null, FacetsConfig? facetsConfig = null) { var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole().SetMinimumLevel(LogLevel.Debug)); return new TestIndex( From de8e1d17b80715344b7600eb6d2b4fd1cdd1e860 Mon Sep 17 00:00:00 2001 From: Nikolaj Brask-Nielsen Date: Fri, 18 Nov 2022 15:12:51 +0100 Subject: [PATCH 3/6] feat: Nullable enabled --- src/Examine.Lucene/Indexing/FullTextType.cs | 2 +- src/Examine.Lucene/Search/LuceneSearchExecutor.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Examine.Lucene/Indexing/FullTextType.cs b/src/Examine.Lucene/Indexing/FullTextType.cs index 9ba51e264..726189fc7 100644 --- a/src/Examine.Lucene/Indexing/FullTextType.cs +++ b/src/Examine.Lucene/Indexing/FullTextType.cs @@ -40,7 +40,7 @@ public class FullTextType : IndexFieldValueTypeBase, IIndexFacetValueType /// /// Defaults to /// - public FullTextType(string fieldName, ILoggerFactory logger, bool sortable = false, bool isFacetable = false, Analyzer analyzer = null) + public FullTextType(string fieldName, ILoggerFactory logger, bool sortable = false, bool isFacetable = false, Analyzer? analyzer = null) : base(fieldName, logger, true) { _sortable = sortable; diff --git a/src/Examine.Lucene/Search/LuceneSearchExecutor.cs b/src/Examine.Lucene/Search/LuceneSearchExecutor.cs index 32ce486c0..b74208d87 100644 --- a/src/Examine.Lucene/Search/LuceneSearchExecutor.cs +++ b/src/Examine.Lucene/Search/LuceneSearchExecutor.cs @@ -26,7 +26,7 @@ public class LuceneSearchExecutor private int? _maxDoc; private readonly FacetsConfig _facetsConfig; - internal LuceneSearchExecutor(QueryOptions? options, Query query, IEnumerable sortField, ISearchContext searchContext, ISet fieldsToLoad, IEnumerable facetFields, FacetsConfig facetsConfig) + internal LuceneSearchExecutor(QueryOptions? options, Query query, IEnumerable sortField, ISearchContext searchContext, ISet? fieldsToLoad, IEnumerable facetFields, FacetsConfig facetsConfig) { _options = options ?? QueryOptions.Default; _luceneQuery = query ?? throw new ArgumentNullException(nameof(query)); From 2585b138e190da7818976588fcc594e94294fa0d Mon Sep 17 00:00:00 2001 From: Nikolaj Brask-Nielsen Date: Sun, 18 Jun 2023 21:23:24 +0200 Subject: [PATCH 4/6] feat: Add remaining nullable markers --- src/Examine.Core/Search/FacetResult.cs | 11 ++++++++++- src/Examine.Core/Search/IFacetOperations.cs | 4 ++-- src/Examine.Lucene/Search/FacetFullTextField.cs | 4 ++-- .../Search/LuceneFacetExtractionContext.cs | 2 +- src/Examine.Lucene/Search/LuceneFacetOperation.cs | 6 +++--- src/Examine.Lucene/Search/LuceneSearchQuery.cs | 2 +- src/Examine.Test/ExamineBaseTest.cs | 2 +- 7 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/Examine.Core/Search/FacetResult.cs b/src/Examine.Core/Search/FacetResult.cs index 87bdec7ad..5ca1bae48 100644 --- a/src/Examine.Core/Search/FacetResult.cs +++ b/src/Examine.Core/Search/FacetResult.cs @@ -1,5 +1,6 @@ using System.Collections; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; namespace Examine.Search @@ -8,7 +9,12 @@ namespace Examine.Search public class FacetResult : IFacetResult { private readonly IEnumerable _values; +#if NETSTANDARD2_1 + [AllowNull] private IDictionary _dictValues; +#else + private IDictionary? _dictValues; +#endif /// public FacetResult(IEnumerable values) @@ -22,6 +28,9 @@ public IEnumerator GetEnumerator() return _values.GetEnumerator(); } +#if !NETSTANDARD2_0 && !NETSTANDARD2_1 + [MemberNotNull(nameof(_dictValues))] +#endif private void SetValuesDictionary() { if(_dictValues == null) @@ -38,7 +47,7 @@ private void SetValuesDictionary() } /// - public bool TryGetFacet(string label, out IFacetValue facetValue) + public bool TryGetFacet(string label, out IFacetValue? facetValue) { SetValuesDictionary(); return _dictValues.TryGetValue(label, out facetValue); diff --git a/src/Examine.Core/Search/IFacetOperations.cs b/src/Examine.Core/Search/IFacetOperations.cs index c4bb8465c..c0439398b 100644 --- a/src/Examine.Core/Search/IFacetOperations.cs +++ b/src/Examine.Core/Search/IFacetOperations.cs @@ -14,7 +14,7 @@ public interface IFacetOperations : IQueryExecutor /// /// /// - IFacetOperations Facet(string field, Action facetConfiguration = null); + IFacetOperations Facet(string field, Action? facetConfiguration = null); /// /// Add a facet string to the current query, filtered by a single value or multiple values @@ -23,7 +23,7 @@ public interface IFacetOperations : IQueryExecutor /// /// /// - IFacetOperations Facet(string field, Action facetConfiguration = null, params string[] values); + IFacetOperations Facet(string field, Action? facetConfiguration = null, params string[] values); /// /// Add a range facet to the current query diff --git a/src/Examine.Lucene/Search/FacetFullTextField.cs b/src/Examine.Lucene/Search/FacetFullTextField.cs index 9a92b2b31..eebd86cea 100644 --- a/src/Examine.Lucene/Search/FacetFullTextField.cs +++ b/src/Examine.Lucene/Search/FacetFullTextField.cs @@ -29,13 +29,13 @@ public class FacetFullTextField : IFacetField /// /// Path hierachy /// - public string[] Path { get; internal set; } + public string[]? Path { get; internal set; } /// public bool IsTaxonomyIndexed { get; } /// - public FacetFullTextField(string field, string[] values, string facetField, int maxCount = 10, string[] path = null, bool isTaxonomyIndexed = false) + public FacetFullTextField(string field, string[] values, string facetField, int maxCount = 10, string[]? path = null, bool isTaxonomyIndexed = false) { Field = field; Values = values; diff --git a/src/Examine.Lucene/Search/LuceneFacetExtractionContext.cs b/src/Examine.Lucene/Search/LuceneFacetExtractionContext.cs index 44517ffea..c45d70ed7 100644 --- a/src/Examine.Lucene/Search/LuceneFacetExtractionContext.cs +++ b/src/Examine.Lucene/Search/LuceneFacetExtractionContext.cs @@ -8,7 +8,7 @@ namespace Examine.Lucene.Search public class LuceneFacetExtractionContext : IFacetExtractionContext { - private SortedSetDocValuesReaderState _sortedSetReaderState = null; + private SortedSetDocValuesReaderState? _sortedSetReaderState = null; /// public LuceneFacetExtractionContext(FacetsCollector facetsCollector, ISearcherReference searcherReference, FacetsConfig facetConfig) diff --git a/src/Examine.Lucene/Search/LuceneFacetOperation.cs b/src/Examine.Lucene/Search/LuceneFacetOperation.cs index 4b5d1d46d..0452834d5 100644 --- a/src/Examine.Lucene/Search/LuceneFacetOperation.cs +++ b/src/Examine.Lucene/Search/LuceneFacetOperation.cs @@ -23,13 +23,13 @@ public LuceneFacetOperation(LuceneSearchQuery search) } /// - public ISearchResults Execute(QueryOptions options = null) => _search.Execute(options); + public ISearchResults Execute(QueryOptions? options = null) => _search.Execute(options); /// - public IFacetOperations Facet(string field, Action facetConfiguration = null) => _search.FacetInternal(field, facetConfiguration, Array.Empty()); + public IFacetOperations Facet(string field, Action? facetConfiguration = null) => _search.FacetInternal(field, facetConfiguration, Array.Empty()); /// - public IFacetOperations Facet(string field, Action facetConfiguration = null, params string[] values) => _search.FacetInternal(field, facetConfiguration, values); + public IFacetOperations Facet(string field, Action? facetConfiguration = null, params string[] values) => _search.FacetInternal(field, facetConfiguration, values); /// public IFacetOperations Facet(string field, params DoubleRange[] doubleRanges) => _search.FacetInternal(field, doubleRanges); diff --git a/src/Examine.Lucene/Search/LuceneSearchQuery.cs b/src/Examine.Lucene/Search/LuceneSearchQuery.cs index 42cbe0412..01b01df4b 100644 --- a/src/Examine.Lucene/Search/LuceneSearchQuery.cs +++ b/src/Examine.Lucene/Search/LuceneSearchQuery.cs @@ -338,7 +338,7 @@ public IBooleanOperation SelectAllFieldsInternal() /// protected override LuceneBooleanOperationBase CreateOp() => new LuceneBooleanOperation(this); - internal IFacetOperations FacetInternal(string field, Action facetConfiguration, params string[] values) + internal IFacetOperations FacetInternal(string field, Action? facetConfiguration, params string[] values) { if(values == null) { diff --git a/src/Examine.Test/ExamineBaseTest.cs b/src/Examine.Test/ExamineBaseTest.cs index 0e79d2803..9a2e1bb25 100644 --- a/src/Examine.Test/ExamineBaseTest.cs +++ b/src/Examine.Test/ExamineBaseTest.cs @@ -21,7 +21,7 @@ public virtual void Setup() loggerFactory.CreateLogger(typeof(ExamineBaseTest)).LogDebug("Initializing test"); } - public TestIndex GetTestIndex(Directory d, Analyzer analyzer, FieldDefinitionCollection? fieldDefinitions = null, IndexDeletionPolicy? indexDeletionPolicy = null, IReadOnlyDictionary? indexValueTypesFactory = null, FacetsConfig? facetsConfig = null) + public TestIndex GetTestIndex(Directory d, Analyzer analyzer, FieldDefinitionCollection fieldDefinitions = null, IndexDeletionPolicy indexDeletionPolicy = null, IReadOnlyDictionary indexValueTypesFactory = null, FacetsConfig facetsConfig = null) { var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole().SetMinimumLevel(LogLevel.Debug)); return new TestIndex( From c205298fe98128cfd1033411864daa157284b6b0 Mon Sep 17 00:00:00 2001 From: Nikolaj Brask-Nielsen Date: Wed, 21 Jun 2023 07:10:31 +0200 Subject: [PATCH 5/6] refactor: Throw when dictionary key is not found --- src/Examine.Core/OrderedDictionary.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Examine.Core/OrderedDictionary.cs b/src/Examine.Core/OrderedDictionary.cs index 59e0378ae..c0d7255e1 100644 --- a/src/Examine.Core/OrderedDictionary.cs +++ b/src/Examine.Core/OrderedDictionary.cs @@ -105,7 +105,7 @@ TVal IDictionary.this[TKey key] { return found.Value; } - return default(TVal); // TODO: should this throw instead + throw new KeyNotFoundException(); } set { From 52f686c52945269b4d01be88b635dbad4f80139f Mon Sep 17 00:00:00 2001 From: Nikolaj Brask-Nielsen Date: Wed, 21 Jun 2023 07:23:54 +0200 Subject: [PATCH 6/6] feat: Added nullability to `GetFieldInternalQuery` --- src/Examine.Lucene/Search/LuceneSearchQueryBase.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Examine.Lucene/Search/LuceneSearchQueryBase.cs b/src/Examine.Lucene/Search/LuceneSearchQueryBase.cs index fb4439241..3d194d40c 100644 --- a/src/Examine.Lucene/Search/LuceneSearchQueryBase.cs +++ b/src/Examine.Lucene/Search/LuceneSearchQueryBase.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using Examine.Search; using Lucene.Net.Facet.Range; @@ -265,7 +266,7 @@ protected internal LuceneBooleanOperationBase FieldInternal(string fieldName, IE /// private LuceneBooleanOperationBase FieldInternal(string fieldName, IExamineValue fieldValue, Occur occurrence, bool useQueryParser) { - Query queryToAdd = GetFieldInternalQuery(fieldName, fieldValue, useQueryParser); + Query? queryToAdd = GetFieldInternalQuery(fieldName, fieldValue, useQueryParser); if (queryToAdd != null) Query.Add(queryToAdd, occurrence); @@ -364,7 +365,7 @@ protected internal LuceneBooleanOperationBase IdInternal(string id, Occur occurr /// /// True to use the query parser to parse the search text, otherwise, manually create the queries /// A new with the clause appended - protected virtual Query GetFieldInternalQuery(string fieldName, IExamineValue fieldValue, bool useQueryParser) + protected virtual Query? GetFieldInternalQuery(string fieldName, IExamineValue fieldValue, bool useQueryParser) { if (string.IsNullOrEmpty(fieldName)) throw new ArgumentException($"'{nameof(fieldName)}' cannot be null or empty", nameof(fieldName)); @@ -373,7 +374,7 @@ protected virtual Query GetFieldInternalQuery(string fieldName, IExamineValue fi if (string.IsNullOrEmpty(fieldValue.Value)) throw new ArgumentException($"'{nameof(fieldName)}' cannot be null or empty", nameof(fieldName)); - Query queryToAdd; + Query? queryToAdd; switch (fieldValue.Examineness) { @@ -409,10 +410,10 @@ protected virtual Query GetFieldInternalQuery(string fieldName, IExamineValue fi if (useQueryParser) { queryToAdd = _queryParser.GetFieldQueryInternal(fieldName, fieldValue.Value); - //if (queryToAdd != null) // TODO: Does this ever happen? Then the method should be made with a nullable return - //{ + if (queryToAdd != null) + { queryToAdd.Boost = fieldValue.Level; - //} + } } else {