From 78b0a11787710116c35199aff0808c2e115d746e Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Sat, 30 Nov 2019 17:02:14 -0800 Subject: [PATCH] Add nullable attributes/parameter checks for query Fixes #16705 Attempted to add null checks when the API is a public-surface API, but not for purely internal APIs. There may be some mistakes here; I plan to do a bit more static analysis after the initial merge. Also fixed the ApiConsistencyTest to check pubternal types again (not sure why this was removed) and to check protected constructors. --- .../Internal/CosmosLoggerExtensions.cs | 2 +- .../Internal/CosmosExpressionExtensions.cs | 3 +- .../Internal/CosmosDbOptionExtension.cs | 10 +- .../Internal/CosmosEntityTypeExtensions.cs | 3 +- .../Internal/CosmosNavigationExtensions.cs | 3 +- .../Query/Internal/ContainsTranslator.cs | 3 +- .../CosmosMemberTranslatorProvider.cs | 12 +- .../CosmosMethodCallTranslatorProvider.cs | 23 +- ...osmosProjectionBindingExpressionVisitor.cs | 16 +- ...yableMethodTranslatingExpressionVisitor.cs | 152 ++++++++++- ...thodTranslatingExpressionVisitorFactory.cs | 9 +- ...jectionBindingRemovingExpressionVisitor.cs | 12 +- ...sitor.JObjectInjectingExpressionVisitor.cs | 3 + ...osShapedQueryCompilingExpressionVisitor.cs | 12 +- ...dQueryCompilingExpressionVisitorFactory.cs | 14 +- .../CosmosSqlTranslatingExpressionVisitor.cs | 84 +++++- .../Internal/EntityProjectionExpression.cs | 21 +- .../Query/Internal/EqualsTranslator.cs | 7 +- .../Query/Internal/ExpressionExtensions.cs | 3 +- .../Query/Internal/IMemberTranslator.cs | 3 +- .../Internal/IMemberTranslatorProvider.cs | 3 +- .../Query/Internal/IMethodCallTranslator.cs | 4 +- .../Internal/IMethodCallTranslatorProvider.cs | 7 +- .../Query/Internal/ISqlExpressionFactory.cs | 78 +++--- .../Query/Internal/InExpression.cs | 9 +- .../Query/Internal/KeyAccessExpression.cs | 14 +- .../Query/Internal/ObjectAccessExpression.cs | 15 +- .../ObjectArrayProjectionExpression.cs | 17 +- .../Query/Internal/OrderingExpression.cs | 18 +- .../Query/Internal/ProjectionExpression.cs | 14 +- .../Query/Internal/QuerySqlGenerator.cs | 35 ++- .../Query/Internal/RootReferenceExpression.cs | 11 +- .../Query/Internal/SelectExpression.cs | 34 ++- .../Query/Internal/SqlBinaryExpression.cs | 15 +- .../Internal/SqlConditionalExpression.cs | 18 +- .../Query/Internal/SqlConstantExpression.cs | 20 +- .../Query/Internal/SqlExpression.cs | 3 +- .../Query/Internal/SqlExpressionFactory.cs | 3 +- .../Query/Internal/SqlExpressionVisitor.cs | 34 +-- .../Query/Internal/SqlFunctionExpression.cs | 18 +- .../Query/Internal/SqlParameterExpression.cs | 17 +- .../Query/Internal/SqlUnaryExpression.cs | 17 +- .../Storage/Internal/CosmosClientWrapper.cs | 72 ++--- .../Storage/Internal/CosmosDatabaseCreator.cs | 8 +- .../Storage/Internal/CosmosDatabaseWrapper.cs | 9 +- .../Storage/Internal/CosmosSqlQuery.cs | 3 +- .../Storage/Internal/HttpException.cs | 3 +- .../Storage/Internal/SqlParameter.cs | 4 +- .../Update/Internal/DocumentSource.cs | 11 +- .../Internal/CosmosValueGeneratorSelector.cs | 3 +- .../Design/Internal/CSharpHelper.cs | 4 +- .../Design/Internal/LanguageBasedSelector.cs | 2 +- .../ScaffoldingEntityTypeAnnotations.cs | 5 +- .../Internal/ScaffoldingModelExtensions.cs | 9 +- .../Scaffolding/Internal/CSharpUtilities.cs | 3 +- .../Internal/ICSharpDbContextGenerator.cs | 4 +- .../Internal/EntityProjectionExpression.cs | 14 +- ...yExpressionTranslatingExpressionVisitor.cs | 47 +++- .../InMemoryGroupByShaperExpression.cs | 9 +- ...emoryProjectionBindingExpressionVisitor.cs | 14 +- .../Query/Internal/InMemoryQueryExpression.cs | 53 ++-- .../InMemoryQueryTranslationPostprocessor.cs | 3 +- ...oryQueryTranslationPostprocessorFactory.cs | 6 +- ...yableMethodTranslatingExpressionVisitor.cs | 198 ++++++++++++-- ...thodTranslatingExpressionVisitorFactory.cs | 7 +- ....CustomShaperCompilingExpressionVisitor.cs | 3 + ...jectionBindingRemovingExpressionVisitor.cs | 7 + ...ryShapedQueryCompilingExpressionVisitor.cs | 10 +- ...moryShapedQueryExpressionVisitorFactory.cs | 10 +- .../Query/Internal/InMemoryTableExpression.cs | 8 +- ...erExpressionProcessingExpressionVisitor.cs | 5 +- .../Internal/SingleResultShaperExpression.cs | 14 +- .../IInMemoryIntegerValueGenerator.cs | 4 +- .../Internal/InMemoryIntegerValueGenerator.cs | 3 + .../RelationalExpressionExtensions.cs | 3 +- ...yFilterDefiningQueryRewritingConvention.cs | 3 + .../Metadata/Internal/DbFunctionParameter.cs | 2 +- .../Internal/RelationalPropertyExtensions.cs | 2 +- .../Metadata/Internal/Sequence.cs | 2 +- .../Migrations/Internal/Migrator.cs | 10 +- .../Query/CollectionInitializingExpression.cs | 17 +- .../Query/CollectionPopulatingExpression.cs | 11 +- .../Query/EntityProjectionExpression.cs | 31 ++- .../Query/ExpressionExtensions.cs | 6 +- .../Query/IMemberTranslator.cs | 3 +- .../Query/IMemberTranslatorProvider.cs | 3 +- .../Query/IMethodCallTranslator.cs | 4 +- .../Query/IMethodCallTranslatorProvider.cs | 7 +- ...lSqlTranslatingExpressionVisitorFactory.cs | 5 +- .../Query/ISqlExpressionFactory.cs | 133 ++++++---- .../Query/Internal/BufferedDataReader.cs | 2 +- .../CaseWhenFlatteningExpressionVisitor.cs | 8 +- ...CollectionJoinApplyingExpressionVisitor.cs | 3 + .../CollectionMaterializationContext.cs | 10 +- .../Query/Internal/ComparisonTranslator.cs | 7 +- .../Query/Internal/ContainsTranslator.cs | 7 +- .../Query/Internal/EnumHasFlagTranslator.cs | 7 +- .../Query/Internal/EqualsTranslator.cs | 7 +- .../Internal/GetValueOrDefaultTranslator.cs | 7 +- .../Query/Internal/LikeTranslator.cs | 7 +- ...NullSemanticsRewritingExpressionVisitor.cs | 68 ++++- .../Internal/NullableMemberTranslator.cs | 7 +- .../Internal/QuerySqlGeneratorFactory.cs | 4 +- .../Query/Internal/QueryingEnumerable.cs | 17 +- .../Query/Internal/RelationalCommandCache.cs | 13 +- ...ionalProjectionBindingExpressionVisitor.cs | 14 +- ...nalQueryTranslationPostprocessorFactory.cs | 8 +- ...onalQueryTranslationPreprocessorFactory.cs | 12 +- ...thodTranslatingExpressionVisitorFactory.cs | 12 +- ...dQueryCompilingExpressionVisitorFactory.cs | 12 +- ...lSqlTranslatingExpressionVisitorFactory.cs | 4 + .../Query/Internal/ResultContext.cs | 4 +- .../Query/Internal/ResultCoordinator.cs | 3 +- ...sionProjectionApplyingExpressionVisitor.cs | 3 + ...qlExpressionOptimizingExpressionVisitor.cs | 20 +- .../Query/Internal/StringMethodTranslator.cs | 7 +- .../TableAliasUniquifyingExpressionVisitor.cs | 3 + .../Query/QuerySqlGenerator.cs | 94 ++++++- .../RelationalCollectionShaperExpression.cs | 32 ++- .../RelationalEvaluatableExpressionFilter.cs | 3 + .../RelationalMemberTranslatorProvider.cs | 17 +- .../RelationalMethodCallTranslatorProvider.cs | 15 +- ...meterBasedQueryTranslationPostprocessor.cs | 12 +- ...eryTranslationPostprocessorDependencies.cs | 4 +- ...sedQueryTranslationPostprocessorFactory.cs | 8 +- ...RelationalQueryTranslationPostprocessor.cs | 18 +- .../RelationalQueryTranslationPreprocessor.cs | 11 +- ...yableMethodTranslatingExpressionVisitor.cs | 196 ++++++++++---- ....CustomShaperCompilingExpressionVisitor.cs | 3 + ...jectionBindingRemovingExpressionVisitor.cs | 7 + ...erExpressionProcessingExpressionVisitor.cs | 3 + ...alShapedQueryCompilingExpressionVisitor.cs | 12 +- ...lationalSqlTranslatingExpressionVisitor.cs | 110 ++++++-- .../Query/SqlExpressionFactory.cs | 246 +++++++++++++++--- .../Query/SqlExpressionFactoryDependencies.cs | 2 +- .../Query/SqlExpressionVisitor.cs | 56 ++-- .../Query/SqlExpressions/CaseExpression.cs | 29 ++- .../Query/SqlExpressions/CaseWhenClause.cs | 7 +- .../Query/SqlExpressions/ColumnExpression.cs | 9 +- .../SqlExpressions/CrossApplyExpression.cs | 20 +- .../SqlExpressions/CrossJoinExpression.cs | 20 +- .../Query/SqlExpressions/ExceptExpression.cs | 21 +- .../Query/SqlExpressions/ExistsExpression.cs | 25 +- .../Query/SqlExpressions/FromSqlExpression.cs | 19 +- .../Query/SqlExpressions/InExpression.cs | 31 ++- .../SqlExpressions/InnerJoinExpression.cs | 17 +- .../SqlExpressions/IntersectExpression.cs | 18 +- .../SqlExpressions/JoinExpressionBase.cs | 6 +- .../SqlExpressions/LeftJoinExpression.cs | 17 +- .../Query/SqlExpressions/LikeExpression.cs | 25 +- .../SqlExpressions/OrderingExpression.cs | 22 +- .../SqlExpressions/OuterApplyExpression.cs | 20 +- .../PredicateJoinExpressionBase.cs | 6 +- .../SqlExpressions/ProjectionExpression.cs | 23 +- .../SqlExpressions/RowNumberExpression.cs | 15 +- .../ScalarSubqueryExpression.cs | 22 +- .../Query/SqlExpressions/SelectExpression.cs | 176 ++++++++++--- .../Query/SqlExpressions/SetOperationBase.cs | 6 +- .../SqlExpressions/SqlBinaryExpression.cs | 22 +- .../SqlExpressions/SqlConstantExpression.cs | 27 +- .../Query/SqlExpressions/SqlExpression.cs | 3 +- .../SqlExpressions/SqlFragmentExpression.cs | 19 +- .../SqlExpressions/SqlFunctionExpression.cs | 130 ++++++--- .../SqlExpressions/SqlParameterExpression.cs | 21 +- .../SqlExpressions/SqlUnaryExpression.cs | 25 +- .../Query/SqlExpressions/TableExpression.cs | 3 + .../SqlExpressions/TableExpressionBase.cs | 7 +- .../Query/SqlExpressions/UnionExpression.cs | 21 +- .../Storage/RelationalGeometryTypeMapping.cs | 2 +- ...erverGeometryCollectionMemberTranslator.cs | 7 +- ...erverGeometryCollectionMethodTranslator.cs | 9 +- .../SqlServerGeometryMemberTranslator.cs | 9 +- .../SqlServerGeometryMethodTranslator.cs | 9 +- .../SqlServerLineStringMemberTranslator.cs | 9 +- .../SqlServerLineStringMethodTranslator.cs | 9 +- ...qlServerMultiLineStringMemberTranslator.cs | 7 +- ...rNetTopologySuiteMemberTranslatorPlugin.cs | 3 +- ...TopologySuiteMethodCallTranslatorPlugin.cs | 5 +- .../SqlServerPolygonMemberTranslator.cs | 9 +- .../SqlServerPolygonMethodTranslator.cs | 9 +- .../Internal/SqlServerGeometryTypeMapping.cs | 4 +- .../Internal/GeometryValueConverter.cs | 3 +- ...rchConditionConvertingExpressionVisitor.cs | 68 ++++- .../SqlServerByteArrayMethodTranslator.cs | 9 +- .../Internal/SqlServerConvertTranslator.cs | 7 +- .../SqlServerDateDiffFunctionsTranslator.cs | 7 +- .../SqlServerDateTimeMemberTranslator.cs | 7 +- .../SqlServerDateTimeMethodTranslator.cs | 8 +- ...ServerFullTextSearchFunctionsTranslator.cs | 8 +- .../SqlServerIsDateFunctionTranslator.cs | 7 +- .../Query/Internal/SqlServerMathTranslator.cs | 7 +- .../Internal/SqlServerNewGuidTranslator.cs | 7 +- .../SqlServerObjectToStringTranslator.cs | 7 +- ...meterBasedQueryTranslationPostprocessor.cs | 7 +- ...sedQueryTranslationPostprocessorFactory.cs | 4 +- .../Internal/SqlServerQuerySqlGenerator.cs | 10 +- .../SqlServerQuerySqlGeneratorFactory.cs | 3 +- .../SqlServerQueryTranslationPostprocessor.cs | 7 +- ...verQueryTranslationPostprocessorFactory.cs | 12 +- ...qlServerSqlTranslatingExpressionVisitor.cs | 10 +- .../SqlServerStringMemberTranslator.cs | 7 +- .../SqlServerStringMethodTranslator.cs | 7 +- .../Internal/SqlServerByteArrayTypeMapping.cs | 2 +- .../Internal/SqlServerUdtTypeMapping.cs | 4 +- .../SqliteByteArrayMethodTranslator.cs | 3 +- .../Internal/SqliteDateTimeAddTranslator.cs | 7 +- .../SqliteDateTimeMemberTranslator.cs | 7 +- .../Query/Internal/SqliteExpression.cs | 13 +- .../Query/Internal/SqliteMathTranslator.cs | 7 +- .../SqliteMemberTranslatorProvider.cs | 3 +- .../Query/Internal/SqliteQuerySqlGenerator.cs | 12 +- .../SqliteQuerySqlGeneratorFactory.cs | 3 +- ...yableMethodTranslatingExpressionVisitor.cs | 16 +- ...thodTranslatingExpressionVisitorFactory.cs | 12 +- .../SqliteSqlTranslatingExpressionVisitor.cs | 20 +- .../Internal/SqliteStringLengthTranslator.cs | 7 +- .../Internal/SqliteStringMethodTranslator.cs | 7 +- .../Internal/SqliteTypeMappingSource.cs | 2 +- ...qliteGeometryCollectionMemberTranslator.cs | 7 +- ...qliteGeometryCollectionMethodTranslator.cs | 7 +- .../SqliteGeometryMemberTranslator.cs | 7 +- .../SqliteGeometryMethodTranslator.cs | 7 +- .../SqliteLineStringMemberTranslator.cs | 7 +- .../SqliteLineStringMethodTranslator.cs | 7 +- .../SqliteMultiLineStringMemberTranslator.cs | 7 +- ...eNetTopologySuiteMemberTranslatorPlugin.cs | 3 +- ...TopologySuiteMethodCallTranslatorPlugin.cs | 3 +- .../Internal/SqlitePointMemberTranslator.cs | 7 +- .../Internal/SqlitePolygonMemberTranslator.cs | 7 +- .../Internal/SqlitePolygonMethodTranslator.cs | 7 +- .../Internal/SqliteGeometryTypeMapping.cs | 4 +- .../Internal/GeometryValueConverter.cs | 3 +- .../ChangeTracking/Internal/IIdentityMap.cs | 2 +- .../Internal/IPrincipalKeyValueFactory.cs | 2 +- .../ChangeTracking/Internal/IStateManager.cs | 4 +- .../Internal/InternalEntityEntry.cs | 4 +- .../Internal/SnapshotFactoryFactory.cs | 8 +- .../Internal/EFPropertyExtensions.cs | 6 +- .../Internal/ExpressionExtensions.cs | 4 +- .../Internal/QueryableExtensions.cs | 11 +- .../Extensions/Internal/TypeExtensions.cs | 4 +- .../DbContextOptionsExtensionInfo.cs | 5 +- .../InvertibleRelationshipBuilderBase.cs | 4 +- .../Metadata/Builders/OwnershipBuilder.cs | 4 +- .../Metadata/Builders/OwnershipBuilder`.cs | 4 +- .../Builders/ReferenceCollectionBuilder.cs | 4 +- .../Builders/ReferenceCollectionBuilder`.cs | 4 +- .../Builders/ReferenceReferenceBuilder.cs | 4 +- .../Builders/ReferenceReferenceBuilder`.cs | 4 +- .../Builders/RelationshipBuilderBase.cs | 4 +- .../Conventions/Internal/ConventionContext.cs | 6 +- .../Internal/ConventionDispatcher.cs | 2 +- ...yFilterDefiningQueryRewritingConvention.cs | 5 + .../Metadata/Internal/ClrAccessorFactory.cs | 2 +- .../Internal/ConventionAnnotatable.cs | 4 +- src/EFCore/Metadata/Internal/EntityType.cs | 16 +- src/EFCore/Metadata/Internal/ForeignKey.cs | 4 +- .../Internal/InternalAnnotatableBuilder.cs | 2 +- .../Internal/InternalEntityTypeBuilder.cs | 33 +-- .../Internal/InternalPropertyBuilder.cs | 2 +- .../InternalServicePropertyBuilder.cs | 4 +- src/EFCore/Metadata/Internal/Model.cs | 2 +- src/EFCore/Metadata/Internal/Property.cs | 2 +- .../Metadata/Internal/ServiceProperty.cs | 2 +- .../Metadata/Internal/TypeBaseExtensions.cs | 6 +- .../Query/CollectionShaperExpression.cs | 28 +- src/EFCore/Query/EntityShaperExpression.cs | 31 ++- .../Query/EvaluatableExpressionFilter.cs | 3 + src/EFCore/Query/ExpressionPrinter.cs | 57 +++- src/EFCore/Query/GroupByShaperExpression.cs | 22 +- .../Query/IEvaluatableExpressionFilter.cs | 3 +- .../IQueryTranslationPostprocessorFactory.cs | 3 +- .../IQueryTranslationPreprocessorFactory.cs | 3 +- ...thodTranslatingExpressionVisitorFactory.cs | 3 +- ...dQueryCompilingExpressionVisitorFactory.cs | 3 +- src/EFCore/Query/IncludeExpression.cs | 48 +++- ...AnyToContainsRewritingExpressionVisitor.cs | 3 + .../Query/Internal/CompiledQueryBase.cs | 3 + ...ntityEqualityRewritingExpressionVisitor.cs | 66 ++++- ...ryableMethodConvertingExpressionVisitor.cs | 3 + .../FunctionPreprocessingExpressionVisitor.cs | 5 + .../GroupJoinFlatteningExpressionVisitor.cs | 9 + ...tionExpressionRemovingExpressionVisitor.cs | 3 + ...ingExpressionVisitor.ExpressionVisitors.cs | 17 ++ ...nExpandingExpressionVisitor.Expressions.cs | 26 +- .../NavigationExpandingExpressionVisitor.cs | 19 +- .../NegationOptimizingExpressionVisitor.cs | 3 + .../NullCheckRemovingExpressionVisitor.cs | 7 + .../ParameterExtractingExpressionVisitor.cs | 37 ++- .../QueryCompilationContextFactory.cs | 3 +- src/EFCore/Query/Internal/QueryCompiler.cs | 18 +- ...ueryMetadataExtractingExpressionVisitor.cs | 6 +- .../QueryTranslationPostprocessorFactory.cs | 6 +- .../QueryTranslationPreprocessorFactory.cs | 10 +- ...SubqueryMemberPushdownExpressionVisitor.cs | 5 + ...terializeCollectionNavigationExpression.cs | 23 +- .../Query/ProjectionBindingExpression.cs | 35 ++- src/EFCore/Query/ProjectionMember.cs | 14 +- src/EFCore/Query/QueryCompilationContext.cs | 19 +- src/EFCore/Query/QueryContext.cs | 11 +- .../Query/QueryTranslationPostprocessor.cs | 10 +- .../Query/QueryTranslationPreprocessor.cs | 34 +-- ...yableMethodTranslatingExpressionVisitor.cs | 176 +++++++++---- src/EFCore/Query/QueryableMethods.cs | 65 ++++- .../Query/ReplacingExpressionVisitor.cs | 16 +- .../ShapedQueryCompilingExpressionVisitor.cs | 28 +- src/EFCore/Query/ShapedQueryExpression.cs | 28 +- .../Query/TransparentIdentifierFactory.cs | 10 +- .../Query/QueryBugsTest.cs | 2 +- test/EFCore.Tests/ApiConsistencyTestBase.cs | 5 +- 310 files changed, 4003 insertions(+), 1164 deletions(-) diff --git a/src/EFCore.Cosmos/Diagnostics/Internal/CosmosLoggerExtensions.cs b/src/EFCore.Cosmos/Diagnostics/Internal/CosmosLoggerExtensions.cs index 7983d343f5d..786fc6d263c 100644 --- a/src/EFCore.Cosmos/Diagnostics/Internal/CosmosLoggerExtensions.cs +++ b/src/EFCore.Cosmos/Diagnostics/Internal/CosmosLoggerExtensions.cs @@ -32,7 +32,7 @@ public static class CosmosLoggerExtensions /// public static void ExecutingSqlQuery( [NotNull] this IDiagnosticsLogger diagnosticsLogger, - CosmosSqlQuery cosmosSqlQuery) + [NotNull] CosmosSqlQuery cosmosSqlQuery) { var definition = new EventDefinition( diagnosticsLogger.Options, diff --git a/src/EFCore.Cosmos/Extensions/Internal/CosmosExpressionExtensions.cs b/src/EFCore.Cosmos/Extensions/Internal/CosmosExpressionExtensions.cs index e4082679c02..b49dcb2538d 100644 --- a/src/EFCore.Cosmos/Extensions/Internal/CosmosExpressionExtensions.cs +++ b/src/EFCore.Cosmos/Extensions/Internal/CosmosExpressionExtensions.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Cosmos.Query.Internal; // ReSharper disable once CheckNamespace @@ -21,7 +22,7 @@ public static class CosmosExpressionExtensions /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public static bool IsLogicalNot(this SqlUnaryExpression sqlUnaryExpression) + public static bool IsLogicalNot([NotNull] this SqlUnaryExpression sqlUnaryExpression) => sqlUnaryExpression.OperatorType == ExpressionType.Not && (sqlUnaryExpression.Type == typeof(bool) || sqlUnaryExpression.Type == typeof(bool?)); diff --git a/src/EFCore.Cosmos/Infrastructure/Internal/CosmosDbOptionExtension.cs b/src/EFCore.Cosmos/Infrastructure/Internal/CosmosDbOptionExtension.cs index f8ccf733b12..76ebf39fc0e 100644 --- a/src/EFCore.Cosmos/Infrastructure/Internal/CosmosDbOptionExtension.cs +++ b/src/EFCore.Cosmos/Infrastructure/Internal/CosmosDbOptionExtension.cs @@ -46,7 +46,7 @@ public CosmosOptionsExtension() /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected CosmosOptionsExtension(CosmosOptionsExtension copyFrom) + protected CosmosOptionsExtension([NotNull] CosmosOptionsExtension copyFrom) { _accountEndpoint = copyFrom._accountEndpoint; _accountKey = copyFrom._accountKey; @@ -79,7 +79,7 @@ public virtual DbContextOptionsExtensionInfo Info /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual CosmosOptionsExtension WithAccountEndpoint(string accountEndpoint) + public virtual CosmosOptionsExtension WithAccountEndpoint([NotNull] string accountEndpoint) { var clone = Clone(); @@ -102,7 +102,7 @@ public virtual CosmosOptionsExtension WithAccountEndpoint(string accountEndpoint /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual CosmosOptionsExtension WithAccountKey(string accountKey) + public virtual CosmosOptionsExtension WithAccountKey([NotNull] string accountKey) { var clone = Clone(); @@ -125,7 +125,7 @@ public virtual CosmosOptionsExtension WithAccountKey(string accountKey) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual CosmosOptionsExtension WithDatabaseName(string database) + public virtual CosmosOptionsExtension WithDatabaseName([NotNull] string database) { var clone = Clone(); @@ -148,7 +148,7 @@ public virtual CosmosOptionsExtension WithDatabaseName(string database) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual CosmosOptionsExtension WithRegion(string region) + public virtual CosmosOptionsExtension WithRegion([NotNull] string region) { var clone = Clone(); diff --git a/src/EFCore.Cosmos/Metadata/Internal/CosmosEntityTypeExtensions.cs b/src/EFCore.Cosmos/Metadata/Internal/CosmosEntityTypeExtensions.cs index a3ad9541c52..0648779f8c1 100644 --- a/src/EFCore.Cosmos/Metadata/Internal/CosmosEntityTypeExtensions.cs +++ b/src/EFCore.Cosmos/Metadata/Internal/CosmosEntityTypeExtensions.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; namespace Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal @@ -19,7 +20,7 @@ public static class CosmosEntityTypeExtensions /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public static bool IsDocumentRoot(this IEntityType entityType) + public static bool IsDocumentRoot([NotNull] this IEntityType entityType) => entityType.BaseType?.IsDocumentRoot() ?? (!entityType.IsOwned() || entityType[CosmosAnnotationNames.ContainerName] != null); diff --git a/src/EFCore.Cosmos/Metadata/Internal/CosmosNavigationExtensions.cs b/src/EFCore.Cosmos/Metadata/Internal/CosmosNavigationExtensions.cs index f3953e0a7c7..5892fd4f046 100644 --- a/src/EFCore.Cosmos/Metadata/Internal/CosmosNavigationExtensions.cs +++ b/src/EFCore.Cosmos/Metadata/Internal/CosmosNavigationExtensions.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; namespace Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal @@ -19,7 +20,7 @@ public static class CosmosNavigationExtensions /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public static bool IsEmbedded(this INavigation navigation) + public static bool IsEmbedded([NotNull] this INavigation navigation) => !navigation.IsDependentToPrincipal() && !navigation.ForeignKey.DeclaringEntityType.IsDocumentRoot(); } diff --git a/src/EFCore.Cosmos/Query/Internal/ContainsTranslator.cs b/src/EFCore.Cosmos/Query/Internal/ContainsTranslator.cs index 8c09046acce..0743949ac3f 100644 --- a/src/EFCore.Cosmos/Query/Internal/ContainsTranslator.cs +++ b/src/EFCore.Cosmos/Query/Internal/ContainsTranslator.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using JetBrains.Annotations; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal { @@ -24,7 +25,7 @@ public class ContainsTranslator : IMethodCallTranslator /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public ContainsTranslator(ISqlExpressionFactory sqlExpressionFactory) + public ContainsTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosMemberTranslatorProvider.cs b/src/EFCore.Cosmos/Query/Internal/CosmosMemberTranslatorProvider.cs index cb93951885f..381fe0c3c25 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosMemberTranslatorProvider.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosMemberTranslatorProvider.cs @@ -5,6 +5,8 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal { @@ -26,8 +28,8 @@ public class CosmosMemberTranslatorProvider : IMemberTranslatorProvider /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public CosmosMemberTranslatorProvider( - ISqlExpressionFactory sqlExpressionFactory, - IEnumerable plugins) + [NotNull] ISqlExpressionFactory sqlExpressionFactory, + [NotNull] IEnumerable plugins) { _plugins.AddRange(plugins.SelectMany(p => p.Translators)); //_translators @@ -46,6 +48,10 @@ public CosmosMemberTranslatorProvider( /// public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { + Check.NotNull(instance, nameof(instance)); + Check.NotNull(member, nameof(member)); + Check.NotNull(returnType, nameof(returnType)); + return _plugins.Concat(_translators) .Select(t => t.Translate(instance, member, returnType)).FirstOrDefault(t => t != null); } @@ -56,7 +62,7 @@ public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected virtual void AddTranslators(IEnumerable translators) + protected virtual void AddTranslators([NotNull] IEnumerable translators) => _translators.InsertRange(0, translators); } } diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosMethodCallTranslatorProvider.cs b/src/EFCore.Cosmos/Query/Internal/CosmosMethodCallTranslatorProvider.cs index cc8a8b526b2..e6007b2344f 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosMethodCallTranslatorProvider.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosMethodCallTranslatorProvider.cs @@ -4,7 +4,9 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal { @@ -26,8 +28,8 @@ public class CosmosMethodCallTranslatorProvider : IMethodCallTranslatorProvider /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public CosmosMethodCallTranslatorProvider( - ISqlExpressionFactory sqlExpressionFactory, - IEnumerable plugins) + [NotNull] ISqlExpressionFactory sqlExpressionFactory, + [NotNull] IEnumerable plugins) { _plugins.AddRange(plugins.SelectMany(p => p.Translators)); @@ -53,18 +55,9 @@ public CosmosMethodCallTranslatorProvider( public virtual SqlExpression Translate( IModel model, SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { - // TODO: UDF support. See issue#15338 - //var dbFunction = model.FindDbFunction(method); - //if (dbFunction != null) - //{ - // return dbFunction.Translation?.Invoke( - // arguments.Select(e => _sqlExpressionFactory.ApplyDefaultTypeMapping(e)).ToList()) - // ?? _sqlExpressionFactory.Function( - // dbFunction.Schema, - // dbFunction.Name, - // arguments, - // method.ReturnType); - //} + Check.NotNull(model, nameof(model)); + Check.NotNull(method, nameof(method)); + Check.NotNull(arguments, nameof(arguments)); return _plugins.Concat(_translators) .Select(t => t.Translate(instance, method, arguments)) @@ -77,7 +70,7 @@ public virtual SqlExpression Translate( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected virtual void AddTranslators(IEnumerable translators) + protected virtual void AddTranslators([NotNull] IEnumerable translators) => _translators.InsertRange(0, translators); } } diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosProjectionBindingExpressionVisitor.cs b/src/EFCore.Cosmos/Query/Internal/CosmosProjectionBindingExpressionVisitor.cs index b664247398c..34140b9caa7 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosProjectionBindingExpressionVisitor.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosProjectionBindingExpressionVisitor.cs @@ -6,12 +6,14 @@ using System.Linq; using System.Linq.Expressions; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal { @@ -44,7 +46,7 @@ private readonly Stack _includedNavigations /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public CosmosProjectionBindingExpressionVisitor(CosmosSqlTranslatingExpressionVisitor sqlTranslator) + public CosmosProjectionBindingExpressionVisitor([NotNull] CosmosSqlTranslatingExpressionVisitor sqlTranslator) { _sqlTranslator = sqlTranslator; } @@ -55,7 +57,7 @@ public CosmosProjectionBindingExpressionVisitor(CosmosSqlTranslatingExpressionVi /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual Expression Translate(SelectExpression selectExpression, Expression expression) + public virtual Expression Translate([NotNull] SelectExpression selectExpression, [NotNull] Expression expression) { _selectExpression = selectExpression; _clientEval = false; @@ -170,6 +172,8 @@ private static T GetParameterValue(QueryContext queryContext, string paramete /// protected override Expression VisitMember(MemberExpression memberExpression) { + Check.NotNull(memberExpression, nameof(memberExpression)); + if (!_clientEval) { return null; @@ -254,6 +258,8 @@ protected override Expression VisitMember(MemberExpression memberExpression) protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { + Check.NotNull(methodCallExpression, nameof(methodCallExpression)); + if (methodCallExpression.TryGetEFPropertyArguments(out var source, out var memberName)) { if (!_clientEval) @@ -403,6 +409,8 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp /// protected override Expression VisitExtension(Expression extensionExpression) { + Check.NotNull(extensionExpression, nameof(extensionExpression)); + switch (extensionExpression) { case EntityShaperExpression entityShaperExpression: @@ -465,6 +473,8 @@ protected override Expression VisitExtension(Expression extensionExpression) /// protected override Expression VisitNew(NewExpression newExpression) { + Check.NotNull(newExpression, nameof(newExpression)); + if (newExpression.Arguments.Count == 0) { return newExpression; @@ -508,6 +518,8 @@ protected override Expression VisitNew(NewExpression newExpression) /// protected override Expression VisitMemberInit(MemberInitExpression memberInitExpression) { + Check.NotNull(memberInitExpression, nameof(memberInitExpression)); + var newExpression = Visit(memberInitExpression.NewExpression); if (newExpression == null) { diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitor.cs index 160ed866281..9e31067ebc3 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitor.cs @@ -11,6 +11,7 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal { @@ -35,10 +36,10 @@ public class CosmosQueryableMethodTranslatingExpressionVisitor : QueryableMethod /// public CosmosQueryableMethodTranslatingExpressionVisitor( [NotNull] QueryableMethodTranslatingExpressionVisitorDependencies dependencies, - IModel model, - ISqlExpressionFactory sqlExpressionFactory, - IMemberTranslatorProvider memberTranslatorProvider, - IMethodCallTranslatorProvider methodCallTranslatorProvider) + [NotNull] IModel model, + [NotNull] ISqlExpressionFactory sqlExpressionFactory, + [NotNull] IMemberTranslatorProvider memberTranslatorProvider, + [NotNull] IMethodCallTranslatorProvider methodCallTranslatorProvider) : base(dependencies, subquery: false) { _model = model; @@ -58,7 +59,7 @@ public CosmosQueryableMethodTranslatingExpressionVisitor( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// protected CosmosQueryableMethodTranslatingExpressionVisitor( - CosmosQueryableMethodTranslatingExpressionVisitor parentVisitor) + [NotNull] CosmosQueryableMethodTranslatingExpressionVisitor parentVisitor) : base(parentVisitor.Dependencies, subquery: true) { _model = parentVisitor._model; @@ -84,6 +85,8 @@ protected override QueryableMethodTranslatingExpressionVisitor CreateSubqueryVis /// public override ShapedQueryExpression TranslateSubquery(Expression expression) { + Check.NotNull(expression, nameof(expression)); + throw new InvalidOperationException(CoreStrings.TranslationFailed(expression.Print())); } @@ -95,6 +98,8 @@ public override ShapedQueryExpression TranslateSubquery(Expression expression) /// protected override ShapedQueryExpression CreateShapedQueryExpression(Type elementType) { + Check.NotNull(elementType, nameof(elementType)); + var entityType = _model.FindEntityType(elementType); var selectExpression = _sqlExpressionFactory.Select(entityType); @@ -115,7 +120,13 @@ protected override ShapedQueryExpression CreateShapedQueryExpression(Type elemen /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateAll(ShapedQueryExpression source, LambdaExpression predicate) => null; + protected override ShapedQueryExpression TranslateAll(ShapedQueryExpression source, LambdaExpression predicate) + { + Check.NotNull(source, nameof(source)); + Check.NotNull(predicate, nameof(predicate)); + + return null; + } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -123,7 +134,13 @@ protected override ShapedQueryExpression CreateShapedQueryExpression(Type elemen /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateAny(ShapedQueryExpression source, LambdaExpression predicate) => null; + protected override ShapedQueryExpression TranslateAny(ShapedQueryExpression source, LambdaExpression predicate) + { + Check.NotNull(source, nameof(source)); + Check.NotNull(predicate, nameof(predicate)); + + return null; + } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -133,6 +150,9 @@ protected override ShapedQueryExpression CreateShapedQueryExpression(Type elemen /// protected override ShapedQueryExpression TranslateAverage(ShapedQueryExpression source, LambdaExpression selector, Type resultType) { + Check.NotNull(source, nameof(source)); + Check.NotNull(resultType, nameof(resultType)); + var selectExpression = (SelectExpression)source.QueryExpression; if (selectExpression.IsDistinct || selectExpression.Limit != null @@ -161,6 +181,9 @@ protected override ShapedQueryExpression TranslateAverage(ShapedQueryExpression /// protected override ShapedQueryExpression TranslateCast(ShapedQueryExpression source, Type resultType) { + Check.NotNull(source, nameof(source)); + Check.NotNull(resultType, nameof(resultType)); + if (source.ShaperExpression.Type == resultType) { return source; @@ -179,6 +202,9 @@ protected override ShapedQueryExpression TranslateCast(ShapedQueryExpression sou /// protected override ShapedQueryExpression TranslateConcat(ShapedQueryExpression source1, ShapedQueryExpression source2) { + Check.NotNull(source1, nameof(source1)); + Check.NotNull(source2, nameof(source2)); + return null; } @@ -190,6 +216,9 @@ protected override ShapedQueryExpression TranslateConcat(ShapedQueryExpression s /// protected override ShapedQueryExpression TranslateContains(ShapedQueryExpression source, Expression item) { + Check.NotNull(source, nameof(source)); + Check.NotNull(item, nameof(item)); + return null; } @@ -201,6 +230,8 @@ protected override ShapedQueryExpression TranslateContains(ShapedQueryExpression /// protected override ShapedQueryExpression TranslateCount(ShapedQueryExpression source, LambdaExpression predicate) { + Check.NotNull(source, nameof(source)); + var selectExpression = (SelectExpression)source.QueryExpression; if (selectExpression.IsDistinct || selectExpression.Limit != null @@ -238,6 +269,8 @@ protected override ShapedQueryExpression TranslateCount(ShapedQueryExpression so /// protected override ShapedQueryExpression TranslateDefaultIfEmpty(ShapedQueryExpression source, Expression defaultValue) { + Check.NotNull(source, nameof(source)); + return null; } @@ -249,6 +282,8 @@ protected override ShapedQueryExpression TranslateDefaultIfEmpty(ShapedQueryExpr /// protected override ShapedQueryExpression TranslateDistinct(ShapedQueryExpression source) { + Check.NotNull(source, nameof(source)); + ((SelectExpression)source.QueryExpression).ApplyDistinct(); return source; @@ -263,6 +298,9 @@ protected override ShapedQueryExpression TranslateDistinct(ShapedQueryExpression protected override ShapedQueryExpression TranslateElementAtOrDefault( ShapedQueryExpression source, Expression index, bool returnDefault) { + Check.NotNull(source, nameof(source)); + Check.NotNull(index, nameof(index)); + return null; } @@ -274,6 +312,9 @@ protected override ShapedQueryExpression TranslateElementAtOrDefault( /// protected override ShapedQueryExpression TranslateExcept(ShapedQueryExpression source1, ShapedQueryExpression source2) { + Check.NotNull(source1, nameof(source1)); + Check.NotNull(source2, nameof(source2)); + return null; } @@ -286,6 +327,9 @@ protected override ShapedQueryExpression TranslateExcept(ShapedQueryExpression s protected override ShapedQueryExpression TranslateFirstOrDefault( ShapedQueryExpression source, LambdaExpression predicate, Type returnType, bool returnDefault) { + Check.NotNull(source, nameof(source)); + Check.NotNull(returnType, nameof(returnType)); + if (predicate != null) { source = TranslateWhere(source, predicate); @@ -313,8 +357,14 @@ protected override ShapedQueryExpression TranslateFirstOrDefault( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// protected override ShapedQueryExpression TranslateGroupBy( - ShapedQueryExpression source, LambdaExpression keySelector, LambdaExpression elementSelector, LambdaExpression resultSelector) + ShapedQueryExpression source, + LambdaExpression keySelector, + LambdaExpression elementSelector, + LambdaExpression resultSelector) { + Check.NotNull(source, nameof(source)); + Check.NotNull(keySelector, nameof(keySelector)); + return null; } @@ -325,9 +375,18 @@ protected override ShapedQueryExpression TranslateGroupBy( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// protected override ShapedQueryExpression TranslateGroupJoin( - ShapedQueryExpression outer, ShapedQueryExpression inner, LambdaExpression outerKeySelector, LambdaExpression innerKeySelector, + ShapedQueryExpression outer, + ShapedQueryExpression inner, + LambdaExpression outerKeySelector, + LambdaExpression innerKeySelector, LambdaExpression resultSelector) { + Check.NotNull(outer, nameof(outer)); + Check.NotNull(inner, nameof(inner)); + Check.NotNull(outerKeySelector, nameof(outerKeySelector)); + Check.NotNull(innerKeySelector, nameof(innerKeySelector)); + Check.NotNull(resultSelector, nameof(resultSelector)); + return null; } @@ -339,6 +398,9 @@ protected override ShapedQueryExpression TranslateGroupJoin( /// protected override ShapedQueryExpression TranslateIntersect(ShapedQueryExpression source1, ShapedQueryExpression source2) { + Check.NotNull(source1, nameof(source1)); + Check.NotNull(source2, nameof(source2)); + return null; } @@ -349,9 +411,16 @@ protected override ShapedQueryExpression TranslateIntersect(ShapedQueryExpressio /// doing so can result in application failures when updating to a new Entity Framework Core release. /// protected override ShapedQueryExpression TranslateJoin( - ShapedQueryExpression outer, ShapedQueryExpression inner, LambdaExpression outerKeySelector, LambdaExpression innerKeySelector, + ShapedQueryExpression outer, + ShapedQueryExpression inner, + LambdaExpression outerKeySelector, + LambdaExpression innerKeySelector, LambdaExpression resultSelector) { + Check.NotNull(outer, nameof(outer)); + Check.NotNull(inner, nameof(inner)); + Check.NotNull(resultSelector, nameof(resultSelector)); + return null; } @@ -364,6 +433,9 @@ protected override ShapedQueryExpression TranslateJoin( protected override ShapedQueryExpression TranslateLastOrDefault( ShapedQueryExpression source, LambdaExpression predicate, Type returnType, bool returnDefault) { + Check.NotNull(source, nameof(source)); + Check.NotNull(returnType, nameof(returnType)); + if (predicate != null) { source = TranslateWhere(source, predicate); @@ -392,9 +464,16 @@ protected override ShapedQueryExpression TranslateLastOrDefault( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// protected override ShapedQueryExpression TranslateLeftJoin( - ShapedQueryExpression outer, ShapedQueryExpression inner, LambdaExpression outerKeySelector, LambdaExpression innerKeySelector, + ShapedQueryExpression outer, + ShapedQueryExpression inner, + LambdaExpression outerKeySelector, + LambdaExpression innerKeySelector, LambdaExpression resultSelector) { + Check.NotNull(outer, nameof(outer)); + Check.NotNull(inner, nameof(inner)); + Check.NotNull(resultSelector, nameof(resultSelector)); + return null; } @@ -406,6 +485,8 @@ protected override ShapedQueryExpression TranslateLeftJoin( /// protected override ShapedQueryExpression TranslateLongCount(ShapedQueryExpression source, LambdaExpression predicate) { + Check.NotNull(source, nameof(source)); + var selectExpression = (SelectExpression)source.QueryExpression; if (selectExpression.IsDistinct || selectExpression.Limit != null @@ -442,6 +523,8 @@ protected override ShapedQueryExpression TranslateLongCount(ShapedQueryExpressio /// protected override ShapedQueryExpression TranslateMax(ShapedQueryExpression source, LambdaExpression selector, Type resultType) { + Check.NotNull(source, nameof(source)); + var selectExpression = (SelectExpression)source.QueryExpression; if (selectExpression.IsDistinct || selectExpression.Limit != null @@ -470,6 +553,8 @@ protected override ShapedQueryExpression TranslateMax(ShapedQueryExpression sour /// protected override ShapedQueryExpression TranslateMin(ShapedQueryExpression source, LambdaExpression selector, Type resultType) { + Check.NotNull(source, nameof(source)); + var selectExpression = (SelectExpression)source.QueryExpression; if (selectExpression.IsDistinct || selectExpression.Limit != null @@ -498,6 +583,9 @@ protected override ShapedQueryExpression TranslateMin(ShapedQueryExpression sour /// protected override ShapedQueryExpression TranslateOfType(ShapedQueryExpression source, Type resultType) { + Check.NotNull(source, nameof(source)); + Check.NotNull(resultType, nameof(resultType)); + return null; } @@ -510,6 +598,9 @@ protected override ShapedQueryExpression TranslateOfType(ShapedQueryExpression s protected override ShapedQueryExpression TranslateOrderBy( ShapedQueryExpression source, LambdaExpression keySelector, bool ascending) { + Check.NotNull(source, nameof(source)); + Check.NotNull(keySelector, nameof(keySelector)); + var translation = TranslateLambdaExpression(source, keySelector); if (translation != null) { @@ -529,6 +620,8 @@ protected override ShapedQueryExpression TranslateOrderBy( /// protected override ShapedQueryExpression TranslateReverse(ShapedQueryExpression source) { + Check.NotNull(source, nameof(source)); + return null; } @@ -540,6 +633,9 @@ protected override ShapedQueryExpression TranslateReverse(ShapedQueryExpression /// protected override ShapedQueryExpression TranslateSelect(ShapedQueryExpression source, LambdaExpression selector) { + Check.NotNull(source, nameof(source)); + Check.NotNull(selector, nameof(selector)); + if (selector.Body == selector.Parameters[0]) { return source; @@ -568,6 +664,10 @@ protected override ShapedQueryExpression TranslateSelect(ShapedQueryExpression s protected override ShapedQueryExpression TranslateSelectMany( ShapedQueryExpression source, LambdaExpression collectionSelector, LambdaExpression resultSelector) { + Check.NotNull(source, nameof(source)); + Check.NotNull(collectionSelector, nameof(collectionSelector)); + Check.NotNull(resultSelector, nameof(resultSelector)); + return null; } @@ -579,6 +679,9 @@ protected override ShapedQueryExpression TranslateSelectMany( /// protected override ShapedQueryExpression TranslateSelectMany(ShapedQueryExpression source, LambdaExpression selector) { + Check.NotNull(source, nameof(source)); + Check.NotNull(selector, nameof(selector)); + return null; } @@ -591,6 +694,9 @@ protected override ShapedQueryExpression TranslateSelectMany(ShapedQueryExpressi protected override ShapedQueryExpression TranslateSingleOrDefault( ShapedQueryExpression source, LambdaExpression predicate, Type returnType, bool returnDefault) { + Check.NotNull(source, nameof(source)); + Check.NotNull(returnType, nameof(returnType)); + if (predicate != null) { source = TranslateWhere(source, predicate); @@ -619,6 +725,9 @@ protected override ShapedQueryExpression TranslateSingleOrDefault( /// protected override ShapedQueryExpression TranslateSkip(ShapedQueryExpression source, Expression count) { + Check.NotNull(source, nameof(source)); + Check.NotNull(count, nameof(count)); + var selectExpression = (SelectExpression)source.QueryExpression; var translation = TranslateExpression(count); @@ -640,6 +749,9 @@ protected override ShapedQueryExpression TranslateSkip(ShapedQueryExpression sou /// protected override ShapedQueryExpression TranslateSkipWhile(ShapedQueryExpression source, LambdaExpression predicate) { + Check.NotNull(source, nameof(source)); + Check.NotNull(predicate, nameof(predicate)); + return null; } @@ -651,6 +763,9 @@ protected override ShapedQueryExpression TranslateSkipWhile(ShapedQueryExpressio /// protected override ShapedQueryExpression TranslateSum(ShapedQueryExpression source, LambdaExpression selector, Type resultType) { + Check.NotNull(source, nameof(source)); + Check.NotNull(resultType, nameof(resultType)); + var selectExpression = (SelectExpression)source.QueryExpression; if (selectExpression.IsDistinct || selectExpression.Limit != null @@ -681,6 +796,9 @@ protected override ShapedQueryExpression TranslateSum(ShapedQueryExpression sour /// protected override ShapedQueryExpression TranslateTake(ShapedQueryExpression source, Expression count) { + Check.NotNull(source, nameof(source)); + Check.NotNull(count, nameof(count)); + var selectExpression = (SelectExpression)source.QueryExpression; var translation = TranslateExpression(count); @@ -702,6 +820,9 @@ protected override ShapedQueryExpression TranslateTake(ShapedQueryExpression sou /// protected override ShapedQueryExpression TranslateTakeWhile(ShapedQueryExpression source, LambdaExpression predicate) { + Check.NotNull(source, nameof(source)); + Check.NotNull(predicate, nameof(predicate)); + return null; } @@ -713,6 +834,9 @@ protected override ShapedQueryExpression TranslateTakeWhile(ShapedQueryExpressio /// protected override ShapedQueryExpression TranslateThenBy(ShapedQueryExpression source, LambdaExpression keySelector, bool ascending) { + Check.NotNull(source, nameof(source)); + Check.NotNull(keySelector, nameof(keySelector)); + var translation = TranslateLambdaExpression(source, keySelector); if (translation != null) { @@ -732,6 +856,9 @@ protected override ShapedQueryExpression TranslateThenBy(ShapedQueryExpression s /// protected override ShapedQueryExpression TranslateUnion(ShapedQueryExpression source1, ShapedQueryExpression source2) { + Check.NotNull(source1, nameof(source1)); + Check.NotNull(source2, nameof(source2)); + return null; } @@ -743,6 +870,9 @@ protected override ShapedQueryExpression TranslateUnion(ShapedQueryExpression so /// protected override ShapedQueryExpression TranslateWhere(ShapedQueryExpression source, LambdaExpression predicate) { + Check.NotNull(source, nameof(source)); + Check.NotNull(predicate, nameof(predicate)); + var translation = TranslateLambdaExpression(source, predicate); if (translation != null) { diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitorFactory.cs b/src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitorFactory.cs index 393ef1c2bdc..c3899e9fc4c 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitorFactory.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitorFactory.cs @@ -4,6 +4,7 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal @@ -36,9 +37,9 @@ public class CosmosQueryableMethodTranslatingExpressionVisitorFactory : IQueryab /// public CosmosQueryableMethodTranslatingExpressionVisitorFactory( [NotNull] QueryableMethodTranslatingExpressionVisitorDependencies dependencies, - ISqlExpressionFactory sqlExpressionFactory, - IMemberTranslatorProvider memberTranslatorProvider, - IMethodCallTranslatorProvider methodCallTranslatorProvider) + [NotNull] ISqlExpressionFactory sqlExpressionFactory, + [NotNull] IMemberTranslatorProvider memberTranslatorProvider, + [NotNull] IMethodCallTranslatorProvider methodCallTranslatorProvider) { _dependencies = dependencies; _sqlExpressionFactory = sqlExpressionFactory; @@ -54,6 +55,8 @@ public CosmosQueryableMethodTranslatingExpressionVisitorFactory( /// public virtual QueryableMethodTranslatingExpressionVisitor Create(IModel model) { + Check.NotNull(model, nameof(model)); + return new CosmosQueryableMethodTranslatingExpressionVisitor( _dependencies, model, diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.CosmosProjectionBindingRemovingExpressionVisitor.cs b/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.CosmosProjectionBindingRemovingExpressionVisitor.cs index 76d165e6d34..7be78204824 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.CosmosProjectionBindingRemovingExpressionVisitor.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.CosmosProjectionBindingRemovingExpressionVisitor.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Linq.Expressions; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.ChangeTracking.Internal; using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal; using Microsoft.EntityFrameworkCore.Diagnostics; @@ -15,6 +16,7 @@ using Microsoft.EntityFrameworkCore.Metadata.Conventions; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; using Newtonsoft.Json.Linq; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal @@ -68,8 +70,8 @@ private List _pendingIncludes = new List(); public CosmosProjectionBindingRemovingExpressionVisitor( - SelectExpression selectExpression, - ParameterExpression jObjectParameter, + [NotNull] SelectExpression selectExpression, + [NotNull] ParameterExpression jObjectParameter, bool trackQueryResults) { _selectExpression = selectExpression; @@ -79,6 +81,8 @@ public CosmosProjectionBindingRemovingExpressionVisitor( protected override Expression VisitBinary(BinaryExpression binaryExpression) { + Check.NotNull(binaryExpression, nameof(binaryExpression)); + if (binaryExpression.NodeType == ExpressionType.Assign) { if (binaryExpression.Left is ParameterExpression parameterExpression) @@ -178,6 +182,8 @@ protected override Expression VisitBinary(BinaryExpression binaryExpression) protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { + Check.NotNull(methodCallExpression, nameof(methodCallExpression)); + var method = methodCallExpression.Method; var genericMethod = method.IsGenericMethod ? method.GetGenericMethodDefinition() : null; if (genericMethod == EntityMaterializerSource.TryReadValueMethod) @@ -227,6 +233,8 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp protected override Expression VisitExtension(Expression extensionExpression) { + Check.NotNull(extensionExpression, nameof(extensionExpression)); + switch (extensionExpression) { case ProjectionBindingExpression projectionBindingExpression: diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.JObjectInjectingExpressionVisitor.cs b/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.JObjectInjectingExpressionVisitor.cs index 633b5a95990..ede96e56a1a 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.JObjectInjectingExpressionVisitor.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.JObjectInjectingExpressionVisitor.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Utilities; using Newtonsoft.Json.Linq; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal @@ -16,6 +17,8 @@ private sealed class JObjectInjectingExpressionVisitor : ExpressionVisitor protected override Expression VisitExtension(Expression extensionExpression) { + Check.NotNull(extensionExpression, nameof(extensionExpression)); + switch (extensionExpression) { case EntityShaperExpression shaperExpression: diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.cs b/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.cs index 0fddf13c0a8..525add50e3b 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.cs @@ -3,8 +3,10 @@ using System; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Utilities; using Newtonsoft.Json.Linq; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal @@ -29,10 +31,10 @@ public partial class CosmosShapedQueryCompilingExpressionVisitor : ShapedQueryCo /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public CosmosShapedQueryCompilingExpressionVisitor( - ShapedQueryCompilingExpressionVisitorDependencies dependencies, - QueryCompilationContext queryCompilationContext, - ISqlExpressionFactory sqlExpressionFactory, - IQuerySqlGeneratorFactory querySqlGeneratorFactory) + [NotNull] ShapedQueryCompilingExpressionVisitorDependencies dependencies, + [NotNull] QueryCompilationContext queryCompilationContext, + [NotNull] ISqlExpressionFactory sqlExpressionFactory, + [NotNull] IQuerySqlGeneratorFactory querySqlGeneratorFactory) : base(dependencies, queryCompilationContext) { _sqlExpressionFactory = sqlExpressionFactory; @@ -49,6 +51,8 @@ public CosmosShapedQueryCompilingExpressionVisitor( /// protected override Expression VisitShapedQueryExpression(ShapedQueryExpression shapedQueryExpression) { + Check.NotNull(shapedQueryExpression, nameof(shapedQueryExpression)); + var selectExpression = (SelectExpression)shapedQueryExpression.QueryExpression; selectExpression.ApplyProjection(); var jObjectParameter = Expression.Parameter(typeof(JObject), "jObject"); diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitorFactory.cs b/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitorFactory.cs index e65e5ad1ef0..761e4b2c6de 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitorFactory.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitorFactory.cs @@ -1,7 +1,9 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal { @@ -24,9 +26,9 @@ public class CosmosShapedQueryCompilingExpressionVisitorFactory : IShapedQueryCo /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public CosmosShapedQueryCompilingExpressionVisitorFactory( - ShapedQueryCompilingExpressionVisitorDependencies dependencies, - ISqlExpressionFactory sqlExpressionFactory, - IQuerySqlGeneratorFactory querySqlGeneratorFactory) + [NotNull] ShapedQueryCompilingExpressionVisitorDependencies dependencies, + [NotNull] ISqlExpressionFactory sqlExpressionFactory, + [NotNull] IQuerySqlGeneratorFactory querySqlGeneratorFactory) { _dependencies = dependencies; _sqlExpressionFactory = sqlExpressionFactory; @@ -40,10 +42,14 @@ public CosmosShapedQueryCompilingExpressionVisitorFactory( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual ShapedQueryCompilingExpressionVisitor Create(QueryCompilationContext queryCompilationContext) - => new CosmosShapedQueryCompilingExpressionVisitor( + { + Check.NotNull(queryCompilationContext, nameof(queryCompilationContext)); + + return new CosmosShapedQueryCompilingExpressionVisitor( _dependencies, queryCompilationContext, _sqlExpressionFactory, _querySqlGeneratorFactory); + } } } diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosSqlTranslatingExpressionVisitor.cs b/src/EFCore.Cosmos/Query/Internal/CosmosSqlTranslatingExpressionVisitor.cs index 64a7b5c3c99..94637bf4aad 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosSqlTranslatingExpressionVisitor.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosSqlTranslatingExpressionVisitor.cs @@ -5,9 +5,11 @@ using System.Diagnostics; using System.Linq; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal { @@ -32,10 +34,10 @@ public class CosmosSqlTranslatingExpressionVisitor : ExpressionVisitor /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public CosmosSqlTranslatingExpressionVisitor( - IModel model, - ISqlExpressionFactory sqlExpressionFactory, - IMemberTranslatorProvider memberTranslatorProvider, - IMethodCallTranslatorProvider methodCallTranslatorProvider) + [NotNull] IModel model, + [NotNull] ISqlExpressionFactory sqlExpressionFactory, + [NotNull] IMemberTranslatorProvider memberTranslatorProvider, + [NotNull] IMethodCallTranslatorProvider methodCallTranslatorProvider) { _model = model; _sqlExpressionFactory = sqlExpressionFactory; @@ -50,7 +52,7 @@ public CosmosSqlTranslatingExpressionVisitor( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate(Expression expression) + public virtual SqlExpression Translate([NotNull] Expression expression) { var result = Visit(expression); @@ -78,6 +80,8 @@ private sealed class SqlTypeMappingVerifyingExpressionVisitor : ExpressionVisito { protected override Expression VisitExtension(Expression node) { + Check.NotNull(node, nameof(node)); + if (node is SqlExpression sqlExpression && sqlExpression.TypeMapping == null) { @@ -95,11 +99,15 @@ protected override Expression VisitExtension(Expression node) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// protected override Expression VisitMember(MemberExpression memberExpression) - => TryBindMember(memberExpression.Expression, MemberIdentity.Create(memberExpression.Member), out var result) + { + Check.NotNull(memberExpression, nameof(memberExpression)); + + return TryBindMember(memberExpression.Expression, MemberIdentity.Create(memberExpression.Member), out var result) ? result : TranslationFailed(memberExpression.Expression, Visit(memberExpression.Expression), out var sqlInnerExpression) ? null : _memberTranslatorProvider.Translate(sqlInnerExpression, memberExpression.Member, memberExpression.Type); + } private bool TryBindMember(Expression source, MemberIdentity member, out Expression expression) { @@ -147,6 +155,8 @@ when methodCallExpression.TryGetEFPropertyArguments(out var innerSource, out var /// protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { + Check.NotNull(methodCallExpression, nameof(methodCallExpression)); + if (methodCallExpression.TryGetEFPropertyArguments(out var source, out var propertyName)) { return TryBindMember(source, MemberIdentity.Create(propertyName), out var result) @@ -211,6 +221,8 @@ private static Expression TryRemoveImplicitConvert(Expression expression) /// protected override Expression VisitBinary(BinaryExpression binaryExpression) { + Check.NotNull(binaryExpression, nameof(binaryExpression)); + if (binaryExpression.NodeType == ExpressionType.Coalesce) { return Visit( @@ -244,6 +256,8 @@ protected override Expression VisitBinary(BinaryExpression binaryExpression) /// protected override Expression VisitConditional(ConditionalExpression conditionalExpression) { + Check.NotNull(conditionalExpression, nameof(conditionalExpression)); + var test = Visit(conditionalExpression.Test); var ifTrue = Visit(conditionalExpression.IfTrue); var ifFalse = Visit(conditionalExpression.IfFalse); @@ -263,6 +277,8 @@ protected override Expression VisitConditional(ConditionalExpression conditional /// protected override Expression VisitUnary(UnaryExpression unaryExpression) { + Check.NotNull(unaryExpression, nameof(unaryExpression)); + var operand = Visit(unaryExpression.Operand); if (TranslationFailed(unaryExpression.Operand, operand, out var sqlOperand)) @@ -333,7 +349,12 @@ private static bool CanEvaluate(Expression expression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override Expression VisitNew(NewExpression node) => GetConstantOrNull(node); + protected override Expression VisitNew(NewExpression node) + { + Check.NotNull(node, nameof(node)); + + return GetConstantOrNull(node); + } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -341,7 +362,12 @@ private static bool CanEvaluate(Expression expression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override Expression VisitMemberInit(MemberInitExpression node) => GetConstantOrNull(node); + protected override Expression VisitMemberInit(MemberInitExpression node) + { + Check.NotNull(node, nameof(node)); + + return GetConstantOrNull(node); + } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -349,7 +375,12 @@ private static bool CanEvaluate(Expression expression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override Expression VisitNewArray(NewArrayExpression node) => null; + protected override Expression VisitNewArray(NewArrayExpression node) + { + Check.NotNull(node, nameof(node)); + + return null; + } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -357,7 +388,12 @@ private static bool CanEvaluate(Expression expression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override Expression VisitListInit(ListInitExpression node) => null; + protected override Expression VisitListInit(ListInitExpression node) + { + Check.NotNull(node, nameof(node)); + + return null; + } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -365,7 +401,12 @@ private static bool CanEvaluate(Expression expression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override Expression VisitInvocation(InvocationExpression node) => null; + protected override Expression VisitInvocation(InvocationExpression node) + { + Check.NotNull(node, nameof(node)); + + return null; + } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -373,7 +414,12 @@ private static bool CanEvaluate(Expression expression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override Expression VisitLambda(Expression node) => null; + protected override Expression VisitLambda(Expression node) + { + Check.NotNull(node, nameof(node)); + + return null; + } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -382,7 +428,11 @@ private static bool CanEvaluate(Expression expression) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// protected override Expression VisitConstant(ConstantExpression constantExpression) - => new SqlConstantExpression(constantExpression, null); + { + Check.NotNull(constantExpression, nameof(constantExpression)); + + return new SqlConstantExpression(constantExpression, null); + } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -391,7 +441,11 @@ protected override Expression VisitConstant(ConstantExpression constantExpressio /// doing so can result in application failures when updating to a new Entity Framework Core release. /// protected override Expression VisitParameter(ParameterExpression parameterExpression) - => new SqlParameterExpression(parameterExpression, null); + { + Check.NotNull(parameterExpression, nameof(parameterExpression)); + + return new SqlParameterExpression(parameterExpression, null); + } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -401,6 +455,8 @@ protected override Expression VisitParameter(ParameterExpression parameterExpres /// protected override Expression VisitExtension(Expression extensionExpression) { + Check.NotNull(extensionExpression, nameof(extensionExpression)); + switch (extensionExpression) { case EntityProjectionExpression _: diff --git a/src/EFCore.Cosmos/Query/Internal/EntityProjectionExpression.cs b/src/EFCore.Cosmos/Query/Internal/EntityProjectionExpression.cs index c753b50a386..8607565da0d 100644 --- a/src/EFCore.Cosmos/Query/Internal/EntityProjectionExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/EntityProjectionExpression.cs @@ -6,8 +6,10 @@ using System.Linq; using System.Linq.Expressions; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal { @@ -31,7 +33,7 @@ private readonly IDictionary _navigationExpressi /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public EntityProjectionExpression(IEntityType entityType, Expression accessExpression) + public EntityProjectionExpression([NotNull] IEntityType entityType, [NotNull] Expression accessExpression) { EntityType = entityType; AccessExpression = accessExpression; @@ -86,6 +88,8 @@ public EntityProjectionExpression(IEntityType entityType, Expression accessExpre /// protected override Expression VisitChildren(ExpressionVisitor visitor) { + Check.NotNull(visitor, nameof(visitor)); + var accessExpression = visitor.Visit(AccessExpression); return accessExpression != AccessExpression @@ -99,7 +103,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual Expression BindProperty(IProperty property, bool clientEval) + public virtual Expression BindProperty([NotNull] IProperty property, bool clientEval) { if (!EntityType.IsAssignableFrom(property.DeclaringEntityType) && !property.DeclaringEntityType.IsAssignableFrom(EntityType)) @@ -130,7 +134,7 @@ public virtual Expression BindProperty(IProperty property, bool clientEval) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual Expression BindNavigation(INavigation navigation, bool clientEval) + public virtual Expression BindNavigation([NotNull] INavigation navigation, bool clientEval) { if (!EntityType.IsAssignableFrom(navigation.DeclaringEntityType) && !navigation.DeclaringEntityType.IsAssignableFrom(EntityType)) @@ -171,7 +175,8 @@ public virtual Expression BindNavigation(INavigation navigation, bool clientEval /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual Expression BindMember(string name, Type entityClrType, bool clientEval, out IPropertyBase propertyBase) + public virtual Expression BindMember( + [NotNull] string name, [NotNull] Type entityClrType, bool clientEval, [NotNull] out IPropertyBase propertyBase) => BindMember(MemberIdentity.Create(name), entityClrType, clientEval, out propertyBase); /// @@ -181,7 +186,7 @@ public virtual Expression BindMember(string name, Type entityClrType, bool clien /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual Expression BindMember( - MemberInfo memberInfo, Type entityClrType, bool clientEval, out IPropertyBase propertyBase) + [NotNull] MemberInfo memberInfo, [NotNull] Type entityClrType, bool clientEval, [NotNull] out IPropertyBase propertyBase) => BindMember(MemberIdentity.Create(memberInfo), entityClrType, clientEval, out propertyBase); private Expression BindMember(MemberIdentity member, Type entityClrType, bool clientEval, out IPropertyBase propertyBase) @@ -223,7 +228,11 @@ private Expression BindMember(MemberIdentity member, Type entityClrType, bool cl /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual void Print(ExpressionPrinter expressionPrinter) - => expressionPrinter.Visit(AccessExpression); + { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + + expressionPrinter.Visit(AccessExpression); + } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.Cosmos/Query/Internal/EqualsTranslator.cs b/src/EFCore.Cosmos/Query/Internal/EqualsTranslator.cs index 276f28b6f40..a9c34364e6e 100644 --- a/src/EFCore.Cosmos/Query/Internal/EqualsTranslator.cs +++ b/src/EFCore.Cosmos/Query/Internal/EqualsTranslator.cs @@ -5,6 +5,8 @@ using System.Collections.Generic; using System.Linq.Expressions; using System.Reflection; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal { @@ -24,7 +26,7 @@ public class EqualsTranslator : IMethodCallTranslator /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public EqualsTranslator(ISqlExpressionFactory sqlExpressionFactory) + public EqualsTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } @@ -37,6 +39,9 @@ public EqualsTranslator(ISqlExpressionFactory sqlExpressionFactory) /// public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { + Check.NotNull(method, nameof(method)); + Check.NotNull(arguments, nameof(arguments)); + SqlExpression left = null; SqlExpression right = null; diff --git a/src/EFCore.Cosmos/Query/Internal/ExpressionExtensions.cs b/src/EFCore.Cosmos/Query/Internal/ExpressionExtensions.cs index 3ab2e4d20d2..e30714d09a6 100644 --- a/src/EFCore.Cosmos/Query/Internal/ExpressionExtensions.cs +++ b/src/EFCore.Cosmos/Query/Internal/ExpressionExtensions.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Storage; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal @@ -20,7 +21,7 @@ public static class ExpressionExtensions /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public static CoreTypeMapping InferTypeMapping(params Expression[] expressions) + public static CoreTypeMapping InferTypeMapping([NotNull] params Expression[] expressions) { for (var i = 0; i < expressions.Length; i++) { diff --git a/src/EFCore.Cosmos/Query/Internal/IMemberTranslator.cs b/src/EFCore.Cosmos/Query/Internal/IMemberTranslator.cs index 92754ca5b75..be1070559f8 100644 --- a/src/EFCore.Cosmos/Query/Internal/IMemberTranslator.cs +++ b/src/EFCore.Cosmos/Query/Internal/IMemberTranslator.cs @@ -3,6 +3,7 @@ using System; using System.Reflection; +using JetBrains.Annotations; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal { @@ -20,6 +21,6 @@ public interface IMemberTranslator /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType); + SqlExpression Translate([NotNull] SqlExpression instance, [NotNull] MemberInfo member, [NotNull] Type returnType); } } diff --git a/src/EFCore.Cosmos/Query/Internal/IMemberTranslatorProvider.cs b/src/EFCore.Cosmos/Query/Internal/IMemberTranslatorProvider.cs index 3a4444fe9ec..2f92117be5f 100644 --- a/src/EFCore.Cosmos/Query/Internal/IMemberTranslatorProvider.cs +++ b/src/EFCore.Cosmos/Query/Internal/IMemberTranslatorProvider.cs @@ -3,6 +3,7 @@ using System; using System.Reflection; +using JetBrains.Annotations; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal { @@ -20,6 +21,6 @@ public interface IMemberTranslatorProvider /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType); + SqlExpression Translate([NotNull] SqlExpression instance, [NotNull] MemberInfo member, [NotNull] Type returnType); } } diff --git a/src/EFCore.Cosmos/Query/Internal/IMethodCallTranslator.cs b/src/EFCore.Cosmos/Query/Internal/IMethodCallTranslator.cs index ba0e1e9223d..00aafb3c7a0 100644 --- a/src/EFCore.Cosmos/Query/Internal/IMethodCallTranslator.cs +++ b/src/EFCore.Cosmos/Query/Internal/IMethodCallTranslator.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Reflection; +using JetBrains.Annotations; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal { @@ -20,6 +21,7 @@ public interface IMethodCallTranslator /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments); + SqlExpression Translate( + [CanBeNull] SqlExpression instance, [NotNull] MethodInfo method, [NotNull] IReadOnlyList arguments); } } diff --git a/src/EFCore.Cosmos/Query/Internal/IMethodCallTranslatorProvider.cs b/src/EFCore.Cosmos/Query/Internal/IMethodCallTranslatorProvider.cs index 4f7a88abf6e..dcdcf043986 100644 --- a/src/EFCore.Cosmos/Query/Internal/IMethodCallTranslatorProvider.cs +++ b/src/EFCore.Cosmos/Query/Internal/IMethodCallTranslatorProvider.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal @@ -21,6 +22,10 @@ public interface IMethodCallTranslatorProvider /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - SqlExpression Translate(IModel model, SqlExpression instance, MethodInfo method, IReadOnlyList arguments); + SqlExpression Translate( + [NotNull] IModel model, + [CanBeNull] SqlExpression instance, + [NotNull] MethodInfo method, + [NotNull] IReadOnlyList arguments); } } diff --git a/src/EFCore.Cosmos/Query/Internal/ISqlExpressionFactory.cs b/src/EFCore.Cosmos/Query/Internal/ISqlExpressionFactory.cs index 4d937fb6344..598142f9561 100644 --- a/src/EFCore.Cosmos/Query/Internal/ISqlExpressionFactory.cs +++ b/src/EFCore.Cosmos/Query/Internal/ISqlExpressionFactory.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Storage; @@ -23,7 +24,7 @@ public interface ISqlExpressionFactory /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - SqlExpression ApplyTypeMapping(SqlExpression sqlExpression, CoreTypeMapping typeMapping); + SqlExpression ApplyTypeMapping([CanBeNull] SqlExpression sqlExpression, [NotNull] CoreTypeMapping typeMapping); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -31,7 +32,7 @@ public interface ISqlExpressionFactory /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - SqlExpression ApplyDefaultTypeMapping(SqlExpression sqlExpression); + SqlExpression ApplyDefaultTypeMapping([CanBeNull] SqlExpression sqlExpression); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -39,7 +40,7 @@ public interface ISqlExpressionFactory /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - CoreTypeMapping FindMapping(Type type); + CoreTypeMapping FindMapping([NotNull] Type type); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -47,7 +48,11 @@ public interface ISqlExpressionFactory /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - SqlBinaryExpression MakeBinary(ExpressionType operatorType, SqlExpression left, SqlExpression right, CoreTypeMapping typeMapping); + SqlBinaryExpression MakeBinary( + ExpressionType operatorType, + [NotNull] SqlExpression left, + [NotNull] SqlExpression right, + [CanBeNull] CoreTypeMapping typeMapping); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -55,7 +60,7 @@ public interface ISqlExpressionFactory /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - SqlBinaryExpression Equal(SqlExpression left, SqlExpression right); + SqlBinaryExpression Equal([NotNull] SqlExpression left, [NotNull] SqlExpression right); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -63,7 +68,7 @@ public interface ISqlExpressionFactory /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - SqlBinaryExpression NotEqual(SqlExpression left, SqlExpression right); + SqlBinaryExpression NotEqual([NotNull] SqlExpression left, [NotNull] SqlExpression right); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -71,7 +76,7 @@ public interface ISqlExpressionFactory /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - SqlBinaryExpression GreaterThan(SqlExpression left, SqlExpression right); + SqlBinaryExpression GreaterThan([NotNull] SqlExpression left, [NotNull] SqlExpression right); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -79,7 +84,7 @@ public interface ISqlExpressionFactory /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - SqlBinaryExpression GreaterThanOrEqual(SqlExpression left, SqlExpression right); + SqlBinaryExpression GreaterThanOrEqual([NotNull] SqlExpression left, [NotNull] SqlExpression right); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -87,7 +92,7 @@ public interface ISqlExpressionFactory /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - SqlBinaryExpression LessThan(SqlExpression left, SqlExpression right); + SqlBinaryExpression LessThan([NotNull] SqlExpression left, [NotNull] SqlExpression right); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -95,7 +100,7 @@ public interface ISqlExpressionFactory /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - SqlBinaryExpression LessThanOrEqual(SqlExpression left, SqlExpression right); + SqlBinaryExpression LessThanOrEqual([NotNull] SqlExpression left, [NotNull] SqlExpression right); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -103,7 +108,7 @@ public interface ISqlExpressionFactory /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - SqlBinaryExpression AndAlso(SqlExpression left, SqlExpression right); + SqlBinaryExpression AndAlso([NotNull] SqlExpression left, [NotNull] SqlExpression right); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -111,7 +116,7 @@ public interface ISqlExpressionFactory /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - SqlBinaryExpression OrElse(SqlExpression left, SqlExpression right); + SqlBinaryExpression OrElse([NotNull] SqlExpression left, [NotNull] SqlExpression right); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -119,7 +124,8 @@ public interface ISqlExpressionFactory /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - SqlBinaryExpression Add(SqlExpression left, SqlExpression right, CoreTypeMapping typeMapping = null); + SqlBinaryExpression Add( + [NotNull] SqlExpression left, [NotNull] SqlExpression right, [CanBeNull] CoreTypeMapping typeMapping = null); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -127,7 +133,8 @@ public interface ISqlExpressionFactory /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - SqlBinaryExpression Subtract(SqlExpression left, SqlExpression right, CoreTypeMapping typeMapping = null); + SqlBinaryExpression Subtract( + [NotNull] SqlExpression left, [NotNull] SqlExpression right, [CanBeNull] CoreTypeMapping typeMapping = null); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -135,7 +142,8 @@ public interface ISqlExpressionFactory /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - SqlBinaryExpression Multiply(SqlExpression left, SqlExpression right, CoreTypeMapping typeMapping = null); + SqlBinaryExpression Multiply( + [NotNull] SqlExpression left, [NotNull] SqlExpression right, [CanBeNull] CoreTypeMapping typeMapping = null); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -143,7 +151,8 @@ public interface ISqlExpressionFactory /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - SqlBinaryExpression Divide(SqlExpression left, SqlExpression right, CoreTypeMapping typeMapping = null); + SqlBinaryExpression Divide( + [NotNull] SqlExpression left, [NotNull] SqlExpression right, [CanBeNull] CoreTypeMapping typeMapping = null); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -151,7 +160,8 @@ public interface ISqlExpressionFactory /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - SqlBinaryExpression Modulo(SqlExpression left, SqlExpression right, CoreTypeMapping typeMapping = null); + SqlBinaryExpression Modulo( + [NotNull] SqlExpression left, [NotNull] SqlExpression right, [CanBeNull] CoreTypeMapping typeMapping = null); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -159,7 +169,8 @@ public interface ISqlExpressionFactory /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - SqlBinaryExpression And(SqlExpression left, SqlExpression right, CoreTypeMapping typeMapping = null); + SqlBinaryExpression And( + [NotNull] SqlExpression left, [NotNull] SqlExpression right, [CanBeNull] CoreTypeMapping typeMapping = null); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -167,7 +178,8 @@ public interface ISqlExpressionFactory /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - SqlBinaryExpression Or(SqlExpression left, SqlExpression right, CoreTypeMapping typeMapping = null); + SqlBinaryExpression Or( + [NotNull] SqlExpression left, [NotNull] SqlExpression right, [CanBeNull] CoreTypeMapping typeMapping = null); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -175,7 +187,8 @@ public interface ISqlExpressionFactory /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - SqlBinaryExpression Coalesce(SqlExpression left, SqlExpression right, CoreTypeMapping typeMapping = null); + SqlBinaryExpression Coalesce( + [NotNull] SqlExpression left, [NotNull] SqlExpression right, [CanBeNull] CoreTypeMapping typeMapping = null); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -183,7 +196,7 @@ public interface ISqlExpressionFactory /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - SqlBinaryExpression IsNull(SqlExpression operand); + SqlBinaryExpression IsNull([NotNull] SqlExpression operand); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -191,7 +204,7 @@ public interface ISqlExpressionFactory /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - SqlBinaryExpression IsNotNull(SqlExpression operand); + SqlBinaryExpression IsNotNull([NotNull] SqlExpression operand); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -199,7 +212,8 @@ public interface ISqlExpressionFactory /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - SqlUnaryExpression Convert(SqlExpression operand, Type type, CoreTypeMapping typeMapping = null); + SqlUnaryExpression Convert( + [NotNull] SqlExpression operand, [NotNull] Type type, [CanBeNull] CoreTypeMapping typeMapping = null); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -207,7 +221,7 @@ public interface ISqlExpressionFactory /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - SqlUnaryExpression Not(SqlExpression operand); + SqlUnaryExpression Not([NotNull] SqlExpression operand); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -215,7 +229,7 @@ public interface ISqlExpressionFactory /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - SqlUnaryExpression Negate(SqlExpression operand); + SqlUnaryExpression Negate([NotNull] SqlExpression operand); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -224,7 +238,10 @@ public interface ISqlExpressionFactory /// doing so can result in application failures when updating to a new Entity Framework Core release. /// SqlFunctionExpression Function( - string functionName, IEnumerable arguments, Type returnType, CoreTypeMapping typeMapping = null); + [NotNull] string functionName, + [NotNull] IEnumerable arguments, + [NotNull] Type returnType, + [CanBeNull] CoreTypeMapping typeMapping = null); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -232,7 +249,8 @@ SqlFunctionExpression Function( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - SqlConditionalExpression Condition(SqlExpression test, SqlExpression ifTrue, SqlExpression ifFalse); + SqlConditionalExpression Condition( + [NotNull] SqlExpression test, [NotNull] SqlExpression ifTrue, [NotNull] SqlExpression ifFalse); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -240,7 +258,7 @@ SqlFunctionExpression Function( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - InExpression In(SqlExpression item, SqlExpression values, bool negated); + InExpression In([NotNull] SqlExpression item, [NotNull] SqlExpression values, bool negated); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -248,7 +266,7 @@ SqlFunctionExpression Function( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - SqlConstantExpression Constant(object value, CoreTypeMapping typeMapping = null); + SqlConstantExpression Constant([CanBeNull] object value, [CanBeNull] CoreTypeMapping typeMapping = null); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -256,6 +274,6 @@ SqlFunctionExpression Function( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - SelectExpression Select(IEntityType entityType); + SelectExpression Select([NotNull] IEntityType entityType); } } diff --git a/src/EFCore.Cosmos/Query/Internal/InExpression.cs b/src/EFCore.Cosmos/Query/Internal/InExpression.cs index e58a23497e8..1e4b87d2f93 100644 --- a/src/EFCore.Cosmos/Query/Internal/InExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/InExpression.cs @@ -3,8 +3,10 @@ using System; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal { @@ -22,7 +24,8 @@ public class InExpression : SqlExpression /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public InExpression(SqlExpression item, bool negated, SqlExpression values, CoreTypeMapping typeMapping) + public InExpression( + [NotNull] SqlExpression item, bool negated, [NotNull] SqlExpression values, [NotNull] CoreTypeMapping typeMapping) : base(typeof(bool), typeMapping) { Item = item; @@ -82,7 +85,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual InExpression Update(SqlExpression item, SqlExpression values) + public virtual InExpression Update([NotNull] SqlExpression item, [NotNull] SqlExpression values) => item != Item || values != Values ? new InExpression(item, IsNegated, values, TypeMapping) : this; @@ -95,6 +98,8 @@ public virtual InExpression Update(SqlExpression item, SqlExpression values) /// public override void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.Visit(Item); expressionPrinter.Append(IsNegated ? " NOT IN " : " IN "); expressionPrinter.Append("("); diff --git a/src/EFCore.Cosmos/Query/Internal/KeyAccessExpression.cs b/src/EFCore.Cosmos/Query/Internal/KeyAccessExpression.cs index 1734fe749bd..4025e055af9 100644 --- a/src/EFCore.Cosmos/Query/Internal/KeyAccessExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/KeyAccessExpression.cs @@ -3,8 +3,10 @@ using System; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal { @@ -22,7 +24,7 @@ public class KeyAccessExpression : SqlExpression, IAccessExpression /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public KeyAccessExpression(IProperty property, Expression accessExpression) + public KeyAccessExpression([NotNull] IProperty property, [NotNull] Expression accessExpression) : base(property.ClrType, property.GetTypeMapping()) { Name = property.GetJsonPropertyName(); @@ -64,6 +66,8 @@ public KeyAccessExpression(IProperty property, Expression accessExpression) /// protected override Expression VisitChildren(ExpressionVisitor visitor) { + Check.NotNull(visitor, nameof(visitor)); + var outerExpression = visitor.Visit(AccessExpression); return Update(outerExpression); @@ -75,7 +79,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual KeyAccessExpression Update(Expression outerExpression) + public virtual KeyAccessExpression Update([NotNull] Expression outerExpression) => outerExpression != AccessExpression ? new KeyAccessExpression(Property, outerExpression) : this; @@ -87,7 +91,11 @@ public virtual KeyAccessExpression Update(Expression outerExpression) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public override void Print(ExpressionPrinter expressionPrinter) - => expressionPrinter.Append(ToString()); + { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + + expressionPrinter.Append(ToString()); + } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.Cosmos/Query/Internal/ObjectAccessExpression.cs b/src/EFCore.Cosmos/Query/Internal/ObjectAccessExpression.cs index 9e0a6b1b4fe..600d7e0d20c 100644 --- a/src/EFCore.Cosmos/Query/Internal/ObjectAccessExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/ObjectAccessExpression.cs @@ -3,8 +3,10 @@ using System; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal { @@ -22,7 +24,7 @@ public class ObjectAccessExpression : Expression, IPrintableExpression, IAccessE /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public ObjectAccessExpression(INavigation navigation, Expression accessExpression) + public ObjectAccessExpression([NotNull] INavigation navigation, [NotNull] Expression accessExpression) { Name = navigation.GetTargetType().GetContainingPropertyName(); if (Name == null) @@ -83,6 +85,8 @@ public ObjectAccessExpression(INavigation navigation, Expression accessExpressio /// protected override Expression VisitChildren(ExpressionVisitor visitor) { + Check.NotNull(visitor, nameof(visitor)); + var outerExpression = visitor.Visit(AccessExpression); return Update(outerExpression); @@ -94,7 +98,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual ObjectAccessExpression Update(Expression outerExpression) + public virtual ObjectAccessExpression Update([NotNull] Expression outerExpression) => outerExpression != AccessExpression ? new ObjectAccessExpression(Navigation, outerExpression) : this; @@ -105,7 +109,12 @@ public virtual ObjectAccessExpression Update(Expression outerExpression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual void Print(ExpressionPrinter expressionPrinter) => expressionPrinter.Append(ToString()); + public virtual void Print(ExpressionPrinter expressionPrinter) + { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + + expressionPrinter.Append(ToString()); + } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.Cosmos/Query/Internal/ObjectArrayProjectionExpression.cs b/src/EFCore.Cosmos/Query/Internal/ObjectArrayProjectionExpression.cs index ad954314ed7..b270435f2fa 100644 --- a/src/EFCore.Cosmos/Query/Internal/ObjectArrayProjectionExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/ObjectArrayProjectionExpression.cs @@ -4,8 +4,10 @@ using System; using System.Collections.Generic; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal { @@ -24,7 +26,9 @@ public class ObjectArrayProjectionExpression : Expression, IPrintableExpression, /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public ObjectArrayProjectionExpression( - INavigation navigation, Expression accessExpression, EntityProjectionExpression innerProjection = null) + [NotNull] INavigation navigation, + [NotNull] Expression accessExpression, + [CanBeNull] EntityProjectionExpression innerProjection = null) { var targetType = navigation.GetTargetType(); Type = typeof(IEnumerable<>).MakeGenericType(targetType.ClrType); @@ -99,6 +103,8 @@ public ObjectArrayProjectionExpression( /// protected override Expression VisitChildren(ExpressionVisitor visitor) { + Check.NotNull(visitor, nameof(visitor)); + var accessExpression = visitor.Visit(AccessExpression); var innerProjection = visitor.Visit(InnerProjection); @@ -111,7 +117,8 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual ObjectArrayProjectionExpression Update(Expression accessExpression, EntityProjectionExpression innerProjection) + public virtual ObjectArrayProjectionExpression Update( + [NotNull] Expression accessExpression, [NotNull] EntityProjectionExpression innerProjection) => accessExpression != AccessExpression || innerProjection != InnerProjection ? new ObjectArrayProjectionExpression(Navigation, accessExpression, innerProjection) : this; @@ -123,7 +130,11 @@ public virtual ObjectArrayProjectionExpression Update(Expression accessExpressio /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual void Print(ExpressionPrinter expressionPrinter) - => expressionPrinter.Append(ToString()); + { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + + expressionPrinter.Append(ToString()); + } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.Cosmos/Query/Internal/OrderingExpression.cs b/src/EFCore.Cosmos/Query/Internal/OrderingExpression.cs index a2d3309beab..dd872ad1e5b 100644 --- a/src/EFCore.Cosmos/Query/Internal/OrderingExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/OrderingExpression.cs @@ -3,7 +3,9 @@ using System; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal { @@ -21,7 +23,7 @@ public class OrderingExpression : Expression, IPrintableExpression /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public OrderingExpression(SqlExpression expression, bool ascending) + public OrderingExpression([NotNull] SqlExpression expression, bool ascending) { Expression = expression; IsAscending = ascending; @@ -66,7 +68,11 @@ public OrderingExpression(SqlExpression expression, bool ascending) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// protected override Expression VisitChildren(ExpressionVisitor visitor) - => Update((SqlExpression)visitor.Visit(Expression)); + { + Check.NotNull(visitor, nameof(visitor)); + + return Update((SqlExpression)visitor.Visit(Expression)); + } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -74,10 +80,12 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual OrderingExpression Update(SqlExpression expression) - => expression != Expression + public virtual OrderingExpression Update([NotNull] SqlExpression expression) + { + return expression != Expression ? new OrderingExpression(expression, IsAscending) : this; + } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -87,6 +95,8 @@ public virtual OrderingExpression Update(SqlExpression expression) /// public virtual void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.Visit(Expression); expressionPrinter.Append(IsAscending ? " ASC" : " DESC"); diff --git a/src/EFCore.Cosmos/Query/Internal/ProjectionExpression.cs b/src/EFCore.Cosmos/Query/Internal/ProjectionExpression.cs index 9a8ac1a6883..b278bac7668 100644 --- a/src/EFCore.Cosmos/Query/Internal/ProjectionExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/ProjectionExpression.cs @@ -3,7 +3,9 @@ using System; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal { @@ -21,7 +23,7 @@ public class ProjectionExpression : Expression, IPrintableExpression /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public ProjectionExpression(Expression expression, string alias) + public ProjectionExpression([NotNull] Expression expression, [NotNull] string alias) { Expression = expression; Alias = alias; @@ -75,7 +77,11 @@ public virtual string Name /// doing so can result in application failures when updating to a new Entity Framework Core release. /// protected override Expression VisitChildren(ExpressionVisitor visitor) - => Update(visitor.Visit(Expression)); + { + Check.NotNull(visitor, nameof(visitor)); + + return Update(visitor.Visit(Expression)); + } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -83,7 +89,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual ProjectionExpression Update(Expression expression) + public virtual ProjectionExpression Update([NotNull] Expression expression) => expression != Expression ? new ProjectionExpression(expression, Alias) : this; @@ -96,6 +102,8 @@ public virtual ProjectionExpression Update(Expression expression) /// public virtual void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.Visit(Expression); if (!string.Equals(string.Empty, Alias) && !string.Equals(Alias, Name)) diff --git a/src/EFCore.Cosmos/Query/Internal/QuerySqlGenerator.cs b/src/EFCore.Cosmos/Query/Internal/QuerySqlGenerator.cs index f8fae428d19..3d34617ad04 100644 --- a/src/EFCore.Cosmos/Query/Internal/QuerySqlGenerator.cs +++ b/src/EFCore.Cosmos/Query/Internal/QuerySqlGenerator.cs @@ -6,10 +6,12 @@ using System.Linq; using System.Linq.Expressions; using System.Text; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Cosmos.Storage.Internal; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -70,7 +72,8 @@ public class QuerySqlGenerator : SqlExpressionVisitor /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual CosmosSqlQuery GetSqlQuery(SelectExpression selectExpression, IReadOnlyDictionary parameterValues) + public virtual CosmosSqlQuery GetSqlQuery( + [NotNull] SelectExpression selectExpression, [NotNull] IReadOnlyDictionary parameterValues) { _sqlBuilder.Clear(); _parameterValues = parameterValues; @@ -89,6 +92,8 @@ public virtual CosmosSqlQuery GetSqlQuery(SelectExpression selectExpression, IRe /// protected override Expression VisitEntityProjection(EntityProjectionExpression entityProjectionExpression) { + Check.NotNull(entityProjectionExpression, nameof(entityProjectionExpression)); + Visit(entityProjectionExpression.AccessExpression); return entityProjectionExpression; @@ -102,6 +107,8 @@ protected override Expression VisitEntityProjection(EntityProjectionExpression e /// protected override Expression VisitObjectArrayProjection(ObjectArrayProjectionExpression objectArrayProjectionExpression) { + Check.NotNull(objectArrayProjectionExpression, nameof(objectArrayProjectionExpression)); + _sqlBuilder.Append(objectArrayProjectionExpression); return objectArrayProjectionExpression; @@ -115,6 +122,8 @@ protected override Expression VisitObjectArrayProjection(ObjectArrayProjectionEx /// protected override Expression VisitKeyAccess(KeyAccessExpression keyAccessExpression) { + Check.NotNull(keyAccessExpression, nameof(keyAccessExpression)); + _sqlBuilder.Append(keyAccessExpression); return keyAccessExpression; @@ -128,6 +137,8 @@ protected override Expression VisitKeyAccess(KeyAccessExpression keyAccessExpres /// protected override Expression VisitObjectAccess(ObjectAccessExpression objectAccessExpression) { + Check.NotNull(objectAccessExpression, nameof(objectAccessExpression)); + _sqlBuilder.Append(objectAccessExpression); return objectAccessExpression; @@ -141,6 +152,8 @@ protected override Expression VisitObjectAccess(ObjectAccessExpression objectAcc /// protected override Expression VisitProjection(ProjectionExpression projectionExpression) { + Check.NotNull(projectionExpression, nameof(projectionExpression)); + Visit(projectionExpression.Expression); if (!string.Equals(string.Empty, projectionExpression.Alias) @@ -160,6 +173,8 @@ protected override Expression VisitProjection(ProjectionExpression projectionExp /// protected override Expression VisitRootReference(RootReferenceExpression rootReferenceExpression) { + Check.NotNull(rootReferenceExpression, nameof(rootReferenceExpression)); + _sqlBuilder.Append(rootReferenceExpression); return rootReferenceExpression; @@ -173,6 +188,8 @@ protected override Expression VisitRootReference(RootReferenceExpression rootRef /// protected override Expression VisitSelect(SelectExpression selectExpression) { + Check.NotNull(selectExpression, nameof(selectExpression)); + _sqlBuilder.Append("SELECT "); if (selectExpression.IsDistinct) @@ -245,6 +262,8 @@ protected override Expression VisitSelect(SelectExpression selectExpression) /// protected override Expression VisitOrdering(OrderingExpression orderingExpression) { + Check.NotNull(orderingExpression, nameof(orderingExpression)); + Visit(orderingExpression.Expression); if (!orderingExpression.IsAscending) @@ -263,6 +282,8 @@ protected override Expression VisitOrdering(OrderingExpression orderingExpressio /// protected override Expression VisitSqlBinary(SqlBinaryExpression sqlBinaryExpression) { + Check.NotNull(sqlBinaryExpression, nameof(sqlBinaryExpression)); + var op = _operatorMap[sqlBinaryExpression.OperatorType]; _sqlBuilder.Append("("); Visit(sqlBinaryExpression.Left); @@ -289,6 +310,8 @@ protected override Expression VisitSqlBinary(SqlBinaryExpression sqlBinaryExpres /// protected override Expression VisitSqlUnary(SqlUnaryExpression sqlUnaryExpression) { + Check.NotNull(sqlUnaryExpression, nameof(sqlUnaryExpression)); + var op = _operatorMap[sqlUnaryExpression.OperatorType]; if (sqlUnaryExpression.OperatorType == ExpressionType.Not @@ -332,6 +355,8 @@ private void GenerateList( /// protected override Expression VisitSqlConstant(SqlConstantExpression sqlConstantExpression) { + Check.NotNull(sqlConstantExpression, nameof(sqlConstantExpression)); + var jToken = GenerateJToken(sqlConstantExpression.Value, sqlConstantExpression.TypeMapping); _sqlBuilder.Append(jToken == null ? "null" : jToken.ToString(Formatting.None)); @@ -363,6 +388,8 @@ private JToken GenerateJToken(object value, CoreTypeMapping typeMapping) /// protected override Expression VisitSqlConditional(SqlConditionalExpression sqlConditionalExpression) { + Check.NotNull(sqlConditionalExpression, nameof(sqlConditionalExpression)); + _sqlBuilder.Append("("); Visit(sqlConditionalExpression.Test); _sqlBuilder.Append(" ? "); @@ -382,6 +409,8 @@ protected override Expression VisitSqlConditional(SqlConditionalExpression sqlCo /// protected override Expression VisitSqlParameter(SqlParameterExpression sqlParameterExpression) { + Check.NotNull(sqlParameterExpression, nameof(sqlParameterExpression)); + var parameterName = $"@{sqlParameterExpression.Name}"; if (_sqlParameters.All(sp => sp.Name != parameterName)) @@ -403,6 +432,8 @@ protected override Expression VisitSqlParameter(SqlParameterExpression sqlParame /// protected override Expression VisitIn(InExpression inExpression) { + Check.NotNull(inExpression, nameof(inExpression)); + Visit(inExpression.Item); _sqlBuilder.Append(inExpression.IsNegated ? " NOT IN " : " IN "); _sqlBuilder.Append("("); @@ -423,6 +454,8 @@ protected override Expression VisitIn(InExpression inExpression) /// protected override Expression VisitSqlFunction(SqlFunctionExpression sqlFunctionExpression) { + Check.NotNull(sqlFunctionExpression, nameof(sqlFunctionExpression)); + _sqlBuilder.Append(sqlFunctionExpression.Name); _sqlBuilder.Append("("); GenerateList(sqlFunctionExpression.Arguments, e => Visit(e)); diff --git a/src/EFCore.Cosmos/Query/Internal/RootReferenceExpression.cs b/src/EFCore.Cosmos/Query/Internal/RootReferenceExpression.cs index b90b9cc96dd..bb0bfdfcf21 100644 --- a/src/EFCore.Cosmos/Query/Internal/RootReferenceExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/RootReferenceExpression.cs @@ -3,7 +3,9 @@ using System; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal { @@ -21,7 +23,7 @@ public class RootReferenceExpression : Expression, IAccessExpression /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public RootReferenceExpression(IEntityType entityType, string alias) + public RootReferenceExpression([NotNull] IEntityType entityType, [NotNull] string alias) { EntityType = entityType; Alias = alias; @@ -73,7 +75,12 @@ public RootReferenceExpression(IEntityType entityType, string alias) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override Expression VisitChildren(ExpressionVisitor visitor) => this; + protected override Expression VisitChildren(ExpressionVisitor visitor) + { + Check.NotNull(visitor, nameof(visitor)); + + return this; + } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.Cosmos/Query/Internal/SelectExpression.cs b/src/EFCore.Cosmos/Query/Internal/SelectExpression.cs index dee08905238..864c62fc513 100644 --- a/src/EFCore.Cosmos/Query/Internal/SelectExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/SelectExpression.cs @@ -5,8 +5,10 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Utilities; using Newtonsoft.Json.Linq; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal @@ -31,7 +33,7 @@ public class SelectExpression : Expression /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public SelectExpression(IEntityType entityType) + public SelectExpression([NotNull] IEntityType entityType) { Container = entityType.GetContainer(); FromExpression = new RootReferenceExpression(entityType, RootAlias); @@ -45,7 +47,9 @@ public SelectExpression(IEntityType entityType) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public SelectExpression( - List projections, RootReferenceExpression fromExpression, List orderings) + [NotNull] List projections, + [NotNull] RootReferenceExpression fromExpression, + [NotNull] List orderings) { _projection = projections; FromExpression = fromExpression; @@ -122,7 +126,7 @@ public SelectExpression( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual Expression GetMappedProjection(ProjectionMember projectionMember) + public virtual Expression GetMappedProjection([NotNull] ProjectionMember projectionMember) => _projectionMapping[projectionMember]; /// @@ -156,7 +160,7 @@ public virtual void ApplyProjection() /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual void ReplaceProjectionMapping(IDictionary projectionMapping) + public virtual void ReplaceProjectionMapping([NotNull] IDictionary projectionMapping) { _projectionMapping.Clear(); foreach (var kvp in projectionMapping) @@ -171,7 +175,8 @@ public virtual void ReplaceProjectionMapping(IDictionary - public virtual int AddToProjection(SqlExpression sqlExpression) => AddToProjection(sqlExpression, null); + public virtual int AddToProjection([NotNull] SqlExpression sqlExpression) + => AddToProjection(sqlExpression, null); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -179,7 +184,8 @@ public virtual void ReplaceProjectionMapping(IDictionary - public virtual int AddToProjection(EntityProjectionExpression entityProjection) => AddToProjection(entityProjection, null); + public virtual int AddToProjection([NotNull] EntityProjectionExpression entityProjection) + => AddToProjection(entityProjection, null); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -187,10 +193,10 @@ public virtual void ReplaceProjectionMapping(IDictionary - public virtual int AddToProjection(ObjectArrayProjectionExpression objectArrayProjection) => + public virtual int AddToProjection([NotNull] ObjectArrayProjectionExpression objectArrayProjection) => AddToProjection(objectArrayProjection, null); - private int AddToProjection(Expression expression, string alias) + private int AddToProjection([NotNull] Expression expression, string alias) { var existingIndex = _projection.FindIndex(pe => pe.Expression.Equals(expression)); if (existingIndex != -1) @@ -242,7 +248,7 @@ public virtual void ClearOrdering() /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual void ApplyPredicate(SqlExpression expression) + public virtual void ApplyPredicate([NotNull] SqlExpression expression) { if (expression is SqlConstantExpression sqlConstant && (bool)sqlConstant.Value) @@ -266,7 +272,7 @@ public virtual void ApplyPredicate(SqlExpression expression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual void ApplyLimit(SqlExpression sqlExpression) + public virtual void ApplyLimit([NotNull] SqlExpression sqlExpression) { if (Limit != null) { @@ -282,7 +288,7 @@ public virtual void ApplyLimit(SqlExpression sqlExpression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual void ApplyOffset(SqlExpression sqlExpression) + public virtual void ApplyOffset([NotNull] SqlExpression sqlExpression) { if (Limit != null || Offset != null) @@ -299,7 +305,7 @@ public virtual void ApplyOffset(SqlExpression sqlExpression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual void ApplyOrdering(OrderingExpression orderingExpression) + public virtual void ApplyOrdering([NotNull] OrderingExpression orderingExpression) { if (IsDistinct || Limit != null @@ -318,7 +324,7 @@ public virtual void ApplyOrdering(OrderingExpression orderingExpression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual void AppendOrdering(OrderingExpression orderingExpression) + public virtual void AppendOrdering([NotNull] OrderingExpression orderingExpression) { if (_orderings.FirstOrDefault(o => o.Expression.Equals(orderingExpression.Expression)) == null) { @@ -377,6 +383,8 @@ public virtual void ReverseOrderings() /// protected override Expression VisitChildren(ExpressionVisitor visitor) { + Check.NotNull(visitor, nameof(visitor)); + var changed = false; var projections = new List(); diff --git a/src/EFCore.Cosmos/Query/Internal/SqlBinaryExpression.cs b/src/EFCore.Cosmos/Query/Internal/SqlBinaryExpression.cs index 004140a572e..4ae45cecc76 100644 --- a/src/EFCore.Cosmos/Query/Internal/SqlBinaryExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/SqlBinaryExpression.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; @@ -54,10 +55,10 @@ private static ExpressionType VerifyOperator(ExpressionType operatorType) /// public SqlBinaryExpression( ExpressionType operatorType, - SqlExpression left, - SqlExpression right, - Type type, - CoreTypeMapping typeMapping) + [NotNull] SqlExpression left, + [NotNull] SqlExpression right, + [NotNull] Type type, + [CanBeNull] CoreTypeMapping typeMapping) : base(type, typeMapping) { Check.NotNull(left, nameof(left)); @@ -101,6 +102,8 @@ public SqlBinaryExpression( /// protected override Expression VisitChildren(ExpressionVisitor visitor) { + Check.NotNull(visitor, nameof(visitor)); + var left = (SqlExpression)visitor.Visit(Left); var right = (SqlExpression)visitor.Visit(Right); @@ -113,7 +116,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlBinaryExpression Update(SqlExpression left, SqlExpression right) + public virtual SqlBinaryExpression Update([NotNull] SqlExpression left, [NotNull] SqlExpression right) => left != Left || right != Right ? new SqlBinaryExpression(OperatorType, left, right, Type, TypeMapping) : this; @@ -126,6 +129,8 @@ public virtual SqlBinaryExpression Update(SqlExpression left, SqlExpression righ /// public override void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + var requiresBrackets = RequiresBrackets(Left); if (requiresBrackets) diff --git a/src/EFCore.Cosmos/Query/Internal/SqlConditionalExpression.cs b/src/EFCore.Cosmos/Query/Internal/SqlConditionalExpression.cs index ef02c31722e..25d7360c703 100644 --- a/src/EFCore.Cosmos/Query/Internal/SqlConditionalExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/SqlConditionalExpression.cs @@ -3,7 +3,9 @@ using System; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal { @@ -22,9 +24,9 @@ public class SqlConditionalExpression : SqlExpression /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public SqlConditionalExpression( - SqlExpression test, - SqlExpression ifTrue, - SqlExpression ifFalse) + [NotNull] SqlExpression test, + [NotNull] SqlExpression ifTrue, + [NotNull] SqlExpression ifFalse) : base(ifTrue.Type, ifTrue.TypeMapping ?? ifFalse.TypeMapping) { Test = test; @@ -64,6 +66,8 @@ public SqlConditionalExpression( /// protected override Expression VisitChildren(ExpressionVisitor visitor) { + Check.NotNull(visitor, nameof(visitor)); + var test = (SqlExpression)visitor.Visit(Test); var ifTrue = (SqlExpression)visitor.Visit(IfTrue); var ifFalse = (SqlExpression)visitor.Visit(IfFalse); @@ -78,9 +82,9 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual SqlConditionalExpression Update( - SqlExpression test, - SqlExpression ifTrue, - SqlExpression ifFalse) + [NotNull] SqlExpression test, + [NotNull] SqlExpression ifTrue, + [NotNull] SqlExpression ifFalse) => test != Test || ifTrue != IfTrue || ifFalse != IfFalse ? new SqlConditionalExpression(test, ifTrue, ifFalse) : this; @@ -93,6 +97,8 @@ public virtual SqlConditionalExpression Update( /// public override void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.Append("("); expressionPrinter.Visit(Test); expressionPrinter.Append(" ? "); diff --git a/src/EFCore.Cosmos/Query/Internal/SqlConstantExpression.cs b/src/EFCore.Cosmos/Query/Internal/SqlConstantExpression.cs index b8159d212ae..2e83486f484 100644 --- a/src/EFCore.Cosmos/Query/Internal/SqlConstantExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/SqlConstantExpression.cs @@ -4,9 +4,11 @@ using System; using System.Collections; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Cosmos.Storage.Internal; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -28,7 +30,7 @@ public class SqlConstantExpression : SqlExpression /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public SqlConstantExpression(ConstantExpression constantExpression, CoreTypeMapping typeMapping) + public SqlConstantExpression([NotNull] ConstantExpression constantExpression, [NotNull] CoreTypeMapping typeMapping) : base(constantExpression.Type, typeMapping) { _constantExpression = constantExpression; @@ -48,7 +50,7 @@ public SqlConstantExpression(ConstantExpression constantExpression, CoreTypeMapp /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression ApplyTypeMapping(CoreTypeMapping typeMapping) + public virtual SqlExpression ApplyTypeMapping([NotNull] CoreTypeMapping typeMapping) => new SqlConstantExpression(_constantExpression, typeMapping); /// @@ -57,7 +59,12 @@ public virtual SqlExpression ApplyTypeMapping(CoreTypeMapping typeMapping) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override Expression VisitChildren(ExpressionVisitor visitor) => this; + protected override Expression VisitChildren(ExpressionVisitor visitor) + { + Check.NotNull(visitor, nameof(visitor)); + + return this; + } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -65,7 +72,12 @@ public virtual SqlExpression ApplyTypeMapping(CoreTypeMapping typeMapping) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public override void Print(ExpressionPrinter expressionPrinter) => Print(Value, expressionPrinter); + public override void Print(ExpressionPrinter expressionPrinter) + { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + + Print(Value, expressionPrinter); + } private void Print( object value, diff --git a/src/EFCore.Cosmos/Query/Internal/SqlExpression.cs b/src/EFCore.Cosmos/Query/Internal/SqlExpression.cs index 4051ab4743f..59dc97dbbfb 100644 --- a/src/EFCore.Cosmos/Query/Internal/SqlExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/SqlExpression.cs @@ -3,6 +3,7 @@ using System; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; @@ -22,7 +23,7 @@ public abstract class SqlExpression : Expression, IPrintableExpression /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected SqlExpression(Type type, CoreTypeMapping typeMapping) + protected SqlExpression([NotNull] Type type, [CanBeNull] CoreTypeMapping typeMapping) { Type = type; TypeMapping = typeMapping; diff --git a/src/EFCore.Cosmos/Query/Internal/SqlExpressionFactory.cs b/src/EFCore.Cosmos/Query/Internal/SqlExpressionFactory.cs index 643c8ae1dc5..9024813d57e 100644 --- a/src/EFCore.Cosmos/Query/Internal/SqlExpressionFactory.cs +++ b/src/EFCore.Cosmos/Query/Internal/SqlExpressionFactory.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; @@ -31,7 +32,7 @@ public class SqlExpressionFactory : ISqlExpressionFactory /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public SqlExpressionFactory(ITypeMappingSource typeMappingSource) + public SqlExpressionFactory([NotNull] ITypeMappingSource typeMappingSource) { _typeMappingSource = typeMappingSource; _boolTypeMapping = typeMappingSource.FindMapping(typeof(bool)); diff --git a/src/EFCore.Cosmos/Query/Internal/SqlExpressionVisitor.cs b/src/EFCore.Cosmos/Query/Internal/SqlExpressionVisitor.cs index 308e6ebabad..2b745193939 100644 --- a/src/EFCore.Cosmos/Query/Internal/SqlExpressionVisitor.cs +++ b/src/EFCore.Cosmos/Query/Internal/SqlExpressionVisitor.cs @@ -2,6 +2,8 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Linq.Expressions; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal { @@ -21,6 +23,8 @@ public abstract class SqlExpressionVisitor : ExpressionVisitor /// protected override Expression VisitExtension(Expression extensionExpression) { + Check.NotNull(extensionExpression, nameof(extensionExpression)); + switch (extensionExpression) { case SelectExpression selectExpression: @@ -78,7 +82,7 @@ protected override Expression VisitExtension(Expression extensionExpression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected abstract Expression VisitOrdering(OrderingExpression orderingExpression); + protected abstract Expression VisitOrdering([NotNull] OrderingExpression orderingExpression); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -86,7 +90,7 @@ protected override Expression VisitExtension(Expression extensionExpression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected abstract Expression VisitSqlFunction(SqlFunctionExpression sqlFunctionExpression); + protected abstract Expression VisitSqlFunction([NotNull] SqlFunctionExpression sqlFunctionExpression); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -94,7 +98,7 @@ protected override Expression VisitExtension(Expression extensionExpression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected abstract Expression VisitIn(InExpression inExpression); + protected abstract Expression VisitIn([NotNull] InExpression inExpression); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -102,7 +106,7 @@ protected override Expression VisitExtension(Expression extensionExpression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected abstract Expression VisitSqlParameter(SqlParameterExpression sqlParameterExpression); + protected abstract Expression VisitSqlParameter([NotNull] SqlParameterExpression sqlParameterExpression); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -110,7 +114,7 @@ protected override Expression VisitExtension(Expression extensionExpression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected abstract Expression VisitSqlConditional(SqlConditionalExpression caseExpression); + protected abstract Expression VisitSqlConditional([NotNull] SqlConditionalExpression caseExpression); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -118,7 +122,7 @@ protected override Expression VisitExtension(Expression extensionExpression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected abstract Expression VisitSqlUnary(SqlUnaryExpression sqlUnaryExpression); + protected abstract Expression VisitSqlUnary([NotNull] SqlUnaryExpression sqlUnaryExpression); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -126,7 +130,7 @@ protected override Expression VisitExtension(Expression extensionExpression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected abstract Expression VisitSqlConstant(SqlConstantExpression sqlConstantExpression); + protected abstract Expression VisitSqlConstant([NotNull] SqlConstantExpression sqlConstantExpression); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -134,7 +138,7 @@ protected override Expression VisitExtension(Expression extensionExpression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected abstract Expression VisitSqlBinary(SqlBinaryExpression sqlBinaryExpression); + protected abstract Expression VisitSqlBinary([NotNull] SqlBinaryExpression sqlBinaryExpression); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -142,7 +146,7 @@ protected override Expression VisitExtension(Expression extensionExpression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected abstract Expression VisitKeyAccess(KeyAccessExpression keyAccessExpression); + protected abstract Expression VisitKeyAccess([NotNull] KeyAccessExpression keyAccessExpression); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -150,7 +154,7 @@ protected override Expression VisitExtension(Expression extensionExpression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected abstract Expression VisitObjectAccess(ObjectAccessExpression objectAccessExpression); + protected abstract Expression VisitObjectAccess([NotNull] ObjectAccessExpression objectAccessExpression); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -158,7 +162,7 @@ protected override Expression VisitExtension(Expression extensionExpression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected abstract Expression VisitRootReference(RootReferenceExpression rootReferenceExpression); + protected abstract Expression VisitRootReference([NotNull] RootReferenceExpression rootReferenceExpression); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -166,7 +170,7 @@ protected override Expression VisitExtension(Expression extensionExpression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected abstract Expression VisitEntityProjection(EntityProjectionExpression entityProjectionExpression); + protected abstract Expression VisitEntityProjection([NotNull] EntityProjectionExpression entityProjectionExpression); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -174,7 +178,7 @@ protected override Expression VisitExtension(Expression extensionExpression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected abstract Expression VisitObjectArrayProjection(ObjectArrayProjectionExpression objectArrayProjectionExpression); + protected abstract Expression VisitObjectArrayProjection([NotNull] ObjectArrayProjectionExpression objectArrayProjectionExpression); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -182,7 +186,7 @@ protected override Expression VisitExtension(Expression extensionExpression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected abstract Expression VisitProjection(ProjectionExpression projectionExpression); + protected abstract Expression VisitProjection([NotNull] ProjectionExpression projectionExpression); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -190,6 +194,6 @@ protected override Expression VisitExtension(Expression extensionExpression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected abstract Expression VisitSelect(SelectExpression selectExpression); + protected abstract Expression VisitSelect([NotNull] SelectExpression selectExpression); } } diff --git a/src/EFCore.Cosmos/Query/Internal/SqlFunctionExpression.cs b/src/EFCore.Cosmos/Query/Internal/SqlFunctionExpression.cs index 22b6c648eb7..7642b793a26 100644 --- a/src/EFCore.Cosmos/Query/Internal/SqlFunctionExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/SqlFunctionExpression.cs @@ -5,8 +5,10 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal { @@ -19,10 +21,10 @@ namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal public class SqlFunctionExpression : SqlExpression { public SqlFunctionExpression( - string name, - IEnumerable arguments, - Type type, - CoreTypeMapping typeMapping) + [NotNull] string name, + [CanBeNull] IEnumerable arguments, + [NotNull] Type type, + [CanBeNull] CoreTypeMapping typeMapping) : base(type, typeMapping) { Name = name; @@ -53,6 +55,8 @@ public SqlFunctionExpression( /// protected override Expression VisitChildren(ExpressionVisitor visitor) { + Check.NotNull(visitor, nameof(visitor)); + var changed = false; var arguments = new SqlExpression[Arguments.Count]; for (var i = 0; i < arguments.Length; i++) @@ -76,7 +80,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlFunctionExpression ApplyTypeMapping(CoreTypeMapping typeMapping) + public virtual SqlFunctionExpression ApplyTypeMapping([CanBeNull] CoreTypeMapping typeMapping) => new SqlFunctionExpression( Name, Arguments, @@ -89,7 +93,7 @@ public virtual SqlFunctionExpression ApplyTypeMapping(CoreTypeMapping typeMappin /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlFunctionExpression Update(IReadOnlyList arguments) + public virtual SqlFunctionExpression Update([NotNull] IReadOnlyList arguments) => !arguments.SequenceEqual(Arguments) ? new SqlFunctionExpression(Name, arguments, Type, TypeMapping) : this; @@ -102,6 +106,8 @@ public virtual SqlFunctionExpression Update(IReadOnlyList argumen /// public override void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.Append(Name); expressionPrinter.Append("("); expressionPrinter.VisitList(Arguments); diff --git a/src/EFCore.Cosmos/Query/Internal/SqlParameterExpression.cs b/src/EFCore.Cosmos/Query/Internal/SqlParameterExpression.cs index b1c6194bed4..13b36687456 100644 --- a/src/EFCore.Cosmos/Query/Internal/SqlParameterExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/SqlParameterExpression.cs @@ -3,8 +3,10 @@ using System; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal { @@ -39,7 +41,7 @@ internal SqlParameterExpression(ParameterExpression parameterExpression, CoreTyp /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public SqlExpression ApplyTypeMapping(CoreTypeMapping typeMapping) + public SqlExpression ApplyTypeMapping([CanBeNull] CoreTypeMapping typeMapping) => new SqlParameterExpression(_parameterExpression, typeMapping); /// @@ -48,7 +50,12 @@ public SqlExpression ApplyTypeMapping(CoreTypeMapping typeMapping) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override Expression VisitChildren(ExpressionVisitor visitor) => this; + protected override Expression VisitChildren(ExpressionVisitor visitor) + { + Check.NotNull(visitor, nameof(visitor)); + + return this; + } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -57,7 +64,11 @@ public SqlExpression ApplyTypeMapping(CoreTypeMapping typeMapping) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public override void Print(ExpressionPrinter expressionPrinter) - => expressionPrinter.Append("@" + _parameterExpression.Name); + { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + + expressionPrinter.Append("@" + _parameterExpression.Name); + } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.Cosmos/Query/Internal/SqlUnaryExpression.cs b/src/EFCore.Cosmos/Query/Internal/SqlUnaryExpression.cs index 2dd41136502..2872d5146e3 100644 --- a/src/EFCore.Cosmos/Query/Internal/SqlUnaryExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/SqlUnaryExpression.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; @@ -36,9 +37,9 @@ private static ExpressionType VerifyOperator(ExpressionType operatorType) /// public SqlUnaryExpression( ExpressionType operatorType, - SqlExpression operand, - Type type, - CoreTypeMapping typeMapping) + [NotNull] SqlExpression operand, + [NotNull] Type type, + [CanBeNull] CoreTypeMapping typeMapping) : base(type, typeMapping) { Check.NotNull(operand, nameof(operand)); @@ -63,7 +64,11 @@ public SqlUnaryExpression( public virtual SqlExpression Operand { get; } protected override Expression VisitChildren(ExpressionVisitor visitor) - => Update((SqlExpression)visitor.Visit(Operand)); + { + Check.NotNull(visitor, nameof(visitor)); + + return Update((SqlExpression)visitor.Visit(Operand)); + } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -71,7 +76,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlUnaryExpression Update(SqlExpression operand) + public virtual SqlUnaryExpression Update([NotNull] SqlExpression operand) => operand != Operand ? new SqlUnaryExpression(OperatorType, operand, Type, TypeMapping) : this; @@ -84,6 +89,8 @@ public virtual SqlUnaryExpression Update(SqlExpression operand) /// public override void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.Append(OperatorType); expressionPrinter.Append("("); expressionPrinter.Visit(Operand); diff --git a/src/EFCore.Cosmos/Storage/Internal/CosmosClientWrapper.cs b/src/EFCore.Cosmos/Storage/Internal/CosmosClientWrapper.cs index 8a87f9d24de..1c7bd8c2c3d 100644 --- a/src/EFCore.Cosmos/Storage/Internal/CosmosClientWrapper.cs +++ b/src/EFCore.Cosmos/Storage/Internal/CosmosClientWrapper.cs @@ -107,8 +107,8 @@ public virtual bool CreateDatabaseIfNotExists() /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual bool CreateDatabaseIfNotExistsOnce( - DbContext context, - object state) + [NotNull] DbContext context, + [NotNull] object state) => CreateDatabaseIfNotExistsOnceAsync(context, state).GetAwaiter().GetResult(); /// @@ -129,8 +129,8 @@ public virtual Task CreateDatabaseIfNotExistsAsync( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual async Task CreateDatabaseIfNotExistsOnceAsync( - DbContext _, - object __, + [CanBeNull] DbContext _, + [CanBeNull] object __, CancellationToken cancellationToken = default) { var response = await Client.CreateDatabaseIfNotExistsAsync(_databaseId, cancellationToken: cancellationToken) @@ -155,8 +155,8 @@ public virtual bool DeleteDatabase() /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual bool DeleteDatabaseOnce( - DbContext context, - object state) + [CanBeNull] DbContext context, + [CanBeNull] object state) => DeleteDatabaseOnceAsync(context, state).GetAwaiter().GetResult(); /// @@ -177,8 +177,8 @@ public virtual Task DeleteDatabaseAsync( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual async Task DeleteDatabaseOnceAsync( - DbContext _, - object __, + [CanBeNull] DbContext _, + [CanBeNull] object __, CancellationToken cancellationToken = default) { using var response = await Client.GetDatabase(_databaseId).DeleteStreamAsync(cancellationToken: cancellationToken) @@ -199,8 +199,8 @@ public virtual async Task DeleteDatabaseOnceAsync( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual bool CreateContainerIfNotExists( - string containerId, - string partitionKey) + [NotNull] string containerId, + [NotNull] string partitionKey) => _executionStrategyFactory.Create().Execute( (containerId, partitionKey), CreateContainerIfNotExistsOnce, null); @@ -216,8 +216,8 @@ private bool CreateContainerIfNotExistsOnce( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual Task CreateContainerIfNotExistsAsync( - string containerId, - string partitionKey, + [NotNull] string containerId, + [NotNull] string partitionKey, CancellationToken cancellationToken = default) => _executionStrategyFactory.Create().ExecuteAsync( (containerId, partitionKey), CreateContainerIfNotExistsOnceAsync, null, cancellationToken); @@ -250,9 +250,9 @@ private async Task CreateContainerIfNotExistsOnceAsync( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual bool CreateItem( - string containerId, - JToken document, - string partitionKey) + [NotNull] string containerId, + [NotNull] JToken document, + [CanBeNull] string partitionKey) => _executionStrategyFactory.Create().Execute( (containerId, document, partitionKey), CreateItemOnce, null); @@ -268,9 +268,9 @@ private bool CreateItemOnce( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual Task CreateItemAsync( - string containerId, - JToken document, - string partitionKey, + [NotNull] string containerId, + [NotNull] JToken document, + [CanBeNull] string partitionKey, CancellationToken cancellationToken = default) => _executionStrategyFactory.Create().ExecuteAsync( (containerId, document, partitionKey), CreateItemOnceAsync, null, cancellationToken); @@ -300,10 +300,10 @@ private async Task CreateItemOnceAsync( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual bool ReplaceItem( - string collectionId, - string documentId, - JObject document, - string partitionKey) + [NotNull] string collectionId, + [NotNull] string documentId, + [NotNull] JObject document, + [CanBeNull] string partitionKey) => _executionStrategyFactory.Create().Execute( (collectionId, documentId, document, partitionKey), ReplaceItemOnce, null); @@ -319,10 +319,10 @@ private bool ReplaceItemOnce( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual Task ReplaceItemAsync( - string collectionId, - string documentId, - JObject document, - string partitionKey, + [NotNull] string collectionId, + [NotNull] string documentId, + [NotNull] JObject document, + [CanBeNull] string partitionKey, CancellationToken cancellationToken = default) => _executionStrategyFactory.Create().ExecuteAsync( (collectionId, documentId, document, partitionKey), ReplaceItemOnceAsync, null, cancellationToken); @@ -353,9 +353,9 @@ private async Task ReplaceItemOnceAsync( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual bool DeleteItem( - string containerId, - string documentId, - string partitionKey) + [NotNull] string containerId, + [NotNull] string documentId, + [CanBeNull] string partitionKey) => _executionStrategyFactory.Create().Execute( (containerId, documentId, partitionKey), DeleteItemOnce, null); @@ -366,7 +366,7 @@ public virtual bool DeleteItem( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual bool DeleteItemOnce( - DbContext context, + [NotNull] DbContext context, (string ContainerId, string DocumentId, string PartitionKey) parameters) => DeleteItemOnceAsync(context, parameters).GetAwaiter().GetResult(); @@ -377,9 +377,9 @@ public virtual bool DeleteItemOnce( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual Task DeleteItemAsync( - string containerId, - string documentId, - string partitionKey, + [NotNull] string containerId, + [NotNull] string documentId, + [CanBeNull] string partitionKey, CancellationToken cancellationToken = default) => _executionStrategyFactory.Create().ExecuteAsync( (containerId, documentId, partitionKey), DeleteItemOnceAsync, null, cancellationToken); @@ -391,7 +391,7 @@ public virtual Task DeleteItemAsync( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual async Task DeleteItemOnceAsync( - DbContext _, + [CanBeNull] DbContext _, (string ContainerId, string DocumentId, string PartitionKey) parameters, CancellationToken cancellationToken = default) { @@ -415,7 +415,7 @@ private PartitionKey CreatePartitionKey(string partitionKey) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual IEnumerable ExecuteSqlQuery( - string containerId, + [NotNull] string containerId, [NotNull] CosmosSqlQuery query) { _commandLogger.ExecutingSqlQuery(query); @@ -430,7 +430,7 @@ public virtual IEnumerable ExecuteSqlQuery( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual IAsyncEnumerable ExecuteSqlQueryAsync( - string containerId, + [NotNull] string containerId, [NotNull] CosmosSqlQuery query) { _commandLogger.ExecutingSqlQuery(query); diff --git a/src/EFCore.Cosmos/Storage/Internal/CosmosDatabaseCreator.cs b/src/EFCore.Cosmos/Storage/Internal/CosmosDatabaseCreator.cs index 09833884aef..8b97d03b1d8 100644 --- a/src/EFCore.Cosmos/Storage/Internal/CosmosDatabaseCreator.cs +++ b/src/EFCore.Cosmos/Storage/Internal/CosmosDatabaseCreator.cs @@ -31,10 +31,10 @@ public class CosmosDatabaseCreator : IDatabaseCreator /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public CosmosDatabaseCreator( - CosmosClientWrapper cosmosClient, - IModel model, - IUpdateAdapterFactory updateAdapterFactory, - IDatabase database) + [NotNull] CosmosClientWrapper cosmosClient, + [NotNull] IModel model, + [NotNull] IUpdateAdapterFactory updateAdapterFactory, + [NotNull] IDatabase database) { _cosmosClient = cosmosClient; _model = model; diff --git a/src/EFCore.Cosmos/Storage/Internal/CosmosDatabaseWrapper.cs b/src/EFCore.Cosmos/Storage/Internal/CosmosDatabaseWrapper.cs index 1ab86f24d0c..8a4d5c29903 100644 --- a/src/EFCore.Cosmos/Storage/Internal/CosmosDatabaseWrapper.cs +++ b/src/EFCore.Cosmos/Storage/Internal/CosmosDatabaseWrapper.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.Threading; using System.Threading.Tasks; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.ChangeTracking.Internal; using Microsoft.EntityFrameworkCore.Cosmos.Internal; using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal; @@ -48,9 +49,9 @@ private readonly Dictionary _documentCollections /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public CosmosDatabaseWrapper( - DatabaseDependencies dependencies, - CosmosClientWrapper cosmosClient, - ILoggingOptions loggingOptions) + [NotNull] DatabaseDependencies dependencies, + [NotNull] CosmosClientWrapper cosmosClient, + [NotNull] ILoggingOptions loggingOptions) : base(dependencies) { _cosmosClient = cosmosClient; @@ -284,7 +285,7 @@ private Task SaveAsync(IUpdateEntry entry, CancellationToken cancellationT /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual DocumentSource GetDocumentSource(IEntityType entityType) + public virtual DocumentSource GetDocumentSource([NotNull] IEntityType entityType) { if (!_documentCollections.TryGetValue(entityType, out var documentSource)) { diff --git a/src/EFCore.Cosmos/Storage/Internal/CosmosSqlQuery.cs b/src/EFCore.Cosmos/Storage/Internal/CosmosSqlQuery.cs index fb610db60a9..9519fa28dbd 100644 --- a/src/EFCore.Cosmos/Storage/Internal/CosmosSqlQuery.cs +++ b/src/EFCore.Cosmos/Storage/Internal/CosmosSqlQuery.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; +using JetBrains.Annotations; namespace Microsoft.EntityFrameworkCore.Cosmos.Storage.Internal { @@ -19,7 +20,7 @@ public class CosmosSqlQuery /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public CosmosSqlQuery(string query, IReadOnlyList parameters) + public CosmosSqlQuery([NotNull] string query, [NotNull] IReadOnlyList parameters) { Query = query; Parameters = parameters; diff --git a/src/EFCore.Cosmos/Storage/Internal/HttpException.cs b/src/EFCore.Cosmos/Storage/Internal/HttpException.cs index cf412b96d15..3e4371a3525 100644 --- a/src/EFCore.Cosmos/Storage/Internal/HttpException.cs +++ b/src/EFCore.Cosmos/Storage/Internal/HttpException.cs @@ -3,6 +3,7 @@ using System; using System.Net.Http; +using JetBrains.Annotations; namespace Microsoft.EntityFrameworkCore.Cosmos.Storage.Internal { @@ -20,7 +21,7 @@ public class HttpException : Exception /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public HttpException(HttpResponseMessage response) + public HttpException([NotNull] HttpResponseMessage response) : base(response.StatusCode.ToString()) { // An error occurred while sending the request. diff --git a/src/EFCore.Cosmos/Storage/Internal/SqlParameter.cs b/src/EFCore.Cosmos/Storage/Internal/SqlParameter.cs index fcaf8573f84..d24b407ca0c 100644 --- a/src/EFCore.Cosmos/Storage/Internal/SqlParameter.cs +++ b/src/EFCore.Cosmos/Storage/Internal/SqlParameter.cs @@ -1,6 +1,8 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using JetBrains.Annotations; + namespace Microsoft.EntityFrameworkCore.Cosmos.Storage.Internal { /// @@ -17,7 +19,7 @@ public class SqlParameter /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public SqlParameter(string name, object value) + public SqlParameter([NotNull] string name, [CanBeNull] object value) { Name = name; Value = value; diff --git a/src/EFCore.Cosmos/Update/Internal/DocumentSource.cs b/src/EFCore.Cosmos/Update/Internal/DocumentSource.cs index 5f9488625cb..1717ffebf16 100644 --- a/src/EFCore.Cosmos/Update/Internal/DocumentSource.cs +++ b/src/EFCore.Cosmos/Update/Internal/DocumentSource.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.ChangeTracking.Internal; using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal; using Microsoft.EntityFrameworkCore.Cosmos.Storage.Internal; @@ -31,7 +32,7 @@ public class DocumentSource /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public DocumentSource(IEntityType entityType, CosmosDatabaseWrapper database) + public DocumentSource([NotNull] IEntityType entityType, [NotNull] CosmosDatabaseWrapper database) { _collectionId = entityType.GetContainer(); _database = database; @@ -54,7 +55,7 @@ public virtual string GetCollectionId() /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual string GetId(IUpdateEntry entry) + public virtual string GetId([NotNull] IUpdateEntry entry) => entry.GetCurrentValue(_idProperty); /// @@ -63,7 +64,7 @@ public virtual string GetId(IUpdateEntry entry) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual JObject CreateDocument(IUpdateEntry entry) + public virtual JObject CreateDocument([NotNull] IUpdateEntry entry) { var document = new JObject(); foreach (var property in entry.EntityType.GetProperties()) @@ -122,7 +123,7 @@ public virtual JObject CreateDocument(IUpdateEntry entry) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual JObject UpdateDocument(JObject document, IUpdateEntry entry) + public virtual JObject UpdateDocument([NotNull] JObject document, [NotNull] IUpdateEntry entry) { var anyPropertyUpdated = false; foreach (var property in entry.EntityType.GetProperties()) @@ -210,7 +211,7 @@ public virtual JObject UpdateDocument(JObject document, IUpdateEntry entry) return anyPropertyUpdated ? document : null; } - public virtual JObject GetCurrentDocument(IUpdateEntry entry) + public virtual JObject GetCurrentDocument([NotNull] IUpdateEntry entry) => _jObjectProperty != null ? (JObject)(entry.SharedIdentityEntry ?? entry).GetCurrentValue(_jObjectProperty) : null; diff --git a/src/EFCore.Cosmos/ValueGeneration/Internal/CosmosValueGeneratorSelector.cs b/src/EFCore.Cosmos/ValueGeneration/Internal/CosmosValueGeneratorSelector.cs index a29951be860..a43e3f44142 100644 --- a/src/EFCore.Cosmos/ValueGeneration/Internal/CosmosValueGeneratorSelector.cs +++ b/src/EFCore.Cosmos/ValueGeneration/Internal/CosmosValueGeneratorSelector.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.ValueGeneration; using Microsoft.EntityFrameworkCore.ValueGeneration.Internal; @@ -10,7 +11,7 @@ namespace Microsoft.EntityFrameworkCore.Cosmos.ValueGeneration.Internal { public class CosmosValueGeneratorSelector : ValueGeneratorSelector { - public CosmosValueGeneratorSelector(ValueGeneratorSelectorDependencies dependencies) + public CosmosValueGeneratorSelector([NotNull] ValueGeneratorSelectorDependencies dependencies) : base(dependencies) { } diff --git a/src/EFCore.Design/Design/Internal/CSharpHelper.cs b/src/EFCore.Design/Design/Internal/CSharpHelper.cs index 75aab965b07..93b23a7667d 100644 --- a/src/EFCore.Design/Design/Internal/CSharpHelper.cs +++ b/src/EFCore.Design/Design/Internal/CSharpHelper.cs @@ -721,7 +721,7 @@ public virtual string Literal(Enum value) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected virtual string GetSimpleEnumValue(Type type, string name) + protected virtual string GetSimpleEnumValue([NotNull] Type type, [NotNull] string name) => Reference(type) + "." + name; /// @@ -730,7 +730,7 @@ protected virtual string GetSimpleEnumValue(Type type, string name) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected virtual string GetCompositeEnumValue(Type type, Enum flags) + protected virtual string GetCompositeEnumValue([NotNull] Type type, [NotNull] Enum flags) { var allValues = new HashSet(GetFlags(flags)); foreach (var currentValue in allValues.ToList()) diff --git a/src/EFCore.Design/Design/Internal/LanguageBasedSelector.cs b/src/EFCore.Design/Design/Internal/LanguageBasedSelector.cs index 3b9f465c9ea..20b2b969ff7 100644 --- a/src/EFCore.Design/Design/Internal/LanguageBasedSelector.cs +++ b/src/EFCore.Design/Design/Internal/LanguageBasedSelector.cs @@ -25,7 +25,7 @@ public abstract class LanguageBasedSelector /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected LanguageBasedSelector(IEnumerable services) + protected LanguageBasedSelector([NotNull] IEnumerable services) => Services = services; /// diff --git a/src/EFCore.Design/Metadata/Internal/ScaffoldingEntityTypeAnnotations.cs b/src/EFCore.Design/Metadata/Internal/ScaffoldingEntityTypeAnnotations.cs index 65d7798824a..5c45cbeb333 100644 --- a/src/EFCore.Design/Metadata/Internal/ScaffoldingEntityTypeAnnotations.cs +++ b/src/EFCore.Design/Metadata/Internal/ScaffoldingEntityTypeAnnotations.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Metadata.Internal @@ -19,7 +20,7 @@ public static class ScaffoldingEntityTypeAnnotations /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public static string GetDbSetName(this IEntityType entityType) + public static string GetDbSetName([NotNull] this IEntityType entityType) => (string)entityType[ScaffoldingAnnotationNames.DbSetName] ?? entityType.Name; @@ -29,7 +30,7 @@ public static string GetDbSetName(this IEntityType entityType) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public static void SetDbSetName(this IMutableEntityType entityType, string value) => + public static void SetDbSetName([NotNull] this IMutableEntityType entityType, [CanBeNull] string value) => entityType.SetAnnotation( ScaffoldingAnnotationNames.DbSetName, Check.NullButNotEmpty(value, nameof(value))); diff --git a/src/EFCore.Design/Metadata/Internal/ScaffoldingModelExtensions.cs b/src/EFCore.Design/Metadata/Internal/ScaffoldingModelExtensions.cs index 7bd093f278e..faf0fdf0b8c 100644 --- a/src/EFCore.Design/Metadata/Internal/ScaffoldingModelExtensions.cs +++ b/src/EFCore.Design/Metadata/Internal/ScaffoldingModelExtensions.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Metadata.Internal @@ -20,7 +21,7 @@ public static class ScaffoldingModelExtensions /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public static IDictionary GetEntityTypeErrors(this IModel model) + public static IDictionary GetEntityTypeErrors([NotNull] this IModel model) { var errors = (IDictionary)model[ScaffoldingAnnotationNames.EntityTypeErrors]; if (errors == null) @@ -38,7 +39,7 @@ public static IDictionary GetEntityTypeErrors(this IModel model) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public static void SetEntityTypeErrors(this IMutableModel model, IDictionary value) => + public static void SetEntityTypeErrors([NotNull] this IMutableModel model, [NotNull] IDictionary value) => model.SetAnnotation( ScaffoldingAnnotationNames.EntityTypeErrors, Check.NotNull(value, nameof(value))); @@ -49,7 +50,7 @@ public static void SetEntityTypeErrors(this IMutableModel model, IDictionary - public static string GetDatabaseName(this IModel model) + public static string GetDatabaseName([NotNull] this IModel model) => (string)model[ScaffoldingAnnotationNames.DatabaseName]; /// @@ -58,7 +59,7 @@ public static string GetDatabaseName(this IModel model) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public static void SetDatabaseName(this IMutableModel model, string value) => + public static void SetDatabaseName([NotNull] this IMutableModel model, [CanBeNull] string value) => model.SetAnnotation( ScaffoldingAnnotationNames.DatabaseName, Check.NullButNotEmpty(value, nameof(value))); diff --git a/src/EFCore.Design/Scaffolding/Internal/CSharpUtilities.cs b/src/EFCore.Design/Scaffolding/Internal/CSharpUtilities.cs index 2e2fb86ddb5..637039bce31 100644 --- a/src/EFCore.Design/Scaffolding/Internal/CSharpUtilities.cs +++ b/src/EFCore.Design/Scaffolding/Internal/CSharpUtilities.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Globalization; using System.Text.RegularExpressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Scaffolding.Internal @@ -176,7 +177,7 @@ public virtual string GenerateCSharpIdentifier( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual string Uniquifier( - string proposedIdentifier, ICollection existingIdentifiers) + [NotNull] string proposedIdentifier, [CanBeNull] ICollection existingIdentifiers) { Check.NotEmpty(proposedIdentifier, nameof(proposedIdentifier)); diff --git a/src/EFCore.Design/Scaffolding/Internal/ICSharpDbContextGenerator.cs b/src/EFCore.Design/Scaffolding/Internal/ICSharpDbContextGenerator.cs index 44dd735ede7..59378ed88d5 100644 --- a/src/EFCore.Design/Scaffolding/Internal/ICSharpDbContextGenerator.cs +++ b/src/EFCore.Design/Scaffolding/Internal/ICSharpDbContextGenerator.cs @@ -24,8 +24,8 @@ string WriteCode( [NotNull] IModel model, [NotNull] string contextName, [NotNull] string connectionString, - string contextNamespace, - string modelNamespace, + [NotNull] string contextNamespace, + [NotNull] string modelNamespace, bool useDataAnnotations, bool suppressConnectionStringWarning); } diff --git a/src/EFCore.InMemory/Query/Internal/EntityProjectionExpression.cs b/src/EFCore.InMemory/Query/Internal/EntityProjectionExpression.cs index 39cebbae6e9..c11b7271291 100644 --- a/src/EFCore.InMemory/Query/Internal/EntityProjectionExpression.cs +++ b/src/EFCore.InMemory/Query/Internal/EntityProjectionExpression.cs @@ -4,8 +4,10 @@ using System; using System.Collections.Generic; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal { @@ -17,7 +19,7 @@ private readonly IDictionary _navigationExp = new Dictionary(); public EntityProjectionExpression( - IEntityType entityType, IDictionary readExpressionMap) + [NotNull] IEntityType entityType, [NotNull] IDictionary readExpressionMap) { EntityType = entityType; _readExpressionMap = readExpressionMap; @@ -27,7 +29,7 @@ public EntityProjectionExpression( public override Type Type => EntityType.ClrType; public sealed override ExpressionType NodeType => ExpressionType.Extension; - public virtual EntityProjectionExpression UpdateEntityType(IEntityType derivedType) + public virtual EntityProjectionExpression UpdateEntityType([NotNull] IEntityType derivedType) { var readExpressionMap = new Dictionary(); foreach (var kvp in _readExpressionMap) @@ -43,7 +45,7 @@ public virtual EntityProjectionExpression UpdateEntityType(IEntityType derivedTy return new EntityProjectionExpression(derivedType, readExpressionMap); } - public virtual Expression BindProperty(IProperty property) + public virtual Expression BindProperty([NotNull] IProperty property) { if (!EntityType.IsAssignableFrom(property.DeclaringEntityType) && !property.DeclaringEntityType.IsAssignableFrom(EntityType)) @@ -55,7 +57,7 @@ public virtual Expression BindProperty(IProperty property) return _readExpressionMap[property]; } - public virtual void AddNavigationBinding(INavigation navigation, EntityShaperExpression entityShaper) + public virtual void AddNavigationBinding([NotNull] INavigation navigation, [NotNull] EntityShaperExpression entityShaper) { if (!EntityType.IsAssignableFrom(navigation.DeclaringEntityType) && !navigation.DeclaringEntityType.IsAssignableFrom(EntityType)) @@ -68,7 +70,7 @@ public virtual void AddNavigationBinding(INavigation navigation, EntityShaperExp _navigationExpressionsCache[navigation] = entityShaper; } - public virtual EntityShaperExpression BindNavigation(INavigation navigation) + public virtual EntityShaperExpression BindNavigation([NotNull] INavigation navigation) { if (!EntityType.IsAssignableFrom(navigation.DeclaringEntityType) && !navigation.DeclaringEntityType.IsAssignableFrom(EntityType)) @@ -85,6 +87,8 @@ public virtual EntityShaperExpression BindNavigation(INavigation navigation) public virtual void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.AppendLine(nameof(EntityProjectionExpression) + ":"); using (expressionPrinter.Indent()) { diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs index d978837fede..1b50e9a92e5 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs @@ -7,11 +7,13 @@ using System.Linq; using System.Linq.Expressions; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal { @@ -23,7 +25,7 @@ public class InMemoryExpressionTranslatingExpressionVisitor : ExpressionVisitor private readonly EntityProjectionFindingExpressionVisitor _entityProjectionFindingExpressionVisitor; public InMemoryExpressionTranslatingExpressionVisitor( - QueryableMethodTranslatingExpressionVisitor queryableMethodTranslatingExpressionVisitor) + [NotNull] QueryableMethodTranslatingExpressionVisitor queryableMethodTranslatingExpressionVisitor) { _queryableMethodTranslatingExpressionVisitor = queryableMethodTranslatingExpressionVisitor; _entityProjectionFindingExpressionVisitor = new EntityProjectionFindingExpressionVisitor(); @@ -59,7 +61,7 @@ public override Expression Visit(Expression expression) } } - public virtual Expression Translate(Expression expression) + public virtual Expression Translate([NotNull] Expression expression) { var result = Visit(expression); @@ -70,6 +72,8 @@ public virtual Expression Translate(Expression expression) protected override Expression VisitBinary(BinaryExpression binaryExpression) { + Check.NotNull(binaryExpression, nameof(binaryExpression)); + var newLeft = Visit(binaryExpression.Left); var newRight = Visit(binaryExpression.Right); @@ -97,6 +101,8 @@ protected override Expression VisitBinary(BinaryExpression binaryExpression) protected override Expression VisitConditional(ConditionalExpression conditionalExpression) { + Check.NotNull(conditionalExpression, nameof(conditionalExpression)); + var test = Visit(conditionalExpression.Test); var ifTrue = Visit(conditionalExpression.IfTrue); var ifFalse = Visit(conditionalExpression.IfFalse); @@ -125,6 +131,8 @@ protected override Expression VisitConditional(ConditionalExpression conditional protected override Expression VisitMember(MemberExpression memberExpression) { + Check.NotNull(memberExpression, nameof(memberExpression)); + if (TryBindMember( memberExpression.Expression, MemberIdentity.Create(memberExpression.Member), @@ -264,6 +272,8 @@ private Expression GetPredicate(MethodCallExpression methodCallExpression, Group protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { + Check.NotNull(methodCallExpression, nameof(methodCallExpression)); + if (methodCallExpression.Method.IsGenericMethod && methodCallExpression.Method.GetGenericMethodDefinition() == EntityMaterializerSource.TryReadValueMethod) { @@ -478,6 +488,8 @@ MethodInfo GetMethod() protected override Expression VisitTypeBinary(TypeBinaryExpression typeBinaryExpression) { + Check.NotNull(typeBinaryExpression, nameof(typeBinaryExpression)); + if (typeBinaryExpression.NodeType == ExpressionType.TypeIs && Visit(typeBinaryExpression.Expression) is EntityProjectionExpression entityProjectionExpression) { @@ -516,6 +528,8 @@ protected override Expression VisitTypeBinary(TypeBinaryExpression typeBinaryExp protected override Expression VisitNew(NewExpression newExpression) { + Check.NotNull(newExpression, nameof(newExpression)); + var newArguments = new List(); foreach (var argument in newExpression.Arguments) { @@ -538,6 +552,8 @@ protected override Expression VisitNew(NewExpression newExpression) protected override Expression VisitNewArray(NewArrayExpression newArrayExpression) { + Check.NotNull(newArrayExpression, nameof(newArrayExpression)); + var newExpressions = new List(); foreach (var expression in newArrayExpression.Expressions) { @@ -576,6 +592,8 @@ protected override MemberAssignment VisitMemberAssignment(MemberAssignment membe protected override Expression VisitExtension(Expression extensionExpression) { + Check.NotNull(extensionExpression, nameof(extensionExpression)); + switch (extensionExpression) { case EntityProjectionExpression _: @@ -595,14 +613,31 @@ protected override Expression VisitExtension(Expression extensionExpression) } } - protected override Expression VisitListInit(ListInitExpression node) => null; + protected override Expression VisitListInit(ListInitExpression node) + { + Check.NotNull(node, nameof(node)); - protected override Expression VisitInvocation(InvocationExpression node) => null; + return null; + } - protected override Expression VisitLambda(Expression node) => null; + protected override Expression VisitInvocation(InvocationExpression node) + { + Check.NotNull(node, nameof(node)); + + return null; + } + + protected override Expression VisitLambda(Expression node) + { + Check.NotNull(node, nameof(node)); + + return null; + } protected override Expression VisitParameter(ParameterExpression parameterExpression) { + Check.NotNull(parameterExpression, nameof(parameterExpression)); + if (parameterExpression.Name.StartsWith(CompiledQueryParameterPrefix, StringComparison.Ordinal)) { return Expression.Call( @@ -625,6 +660,8 @@ private static T GetParameterValue(QueryContext queryContext, string paramete protected override Expression VisitUnary(UnaryExpression unaryExpression) { + Check.NotNull(unaryExpression, nameof(unaryExpression)); + var newOperand = Visit(unaryExpression.Operand); if (newOperand == null) { diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryGroupByShaperExpression.cs b/src/EFCore.InMemory/Query/Internal/InMemoryGroupByShaperExpression.cs index 4dfefd23622..694dba96e16 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryGroupByShaperExpression.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryGroupByShaperExpression.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal @@ -9,10 +10,10 @@ namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal public class InMemoryGroupByShaperExpression : GroupByShaperExpression { public InMemoryGroupByShaperExpression( - Expression keySelector, - Expression elementSelector, - ParameterExpression groupingParameter, - ParameterExpression valueBufferParameter) + [NotNull] Expression keySelector, + [NotNull] Expression elementSelector, + [NotNull] ParameterExpression groupingParameter, + [NotNull] ParameterExpression valueBufferParameter) : base(keySelector, elementSelector) { GroupingParameter = groupingParameter; diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryProjectionBindingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/InMemoryProjectionBindingExpressionVisitor.cs index 446eaf6829f..bc4f2d75663 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryProjectionBindingExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryProjectionBindingExpressionVisitor.cs @@ -5,11 +5,13 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal { @@ -27,14 +29,14 @@ private readonly IDictionary _projectionMapping private readonly Stack _projectionMembers = new Stack(); public InMemoryProjectionBindingExpressionVisitor( - InMemoryQueryableMethodTranslatingExpressionVisitor queryableMethodTranslatingExpressionVisitor, - InMemoryExpressionTranslatingExpressionVisitor expressionTranslatingExpressionVisitor) + [NotNull] InMemoryQueryableMethodTranslatingExpressionVisitor queryableMethodTranslatingExpressionVisitor, + [NotNull] InMemoryExpressionTranslatingExpressionVisitor expressionTranslatingExpressionVisitor) { _queryableMethodTranslatingExpressionVisitor = queryableMethodTranslatingExpressionVisitor; _expressionTranslatingExpressionVisitor = expressionTranslatingExpressionVisitor; } - public virtual Expression Translate(InMemoryQueryExpression queryExpression, Expression expression) + public virtual Expression Translate([NotNull] InMemoryQueryExpression queryExpression, [NotNull] Expression expression) { _queryExpression = queryExpression; _clientEval = false; @@ -186,6 +188,8 @@ private CollectionShaperExpression AddCollectionProjection( protected override Expression VisitExtension(Expression extensionExpression) { + Check.NotNull(extensionExpression, nameof(extensionExpression)); + if (extensionExpression is EntityShaperExpression entityShaperExpression) { EntityProjectionExpression entityProjectionExpression; @@ -224,6 +228,8 @@ protected override Expression VisitExtension(Expression extensionExpression) protected override Expression VisitNew(NewExpression newExpression) { + Check.NotNull(newExpression, nameof(newExpression)); + if (newExpression.Arguments.Count == 0) { return newExpression; @@ -261,6 +267,8 @@ protected override Expression VisitNew(NewExpression newExpression) protected override Expression VisitMemberInit(MemberInitExpression memberInitExpression) { + Check.NotNull(memberInitExpression, nameof(memberInitExpression)); + var newExpression = Visit(memberInitExpression.NewExpression); if (newExpression == null) { diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs b/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs index 67e1104142c..b2b68f22bc3 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs @@ -6,10 +6,12 @@ using System.Linq; using System.Linq.Expressions; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal { @@ -32,12 +34,12 @@ private readonly IDictionary Projection => _valueBufferSlots; - public virtual Expression ServerQueryExpression { get; set; } + public virtual Expression ServerQueryExpression { get; [param: NotNull] set; } public virtual ParameterExpression CurrentParameter => _groupingParameter ?? _valueBufferParameter; public override Type Type => typeof(IEnumerable); public sealed override ExpressionType NodeType => ExpressionType.Extension; - public InMemoryQueryExpression(IEntityType entityType) + public InMemoryQueryExpression([NotNull] IEntityType entityType) { _valueBufferParameter = Parameter(typeof(ValueBuffer), "valueBuffer"); ServerQueryExpression = new InMemoryTableExpression(entityType); @@ -101,7 +103,7 @@ public virtual void ConvertToEnumerable() } } - public virtual void ReplaceProjectionMapping(IDictionary projectionMappings) + public virtual void ReplaceProjectionMapping([NotNull] IDictionary projectionMappings) { _projectionMapping.Clear(); foreach (var kvp in projectionMappings) @@ -110,7 +112,7 @@ public virtual void ReplaceProjectionMapping(IDictionary AddToProjection(EntityProjectionExpression entityProjectionExpression) + public virtual IDictionary AddToProjection([NotNull] EntityProjectionExpression entityProjectionExpression) { if (!_entityProjectionCache.TryGetValue(entityProjectionExpression, out var indexMap)) { @@ -126,14 +128,14 @@ public virtual IDictionary AddToProjection(EntityProjectionExpre return indexMap; } - public virtual int AddToProjection(Expression expression) + public virtual int AddToProjection([NotNull] Expression expression) { _valueBufferSlots.Add(expression); return _valueBufferSlots.Count - 1; } - public virtual int AddSubqueryProjection(ShapedQueryExpression shapedQueryExpression, out Expression innerShaper) + public virtual int AddSubqueryProjection([NotNull] ShapedQueryExpression shapedQueryExpression, [CanBeNull] out Expression innerShaper) { var subquery = (InMemoryQueryExpression)shapedQueryExpression.QueryExpression; subquery.ApplyProjection(); @@ -193,7 +195,7 @@ public override Expression Visit(Expression expression) private IEnumerable GetAllPropertiesInHierarchy(IEntityType entityType) => entityType.GetTypesInHierarchy().SelectMany(EntityTypeExtensions.GetDeclaredProperties); - public virtual Expression GetMappedProjection(ProjectionMember member) + public virtual Expression GetMappedProjection([NotNull] ProjectionMember member) => _projectionMapping[member]; public virtual void PushdownIntoSubquery() @@ -368,7 +370,7 @@ public virtual void ApplyProjection() selectorLambda); } - public virtual InMemoryGroupByShaperExpression ApplyGrouping(Expression groupingKey, Expression shaperExpression) + public virtual InMemoryGroupByShaperExpression ApplyGrouping([NotNull] Expression groupingKey, [NotNull] Expression shaperExpression) { PushdownIntoSubquery(); @@ -458,10 +460,10 @@ private Expression CreateReadValueExpression(Type type, int index, IPropertyBase => CreateReadValueExpression(_valueBufferParameter, type, index, property); public virtual void AddInnerJoin( - InMemoryQueryExpression innerQueryExpression, - LambdaExpression outerKeySelector, - LambdaExpression innerKeySelector, - Type transparentIdentifierType) + [NotNull] InMemoryQueryExpression innerQueryExpression, + [NotNull] LambdaExpression outerKeySelector, + [NotNull] LambdaExpression innerKeySelector, + [CanBeNull] Type transparentIdentifierType) { var outerParameter = Parameter(typeof(ValueBuffer), "outer"); var innerParameter = Parameter(typeof(ValueBuffer), "inner"); @@ -546,10 +548,10 @@ public virtual void AddInnerJoin( } public virtual void AddLeftJoin( - InMemoryQueryExpression innerQueryExpression, - LambdaExpression outerKeySelector, - LambdaExpression innerKeySelector, - Type transparentIdentifierType) + [NotNull] InMemoryQueryExpression innerQueryExpression, + [NotNull] LambdaExpression outerKeySelector, + [NotNull] LambdaExpression innerKeySelector, + [CanBeNull] Type transparentIdentifierType) { // GroupJoin phase var groupTransparentIdentifierType = TransparentIdentifierFactory.Create( @@ -676,7 +678,8 @@ public virtual void AddLeftJoin( _projectionMapping = projectionMapping; } - public virtual void AddSelectMany(InMemoryQueryExpression innerQueryExpression, Type transparentIdentifierType, bool innerNullable) + public virtual void AddSelectMany( + [NotNull] InMemoryQueryExpression innerQueryExpression, [CanBeNull] Type transparentIdentifierType, bool innerNullable) { var outerParameter = Parameter(typeof(ValueBuffer), "outer"); var innerParameter = Parameter(typeof(ValueBuffer), "inner"); @@ -771,11 +774,11 @@ public virtual void AddSelectMany(InMemoryQueryExpression innerQueryExpression, } public virtual EntityShaperExpression AddNavigationToWeakEntityType( - EntityProjectionExpression entityProjectionExpression, - INavigation navigation, - InMemoryQueryExpression innerQueryExpression, - LambdaExpression outerKeySelector, - LambdaExpression innerKeySelector) + [NotNull] EntityProjectionExpression entityProjectionExpression, + [NotNull] INavigation navigation, + [NotNull] InMemoryQueryExpression innerQueryExpression, + [NotNull] LambdaExpression outerKeySelector, + [NotNull] LambdaExpression innerKeySelector) { // GroupJoin phase var groupTransparentIdentifierType = TransparentIdentifierFactory.Create( @@ -918,6 +921,8 @@ EntityProjectionExpression copyEntityProjectionToOuter(EntityProjectionExpressio public virtual void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.AppendLine(nameof(InMemoryQueryExpression) + ": "); using (expressionPrinter.Indent()) { @@ -945,6 +950,8 @@ private sealed class NullableReadValueExpressionVisitor : ExpressionVisitor { protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { + Check.NotNull(methodCallExpression, nameof(methodCallExpression)); + if (methodCallExpression.Method.IsGenericMethod && methodCallExpression.Method.GetGenericMethodDefinition() == EntityMaterializerSource.TryReadValueMethod && !methodCallExpression.Type.IsNullableType()) @@ -959,6 +966,8 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp protected override Expression VisitConditional(ConditionalExpression conditionalExpression) { + Check.NotNull(conditionalExpression, nameof(conditionalExpression)); + var test = Visit(conditionalExpression.Test); var ifTrue = Visit(conditionalExpression.IfTrue); var ifFalse = Visit(conditionalExpression.IfFalse); diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryQueryTranslationPostprocessor.cs b/src/EFCore.InMemory/Query/Internal/InMemoryQueryTranslationPostprocessor.cs index 9fb2c89adec..d7d21b84a85 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryQueryTranslationPostprocessor.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryQueryTranslationPostprocessor.cs @@ -2,13 +2,14 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal { public class InMemoryQueryTranslationPostprocessor : QueryTranslationPostprocessor { - public InMemoryQueryTranslationPostprocessor(QueryTranslationPostprocessorDependencies dependencies) + public InMemoryQueryTranslationPostprocessor([NotNull] QueryTranslationPostprocessorDependencies dependencies) : base(dependencies) { } diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryQueryTranslationPostprocessorFactory.cs b/src/EFCore.InMemory/Query/Internal/InMemoryQueryTranslationPostprocessorFactory.cs index 8c1208ef35b..a7474b3d89e 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryQueryTranslationPostprocessorFactory.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryQueryTranslationPostprocessorFactory.cs @@ -1,7 +1,9 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal @@ -23,13 +25,15 @@ public class InMemoryQueryTranslationPostprocessorFactory : IQueryTranslationPos { private readonly QueryTranslationPostprocessorDependencies _dependencies; - public InMemoryQueryTranslationPostprocessorFactory(QueryTranslationPostprocessorDependencies dependencies) + public InMemoryQueryTranslationPostprocessorFactory([NotNull] QueryTranslationPostprocessorDependencies dependencies) { _dependencies = dependencies; } public virtual QueryTranslationPostprocessor Create(QueryCompilationContext queryCompilationContext) { + Check.NotNull(queryCompilationContext, nameof(queryCompilationContext)); + return new InMemoryQueryTranslationPostprocessor(_dependencies); } } diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitor.cs index 9770054255f..e5d23b667fc 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitor.cs @@ -6,12 +6,14 @@ using System.Linq; using System.Linq.Expressions; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal { @@ -25,8 +27,8 @@ public class InMemoryQueryableMethodTranslatingExpressionVisitor : QueryableMeth private readonly IModel _model; public InMemoryQueryableMethodTranslatingExpressionVisitor( - QueryableMethodTranslatingExpressionVisitorDependencies dependencies, - IModel model) + [NotNull] QueryableMethodTranslatingExpressionVisitorDependencies dependencies, + [NotNull] IModel model) : base(dependencies, subquery: false) { _expressionTranslator = new InMemoryExpressionTranslatingExpressionVisitor(this); @@ -36,7 +38,7 @@ public InMemoryQueryableMethodTranslatingExpressionVisitor( } protected InMemoryQueryableMethodTranslatingExpressionVisitor( - InMemoryQueryableMethodTranslatingExpressionVisitor parentVisitor) + [NotNull] InMemoryQueryableMethodTranslatingExpressionVisitor parentVisitor) : base(parentVisitor.Dependencies, subquery: true) { _expressionTranslator = parentVisitor._expressionTranslator; @@ -49,7 +51,11 @@ protected override QueryableMethodTranslatingExpressionVisitor CreateSubqueryVis => new InMemoryQueryableMethodTranslatingExpressionVisitor(this); protected override ShapedQueryExpression CreateShapedQueryExpression(Type elementType) - => CreateShapedQueryExpression(_model.FindEntityType(elementType)); + { + Check.NotNull(elementType, nameof(elementType)); + + return CreateShapedQueryExpression(_model.FindEntityType(elementType)); + } private static ShapedQueryExpression CreateShapedQueryExpression(IEntityType entityType) { @@ -68,6 +74,9 @@ private static ShapedQueryExpression CreateShapedQueryExpression(IEntityType ent protected override ShapedQueryExpression TranslateAll(ShapedQueryExpression source, LambdaExpression predicate) { + Check.NotNull(source, nameof(source)); + Check.NotNull(predicate, nameof(predicate)); + var inMemoryQueryExpression = (InMemoryQueryExpression)source.QueryExpression; predicate = TranslateLambdaExpression(source, predicate, preserveType: true); if (predicate == null) @@ -116,10 +125,18 @@ protected override ShapedQueryExpression TranslateAny(ShapedQueryExpression sour } protected override ShapedQueryExpression TranslateAverage(ShapedQueryExpression source, LambdaExpression selector, Type resultType) - => TranslateScalarAggregate(source, selector, nameof(Enumerable.Average)); + { + Check.NotNull(source, nameof(source)); + Check.NotNull(resultType, nameof(resultType)); + + return TranslateScalarAggregate(source, selector, nameof(Enumerable.Average)); + } protected override ShapedQueryExpression TranslateCast(ShapedQueryExpression source, Type resultType) { + Check.NotNull(source, nameof(source)); + Check.NotNull(resultType, nameof(resultType)); + if (source.ShaperExpression.Type == resultType) { return source; @@ -131,10 +148,18 @@ protected override ShapedQueryExpression TranslateCast(ShapedQueryExpression sou } protected override ShapedQueryExpression TranslateConcat(ShapedQueryExpression source1, ShapedQueryExpression source2) - => TranslateSetOperation(EnumerableMethods.Concat, source1, source2); + { + Check.NotNull(source1, nameof(source1)); + Check.NotNull(source2, nameof(source2)); + + return TranslateSetOperation(EnumerableMethods.Concat, source1, source2); + } protected override ShapedQueryExpression TranslateContains(ShapedQueryExpression source, Expression item) { + Check.NotNull(source, nameof(source)); + Check.NotNull(item, nameof(item)); + var inMemoryQueryExpression = (InMemoryQueryExpression)source.QueryExpression; item = TranslateExpression(item, preserveType: true); if (item == null) @@ -159,6 +184,8 @@ protected override ShapedQueryExpression TranslateContains(ShapedQueryExpression protected override ShapedQueryExpression TranslateCount(ShapedQueryExpression source, LambdaExpression predicate) { + Check.NotNull(source, nameof(source)); + var inMemoryQueryExpression = (InMemoryQueryExpression)source.QueryExpression; if (predicate == null) @@ -190,6 +217,8 @@ protected override ShapedQueryExpression TranslateCount(ShapedQueryExpression so protected override ShapedQueryExpression TranslateDefaultIfEmpty(ShapedQueryExpression source, Expression defaultValue) { + Check.NotNull(source, nameof(source)); + if (defaultValue == null) { ((InMemoryQueryExpression)source.QueryExpression).ApplyDefaultIfEmpty(); @@ -203,6 +232,8 @@ protected override ShapedQueryExpression TranslateDefaultIfEmpty(ShapedQueryExpr protected override ShapedQueryExpression TranslateDistinct(ShapedQueryExpression source) { + Check.NotNull(source, nameof(source)); + var inMemoryQueryExpression = (InMemoryQueryExpression)source.QueryExpression; inMemoryQueryExpression.PushdownIntoSubquery(); @@ -216,14 +247,27 @@ protected override ShapedQueryExpression TranslateDistinct(ShapedQueryExpression protected override ShapedQueryExpression TranslateElementAtOrDefault( ShapedQueryExpression source, Expression index, bool returnDefault) - => null; + { + Check.NotNull(source, nameof(source)); + Check.NotNull(index, nameof(index)); + + return null; + } protected override ShapedQueryExpression TranslateExcept(ShapedQueryExpression source1, ShapedQueryExpression source2) - => TranslateSetOperation(EnumerableMethods.Except, source1, source2); + { + Check.NotNull(source1, nameof(source1)); + Check.NotNull(source2, nameof(source2)); + + return TranslateSetOperation(EnumerableMethods.Except, source1, source2); + } protected override ShapedQueryExpression TranslateFirstOrDefault( ShapedQueryExpression source, LambdaExpression predicate, Type returnType, bool returnDefault) { + Check.NotNull(source, nameof(source)); + Check.NotNull(returnType, nameof(returnType)); + return TranslateSingleResultOperator( source, predicate, @@ -236,6 +280,9 @@ protected override ShapedQueryExpression TranslateFirstOrDefault( protected override ShapedQueryExpression TranslateGroupBy( ShapedQueryExpression source, LambdaExpression keySelector, LambdaExpression elementSelector, LambdaExpression resultSelector) { + Check.NotNull(source, nameof(source)); + Check.NotNull(keySelector, nameof(keySelector)); + var remappedKeySelector = RemapLambdaBody(source, keySelector); var translatedKey = TranslateGroupingKey(remappedKeySelector); @@ -334,17 +381,40 @@ private Expression TranslateGroupingKey(Expression expression) } protected override ShapedQueryExpression TranslateGroupJoin( - ShapedQueryExpression outer, ShapedQueryExpression inner, LambdaExpression outerKeySelector, LambdaExpression innerKeySelector, + ShapedQueryExpression outer, + ShapedQueryExpression inner, + LambdaExpression outerKeySelector, + LambdaExpression innerKeySelector, LambdaExpression resultSelector) - => null; + { + Check.NotNull(outer, nameof(outer)); + Check.NotNull(inner, nameof(inner)); + Check.NotNull(outerKeySelector, nameof(outerKeySelector)); + Check.NotNull(innerKeySelector, nameof(innerKeySelector)); + Check.NotNull(resultSelector, nameof(resultSelector)); + + return null; + } protected override ShapedQueryExpression TranslateIntersect(ShapedQueryExpression source1, ShapedQueryExpression source2) - => TranslateSetOperation(EnumerableMethods.Intersect, source1, source2); + { + Check.NotNull(source1, nameof(source1)); + Check.NotNull(source2, nameof(source2)); + + return TranslateSetOperation(EnumerableMethods.Intersect, source1, source2); + } protected override ShapedQueryExpression TranslateJoin( - ShapedQueryExpression outer, ShapedQueryExpression inner, LambdaExpression outerKeySelector, LambdaExpression innerKeySelector, + ShapedQueryExpression outer, + ShapedQueryExpression inner, + LambdaExpression outerKeySelector, + LambdaExpression innerKeySelector, LambdaExpression resultSelector) { + Check.NotNull(outer, nameof(outer)); + Check.NotNull(inner, nameof(inner)); + Check.NotNull(resultSelector, nameof(resultSelector)); + outerKeySelector = TranslateLambdaExpression(outer, outerKeySelector); innerKeySelector = TranslateLambdaExpression(inner, innerKeySelector); if (outerKeySelector == null @@ -400,6 +470,9 @@ static bool isConvertedToNullable(Expression outer, Expression inner) protected override ShapedQueryExpression TranslateLastOrDefault( ShapedQueryExpression source, LambdaExpression predicate, Type returnType, bool returnDefault) { + Check.NotNull(source, nameof(source)); + Check.NotNull(returnType, nameof(returnType)); + return TranslateSingleResultOperator( source, predicate, @@ -413,6 +486,10 @@ protected override ShapedQueryExpression TranslateLeftJoin( ShapedQueryExpression outer, ShapedQueryExpression inner, LambdaExpression outerKeySelector, LambdaExpression innerKeySelector, LambdaExpression resultSelector) { + Check.NotNull(outer, nameof(outer)); + Check.NotNull(inner, nameof(inner)); + Check.NotNull(resultSelector, nameof(resultSelector)); + outerKeySelector = TranslateLambdaExpression(outer, outerKeySelector); innerKeySelector = TranslateLambdaExpression(inner, innerKeySelector); if (outerKeySelector == null @@ -440,8 +517,11 @@ protected override ShapedQueryExpression TranslateLeftJoin( transparentIdentifierType); } - protected override ShapedQueryExpression TranslateLongCount(ShapedQueryExpression source, LambdaExpression predicate) + protected override ShapedQueryExpression TranslateLongCount( + ShapedQueryExpression source, LambdaExpression predicate) { + Check.NotNull(source, nameof(source)); + var inMemoryQueryExpression = (InMemoryQueryExpression)source.QueryExpression; if (predicate == null) @@ -473,14 +553,26 @@ protected override ShapedQueryExpression TranslateLongCount(ShapedQueryExpressio return source; } - protected override ShapedQueryExpression TranslateMax(ShapedQueryExpression source, LambdaExpression selector, Type resultType) - => TranslateScalarAggregate(source, selector, nameof(Enumerable.Max)); + protected override ShapedQueryExpression TranslateMax( + ShapedQueryExpression source, LambdaExpression selector, Type resultType) + { + Check.NotNull(source, nameof(source)); + + return TranslateScalarAggregate(source, selector, nameof(Enumerable.Max)); + } protected override ShapedQueryExpression TranslateMin(ShapedQueryExpression source, LambdaExpression selector, Type resultType) - => TranslateScalarAggregate(source, selector, nameof(Enumerable.Min)); + { + Check.NotNull(source, nameof(source)); + + return TranslateScalarAggregate(source, selector, nameof(Enumerable.Min)); + } protected override ShapedQueryExpression TranslateOfType(ShapedQueryExpression source, Type resultType) { + Check.NotNull(source, nameof(source)); + Check.NotNull(resultType, nameof(resultType)); + if (source.ShaperExpression is EntityShaperExpression entityShaperExpression) { var entityType = entityShaperExpression.EntityType; @@ -556,6 +648,9 @@ protected override ShapedQueryExpression TranslateOfType(ShapedQueryExpression s protected override ShapedQueryExpression TranslateOrderBy( ShapedQueryExpression source, LambdaExpression keySelector, bool ascending) { + Check.NotNull(source, nameof(source)); + Check.NotNull(keySelector, nameof(keySelector)); + var inMemoryQueryExpression = (InMemoryQueryExpression)source.QueryExpression; keySelector = TranslateLambdaExpression(source, keySelector); @@ -575,10 +670,17 @@ protected override ShapedQueryExpression TranslateOrderBy( } protected override ShapedQueryExpression TranslateReverse(ShapedQueryExpression source) - => null; + { + Check.NotNull(source, nameof(source)); + + return null; + } protected override ShapedQueryExpression TranslateSelect(ShapedQueryExpression source, LambdaExpression selector) { + Check.NotNull(source, nameof(source)); + Check.NotNull(selector, nameof(selector)); + if (selector.Body == selector.Parameters[0]) { return source; @@ -603,6 +705,10 @@ protected override ShapedQueryExpression TranslateSelect(ShapedQueryExpression s protected override ShapedQueryExpression TranslateSelectMany( ShapedQueryExpression source, LambdaExpression collectionSelector, LambdaExpression resultSelector) { + Check.NotNull(source, nameof(source)); + Check.NotNull(collectionSelector, nameof(collectionSelector)); + Check.NotNull(resultSelector, nameof(resultSelector)); + var defaultIfEmpty = new DefaultIfEmptyFindingExpressionVisitor().IsOptional(collectionSelector); var collectionSelectorBody = RemapLambdaBody(source, collectionSelector); @@ -644,6 +750,8 @@ public bool IsOptional(LambdaExpression lambdaExpression) protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { + Check.NotNull(methodCallExpression, nameof(methodCallExpression)); + if (methodCallExpression.Method.IsGenericMethod && methodCallExpression.Method.GetGenericMethodDefinition() == QueryableMethods.DefaultIfEmptyWithoutArgument) { @@ -656,6 +764,9 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp protected override ShapedQueryExpression TranslateSelectMany(ShapedQueryExpression source, LambdaExpression selector) { + Check.NotNull(source, nameof(source)); + Check.NotNull(selector, nameof(selector)); + var innerParameter = Expression.Parameter(selector.ReturnType.TryGetSequenceType(), "i"); var resultSelector = Expression.Lambda( innerParameter, Expression.Parameter(source.Type.TryGetSequenceType()), innerParameter); @@ -666,6 +777,9 @@ protected override ShapedQueryExpression TranslateSelectMany(ShapedQueryExpressi protected override ShapedQueryExpression TranslateSingleOrDefault( ShapedQueryExpression source, LambdaExpression predicate, Type returnType, bool returnDefault) { + Check.NotNull(source, nameof(source)); + Check.NotNull(returnType, nameof(returnType)); + return TranslateSingleResultOperator( source, predicate, @@ -677,6 +791,9 @@ protected override ShapedQueryExpression TranslateSingleOrDefault( protected override ShapedQueryExpression TranslateSkip(ShapedQueryExpression source, Expression count) { + Check.NotNull(source, nameof(source)); + Check.NotNull(count, nameof(count)); + var inMemoryQueryExpression = (InMemoryQueryExpression)source.QueryExpression; count = TranslateExpression(count); if (count == null) @@ -694,13 +811,26 @@ protected override ShapedQueryExpression TranslateSkip(ShapedQueryExpression sou } protected override ShapedQueryExpression TranslateSkipWhile(ShapedQueryExpression source, LambdaExpression predicate) - => null; + { + Check.NotNull(source, nameof(source)); + Check.NotNull(predicate, nameof(predicate)); + + return null; + } protected override ShapedQueryExpression TranslateSum(ShapedQueryExpression source, LambdaExpression selector, Type resultType) - => TranslateScalarAggregate(source, selector, nameof(Enumerable.Sum)); + { + Check.NotNull(source, nameof(source)); + Check.NotNull(resultType, nameof(resultType)); + + return TranslateScalarAggregate(source, selector, nameof(Enumerable.Sum)); + } protected override ShapedQueryExpression TranslateTake(ShapedQueryExpression source, Expression count) { + Check.NotNull(source, nameof(source)); + Check.NotNull(count, nameof(count)); + var inMemoryQueryExpression = (InMemoryQueryExpression)source.QueryExpression; count = TranslateExpression(count); if (count == null) @@ -718,10 +848,18 @@ protected override ShapedQueryExpression TranslateTake(ShapedQueryExpression sou } protected override ShapedQueryExpression TranslateTakeWhile(ShapedQueryExpression source, LambdaExpression predicate) - => null; + { + Check.NotNull(source, nameof(source)); + Check.NotNull(predicate, nameof(predicate)); + + return null; + } protected override ShapedQueryExpression TranslateThenBy(ShapedQueryExpression source, LambdaExpression keySelector, bool ascending) { + Check.NotNull(source, nameof(source)); + Check.NotNull(keySelector, nameof(keySelector)); + var inMemoryQueryExpression = (InMemoryQueryExpression)source.QueryExpression; keySelector = TranslateLambdaExpression(source, keySelector); if (keySelector == null) @@ -740,10 +878,18 @@ protected override ShapedQueryExpression TranslateThenBy(ShapedQueryExpression s } protected override ShapedQueryExpression TranslateUnion(ShapedQueryExpression source1, ShapedQueryExpression source2) - => TranslateSetOperation(EnumerableMethods.Union, source1, source2); + { + Check.NotNull(source1, nameof(source1)); + Check.NotNull(source2, nameof(source2)); + + return TranslateSetOperation(EnumerableMethods.Union, source1, source2); + } protected override ShapedQueryExpression TranslateWhere(ShapedQueryExpression source, LambdaExpression predicate) { + Check.NotNull(source, nameof(source)); + Check.NotNull(predicate, nameof(predicate)); + var inMemoryQueryExpression = (InMemoryQueryExpression)source.QueryExpression; predicate = TranslateLambdaExpression(source, predicate, preserveType: true); if (predicate == null) @@ -820,6 +966,8 @@ public Expression Expand(InMemoryQueryExpression queryExpression, Expression lam protected override Expression VisitMember(MemberExpression memberExpression) { + Check.NotNull(memberExpression, nameof(memberExpression)); + var innerExpression = Visit(memberExpression.Expression); return TryExpand(innerExpression, MemberIdentity.Create(memberExpression.Member)) @@ -828,6 +976,8 @@ protected override Expression VisitMember(MemberExpression memberExpression) protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { + Check.NotNull(methodCallExpression, nameof(methodCallExpression)); + if (methodCallExpression.TryGetEFPropertyArguments(out var source, out var navigationName)) { source = Visit(source); @@ -840,9 +990,13 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp } protected override Expression VisitExtension(Expression extensionExpression) - => extensionExpression is EntityShaperExpression + { + Check.NotNull(extensionExpression, nameof(extensionExpression)); + + return extensionExpression is EntityShaperExpression ? extensionExpression : base.VisitExtension(extensionExpression); + } private Expression TryExpand(Expression source, MemberIdentity member) { diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitorFactory.cs b/src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitorFactory.cs index c97f6520f3d..694c33715c5 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitorFactory.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitorFactory.cs @@ -4,6 +4,7 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal @@ -32,6 +33,10 @@ public InMemoryQueryableMethodTranslatingExpressionVisitorFactory( } public virtual QueryableMethodTranslatingExpressionVisitor Create(IModel model) - => new InMemoryQueryableMethodTranslatingExpressionVisitor(_dependencies, model); + { + Check.NotNull(model, nameof(model)); + + return new InMemoryQueryableMethodTranslatingExpressionVisitor(_dependencies, model); + } } } diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.CustomShaperCompilingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.CustomShaperCompilingExpressionVisitor.cs index 14be7b1947a..4c0322473d1 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.CustomShaperCompilingExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.CustomShaperCompilingExpressionVisitor.cs @@ -10,6 +10,7 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal { @@ -158,6 +159,8 @@ private static TResult MaterializeSingleResult( protected override Expression VisitExtension(Expression extensionExpression) { + Check.NotNull(extensionExpression, nameof(extensionExpression)); + if (extensionExpression is IncludeExpression includeExpression) { var entityClrType = includeExpression.EntityExpression.Type; diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.InMemoryProjectionBindingRemovingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.InMemoryProjectionBindingRemovingExpressionVisitor.cs index 4990c437a4c..6934d61f31d 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.InMemoryProjectionBindingRemovingExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.InMemoryProjectionBindingRemovingExpressionVisitor.cs @@ -8,6 +8,7 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal { @@ -21,6 +22,8 @@ private sealed class InMemoryProjectionBindingRemovingExpressionVisitor : Expres protected override Expression VisitBinary(BinaryExpression binaryExpression) { + Check.NotNull(binaryExpression, nameof(binaryExpression)); + if (binaryExpression.NodeType == ExpressionType.Assign && binaryExpression.Left is ParameterExpression parameterExpression && parameterExpression.Type == typeof(MaterializationContext)) @@ -55,6 +58,8 @@ protected override Expression VisitBinary(BinaryExpression binaryExpression) protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { + Check.NotNull(methodCallExpression, nameof(methodCallExpression)); + if (methodCallExpression.Method.IsGenericMethod && methodCallExpression.Method.GetGenericMethodDefinition() == EntityMaterializerSource.TryReadValueMethod) { @@ -75,6 +80,8 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp protected override Expression VisitExtension(Expression extensionExpression) { + Check.NotNull(extensionExpression, nameof(extensionExpression)); + if (extensionExpression is ProjectionBindingExpression projectionBindingExpression) { var queryExpression = (InMemoryQueryExpression)projectionBindingExpression.QueryExpression; diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.cs index 3a77fc27b7d..bcbf603d8cb 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.cs @@ -6,10 +6,12 @@ using System.Linq; using System.Linq.Expressions; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal { @@ -19,8 +21,8 @@ public partial class InMemoryShapedQueryCompilingExpressionVisitor : ShapedQuery private readonly IDiagnosticsLogger _logger; public InMemoryShapedQueryCompilingExpressionVisitor( - ShapedQueryCompilingExpressionVisitorDependencies dependencies, - QueryCompilationContext queryCompilationContext) + [NotNull] ShapedQueryCompilingExpressionVisitorDependencies dependencies, + [NotNull] QueryCompilationContext queryCompilationContext) : base(dependencies, queryCompilationContext) { _contextType = queryCompilationContext.ContextType; @@ -29,6 +31,8 @@ public InMemoryShapedQueryCompilingExpressionVisitor( protected override Expression VisitExtension(Expression extensionExpression) { + Check.NotNull(extensionExpression, nameof(extensionExpression)); + switch (extensionExpression) { case InMemoryQueryExpression inMemoryQueryExpression: @@ -47,6 +51,8 @@ protected override Expression VisitExtension(Expression extensionExpression) protected override Expression VisitShapedQueryExpression(ShapedQueryExpression shapedQueryExpression) { + Check.NotNull(shapedQueryExpression, nameof(shapedQueryExpression)); + var inMemoryQueryExpression = (InMemoryQueryExpression)shapedQueryExpression.QueryExpression; var shaper = new ShaperExpressionProcessingExpressionVisitor( diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryExpressionVisitorFactory.cs b/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryExpressionVisitorFactory.cs index da199a92852..52f1ce148c1 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryExpressionVisitorFactory.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryExpressionVisitorFactory.cs @@ -1,7 +1,9 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal { @@ -9,12 +11,16 @@ public class InMemoryShapedQueryCompilingExpressionVisitorFactory : IShapedQuery { private readonly ShapedQueryCompilingExpressionVisitorDependencies _dependencies; - public InMemoryShapedQueryCompilingExpressionVisitorFactory(ShapedQueryCompilingExpressionVisitorDependencies dependencies) + public InMemoryShapedQueryCompilingExpressionVisitorFactory([NotNull] ShapedQueryCompilingExpressionVisitorDependencies dependencies) { _dependencies = dependencies; } public virtual ShapedQueryCompilingExpressionVisitor Create(QueryCompilationContext queryCompilationContext) - => new InMemoryShapedQueryCompilingExpressionVisitor(_dependencies, queryCompilationContext); + { + Check.NotNull(queryCompilationContext, nameof(queryCompilationContext)); + + return new InMemoryShapedQueryCompilingExpressionVisitor(_dependencies, queryCompilationContext); + } } } diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryTableExpression.cs b/src/EFCore.InMemory/Query/Internal/InMemoryTableExpression.cs index a12ad78ef7b..e6a13257549 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryTableExpression.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryTableExpression.cs @@ -4,15 +4,17 @@ using System; using System.Collections.Generic; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal { public class InMemoryTableExpression : Expression, IPrintableExpression { - public InMemoryTableExpression(IEntityType entityType) + public InMemoryTableExpression([NotNull] IEntityType entityType) { EntityType = entityType; } @@ -25,11 +27,15 @@ public InMemoryTableExpression(IEntityType entityType) protected override Expression VisitChildren(ExpressionVisitor visitor) { + Check.NotNull(visitor, nameof(visitor)); + return this; } public virtual void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.Append(nameof(InMemoryTableExpression) + ": Entity: " + EntityType.DisplayName()); } } diff --git a/src/EFCore.InMemory/Query/Internal/ShaperExpressionProcessingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/ShaperExpressionProcessingExpressionVisitor.cs index 6ae82e6c56a..95851e31118 100644 --- a/src/EFCore.InMemory/Query/Internal/ShaperExpressionProcessingExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Internal/ShaperExpressionProcessingExpressionVisitor.cs @@ -5,6 +5,7 @@ using System.Linq.Expressions; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal { @@ -24,7 +25,7 @@ public ShaperExpressionProcessingExpressionVisitor( _valueBufferParameter = valueBufferParameter; } - public virtual Expression Inject(Expression expression) + public virtual Expression Inject([NotNull] Expression expression) { var result = Visit(expression); _expressions.Add(result); @@ -41,6 +42,8 @@ private LambdaExpression ConvertToLambda(Expression result) protected override Expression VisitExtension(Expression extensionExpression) { + Check.NotNull(extensionExpression, nameof(extensionExpression)); + switch (extensionExpression) { case EntityShaperExpression entityShaperExpression: diff --git a/src/EFCore.InMemory/Query/Internal/SingleResultShaperExpression.cs b/src/EFCore.InMemory/Query/Internal/SingleResultShaperExpression.cs index d8c3ce1089e..2911ab5750f 100644 --- a/src/EFCore.InMemory/Query/Internal/SingleResultShaperExpression.cs +++ b/src/EFCore.InMemory/Query/Internal/SingleResultShaperExpression.cs @@ -3,16 +3,18 @@ using System; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal { public class SingleResultShaperExpression : Expression, IPrintableExpression { public SingleResultShaperExpression( - Expression projection, - Expression innerShaper, - Type type) + [NotNull] Expression projection, + [NotNull] Expression innerShaper, + [NotNull] Type type) { Projection = projection; InnerShaper = innerShaper; @@ -21,13 +23,15 @@ public SingleResultShaperExpression( protected override Expression VisitChildren(ExpressionVisitor visitor) { + Check.NotNull(visitor, nameof(visitor)); + var projection = visitor.Visit(Projection); var innerShaper = visitor.Visit(InnerShaper); return Update(projection, innerShaper); } - public virtual SingleResultShaperExpression Update(Expression projection, Expression innerShaper) + public virtual SingleResultShaperExpression Update([NotNull] Expression projection, [NotNull] Expression innerShaper) => projection != Projection || innerShaper != InnerShaper ? new SingleResultShaperExpression(projection, innerShaper, Type) : this; @@ -40,6 +44,8 @@ public virtual SingleResultShaperExpression Update(Expression projection, Expres public virtual void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.AppendLine($"{nameof(SingleResultShaperExpression)}:"); using (expressionPrinter.Indent()) { diff --git a/src/EFCore.InMemory/ValueGeneration/Internal/IInMemoryIntegerValueGenerator.cs b/src/EFCore.InMemory/ValueGeneration/Internal/IInMemoryIntegerValueGenerator.cs index c4aaf136c89..c108f1c8f34 100644 --- a/src/EFCore.InMemory/ValueGeneration/Internal/IInMemoryIntegerValueGenerator.cs +++ b/src/EFCore.InMemory/ValueGeneration/Internal/IInMemoryIntegerValueGenerator.cs @@ -1,6 +1,8 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using JetBrains.Annotations; + namespace Microsoft.EntityFrameworkCore.InMemory.ValueGeneration.Internal { /// @@ -17,6 +19,6 @@ public interface IInMemoryIntegerValueGenerator /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - void Bump(object[] row); + void Bump([NotNull] object[] row); } } diff --git a/src/EFCore.InMemory/ValueGeneration/Internal/InMemoryIntegerValueGenerator.cs b/src/EFCore.InMemory/ValueGeneration/Internal/InMemoryIntegerValueGenerator.cs index 001323b1d24..81135b13052 100644 --- a/src/EFCore.InMemory/ValueGeneration/Internal/InMemoryIntegerValueGenerator.cs +++ b/src/EFCore.InMemory/ValueGeneration/Internal/InMemoryIntegerValueGenerator.cs @@ -5,6 +5,7 @@ using System.Globalization; using System.Threading; using Microsoft.EntityFrameworkCore.ChangeTracking; +using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.EntityFrameworkCore.ValueGeneration; namespace Microsoft.EntityFrameworkCore.InMemory.ValueGeneration.Internal @@ -39,6 +40,8 @@ public InMemoryIntegerValueGenerator(int propertyIndex) /// public virtual void Bump(object[] row) { + Check.NotNull(row, nameof(row)); + var newValue = (long)Convert.ChangeType(row[_propertyIndex], typeof(long)); if (_current < newValue) diff --git a/src/EFCore.Relational/Extensions/Internal/RelationalExpressionExtensions.cs b/src/EFCore.Relational/Extensions/Internal/RelationalExpressionExtensions.cs index 24337c302a6..edd3fb51962 100644 --- a/src/EFCore.Relational/Extensions/Internal/RelationalExpressionExtensions.cs +++ b/src/EFCore.Relational/Extensions/Internal/RelationalExpressionExtensions.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; // ReSharper disable once CheckNamespace @@ -21,7 +22,7 @@ public static class RelationalExpressionExtensions /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public static bool IsLogicalNot(this SqlUnaryExpression sqlUnaryExpression) + public static bool IsLogicalNot([NotNull] this SqlUnaryExpression sqlUnaryExpression) => sqlUnaryExpression.OperatorType == ExpressionType.Not && (sqlUnaryExpression.Type == typeof(bool) || sqlUnaryExpression.Type == typeof(bool?)); diff --git a/src/EFCore.Relational/Metadata/Conventions/RelationalQueryFilterDefiningQueryRewritingConvention.cs b/src/EFCore.Relational/Metadata/Conventions/RelationalQueryFilterDefiningQueryRewritingConvention.cs index 7cbb12817a8..b59737adf3f 100644 --- a/src/EFCore.Relational/Metadata/Conventions/RelationalQueryFilterDefiningQueryRewritingConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/RelationalQueryFilterDefiningQueryRewritingConvention.cs @@ -5,6 +5,7 @@ using System.Linq.Expressions; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { @@ -32,6 +33,8 @@ public RelationalDbSetAccessRewritingExpressionVisitor(Type contextType) protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { + Check.NotNull(methodCallExpression, nameof(methodCallExpression)); + var methodName = methodCallExpression.Method.Name; if (methodCallExpression.Method.DeclaringType == typeof(RelationalQueryableExtensions) && (methodName == nameof(RelationalQueryableExtensions.FromSqlRaw) diff --git a/src/EFCore.Relational/Metadata/Internal/DbFunctionParameter.cs b/src/EFCore.Relational/Metadata/Internal/DbFunctionParameter.cs index 9e2ee4f50df..b308570bd54 100644 --- a/src/EFCore.Relational/Metadata/Internal/DbFunctionParameter.cs +++ b/src/EFCore.Relational/Metadata/Internal/DbFunctionParameter.cs @@ -111,7 +111,7 @@ public virtual RelationalTypeMapping TypeMapping /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual void SetTypeMapping(RelationalTypeMapping typeMapping, ConfigurationSource configurationSource) + public virtual void SetTypeMapping([NotNull] RelationalTypeMapping typeMapping, ConfigurationSource configurationSource) { _typeMapping = typeMapping; diff --git a/src/EFCore.Relational/Metadata/Internal/RelationalPropertyExtensions.cs b/src/EFCore.Relational/Metadata/Internal/RelationalPropertyExtensions.cs index 7ea1ff30036..8a34db48f15 100644 --- a/src/EFCore.Relational/Metadata/Internal/RelationalPropertyExtensions.cs +++ b/src/EFCore.Relational/Metadata/Internal/RelationalPropertyExtensions.cs @@ -29,7 +29,7 @@ public static IForeignKey FindSharedTableLink([NotNull] this IProperty property) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public static IForeignKey FindSharedTableLink([NotNull] this IProperty property, string table, string schema) + public static IForeignKey FindSharedTableLink([NotNull] this IProperty property, [CanBeNull] string table, [CanBeNull] string schema) { var pk = property.FindContainingPrimaryKey(); if (pk == null) diff --git a/src/EFCore.Relational/Metadata/Internal/Sequence.cs b/src/EFCore.Relational/Metadata/Internal/Sequence.cs index 585a2f38dee..948bc27f96a 100644 --- a/src/EFCore.Relational/Metadata/Internal/Sequence.cs +++ b/src/EFCore.Relational/Metadata/Internal/Sequence.cs @@ -338,7 +338,7 @@ public virtual Type ClrType /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual void SetClrType(Type clrType, ConfigurationSource configurationSource) + public virtual void SetClrType([CanBeNull] Type clrType, ConfigurationSource configurationSource) { clrType ??= DefaultClrType; if (!SupportedTypes.Contains(clrType)) diff --git a/src/EFCore.Relational/Migrations/Internal/Migrator.cs b/src/EFCore.Relational/Migrations/Internal/Migrator.cs index f8dc7514f7d..80de0adcc2a 100644 --- a/src/EFCore.Relational/Migrations/Internal/Migrator.cs +++ b/src/EFCore.Relational/Migrations/Internal/Migrator.cs @@ -222,11 +222,11 @@ private IEnumerable>> GetMigrationCommandLi /// doing so can result in application failures when updating to a new Entity Framework Core release. /// protected virtual void PopulateMigrations( - IEnumerable appliedMigrationEntries, - string targetMigration, - out IReadOnlyList migrationsToApply, - out IReadOnlyList migrationsToRevert, - out Migration actualTargetMigration) + [NotNull] IEnumerable appliedMigrationEntries, + [NotNull] string targetMigration, + [NotNull] out IReadOnlyList migrationsToApply, + [NotNull] out IReadOnlyList migrationsToRevert, + [NotNull] out Migration actualTargetMigration) { var appliedMigrations = new Dictionary(); var unappliedMigrations = new Dictionary(); diff --git a/src/EFCore.Relational/Query/CollectionInitializingExpression.cs b/src/EFCore.Relational/Query/CollectionInitializingExpression.cs index 6fdac3fbce4..6bfa0f17b5c 100644 --- a/src/EFCore.Relational/Query/CollectionInitializingExpression.cs +++ b/src/EFCore.Relational/Query/CollectionInitializingExpression.cs @@ -3,15 +3,26 @@ using System; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query { public class CollectionInitializingExpression : Expression, IPrintableExpression { public CollectionInitializingExpression( - int collectionId, Expression parent, Expression parentIdentifier, Expression outerIdentifier, INavigation navigation, Type type) + int collectionId, + [CanBeNull] Expression parent, + [NotNull] Expression parentIdentifier, + [NotNull] Expression outerIdentifier, + [CanBeNull] INavigation navigation, + [NotNull] Type type) { + Check.NotNull(parentIdentifier, nameof(parentIdentifier)); + Check.NotNull(outerIdentifier, nameof(outerIdentifier)); + Check.NotNull(type, nameof(type)); + CollectionId = collectionId; Parent = parent; ParentIdentifier = parentIdentifier; @@ -22,6 +33,8 @@ public CollectionInitializingExpression( protected override Expression VisitChildren(ExpressionVisitor visitor) { + Check.NotNull(visitor, nameof(visitor)); + var parent = visitor.Visit(Parent); var parentIdentifier = visitor.Visit(ParentIdentifier); var outerIdentifier = visitor.Visit(OuterIdentifier); @@ -33,6 +46,8 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) public virtual void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.AppendLine("InitializeCollection:"); using (expressionPrinter.Indent()) { diff --git a/src/EFCore.Relational/Query/CollectionPopulatingExpression.cs b/src/EFCore.Relational/Query/CollectionPopulatingExpression.cs index 68e78e76a0c..f17ceb6bdec 100644 --- a/src/EFCore.Relational/Query/CollectionPopulatingExpression.cs +++ b/src/EFCore.Relational/Query/CollectionPopulatingExpression.cs @@ -3,13 +3,18 @@ using System; using System.Linq.Expressions; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query { public class CollectionPopulatingExpression : Expression, IPrintableExpression { - public CollectionPopulatingExpression(RelationalCollectionShaperExpression parent, Type type, bool include) + public CollectionPopulatingExpression([NotNull] RelationalCollectionShaperExpression parent, [NotNull] Type type, bool include) { + Check.NotNull(parent, nameof(parent)); + Check.NotNull(type, nameof(type)); + Parent = parent; Type = type; IsInclude = include; @@ -17,6 +22,8 @@ public CollectionPopulatingExpression(RelationalCollectionShaperExpression paren protected override Expression VisitChildren(ExpressionVisitor visitor) { + Check.NotNull(visitor, nameof(visitor)); + var parent = (RelationalCollectionShaperExpression)visitor.Visit(Parent); return parent != Parent @@ -26,6 +33,8 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) public virtual void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.AppendLine("PopulateCollection:"); using (expressionPrinter.Indent()) { diff --git a/src/EFCore.Relational/Query/EntityProjectionExpression.cs b/src/EFCore.Relational/Query/EntityProjectionExpression.cs index f1db8158d37..d10c43eb492 100644 --- a/src/EFCore.Relational/Query/EntityProjectionExpression.cs +++ b/src/EFCore.Relational/Query/EntityProjectionExpression.cs @@ -4,8 +4,10 @@ using System; using System.Collections.Generic; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query { @@ -20,21 +22,29 @@ private readonly IDictionary _navigationExp private readonly TableExpressionBase _innerTable; private readonly bool _nullable; - public EntityProjectionExpression(IEntityType entityType, TableExpressionBase innerTable, bool nullable) + public EntityProjectionExpression([NotNull] IEntityType entityType, [NotNull] TableExpressionBase innerTable, bool nullable) { + Check.NotNull(entityType, nameof(entityType)); + Check.NotNull(innerTable, nameof(innerTable)); + EntityType = entityType; _innerTable = innerTable; _nullable = nullable; } - public EntityProjectionExpression(IEntityType entityType, IDictionary propertyExpressions) + public EntityProjectionExpression([NotNull] IEntityType entityType, [NotNull] IDictionary propertyExpressions) { + Check.NotNull(entityType, nameof(entityType)); + Check.NotNull(propertyExpressions, nameof(propertyExpressions)); + EntityType = entityType; _propertyExpressionsCache = propertyExpressions; } protected override Expression VisitChildren(ExpressionVisitor visitor) { + Check.NotNull(visitor, nameof(visitor)); + if (_innerTable != null) { var table = (TableExpressionBase)visitor.Visit(_innerTable); @@ -75,8 +85,10 @@ public virtual EntityProjectionExpression MakeNullable() return new EntityProjectionExpression(EntityType, newCache); } - public virtual EntityProjectionExpression UpdateEntityType(IEntityType derivedType) + public virtual EntityProjectionExpression UpdateEntityType([NotNull] IEntityType derivedType) { + Check.NotNull(derivedType, nameof(derivedType)); + if (_innerTable != null) { return new EntityProjectionExpression(derivedType, _innerTable, _nullable); @@ -100,8 +112,10 @@ public virtual EntityProjectionExpression UpdateEntityType(IEntityType derivedTy public sealed override ExpressionType NodeType => ExpressionType.Extension; public override Type Type => EntityType.ClrType; - public virtual ColumnExpression BindProperty(IProperty property) + public virtual ColumnExpression BindProperty([NotNull] IProperty property) { + Check.NotNull(property, nameof(property)); + if (!EntityType.IsAssignableFrom(property.DeclaringEntityType) && !property.DeclaringEntityType.IsAssignableFrom(EntityType)) { @@ -118,8 +132,11 @@ public virtual ColumnExpression BindProperty(IProperty property) return expression; } - public virtual void AddNavigationBinding(INavigation navigation, EntityShaperExpression entityShaper) + public virtual void AddNavigationBinding([NotNull] INavigation navigation, [NotNull] EntityShaperExpression entityShaper) { + Check.NotNull(navigation, nameof(navigation)); + Check.NotNull(entityShaper, nameof(entityShaper)); + if (!EntityType.IsAssignableFrom(navigation.DeclaringEntityType) && !navigation.DeclaringEntityType.IsAssignableFrom(EntityType)) { @@ -131,8 +148,10 @@ public virtual void AddNavigationBinding(INavigation navigation, EntityShaperExp _navigationExpressionsCache[navigation] = entityShaper; } - public virtual EntityShaperExpression BindNavigation(INavigation navigation) + public virtual EntityShaperExpression BindNavigation([NotNull] INavigation navigation) { + Check.NotNull(navigation, nameof(navigation)); + if (!EntityType.IsAssignableFrom(navigation.DeclaringEntityType) && !navigation.DeclaringEntityType.IsAssignableFrom(EntityType)) { diff --git a/src/EFCore.Relational/Query/ExpressionExtensions.cs b/src/EFCore.Relational/Query/ExpressionExtensions.cs index 7a00f5fe0a5..5e1b628cc04 100644 --- a/src/EFCore.Relational/Query/ExpressionExtensions.cs +++ b/src/EFCore.Relational/Query/ExpressionExtensions.cs @@ -1,15 +1,19 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query { public static class ExpressionExtensions { - public static RelationalTypeMapping InferTypeMapping(params SqlExpression[] expressions) + public static RelationalTypeMapping InferTypeMapping([NotNull] params SqlExpression[] expressions) { + Check.NotNull(expressions, nameof(expressions)); + for (var i = 0; i < expressions.Length; i++) { var sql = expressions[i]; diff --git a/src/EFCore.Relational/Query/IMemberTranslator.cs b/src/EFCore.Relational/Query/IMemberTranslator.cs index d60efd66f2f..8084bb1f43c 100644 --- a/src/EFCore.Relational/Query/IMemberTranslator.cs +++ b/src/EFCore.Relational/Query/IMemberTranslator.cs @@ -3,12 +3,13 @@ using System; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; namespace Microsoft.EntityFrameworkCore.Query { public interface IMemberTranslator { - SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType); + SqlExpression Translate([CanBeNull] SqlExpression instance, [NotNull] MemberInfo member, [NotNull] Type returnType); } } diff --git a/src/EFCore.Relational/Query/IMemberTranslatorProvider.cs b/src/EFCore.Relational/Query/IMemberTranslatorProvider.cs index b9839f580e2..3710dcd70a4 100644 --- a/src/EFCore.Relational/Query/IMemberTranslatorProvider.cs +++ b/src/EFCore.Relational/Query/IMemberTranslatorProvider.cs @@ -3,6 +3,7 @@ using System; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.Extensions.DependencyInjection; @@ -20,6 +21,6 @@ namespace Microsoft.EntityFrameworkCore.Query /// public interface IMemberTranslatorProvider { - SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType); + SqlExpression Translate([CanBeNull] SqlExpression instance, [NotNull] MemberInfo member, [NotNull] Type returnType); } } diff --git a/src/EFCore.Relational/Query/IMethodCallTranslator.cs b/src/EFCore.Relational/Query/IMethodCallTranslator.cs index 65470501dc7..91133be5384 100644 --- a/src/EFCore.Relational/Query/IMethodCallTranslator.cs +++ b/src/EFCore.Relational/Query/IMethodCallTranslator.cs @@ -3,12 +3,14 @@ using System.Collections.Generic; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; namespace Microsoft.EntityFrameworkCore.Query { public interface IMethodCallTranslator { - SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments); + SqlExpression Translate( + [CanBeNull] SqlExpression instance, [NotNull] MethodInfo method, [NotNull] IReadOnlyList arguments); } } diff --git a/src/EFCore.Relational/Query/IMethodCallTranslatorProvider.cs b/src/EFCore.Relational/Query/IMethodCallTranslatorProvider.cs index 446098ff8af..1ca9be8da40 100644 --- a/src/EFCore.Relational/Query/IMethodCallTranslatorProvider.cs +++ b/src/EFCore.Relational/Query/IMethodCallTranslatorProvider.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.Extensions.DependencyInjection; @@ -21,6 +22,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// public interface IMethodCallTranslatorProvider { - SqlExpression Translate(IModel model, SqlExpression instance, MethodInfo method, IReadOnlyList arguments); + SqlExpression Translate( + [NotNull] IModel model, + [CanBeNull] SqlExpression instance, + [NotNull] MethodInfo method, + [NotNull] IReadOnlyList arguments); } } diff --git a/src/EFCore.Relational/Query/IRelationalSqlTranslatingExpressionVisitorFactory.cs b/src/EFCore.Relational/Query/IRelationalSqlTranslatingExpressionVisitorFactory.cs index be60d7ef475..9d0bd4e62dd 100644 --- a/src/EFCore.Relational/Query/IRelationalSqlTranslatingExpressionVisitorFactory.cs +++ b/src/EFCore.Relational/Query/IRelationalSqlTranslatingExpressionVisitorFactory.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.Extensions.DependencyInjection; @@ -19,7 +20,7 @@ namespace Microsoft.EntityFrameworkCore.Query public interface IRelationalSqlTranslatingExpressionVisitorFactory { RelationalSqlTranslatingExpressionVisitor Create( - IModel model, - QueryableMethodTranslatingExpressionVisitor queryableMethodTranslatingExpressionVisitor); + [NotNull] IModel model, + [NotNull] QueryableMethodTranslatingExpressionVisitor queryableMethodTranslatingExpressionVisitor); } } diff --git a/src/EFCore.Relational/Query/ISqlExpressionFactory.cs b/src/EFCore.Relational/Query/ISqlExpressionFactory.cs index 0ff904818fe..10348045362 100644 --- a/src/EFCore.Relational/Query/ISqlExpressionFactory.cs +++ b/src/EFCore.Relational/Query/ISqlExpressionFactory.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; @@ -23,84 +24,122 @@ namespace Microsoft.EntityFrameworkCore.Query /// public interface ISqlExpressionFactory { - SqlExpression ApplyTypeMapping(SqlExpression sqlExpression, RelationalTypeMapping typeMapping); - SqlExpression ApplyDefaultTypeMapping(SqlExpression sqlExpression); - RelationalTypeMapping GetTypeMappingForValue(object value); - RelationalTypeMapping FindMapping(Type type); + SqlExpression ApplyTypeMapping([CanBeNull] SqlExpression sqlExpression, [CanBeNull] RelationalTypeMapping typeMapping); + SqlExpression ApplyDefaultTypeMapping([CanBeNull] SqlExpression sqlExpression); + RelationalTypeMapping GetTypeMappingForValue([CanBeNull] object value); + RelationalTypeMapping FindMapping([NotNull] Type type); SqlUnaryExpression MakeUnary( - ExpressionType operatorType, SqlExpression operand, Type type, RelationalTypeMapping typeMapping = null); + ExpressionType operatorType, + [NotNull] SqlExpression operand, + [NotNull] Type type, + [CanBeNull] RelationalTypeMapping typeMapping = null); SqlBinaryExpression MakeBinary( - ExpressionType operatorType, SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping); + ExpressionType operatorType, + [NotNull] SqlExpression left, + [NotNull] SqlExpression right, + [CanBeNull] RelationalTypeMapping typeMapping); // Comparison - SqlBinaryExpression Equal(SqlExpression left, SqlExpression right); - SqlBinaryExpression NotEqual(SqlExpression left, SqlExpression right); - SqlBinaryExpression GreaterThan(SqlExpression left, SqlExpression right); - SqlBinaryExpression GreaterThanOrEqual(SqlExpression left, SqlExpression right); - SqlBinaryExpression LessThan(SqlExpression left, SqlExpression right); + SqlBinaryExpression Equal([NotNull] SqlExpression left, [NotNull] SqlExpression right); + SqlBinaryExpression NotEqual([NotNull] SqlExpression left, [NotNull] SqlExpression right); + SqlBinaryExpression GreaterThan([NotNull] SqlExpression left, [NotNull] SqlExpression right); + SqlBinaryExpression GreaterThanOrEqual([NotNull] SqlExpression left, [NotNull] SqlExpression right); + SqlBinaryExpression LessThan([NotNull] SqlExpression left, [NotNull] SqlExpression right); - SqlBinaryExpression LessThanOrEqual(SqlExpression left, SqlExpression right); + SqlBinaryExpression LessThanOrEqual([NotNull] SqlExpression left, [NotNull] SqlExpression right); // Logical - SqlBinaryExpression AndAlso(SqlExpression left, SqlExpression right); + SqlBinaryExpression AndAlso([NotNull] SqlExpression left, [NotNull] SqlExpression right); - SqlBinaryExpression OrElse(SqlExpression left, SqlExpression right); + SqlBinaryExpression OrElse([NotNull] SqlExpression left, [NotNull] SqlExpression right); // Arithmetic - SqlBinaryExpression Add(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null); - SqlBinaryExpression Subtract(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null); - SqlBinaryExpression Multiply(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null); - SqlBinaryExpression Divide(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null); + SqlBinaryExpression Add( + [NotNull] SqlExpression left, [NotNull] SqlExpression right, [CanBeNull] RelationalTypeMapping typeMapping = null); - SqlBinaryExpression Modulo(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null); + SqlBinaryExpression Subtract( + [NotNull] SqlExpression left, [NotNull] SqlExpression right, [CanBeNull] RelationalTypeMapping typeMapping = null); + + SqlBinaryExpression Multiply( + [NotNull] SqlExpression left, [NotNull] SqlExpression right, [CanBeNull] RelationalTypeMapping typeMapping = null); + + SqlBinaryExpression Divide( + [NotNull] SqlExpression left, [NotNull] SqlExpression right, [CanBeNull] RelationalTypeMapping typeMapping = null); + + SqlBinaryExpression Modulo( + [NotNull] SqlExpression left, [NotNull] SqlExpression right, [CanBeNull] RelationalTypeMapping typeMapping = null); // Bitwise - SqlBinaryExpression And(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null); + SqlBinaryExpression And( + [NotNull] SqlExpression left, [NotNull] SqlExpression right, [CanBeNull] RelationalTypeMapping typeMapping = null); - SqlBinaryExpression Or(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null); + SqlBinaryExpression Or( + [NotNull] SqlExpression left, [NotNull] SqlExpression right, [CanBeNull] RelationalTypeMapping typeMapping = null); // Other - SqlBinaryExpression Coalesce(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null); + SqlBinaryExpression Coalesce( + [NotNull] SqlExpression left, [NotNull] SqlExpression right, [CanBeNull] RelationalTypeMapping typeMapping = null); + + SqlUnaryExpression IsNull([NotNull] SqlExpression operand); + SqlUnaryExpression IsNotNull([NotNull] SqlExpression operand); + + SqlUnaryExpression Convert( + [NotNull] SqlExpression operand, [NotNull] Type type, [CanBeNull] RelationalTypeMapping typeMapping = null); - SqlUnaryExpression IsNull(SqlExpression operand); - SqlUnaryExpression IsNotNull(SqlExpression operand); - SqlUnaryExpression Convert(SqlExpression operand, Type type, RelationalTypeMapping typeMapping = null); - SqlUnaryExpression Not(SqlExpression operand); - SqlUnaryExpression Negate(SqlExpression operand); + SqlUnaryExpression Not([NotNull] SqlExpression operand); + SqlUnaryExpression Negate([NotNull] SqlExpression operand); - CaseExpression Case(SqlExpression operand, params CaseWhenClause[] whenClauses); - CaseExpression Case(IReadOnlyList whenClauses, SqlExpression elseResult); + CaseExpression Case([NotNull] SqlExpression operand, [NotNull] params CaseWhenClause[] whenClauses); + CaseExpression Case([NotNull] IReadOnlyList whenClauses, [CanBeNull] SqlExpression elseResult); SqlFunctionExpression Function( - string name, IEnumerable arguments, Type returnType, RelationalTypeMapping typeMapping = null); + [NotNull] string name, + [NotNull] IEnumerable arguments, + [NotNull] Type returnType, + [CanBeNull] RelationalTypeMapping typeMapping = null); SqlFunctionExpression Function( - string schema, string name, IEnumerable arguments, Type returnType, RelationalTypeMapping typeMapping = null); + [CanBeNull] string schema, + [NotNull] string name, + [NotNull] IEnumerable arguments, + [NotNull] Type returnType, + [CanBeNull] RelationalTypeMapping typeMapping = null); SqlFunctionExpression Function( - SqlExpression instance, string name, IEnumerable arguments, Type returnType, - RelationalTypeMapping typeMapping = null); + [CanBeNull] SqlExpression instance, + [NotNull] string name, + [NotNull] IEnumerable arguments, + [NotNull] Type returnType, + [CanBeNull] RelationalTypeMapping typeMapping = null); SqlFunctionExpression Function( - string name, Type returnType, RelationalTypeMapping typeMapping = null); + [NotNull] string name, + [NotNull] Type returnType, + [CanBeNull] RelationalTypeMapping typeMapping = null); SqlFunctionExpression Function( - string schema, string name, Type returnType, RelationalTypeMapping typeMapping = null); + [NotNull] string schema, + [NotNull] string name, + [NotNull] Type returnType, + [CanBeNull] RelationalTypeMapping typeMapping = null); SqlFunctionExpression Function( - SqlExpression instance, string name, Type returnType, RelationalTypeMapping typeMapping = null); - - ExistsExpression Exists(SelectExpression subquery, bool negated); - InExpression In(SqlExpression item, SqlExpression values, bool negated); - InExpression In(SqlExpression item, SelectExpression subquery, bool negated); - LikeExpression Like(SqlExpression match, SqlExpression pattern, SqlExpression escapeChar = null); - SqlConstantExpression Constant(object value, RelationalTypeMapping typeMapping = null); - SqlFragmentExpression Fragment(string sql); - - SelectExpression Select(SqlExpression projection); - SelectExpression Select(IEntityType entityType); - SelectExpression Select(IEntityType entityType, string sql, Expression sqlArguments); + [CanBeNull] SqlExpression instance, + [NotNull] string name, + [NotNull] Type returnType, + [CanBeNull] RelationalTypeMapping typeMapping = null); + + ExistsExpression Exists([NotNull] SelectExpression subquery, bool negated); + InExpression In([NotNull] SqlExpression item, [NotNull] SqlExpression values, bool negated); + InExpression In([NotNull] SqlExpression item, [NotNull] SelectExpression subquery, bool negated); + LikeExpression Like([NotNull] SqlExpression match, [NotNull] SqlExpression pattern, [CanBeNull] SqlExpression escapeChar = null); + SqlConstantExpression Constant([NotNull] object value, [CanBeNull] RelationalTypeMapping typeMapping = null); + SqlFragmentExpression Fragment([NotNull] string sql); + + SelectExpression Select([CanBeNull] SqlExpression projection); + SelectExpression Select([NotNull] IEntityType entityType); + SelectExpression Select([NotNull] IEntityType entityType, [NotNull] string sql, [NotNull] Expression sqlArguments); } } diff --git a/src/EFCore.Relational/Query/Internal/BufferedDataReader.cs b/src/EFCore.Relational/Query/Internal/BufferedDataReader.cs index 8bbeebd3a1c..487acfe9462 100644 --- a/src/EFCore.Relational/Query/Internal/BufferedDataReader.cs +++ b/src/EFCore.Relational/Query/Internal/BufferedDataReader.cs @@ -158,7 +158,7 @@ public virtual async Task InitializeAsync( } } - public static bool IsSupportedValueType(Type type) + public static bool IsSupportedValueType([NotNull] Type type) => type == typeof(int) || type == typeof(bool) || type == typeof(Guid) diff --git a/src/EFCore.Relational/Query/Internal/CaseWhenFlatteningExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/CaseWhenFlatteningExpressionVisitor.cs index 829738a3769..9b903cd634b 100644 --- a/src/EFCore.Relational/Query/Internal/CaseWhenFlatteningExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/CaseWhenFlatteningExpressionVisitor.cs @@ -1,11 +1,11 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System; -using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.Internal { @@ -13,13 +13,15 @@ public class CaseWhenFlatteningExpressionVisitor : ExpressionVisitor { private readonly ISqlExpressionFactory _sqlExpressionFactory; - public CaseWhenFlatteningExpressionVisitor(ISqlExpressionFactory sqlExpressionFactory) + public CaseWhenFlatteningExpressionVisitor([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } protected override Expression VisitExtension(Expression node) { + Check.NotNull(node, nameof(node)); + // Only applies to 'CASE WHEN condition...' not 'CASE operand WHEN...' if (node is CaseExpression caseExpression && caseExpression.Operand == null) { diff --git a/src/EFCore.Relational/Query/Internal/CollectionJoinApplyingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/CollectionJoinApplyingExpressionVisitor.cs index 8c7338c8594..05f3f19d5ff 100644 --- a/src/EFCore.Relational/Query/Internal/CollectionJoinApplyingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/CollectionJoinApplyingExpressionVisitor.cs @@ -3,6 +3,7 @@ using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.Internal { @@ -12,6 +13,8 @@ public class CollectionJoinApplyingExpressionVisitor : ExpressionVisitor protected override Expression VisitExtension(Expression extensionExpression) { + Check.NotNull(extensionExpression, nameof(extensionExpression)); + if (extensionExpression is CollectionShaperExpression collectionShaperExpression) { var collectionId = _collectionId++; diff --git a/src/EFCore.Relational/Query/Internal/CollectionMaterializationContext.cs b/src/EFCore.Relational/Query/Internal/CollectionMaterializationContext.cs index ea4cdf05e98..8f27942e1e7 100644 --- a/src/EFCore.Relational/Query/Internal/CollectionMaterializationContext.cs +++ b/src/EFCore.Relational/Query/Internal/CollectionMaterializationContext.cs @@ -1,6 +1,8 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using JetBrains.Annotations; + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// @@ -11,7 +13,11 @@ namespace Microsoft.EntityFrameworkCore.Query.Internal /// public class CollectionMaterializationContext { - public CollectionMaterializationContext(object parent, object collection, object[] parentIdentifier, object[] outerIdentifier) + public CollectionMaterializationContext( + [NotNull] object parent, + [NotNull] object collection, + [NotNull] object[] parentIdentifier, + [NotNull] object[] outerIdentifier) { Parent = parent; Collection = collection; @@ -27,7 +33,7 @@ public CollectionMaterializationContext(object parent, object collection, object public virtual object[] OuterIdentifier { get; } public virtual object[] SelfIdentifier { get; private set; } - public virtual void UpdateSelfIdentifier(object[] selfIdentifier) + public virtual void UpdateSelfIdentifier([NotNull] object[] selfIdentifier) { SelfIdentifier = selfIdentifier; } diff --git a/src/EFCore.Relational/Query/Internal/ComparisonTranslator.cs b/src/EFCore.Relational/Query/Internal/ComparisonTranslator.cs index d93d9338eb3..af677518afb 100644 --- a/src/EFCore.Relational/Query/Internal/ComparisonTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/ComparisonTranslator.cs @@ -4,7 +4,9 @@ using System; using System.Collections.Generic; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.Internal { @@ -12,13 +14,16 @@ public class ComparisonTranslator : IMethodCallTranslator { private readonly ISqlExpressionFactory _sqlExpressionFactory; - public ComparisonTranslator(ISqlExpressionFactory sqlExpressionFactory) + public ComparisonTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { + Check.NotNull(method, nameof(method)); + Check.NotNull(arguments, nameof(arguments)); + if (method.ReturnType == typeof(int)) { SqlExpression left = null; diff --git a/src/EFCore.Relational/Query/Internal/ContainsTranslator.cs b/src/EFCore.Relational/Query/Internal/ContainsTranslator.cs index 46a7c9b9ca8..323d035e488 100644 --- a/src/EFCore.Relational/Query/Internal/ContainsTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/ContainsTranslator.cs @@ -5,7 +5,9 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.Internal { @@ -13,13 +15,16 @@ public class ContainsTranslator : IMethodCallTranslator { private readonly ISqlExpressionFactory _sqlExpressionFactory; - public ContainsTranslator(ISqlExpressionFactory sqlExpressionFactory) + public ContainsTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { + Check.NotNull(method, nameof(method)); + Check.NotNull(arguments, nameof(arguments)); + if (method.IsGenericMethod && method.GetGenericMethodDefinition().Equals(EnumerableMethods.Contains)) { diff --git a/src/EFCore.Relational/Query/Internal/EnumHasFlagTranslator.cs b/src/EFCore.Relational/Query/Internal/EnumHasFlagTranslator.cs index 9c63fc9c048..469e37939c0 100644 --- a/src/EFCore.Relational/Query/Internal/EnumHasFlagTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/EnumHasFlagTranslator.cs @@ -4,7 +4,9 @@ using System; using System.Collections.Generic; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.Internal { @@ -15,13 +17,16 @@ private static readonly MethodInfo _methodInfo private readonly ISqlExpressionFactory _sqlExpressionFactory; - public EnumHasFlagTranslator(ISqlExpressionFactory sqlExpressionFactory) + public EnumHasFlagTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { + Check.NotNull(method, nameof(method)); + Check.NotNull(arguments, nameof(arguments)); + if (Equals(method, _methodInfo)) { var argument = arguments[0]; diff --git a/src/EFCore.Relational/Query/Internal/EqualsTranslator.cs b/src/EFCore.Relational/Query/Internal/EqualsTranslator.cs index 1763268ce01..77fc27c2c8c 100644 --- a/src/EFCore.Relational/Query/Internal/EqualsTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/EqualsTranslator.cs @@ -5,7 +5,9 @@ using System.Collections.Generic; using System.Linq.Expressions; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.Internal { @@ -13,13 +15,16 @@ public class EqualsTranslator : IMethodCallTranslator { private readonly ISqlExpressionFactory _sqlExpressionFactory; - public EqualsTranslator(ISqlExpressionFactory sqlExpressionFactory) + public EqualsTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { + Check.NotNull(method, nameof(method)); + Check.NotNull(arguments, nameof(arguments)); + SqlExpression left = null; SqlExpression right = null; diff --git a/src/EFCore.Relational/Query/Internal/GetValueOrDefaultTranslator.cs b/src/EFCore.Relational/Query/Internal/GetValueOrDefaultTranslator.cs index 7d0205ed214..f1756d7e15c 100644 --- a/src/EFCore.Relational/Query/Internal/GetValueOrDefaultTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/GetValueOrDefaultTranslator.cs @@ -5,7 +5,9 @@ using System.Collections.Generic; using System.Linq.Expressions; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.Internal { @@ -13,13 +15,16 @@ public class GetValueOrDefaultTranslator : IMethodCallTranslator { private readonly ISqlExpressionFactory _sqlExpressionFactory; - public GetValueOrDefaultTranslator(ISqlExpressionFactory sqlExpressionFactory) + public GetValueOrDefaultTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { + Check.NotNull(method, nameof(method)); + Check.NotNull(arguments, nameof(arguments)); + if (method.Name == nameof(Nullable.GetValueOrDefault) && method.ReturnType.IsNumeric()) { diff --git a/src/EFCore.Relational/Query/Internal/LikeTranslator.cs b/src/EFCore.Relational/Query/Internal/LikeTranslator.cs index 887577675db..3f64e45f825 100644 --- a/src/EFCore.Relational/Query/Internal/LikeTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/LikeTranslator.cs @@ -3,7 +3,9 @@ using System.Collections.Generic; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.Internal { @@ -21,13 +23,16 @@ private static readonly MethodInfo _methodInfoWithEscape private readonly ISqlExpressionFactory _sqlExpressionFactory; - public LikeTranslator(ISqlExpressionFactory sqlExpressionFactory) + public LikeTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { + Check.NotNull(method, nameof(method)); + Check.NotNull(arguments, nameof(arguments)); + if (Equals(method, _methodInfo)) { return _sqlExpressionFactory.Like(arguments[1], arguments[2]); diff --git a/src/EFCore.Relational/Query/Internal/NullSemanticsRewritingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/NullSemanticsRewritingExpressionVisitor.cs index 8d9c1f200c8..1e82a255be6 100644 --- a/src/EFCore.Relational/Query/Internal/NullSemanticsRewritingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/NullSemanticsRewritingExpressionVisitor.cs @@ -4,8 +4,10 @@ using System; using System.Collections.Generic; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.Internal { @@ -17,7 +19,7 @@ public class NullSemanticsRewritingExpressionVisitor : SqlExpressionVisitor private bool _canOptimize; private readonly List _nonNullableColumns = new List(); - public NullSemanticsRewritingExpressionVisitor(ISqlExpressionFactory sqlExpressionFactory) + public NullSemanticsRewritingExpressionVisitor([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; _canOptimize = true; @@ -25,6 +27,8 @@ public NullSemanticsRewritingExpressionVisitor(ISqlExpressionFactory sqlExpressi protected override Expression VisitCase(CaseExpression caseExpression) { + Check.NotNull(caseExpression, nameof(caseExpression)); + _isNullable = false; // if there is no 'else' there is a possibility of null, when none of the conditions are met // otherwise the result is nullable if any of the WhenClause results OR ElseResult is nullable @@ -56,6 +60,8 @@ protected override Expression VisitCase(CaseExpression caseExpression) protected override Expression VisitColumn(ColumnExpression columnExpression) { + Check.NotNull(columnExpression, nameof(columnExpression)); + _isNullable = !_nonNullableColumns.Contains(columnExpression) && columnExpression.IsNullable; return columnExpression; @@ -63,6 +69,8 @@ protected override Expression VisitColumn(ColumnExpression columnExpression) protected override Expression VisitCrossApply(CrossApplyExpression crossApplyExpression) { + Check.NotNull(crossApplyExpression, nameof(crossApplyExpression)); + var canOptimize = _canOptimize; _canOptimize = false; var table = (TableExpressionBase)Visit(crossApplyExpression.Table); @@ -73,6 +81,8 @@ protected override Expression VisitCrossApply(CrossApplyExpression crossApplyExp protected override Expression VisitCrossJoin(CrossJoinExpression crossJoinExpression) { + Check.NotNull(crossJoinExpression, nameof(crossJoinExpression)); + var canOptimize = _canOptimize; _canOptimize = false; var table = (TableExpressionBase)Visit(crossJoinExpression.Table); @@ -83,6 +93,8 @@ protected override Expression VisitCrossJoin(CrossJoinExpression crossJoinExpres protected override Expression VisitExcept(ExceptExpression exceptExpression) { + Check.NotNull(exceptExpression, nameof(exceptExpression)); + var canOptimize = _canOptimize; _canOptimize = false; var source1 = (SelectExpression)Visit(exceptExpression.Source1); @@ -94,6 +106,8 @@ protected override Expression VisitExcept(ExceptExpression exceptExpression) protected override Expression VisitExists(ExistsExpression existsExpression) { + Check.NotNull(existsExpression, nameof(existsExpression)); + var canOptimize = _canOptimize; _canOptimize = false; var newSubquery = (SelectExpression)Visit(existsExpression.Subquery); @@ -103,10 +117,16 @@ protected override Expression VisitExists(ExistsExpression existsExpression) } protected override Expression VisitFromSql(FromSqlExpression fromSqlExpression) - => fromSqlExpression; + { + Check.NotNull(fromSqlExpression, nameof(fromSqlExpression)); + + return fromSqlExpression; + } protected override Expression VisitIn(InExpression inExpression) { + Check.NotNull(inExpression, nameof(inExpression)); + var canOptimize = _canOptimize; _canOptimize = false; _isNullable = false; @@ -125,6 +145,8 @@ protected override Expression VisitIn(InExpression inExpression) protected override Expression VisitIntersect(IntersectExpression intersectExpression) { + Check.NotNull(intersectExpression, nameof(intersectExpression)); + var canOptimize = _canOptimize; _canOptimize = false; var source1 = (SelectExpression)Visit(intersectExpression.Source1); @@ -136,6 +158,8 @@ protected override Expression VisitIntersect(IntersectExpression intersectExpres protected override Expression VisitLike(LikeExpression likeExpression) { + Check.NotNull(likeExpression, nameof(likeExpression)); + var canOptimize = _canOptimize; _canOptimize = false; _isNullable = false; @@ -154,6 +178,8 @@ protected override Expression VisitLike(LikeExpression likeExpression) protected override Expression VisitInnerJoin(InnerJoinExpression innerJoinExpression) { + Check.NotNull(innerJoinExpression, nameof(innerJoinExpression)); + var canOptimize = _canOptimize; _canOptimize = false; var newTable = (TableExpressionBase)Visit(innerJoinExpression.Table); @@ -165,6 +191,8 @@ protected override Expression VisitInnerJoin(InnerJoinExpression innerJoinExpres protected override Expression VisitLeftJoin(LeftJoinExpression leftJoinExpression) { + Check.NotNull(leftJoinExpression, nameof(leftJoinExpression)); + var canOptimize = _canOptimize; _canOptimize = false; var newTable = (TableExpressionBase)Visit(leftJoinExpression.Table); @@ -201,6 +229,8 @@ private SqlExpression VisitJoinPredicate(SqlBinaryExpression predicate) protected override Expression VisitOrdering(OrderingExpression orderingExpression) { + Check.NotNull(orderingExpression, nameof(orderingExpression)); + var expression = (SqlExpression)Visit(orderingExpression.Expression); return orderingExpression.Update(expression); @@ -208,6 +238,8 @@ protected override Expression VisitOrdering(OrderingExpression orderingExpressio protected override Expression VisitOuterApply(OuterApplyExpression outerApplyExpression) { + Check.NotNull(outerApplyExpression, nameof(outerApplyExpression)); + var canOptimize = _canOptimize; _canOptimize = false; var table = (TableExpressionBase)Visit(outerApplyExpression.Table); @@ -218,6 +250,8 @@ protected override Expression VisitOuterApply(OuterApplyExpression outerApplyExp protected override Expression VisitProjection(ProjectionExpression projectionExpression) { + Check.NotNull(projectionExpression, nameof(projectionExpression)); + var expression = (SqlExpression)Visit(projectionExpression.Expression); return projectionExpression.Update(expression); @@ -225,6 +259,8 @@ protected override Expression VisitProjection(ProjectionExpression projectionExp protected override Expression VisitRowNumber(RowNumberExpression rowNumberExpression) { + Check.NotNull(rowNumberExpression, nameof(rowNumberExpression)); + var canOptimize = _canOptimize; _canOptimize = false; var changed = false; @@ -251,6 +287,8 @@ protected override Expression VisitRowNumber(RowNumberExpression rowNumberExpres protected override Expression VisitScalarSubquery(ScalarSubqueryExpression scalarSubqueryExpression) { + Check.NotNull(scalarSubqueryExpression, nameof(scalarSubqueryExpression)); + var canOptimize = _canOptimize; _canOptimize = false; var subquery = (SelectExpression)Visit(scalarSubqueryExpression.Subquery); @@ -261,6 +299,8 @@ protected override Expression VisitScalarSubquery(ScalarSubqueryExpression scala protected override Expression VisitSelect(SelectExpression selectExpression) { + Check.NotNull(selectExpression, nameof(selectExpression)); + var changed = false; var canOptimize = _canOptimize; var projections = new List(); @@ -327,6 +367,8 @@ protected override Expression VisitSelect(SelectExpression selectExpression) protected override Expression VisitSqlBinary(SqlBinaryExpression sqlBinaryExpression) { + Check.NotNull(sqlBinaryExpression, nameof(sqlBinaryExpression)); + _isNullable = false; var canOptimize = _canOptimize; @@ -537,16 +579,24 @@ protected override Expression VisitSqlBinary(SqlBinaryExpression sqlBinaryExpres protected override Expression VisitSqlConstant(SqlConstantExpression sqlConstantExpression) { + Check.NotNull(sqlConstantExpression, nameof(sqlConstantExpression)); + _isNullable = sqlConstantExpression.Value == null; return sqlConstantExpression; } protected override Expression VisitSqlFragment(SqlFragmentExpression sqlFragmentExpression) - => sqlFragmentExpression; + { + Check.NotNull(sqlFragmentExpression, nameof(sqlFragmentExpression)); + + return sqlFragmentExpression; + } protected override Expression VisitSqlFunction(SqlFunctionExpression sqlFunctionExpression) { + Check.NotNull(sqlFunctionExpression, nameof(sqlFunctionExpression)); + var canOptimize = _canOptimize; _canOptimize = false; @@ -567,6 +617,8 @@ protected override Expression VisitSqlFunction(SqlFunctionExpression sqlFunction protected override Expression VisitSqlParameter(SqlParameterExpression sqlParameterExpression) { + Check.NotNull(sqlParameterExpression, nameof(sqlParameterExpression)); + // at this point we assume every parameter is nullable, we will filter out the non-nullable ones once we know the actual values _isNullable = true; @@ -575,6 +627,8 @@ protected override Expression VisitSqlParameter(SqlParameterExpression sqlParame protected override Expression VisitSqlUnary(SqlUnaryExpression sqlCastExpression) { + Check.NotNull(sqlCastExpression, nameof(sqlCastExpression)); + _isNullable = false; var canOptimize = _canOptimize; @@ -595,10 +649,16 @@ protected override Expression VisitSqlUnary(SqlUnaryExpression sqlCastExpression } protected override Expression VisitTable(TableExpression tableExpression) - => tableExpression; + { + Check.NotNull(tableExpression, nameof(tableExpression)); + + return tableExpression; + } protected override Expression VisitUnion(UnionExpression unionExpression) { + Check.NotNull(unionExpression, nameof(unionExpression)); + var canOptimize = _canOptimize; _canOptimize = false; var source1 = (SelectExpression)Visit(unionExpression.Source1); diff --git a/src/EFCore.Relational/Query/Internal/NullableMemberTranslator.cs b/src/EFCore.Relational/Query/Internal/NullableMemberTranslator.cs index 8a103805c37..7b30dbd646e 100644 --- a/src/EFCore.Relational/Query/Internal/NullableMemberTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/NullableMemberTranslator.cs @@ -3,7 +3,9 @@ using System; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.Internal { @@ -11,13 +13,16 @@ public class NullableMemberTranslator : IMemberTranslator { private readonly ISqlExpressionFactory _sqlExpressionFactory; - public NullableMemberTranslator(ISqlExpressionFactory sqlExpressionFactory) + public NullableMemberTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { + Check.NotNull(member, nameof(member)); + Check.NotNull(returnType, nameof(returnType)); + if (member.DeclaringType.IsNullableValueType()) { switch (member.Name) diff --git a/src/EFCore.Relational/Query/Internal/QuerySqlGeneratorFactory.cs b/src/EFCore.Relational/Query/Internal/QuerySqlGeneratorFactory.cs index cfd2510fdf3..3f9ca4abae1 100644 --- a/src/EFCore.Relational/Query/Internal/QuerySqlGeneratorFactory.cs +++ b/src/EFCore.Relational/Query/Internal/QuerySqlGeneratorFactory.cs @@ -1,13 +1,15 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using JetBrains.Annotations; + namespace Microsoft.EntityFrameworkCore.Query.Internal { public class QuerySqlGeneratorFactory : IQuerySqlGeneratorFactory { private readonly QuerySqlGeneratorDependencies _dependencies; - public QuerySqlGeneratorFactory(QuerySqlGeneratorDependencies dependencies) + public QuerySqlGeneratorFactory([NotNull] QuerySqlGeneratorDependencies dependencies) { _dependencies = dependencies; } diff --git a/src/EFCore.Relational/Query/Internal/QueryingEnumerable.cs b/src/EFCore.Relational/Query/Internal/QueryingEnumerable.cs index 4a58a8c7acb..c8b70945ee0 100644 --- a/src/EFCore.Relational/Query/Internal/QueryingEnumerable.cs +++ b/src/EFCore.Relational/Query/Internal/QueryingEnumerable.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Storage; @@ -30,13 +31,13 @@ public class QueryingEnumerable : IEnumerable, IAsyncEnumerable private readonly IDiagnosticsLogger _logger; public QueryingEnumerable( - RelationalQueryContext relationalQueryContext, - RelationalCommandCache relationalCommandCache, - IReadOnlyList columnNames, - IReadOnlyList readerColumns, - Func shaper, - Type contextType, - IDiagnosticsLogger logger) + [NotNull] RelationalQueryContext relationalQueryContext, + [NotNull] RelationalCommandCache relationalCommandCache, + [NotNull] IReadOnlyList columnNames, + [NotNull] IReadOnlyList readerColumns, + [NotNull] Func shaper, + [NotNull] Type contextType, + [NotNull] IDiagnosticsLogger logger) { _relationalQueryContext = relationalQueryContext; _relationalCommandCache = relationalCommandCache; @@ -53,7 +54,7 @@ public virtual IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancella public virtual IEnumerator GetEnumerator() => new Enumerator(this); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - public static int[] BuildIndexMap(IReadOnlyList columnNames, DbDataReader dataReader) + public static int[] BuildIndexMap([CanBeNull] IReadOnlyList columnNames, [NotNull] DbDataReader dataReader) { if (columnNames == null) { diff --git a/src/EFCore.Relational/Query/Internal/RelationalCommandCache.cs b/src/EFCore.Relational/Query/Internal/RelationalCommandCache.cs index 564daf5b287..15124daf2e1 100644 --- a/src/EFCore.Relational/Query/Internal/RelationalCommandCache.cs +++ b/src/EFCore.Relational/Query/Internal/RelationalCommandCache.cs @@ -4,6 +4,7 @@ using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.Extensions.Caching.Memory; @@ -27,12 +28,12 @@ private static readonly ConcurrentDictionary _syncObjects private readonly RelationalParameterBasedQueryTranslationPostprocessor _relationalParameterBasedQueryTranslationPostprocessor; public RelationalCommandCache( - IMemoryCache memoryCache, - ISqlExpressionFactory sqlExpressionFactory, - IQuerySqlGeneratorFactory querySqlGeneratorFactory, - IRelationalParameterBasedQueryTranslationPostprocessorFactory relationalParameterBasedQueryTranslationPostprocessorFactory, + [NotNull] IMemoryCache memoryCache, + [NotNull] ISqlExpressionFactory sqlExpressionFactory, + [NotNull] IQuerySqlGeneratorFactory querySqlGeneratorFactory, + [NotNull] IRelationalParameterBasedQueryTranslationPostprocessorFactory relationalParameterBasedQueryTranslationPostprocessorFactory, bool useRelationalNulls, - SelectExpression selectExpression) + [NotNull] SelectExpression selectExpression) { _memoryCache = memoryCache; _querySqlGeneratorFactory = querySqlGeneratorFactory; @@ -40,7 +41,7 @@ public RelationalCommandCache( _relationalParameterBasedQueryTranslationPostprocessor = relationalParameterBasedQueryTranslationPostprocessorFactory.Create(useRelationalNulls); } - public virtual IRelationalCommand GetRelationalCommand(IReadOnlyDictionary parameters) + public virtual IRelationalCommand GetRelationalCommand([NotNull] IReadOnlyDictionary parameters) { var cacheKey = new CommandCacheKey(_selectExpression, parameters); diff --git a/src/EFCore.Relational/Query/Internal/RelationalProjectionBindingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/RelationalProjectionBindingExpressionVisitor.cs index 6a4463a9458..694ea4513c1 100644 --- a/src/EFCore.Relational/Query/Internal/RelationalProjectionBindingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/RelationalProjectionBindingExpressionVisitor.cs @@ -6,10 +6,12 @@ using System.Linq; using System.Linq.Expressions; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.Internal { @@ -27,14 +29,14 @@ private readonly IDictionary _projectionMapping private readonly Stack _projectionMembers = new Stack(); public RelationalProjectionBindingExpressionVisitor( - RelationalQueryableMethodTranslatingExpressionVisitor queryableMethodTranslatingExpressionVisitor, - RelationalSqlTranslatingExpressionVisitor sqlTranslatingExpressionVisitor) + [NotNull] RelationalQueryableMethodTranslatingExpressionVisitor queryableMethodTranslatingExpressionVisitor, + [NotNull] RelationalSqlTranslatingExpressionVisitor sqlTranslatingExpressionVisitor) { _queryableMethodTranslatingExpressionVisitor = queryableMethodTranslatingExpressionVisitor; _sqlTranslator = sqlTranslatingExpressionVisitor; } - public virtual Expression Translate(SelectExpression selectExpression, Expression expression) + public virtual Expression Translate([NotNull] SelectExpression selectExpression, [NotNull] Expression expression) { _selectExpression = selectExpression; _clientEval = false; @@ -186,6 +188,8 @@ private static T GetParameterValue(QueryContext queryContext, string paramete protected override Expression VisitExtension(Expression extensionExpression) { + Check.NotNull(extensionExpression, nameof(extensionExpression)); + if (extensionExpression is EntityShaperExpression entityShaperExpression) { EntityProjectionExpression entityProjectionExpression; @@ -225,6 +229,8 @@ protected override Expression VisitExtension(Expression extensionExpression) protected override Expression VisitNew(NewExpression newExpression) { + Check.NotNull(newExpression, nameof(newExpression)); + if (newExpression.Arguments.Count == 0) { return newExpression; @@ -262,6 +268,8 @@ protected override Expression VisitNew(NewExpression newExpression) protected override Expression VisitMemberInit(MemberInitExpression memberInitExpression) { + Check.NotNull(memberInitExpression, nameof(memberInitExpression)); + var newExpression = Visit(memberInitExpression.NewExpression); if (newExpression == null) { diff --git a/src/EFCore.Relational/Query/Internal/RelationalQueryTranslationPostprocessorFactory.cs b/src/EFCore.Relational/Query/Internal/RelationalQueryTranslationPostprocessorFactory.cs index f39a2a71199..b54dff17917 100644 --- a/src/EFCore.Relational/Query/Internal/RelationalQueryTranslationPostprocessorFactory.cs +++ b/src/EFCore.Relational/Query/Internal/RelationalQueryTranslationPostprocessorFactory.cs @@ -1,6 +1,8 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; namespace Microsoft.EntityFrameworkCore.Query.Internal @@ -21,8 +23,8 @@ public class RelationalQueryTranslationPostprocessorFactory : IQueryTranslationP private readonly RelationalQueryTranslationPostprocessorDependencies _relationalDependencies; public RelationalQueryTranslationPostprocessorFactory( - QueryTranslationPostprocessorDependencies dependencies, - RelationalQueryTranslationPostprocessorDependencies relationalDependencies) + [NotNull] QueryTranslationPostprocessorDependencies dependencies, + [NotNull] RelationalQueryTranslationPostprocessorDependencies relationalDependencies) { _dependencies = dependencies; _relationalDependencies = relationalDependencies; @@ -30,6 +32,8 @@ public RelationalQueryTranslationPostprocessorFactory( public virtual QueryTranslationPostprocessor Create(QueryCompilationContext queryCompilationContext) { + Check.NotNull(queryCompilationContext, nameof(queryCompilationContext)); + return new RelationalQueryTranslationPostprocessor( _dependencies, _relationalDependencies, diff --git a/src/EFCore.Relational/Query/Internal/RelationalQueryTranslationPreprocessorFactory.cs b/src/EFCore.Relational/Query/Internal/RelationalQueryTranslationPreprocessorFactory.cs index b536580b009..8ba74997331 100644 --- a/src/EFCore.Relational/Query/Internal/RelationalQueryTranslationPreprocessorFactory.cs +++ b/src/EFCore.Relational/Query/Internal/RelationalQueryTranslationPreprocessorFactory.cs @@ -1,6 +1,8 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; namespace Microsoft.EntityFrameworkCore.Query.Internal @@ -21,14 +23,18 @@ public class RelationalQueryTranslationPreprocessorFactory : IQueryTranslationPr private readonly RelationalQueryTranslationPreprocessorDependencies _relationalDependencies; public RelationalQueryTranslationPreprocessorFactory( - QueryTranslationPreprocessorDependencies dependencies, - RelationalQueryTranslationPreprocessorDependencies relationalDependencies) + [NotNull] QueryTranslationPreprocessorDependencies dependencies, + [NotNull] RelationalQueryTranslationPreprocessorDependencies relationalDependencies) { _dependencies = dependencies; _relationalDependencies = relationalDependencies; } public virtual QueryTranslationPreprocessor Create(QueryCompilationContext queryCompilationContext) - => new RelationalQueryTranslationPreprocessor(_dependencies, _relationalDependencies, queryCompilationContext); + { + Check.NotNull(queryCompilationContext, nameof(queryCompilationContext)); + + return new RelationalQueryTranslationPreprocessor(_dependencies, _relationalDependencies, queryCompilationContext); + } } } diff --git a/src/EFCore.Relational/Query/Internal/RelationalQueryableMethodTranslatingExpressionVisitorFactory.cs b/src/EFCore.Relational/Query/Internal/RelationalQueryableMethodTranslatingExpressionVisitorFactory.cs index 58e89303c5c..bb5708785e2 100644 --- a/src/EFCore.Relational/Query/Internal/RelationalQueryableMethodTranslatingExpressionVisitorFactory.cs +++ b/src/EFCore.Relational/Query/Internal/RelationalQueryableMethodTranslatingExpressionVisitorFactory.cs @@ -1,7 +1,9 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; namespace Microsoft.EntityFrameworkCore.Query.Internal @@ -22,17 +24,21 @@ public class RelationalQueryableMethodTranslatingExpressionVisitorFactory : IQue private readonly RelationalQueryableMethodTranslatingExpressionVisitorDependencies _relationalDependencies; public RelationalQueryableMethodTranslatingExpressionVisitorFactory( - QueryableMethodTranslatingExpressionVisitorDependencies dependencies, - RelationalQueryableMethodTranslatingExpressionVisitorDependencies relationalDependencies) + [NotNull] QueryableMethodTranslatingExpressionVisitorDependencies dependencies, + [NotNull] RelationalQueryableMethodTranslatingExpressionVisitorDependencies relationalDependencies) { _dependencies = dependencies; _relationalDependencies = relationalDependencies; } public virtual QueryableMethodTranslatingExpressionVisitor Create(IModel model) - => new RelationalQueryableMethodTranslatingExpressionVisitor( + { + Check.NotNull(model, nameof(model)); + + return new RelationalQueryableMethodTranslatingExpressionVisitor( _dependencies, _relationalDependencies, model); + } } } diff --git a/src/EFCore.Relational/Query/Internal/RelationalShapedQueryCompilingExpressionVisitorFactory.cs b/src/EFCore.Relational/Query/Internal/RelationalShapedQueryCompilingExpressionVisitorFactory.cs index b1db95792fb..6486125beb3 100644 --- a/src/EFCore.Relational/Query/Internal/RelationalShapedQueryCompilingExpressionVisitorFactory.cs +++ b/src/EFCore.Relational/Query/Internal/RelationalShapedQueryCompilingExpressionVisitorFactory.cs @@ -1,6 +1,8 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; namespace Microsoft.EntityFrameworkCore.Query.Internal @@ -21,17 +23,21 @@ public class RelationalShapedQueryCompilingExpressionVisitorFactory : IShapedQue private readonly RelationalShapedQueryCompilingExpressionVisitorDependencies _relationalDependencies; public RelationalShapedQueryCompilingExpressionVisitorFactory( - ShapedQueryCompilingExpressionVisitorDependencies dependencies, - RelationalShapedQueryCompilingExpressionVisitorDependencies relationalDependencies) + [NotNull] ShapedQueryCompilingExpressionVisitorDependencies dependencies, + [NotNull] RelationalShapedQueryCompilingExpressionVisitorDependencies relationalDependencies) { _dependencies = dependencies; _relationalDependencies = relationalDependencies; } public virtual ShapedQueryCompilingExpressionVisitor Create(QueryCompilationContext queryCompilationContext) - => new RelationalShapedQueryCompilingExpressionVisitor( + { + Check.NotNull(queryCompilationContext, nameof(queryCompilationContext)); + + return new RelationalShapedQueryCompilingExpressionVisitor( _dependencies, _relationalDependencies, queryCompilationContext); + } } } diff --git a/src/EFCore.Relational/Query/Internal/RelationalSqlTranslatingExpressionVisitorFactory.cs b/src/EFCore.Relational/Query/Internal/RelationalSqlTranslatingExpressionVisitorFactory.cs index 7c8cae5828d..0895a00638d 100644 --- a/src/EFCore.Relational/Query/Internal/RelationalSqlTranslatingExpressionVisitorFactory.cs +++ b/src/EFCore.Relational/Query/Internal/RelationalSqlTranslatingExpressionVisitorFactory.cs @@ -3,6 +3,7 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query { @@ -20,6 +21,9 @@ public virtual RelationalSqlTranslatingExpressionVisitor Create( IModel model, QueryableMethodTranslatingExpressionVisitor queryableMethodTranslatingExpressionVisitor) { + Check.NotNull(model, nameof(model)); + Check.NotNull(queryableMethodTranslatingExpressionVisitor, nameof(queryableMethodTranslatingExpressionVisitor)); + return new RelationalSqlTranslatingExpressionVisitor( _dependencies, model, diff --git a/src/EFCore.Relational/Query/Internal/ResultContext.cs b/src/EFCore.Relational/Query/Internal/ResultContext.cs index 61f960eb793..7e962489f64 100644 --- a/src/EFCore.Relational/Query/Internal/ResultContext.cs +++ b/src/EFCore.Relational/Query/Internal/ResultContext.cs @@ -1,6 +1,8 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using JetBrains.Annotations; + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// @@ -11,6 +13,6 @@ namespace Microsoft.EntityFrameworkCore.Query.Internal /// public class ResultContext { - public virtual object[] Values { get; set; } + public virtual object[] Values { get; [param: NotNull] set; } } } diff --git a/src/EFCore.Relational/Query/Internal/ResultCoordinator.cs b/src/EFCore.Relational/Query/Internal/ResultCoordinator.cs index 1dd9a6a9131..86e6ee39d09 100644 --- a/src/EFCore.Relational/Query/Internal/ResultCoordinator.cs +++ b/src/EFCore.Relational/Query/Internal/ResultCoordinator.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; +using JetBrains.Annotations; namespace Microsoft.EntityFrameworkCore.Query.Internal { @@ -24,7 +25,7 @@ public ResultCoordinator() public virtual IList Collections { get; } = new List(); public virtual void SetCollectionMaterializationContext( - int collectionId, CollectionMaterializationContext collectionMaterializationContext) + int collectionId, [NotNull] CollectionMaterializationContext collectionMaterializationContext) { while (Collections.Count <= collectionId) { diff --git a/src/EFCore.Relational/Query/Internal/SelectExpressionProjectionApplyingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/SelectExpressionProjectionApplyingExpressionVisitor.cs index 2be4e1c47bc..1f0b1a091ba 100644 --- a/src/EFCore.Relational/Query/Internal/SelectExpressionProjectionApplyingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/SelectExpressionProjectionApplyingExpressionVisitor.cs @@ -3,6 +3,7 @@ using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.Internal { @@ -10,6 +11,8 @@ public class SelectExpressionProjectionApplyingExpressionVisitor : ExpressionVis { protected override Expression VisitExtension(Expression node) { + Check.NotNull(node, nameof(node)); + if (node is SelectExpression selectExpression) { selectExpression.ApplyProjection(); diff --git a/src/EFCore.Relational/Query/Internal/SqlExpressionOptimizingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/SqlExpressionOptimizingExpressionVisitor.cs index 5e72b69104c..1e555aa198d 100644 --- a/src/EFCore.Relational/Query/Internal/SqlExpressionOptimizingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/SqlExpressionOptimizingExpressionVisitor.cs @@ -4,8 +4,10 @@ using System; using System.Linq; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.Internal { @@ -33,7 +35,7 @@ private static bool TryNegate(ExpressionType expressionType, out ExpressionType return negated.HasValue; } - public SqlExpressionOptimizingExpressionVisitor(ISqlExpressionFactory sqlExpressionFactory, bool useRelationalNulls) + public SqlExpressionOptimizingExpressionVisitor([NotNull] ISqlExpressionFactory sqlExpressionFactory, bool useRelationalNulls) { SqlExpressionFactory = sqlExpressionFactory; _useRelationalNulls = useRelationalNulls; @@ -42,13 +44,17 @@ public SqlExpressionOptimizingExpressionVisitor(ISqlExpressionFactory sqlExpress protected virtual ISqlExpressionFactory SqlExpressionFactory { get; } protected override Expression VisitExtension(Expression extensionExpression) - => extensionExpression switch + { + Check.NotNull(extensionExpression, nameof(extensionExpression)); + + return extensionExpression switch { SqlUnaryExpression sqlUnaryExpression => VisitSqlUnaryExpression(sqlUnaryExpression), SqlBinaryExpression sqlBinaryExpression => VisitSqlBinaryExpression(sqlBinaryExpression), SelectExpression selectExpression => VisitSelectExpression(selectExpression), _ => base.VisitExtension(extensionExpression), }; + } private Expression VisitSelectExpression(SelectExpression selectExpression) { @@ -94,7 +100,7 @@ private Expression VisitSelectExpression(SelectExpression selectExpression) return newExpression; } - protected virtual Expression VisitSqlUnaryExpression(SqlUnaryExpression sqlUnaryExpression) + protected virtual Expression VisitSqlUnaryExpression([NotNull] SqlUnaryExpression sqlUnaryExpression) { var newOperand = (SqlExpression)Visit(sqlUnaryExpression.Operand); @@ -280,7 +286,7 @@ private SqlExpression SimplifyNullNotNullExpression( return SqlExpressionFactory.MakeUnary(operatorType, operand, type, typeMapping); } - protected virtual Expression VisitSqlBinaryExpression(SqlBinaryExpression sqlBinaryExpression) + protected virtual Expression VisitSqlBinaryExpression([NotNull] SqlBinaryExpression sqlBinaryExpression) { var newLeft = (SqlExpression)Visit(sqlBinaryExpression.Left); var newRight = (SqlExpression)Visit(sqlBinaryExpression.Right); @@ -375,11 +381,11 @@ private SqlExpression SimplifyBinaryExpression( protected virtual SqlExpression SimplifyNullComparisonExpression( ExpressionType operatorType, - SqlExpression left, - SqlExpression right, + [NotNull] SqlExpression left, + [NotNull] SqlExpression right, bool leftNull, bool rightNull, - RelationalTypeMapping typeMapping) + [CanBeNull] RelationalTypeMapping typeMapping) { if ((operatorType == ExpressionType.Equal || operatorType == ExpressionType.NotEqual) && (leftNull || rightNull)) diff --git a/src/EFCore.Relational/Query/Internal/StringMethodTranslator.cs b/src/EFCore.Relational/Query/Internal/StringMethodTranslator.cs index f39857765f0..1d18b85268f 100644 --- a/src/EFCore.Relational/Query/Internal/StringMethodTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/StringMethodTranslator.cs @@ -3,7 +3,9 @@ using System.Collections.Generic; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.Internal { @@ -17,13 +19,16 @@ private static readonly MethodInfo _concatMethodInfo private readonly ISqlExpressionFactory _sqlExpressionFactory; - public StringMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) + public StringMethodTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { + Check.NotNull(method, nameof(method)); + Check.NotNull(arguments, nameof(arguments)); + if (Equals(method, _isNullOrEmptyMethodInfo)) { var argument = arguments[0]; diff --git a/src/EFCore.Relational/Query/Internal/TableAliasUniquifyingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/TableAliasUniquifyingExpressionVisitor.cs index 95deea9123a..75656d83d83 100644 --- a/src/EFCore.Relational/Query/Internal/TableAliasUniquifyingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/TableAliasUniquifyingExpressionVisitor.cs @@ -6,6 +6,7 @@ using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.Internal { @@ -18,6 +19,8 @@ private readonly ISet _visitedTableExpressionBases protected override Expression VisitExtension(Expression extensionExpression) { + Check.NotNull(extensionExpression, nameof(extensionExpression)); + var visitedExpression = base.VisitExtension(extensionExpression); if (visitedExpression is TableExpressionBase tableExpressionBase && !_visitedTableExpressionBases.Contains(tableExpressionBase) diff --git a/src/EFCore.Relational/Query/QuerySqlGenerator.cs b/src/EFCore.Relational/Query/QuerySqlGenerator.cs index 813044bdefe..37300d8749b 100644 --- a/src/EFCore.Relational/Query/QuerySqlGenerator.cs +++ b/src/EFCore.Relational/Query/QuerySqlGenerator.cs @@ -6,11 +6,13 @@ using System.Linq; using System.Linq.Expressions; using System.Text.RegularExpressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query { @@ -42,8 +44,10 @@ private static readonly Regex _composableSql { ExpressionType.Or, " | " } }; - public QuerySqlGenerator(QuerySqlGeneratorDependencies dependencies) + public QuerySqlGenerator([NotNull] QuerySqlGeneratorDependencies dependencies) { + Check.NotNull(dependencies, nameof(dependencies)); + Dependencies = dependencies; _relationalCommandBuilderFactory = dependencies.RelationalCommandBuilderFactory; @@ -52,8 +56,10 @@ public QuerySqlGenerator(QuerySqlGeneratorDependencies dependencies) protected virtual QuerySqlGeneratorDependencies Dependencies { get; } - public virtual IRelationalCommand GetCommand(SelectExpression selectExpression) + public virtual IRelationalCommand GetCommand([NotNull] SelectExpression selectExpression) { + Check.NotNull(selectExpression, nameof(selectExpression)); + _relationalCommandBuilder = _relationalCommandBuilderFactory.Create(); GenerateTagsHeaderComment(selectExpression); @@ -77,8 +83,10 @@ public virtual IRelationalCommand GetCommand(SelectExpression selectExpression) protected virtual IRelationalCommandBuilder Sql => _relationalCommandBuilder; - protected virtual void GenerateTagsHeaderComment(SelectExpression selectExpression) + protected virtual void GenerateTagsHeaderComment([NotNull] SelectExpression selectExpression) { + Check.NotNull(selectExpression, nameof(selectExpression)); + if (selectExpression.Tags.Count > 0) { foreach (var tag in selectExpression.Tags) @@ -92,6 +100,8 @@ protected virtual void GenerateTagsHeaderComment(SelectExpression selectExpressi protected override Expression VisitSqlFragment(SqlFragmentExpression sqlFragmentExpression) { + Check.NotNull(sqlFragmentExpression, nameof(sqlFragmentExpression)); + _relationalCommandBuilder.Append(sqlFragmentExpression.Sql); return sqlFragmentExpression; @@ -117,6 +127,8 @@ private bool IsNonComposedSetOperation(SelectExpression selectExpression) protected override Expression VisitSelect(SelectExpression selectExpression) { + Check.NotNull(selectExpression, nameof(selectExpression)); + if (IsNonComposedSetOperation(selectExpression)) { // Naked set operation @@ -207,6 +219,8 @@ protected virtual void GeneratePseudoFromClause() protected override Expression VisitProjection(ProjectionExpression projectionExpression) { + Check.NotNull(projectionExpression, nameof(projectionExpression)); + Visit(projectionExpression.Expression); if (!string.Equals(string.Empty, projectionExpression.Alias) @@ -221,6 +235,8 @@ protected override Expression VisitProjection(ProjectionExpression projectionExp protected override Expression VisitSqlFunction(SqlFunctionExpression sqlFunctionExpression) { + Check.NotNull(sqlFunctionExpression, nameof(sqlFunctionExpression)); + if (sqlFunctionExpression.IsBuiltIn) { if (sqlFunctionExpression.Instance != null) @@ -256,6 +272,8 @@ protected override Expression VisitSqlFunction(SqlFunctionExpression sqlFunction protected override Expression VisitColumn(ColumnExpression columnExpression) { + Check.NotNull(columnExpression, nameof(columnExpression)); + _relationalCommandBuilder .Append(_sqlGenerationHelper.DelimitIdentifier(columnExpression.Table.Alias)) .Append(".") @@ -266,6 +284,8 @@ protected override Expression VisitColumn(ColumnExpression columnExpression) protected override Expression VisitTable(TableExpression tableExpression) { + Check.NotNull(tableExpression, nameof(tableExpression)); + _relationalCommandBuilder .Append(_sqlGenerationHelper.DelimitIdentifier(tableExpression.Name, tableExpression.Schema)) .Append(AliasSeparator) @@ -330,6 +350,8 @@ private void GenerateFromSql(FromSqlExpression fromSqlExpression) protected override Expression VisitFromSql(FromSqlExpression fromSqlExpression) { + Check.NotNull(fromSqlExpression, nameof(fromSqlExpression)); + _relationalCommandBuilder.AppendLine("("); if (!_composableSql.IsMatch(fromSqlExpression.Sql)) @@ -351,6 +373,8 @@ protected override Expression VisitFromSql(FromSqlExpression fromSqlExpression) protected override Expression VisitSqlBinary(SqlBinaryExpression sqlBinaryExpression) { + Check.NotNull(sqlBinaryExpression, nameof(sqlBinaryExpression)); + if (sqlBinaryExpression.OperatorType == ExpressionType.Coalesce) { _relationalCommandBuilder.Append("COALESCE("); @@ -404,6 +428,8 @@ private bool RequiresBrackets(SqlExpression expression) protected override Expression VisitSqlConstant(SqlConstantExpression sqlConstantExpression) { + Check.NotNull(sqlConstantExpression, nameof(sqlConstantExpression)); + _relationalCommandBuilder .Append(sqlConstantExpression.TypeMapping.GenerateSqlLiteral(sqlConstantExpression.Value)); @@ -412,6 +438,8 @@ protected override Expression VisitSqlConstant(SqlConstantExpression sqlConstant protected override Expression VisitSqlParameter(SqlParameterExpression sqlParameterExpression) { + Check.NotNull(sqlParameterExpression, nameof(sqlParameterExpression)); + var parameterNameInCommand = _sqlGenerationHelper.GenerateParameterName(sqlParameterExpression.Name); if (_relationalCommandBuilder.Parameters @@ -432,6 +460,8 @@ protected override Expression VisitSqlParameter(SqlParameterExpression sqlParame protected override Expression VisitOrdering(OrderingExpression orderingExpression) { + Check.NotNull(orderingExpression, nameof(orderingExpression)); + if (orderingExpression.Expression is SqlConstantExpression || orderingExpression.Expression is SqlParameterExpression) { @@ -452,6 +482,8 @@ protected override Expression VisitOrdering(OrderingExpression orderingExpressio protected override Expression VisitLike(LikeExpression likeExpression) { + Check.NotNull(likeExpression, nameof(likeExpression)); + Visit(likeExpression.Match); _relationalCommandBuilder.Append(" LIKE "); Visit(likeExpression.Pattern); @@ -467,6 +499,8 @@ protected override Expression VisitLike(LikeExpression likeExpression) protected override Expression VisitCase(CaseExpression caseExpression) { + Check.NotNull(caseExpression, nameof(caseExpression)); + _relationalCommandBuilder.Append("CASE"); if (caseExpression.Operand != null) @@ -505,6 +539,8 @@ protected override Expression VisitCase(CaseExpression caseExpression) protected override Expression VisitSqlUnary(SqlUnaryExpression sqlUnaryExpression) { + Check.NotNull(sqlUnaryExpression, nameof(sqlUnaryExpression)); + switch (sqlUnaryExpression.OperatorType) { case ExpressionType.Convert: @@ -571,6 +607,8 @@ when sqlUnaryExpression.IsLogicalNot(): protected override Expression VisitExists(ExistsExpression existsExpression) { + Check.NotNull(existsExpression, nameof(existsExpression)); + if (existsExpression.IsNegated) { _relationalCommandBuilder.Append("NOT "); @@ -590,6 +628,8 @@ protected override Expression VisitExists(ExistsExpression existsExpression) protected override Expression VisitIn(InExpression inExpression) { + Check.NotNull(inExpression, nameof(inExpression)); + if (inExpression.Values != null) { Visit(inExpression.Item); @@ -618,15 +658,22 @@ protected override Expression VisitIn(InExpression inExpression) return inExpression; } - protected virtual string GenerateOperator(SqlBinaryExpression binaryExpression) - => _operatorMap[binaryExpression.OperatorType]; + protected virtual string GenerateOperator([NotNull] SqlBinaryExpression binaryExpression) + { + Check.NotNull(binaryExpression, nameof(binaryExpression)); - protected virtual void GenerateTop(SelectExpression selectExpression) + return _operatorMap[binaryExpression.OperatorType]; + } + + protected virtual void GenerateTop([NotNull] SelectExpression selectExpression) { + Check.NotNull(selectExpression, nameof(selectExpression)); } - protected virtual void GenerateOrderings(SelectExpression selectExpression) + protected virtual void GenerateOrderings([NotNull] SelectExpression selectExpression) { + Check.NotNull(selectExpression, nameof(selectExpression)); + if (selectExpression.Orderings.Any()) { var orderings = selectExpression.Orderings.ToList(); @@ -651,8 +698,10 @@ protected virtual void GenerateOrderings(SelectExpression selectExpression) } } - protected virtual void GenerateLimitOffset(SelectExpression selectExpression) + protected virtual void GenerateLimitOffset([NotNull] SelectExpression selectExpression) { + Check.NotNull(selectExpression, nameof(selectExpression)); + if (selectExpression.Offset != null) { _relationalCommandBuilder.AppendLine() @@ -702,6 +751,8 @@ private void GenerateList( protected override Expression VisitCrossJoin(CrossJoinExpression crossJoinExpression) { + Check.NotNull(crossJoinExpression, nameof(crossJoinExpression)); + _relationalCommandBuilder.Append("CROSS JOIN "); Visit(crossJoinExpression.Table); @@ -710,6 +761,8 @@ protected override Expression VisitCrossJoin(CrossJoinExpression crossJoinExpres protected override Expression VisitCrossApply(CrossApplyExpression crossApplyExpression) { + Check.NotNull(crossApplyExpression, nameof(crossApplyExpression)); + _relationalCommandBuilder.Append("CROSS APPLY "); Visit(crossApplyExpression.Table); @@ -718,6 +771,8 @@ protected override Expression VisitCrossApply(CrossApplyExpression crossApplyExp protected override Expression VisitOuterApply(OuterApplyExpression outerApplyExpression) { + Check.NotNull(outerApplyExpression, nameof(outerApplyExpression)); + _relationalCommandBuilder.Append("OUTER APPLY "); Visit(outerApplyExpression.Table); @@ -726,6 +781,8 @@ protected override Expression VisitOuterApply(OuterApplyExpression outerApplyExp protected override Expression VisitInnerJoin(InnerJoinExpression innerJoinExpression) { + Check.NotNull(innerJoinExpression, nameof(innerJoinExpression)); + _relationalCommandBuilder.Append("INNER JOIN "); Visit(innerJoinExpression.Table); _relationalCommandBuilder.Append(" ON "); @@ -736,6 +793,8 @@ protected override Expression VisitInnerJoin(InnerJoinExpression innerJoinExpres protected override Expression VisitLeftJoin(LeftJoinExpression leftJoinExpression) { + Check.NotNull(leftJoinExpression, nameof(leftJoinExpression)); + _relationalCommandBuilder.Append("LEFT JOIN "); Visit(leftJoinExpression.Table); _relationalCommandBuilder.Append(" ON "); @@ -746,6 +805,8 @@ protected override Expression VisitLeftJoin(LeftJoinExpression leftJoinExpressio protected override Expression VisitScalarSubquery(ScalarSubqueryExpression scalarSubqueryExpression) { + Check.NotNull(scalarSubqueryExpression, nameof(scalarSubqueryExpression)); + _relationalCommandBuilder.AppendLine("("); using (_relationalCommandBuilder.Indent()) { @@ -759,6 +820,8 @@ protected override Expression VisitScalarSubquery(ScalarSubqueryExpression scala protected override Expression VisitRowNumber(RowNumberExpression rowNumberExpression) { + Check.NotNull(rowNumberExpression, nameof(rowNumberExpression)); + _relationalCommandBuilder.Append("ROW_NUMBER() OVER("); if (rowNumberExpression.Partitions.Any()) { @@ -774,8 +837,10 @@ protected override Expression VisitRowNumber(RowNumberExpression rowNumberExpres return rowNumberExpression; } - protected virtual void GenerateSetOperation(SetOperationBase setOperation) + protected virtual void GenerateSetOperation([NotNull] SetOperationBase setOperation) { + Check.NotNull(setOperation, nameof(setOperation)); + string getSetOperation() => setOperation switch { ExceptExpression _ => "EXCEPT", @@ -790,8 +855,11 @@ protected virtual void GenerateSetOperation(SetOperationBase setOperation) GenerateSetOperationOperand(setOperation, setOperation.Source2); } - protected virtual void GenerateSetOperationOperand(SetOperationBase setOperation, SelectExpression operand) + protected virtual void GenerateSetOperationOperand([NotNull] SetOperationBase setOperation, [NotNull] SelectExpression operand) { + Check.NotNull(setOperation, nameof(setOperation)); + Check.NotNull(operand, nameof(operand)); + // INTERSECT has higher precedence over UNION and EXCEPT, but otherwise evaluation is left-to-right. // To preserve meaning, add parentheses whenever a set operation is nested within a different set operation. if (IsNonComposedSetOperation(operand) @@ -827,6 +895,8 @@ private void GenerateSetOperationHelper(SetOperationBase setOperation) protected override Expression VisitExcept(ExceptExpression exceptExpression) { + Check.NotNull(exceptExpression, nameof(exceptExpression)); + GenerateSetOperationHelper(exceptExpression); return exceptExpression; @@ -834,6 +904,8 @@ protected override Expression VisitExcept(ExceptExpression exceptExpression) protected override Expression VisitIntersect(IntersectExpression intersectExpression) { + Check.NotNull(intersectExpression, nameof(intersectExpression)); + GenerateSetOperationHelper(intersectExpression); return intersectExpression; @@ -841,6 +913,8 @@ protected override Expression VisitIntersect(IntersectExpression intersectExpres protected override Expression VisitUnion(UnionExpression unionExpression) { + Check.NotNull(unionExpression, nameof(unionExpression)); + GenerateSetOperationHelper(unionExpression); return unionExpression; diff --git a/src/EFCore.Relational/Query/RelationalCollectionShaperExpression.cs b/src/EFCore.Relational/Query/RelationalCollectionShaperExpression.cs index e75d8c155e8..1cb03070176 100644 --- a/src/EFCore.Relational/Query/RelationalCollectionShaperExpression.cs +++ b/src/EFCore.Relational/Query/RelationalCollectionShaperExpression.cs @@ -4,7 +4,9 @@ using System; using System.Collections.Generic; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query { @@ -12,13 +14,17 @@ public class RelationalCollectionShaperExpression : Expression, IPrintableExpres { public RelationalCollectionShaperExpression( int collectionId, - Expression parentIdentifier, - Expression outerIdentifier, - Expression selfIdentifier, - Expression innerShaper, - INavigation navigation, - Type elementType) + [NotNull] Expression parentIdentifier, + [NotNull] Expression outerIdentifier, + [CanBeNull] Expression selfIdentifier, + [CanBeNull] Expression innerShaper, + [CanBeNull] INavigation navigation, + [NotNull] Type elementType) { + Check.NotNull(parentIdentifier, nameof(parentIdentifier)); + Check.NotNull(outerIdentifier, nameof(outerIdentifier)); + Check.NotNull(elementType, nameof(elementType)); + CollectionId = collectionId; ParentIdentifier = parentIdentifier; OuterIdentifier = outerIdentifier; @@ -41,6 +47,8 @@ public RelationalCollectionShaperExpression( protected override Expression VisitChildren(ExpressionVisitor visitor) { + Check.NotNull(visitor, nameof(visitor)); + var parentIdentifier = visitor.Visit(ParentIdentifier); var outerIdentifier = visitor.Visit(OuterIdentifier); var selfIdentifier = visitor.Visit(SelfIdentifier); @@ -50,8 +58,16 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) } public virtual RelationalCollectionShaperExpression Update( - Expression parentIdentifier, Expression outerIdentifier, Expression selfIdentifier, Expression innerShaper) + [NotNull] Expression parentIdentifier, + [NotNull] Expression outerIdentifier, + [NotNull] Expression selfIdentifier, + [NotNull] Expression innerShaper) { + Check.NotNull(parentIdentifier, nameof(parentIdentifier)); + Check.NotNull(outerIdentifier, nameof(outerIdentifier)); + Check.NotNull(selfIdentifier, nameof(selfIdentifier)); + Check.NotNull(innerShaper, nameof(innerShaper)); + return parentIdentifier != ParentIdentifier || outerIdentifier != OuterIdentifier || selfIdentifier != SelfIdentifier @@ -63,6 +79,8 @@ public virtual RelationalCollectionShaperExpression Update( public virtual void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.AppendLine("RelationalCollectionShaper:"); using (expressionPrinter.Indent()) { diff --git a/src/EFCore.Relational/Query/RelationalEvaluatableExpressionFilter.cs b/src/EFCore.Relational/Query/RelationalEvaluatableExpressionFilter.cs index 9cb272bb41d..786419d6ab5 100644 --- a/src/EFCore.Relational/Query/RelationalEvaluatableExpressionFilter.cs +++ b/src/EFCore.Relational/Query/RelationalEvaluatableExpressionFilter.cs @@ -55,6 +55,9 @@ public RelationalEvaluatableExpressionFilter( /// True if the expression can be evaluated; false otherwise. public override bool IsEvaluatableExpression(Expression expression, IModel model) { + Check.NotNull(expression, nameof(expression)); + Check.NotNull(model, nameof(model)); + if (expression is MethodCallExpression methodCallExpression && model.FindDbFunction(methodCallExpression.Method) != null) { diff --git a/src/EFCore.Relational/Query/RelationalMemberTranslatorProvider.cs b/src/EFCore.Relational/Query/RelationalMemberTranslatorProvider.cs index 1f7ca897f62..e63d09447e8 100644 --- a/src/EFCore.Relational/Query/RelationalMemberTranslatorProvider.cs +++ b/src/EFCore.Relational/Query/RelationalMemberTranslatorProvider.cs @@ -5,8 +5,10 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query { @@ -15,8 +17,10 @@ public class RelationalMemberTranslatorProvider : IMemberTranslatorProvider private readonly List _plugins = new List(); private readonly List _translators = new List(); - public RelationalMemberTranslatorProvider(RelationalMemberTranslatorProviderDependencies dependencies) + public RelationalMemberTranslatorProvider([NotNull] RelationalMemberTranslatorProviderDependencies dependencies) { + Check.NotNull(dependencies, nameof(dependencies)); + _plugins.AddRange(dependencies.Plugins.SelectMany(p => p.Translators)); _translators .AddRange( @@ -25,11 +29,18 @@ public RelationalMemberTranslatorProvider(RelationalMemberTranslatorProviderDepe public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { + Check.NotNull(member, nameof(member)); + Check.NotNull(returnType, nameof(returnType)); + return _plugins.Concat(_translators) .Select(t => t.Translate(instance, member, returnType)).FirstOrDefault(t => t != null); } - protected virtual void AddTranslators(IEnumerable translators) - => _translators.InsertRange(0, translators); + protected virtual void AddTranslators([NotNull] IEnumerable translators) + { + Check.NotNull(translators, nameof(translators)); + + _translators.InsertRange(0, translators); + } } } diff --git a/src/EFCore.Relational/Query/RelationalMethodCallTranslatorProvider.cs b/src/EFCore.Relational/Query/RelationalMethodCallTranslatorProvider.cs index 4e39280e734..20f3cddb026 100644 --- a/src/EFCore.Relational/Query/RelationalMethodCallTranslatorProvider.cs +++ b/src/EFCore.Relational/Query/RelationalMethodCallTranslatorProvider.cs @@ -8,6 +8,7 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query { @@ -19,6 +20,8 @@ public class RelationalMethodCallTranslatorProvider : IMethodCallTranslatorProvi public RelationalMethodCallTranslatorProvider([NotNull] RelationalMethodCallTranslatorProviderDependencies dependencies) { + Check.NotNull(dependencies, nameof(dependencies)); + _plugins.AddRange(dependencies.Plugins.SelectMany(p => p.Translators)); var sqlExpressionFactory = dependencies.SqlExpressionFactory; @@ -40,6 +43,10 @@ public RelationalMethodCallTranslatorProvider([NotNull] RelationalMethodCallTran public virtual SqlExpression Translate( IModel model, SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { + Check.NotNull(model, nameof(model)); + Check.NotNull(method, nameof(method)); + Check.NotNull(arguments, nameof(arguments)); + var dbFunction = model.FindDbFunction(method); if (dbFunction != null) { @@ -57,7 +64,11 @@ public virtual SqlExpression Translate( .FirstOrDefault(t => t != null); } - protected virtual void AddTranslators(IEnumerable translators) - => _translators.InsertRange(0, translators); + protected virtual void AddTranslators([NotNull] IEnumerable translators) + { + Check.NotNull(translators, nameof(translators)); + + _translators.InsertRange(0, translators); + } } } diff --git a/src/EFCore.Relational/Query/RelationalParameterBasedQueryTranslationPostprocessor.cs b/src/EFCore.Relational/Query/RelationalParameterBasedQueryTranslationPostprocessor.cs index 95c7b171976..5610cf29666 100644 --- a/src/EFCore.Relational/Query/RelationalParameterBasedQueryTranslationPostprocessor.cs +++ b/src/EFCore.Relational/Query/RelationalParameterBasedQueryTranslationPostprocessor.cs @@ -6,11 +6,13 @@ using System.Collections.Generic; using System.Data.Common; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query { @@ -23,9 +25,11 @@ namespace Microsoft.EntityFrameworkCore.Query public class RelationalParameterBasedQueryTranslationPostprocessor { public RelationalParameterBasedQueryTranslationPostprocessor( - RelationalParameterBasedQueryTranslationPostprocessorDependencies dependencies, + [NotNull] RelationalParameterBasedQueryTranslationPostprocessorDependencies dependencies, bool useRelationalNulls) { + Check.NotNull(dependencies, nameof(dependencies)); + Dependencies = dependencies; UseRelationalNulls = useRelationalNulls; } @@ -35,8 +39,12 @@ public RelationalParameterBasedQueryTranslationPostprocessor( protected virtual bool UseRelationalNulls { get; } public virtual (SelectExpression selectExpression, bool canCache) Optimize( - SelectExpression selectExpression, IReadOnlyDictionary parametersValues) + [NotNull] SelectExpression selectExpression, + [NotNull] IReadOnlyDictionary parametersValues) { + Check.NotNull(selectExpression, nameof(selectExpression)); + Check.NotNull(parametersValues, nameof(parametersValues)); + var canCache = true; var inExpressionOptimized = new InExpressionValuesExpandingExpressionVisitor( diff --git a/src/EFCore.Relational/Query/RelationalParameterBasedQueryTranslationPostprocessorDependencies.cs b/src/EFCore.Relational/Query/RelationalParameterBasedQueryTranslationPostprocessorDependencies.cs index 4e0df3c03de..8fcf327171b 100644 --- a/src/EFCore.Relational/Query/RelationalParameterBasedQueryTranslationPostprocessorDependencies.cs +++ b/src/EFCore.Relational/Query/RelationalParameterBasedQueryTranslationPostprocessorDependencies.cs @@ -79,7 +79,7 @@ public RelationalParameterBasedQueryTranslationPostprocessorDependencies( /// /// A replacement for the current dependency of this type. /// A new parameter object with the given service replaced. - public RelationalParameterBasedQueryTranslationPostprocessorDependencies With(ISqlExpressionFactory sqlExpressionFactory) + public RelationalParameterBasedQueryTranslationPostprocessorDependencies With([NotNull] ISqlExpressionFactory sqlExpressionFactory) => new RelationalParameterBasedQueryTranslationPostprocessorDependencies(sqlExpressionFactory, ParameterNameGeneratorFactory); /// @@ -87,7 +87,7 @@ public RelationalParameterBasedQueryTranslationPostprocessorDependencies With(IS /// /// A replacement for the current dependency of this type. /// A new parameter object with the given service replaced. - public RelationalParameterBasedQueryTranslationPostprocessorDependencies With(IParameterNameGeneratorFactory parameterNameGeneratorFactory) + public RelationalParameterBasedQueryTranslationPostprocessorDependencies With([NotNull] IParameterNameGeneratorFactory parameterNameGeneratorFactory) => new RelationalParameterBasedQueryTranslationPostprocessorDependencies(SqlExpressionFactory, parameterNameGeneratorFactory); } } diff --git a/src/EFCore.Relational/Query/RelationalParameterBasedQueryTranslationPostprocessorFactory.cs b/src/EFCore.Relational/Query/RelationalParameterBasedQueryTranslationPostprocessorFactory.cs index 8a5d295a7ce..f34deb54c46 100644 --- a/src/EFCore.Relational/Query/RelationalParameterBasedQueryTranslationPostprocessorFactory.cs +++ b/src/EFCore.Relational/Query/RelationalParameterBasedQueryTranslationPostprocessorFactory.cs @@ -1,14 +1,20 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Utilities; + namespace Microsoft.EntityFrameworkCore.Query { public class RelationalParameterBasedQueryTranslationPostprocessorFactory : IRelationalParameterBasedQueryTranslationPostprocessorFactory { private readonly RelationalParameterBasedQueryTranslationPostprocessorDependencies _dependencies; - public RelationalParameterBasedQueryTranslationPostprocessorFactory(RelationalParameterBasedQueryTranslationPostprocessorDependencies dependencies) + public RelationalParameterBasedQueryTranslationPostprocessorFactory( + [NotNull] RelationalParameterBasedQueryTranslationPostprocessorDependencies dependencies) { + Check.NotNull(dependencies, nameof(dependencies)); + _dependencies = dependencies; } diff --git a/src/EFCore.Relational/Query/RelationalQueryTranslationPostprocessor.cs b/src/EFCore.Relational/Query/RelationalQueryTranslationPostprocessor.cs index 1c51cf88d51..d25ecdf8a09 100644 --- a/src/EFCore.Relational/Query/RelationalQueryTranslationPostprocessor.cs +++ b/src/EFCore.Relational/Query/RelationalQueryTranslationPostprocessor.cs @@ -2,8 +2,10 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Query.Internal; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query { @@ -12,11 +14,14 @@ public class RelationalQueryTranslationPostprocessor : QueryTranslationPostproce private readonly SqlExpressionOptimizingExpressionVisitor _sqlExpressionOptimizingExpressionVisitor; public RelationalQueryTranslationPostprocessor( - QueryTranslationPostprocessorDependencies dependencies, - RelationalQueryTranslationPostprocessorDependencies relationalDependencies, - QueryCompilationContext queryCompilationContext) + [NotNull] QueryTranslationPostprocessorDependencies dependencies, + [NotNull] RelationalQueryTranslationPostprocessorDependencies relationalDependencies, + [NotNull] QueryCompilationContext queryCompilationContext) : base(dependencies) { + Check.NotNull(relationalDependencies, nameof(relationalDependencies)); + Check.NotNull(queryCompilationContext, nameof(queryCompilationContext)); + RelationalDependencies = relationalDependencies; UseRelationalNulls = RelationalOptionsExtension.Extract(queryCompilationContext.ContextOptions).UseRelationalNulls; SqlExpressionFactory = relationalDependencies.SqlExpressionFactory; @@ -48,6 +53,11 @@ public override Expression Process(Expression query) return query; } - protected virtual Expression OptimizeSqlExpression(Expression query) => _sqlExpressionOptimizingExpressionVisitor.Visit(query); + protected virtual Expression OptimizeSqlExpression([NotNull] Expression query) + { + Check.NotNull(query, nameof(query)); + + return _sqlExpressionOptimizingExpressionVisitor.Visit(query); + } } } diff --git a/src/EFCore.Relational/Query/RelationalQueryTranslationPreprocessor.cs b/src/EFCore.Relational/Query/RelationalQueryTranslationPreprocessor.cs index fee317bd46e..721660089da 100644 --- a/src/EFCore.Relational/Query/RelationalQueryTranslationPreprocessor.cs +++ b/src/EFCore.Relational/Query/RelationalQueryTranslationPreprocessor.cs @@ -1,16 +1,21 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Utilities; + namespace Microsoft.EntityFrameworkCore.Query { public class RelationalQueryTranslationPreprocessor : QueryTranslationPreprocessor { public RelationalQueryTranslationPreprocessor( - QueryTranslationPreprocessorDependencies dependencies, - RelationalQueryTranslationPreprocessorDependencies relationalDependencies, - QueryCompilationContext queryCompilationContext) + [NotNull] QueryTranslationPreprocessorDependencies dependencies, + [NotNull] RelationalQueryTranslationPreprocessorDependencies relationalDependencies, + [NotNull] QueryCompilationContext queryCompilationContext) : base(dependencies, queryCompilationContext) { + Check.NotNull(relationalDependencies, nameof(relationalDependencies)); + RelationalDependencies = relationalDependencies; } diff --git a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs index 18c9f7f531f..c7f83941991 100644 --- a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.Linq; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; @@ -14,6 +15,7 @@ using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query { @@ -27,11 +29,15 @@ public class RelationalQueryableMethodTranslatingExpressionVisitor : QueryableMe private readonly bool _subquery; public RelationalQueryableMethodTranslatingExpressionVisitor( - QueryableMethodTranslatingExpressionVisitorDependencies dependencies, - RelationalQueryableMethodTranslatingExpressionVisitorDependencies relationalDependencies, - IModel model) + [NotNull] QueryableMethodTranslatingExpressionVisitorDependencies dependencies, + [NotNull] RelationalQueryableMethodTranslatingExpressionVisitorDependencies relationalDependencies, + [NotNull] IModel model) : base(dependencies, subquery: false) { + Check.NotNull(dependencies, nameof(dependencies)); + Check.NotNull(relationalDependencies, nameof(relationalDependencies)); + Check.NotNull(model, nameof(model)); + RelationalDependencies = relationalDependencies; var sqlExpressionFactory = relationalDependencies.SqlExpressionFactory; @@ -46,7 +52,7 @@ public RelationalQueryableMethodTranslatingExpressionVisitor( protected virtual RelationalQueryableMethodTranslatingExpressionVisitorDependencies RelationalDependencies { get; } protected RelationalQueryableMethodTranslatingExpressionVisitor( - RelationalQueryableMethodTranslatingExpressionVisitor parentVisitor) + [NotNull] RelationalQueryableMethodTranslatingExpressionVisitor parentVisitor) : base(parentVisitor.Dependencies, subquery: true) { RelationalDependencies = parentVisitor.RelationalDependencies; @@ -60,6 +66,8 @@ protected RelationalQueryableMethodTranslatingExpressionVisitor( protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { + Check.NotNull(methodCallExpression, nameof(methodCallExpression)); + if (methodCallExpression.Method.DeclaringType == typeof(RelationalQueryableExtensions) && methodCallExpression.Method.Name == nameof(RelationalQueryableExtensions.FromSqlOnQueryable)) { @@ -76,6 +84,8 @@ protected override QueryableMethodTranslatingExpressionVisitor CreateSubqueryVis protected override ShapedQueryExpression CreateShapedQueryExpression(Type elementType) { + Check.NotNull(elementType, nameof(elementType)); + var entityType = _model.FindEntityType(elementType); var queryExpression = _sqlExpressionFactory.Select(entityType); @@ -103,6 +113,9 @@ private static ShapedQueryExpression CreateShapedQueryExpression(IEntityType ent protected override ShapedQueryExpression TranslateAll(ShapedQueryExpression source, LambdaExpression predicate) { + Check.NotNull(source, nameof(source)); + Check.NotNull(predicate, nameof(predicate)); + var translation = TranslateLambdaExpression(source, predicate); if (translation == null) { @@ -153,6 +166,9 @@ protected override ShapedQueryExpression TranslateAny(ShapedQueryExpression sour protected override ShapedQueryExpression TranslateAverage(ShapedQueryExpression source, LambdaExpression selector, Type resultType) { + Check.NotNull(source, nameof(source)); + Check.NotNull(resultType, nameof(resultType)); + var selectExpression = (SelectExpression)source.QueryExpression; selectExpression.PrepareForAggregate(); @@ -169,6 +185,9 @@ protected override ShapedQueryExpression TranslateAverage(ShapedQueryExpression protected override ShapedQueryExpression TranslateCast(ShapedQueryExpression source, Type resultType) { + Check.NotNull(source, nameof(source)); + Check.NotNull(resultType, nameof(resultType)); + if (source.ShaperExpression.Type != resultType) { source.ShaperExpression = Expression.Convert(source.ShaperExpression, resultType); @@ -179,6 +198,9 @@ protected override ShapedQueryExpression TranslateCast(ShapedQueryExpression sou protected override ShapedQueryExpression TranslateConcat(ShapedQueryExpression source1, ShapedQueryExpression source2) { + Check.NotNull(source1, nameof(source1)); + Check.NotNull(source2, nameof(source2)); + ((SelectExpression)source1.QueryExpression).ApplyUnion((SelectExpression)source2.QueryExpression, distinct: false); return source1; @@ -186,6 +208,9 @@ protected override ShapedQueryExpression TranslateConcat(ShapedQueryExpression s protected override ShapedQueryExpression TranslateContains(ShapedQueryExpression source, Expression item) { + Check.NotNull(source, nameof(source)); + Check.NotNull(item, nameof(item)); + var selectExpression = (SelectExpression)source.QueryExpression; var translation = TranslateExpression(item); if (translation == null) @@ -209,6 +234,8 @@ protected override ShapedQueryExpression TranslateContains(ShapedQueryExpression protected override ShapedQueryExpression TranslateCount(ShapedQueryExpression source, LambdaExpression predicate) { + Check.NotNull(source, nameof(source)); + var selectExpression = (SelectExpression)source.QueryExpression; selectExpression.PrepareForAggregate(); @@ -238,6 +265,8 @@ protected override ShapedQueryExpression TranslateCount(ShapedQueryExpression so protected override ShapedQueryExpression TranslateDefaultIfEmpty(ShapedQueryExpression source, Expression defaultValue) { + Check.NotNull(source, nameof(source)); + if (defaultValue == null) { ((SelectExpression)source.QueryExpression).ApplyDefaultIfEmpty(_sqlExpressionFactory); @@ -251,6 +280,8 @@ protected override ShapedQueryExpression TranslateDefaultIfEmpty(ShapedQueryExpr protected override ShapedQueryExpression TranslateDistinct(ShapedQueryExpression source) { + Check.NotNull(source, nameof(source)); + ((SelectExpression)source.QueryExpression).ApplyDistinct(); return source; @@ -258,10 +289,18 @@ protected override ShapedQueryExpression TranslateDistinct(ShapedQueryExpression protected override ShapedQueryExpression TranslateElementAtOrDefault( ShapedQueryExpression source, Expression index, bool returnDefault) - => null; + { + Check.NotNull(source, nameof(source)); + Check.NotNull(index, nameof(index)); + + return null; + } protected override ShapedQueryExpression TranslateExcept(ShapedQueryExpression source1, ShapedQueryExpression source2) { + Check.NotNull(source1, nameof(source1)); + Check.NotNull(source2, nameof(source2)); + ((SelectExpression)source1.QueryExpression).ApplyExcept((SelectExpression)source2.QueryExpression, distinct: true); return source1; } @@ -269,6 +308,9 @@ protected override ShapedQueryExpression TranslateExcept(ShapedQueryExpression s protected override ShapedQueryExpression TranslateFirstOrDefault( ShapedQueryExpression source, LambdaExpression predicate, Type returnType, bool returnDefault) { + Check.NotNull(source, nameof(source)); + Check.NotNull(returnType, nameof(returnType)); + if (predicate != null) { source = TranslateWhere(source, predicate); @@ -295,6 +337,9 @@ protected override ShapedQueryExpression TranslateGroupBy( LambdaExpression elementSelector, LambdaExpression resultSelector) { + Check.NotNull(source, nameof(source)); + Check.NotNull(keySelector, nameof(keySelector)); + var selectExpression = (SelectExpression)source.QueryExpression; selectExpression.PrepareForAggregate(); @@ -391,55 +436,28 @@ private Expression TranslateGroupingKey(Expression expression) } protected override ShapedQueryExpression TranslateGroupJoin( - ShapedQueryExpression outer, ShapedQueryExpression inner, LambdaExpression outerKeySelector, LambdaExpression innerKeySelector, + ShapedQueryExpression outer, + ShapedQueryExpression inner, + LambdaExpression outerKeySelector, + LambdaExpression innerKeySelector, LambdaExpression resultSelector) { - //var outerSelectExpression = (SelectExpression)outer.QueryExpression; - //if (outerSelectExpression.Limit != null - // || outerSelectExpression.Offset != null - // || outerSelectExpression.IsDistinct) - //{ - // outerSelectExpression.PushdownIntoSubQuery(); - //} - - //var innerSelectExpression = (SelectExpression)inner.QueryExpression; - //if (innerSelectExpression.Orderings.Any() - // || innerSelectExpression.Limit != null - // || innerSelectExpression.Offset != null - // || innerSelectExpression.IsDistinct - // || innerSelectExpression.Predicate != null - // || innerSelectExpression.Tables.Count > 1) - //{ - // innerSelectExpression.PushdownIntoSubQuery(); - //} - - //var joinPredicate = CreateJoinPredicate(outer, outerKeySelector, inner, innerKeySelector); - //if (joinPredicate != null) - //{ - // outer = TranslateThenBy(outer, outerKeySelector, true); - - // var innerTransparentIdentifierType = CreateTransparentIdentifierType( - // resultSelector.Parameters[0].Type, - // resultSelector.Parameters[1].Type.TryGetSequenceType()); - - // outerSelectExpression.AddLeftJoin( - // innerSelectExpression, joinPredicate, innerTransparentIdentifierType); - - // return TranslateResultSelectorForGroupJoin( - // outer, - // inner.ShaperExpression, - // outerKeySelector, - // innerKeySelector, - // resultSelector, - // innerTransparentIdentifierType); - //} + Check.NotNull(outer, nameof(outer)); + Check.NotNull(inner, nameof(inner)); + Check.NotNull(outerKeySelector, nameof(outerKeySelector)); + Check.NotNull(innerKeySelector, nameof(innerKeySelector)); + Check.NotNull(resultSelector, nameof(resultSelector)); return null; } protected override ShapedQueryExpression TranslateIntersect(ShapedQueryExpression source1, ShapedQueryExpression source2) { + Check.NotNull(source1, nameof(source1)); + Check.NotNull(source2, nameof(source2)); + ((SelectExpression)source1.QueryExpression).ApplyIntersect((SelectExpression)source2.QueryExpression, distinct: true); + return source1; } @@ -450,6 +468,10 @@ protected override ShapedQueryExpression TranslateJoin( LambdaExpression innerKeySelector, LambdaExpression resultSelector) { + Check.NotNull(outer, nameof(outer)); + Check.NotNull(inner, nameof(inner)); + Check.NotNull(resultSelector, nameof(resultSelector)); + var joinPredicate = CreateJoinPredicate(outer, outerKeySelector, inner, innerKeySelector); if (joinPredicate != null) { @@ -477,6 +499,10 @@ protected override ShapedQueryExpression TranslateLeftJoin( LambdaExpression innerKeySelector, LambdaExpression resultSelector) { + Check.NotNull(outer, nameof(outer)); + Check.NotNull(inner, nameof(inner)); + Check.NotNull(resultSelector, nameof(resultSelector)); + var joinPredicate = CreateJoinPredicate(outer, outerKeySelector, inner, innerKeySelector); if (joinPredicate != null) { @@ -539,6 +565,9 @@ private SqlExpression CreateJoinPredicate(Expression outerKey, Expression innerK protected override ShapedQueryExpression TranslateLastOrDefault( ShapedQueryExpression source, LambdaExpression predicate, Type returnType, bool returnDefault) { + Check.NotNull(source, nameof(source)); + Check.NotNull(returnType, nameof(returnType)); + var selectExpression = (SelectExpression)source.QueryExpression; if (selectExpression.Orderings.Count == 0) { @@ -567,6 +596,8 @@ protected override ShapedQueryExpression TranslateLastOrDefault( protected override ShapedQueryExpression TranslateLongCount(ShapedQueryExpression source, LambdaExpression predicate) { + Check.NotNull(source, nameof(source)); + var selectExpression = (SelectExpression)source.QueryExpression; selectExpression.PrepareForAggregate(); @@ -596,6 +627,8 @@ protected override ShapedQueryExpression TranslateLongCount(ShapedQueryExpressio protected override ShapedQueryExpression TranslateMax(ShapedQueryExpression source, LambdaExpression selector, Type resultType) { + Check.NotNull(source, nameof(source)); + var selectExpression = (SelectExpression)source.QueryExpression; selectExpression.PrepareForAggregate(); @@ -611,6 +644,8 @@ protected override ShapedQueryExpression TranslateMax(ShapedQueryExpression sour protected override ShapedQueryExpression TranslateMin(ShapedQueryExpression source, LambdaExpression selector, Type resultType) { + Check.NotNull(source, nameof(source)); + var selectExpression = (SelectExpression)source.QueryExpression; selectExpression.PrepareForAggregate(); @@ -626,6 +661,9 @@ protected override ShapedQueryExpression TranslateMin(ShapedQueryExpression sour protected override ShapedQueryExpression TranslateOfType(ShapedQueryExpression source, Type resultType) { + Check.NotNull(source, nameof(source)); + Check.NotNull(resultType, nameof(resultType)); + if (source.ShaperExpression is EntityShaperExpression entityShaperExpression) { var entityType = entityShaperExpression.EntityType; @@ -691,6 +729,9 @@ protected override ShapedQueryExpression TranslateOfType(ShapedQueryExpression s protected override ShapedQueryExpression TranslateOrderBy( ShapedQueryExpression source, LambdaExpression keySelector, bool ascending) { + Check.NotNull(source, nameof(source)); + Check.NotNull(keySelector, nameof(keySelector)); + var translation = TranslateLambdaExpression(source, keySelector); if (translation == null) { @@ -703,10 +744,17 @@ protected override ShapedQueryExpression TranslateOrderBy( } protected override ShapedQueryExpression TranslateReverse(ShapedQueryExpression source) - => null; + { + Check.NotNull(source, nameof(source)); + + return null; + } protected override ShapedQueryExpression TranslateSelect(ShapedQueryExpression source, LambdaExpression selector) { + Check.NotNull(source, nameof(source)); + Check.NotNull(selector, nameof(selector)); + if (selector.Body == selector.Parameters[0]) { return source; @@ -728,6 +776,10 @@ protected override ShapedQueryExpression TranslateSelect(ShapedQueryExpression s protected override ShapedQueryExpression TranslateSelectMany( ShapedQueryExpression source, LambdaExpression collectionSelector, LambdaExpression resultSelector) { + Check.NotNull(source, nameof(source)); + Check.NotNull(collectionSelector, nameof(collectionSelector)); + Check.NotNull(resultSelector, nameof(resultSelector)); + var (newCollectionSelector, correlated, defaultIfEmpty) = new CorrelationFindingExpressionVisitor().IsCorrelated(collectionSelector); if (correlated) @@ -811,6 +863,8 @@ private sealed class CorrelationFindingExpressionVisitor : ExpressionVisitor protected override Expression VisitParameter(ParameterExpression parameterExpression) { + Check.NotNull(parameterExpression, nameof(parameterExpression)); + if (parameterExpression == _outerParameter) { _correlated = true; @@ -821,6 +875,8 @@ protected override Expression VisitParameter(ParameterExpression parameterExpres protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { + Check.NotNull(methodCallExpression, nameof(methodCallExpression)); + if (methodCallExpression.Method.IsGenericMethod && methodCallExpression.Method.GetGenericMethodDefinition() == QueryableMethods.DefaultIfEmptyWithoutArgument) { @@ -834,6 +890,9 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp protected override ShapedQueryExpression TranslateSelectMany(ShapedQueryExpression source, LambdaExpression selector) { + Check.NotNull(source, nameof(source)); + Check.NotNull(selector, nameof(selector)); + var innerParameter = Expression.Parameter(selector.ReturnType.TryGetSequenceType(), "i"); var resultSelector = Expression.Lambda( innerParameter, Expression.Parameter(source.Type.TryGetSequenceType()), innerParameter); @@ -844,6 +903,9 @@ protected override ShapedQueryExpression TranslateSelectMany(ShapedQueryExpressi protected override ShapedQueryExpression TranslateSingleOrDefault( ShapedQueryExpression source, LambdaExpression predicate, Type returnType, bool returnDefault) { + Check.NotNull(source, nameof(source)); + Check.NotNull(returnType, nameof(returnType)); + if (predicate != null) { source = TranslateWhere(source, predicate); @@ -866,6 +928,9 @@ protected override ShapedQueryExpression TranslateSingleOrDefault( protected override ShapedQueryExpression TranslateSkip(ShapedQueryExpression source, Expression count) { + Check.NotNull(source, nameof(source)); + Check.NotNull(count, nameof(count)); + var selectExpression = (SelectExpression)source.QueryExpression; var translation = TranslateExpression(count); if (translation == null) @@ -879,10 +944,18 @@ protected override ShapedQueryExpression TranslateSkip(ShapedQueryExpression sou } protected override ShapedQueryExpression TranslateSkipWhile(ShapedQueryExpression source, LambdaExpression predicate) - => null; + { + Check.NotNull(source, nameof(source)); + Check.NotNull(predicate, nameof(predicate)); + + return null; + } protected override ShapedQueryExpression TranslateSum(ShapedQueryExpression source, LambdaExpression selector, Type resultType) { + Check.NotNull(source, nameof(source)); + Check.NotNull(resultType, nameof(resultType)); + var selectExpression = (SelectExpression)source.QueryExpression; selectExpression.PrepareForAggregate(); var newSelector = selector == null @@ -898,6 +971,9 @@ protected override ShapedQueryExpression TranslateSum(ShapedQueryExpression sour protected override ShapedQueryExpression TranslateTake(ShapedQueryExpression source, Expression count) { + Check.NotNull(source, nameof(source)); + Check.NotNull(count, nameof(count)); + var selectExpression = (SelectExpression)source.QueryExpression; var translation = TranslateExpression(count); if (translation == null) @@ -911,10 +987,18 @@ protected override ShapedQueryExpression TranslateTake(ShapedQueryExpression sou } protected override ShapedQueryExpression TranslateTakeWhile(ShapedQueryExpression source, LambdaExpression predicate) - => null; + { + Check.NotNull(source, nameof(source)); + Check.NotNull(predicate, nameof(predicate)); + + return null; + } protected override ShapedQueryExpression TranslateThenBy(ShapedQueryExpression source, LambdaExpression keySelector, bool ascending) { + Check.NotNull(source, nameof(source)); + Check.NotNull(keySelector, nameof(keySelector)); + var translation = TranslateLambdaExpression(source, keySelector); if (translation == null) { @@ -928,12 +1012,18 @@ protected override ShapedQueryExpression TranslateThenBy(ShapedQueryExpression s protected override ShapedQueryExpression TranslateUnion(ShapedQueryExpression source1, ShapedQueryExpression source2) { + Check.NotNull(source1, nameof(source1)); + Check.NotNull(source2, nameof(source2)); + ((SelectExpression)source1.QueryExpression).ApplyUnion((SelectExpression)source2.QueryExpression, distinct: true); return source1; } protected override ShapedQueryExpression TranslateWhere(ShapedQueryExpression source, LambdaExpression predicate) { + Check.NotNull(source, nameof(source)); + Check.NotNull(predicate, nameof(predicate)); + var translation = TranslateLambdaExpression(source, predicate); if (translation == null) { @@ -985,6 +1075,8 @@ public Expression Expand(SelectExpression selectExpression, Expression lambdaBod protected override Expression VisitMember(MemberExpression memberExpression) { + Check.NotNull(memberExpression, nameof(memberExpression)); + var innerExpression = Visit(memberExpression.Expression); return TryExpand(innerExpression, MemberIdentity.Create(memberExpression.Member)) @@ -993,6 +1085,8 @@ protected override Expression VisitMember(MemberExpression memberExpression) protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { + Check.NotNull(methodCallExpression, nameof(methodCallExpression)); + if (methodCallExpression.TryGetEFPropertyArguments(out var source, out var navigationName)) { source = Visit(source); @@ -1005,9 +1099,13 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp } protected override Expression VisitExtension(Expression extensionExpression) - => extensionExpression is EntityShaperExpression + { + Check.NotNull(extensionExpression, nameof(extensionExpression)); + + return extensionExpression is EntityShaperExpression ? extensionExpression : base.VisitExtension(extensionExpression); + } private Expression TryExpand(Expression source, MemberIdentity member) { diff --git a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.CustomShaperCompilingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.CustomShaperCompilingExpressionVisitor.cs index d7d2fe25234..4a30d9c7223 100644 --- a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.CustomShaperCompilingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.CustomShaperCompilingExpressionVisitor.cs @@ -12,6 +12,7 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query.Internal; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query { @@ -377,6 +378,8 @@ private static void SetIsLoadedNoTracking(object entity, INavigation navigation) protected override Expression VisitExtension(Expression extensionExpression) { + Check.NotNull(extensionExpression, nameof(extensionExpression)); + if (extensionExpression is IncludeExpression includeExpression) { Debug.Assert( diff --git a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.RelationalProjectionBindingRemovingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.RelationalProjectionBindingRemovingExpressionVisitor.cs index b4fc489cf94..f8735eba83f 100644 --- a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.RelationalProjectionBindingRemovingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.RelationalProjectionBindingRemovingExpressionVisitor.cs @@ -12,6 +12,7 @@ using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query { @@ -55,6 +56,8 @@ public Expression Visit(Expression node, out IReadOnlyList project protected override Expression VisitBinary(BinaryExpression binaryExpression) { + Check.NotNull(binaryExpression, nameof(binaryExpression)); + if (binaryExpression.NodeType == ExpressionType.Assign && binaryExpression.Left is ParameterExpression parameterExpression && parameterExpression.Type == typeof(MaterializationContext)) @@ -86,6 +89,8 @@ protected override Expression VisitBinary(BinaryExpression binaryExpression) protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { + Check.NotNull(methodCallExpression, nameof(methodCallExpression)); + if (methodCallExpression.Method.IsGenericMethod && methodCallExpression.Method.GetGenericMethodDefinition() == EntityMaterializerSource.TryReadValueMethod) { @@ -111,6 +116,8 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp protected override Expression VisitExtension(Expression extensionExpression) { + Check.NotNull(extensionExpression, nameof(extensionExpression)); + if (extensionExpression is ProjectionBindingExpression projectionBindingExpression) { var projectionIndex = (int)GetProjectionIndex(projectionBindingExpression); diff --git a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperExpressionProcessingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperExpressionProcessingExpressionVisitor.cs index 777c303a81b..d6234eb7ea5 100644 --- a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperExpressionProcessingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperExpressionProcessingExpressionVisitor.cs @@ -6,6 +6,7 @@ using System.Reflection; using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query { @@ -161,6 +162,8 @@ private LambdaExpression ConvertToLambda(Expression result) protected override Expression VisitExtension(Expression extensionExpression) { + Check.NotNull(extensionExpression, nameof(extensionExpression)); + switch (extensionExpression) { case EntityShaperExpression entityShaperExpression: diff --git a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.cs index 4275e9db773..e695596cf26 100644 --- a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.cs @@ -6,11 +6,13 @@ using System.Data.Common; using System.Linq; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query { @@ -22,11 +24,13 @@ public partial class RelationalShapedQueryCompilingExpressionVisitor : ShapedQue private readonly bool _useRelationalNulls; public RelationalShapedQueryCompilingExpressionVisitor( - ShapedQueryCompilingExpressionVisitorDependencies dependencies, - RelationalShapedQueryCompilingExpressionVisitorDependencies relationalDependencies, - QueryCompilationContext queryCompilationContext) + [NotNull] ShapedQueryCompilingExpressionVisitorDependencies dependencies, + [NotNull] RelationalShapedQueryCompilingExpressionVisitorDependencies relationalDependencies, + [NotNull] QueryCompilationContext queryCompilationContext) : base(dependencies, queryCompilationContext) { + Check.NotNull(relationalDependencies, nameof(relationalDependencies)); + RelationalDependencies = relationalDependencies; _contextType = queryCompilationContext.ContextType; @@ -39,6 +43,8 @@ public RelationalShapedQueryCompilingExpressionVisitor( protected override Expression VisitShapedQueryExpression(ShapedQueryExpression shapedQueryExpression) { + Check.NotNull(shapedQueryExpression, nameof(shapedQueryExpression)); + var selectExpression = (SelectExpression)shapedQueryExpression.QueryExpression; selectExpression.ApplyTags(_tags); diff --git a/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs index 90022944a77..100389f3e9c 100644 --- a/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs @@ -6,11 +6,13 @@ using System.Linq; using System.Linq.Expressions; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query { @@ -22,10 +24,14 @@ public class RelationalSqlTranslatingExpressionVisitor : ExpressionVisitor private readonly SqlTypeMappingVerifyingExpressionVisitor _sqlTypeMappingVerifyingExpressionVisitor; public RelationalSqlTranslatingExpressionVisitor( - RelationalSqlTranslatingExpressionVisitorDependencies dependencies, - IModel model, - QueryableMethodTranslatingExpressionVisitor queryableMethodTranslatingExpressionVisitor) + [NotNull] RelationalSqlTranslatingExpressionVisitorDependencies dependencies, + [NotNull] IModel model, + [NotNull] QueryableMethodTranslatingExpressionVisitor queryableMethodTranslatingExpressionVisitor) { + Check.NotNull(dependencies, nameof(dependencies)); + Check.NotNull(model, nameof(model)); + Check.NotNull(queryableMethodTranslatingExpressionVisitor, nameof(queryableMethodTranslatingExpressionVisitor)); + Dependencies = dependencies; _model = model; @@ -36,8 +42,10 @@ public RelationalSqlTranslatingExpressionVisitor( protected virtual RelationalSqlTranslatingExpressionVisitorDependencies Dependencies { get; } - public virtual SqlExpression Translate(Expression expression) + public virtual SqlExpression Translate([NotNull] Expression expression) { + Check.NotNull(expression, nameof(expression)); + var result = Visit(expression); if (result is SqlExpression translation) @@ -67,8 +75,10 @@ public virtual SqlExpression Translate(Expression expression) return null; } - public virtual SqlExpression TranslateAverage(Expression expression) + public virtual SqlExpression TranslateAverage([NotNull] Expression expression) { + Check.NotNull(expression, nameof(expression)); + if (!(expression is SqlExpression sqlExpression)) { sqlExpression = Translate(expression); @@ -97,7 +107,7 @@ public virtual SqlExpression TranslateAverage(Expression expression) "AVG", new[] { sqlExpression }, sqlExpression.Type, sqlExpression.TypeMapping); } - public virtual SqlExpression TranslateCount(Expression expression = null) + public virtual SqlExpression TranslateCount([CanBeNull] Expression expression = null) { if (expression != null) { @@ -109,7 +119,7 @@ public virtual SqlExpression TranslateCount(Expression expression = null) _sqlExpressionFactory.Function("COUNT", new[] { _sqlExpressionFactory.Fragment("*") }, typeof(int))); } - public virtual SqlExpression TranslateLongCount(Expression expression = null) + public virtual SqlExpression TranslateLongCount([CanBeNull] Expression expression = null) { if (expression != null) { @@ -121,8 +131,10 @@ public virtual SqlExpression TranslateLongCount(Expression expression = null) _sqlExpressionFactory.Function("COUNT", new[] { _sqlExpressionFactory.Fragment("*") }, typeof(long))); } - public virtual SqlExpression TranslateMax(Expression expression) + public virtual SqlExpression TranslateMax([NotNull] Expression expression) { + Check.NotNull(expression, nameof(expression)); + if (!(expression is SqlExpression sqlExpression)) { sqlExpression = Translate(expression); @@ -133,8 +145,10 @@ public virtual SqlExpression TranslateMax(Expression expression) : null; } - public virtual SqlExpression TranslateMin(Expression expression) + public virtual SqlExpression TranslateMin([NotNull] Expression expression) { + Check.NotNull(expression, nameof(expression)); + if (!(expression is SqlExpression sqlExpression)) { sqlExpression = Translate(expression); @@ -145,8 +159,10 @@ public virtual SqlExpression TranslateMin(Expression expression) : null; } - public virtual SqlExpression TranslateSum(Expression expression) + public virtual SqlExpression TranslateSum([NotNull] Expression expression) { + Check.NotNull(expression, nameof(expression)); + if (!(expression is SqlExpression sqlExpression)) { sqlExpression = Translate(expression); @@ -172,6 +188,8 @@ private sealed class SqlTypeMappingVerifyingExpressionVisitor : ExpressionVisito { protected override Expression VisitExtension(Expression node) { + Check.NotNull(node, nameof(node)); + if (node is SqlExpression sqlExpression && !(node is SqlFragmentExpression)) { @@ -186,11 +204,15 @@ protected override Expression VisitExtension(Expression node) } protected override Expression VisitMember(MemberExpression memberExpression) - => TryBindMember(memberExpression.Expression, MemberIdentity.Create(memberExpression.Member), out var result) + { + Check.NotNull(memberExpression, nameof(memberExpression)); + + return TryBindMember(memberExpression.Expression, MemberIdentity.Create(memberExpression.Member), out var result) ? result : TranslationFailed(memberExpression.Expression, base.Visit(memberExpression.Expression), out var sqlInnerExpression) ? null : Dependencies.MemberTranslatorProvider.Translate(sqlInnerExpression, memberExpression.Member, memberExpression.Type); + } private bool TryBindMember(Expression source, MemberIdentity member, out Expression expression) { @@ -227,6 +249,8 @@ private bool TryBindMember(Expression source, MemberIdentity member, out Express protected override Expression VisitTypeBinary(TypeBinaryExpression typeBinaryExpression) { + Check.NotNull(typeBinaryExpression, nameof(typeBinaryExpression)); + if (typeBinaryExpression.NodeType == ExpressionType.TypeIs && Visit(typeBinaryExpression.Expression) is EntityProjectionExpression entityProjectionExpression) { @@ -298,6 +322,8 @@ private Expression GetPredicate(MethodCallExpression methodCallExpression, Group protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { + Check.NotNull(methodCallExpression, nameof(methodCallExpression)); + // EF.Property case if (methodCallExpression.TryGetEFPropertyArguments(out var source, out var propertyName)) { @@ -471,6 +497,8 @@ static Expression RemoveObjectConvert(Expression expression) protected override Expression VisitBinary(BinaryExpression binaryExpression) { + Check.NotNull(binaryExpression, nameof(binaryExpression)); + if (binaryExpression.Left.Type == typeof(AnonymousObject) && binaryExpression.NodeType == ExpressionType.Equal) { @@ -523,26 +551,66 @@ private static bool CanEvaluate(Expression expression) } } - protected override Expression VisitNew(NewExpression node) => GetConstantOrNull(node); + protected override Expression VisitNew(NewExpression node) + { + Check.NotNull(node, nameof(node)); + + return GetConstantOrNull(node); + } + + protected override Expression VisitMemberInit(MemberInitExpression node) + { + Check.NotNull(node, nameof(node)); + + return GetConstantOrNull(node); + } + + protected override Expression VisitNewArray(NewArrayExpression node) + { + Check.NotNull(node, nameof(node)); + + return null; + } + + protected override Expression VisitListInit(ListInitExpression node) + { + Check.NotNull(node, nameof(node)); - protected override Expression VisitMemberInit(MemberInitExpression node) => GetConstantOrNull(node); + return null; + } - protected override Expression VisitNewArray(NewArrayExpression node) => null; + protected override Expression VisitInvocation(InvocationExpression node) + { + Check.NotNull(node, nameof(node)); - protected override Expression VisitListInit(ListInitExpression node) => null; + return null; + } - protected override Expression VisitInvocation(InvocationExpression node) => null; + protected override Expression VisitLambda(Expression node) + { + Check.NotNull(node, nameof(node)); - protected override Expression VisitLambda(Expression node) => null; + return null; + } protected override Expression VisitConstant(ConstantExpression constantExpression) - => new SqlConstantExpression(constantExpression, null); + { + Check.NotNull(constantExpression, nameof(constantExpression)); + + return new SqlConstantExpression(constantExpression, null); + } protected override Expression VisitParameter(ParameterExpression parameterExpression) - => new SqlParameterExpression(parameterExpression, null); + { + Check.NotNull(parameterExpression, nameof(parameterExpression)); + + return new SqlParameterExpression(parameterExpression, null); + } protected override Expression VisitExtension(Expression extensionExpression) { + Check.NotNull(extensionExpression, nameof(extensionExpression)); + switch (extensionExpression) { case EntityProjectionExpression _: @@ -565,6 +633,8 @@ protected override Expression VisitExtension(Expression extensionExpression) protected override Expression VisitConditional(ConditionalExpression conditionalExpression) { + Check.NotNull(conditionalExpression, nameof(conditionalExpression)); + var test = Visit(conditionalExpression.Test); var ifTrue = Visit(conditionalExpression.IfTrue); var ifFalse = Visit(conditionalExpression.IfFalse); @@ -578,6 +648,8 @@ protected override Expression VisitConditional(ConditionalExpression conditional protected override Expression VisitUnary(UnaryExpression unaryExpression) { + Check.NotNull(unaryExpression, nameof(unaryExpression)); + var operand = Visit(unaryExpression.Operand); if (TranslationFailed(unaryExpression.Operand, operand, out var sqlOperand)) diff --git a/src/EFCore.Relational/Query/SqlExpressionFactory.cs b/src/EFCore.Relational/Query/SqlExpressionFactory.cs index e72aadf325e..b31644d24f8 100644 --- a/src/EFCore.Relational/Query/SqlExpressionFactory.cs +++ b/src/EFCore.Relational/Query/SqlExpressionFactory.cs @@ -5,11 +5,13 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query { @@ -18,8 +20,10 @@ public class SqlExpressionFactory : ISqlExpressionFactory private readonly IRelationalTypeMappingSource _typeMappingSource; private readonly RelationalTypeMapping _boolTypeMapping; - public SqlExpressionFactory(SqlExpressionFactoryDependencies dependencies) + public SqlExpressionFactory([NotNull] SqlExpressionFactoryDependencies dependencies) { + Check.NotNull(dependencies, nameof(dependencies)); + _typeMappingSource = dependencies.TypeMappingSource; _boolTypeMapping = _typeMappingSource.FindMapping(typeof(bool)); } @@ -202,11 +206,19 @@ public virtual RelationalTypeMapping GetTypeMappingForValue(object value) => _typeMappingSource.GetMappingForValue(value); public virtual RelationalTypeMapping FindMapping(Type type) - => _typeMappingSource.FindMapping(type); + { + Check.NotNull(type, nameof(type)); + + return _typeMappingSource.FindMapping(type); + } public virtual SqlBinaryExpression MakeBinary( ExpressionType operatorType, SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping) { + Check.NotNull(operatorType, nameof(operatorType)); + Check.NotNull(left, nameof(left)); + Check.NotNull(right, nameof(right)); + var returnType = left.Type; switch (operatorType) { @@ -227,74 +239,185 @@ public virtual SqlBinaryExpression MakeBinary( } public virtual SqlBinaryExpression Equal(SqlExpression left, SqlExpression right) - => MakeBinary(ExpressionType.Equal, left, right, null); + { + Check.NotNull(left, nameof(left)); + Check.NotNull(right, nameof(right)); + + return MakeBinary(ExpressionType.Equal, left, right, null); + } public virtual SqlBinaryExpression NotEqual(SqlExpression left, SqlExpression right) - => MakeBinary(ExpressionType.NotEqual, left, right, null); + { + Check.NotNull(left, nameof(left)); + Check.NotNull(right, nameof(right)); + + return MakeBinary(ExpressionType.NotEqual, left, right, null); + } public virtual SqlBinaryExpression GreaterThan(SqlExpression left, SqlExpression right) - => MakeBinary(ExpressionType.GreaterThan, left, right, null); + { + Check.NotNull(left, nameof(left)); + Check.NotNull(right, nameof(right)); + + return MakeBinary(ExpressionType.GreaterThan, left, right, null); + } public virtual SqlBinaryExpression GreaterThanOrEqual(SqlExpression left, SqlExpression right) - => MakeBinary(ExpressionType.GreaterThanOrEqual, left, right, null); + { + Check.NotNull(left, nameof(left)); + Check.NotNull(right, nameof(right)); + + return MakeBinary(ExpressionType.GreaterThanOrEqual, left, right, null); + } public virtual SqlBinaryExpression LessThan(SqlExpression left, SqlExpression right) - => MakeBinary(ExpressionType.LessThan, left, right, null); + { + Check.NotNull(left, nameof(left)); + Check.NotNull(right, nameof(right)); + + return MakeBinary(ExpressionType.LessThan, left, right, null); + } public virtual SqlBinaryExpression LessThanOrEqual(SqlExpression left, SqlExpression right) - => MakeBinary(ExpressionType.LessThanOrEqual, left, right, null); + { + Check.NotNull(left, nameof(left)); + Check.NotNull(right, nameof(right)); + + return MakeBinary(ExpressionType.LessThanOrEqual, left, right, null); + } public virtual SqlBinaryExpression AndAlso(SqlExpression left, SqlExpression right) - => MakeBinary(ExpressionType.AndAlso, left, right, null); + { + Check.NotNull(left, nameof(left)); + Check.NotNull(right, nameof(right)); + + return MakeBinary(ExpressionType.AndAlso, left, right, null); + } public virtual SqlBinaryExpression OrElse(SqlExpression left, SqlExpression right) - => MakeBinary(ExpressionType.OrElse, left, right, null); + { + Check.NotNull(left, nameof(left)); + Check.NotNull(right, nameof(right)); + + return MakeBinary(ExpressionType.OrElse, left, right, null); + } public virtual SqlBinaryExpression Add(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null) - => MakeBinary(ExpressionType.Add, left, right, typeMapping); + { + Check.NotNull(left, nameof(left)); + Check.NotNull(right, nameof(right)); + + return MakeBinary(ExpressionType.Add, left, right, typeMapping); + } public virtual SqlBinaryExpression Subtract(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null) - => MakeBinary(ExpressionType.Subtract, left, right, typeMapping); + { + Check.NotNull(left, nameof(left)); + Check.NotNull(right, nameof(right)); + + return MakeBinary(ExpressionType.Subtract, left, right, typeMapping); + } public virtual SqlBinaryExpression Multiply(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null) - => MakeBinary(ExpressionType.Multiply, left, right, typeMapping); + { + Check.NotNull(left, nameof(left)); + Check.NotNull(right, nameof(right)); + + return MakeBinary(ExpressionType.Multiply, left, right, typeMapping); + } public virtual SqlBinaryExpression Divide(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null) - => MakeBinary(ExpressionType.Divide, left, right, typeMapping); + { + Check.NotNull(left, nameof(left)); + Check.NotNull(right, nameof(right)); + + return MakeBinary(ExpressionType.Divide, left, right, typeMapping); + } public virtual SqlBinaryExpression Modulo(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null) - => MakeBinary(ExpressionType.Modulo, left, right, typeMapping); + { + Check.NotNull(left, nameof(left)); + Check.NotNull(right, nameof(right)); + + return MakeBinary(ExpressionType.Modulo, left, right, typeMapping); + } public virtual SqlBinaryExpression And(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null) - => MakeBinary(ExpressionType.And, left, right, typeMapping); + { + Check.NotNull(left, nameof(left)); + Check.NotNull(right, nameof(right)); + + return MakeBinary(ExpressionType.And, left, right, typeMapping); + } public virtual SqlBinaryExpression Or(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null) - => MakeBinary(ExpressionType.Or, left, right, typeMapping); + { + Check.NotNull(left, nameof(left)); + Check.NotNull(right, nameof(right)); + + return MakeBinary(ExpressionType.Or, left, right, typeMapping); + } public virtual SqlBinaryExpression Coalesce(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null) - => MakeBinary(ExpressionType.Coalesce, left, right, typeMapping); + { + Check.NotNull(left, nameof(left)); + Check.NotNull(right, nameof(right)); + + return MakeBinary(ExpressionType.Coalesce, left, right, typeMapping); + } public virtual SqlUnaryExpression MakeUnary( ExpressionType operatorType, SqlExpression operand, Type type, RelationalTypeMapping typeMapping = null) - => (SqlUnaryExpression)ApplyTypeMapping(new SqlUnaryExpression(operatorType, operand, type, null), typeMapping); + { + Check.NotNull(operatorType, nameof(operand)); + Check.NotNull(operand, nameof(operand)); + Check.NotNull(type, nameof(type)); + + return (SqlUnaryExpression)ApplyTypeMapping(new SqlUnaryExpression(operatorType, operand, type, null), typeMapping); + } public virtual SqlUnaryExpression IsNull(SqlExpression operand) - => MakeUnary(ExpressionType.Equal, operand, typeof(bool)); + { + Check.NotNull(operand, nameof(operand)); + + return MakeUnary(ExpressionType.Equal, operand, typeof(bool)); + } public virtual SqlUnaryExpression IsNotNull(SqlExpression operand) - => MakeUnary(ExpressionType.NotEqual, operand, typeof(bool)); + { + Check.NotNull(operand, nameof(operand)); + + return MakeUnary(ExpressionType.NotEqual, operand, typeof(bool)); + } public virtual SqlUnaryExpression Convert(SqlExpression operand, Type type, RelationalTypeMapping typeMapping = null) - => MakeUnary(ExpressionType.Convert, operand, type, typeMapping); + { + Check.NotNull(operand, nameof(operand)); + Check.NotNull(type, nameof(type)); + + return MakeUnary(ExpressionType.Convert, operand, type, typeMapping); + } public virtual SqlUnaryExpression Not(SqlExpression operand) - => MakeUnary(ExpressionType.Not, operand, operand.Type, operand.TypeMapping); + { + Check.NotNull(operand, nameof(operand)); + + return MakeUnary(ExpressionType.Not, operand, operand.Type, operand.TypeMapping); + } public virtual SqlUnaryExpression Negate(SqlExpression operand) - => MakeUnary(ExpressionType.Negate, operand, operand.Type, operand.TypeMapping); + { + Check.NotNull(operand, nameof(operand)); + + return MakeUnary(ExpressionType.Negate, operand, operand.Type, operand.TypeMapping); + } - public virtual CaseExpression Case(SqlExpression operand, SqlExpression elseResult, params CaseWhenClause[] whenClauses) + public virtual CaseExpression Case( + [NotNull] SqlExpression operand, [CanBeNull] SqlExpression elseResult, [NotNull] params CaseWhenClause[] whenClauses) { + Check.NotNull(operand, nameof(operand)); + Check.NotNull(whenClauses, nameof(whenClauses)); + var operandTypeMapping = operand.TypeMapping ?? whenClauses.Select(wc => wc.Test.TypeMapping).FirstOrDefault(t => t != null) ?? _typeMappingSource.FindMapping(operand.Type); @@ -319,10 +442,17 @@ public virtual CaseExpression Case(SqlExpression operand, SqlExpression elseResu } public virtual CaseExpression Case(SqlExpression operand, params CaseWhenClause[] whenClauses) - => Case(operand, null, whenClauses); + { + Check.NotNull(operand, nameof(operand)); + Check.NotNull(whenClauses, nameof(whenClauses)); + + return Case(operand, null, whenClauses); + } public virtual CaseExpression Case(IReadOnlyList whenClauses, SqlExpression elseResult) { + Check.NotNull(whenClauses, nameof(whenClauses)); + var resultTypeMapping = elseResult?.TypeMapping ?? whenClauses.Select(wc => wc.Result.TypeMapping).FirstOrDefault(t => t != null); @@ -343,6 +473,10 @@ public virtual CaseExpression Case(IReadOnlyList whenClauses, Sq public virtual SqlFunctionExpression Function( string name, IEnumerable arguments, Type returnType, RelationalTypeMapping typeMapping = null) { + Check.NotEmpty(name, nameof(name)); + Check.NotNull(arguments, nameof(arguments)); + Check.NotNull(returnType, nameof(returnType)); + var typeMappedArguments = new List(); foreach (var argument in arguments) @@ -360,6 +494,10 @@ public virtual SqlFunctionExpression Function( public virtual SqlFunctionExpression Function( string schema, string name, IEnumerable arguments, Type returnType, RelationalTypeMapping typeMapping = null) { + Check.NotEmpty(name, nameof(name)); + Check.NotNull(arguments, nameof(arguments)); + Check.NotNull(returnType, nameof(returnType)); + var typeMappedArguments = new List(); foreach (var argument in arguments) { @@ -378,6 +516,10 @@ public virtual SqlFunctionExpression Function( SqlExpression instance, string name, IEnumerable arguments, Type returnType, RelationalTypeMapping typeMapping = null) { + Check.NotEmpty(name, nameof(name)); + Check.NotNull(arguments, nameof(arguments)); + Check.NotNull(returnType, nameof(returnType)); + instance = ApplyDefaultTypeMapping(instance); var typeMappedArguments = new List(); foreach (var argument in arguments) @@ -394,20 +536,43 @@ public virtual SqlFunctionExpression Function( } public virtual SqlFunctionExpression Function(string name, Type returnType, RelationalTypeMapping typeMapping = null) - => SqlFunctionExpression.CreateNiladic(name, returnType, typeMapping); + { + Check.NotEmpty(name, nameof(name)); + Check.NotNull(returnType, nameof(returnType)); + + return SqlFunctionExpression.CreateNiladic(name, returnType, typeMapping); + } public virtual SqlFunctionExpression Function(string schema, string name, Type returnType, RelationalTypeMapping typeMapping = null) - => SqlFunctionExpression.CreateNiladic(schema, name, returnType, typeMapping); + { + Check.NotEmpty(schema, nameof(schema)); + Check.NotEmpty(name, nameof(name)); + Check.NotNull(returnType, nameof(returnType)); + + return SqlFunctionExpression.CreateNiladic(schema, name, returnType, typeMapping); + } public virtual SqlFunctionExpression Function( SqlExpression instance, string name, Type returnType, RelationalTypeMapping typeMapping = null) - => SqlFunctionExpression.CreateNiladic(ApplyDefaultTypeMapping(instance), name, returnType, typeMapping); + { + Check.NotEmpty(name, nameof(name)); + Check.NotNull(returnType, nameof(returnType)); + + return SqlFunctionExpression.CreateNiladic(ApplyDefaultTypeMapping(instance), name, returnType, typeMapping); + } public virtual ExistsExpression Exists(SelectExpression subquery, bool negated) - => new ExistsExpression(subquery, negated, _boolTypeMapping); + { + Check.NotNull(subquery, nameof(subquery)); + + return new ExistsExpression(subquery, negated, _boolTypeMapping); + } public virtual InExpression In(SqlExpression item, SqlExpression values, bool negated) { + Check.NotNull(item, nameof(item)); + Check.NotNull(values, nameof(values)); + var typeMapping = item.TypeMapping ?? _typeMappingSource.FindMapping(item.Type); item = ApplyTypeMapping(item, typeMapping); @@ -418,6 +583,9 @@ public virtual InExpression In(SqlExpression item, SqlExpression values, bool ne public virtual InExpression In(SqlExpression item, SelectExpression subquery, bool negated) { + Check.NotNull(item, nameof(item)); + Check.NotNull(subquery, nameof(subquery)); + var sqlExpression = subquery.Projection.Single().Expression; var typeMapping = sqlExpression.TypeMapping; @@ -432,10 +600,19 @@ public virtual InExpression In(SqlExpression item, SelectExpression subquery, bo } public virtual LikeExpression Like(SqlExpression match, SqlExpression pattern, SqlExpression escapeChar = null) - => (LikeExpression)ApplyDefaultTypeMapping(new LikeExpression(match, pattern, escapeChar, null)); + { + Check.NotNull(match, nameof(match)); + Check.NotNull(pattern, nameof(pattern)); + + return (LikeExpression)ApplyDefaultTypeMapping(new LikeExpression(match, pattern, escapeChar, null)); + } public virtual SqlFragmentExpression Fragment(string sql) - => new SqlFragmentExpression(sql); + { + Check.NotNull(sql, nameof(sql)); + + return new SqlFragmentExpression(sql); + } public virtual SqlConstantExpression Constant(object value, RelationalTypeMapping typeMapping = null) => new SqlConstantExpression(Expression.Constant(value), typeMapping); @@ -460,6 +637,8 @@ public virtual SelectExpression Select(SqlExpression projection) public virtual SelectExpression Select(IEntityType entityType) { + Check.NotNull(entityType, nameof(entityType)); + var selectExpression = new SelectExpression(entityType); AddConditions(selectExpression, entityType); @@ -468,6 +647,9 @@ public virtual SelectExpression Select(IEntityType entityType) public virtual SelectExpression Select(IEntityType entityType, string sql, Expression sqlArguments) { + Check.NotNull(entityType, nameof(entityType)); + Check.NotNull(sql, nameof(sql)); + var selectExpression = new SelectExpression(entityType, sql, sqlArguments); AddConditions(selectExpression, entityType); diff --git a/src/EFCore.Relational/Query/SqlExpressionFactoryDependencies.cs b/src/EFCore.Relational/Query/SqlExpressionFactoryDependencies.cs index d644d02fd68..c9ddb288c9b 100644 --- a/src/EFCore.Relational/Query/SqlExpressionFactoryDependencies.cs +++ b/src/EFCore.Relational/Query/SqlExpressionFactoryDependencies.cs @@ -53,7 +53,7 @@ public sealed class SqlExpressionFactoryDependencies /// /// [EntityFrameworkInternal] - public SqlExpressionFactoryDependencies(IRelationalTypeMappingSource typeMappingSource) + public SqlExpressionFactoryDependencies([NotNull] IRelationalTypeMappingSource typeMappingSource) { Check.NotNull(typeMappingSource, nameof(typeMappingSource)); diff --git a/src/EFCore.Relational/Query/SqlExpressionVisitor.cs b/src/EFCore.Relational/Query/SqlExpressionVisitor.cs index bc3ea3cbbfd..f42270403a7 100644 --- a/src/EFCore.Relational/Query/SqlExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/SqlExpressionVisitor.cs @@ -2,7 +2,9 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query { @@ -10,6 +12,8 @@ public abstract class SqlExpressionVisitor : ExpressionVisitor { protected override Expression VisitExtension(Expression extensionExpression) { + Check.NotNull(extensionExpression, nameof(extensionExpression)); + switch (extensionExpression) { case CaseExpression caseExpression: @@ -94,31 +98,31 @@ protected override Expression VisitExtension(Expression extensionExpression) return base.VisitExtension(extensionExpression); } - protected abstract Expression VisitCase(CaseExpression caseExpression); - protected abstract Expression VisitColumn(ColumnExpression columnExpression); - protected abstract Expression VisitCrossApply(CrossApplyExpression crossApplyExpression); - protected abstract Expression VisitCrossJoin(CrossJoinExpression crossJoinExpression); - protected abstract Expression VisitExcept(ExceptExpression exceptExpression); - protected abstract Expression VisitExists(ExistsExpression existsExpression); - protected abstract Expression VisitFromSql(FromSqlExpression fromSqlExpression); - protected abstract Expression VisitIn(InExpression inExpression); - protected abstract Expression VisitIntersect(IntersectExpression intersectExpression); - protected abstract Expression VisitLike(LikeExpression likeExpression); - protected abstract Expression VisitInnerJoin(InnerJoinExpression innerJoinExpression); - protected abstract Expression VisitLeftJoin(LeftJoinExpression leftJoinExpression); - protected abstract Expression VisitOrdering(OrderingExpression orderingExpression); - protected abstract Expression VisitOuterApply(OuterApplyExpression outerApplyExpression); - protected abstract Expression VisitProjection(ProjectionExpression projectionExpression); - protected abstract Expression VisitRowNumber(RowNumberExpression rowNumberExpression); - protected abstract Expression VisitScalarSubquery(ScalarSubqueryExpression scalarSubqueryExpression); - protected abstract Expression VisitSelect(SelectExpression selectExpression); - protected abstract Expression VisitSqlBinary(SqlBinaryExpression sqlBinaryExpression); - protected abstract Expression VisitSqlConstant(SqlConstantExpression sqlConstantExpression); - protected abstract Expression VisitSqlFragment(SqlFragmentExpression sqlFragmentExpression); - protected abstract Expression VisitSqlFunction(SqlFunctionExpression sqlFunctionExpression); - protected abstract Expression VisitSqlParameter(SqlParameterExpression sqlParameterExpression); - protected abstract Expression VisitSqlUnary(SqlUnaryExpression sqlUnaryExpression); - protected abstract Expression VisitTable(TableExpression tableExpression); - protected abstract Expression VisitUnion(UnionExpression unionExpression); + protected abstract Expression VisitCase([NotNull] CaseExpression caseExpression); + protected abstract Expression VisitColumn([NotNull] ColumnExpression columnExpression); + protected abstract Expression VisitCrossApply([NotNull] CrossApplyExpression crossApplyExpression); + protected abstract Expression VisitCrossJoin([NotNull] CrossJoinExpression crossJoinExpression); + protected abstract Expression VisitExcept([NotNull] ExceptExpression exceptExpression); + protected abstract Expression VisitExists([NotNull] ExistsExpression existsExpression); + protected abstract Expression VisitFromSql([NotNull] FromSqlExpression fromSqlExpression); + protected abstract Expression VisitIn([NotNull] InExpression inExpression); + protected abstract Expression VisitIntersect([NotNull] IntersectExpression intersectExpression); + protected abstract Expression VisitLike([NotNull] LikeExpression likeExpression); + protected abstract Expression VisitInnerJoin([NotNull] InnerJoinExpression innerJoinExpression); + protected abstract Expression VisitLeftJoin([NotNull] LeftJoinExpression leftJoinExpression); + protected abstract Expression VisitOrdering([NotNull] OrderingExpression orderingExpression); + protected abstract Expression VisitOuterApply([NotNull] OuterApplyExpression outerApplyExpression); + protected abstract Expression VisitProjection([NotNull] ProjectionExpression projectionExpression); + protected abstract Expression VisitRowNumber([NotNull] RowNumberExpression rowNumberExpression); + protected abstract Expression VisitScalarSubquery([NotNull] ScalarSubqueryExpression scalarSubqueryExpression); + protected abstract Expression VisitSelect([NotNull] SelectExpression selectExpression); + protected abstract Expression VisitSqlBinary([NotNull] SqlBinaryExpression sqlBinaryExpression); + protected abstract Expression VisitSqlConstant([NotNull] SqlConstantExpression sqlConstantExpression); + protected abstract Expression VisitSqlFragment([NotNull] SqlFragmentExpression sqlFragmentExpression); + protected abstract Expression VisitSqlFunction([NotNull] SqlFunctionExpression sqlFunctionExpression); + protected abstract Expression VisitSqlParameter([NotNull] SqlParameterExpression sqlParameterExpression); + protected abstract Expression VisitSqlUnary([NotNull] SqlUnaryExpression sqlUnaryExpression); + protected abstract Expression VisitTable([NotNull] TableExpression tableExpression); + protected abstract Expression VisitUnion([NotNull] UnionExpression unionExpression); } } diff --git a/src/EFCore.Relational/Query/SqlExpressions/CaseExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/CaseExpression.cs index ca50076d2e1..5abb4412d1c 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/CaseExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/CaseExpression.cs @@ -5,6 +5,8 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { @@ -13,25 +15,28 @@ public class CaseExpression : SqlExpression private readonly List _whenClauses = new List(); public CaseExpression( - SqlExpression operand, - IReadOnlyList whenClauses) + [NotNull] SqlExpression operand, + [NotNull] IReadOnlyList whenClauses) : this(operand, whenClauses, null) { + Check.NotNull(operand, nameof(operand)); } public CaseExpression( - IReadOnlyList whenClauses, - SqlExpression elseResult) + [NotNull] IReadOnlyList whenClauses, + [CanBeNull] SqlExpression elseResult) : this(null, whenClauses, elseResult) { } public CaseExpression( - SqlExpression operand, - IReadOnlyList whenClauses, - SqlExpression elseResult) + [CanBeNull] SqlExpression operand, + [NotNull] IReadOnlyList whenClauses, + [CanBeNull] SqlExpression elseResult) : base(whenClauses[0].Result.Type, whenClauses[0].Result.TypeMapping) { + Check.NotNull(whenClauses, nameof(whenClauses)); + Operand = operand; _whenClauses.AddRange(whenClauses); ElseResult = elseResult; @@ -43,6 +48,8 @@ public CaseExpression( protected override Expression VisitChildren(ExpressionVisitor visitor) { + Check.NotNull(visitor, nameof(visitor)); + var operand = (SqlExpression)visitor.Visit(Operand); var changed = operand != Operand; var whenClauses = new List(); @@ -72,15 +79,17 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) } public virtual CaseExpression Update( - SqlExpression operand, - IReadOnlyList whenClauses, - SqlExpression elseResult) + [CanBeNull] SqlExpression operand, + [CanBeNull] IReadOnlyList whenClauses, + [CanBeNull] SqlExpression elseResult) => operand != Operand || !whenClauses.SequenceEqual(WhenClauses) || elseResult != ElseResult ? new CaseExpression(operand, whenClauses, elseResult) : this; public override void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.Append("CASE"); if (Operand != null) { diff --git a/src/EFCore.Relational/Query/SqlExpressions/CaseWhenClause.cs b/src/EFCore.Relational/Query/SqlExpressions/CaseWhenClause.cs index 6168fdda793..49cbc000765 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/CaseWhenClause.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/CaseWhenClause.cs @@ -2,13 +2,18 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class CaseWhenClause { - public CaseWhenClause(SqlExpression test, SqlExpression result) + public CaseWhenClause([NotNull] SqlExpression test, [NotNull] SqlExpression result) { + Check.NotNull(test, nameof(test)); + Check.NotNull(result, nameof(result)); + Test = test; Result = result; } diff --git a/src/EFCore.Relational/Query/SqlExpressions/ColumnExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/ColumnExpression.cs index 0db3f21a9b7..7373d3d9ee9 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/ColumnExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/ColumnExpression.cs @@ -53,13 +53,20 @@ private ColumnExpression(string name, TableExpressionBase table, Type type, Rela public TableExpressionBase Table { get; } public bool IsNullable { get; } - protected override Expression VisitChildren(ExpressionVisitor visitor) => this; + protected override Expression VisitChildren(ExpressionVisitor visitor) + { + Check.NotNull(visitor, nameof(visitor)); + + return this; + } public ColumnExpression MakeNullable() => new ColumnExpression(Name, Table, Type.MakeNullable(), TypeMapping, true); public override void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.Append(Table.Alias).Append("."); expressionPrinter.Append(Name); } diff --git a/src/EFCore.Relational/Query/SqlExpressions/CrossApplyExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/CrossApplyExpression.cs index 41b4e94aa6c..443cfebf559 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/CrossApplyExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/CrossApplyExpression.cs @@ -2,26 +2,38 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Linq.Expressions; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class CrossApplyExpression : JoinExpressionBase { - public CrossApplyExpression(TableExpressionBase table) + public CrossApplyExpression([NotNull] TableExpressionBase table) : base(table) { } protected override Expression VisitChildren(ExpressionVisitor visitor) - => Update((TableExpressionBase)visitor.Visit(Table)); + { + Check.NotNull(visitor, nameof(visitor)); + + return Update((TableExpressionBase)visitor.Visit(Table)); + } - public virtual CrossApplyExpression Update(TableExpressionBase table) - => table != Table + public virtual CrossApplyExpression Update([NotNull] TableExpressionBase table) + { + Check.NotNull(table, nameof(table)); + + return table != Table ? new CrossApplyExpression(table) : this; + } public override void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.Append("CROSS APPLY "); expressionPrinter.Visit(Table); } diff --git a/src/EFCore.Relational/Query/SqlExpressions/CrossJoinExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/CrossJoinExpression.cs index 25fb0b1bbd0..30ddbfb442e 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/CrossJoinExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/CrossJoinExpression.cs @@ -2,26 +2,38 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Linq.Expressions; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class CrossJoinExpression : JoinExpressionBase { - public CrossJoinExpression(TableExpressionBase table) + public CrossJoinExpression([NotNull] TableExpressionBase table) : base(table) { } protected override Expression VisitChildren(ExpressionVisitor visitor) - => Update((TableExpressionBase)visitor.Visit(Table)); + { + Check.NotNull(visitor, nameof(visitor)); + + return Update((TableExpressionBase)visitor.Visit(Table)); + } - public virtual CrossJoinExpression Update(TableExpressionBase table) - => table != Table + public virtual CrossJoinExpression Update([NotNull] TableExpressionBase table) + { + Check.NotNull(table, nameof(table)); + + return table != Table ? new CrossJoinExpression(table) : this; + } public override void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.Append("CROSS JOIN "); expressionPrinter.Visit(Table); } diff --git a/src/EFCore.Relational/Query/SqlExpressions/ExceptExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/ExceptExpression.cs index 35340085326..7c27a509f79 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/ExceptExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/ExceptExpression.cs @@ -3,31 +3,46 @@ using System; using System.Linq.Expressions; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class ExceptExpression : SetOperationBase { - public ExceptExpression(string alias, SelectExpression source1, SelectExpression source2, bool distinct) + public ExceptExpression( + [NotNull] string alias, + [NotNull] SelectExpression source1, + [NotNull] SelectExpression source2, + bool distinct) : base(alias, source1, source2, distinct) { } protected override Expression VisitChildren(ExpressionVisitor visitor) { + Check.NotNull(visitor, nameof(visitor)); + var source1 = (SelectExpression)visitor.Visit(Source1); var source2 = (SelectExpression)visitor.Visit(Source2); return Update(source1, source2); } - public virtual ExceptExpression Update(SelectExpression source1, SelectExpression source2) - => source1 != Source1 || source2 != Source2 + public virtual ExceptExpression Update([NotNull] SelectExpression source1, [NotNull] SelectExpression source2) + { + Check.NotNull(source1, nameof(source1)); + Check.NotNull(source2, nameof(source2)); + + return source1 != Source1 || source2 != Source2 ? new ExceptExpression(Alias, source1, source2, IsDistinct) : this; + } public override void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.Append("("); using (expressionPrinter.Indent()) { diff --git a/src/EFCore.Relational/Query/SqlExpressions/ExistsExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/ExistsExpression.cs index 195f88a23b5..ba6b2aa08fd 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/ExistsExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/ExistsExpression.cs @@ -3,15 +3,22 @@ using System; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class ExistsExpression : SqlExpression { - public ExistsExpression(SelectExpression subquery, bool negated, RelationalTypeMapping typeMapping) + public ExistsExpression( + [NotNull] SelectExpression subquery, + bool negated, + [CanBeNull] RelationalTypeMapping typeMapping) : base(typeof(bool), typeMapping) { + Check.NotNull(subquery, nameof(subquery)); + Subquery = subquery; IsNegated = negated; } @@ -20,15 +27,25 @@ public ExistsExpression(SelectExpression subquery, bool negated, RelationalTypeM public virtual bool IsNegated { get; } protected override Expression VisitChildren(ExpressionVisitor visitor) - => Update((SelectExpression)visitor.Visit(Subquery)); + { + Check.NotNull(visitor, nameof(visitor)); + + return Update((SelectExpression)visitor.Visit(Subquery)); + } - public virtual ExistsExpression Update(SelectExpression subquery) - => subquery != Subquery + public virtual ExistsExpression Update([NotNull] SelectExpression subquery) + { + Check.NotNull(subquery, nameof(subquery)); + + return subquery != Subquery ? new ExistsExpression(subquery, IsNegated, TypeMapping) : this; + } public override void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + if (IsNegated) { expressionPrinter.Append("NOT "); diff --git a/src/EFCore.Relational/Query/SqlExpressions/FromSqlExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/FromSqlExpression.cs index 91891570a4f..bdbba477333 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/FromSqlExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/FromSqlExpression.cs @@ -4,14 +4,18 @@ using System; using System.Linq.Expressions; using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class FromSqlExpression : TableExpressionBase { - public FromSqlExpression([NotNull] string sql, Expression arguments, [NotNull] string alias) + public FromSqlExpression([NotNull] string sql, [NotNull] Expression arguments, [NotNull] string alias) : base(alias) { + Check.NotEmpty(sql, nameof(sql)); + Check.NotNull(arguments, nameof(arguments)); + Sql = sql; Arguments = arguments; } @@ -19,10 +23,19 @@ public FromSqlExpression([NotNull] string sql, Expression arguments, [NotNull] s public virtual string Sql { get; } public virtual Expression Arguments { get; } - protected override Expression VisitChildren(ExpressionVisitor visitor) => this; + protected override Expression VisitChildren(ExpressionVisitor visitor) + { + Check.NotNull(visitor, nameof(visitor)); + + return this; + } public override void Print(ExpressionPrinter expressionPrinter) - => expressionPrinter.Append(Sql); + { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + + expressionPrinter.Append(Sql); + } public override bool Equals(object obj) => obj != null diff --git a/src/EFCore.Relational/Query/SqlExpressions/InExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/InExpression.cs index 4f71cc8ff4d..a67454dc235 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/InExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/InExpression.cs @@ -4,20 +4,34 @@ using System; using System.Collections; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class InExpression : SqlExpression { - public InExpression(SqlExpression item, bool negated, SelectExpression subquery, RelationalTypeMapping typeMapping) + public InExpression( + [NotNull] SqlExpression item, + bool negated, + [NotNull] SelectExpression subquery, + [CanBeNull] RelationalTypeMapping typeMapping) : this(item, negated, null, subquery, typeMapping) { + Check.NotNull(item, nameof(item)); + Check.NotNull(subquery, nameof(subquery)); } - public InExpression(SqlExpression item, bool negated, SqlExpression values, RelationalTypeMapping typeMapping) + public InExpression( + [NotNull] SqlExpression item, + bool negated, + [NotNull] SqlExpression values, + [CanBeNull] RelationalTypeMapping typeMapping) : this(item, negated, values, null, typeMapping) { + Check.NotNull(item, nameof(item)); + Check.NotNull(values, nameof(values)); } private InExpression( @@ -38,6 +52,8 @@ private InExpression( protected override Expression VisitChildren(ExpressionVisitor visitor) { + Check.NotNull(visitor, nameof(visitor)); + var newItem = (SqlExpression)visitor.Visit(Item); var subquery = (SelectExpression)visitor.Visit(Subquery); var values = (SqlExpression)visitor.Visit(Values); @@ -47,13 +63,20 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) public virtual InExpression Negate() => new InExpression(Item, !IsNegated, Values, Subquery, TypeMapping); - public virtual InExpression Update(SqlExpression item, SqlExpression values, SelectExpression subquery) - => item != Item || subquery != Subquery || values != Values + public virtual InExpression Update( + [NotNull] SqlExpression item, [CanBeNull] SqlExpression values, [CanBeNull] SelectExpression subquery) + { + Check.NotNull(item, nameof(item)); + + return item != Item || subquery != Subquery || values != Values ? new InExpression(item, IsNegated, values, subquery, TypeMapping) : this; + } public override void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.Visit(Item); expressionPrinter.Append(IsNegated ? " NOT IN " : " IN "); expressionPrinter.Append("("); diff --git a/src/EFCore.Relational/Query/SqlExpressions/InnerJoinExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/InnerJoinExpression.cs index ddad3de5f37..60cae4b4e94 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/InnerJoinExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/InnerJoinExpression.cs @@ -2,31 +2,42 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Linq.Expressions; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class InnerJoinExpression : PredicateJoinExpressionBase { - public InnerJoinExpression(TableExpressionBase table, SqlExpression joinPredicate) + public InnerJoinExpression([NotNull] TableExpressionBase table, [NotNull] SqlExpression joinPredicate) : base(table, joinPredicate) { } protected override Expression VisitChildren(ExpressionVisitor visitor) { + Check.NotNull(visitor, nameof(visitor)); + var table = (TableExpressionBase)visitor.Visit(Table); var joinPredicate = (SqlExpression)visitor.Visit(JoinPredicate); return Update(table, joinPredicate); } - public virtual InnerJoinExpression Update(TableExpressionBase table, SqlExpression joinPredicate) - => table != Table || joinPredicate != JoinPredicate + public virtual InnerJoinExpression Update([NotNull] TableExpressionBase table, [NotNull] SqlExpression joinPredicate) + { + Check.NotNull(table, nameof(table)); + Check.NotNull(joinPredicate, nameof(joinPredicate)); + + return table != Table || joinPredicate != JoinPredicate ? new InnerJoinExpression(table, joinPredicate) : this; + } public override void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.Append("INNER JOIN "); expressionPrinter.Visit(Table); expressionPrinter.Append(" ON "); diff --git a/src/EFCore.Relational/Query/SqlExpressions/IntersectExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/IntersectExpression.cs index 56d363037c3..d636e680403 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/IntersectExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/IntersectExpression.cs @@ -3,31 +3,43 @@ using System; using System.Linq.Expressions; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class IntersectExpression : SetOperationBase { - public IntersectExpression(string alias, SelectExpression source1, SelectExpression source2, bool distinct) + public IntersectExpression( + [NotNull] string alias, [NotNull] SelectExpression source1, [NotNull] SelectExpression source2, bool distinct) : base(alias, source1, source2, distinct) { } protected override Expression VisitChildren(ExpressionVisitor visitor) { + Check.NotNull(visitor, nameof(visitor)); + var source1 = (SelectExpression)visitor.Visit(Source1); var source2 = (SelectExpression)visitor.Visit(Source2); return Update(source1, source2); } - public virtual IntersectExpression Update(SelectExpression source1, SelectExpression source2) - => source1 != Source1 || source2 != Source2 + public virtual IntersectExpression Update([NotNull] SelectExpression source1, [NotNull] SelectExpression source2) + { + Check.NotNull(source1, nameof(source1)); + Check.NotNull(source2, nameof(source2)); + + return source1 != Source1 || source2 != Source2 ? new IntersectExpression(Alias, source1, source2, IsDistinct) : this; + } public override void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.Append("("); using (expressionPrinter.Indent()) { diff --git a/src/EFCore.Relational/Query/SqlExpressions/JoinExpressionBase.cs b/src/EFCore.Relational/Query/SqlExpressions/JoinExpressionBase.cs index acaa82c4688..9559dac1898 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/JoinExpressionBase.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/JoinExpressionBase.cs @@ -2,14 +2,18 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public abstract class JoinExpressionBase : TableExpressionBase { - protected JoinExpressionBase(TableExpressionBase table) + protected JoinExpressionBase([NotNull] TableExpressionBase table) : base(null) { + Check.NotNull(table, nameof(table)); + Table = table; } diff --git a/src/EFCore.Relational/Query/SqlExpressions/LeftJoinExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/LeftJoinExpression.cs index 0b0a64055c1..5e317d5c038 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/LeftJoinExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/LeftJoinExpression.cs @@ -2,31 +2,42 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Linq.Expressions; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class LeftJoinExpression : PredicateJoinExpressionBase { - public LeftJoinExpression(TableExpressionBase table, SqlExpression joinPredicate) + public LeftJoinExpression([NotNull] TableExpressionBase table, [NotNull] SqlExpression joinPredicate) : base(table, joinPredicate) { } protected override Expression VisitChildren(ExpressionVisitor visitor) { + Check.NotNull(visitor, nameof(visitor)); + var table = (TableExpressionBase)visitor.Visit(Table); var joinPredicate = (SqlExpression)visitor.Visit(JoinPredicate); return Update(table, joinPredicate); } - public virtual LeftJoinExpression Update(TableExpressionBase table, SqlExpression joinPredicate) - => table != Table || joinPredicate != JoinPredicate + public virtual LeftJoinExpression Update([NotNull] TableExpressionBase table, [NotNull] SqlExpression joinPredicate) + { + Check.NotNull(table, nameof(table)); + Check.NotNull(joinPredicate, nameof(joinPredicate)); + + return table != Table || joinPredicate != JoinPredicate ? new LeftJoinExpression(table, joinPredicate) : this; + } public override void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.Append("LEFT JOIN "); expressionPrinter.Visit(Table); expressionPrinter.Append(" ON "); diff --git a/src/EFCore.Relational/Query/SqlExpressions/LikeExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/LikeExpression.cs index b91bd5579ef..bcac20c8b04 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/LikeExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/LikeExpression.cs @@ -3,15 +3,24 @@ using System; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class LikeExpression : SqlExpression { - public LikeExpression(SqlExpression match, SqlExpression pattern, SqlExpression escapeChar, RelationalTypeMapping typeMapping) + public LikeExpression( + [NotNull] SqlExpression match, + [NotNull] SqlExpression pattern, + [CanBeNull] SqlExpression escapeChar, + [CanBeNull] RelationalTypeMapping typeMapping) : base(typeof(bool), typeMapping) { + Check.NotNull(match, nameof(match)); + Check.NotNull(pattern, nameof(pattern)); + Match = match; Pattern = pattern; EscapeChar = escapeChar; @@ -23,6 +32,8 @@ public LikeExpression(SqlExpression match, SqlExpression pattern, SqlExpression protected override Expression VisitChildren(ExpressionVisitor visitor) { + Check.NotNull(visitor, nameof(visitor)); + var match = (SqlExpression)visitor.Visit(Match); var pattern = (SqlExpression)visitor.Visit(Pattern); var escapeChar = (SqlExpression)visitor.Visit(EscapeChar); @@ -30,13 +41,21 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) return Update(match, pattern, escapeChar); } - public virtual LikeExpression Update(SqlExpression match, SqlExpression pattern, SqlExpression escapeChar) - => match != Match || pattern != Pattern || escapeChar != EscapeChar + public virtual LikeExpression Update( + [NotNull] SqlExpression match, [NotNull] SqlExpression pattern, [CanBeNull] SqlExpression escapeChar) + { + Check.NotNull(match, nameof(match)); + Check.NotNull(pattern, nameof(pattern)); + + return match != Match || pattern != Pattern || escapeChar != EscapeChar ? new LikeExpression(match, pattern, escapeChar, TypeMapping) : this; + } public override void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.Visit(Match); expressionPrinter.Append(" LIKE "); expressionPrinter.Visit(Pattern); diff --git a/src/EFCore.Relational/Query/SqlExpressions/OrderingExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/OrderingExpression.cs index e7d243dbeb8..88c6de5f177 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/OrderingExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/OrderingExpression.cs @@ -3,13 +3,17 @@ using System; using System.Linq.Expressions; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class OrderingExpression : Expression, IPrintableExpression { - public OrderingExpression(SqlExpression expression, bool ascending) + public OrderingExpression([NotNull] SqlExpression expression, bool ascending) { + Check.NotNull(expression, nameof(expression)); + Expression = expression; IsAscending = ascending; } @@ -21,15 +25,25 @@ public OrderingExpression(SqlExpression expression, bool ascending) public override Type Type => Expression.Type; protected override Expression VisitChildren(ExpressionVisitor visitor) - => Update((SqlExpression)visitor.Visit(Expression)); + { + Check.NotNull(visitor, nameof(visitor)); + + return Update((SqlExpression)visitor.Visit(Expression)); + } - public virtual OrderingExpression Update(SqlExpression expression) - => expression != Expression + public virtual OrderingExpression Update([NotNull] SqlExpression expression) + { + Check.NotNull(expression, nameof(expression)); + + return expression != Expression ? new OrderingExpression(expression, IsAscending) : this; + } public virtual void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.Visit(Expression); expressionPrinter.Append(IsAscending ? " ASC" : " DESC"); diff --git a/src/EFCore.Relational/Query/SqlExpressions/OuterApplyExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/OuterApplyExpression.cs index 50d9fe32763..a1ce2eb9da4 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/OuterApplyExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/OuterApplyExpression.cs @@ -2,26 +2,38 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Linq.Expressions; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class OuterApplyExpression : JoinExpressionBase { - public OuterApplyExpression(TableExpressionBase table) + public OuterApplyExpression([NotNull] TableExpressionBase table) : base(table) { } protected override Expression VisitChildren(ExpressionVisitor visitor) - => Update((TableExpressionBase)visitor.Visit(Table)); + { + Check.NotNull(visitor, nameof(visitor)); + + return Update((TableExpressionBase)visitor.Visit(Table)); + } - public virtual OuterApplyExpression Update(TableExpressionBase table) - => table != Table + public virtual OuterApplyExpression Update([NotNull] TableExpressionBase table) + { + Check.NotNull(table, nameof(table)); + + return table != Table ? new OuterApplyExpression(table) : this; + } public override void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.Append("OUTER APPLY "); expressionPrinter.Visit(Table); } diff --git a/src/EFCore.Relational/Query/SqlExpressions/PredicateJoinExpressionBase.cs b/src/EFCore.Relational/Query/SqlExpressions/PredicateJoinExpressionBase.cs index 6ad218056b3..3d2ce3c08fd 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/PredicateJoinExpressionBase.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/PredicateJoinExpressionBase.cs @@ -2,14 +2,18 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public abstract class PredicateJoinExpressionBase : JoinExpressionBase { - protected PredicateJoinExpressionBase(TableExpressionBase table, SqlExpression joinPredicate) + protected PredicateJoinExpressionBase([NotNull] TableExpressionBase table, [NotNull] SqlExpression joinPredicate) : base(table) { + Check.NotNull(joinPredicate, nameof(joinPredicate)); + JoinPredicate = joinPredicate; } diff --git a/src/EFCore.Relational/Query/SqlExpressions/ProjectionExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/ProjectionExpression.cs index 8eeeb559b9a..09dfd1fa14a 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/ProjectionExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/ProjectionExpression.cs @@ -3,13 +3,18 @@ using System; using System.Linq.Expressions; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class ProjectionExpression : Expression, IPrintableExpression { - public ProjectionExpression(SqlExpression expression, string alias) + public ProjectionExpression([NotNull] SqlExpression expression, [NotNull] string alias) { + Check.NotNull(expression, nameof(expression)); + Check.NotNull(alias, nameof(alias)); + Expression = expression; Alias = alias; } @@ -21,15 +26,25 @@ public ProjectionExpression(SqlExpression expression, string alias) public sealed override ExpressionType NodeType => ExpressionType.Extension; protected override Expression VisitChildren(ExpressionVisitor visitor) - => Update((SqlExpression)visitor.Visit(Expression)); + { + Check.NotNull(visitor, nameof(visitor)); + + return Update((SqlExpression)visitor.Visit(Expression)); + } - public virtual ProjectionExpression Update(SqlExpression expression) - => expression != Expression + public virtual ProjectionExpression Update([NotNull] SqlExpression expression) + { + Check.NotNull(expression, nameof(expression)); + + return expression != Expression ? new ProjectionExpression(expression, Alias) : this; + } public virtual void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.Visit(Expression); if (!string.Equals(string.Empty, Alias) && !(Expression is ColumnExpression column diff --git a/src/EFCore.Relational/Query/SqlExpressions/RowNumberExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/RowNumberExpression.cs index 478aa6fc77b..428265183b5 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/RowNumberExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/RowNumberExpression.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; @@ -13,9 +14,12 @@ namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions public class RowNumberExpression : SqlExpression { public RowNumberExpression( - IReadOnlyList partitions, IReadOnlyList orderings, RelationalTypeMapping typeMapping) + [NotNull] IReadOnlyList partitions, + [NotNull] IReadOnlyList orderings, + [CanBeNull] RelationalTypeMapping typeMapping) : base(typeof(long), typeMapping) { + Check.NotNull(partitions, nameof(partitions)); Check.NotEmpty(orderings, nameof(orderings)); Partitions = partitions; @@ -27,6 +31,8 @@ public RowNumberExpression( protected override Expression VisitChildren(ExpressionVisitor visitor) { + Check.NotNull(visitor, nameof(visitor)); + var changed = false; var partitions = new List(); foreach (var partition in Partitions) @@ -49,8 +55,11 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) : this; } - public virtual RowNumberExpression Update(IReadOnlyList partitions, IReadOnlyList orderings) + public virtual RowNumberExpression Update( + [CanBeNull] IReadOnlyList partitions, [NotNull] IReadOnlyList orderings) { + Check.NotNull(orderings, nameof(orderings)); + return (Partitions == null ? partitions == null : Partitions.SequenceEqual(partitions)) && Orderings.SequenceEqual(orderings) ? this @@ -59,6 +68,8 @@ public virtual RowNumberExpression Update(IReadOnlyList partition public override void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.Append("ROW_NUMBER() OVER("); if (Partitions.Any()) { diff --git a/src/EFCore.Relational/Query/SqlExpressions/ScalarSubqueryExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/ScalarSubqueryExpression.cs index e8d05f45e22..6265a2dba19 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/ScalarSubqueryExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/ScalarSubqueryExpression.cs @@ -3,16 +3,20 @@ using System; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class ScalarSubqueryExpression : SqlExpression { - public ScalarSubqueryExpression(SelectExpression subquery) + public ScalarSubqueryExpression([NotNull] SelectExpression subquery) : base(Verify(subquery).Projection[0].Type, subquery.Projection[0].Expression.TypeMapping) { + Check.NotNull(subquery, nameof(subquery)); + Subquery = subquery; } @@ -29,15 +33,25 @@ private static SelectExpression Verify(SelectExpression selectExpression) public virtual SelectExpression Subquery { get; } protected override Expression VisitChildren(ExpressionVisitor visitor) - => Update((SelectExpression)visitor.Visit(Subquery)); + { + Check.NotNull(visitor, nameof(visitor)); + + return Update((SelectExpression)visitor.Visit(Subquery)); + } - public virtual ScalarSubqueryExpression Update(SelectExpression subquery) - => subquery != Subquery + public virtual ScalarSubqueryExpression Update([NotNull] SelectExpression subquery) + { + Check.NotNull(subquery, nameof(subquery)); + + return subquery != Subquery ? new ScalarSubqueryExpression(subquery) : this; + } public override void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.Append("("); using (expressionPrinter.Indent()) { diff --git a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs index d6ad550ebc7..7ebe2052936 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs @@ -6,8 +6,10 @@ using System.Linq; using System.Linq.Expressions; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { @@ -38,8 +40,10 @@ private readonly IDictionary tags) + public void ApplyTags([NotNull] ISet tags) { + Check.NotNull(tags, nameof(tags)); + Tags = tags; } @@ -141,8 +145,10 @@ public void ApplyProjection() private static IEnumerable GetAllPropertiesInHierarchy(IEntityType entityType) => entityType.GetTypesInHierarchy().SelectMany(EntityTypeExtensions.GetDeclaredProperties); - public void ReplaceProjectionMapping(IDictionary projectionMapping) + public void ReplaceProjectionMapping([NotNull] IDictionary projectionMapping) { + Check.NotNull(projectionMapping, nameof(projectionMapping)); + _projectionMapping.Clear(); foreach (var kvp in projectionMapping) { @@ -150,11 +156,19 @@ public void ReplaceProjectionMapping(IDictionary p } } - public Expression GetMappedProjection(ProjectionMember projectionMember) - => _projectionMapping[projectionMember]; + public Expression GetMappedProjection([NotNull] ProjectionMember projectionMember) + { + Check.NotNull(projectionMember, nameof(projectionMember)); - public int AddToProjection(SqlExpression sqlExpression) - => AddToProjection(sqlExpression, null); + return _projectionMapping[projectionMember]; + } + + public int AddToProjection([NotNull] SqlExpression sqlExpression) + { + Check.NotNull(sqlExpression, nameof(sqlExpression)); + + return AddToProjection(sqlExpression, null); + } private int AddToProjection(SqlExpression sqlExpression, string alias) { @@ -181,8 +195,10 @@ private int AddToProjection(SqlExpression sqlExpression, string alias) return _projection.Count - 1; } - public IDictionary AddToProjection(EntityProjectionExpression entityProjection) + public IDictionary AddToProjection([NotNull] EntityProjectionExpression entityProjection) { + Check.NotNull(entityProjection, nameof(entityProjection)); + if (!_entityProjectionCache.TryGetValue(entityProjection, out var dictionary)) { dictionary = new Dictionary(); @@ -208,8 +224,10 @@ public void PrepareForAggregate() } } - public void ApplyPredicate(SqlExpression expression) + public void ApplyPredicate([NotNull] SqlExpression expression) { + Check.NotNull(expression, nameof(expression)); + if (expression is SqlConstantExpression sqlConstant && (bool)sqlConstant.Value) { @@ -246,15 +264,19 @@ public void ApplyPredicate(SqlExpression expression) } } - public void ApplyGrouping(Expression keySelector) + public void ApplyGrouping([NotNull] Expression keySelector) { + Check.NotNull(keySelector, nameof(keySelector)); + ClearOrdering(); AppendGroupBy(keySelector); } - private void AppendGroupBy(Expression keySelector) + private void AppendGroupBy([NotNull] Expression keySelector) { + Check.NotNull(keySelector, nameof(keySelector)); + switch (keySelector) { case SqlExpression sqlExpression: @@ -294,8 +316,10 @@ private void AppendGroupBy(Expression keySelector) } } - public void ApplyOrdering(OrderingExpression orderingExpression) + public void ApplyOrdering([NotNull] OrderingExpression orderingExpression) { + Check.NotNull(orderingExpression, nameof(orderingExpression)); + if (IsDistinct || Limit != null || Offset != null) @@ -309,15 +333,17 @@ public void ApplyOrdering(OrderingExpression orderingExpression) _orderings.Add(orderingExpression); } - public void AppendOrdering(OrderingExpression orderingExpression) + public void AppendOrdering([NotNull] OrderingExpression orderingExpression) { + Check.NotNull(orderingExpression, nameof(orderingExpression)); + if (_orderings.FirstOrDefault(o => o.Expression.Equals(orderingExpression.Expression)) == null) { _orderings.Add(orderingExpression); } } - public void ApplyLimit(SqlExpression sqlExpression) + public void ApplyLimit([CanBeNull] SqlExpression sqlExpression) { if (Limit != null) { @@ -327,8 +353,10 @@ public void ApplyLimit(SqlExpression sqlExpression) Limit = sqlExpression; } - public void ApplyOffset(SqlExpression sqlExpression) + public void ApplyOffset([NotNull] SqlExpression sqlExpression) { + Check.NotNull(sqlExpression, nameof(sqlExpression)); + if (Limit != null || Offset != null) { @@ -372,8 +400,10 @@ public void ApplyDistinct() ClearOrdering(); } - public void ApplyDefaultIfEmpty(ISqlExpressionFactory sqlExpressionFactory) + public void ApplyDefaultIfEmpty([NotNull] ISqlExpressionFactory sqlExpressionFactory) { + Check.NotNull(sqlExpressionFactory, nameof(sqlExpressionFactory)); + var nullSqlExpression = sqlExpressionFactory.ApplyDefaultTypeMapping( new SqlConstantExpression(Constant(null, typeof(string)), null)); @@ -448,14 +478,26 @@ private enum SetOperationType Union } - public void ApplyExcept(SelectExpression source2, bool distinct) - => ApplySetOperation(SetOperationType.Except, source2, distinct); + public void ApplyExcept([NotNull] SelectExpression source2, bool distinct) + { + Check.NotNull(source2, nameof(source2)); - public void ApplyIntersect(SelectExpression source2, bool distinct) - => ApplySetOperation(SetOperationType.Intersect, source2, distinct); + ApplySetOperation(SetOperationType.Except, source2, distinct); + } - public void ApplyUnion(SelectExpression source2, bool distinct) - => ApplySetOperation(SetOperationType.Union, source2, distinct); + public void ApplyIntersect([NotNull] SelectExpression source2, bool distinct) + { + Check.NotNull(source2, nameof(source2)); + + ApplySetOperation(SetOperationType.Intersect, source2, distinct); + } + + public void ApplyUnion([NotNull] SelectExpression source2, bool distinct) + { + Check.NotNull(source2, nameof(source2)); + + ApplySetOperation(SetOperationType.Union, source2, distinct); + } private void ApplySetOperation(SetOperationType setOperationType, SelectExpression select2, bool distinct) { @@ -797,8 +839,10 @@ EntityProjectionExpression LiftEntityProjectionFromSubquery(EntityProjectionExpr } } - public Expression AddSingleProjection(ShapedQueryExpression shapedQueryExpression) + public Expression AddSingleProjection([NotNull] ShapedQueryExpression shapedQueryExpression) { + Check.NotNull(shapedQueryExpression, nameof(shapedQueryExpression)); + var innerSelectExpression = (SelectExpression)shapedQueryExpression.QueryExpression; var shaperExpression = shapedQueryExpression.ShaperExpression; var innerExpression = RemoveConvert(shaperExpression); @@ -852,8 +896,10 @@ static Expression RemoveConvert(Expression expression) } public CollectionShaperExpression AddCollectionProjection( - ShapedQueryExpression shapedQueryExpression, INavigation navigation, Type elementType) + [NotNull] ShapedQueryExpression shapedQueryExpression, [CanBeNull] INavigation navigation, [CanBeNull] Type elementType) { + Check.NotNull(shapedQueryExpression, nameof(shapedQueryExpression)); + var innerSelectExpression = (SelectExpression)shapedQueryExpression.QueryExpression; _pendingCollections.Add(innerSelectExpression); @@ -865,8 +911,15 @@ public CollectionShaperExpression AddCollectionProjection( } public Expression ApplyCollectionJoin( - int collectionIndex, int collectionId, Expression innerShaper, INavigation navigation, Type elementType) + int collectionIndex, + int collectionId, + [NotNull] Expression innerShaper, + [CanBeNull] INavigation navigation, + [NotNull] Type elementType) { + Check.NotNull(innerShaper, nameof(innerShaper)); + Check.NotNull(elementType, nameof(elementType)); + var innerSelectExpression = _pendingCollections[collectionIndex]; _pendingCollections[collectionIndex] = null; var parentIdentifier = GetIdentifierAccessor(_identifier); @@ -972,6 +1025,8 @@ public ShaperRemappingExpressionVisitor(SelectExpression queryExpression, Select protected override Expression VisitExtension(Expression extensionExpression) { + Check.NotNull(extensionExpression, nameof(extensionExpression)); + if (extensionExpression is ProjectionBindingExpression projectionBindingExpression) { var oldIndex = (int)GetProjectionIndex(projectionBindingExpression); @@ -1350,20 +1405,48 @@ private void AddJoin( } } - public void AddInnerJoin(SelectExpression innerSelectExpression, SqlExpression joinPredicate, Type transparentIdentifierType) - => AddJoin(JoinType.InnerJoin, innerSelectExpression, transparentIdentifierType, joinPredicate); + public void AddInnerJoin( + [NotNull] SelectExpression innerSelectExpression, + [NotNull] SqlExpression joinPredicate, + [CanBeNull] Type transparentIdentifierType) + { + Check.NotNull(innerSelectExpression, nameof(innerSelectExpression)); + Check.NotNull(joinPredicate, nameof(joinPredicate)); - public void AddLeftJoin(SelectExpression innerSelectExpression, SqlExpression joinPredicate, Type transparentIdentifierType) - => AddJoin(JoinType.LeftJoin, innerSelectExpression, transparentIdentifierType, joinPredicate); + AddJoin(JoinType.InnerJoin, innerSelectExpression, transparentIdentifierType, joinPredicate); + } - public void AddCrossJoin(SelectExpression innerSelectExpression, Type transparentIdentifierType) - => AddJoin(JoinType.CrossJoin, innerSelectExpression, transparentIdentifierType); + public void AddLeftJoin( + [NotNull] SelectExpression innerSelectExpression, + [NotNull] SqlExpression joinPredicate, + [CanBeNull] Type transparentIdentifierType) + { + Check.NotNull(innerSelectExpression, nameof(innerSelectExpression)); + Check.NotNull(joinPredicate, nameof(joinPredicate)); - public void AddCrossApply(SelectExpression innerSelectExpression, Type transparentIdentifierType) - => AddJoin(JoinType.CrossApply, innerSelectExpression, transparentIdentifierType); + AddJoin(JoinType.LeftJoin, innerSelectExpression, transparentIdentifierType, joinPredicate); + } - public void AddOuterApply(SelectExpression innerSelectExpression, Type transparentIdentifierType) - => AddJoin(JoinType.OuterApply, innerSelectExpression, transparentIdentifierType); + public void AddCrossJoin([NotNull] SelectExpression innerSelectExpression, [CanBeNull] Type transparentIdentifierType) + { + Check.NotNull(innerSelectExpression, nameof(innerSelectExpression)); + + AddJoin(JoinType.CrossJoin, innerSelectExpression, transparentIdentifierType); + } + + public void AddCrossApply([NotNull] SelectExpression innerSelectExpression, [CanBeNull] Type transparentIdentifierType) + { + Check.NotNull(innerSelectExpression, nameof(innerSelectExpression)); + + AddJoin(JoinType.CrossApply, innerSelectExpression, transparentIdentifierType); + } + + public void AddOuterApply([NotNull] SelectExpression innerSelectExpression, [CanBeNull] Type transparentIdentifierType) + { + Check.NotNull(innerSelectExpression, nameof(innerSelectExpression)); + + AddJoin(JoinType.OuterApply, innerSelectExpression, transparentIdentifierType); + } private sealed class SqlRemappingVisitor : ExpressionVisitor { @@ -1401,6 +1484,8 @@ when _subquery.ContainsTableReference(columnExpression.Table): protected override Expression VisitChildren(ExpressionVisitor visitor) { + Check.NotNull(visitor, nameof(visitor)); + // We have to do in-place mutation till we have applied pending collections because of shaper references // This is pseudo finalization phase for select expression. if (_pendingCollections.Any(e => e != null)) @@ -1691,17 +1776,20 @@ private bool Equals(SelectExpression selectExpression) // This does not take internal states since when using this method SelectExpression should be finalized public SelectExpression Update( - List projections, - List tables, - SqlExpression predicate, - List groupBy, - SqlExpression havingExpression, - List orderings, - SqlExpression limit, - SqlExpression offset, + [NotNull] List projections, + [NotNull] List tables, + [CanBeNull] SqlExpression predicate, + [CanBeNull] List groupBy, + [CanBeNull] SqlExpression havingExpression, + [CanBeNull] List orderings, + [CanBeNull] SqlExpression limit, + [CanBeNull] SqlExpression offset, bool distinct, - string alias) + [CanBeNull] string alias) { + Check.NotNull(projections, nameof(projections)); + Check.NotNull(tables, nameof(tables)); + var projectionMapping = new Dictionary(); foreach (var kvp in _projectionMapping) { @@ -1764,6 +1852,8 @@ public override int GetHashCode() public override void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.AppendLine("Projection Mapping:"); using (expressionPrinter.Indent()) { diff --git a/src/EFCore.Relational/Query/SqlExpressions/SetOperationBase.cs b/src/EFCore.Relational/Query/SqlExpressions/SetOperationBase.cs index ee730ca98cf..5f4764de832 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SetOperationBase.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SetOperationBase.cs @@ -9,9 +9,13 @@ namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public abstract class SetOperationBase : TableExpressionBase { - protected SetOperationBase([NotNull] string alias, SelectExpression source1, SelectExpression source2, bool distinct) + protected SetOperationBase( + [NotNull] string alias, [NotNull] SelectExpression source1, [NotNull] SelectExpression source2, bool distinct) : base(Check.NotEmpty(alias, nameof(alias))) { + Check.NotNull(source1, nameof(source1)); + Check.NotNull(source2, nameof(source2)); + IsDistinct = distinct; Source1 = source1; Source2 = source2; diff --git a/src/EFCore.Relational/Query/SqlExpressions/SqlBinaryExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SqlBinaryExpression.cs index d5b54d5a20e..0b52afe55b0 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SqlBinaryExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SqlBinaryExpression.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; @@ -43,10 +44,10 @@ private static ExpressionType VerifyOperator(ExpressionType operatorType) public SqlBinaryExpression( ExpressionType operatorType, - SqlExpression left, - SqlExpression right, - Type type, - RelationalTypeMapping typeMapping) + [NotNull] SqlExpression left, + [NotNull] SqlExpression right, + [NotNull] Type type, + [CanBeNull] RelationalTypeMapping typeMapping) : base(type, typeMapping) { Check.NotNull(left, nameof(left)); @@ -64,19 +65,28 @@ public SqlBinaryExpression( protected override Expression VisitChildren(ExpressionVisitor visitor) { + Check.NotNull(visitor, nameof(visitor)); + var left = (SqlExpression)visitor.Visit(Left); var right = (SqlExpression)visitor.Visit(Right); return Update(left, right); } - public virtual SqlBinaryExpression Update(SqlExpression left, SqlExpression right) - => left != Left || right != Right + public virtual SqlBinaryExpression Update([NotNull] SqlExpression left, [NotNull] SqlExpression right) + { + Check.NotNull(left, nameof(left)); + Check.NotNull(right, nameof(right)); + + return left != Left || right != Right ? new SqlBinaryExpression(OperatorType, left, right, Type, TypeMapping) : this; + } public override void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + var requiresBrackets = RequiresBrackets(Left); if (requiresBrackets) diff --git a/src/EFCore.Relational/Query/SqlExpressions/SqlConstantExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SqlConstantExpression.cs index fa05649f450..7cebc6d6ebb 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SqlConstantExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SqlConstantExpression.cs @@ -4,7 +4,9 @@ using System; using System.Collections; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { @@ -12,19 +14,32 @@ public class SqlConstantExpression : SqlExpression { private readonly ConstantExpression _constantExpression; - public SqlConstantExpression(ConstantExpression constantExpression, RelationalTypeMapping typeMapping) - : base(constantExpression.Type, typeMapping) + public SqlConstantExpression([NotNull] ConstantExpression constantExpression, [CanBeNull] RelationalTypeMapping typeMapping) + : base(Check.NotNull(constantExpression, nameof(constantExpression)).Type, typeMapping) { _constantExpression = constantExpression; } public virtual object Value => _constantExpression.Value; - public virtual SqlExpression ApplyTypeMapping(RelationalTypeMapping typeMapping) - => new SqlConstantExpression(_constantExpression, typeMapping); + public virtual SqlExpression ApplyTypeMapping([CanBeNull] RelationalTypeMapping typeMapping) + { + return new SqlConstantExpression(_constantExpression, typeMapping); + } - protected override Expression VisitChildren(ExpressionVisitor visitor) => this; - public override void Print(ExpressionPrinter expressionPrinter) => Print(Value, expressionPrinter); + protected override Expression VisitChildren(ExpressionVisitor visitor) + { + Check.NotNull(visitor, nameof(visitor)); + + return this; + } + + public override void Print(ExpressionPrinter expressionPrinter) + { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + + Print(Value, expressionPrinter); + } private void Print(object value, ExpressionPrinter expressionPrinter) => expressionPrinter.Append(TypeMapping?.GenerateSqlLiteral(value) ?? Value?.ToString() ?? "NULL"); diff --git a/src/EFCore.Relational/Query/SqlExpressions/SqlExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SqlExpression.cs index 57553c24164..d1796f2382e 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SqlExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SqlExpression.cs @@ -3,13 +3,14 @@ using System; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Storage; namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public abstract class SqlExpression : Expression, IPrintableExpression { - protected SqlExpression(Type type, RelationalTypeMapping typeMapping) + protected SqlExpression([NotNull] Type type, [CanBeNull] RelationalTypeMapping typeMapping) { Type = type; TypeMapping = typeMapping; diff --git a/src/EFCore.Relational/Query/SqlExpressions/SqlFragmentExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SqlFragmentExpression.cs index ebce1cb087b..ad0a14b5ab7 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SqlFragmentExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SqlFragmentExpression.cs @@ -3,23 +3,36 @@ using System; using System.Linq.Expressions; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class SqlFragmentExpression : SqlExpression { - public SqlFragmentExpression(string sql) + public SqlFragmentExpression([NotNull] string sql) : base(typeof(string), null) { + Check.NotEmpty(sql, nameof(sql)); + Sql = sql; } public virtual string Sql { get; } - protected override Expression VisitChildren(ExpressionVisitor visitor) => this; + protected override Expression VisitChildren(ExpressionVisitor visitor) + { + Check.NotNull(visitor, nameof(visitor)); + + return this; + } public override void Print(ExpressionPrinter expressionPrinter) - => expressionPrinter.Append(Sql); + { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + + expressionPrinter.Append(Sql); + } public override bool Equals(object obj) => obj != null diff --git a/src/EFCore.Relational/Query/SqlExpressions/SqlFunctionExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SqlFunctionExpression.cs index a96ba570ac7..e77848a02a9 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SqlFunctionExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SqlFunctionExpression.cs @@ -5,67 +5,111 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class SqlFunctionExpression : SqlExpression { public static SqlFunctionExpression CreateNiladic( - string name, - Type type, - RelationalTypeMapping typeMapping) - => new SqlFunctionExpression( + [NotNull] string name, + [NotNull] Type type, + [CanBeNull] RelationalTypeMapping typeMapping) + { + Check.NotEmpty(name, nameof(name)); + Check.NotNull(type, nameof(type)); + + return new SqlFunctionExpression( instance: null, schema: null, name, niladic: true, arguments: null, builtIn: true, type, typeMapping); + } public static SqlFunctionExpression CreateNiladic( - string schema, - string name, - Type type, - RelationalTypeMapping typeMapping) - => new SqlFunctionExpression(instance: null, schema, name, niladic: true, arguments: null, builtIn: true, type, typeMapping); + [NotNull] string schema, + [NotNull] string name, + [NotNull] Type type, + [CanBeNull] RelationalTypeMapping typeMapping) + { + Check.NotEmpty(name, nameof(name)); + Check.NotEmpty(schema, nameof(schema)); + Check.NotNull(type, nameof(type)); + + return new SqlFunctionExpression( + instance: null, schema, name, niladic: true, arguments: null, builtIn: true, type, typeMapping); + } public static SqlFunctionExpression CreateNiladic( - SqlExpression instance, - string name, - Type type, - RelationalTypeMapping typeMapping) - => new SqlFunctionExpression(instance, schema: null, name, niladic: true, arguments: null, builtIn: true, type, typeMapping); + [NotNull] SqlExpression instance, + [NotNull] string name, + [NotNull] Type type, + [CanBeNull] RelationalTypeMapping typeMapping) + { + Check.NotNull(instance, nameof(instance)); + Check.NotEmpty(name, nameof(name)); + Check.NotNull(type, nameof(type)); + + return new SqlFunctionExpression( + instance, schema: null, name, niladic: true, arguments: null, builtIn: true, type, typeMapping); + } public static SqlFunctionExpression Create( - SqlExpression instance, - string name, - IEnumerable arguments, - Type type, - RelationalTypeMapping typeMapping) - => new SqlFunctionExpression(instance, schema: null, name, niladic: false, arguments, builtIn: true, type, typeMapping); + [NotNull] SqlExpression instance, + [NotNull] string name, + [NotNull] IEnumerable arguments, + [NotNull] Type type, + [CanBeNull] RelationalTypeMapping typeMapping) + { + Check.NotNull(instance, nameof(instance)); + Check.NotEmpty(name, nameof(name)); + Check.NotNull(arguments, nameof(arguments)); + Check.NotNull(type, nameof(type)); + + return new SqlFunctionExpression(instance, schema: null, name, niladic: false, arguments, builtIn: true, type, typeMapping); + } public static SqlFunctionExpression Create( - string name, - IEnumerable arguments, - Type type, - RelationalTypeMapping typeMapping) - => new SqlFunctionExpression(instance: null, schema: null, name, niladic: false, arguments, builtIn: true, type, typeMapping); + [NotNull] string name, + [NotNull] IEnumerable arguments, + [NotNull] Type type, + [CanBeNull] RelationalTypeMapping typeMapping) + { + Check.NotEmpty(name, nameof(name)); + Check.NotNull(arguments, nameof(arguments)); + Check.NotNull(type, nameof(type)); + + return new SqlFunctionExpression( + instance: null, schema: null, name, niladic: false, arguments, builtIn: true, type, typeMapping); + } public static SqlFunctionExpression Create( - string schema, - string name, - IEnumerable arguments, - Type type, - RelationalTypeMapping typeMapping) - => new SqlFunctionExpression(instance: null, schema, name, niladic: false, arguments, builtIn: false, type, typeMapping); + [CanBeNull] string schema, + [NotNull] string name, + [NotNull] IEnumerable arguments, + [NotNull] Type type, + [CanBeNull] RelationalTypeMapping typeMapping) + { + Check.NotEmpty(name, nameof(name)); + Check.NotNull(arguments, nameof(arguments)); + Check.NotNull(type, nameof(type)); + + return new SqlFunctionExpression(instance: null, schema, name, niladic: false, arguments, builtIn: false, type, typeMapping); + } public SqlFunctionExpression( - SqlExpression instance, - string schema, - string name, + [CanBeNull] SqlExpression instance, + [CanBeNull] string schema, + [NotNull] string name, bool niladic, - IEnumerable arguments, + [CanBeNull] IEnumerable arguments, bool builtIn, - Type type, - RelationalTypeMapping typeMapping) + [NotNull] Type type, + [CanBeNull] RelationalTypeMapping typeMapping) : base(type, typeMapping) { + Check.NotEmpty(name, nameof(name)); + Check.NotNull(type, nameof(type)); + Instance = instance; Name = name; Schema = schema; @@ -83,6 +127,8 @@ public SqlFunctionExpression( protected override Expression VisitChildren(ExpressionVisitor visitor) { + Check.NotNull(visitor, nameof(visitor)); + var changed = false; var instance = (SqlExpression)visitor.Visit(Instance); changed |= instance != Instance; @@ -106,7 +152,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) : this; } - public virtual SqlFunctionExpression ApplyTypeMapping(RelationalTypeMapping typeMapping) + public virtual SqlFunctionExpression ApplyTypeMapping([CanBeNull] RelationalTypeMapping typeMapping) => new SqlFunctionExpression( Instance, Schema, @@ -117,13 +163,17 @@ public virtual SqlFunctionExpression ApplyTypeMapping(RelationalTypeMapping type Type, typeMapping ?? TypeMapping); - public virtual SqlFunctionExpression Update(SqlExpression instance, IReadOnlyList arguments) - => instance != Instance || !arguments.SequenceEqual(Arguments) + public virtual SqlFunctionExpression Update([CanBeNull] SqlExpression instance, [CanBeNull] IReadOnlyList arguments) + { + return instance != Instance || !arguments.SequenceEqual(Arguments) ? new SqlFunctionExpression(instance, Schema, Name, IsNiladic, arguments, IsBuiltIn, Type, TypeMapping) : this; + } public override void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + if (!string.IsNullOrEmpty(Schema)) { expressionPrinter.Append(Schema).Append(".").Append(Name); diff --git a/src/EFCore.Relational/Query/SqlExpressions/SqlParameterExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SqlParameterExpression.cs index dfaa26512c2..0610b34ca10 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SqlParameterExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SqlParameterExpression.cs @@ -3,7 +3,9 @@ using System; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { @@ -20,13 +22,24 @@ internal SqlParameterExpression(ParameterExpression parameterExpression, Relatio public string Name => _parameterExpression.Name; - public SqlExpression ApplyTypeMapping(RelationalTypeMapping typeMapping) - => new SqlParameterExpression(_parameterExpression, typeMapping); + public SqlExpression ApplyTypeMapping([CanBeNull] RelationalTypeMapping typeMapping) + { + return new SqlParameterExpression(_parameterExpression, typeMapping); + } + + protected override Expression VisitChildren(ExpressionVisitor visitor) + { + Check.NotNull(visitor, nameof(visitor)); - protected override Expression VisitChildren(ExpressionVisitor visitor) => this; + return this; + } public override void Print(ExpressionPrinter expressionPrinter) - => expressionPrinter.Append("@" + _parameterExpression.Name); + { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + + expressionPrinter.Append("@" + _parameterExpression.Name); + } public override bool Equals(object obj) => obj != null diff --git a/src/EFCore.Relational/Query/SqlExpressions/SqlUnaryExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SqlUnaryExpression.cs index 1e786605a2b..67fb437d42d 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SqlUnaryExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SqlUnaryExpression.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; @@ -27,12 +28,14 @@ private static ExpressionType VerifyOperator(ExpressionType operatorType) public SqlUnaryExpression( ExpressionType operatorType, - SqlExpression operand, - Type type, - RelationalTypeMapping typeMapping) + [NotNull] SqlExpression operand, + [NotNull] Type type, + [CanBeNull] RelationalTypeMapping typeMapping) : base(type, typeMapping) { Check.NotNull(operand, nameof(operand)); + Check.NotNull(type, nameof(type)); + OperatorType = VerifyOperator(operatorType); Operand = operand; } @@ -41,15 +44,25 @@ public SqlUnaryExpression( public virtual SqlExpression Operand { get; } protected override Expression VisitChildren(ExpressionVisitor visitor) - => Update((SqlExpression)visitor.Visit(Operand)); + { + Check.NotNull(visitor, nameof(visitor)); - public virtual SqlUnaryExpression Update(SqlExpression operand) - => operand != Operand + return Update((SqlExpression)visitor.Visit(Operand)); + } + + public virtual SqlUnaryExpression Update([NotNull] SqlExpression operand) + { + Check.NotNull(operand, nameof(operand)); + + return operand != Operand ? new SqlUnaryExpression(OperatorType, operand, Type, TypeMapping) : this; + } public override void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + if (OperatorType == ExpressionType.Convert) { expressionPrinter.Append("CAST("); diff --git a/src/EFCore.Relational/Query/SqlExpressions/TableExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/TableExpression.cs index d8e8468c9ff..427897a1806 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/TableExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/TableExpression.cs @@ -3,6 +3,7 @@ using System; using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { @@ -18,6 +19,8 @@ internal TableExpression(string name, string schema, [NotNull] string alias) public override void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + if (!string.IsNullOrEmpty(Schema)) { expressionPrinter.Append(Schema).Append("."); diff --git a/src/EFCore.Relational/Query/SqlExpressions/TableExpressionBase.cs b/src/EFCore.Relational/Query/SqlExpressions/TableExpressionBase.cs index bdf98e7b6d0..2d7bb42ce32 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/TableExpressionBase.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/TableExpressionBase.cs @@ -19,7 +19,12 @@ protected TableExpressionBase([CanBeNull] string alias) public virtual string Alias { get; internal set; } - protected override Expression VisitChildren(ExpressionVisitor visitor) => this; + protected override Expression VisitChildren(ExpressionVisitor visitor) + { + Check.NotNull(visitor, nameof(visitor)); + + return this; + } public override Type Type => typeof(object); public sealed override ExpressionType NodeType => ExpressionType.Extension; diff --git a/src/EFCore.Relational/Query/SqlExpressions/UnionExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/UnionExpression.cs index 0614ed279cf..7420b4b122b 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/UnionExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/UnionExpression.cs @@ -3,31 +3,46 @@ using System; using System.Linq.Expressions; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class UnionExpression : SetOperationBase { - public UnionExpression(string alias, SelectExpression source1, SelectExpression source2, bool distinct) + public UnionExpression( + [NotNull] string alias, + [NotNull] SelectExpression source1, + [NotNull] SelectExpression source2, + bool distinct) : base(alias, source1, source2, distinct) { } protected override Expression VisitChildren(ExpressionVisitor visitor) { + Check.NotNull(visitor, nameof(visitor)); + var source1 = (SelectExpression)visitor.Visit(Source1); var source2 = (SelectExpression)visitor.Visit(Source2); return Update(source1, source2); } - public virtual UnionExpression Update(SelectExpression source1, SelectExpression source2) - => source1 != Source1 || source2 != Source2 + public virtual UnionExpression Update([NotNull] SelectExpression source1, [NotNull] SelectExpression source2) + { + Check.NotNull(source1, nameof(source1)); + Check.NotNull(source2, nameof(source2)); + + return source1 != Source1 || source2 != Source2 ? new UnionExpression(Alias, source1, source2, IsDistinct) : this; + } public override void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.Append("("); using (expressionPrinter.Indent()) { diff --git a/src/EFCore.Relational/Storage/RelationalGeometryTypeMapping.cs b/src/EFCore.Relational/Storage/RelationalGeometryTypeMapping.cs index bf8989d2b0b..d1482473c26 100644 --- a/src/EFCore.Relational/Storage/RelationalGeometryTypeMapping.cs +++ b/src/EFCore.Relational/Storage/RelationalGeometryTypeMapping.cs @@ -40,7 +40,7 @@ protected RelationalGeometryTypeMapping( /// The converter to use when converting to and from database types. protected RelationalGeometryTypeMapping( RelationalTypeMappingParameters parameters, - ValueConverter converter) + [CanBeNull] ValueConverter converter) : base(parameters) { SpatialConverter = converter; diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMemberTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMemberTranslator.cs index 05454cbc997..86843c9cc17 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMemberTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMemberTranslator.cs @@ -3,8 +3,10 @@ using System; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal @@ -14,13 +16,16 @@ public class SqlServerGeometryCollectionMemberTranslator : IMemberTranslator private static readonly MemberInfo _count = typeof(GeometryCollection).GetRuntimeProperty(nameof(GeometryCollection.Count)); private readonly ISqlExpressionFactory _sqlExpressionFactory; - public SqlServerGeometryCollectionMemberTranslator(ISqlExpressionFactory sqlExpressionFactory) + public SqlServerGeometryCollectionMemberTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { + Check.NotNull(member, nameof(member)); + Check.NotNull(returnType, nameof(returnType)); + if (Equals(member, _count)) { return _sqlExpressionFactory.Function( diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMethodTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMethodTranslator.cs index 3ad63a18097..60d1b3f4e2b 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMethodTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMethodTranslator.cs @@ -3,9 +3,11 @@ using System.Collections.Generic; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal @@ -17,8 +19,8 @@ public class SqlServerGeometryCollectionMethodTranslator : IMethodCallTranslator private readonly ISqlExpressionFactory _sqlExpressionFactory; public SqlServerGeometryCollectionMethodTranslator( - IRelationalTypeMappingSource typeMappingSource, - ISqlExpressionFactory sqlExpressionFactory) + [NotNull] IRelationalTypeMappingSource typeMappingSource, + [NotNull] ISqlExpressionFactory sqlExpressionFactory) { _typeMappingSource = typeMappingSource; _sqlExpressionFactory = sqlExpressionFactory; @@ -26,6 +28,9 @@ public SqlServerGeometryCollectionMethodTranslator( public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { + Check.NotNull(method, nameof(method)); + Check.NotNull(arguments, nameof(arguments)); + if (Equals(method, _item)) { return _sqlExpressionFactory.Function( diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMemberTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMemberTranslator.cs index 3ae8a7a77bd..1ac5464828d 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMemberTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMemberTranslator.cs @@ -5,9 +5,11 @@ using System.Collections.Generic; using System.Diagnostics; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal @@ -43,8 +45,8 @@ public class SqlServerGeometryMemberTranslator : IMemberTranslator private readonly ISqlExpressionFactory _sqlExpressionFactory; public SqlServerGeometryMemberTranslator( - IRelationalTypeMappingSource typeMappingSource, - ISqlExpressionFactory sqlExpressionFactory) + [NotNull] IRelationalTypeMappingSource typeMappingSource, + [NotNull] ISqlExpressionFactory sqlExpressionFactory) { _typeMappingSource = typeMappingSource; _sqlExpressionFactory = sqlExpressionFactory; @@ -52,6 +54,9 @@ public SqlServerGeometryMemberTranslator( public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { + Check.NotNull(member, nameof(member)); + Check.NotNull(returnType, nameof(returnType)); + if (typeof(Geometry).IsAssignableFrom(member.DeclaringType)) { Debug.Assert(instance.TypeMapping != null, "Instance must have typeMapping assigned."); diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMethodTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMethodTranslator.cs index e8f61922d03..ea880868bef 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMethodTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMethodTranslator.cs @@ -6,9 +6,11 @@ using System.Diagnostics; using System.Linq; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal @@ -53,8 +55,8 @@ public class SqlServerGeometryMethodTranslator : IMethodCallTranslator private readonly ISqlExpressionFactory _sqlExpressionFactory; public SqlServerGeometryMethodTranslator( - IRelationalTypeMappingSource typeMappingSource, - ISqlExpressionFactory sqlExpressionFactory) + [NotNull] IRelationalTypeMappingSource typeMappingSource, + [NotNull] ISqlExpressionFactory sqlExpressionFactory) { _typeMappingSource = typeMappingSource; _sqlExpressionFactory = sqlExpressionFactory; @@ -62,6 +64,9 @@ public SqlServerGeometryMethodTranslator( public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { + Check.NotNull(method, nameof(method)); + Check.NotNull(arguments, nameof(arguments)); + if (typeof(Geometry).IsAssignableFrom(method.DeclaringType)) { var geometryExpressions = new[] { instance }.Concat( diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMemberTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMemberTranslator.cs index 93bd4f35ac5..96ffaf203a5 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMemberTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMemberTranslator.cs @@ -6,9 +6,11 @@ using System.Diagnostics; using System.Linq; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal @@ -28,8 +30,8 @@ public class SqlServerLineStringMemberTranslator : IMemberTranslator private readonly ISqlExpressionFactory _sqlExpressionFactory; public SqlServerLineStringMemberTranslator( - IRelationalTypeMappingSource typeMappingSource, - ISqlExpressionFactory sqlExpressionFactory) + [NotNull] IRelationalTypeMappingSource typeMappingSource, + [NotNull] ISqlExpressionFactory sqlExpressionFactory) { _typeMappingSource = typeMappingSource; _sqlExpressionFactory = sqlExpressionFactory; @@ -37,6 +39,9 @@ public SqlServerLineStringMemberTranslator( public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { + Check.NotNull(member, nameof(member)); + Check.NotNull(returnType, nameof(returnType)); + if (_memberToFunctionName.TryGetValue(member, out var functionName)) { Debug.Assert(instance.TypeMapping != null, "Instance must have typeMapping assigned."); diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMethodTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMethodTranslator.cs index 24a2a89fb4d..1595a98cb0c 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMethodTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMethodTranslator.cs @@ -3,9 +3,11 @@ using System.Collections.Generic; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal @@ -19,8 +21,8 @@ public class SqlServerLineStringMethodTranslator : IMethodCallTranslator private readonly ISqlExpressionFactory _sqlExpressionFactory; public SqlServerLineStringMethodTranslator( - IRelationalTypeMappingSource typeMappingSource, - ISqlExpressionFactory sqlExpressionFactory) + [NotNull] IRelationalTypeMappingSource typeMappingSource, + [NotNull] ISqlExpressionFactory sqlExpressionFactory) { _typeMappingSource = typeMappingSource; _sqlExpressionFactory = sqlExpressionFactory; @@ -28,6 +30,9 @@ public SqlServerLineStringMethodTranslator( public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { + Check.NotNull(method, nameof(method)); + Check.NotNull(arguments, nameof(arguments)); + if (Equals(method, _getPointN)) { return _sqlExpressionFactory.Function( diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerMultiLineStringMemberTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerMultiLineStringMemberTranslator.cs index d690083b98f..efdb59fb223 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerMultiLineStringMemberTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerMultiLineStringMemberTranslator.cs @@ -3,8 +3,10 @@ using System; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal @@ -14,13 +16,16 @@ public class SqlServerMultiLineStringMemberTranslator : IMemberTranslator private static readonly MemberInfo _isClosed = typeof(MultiLineString).GetRuntimeProperty(nameof(MultiLineString.IsClosed)); private readonly ISqlExpressionFactory _sqlExpressionFactory; - public SqlServerMultiLineStringMemberTranslator(ISqlExpressionFactory sqlExpressionFactory) + public SqlServerMultiLineStringMemberTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { + Check.NotNull(member, nameof(member)); + Check.NotNull(returnType, nameof(returnType)); + if (Equals(member, _isClosed)) { return _sqlExpressionFactory.Function( diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteMemberTranslatorPlugin.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteMemberTranslatorPlugin.cs index def42d6ee06..8ad887a52a2 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteMemberTranslatorPlugin.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteMemberTranslatorPlugin.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.Extensions.DependencyInjection; @@ -30,7 +31,7 @@ public class SqlServerNetTopologySuiteMemberTranslatorPlugin : IMemberTranslator /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public SqlServerNetTopologySuiteMemberTranslatorPlugin( - IRelationalTypeMappingSource typeMappingSource, ISqlExpressionFactory sqlExpressionFactory) + [NotNull] IRelationalTypeMappingSource typeMappingSource, [NotNull] ISqlExpressionFactory sqlExpressionFactory) { Translators = new IMemberTranslator[] { diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteMethodCallTranslatorPlugin.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteMethodCallTranslatorPlugin.cs index 7c2dcb3d682..0aef5a342eb 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteMethodCallTranslatorPlugin.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteMethodCallTranslatorPlugin.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.Extensions.DependencyInjection; @@ -31,8 +32,8 @@ public class SqlServerNetTopologySuiteMethodCallTranslatorPlugin : IMethodCallTr /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public SqlServerNetTopologySuiteMethodCallTranslatorPlugin( - IRelationalTypeMappingSource typeMappingSource, - ISqlExpressionFactory sqlExpressionFactory) + [NotNull] IRelationalTypeMappingSource typeMappingSource, + [NotNull] ISqlExpressionFactory sqlExpressionFactory) { Translators = new IMethodCallTranslator[] { diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMemberTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMemberTranslator.cs index bb322147920..cdcb69061fd 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMemberTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMemberTranslator.cs @@ -5,9 +5,11 @@ using System.Collections.Generic; using System.Diagnostics; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal @@ -26,8 +28,8 @@ public class SqlServerPolygonMemberTranslator : IMemberTranslator private readonly ISqlExpressionFactory _sqlExpressionFactory; public SqlServerPolygonMemberTranslator( - IRelationalTypeMappingSource typeMappingSource, - ISqlExpressionFactory sqlExpressionFactory) + [NotNull] IRelationalTypeMappingSource typeMappingSource, + [NotNull] ISqlExpressionFactory sqlExpressionFactory) { _typeMappingSource = typeMappingSource; _sqlExpressionFactory = sqlExpressionFactory; @@ -35,6 +37,9 @@ public SqlServerPolygonMemberTranslator( public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { + Check.NotNull(member, nameof(member)); + Check.NotNull(returnType, nameof(returnType)); + if (typeof(Polygon).IsAssignableFrom(member.DeclaringType)) { Debug.Assert(instance.TypeMapping != null, "Instance must have typeMapping assigned."); diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMethodTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMethodTranslator.cs index 0004f871e2e..7dcfd0409c3 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMethodTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMethodTranslator.cs @@ -4,9 +4,11 @@ using System; using System.Collections.Generic; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal @@ -20,8 +22,8 @@ public class SqlServerPolygonMethodTranslator : IMethodCallTranslator private readonly ISqlExpressionFactory _sqlExpressionFactory; public SqlServerPolygonMethodTranslator( - IRelationalTypeMappingSource typeMappingSource, - ISqlExpressionFactory sqlExpressionFactory) + [NotNull] IRelationalTypeMappingSource typeMappingSource, + [NotNull] ISqlExpressionFactory sqlExpressionFactory) { _typeMappingSource = typeMappingSource; _sqlExpressionFactory = sqlExpressionFactory; @@ -29,6 +31,9 @@ public SqlServerPolygonMethodTranslator( public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { + Check.NotNull(method, nameof(method)); + Check.NotNull(arguments, nameof(arguments)); + if (Equals(method, _getInteriorRingN)) { var storeType = instance.TypeMapping.StoreType; diff --git a/src/EFCore.SqlServer.NTS/Storage/Internal/SqlServerGeometryTypeMapping.cs b/src/EFCore.SqlServer.NTS/Storage/Internal/SqlServerGeometryTypeMapping.cs index 2ee0ddf2c5c..c7b0c8353fe 100644 --- a/src/EFCore.SqlServer.NTS/Storage/Internal/SqlServerGeometryTypeMapping.cs +++ b/src/EFCore.SqlServer.NTS/Storage/Internal/SqlServerGeometryTypeMapping.cs @@ -44,7 +44,7 @@ private static readonly MethodInfo _getSqlBytes /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [UsedImplicitly] - public SqlServerGeometryTypeMapping(NtsGeometryServices geometryServices, string storeType) + public SqlServerGeometryTypeMapping([NotNull] NtsGeometryServices geometryServices, [NotNull] string storeType) : base( new GeometryValueConverter( CreateReader(geometryServices, IsGeography(storeType)), @@ -60,7 +60,7 @@ public SqlServerGeometryTypeMapping(NtsGeometryServices geometryServices, string /// protected SqlServerGeometryTypeMapping( RelationalTypeMappingParameters parameters, - ValueConverter converter) + [CanBeNull] ValueConverter converter) : base(parameters, converter) { _isGeography = IsGeography(StoreType); diff --git a/src/EFCore.SqlServer.NTS/Storage/ValueConversion/Internal/GeometryValueConverter.cs b/src/EFCore.SqlServer.NTS/Storage/ValueConversion/Internal/GeometryValueConverter.cs index 6e75cbe38d6..2bd23aa8527 100644 --- a/src/EFCore.SqlServer.NTS/Storage/ValueConversion/Internal/GeometryValueConverter.cs +++ b/src/EFCore.SqlServer.NTS/Storage/ValueConversion/Internal/GeometryValueConverter.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Data.SqlTypes; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using NetTopologySuite.Geometries; using NetTopologySuite.IO; @@ -23,7 +24,7 @@ public class GeometryValueConverter : ValueConverter - public GeometryValueConverter(SqlServerBytesReader reader, SqlServerBytesWriter writer) + public GeometryValueConverter([NotNull] SqlServerBytesReader reader, [NotNull] SqlServerBytesWriter writer) : base( g => new SqlBytes(writer.Write(g)), b => (TGeometry)reader.Read(b.Value)) diff --git a/src/EFCore.SqlServer/Query/Internal/SearchConditionConvertingExpressionVisitor.cs b/src/EFCore.SqlServer/Query/Internal/SearchConditionConvertingExpressionVisitor.cs index f578fc5166b..685999152bc 100644 --- a/src/EFCore.SqlServer/Query/Internal/SearchConditionConvertingExpressionVisitor.cs +++ b/src/EFCore.SqlServer/Query/Internal/SearchConditionConvertingExpressionVisitor.cs @@ -4,9 +4,11 @@ using System; using System.Collections.Generic; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { @@ -16,7 +18,7 @@ public class SearchConditionConvertingExpressionVisitor : SqlExpressionVisitor private readonly ISqlExpressionFactory _sqlExpressionFactory; public SearchConditionConvertingExpressionVisitor( - ISqlExpressionFactory sqlExpressionFactory) + [NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } @@ -52,6 +54,8 @@ private SqlExpression BuildCompareToExpression(SqlExpression sqlExpression) protected override Expression VisitCase(CaseExpression caseExpression) { + Check.NotNull(caseExpression, nameof(caseExpression)); + var parentSearchCondition = _isSearchCondition; var testIsCondition = caseExpression.Operand == null; @@ -77,11 +81,15 @@ protected override Expression VisitCase(CaseExpression caseExpression) protected override Expression VisitColumn(ColumnExpression columnExpression) { + Check.NotNull(columnExpression, nameof(columnExpression)); + return ApplyConversion(columnExpression, condition: false); } protected override Expression VisitExists(ExistsExpression existsExpression) { + Check.NotNull(existsExpression, nameof(existsExpression)); + var parentSearchCondition = _isSearchCondition; _isSearchCondition = false; var subquery = (SelectExpression)Visit(existsExpression.Subquery); @@ -91,10 +99,16 @@ protected override Expression VisitExists(ExistsExpression existsExpression) } protected override Expression VisitFromSql(FromSqlExpression fromSqlExpression) - => fromSqlExpression; + { + Check.NotNull(fromSqlExpression, nameof(fromSqlExpression)); + + return fromSqlExpression; + } protected override Expression VisitIn(InExpression inExpression) { + Check.NotNull(inExpression, nameof(inExpression)); + var parentSearchCondition = _isSearchCondition; _isSearchCondition = false; @@ -108,6 +122,8 @@ protected override Expression VisitIn(InExpression inExpression) protected override Expression VisitLike(LikeExpression likeExpression) { + Check.NotNull(likeExpression, nameof(likeExpression)); + var parentSearchCondition = _isSearchCondition; _isSearchCondition = false; var match = (SqlExpression)Visit(likeExpression.Match); @@ -120,6 +136,8 @@ protected override Expression VisitLike(LikeExpression likeExpression) protected override Expression VisitSelect(SelectExpression selectExpression) { + Check.NotNull(selectExpression, nameof(selectExpression)); + var changed = false; var parentSearchCondition = _isSearchCondition; @@ -183,6 +201,8 @@ protected override Expression VisitSelect(SelectExpression selectExpression) protected override Expression VisitSqlBinary(SqlBinaryExpression sqlBinaryExpression) { + Check.NotNull(sqlBinaryExpression, nameof(sqlBinaryExpression)); + var parentIsSearchCondition = _isSearchCondition; switch (sqlBinaryExpression.OperatorType) @@ -217,6 +237,8 @@ protected override Expression VisitSqlBinary(SqlBinaryExpression sqlBinaryExpres protected override Expression VisitSqlUnary(SqlUnaryExpression sqlUnaryExpression) { + Check.NotNull(sqlUnaryExpression, nameof(sqlUnaryExpression)); + var parentSearchCondition = _isSearchCondition; bool resultCondition; switch (sqlUnaryExpression.OperatorType) @@ -258,14 +280,22 @@ when sqlUnaryExpression.IsLogicalNot(): protected override Expression VisitSqlConstant(SqlConstantExpression sqlConstantExpression) { + Check.NotNull(sqlConstantExpression, nameof(sqlConstantExpression)); + return ApplyConversion(sqlConstantExpression, condition: false); } protected override Expression VisitSqlFragment(SqlFragmentExpression sqlFragmentExpression) - => sqlFragmentExpression; + { + Check.NotNull(sqlFragmentExpression, nameof(sqlFragmentExpression)); + + return sqlFragmentExpression; + } protected override Expression VisitSqlFunction(SqlFunctionExpression sqlFunctionExpression) { + Check.NotNull(sqlFunctionExpression, nameof(sqlFunctionExpression)); + var parentSearchCondition = _isSearchCondition; _isSearchCondition = false; var instance = (SqlExpression)Visit(sqlFunctionExpression.Instance); @@ -286,14 +316,22 @@ protected override Expression VisitSqlFunction(SqlFunctionExpression sqlFunction protected override Expression VisitSqlParameter(SqlParameterExpression sqlParameterExpression) { + Check.NotNull(sqlParameterExpression, nameof(sqlParameterExpression)); + return ApplyConversion(sqlParameterExpression, condition: false); } protected override Expression VisitTable(TableExpression tableExpression) - => tableExpression; + { + Check.NotNull(tableExpression, nameof(tableExpression)); + + return tableExpression; + } protected override Expression VisitProjection(ProjectionExpression projectionExpression) { + Check.NotNull(projectionExpression, nameof(projectionExpression)); + var expression = (SqlExpression)Visit(projectionExpression.Expression); return projectionExpression.Update(expression); @@ -301,6 +339,8 @@ protected override Expression VisitProjection(ProjectionExpression projectionExp protected override Expression VisitOrdering(OrderingExpression orderingExpression) { + Check.NotNull(orderingExpression, nameof(orderingExpression)); + var expression = (SqlExpression)Visit(orderingExpression.Expression); return orderingExpression.Update(expression); @@ -308,6 +348,8 @@ protected override Expression VisitOrdering(OrderingExpression orderingExpressio protected override Expression VisitCrossJoin(CrossJoinExpression crossJoinExpression) { + Check.NotNull(crossJoinExpression, nameof(crossJoinExpression)); + var parentSearchCondition = _isSearchCondition; _isSearchCondition = false; var table = (TableExpressionBase)Visit(crossJoinExpression.Table); @@ -318,6 +360,8 @@ protected override Expression VisitCrossJoin(CrossJoinExpression crossJoinExpres protected override Expression VisitCrossApply(CrossApplyExpression crossApplyExpression) { + Check.NotNull(crossApplyExpression, nameof(crossApplyExpression)); + var parentSearchCondition = _isSearchCondition; _isSearchCondition = false; var table = (TableExpressionBase)Visit(crossApplyExpression.Table); @@ -328,6 +372,8 @@ protected override Expression VisitCrossApply(CrossApplyExpression crossApplyExp protected override Expression VisitOuterApply(OuterApplyExpression outerApplyExpression) { + Check.NotNull(outerApplyExpression, nameof(outerApplyExpression)); + var parentSearchCondition = _isSearchCondition; _isSearchCondition = false; var table = (TableExpressionBase)Visit(outerApplyExpression.Table); @@ -338,6 +384,8 @@ protected override Expression VisitOuterApply(OuterApplyExpression outerApplyExp protected override Expression VisitInnerJoin(InnerJoinExpression innerJoinExpression) { + Check.NotNull(innerJoinExpression, nameof(innerJoinExpression)); + var parentSearchCondition = _isSearchCondition; _isSearchCondition = false; var table = (TableExpressionBase)Visit(innerJoinExpression.Table); @@ -350,6 +398,8 @@ protected override Expression VisitInnerJoin(InnerJoinExpression innerJoinExpres protected override Expression VisitLeftJoin(LeftJoinExpression leftJoinExpression) { + Check.NotNull(leftJoinExpression, nameof(leftJoinExpression)); + var parentSearchCondition = _isSearchCondition; _isSearchCondition = false; var table = (TableExpressionBase)Visit(leftJoinExpression.Table); @@ -362,6 +412,8 @@ protected override Expression VisitLeftJoin(LeftJoinExpression leftJoinExpressio protected override Expression VisitScalarSubquery(ScalarSubqueryExpression scalarSubqueryExpression) { + Check.NotNull(scalarSubqueryExpression, nameof(scalarSubqueryExpression)); + var parentSearchCondition = _isSearchCondition; var subquery = (SelectExpression)Visit(scalarSubqueryExpression.Subquery); _isSearchCondition = parentSearchCondition; @@ -371,6 +423,8 @@ protected override Expression VisitScalarSubquery(ScalarSubqueryExpression scala protected override Expression VisitRowNumber(RowNumberExpression rowNumberExpression) { + Check.NotNull(rowNumberExpression, nameof(rowNumberExpression)); + var parentSearchCondition = _isSearchCondition; _isSearchCondition = false; var changed = false; @@ -397,6 +451,8 @@ protected override Expression VisitRowNumber(RowNumberExpression rowNumberExpres protected override Expression VisitExcept(ExceptExpression exceptExpression) { + Check.NotNull(exceptExpression, nameof(exceptExpression)); + var parentSearchCondition = _isSearchCondition; _isSearchCondition = false; var source1 = (SelectExpression)Visit(exceptExpression.Source1); @@ -408,6 +464,8 @@ protected override Expression VisitExcept(ExceptExpression exceptExpression) protected override Expression VisitIntersect(IntersectExpression intersectExpression) { + Check.NotNull(intersectExpression, nameof(intersectExpression)); + var parentSearchCondition = _isSearchCondition; _isSearchCondition = false; var source1 = (SelectExpression)Visit(intersectExpression.Source1); @@ -419,6 +477,8 @@ protected override Expression VisitIntersect(IntersectExpression intersectExpres protected override Expression VisitUnion(UnionExpression unionExpression) { + Check.NotNull(unionExpression, nameof(unionExpression)); + var parentSearchCondition = _isSearchCondition; _isSearchCondition = false; var source1 = (SelectExpression)Visit(unionExpression.Source1); diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerByteArrayMethodTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerByteArrayMethodTranslator.cs index e83212f00f9..b05fe5ed68c 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerByteArrayMethodTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerByteArrayMethodTranslator.cs @@ -3,8 +3,12 @@ using System.Collections.Generic; using System.Reflection; +using System.Text; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { @@ -12,13 +16,16 @@ public class SqlServerByteArrayMethodTranslator : IMethodCallTranslator { private readonly ISqlExpressionFactory _sqlExpressionFactory; - public SqlServerByteArrayMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) + public SqlServerByteArrayMethodTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { + Check.NotNull(method, nameof(method)); + Check.NotNull(arguments, nameof(arguments)); + if (method.IsGenericMethod && method.GetGenericMethodDefinition().Equals(EnumerableMethods.Contains) && arguments[0].Type == typeof(byte[])) diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerConvertTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerConvertTranslator.cs index 42436ca7015..0097d6431ed 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerConvertTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerConvertTranslator.cs @@ -5,8 +5,10 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { @@ -46,13 +48,16 @@ private static readonly IEnumerable _supportedMethods private readonly ISqlExpressionFactory _sqlExpressionFactory; - public SqlServerConvertTranslator(ISqlExpressionFactory sqlExpressionFactory) + public SqlServerConvertTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { + Check.NotNull(method, nameof(method)); + Check.NotNull(arguments, nameof(arguments)); + return _supportedMethods.Contains(method) ? _sqlExpressionFactory.Function( "CONVERT", diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerDateDiffFunctionsTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerDateDiffFunctionsTranslator.cs index 54aa874590e..2109771d9ff 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerDateDiffFunctionsTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerDateDiffFunctionsTranslator.cs @@ -4,8 +4,10 @@ using System; using System.Collections.Generic; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { @@ -331,13 +333,16 @@ private readonly Dictionary _methodInfoDateDiffMapping private readonly ISqlExpressionFactory _sqlExpressionFactory; public SqlServerDateDiffFunctionsTranslator( - ISqlExpressionFactory sqlExpressionFactory) + [NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { + Check.NotNull(method, nameof(method)); + Check.NotNull(arguments, nameof(arguments)); + if (_methodInfoDateDiffMapping.TryGetValue(method, out var datePart)) { var startDate = arguments[1]; diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeMemberTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeMemberTranslator.cs index 293036b5fa5..80786705a11 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeMemberTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeMemberTranslator.cs @@ -4,8 +4,10 @@ using System; using System.Collections.Generic; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { @@ -26,13 +28,16 @@ private static readonly Dictionary _datePartMapping private readonly ISqlExpressionFactory _sqlExpressionFactory; - public SqlServerDateTimeMemberTranslator(ISqlExpressionFactory sqlExpressionFactory) + public SqlServerDateTimeMemberTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { + Check.NotNull(member, nameof(member)); + Check.NotNull(returnType, nameof(returnType)); + var declaringType = member.DeclaringType; if (declaringType == typeof(DateTime) diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeMethodTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeMethodTranslator.cs index 3c5eeb4bfe3..bc2e39a63d3 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeMethodTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeMethodTranslator.cs @@ -4,8 +4,10 @@ using System; using System.Collections.Generic; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { @@ -31,14 +33,16 @@ public class SqlServerDateTimeMethodTranslator : IMethodCallTranslator private readonly ISqlExpressionFactory _sqlExpressionFactory; - public SqlServerDateTimeMethodTranslator( - ISqlExpressionFactory sqlExpressionFactory) + public SqlServerDateTimeMethodTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { + Check.NotNull(method, nameof(method)); + Check.NotNull(arguments, nameof(arguments)); + if (_methodInfoDatePartMapping.TryGetValue(method, out var datePart)) { return !datePart.Equals("year") diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerFullTextSearchFunctionsTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerFullTextSearchFunctionsTranslator.cs index b63a5c41194..ba01e1ae470 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerFullTextSearchFunctionsTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerFullTextSearchFunctionsTranslator.cs @@ -4,9 +4,11 @@ using System; using System.Collections.Generic; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.SqlServer.Internal; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { @@ -46,14 +48,16 @@ private static readonly IDictionary _functionMapping private readonly ISqlExpressionFactory _sqlExpressionFactory; - public SqlServerFullTextSearchFunctionsTranslator( - ISqlExpressionFactory sqlExpressionFactory) + public SqlServerFullTextSearchFunctionsTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { + Check.NotNull(method, nameof(method)); + Check.NotNull(arguments, nameof(arguments)); + if (_functionMapping.TryGetValue(method, out var functionName)) { var propertyReference = arguments[1]; diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerIsDateFunctionTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerIsDateFunctionTranslator.cs index 18f0c004fee..0059fd0d141 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerIsDateFunctionTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerIsDateFunctionTranslator.cs @@ -3,8 +3,10 @@ using System.Collections.Generic; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { @@ -15,11 +17,14 @@ public class SqlServerIsDateFunctionTranslator : IMethodCallTranslator private static readonly MethodInfo _methodInfo = typeof(SqlServerDbFunctionsExtensions) .GetRuntimeMethod(nameof(SqlServerDbFunctionsExtensions.IsDate), new[] { typeof(DbFunctions), typeof(string) }); - public SqlServerIsDateFunctionTranslator(ISqlExpressionFactory sqlExpressionFactory) + public SqlServerIsDateFunctionTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) => _sqlExpressionFactory = sqlExpressionFactory; public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { + Check.NotNull(method, nameof(method)); + Check.NotNull(arguments, nameof(arguments)); + return _methodInfo.Equals(method) ? _sqlExpressionFactory.Convert( _sqlExpressionFactory.Function( diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerMathTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerMathTranslator.cs index 974a0cb2d66..aa9c76367f2 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerMathTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerMathTranslator.cs @@ -5,8 +5,10 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { @@ -63,13 +65,16 @@ public class SqlServerMathTranslator : IMethodCallTranslator private readonly ISqlExpressionFactory _sqlExpressionFactory; - public SqlServerMathTranslator(ISqlExpressionFactory sqlExpressionFactory) + public SqlServerMathTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { + Check.NotNull(method, nameof(method)); + Check.NotNull(arguments, nameof(arguments)); + if (_supportedMethodTranslations.TryGetValue(method, out var sqlFunctionName)) { var typeMapping = arguments.Count == 1 diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerNewGuidTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerNewGuidTranslator.cs index bd9aec0745e..2c823c7c5b5 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerNewGuidTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerNewGuidTranslator.cs @@ -4,8 +4,10 @@ using System; using System.Collections.Generic; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { @@ -14,13 +16,16 @@ public class SqlServerNewGuidTranslator : IMethodCallTranslator private static readonly MethodInfo _methodInfo = typeof(Guid).GetRuntimeMethod(nameof(Guid.NewGuid), Array.Empty()); private readonly ISqlExpressionFactory _sqlExpressionFactory; - public SqlServerNewGuidTranslator(ISqlExpressionFactory sqlExpressionFactory) + public SqlServerNewGuidTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { + Check.NotNull(method, nameof(method)); + Check.NotNull(arguments, nameof(arguments)); + return _methodInfo.Equals(method) ? _sqlExpressionFactory.Function( "NEWID", diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerObjectToStringTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerObjectToStringTranslator.cs index 90647c0ccc2..3f686195549 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerObjectToStringTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerObjectToStringTranslator.cs @@ -4,8 +4,10 @@ using System; using System.Collections.Generic; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { @@ -37,13 +39,16 @@ private static readonly Dictionary _typeMapping private readonly ISqlExpressionFactory _sqlExpressionFactory; - public SqlServerObjectToStringTranslator(ISqlExpressionFactory sqlExpressionFactory) + public SqlServerObjectToStringTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { + Check.NotNull(method, nameof(method)); + Check.NotNull(arguments, nameof(arguments)); + return method.Name == nameof(ToString) && arguments.Count == 0 && instance != null diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerParameterBasedQueryTranslationPostprocessor.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerParameterBasedQueryTranslationPostprocessor.cs index 62d277f4e9e..b7cf63d1973 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerParameterBasedQueryTranslationPostprocessor.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerParameterBasedQueryTranslationPostprocessor.cs @@ -2,15 +2,17 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { public class SqlServerParameterBasedQueryTranslationPostprocessor : RelationalParameterBasedQueryTranslationPostprocessor { public SqlServerParameterBasedQueryTranslationPostprocessor( - RelationalParameterBasedQueryTranslationPostprocessorDependencies dependencies, + [NotNull] RelationalParameterBasedQueryTranslationPostprocessorDependencies dependencies, bool useRelationalNulls) : base(dependencies, useRelationalNulls) { @@ -20,6 +22,9 @@ public override (SelectExpression selectExpression, bool canCache) Optimize( SelectExpression selectExpression, IReadOnlyDictionary parametersValues) { + Check.NotNull(selectExpression, nameof(selectExpression)); + Check.NotNull(parametersValues, nameof(parametersValues)); + var (optimizedSelectExpression, canCache) = base.Optimize(selectExpression, parametersValues); var searchConditionOptimized = (SelectExpression)new SearchConditionConvertingExpressionVisitor(Dependencies.SqlExpressionFactory) diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerParameterBasedQueryTranslationPostprocessorFactory.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerParameterBasedQueryTranslationPostprocessorFactory.cs index c6cd770cfac..5631d625d11 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerParameterBasedQueryTranslationPostprocessorFactory.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerParameterBasedQueryTranslationPostprocessorFactory.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal @@ -9,7 +10,8 @@ public class SqlServerParameterBasedQueryTranslationPostprocessorFactory : IRela { private readonly RelationalParameterBasedQueryTranslationPostprocessorDependencies _dependencies; - public SqlServerParameterBasedQueryTranslationPostprocessorFactory(RelationalParameterBasedQueryTranslationPostprocessorDependencies dependencies) + public SqlServerParameterBasedQueryTranslationPostprocessorFactory( + [NotNull] RelationalParameterBasedQueryTranslationPostprocessorDependencies dependencies) { _dependencies = dependencies; } diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGenerator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGenerator.cs index 2a07ece04bd..e6b695f315b 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGenerator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGenerator.cs @@ -2,20 +2,24 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { public class SqlServerQuerySqlGenerator : QuerySqlGenerator { - public SqlServerQuerySqlGenerator(QuerySqlGeneratorDependencies dependencies) + public SqlServerQuerySqlGenerator([NotNull] QuerySqlGeneratorDependencies dependencies) : base(dependencies) { } protected override void GenerateTop(SelectExpression selectExpression) { + Check.NotNull(selectExpression, nameof(selectExpression)); + if (selectExpression.Limit != null && selectExpression.Offset == null) { @@ -29,6 +33,8 @@ protected override void GenerateTop(SelectExpression selectExpression) protected override void GenerateLimitOffset(SelectExpression selectExpression) { + Check.NotNull(selectExpression, nameof(selectExpression)); + // Note: For Limit without Offset, SqlServer generates TOP() if (selectExpression.Offset != null) { @@ -52,6 +58,8 @@ protected override void GenerateLimitOffset(SelectExpression selectExpression) protected override Expression VisitSqlFunction(SqlFunctionExpression sqlFunctionExpression) { + Check.NotNull(sqlFunctionExpression, nameof(sqlFunctionExpression)); + if (!sqlFunctionExpression.IsBuiltIn && string.IsNullOrEmpty(sqlFunctionExpression.Schema)) { diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGeneratorFactory.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGeneratorFactory.cs index 436a5ec4ac8..0fc4d1c289e 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGeneratorFactory.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGeneratorFactory.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal @@ -9,7 +10,7 @@ public class SqlServerQuerySqlGeneratorFactory : IQuerySqlGeneratorFactory { private readonly QuerySqlGeneratorDependencies _dependencies; - public SqlServerQuerySqlGeneratorFactory(QuerySqlGeneratorDependencies dependencies) + public SqlServerQuerySqlGeneratorFactory([NotNull] QuerySqlGeneratorDependencies dependencies) { _dependencies = dependencies; } diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerQueryTranslationPostprocessor.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerQueryTranslationPostprocessor.cs index 500cf13d63a..f29dd958ed4 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerQueryTranslationPostprocessor.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerQueryTranslationPostprocessor.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal @@ -9,9 +10,9 @@ namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal public class SqlServerQueryTranslationPostprocessor : RelationalQueryTranslationPostprocessor { public SqlServerQueryTranslationPostprocessor( - QueryTranslationPostprocessorDependencies dependencies, - RelationalQueryTranslationPostprocessorDependencies relationalDependencies, - QueryCompilationContext queryCompilationContext) + [NotNull] QueryTranslationPostprocessorDependencies dependencies, + [NotNull] RelationalQueryTranslationPostprocessorDependencies relationalDependencies, + [NotNull] QueryCompilationContext queryCompilationContext) : base(dependencies, relationalDependencies, queryCompilationContext) { } diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerQueryTranslationPostprocessorFactory.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerQueryTranslationPostprocessorFactory.cs index c87d356fd6a..bcf96e23df9 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerQueryTranslationPostprocessorFactory.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerQueryTranslationPostprocessorFactory.cs @@ -1,7 +1,9 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal @@ -25,17 +27,21 @@ public class SqlServerQueryTranslationPostprocessorFactory : IQueryTranslationPo private readonly RelationalQueryTranslationPostprocessorDependencies _relationalDependencies; public SqlServerQueryTranslationPostprocessorFactory( - QueryTranslationPostprocessorDependencies dependencies, - RelationalQueryTranslationPostprocessorDependencies relationalDependencies) + [NotNull] QueryTranslationPostprocessorDependencies dependencies, + [NotNull] RelationalQueryTranslationPostprocessorDependencies relationalDependencies) { _dependencies = dependencies; _relationalDependencies = relationalDependencies; } public virtual QueryTranslationPostprocessor Create(QueryCompilationContext queryCompilationContext) - => new SqlServerQueryTranslationPostprocessor( + { + Check.NotNull(queryCompilationContext, nameof(queryCompilationContext)); + + return new SqlServerQueryTranslationPostprocessor( _dependencies, _relationalDependencies, queryCompilationContext); + } } } diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerSqlTranslatingExpressionVisitor.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerSqlTranslatingExpressionVisitor.cs index ab495a5cd5a..365b00257c5 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerSqlTranslatingExpressionVisitor.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerSqlTranslatingExpressionVisitor.cs @@ -3,9 +3,11 @@ using System.Collections.Generic; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { @@ -35,9 +37,9 @@ private static readonly HashSet _arithmeticOperatorTypes private readonly ISqlExpressionFactory _sqlExpressionFactory; public SqlServerSqlTranslatingExpressionVisitor( - RelationalSqlTranslatingExpressionVisitorDependencies dependencies, - IModel model, - QueryableMethodTranslatingExpressionVisitor queryableMethodTranslatingExpressionVisitor) + [NotNull] RelationalSqlTranslatingExpressionVisitorDependencies dependencies, + [NotNull] IModel model, + [NotNull] QueryableMethodTranslatingExpressionVisitor queryableMethodTranslatingExpressionVisitor) : base(dependencies, model, queryableMethodTranslatingExpressionVisitor) { _sqlExpressionFactory = dependencies.SqlExpressionFactory; @@ -45,6 +47,8 @@ public SqlServerSqlTranslatingExpressionVisitor( protected override Expression VisitBinary(BinaryExpression binaryExpression) { + Check.NotNull(binaryExpression, nameof(binaryExpression)); + var visitedExpression = (SqlExpression)base.VisitBinary(binaryExpression); if (visitedExpression == null) diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerStringMemberTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerStringMemberTranslator.cs index 4fb3fa5eb7f..853c78e2c79 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerStringMemberTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerStringMemberTranslator.cs @@ -3,8 +3,10 @@ using System; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { @@ -12,13 +14,16 @@ public class SqlServerStringMemberTranslator : IMemberTranslator { private readonly ISqlExpressionFactory _sqlExpressionFactory; - public SqlServerStringMemberTranslator(ISqlExpressionFactory sqlExpressionFactory) + public SqlServerStringMemberTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { + Check.NotNull(member, nameof(member)); + Check.NotNull(returnType, nameof(returnType)); + if (member.Name == nameof(string.Length) && instance?.Type == typeof(string)) { diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs index d20aa0b6f30..1142f4d3677 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs @@ -6,8 +6,10 @@ using System.Linq; using System.Reflection; using System.Text; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { @@ -64,13 +66,16 @@ private static readonly MethodInfo _endsWithMethodInfo private const char LikeEscapeChar = '\\'; - public SqlServerStringMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) + public SqlServerStringMethodTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { + Check.NotNull(method, nameof(method)); + Check.NotNull(arguments, nameof(arguments)); + if (_indexOfMethodInfo.Equals(method)) { var argument = arguments[0]; diff --git a/src/EFCore.SqlServer/Storage/Internal/SqlServerByteArrayTypeMapping.cs b/src/EFCore.SqlServer/Storage/Internal/SqlServerByteArrayTypeMapping.cs index 71a47fe840c..e5448f6f5b2 100644 --- a/src/EFCore.SqlServer/Storage/Internal/SqlServerByteArrayTypeMapping.cs +++ b/src/EFCore.SqlServer/Storage/Internal/SqlServerByteArrayTypeMapping.cs @@ -35,7 +35,7 @@ public SqlServerByteArrayTypeMapping( [CanBeNull] string storeType = null, int? size = null, bool fixedLength = false, - ValueComparer comparer = null, + [CanBeNull] ValueComparer comparer = null, SqlDbType? sqlDbType = null, StoreTypePostfix? storeTypePostfix = null) : this( diff --git a/src/EFCore.SqlServer/Storage/Internal/SqlServerUdtTypeMapping.cs b/src/EFCore.SqlServer/Storage/Internal/SqlServerUdtTypeMapping.cs index 1631e39c356..7374948f08b 100644 --- a/src/EFCore.SqlServer/Storage/Internal/SqlServerUdtTypeMapping.cs +++ b/src/EFCore.SqlServer/Storage/Internal/SqlServerUdtTypeMapping.cs @@ -147,7 +147,7 @@ private static Action CreateUdtTypeNameAccessor(Type paramT /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public static SqlServerUdtTypeMapping CreateSqlHierarchyIdMapping(Type udtType) + public static SqlServerUdtTypeMapping CreateSqlHierarchyIdMapping([NotNull] Type udtType) => new SqlServerUdtTypeMapping( udtType, "hierarchyid", @@ -163,7 +163,7 @@ public static SqlServerUdtTypeMapping CreateSqlHierarchyIdMapping(Type udtType) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public static SqlServerUdtTypeMapping CreateSqlSpatialMapping(Type udtType, string storeName) + public static SqlServerUdtTypeMapping CreateSqlSpatialMapping([NotNull] Type udtType, [NotNull] string storeName) => new SqlServerUdtTypeMapping( udtType, storeName, diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteByteArrayMethodTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteByteArrayMethodTranslator.cs index 536ece74936..74d856083ac 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteByteArrayMethodTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteByteArrayMethodTranslator.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; @@ -12,7 +13,7 @@ public class SqliteByteArrayMethodTranslator : IMethodCallTranslator { private readonly ISqlExpressionFactory _sqlExpressionFactory; - public SqliteByteArrayMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) + public SqliteByteArrayMethodTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteDateTimeAddTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteDateTimeAddTranslator.cs index 43fbcf58336..d00454aa978 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteDateTimeAddTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteDateTimeAddTranslator.cs @@ -4,8 +4,10 @@ using System; using System.Collections.Generic; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { @@ -29,13 +31,16 @@ private static readonly MethodInfo _addTicks private readonly ISqlExpressionFactory _sqlExpressionFactory; - public SqliteDateTimeAddTranslator(ISqlExpressionFactory sqlExpressionFactory) + public SqliteDateTimeAddTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { + Check.NotNull(method, nameof(method)); + Check.NotNull(arguments, nameof(arguments)); + SqlExpression modifier = null; if (_addMilliseconds.Equals(method)) { diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteDateTimeMemberTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteDateTimeMemberTranslator.cs index 558ac39f8e7..8b162c32587 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteDateTimeMemberTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteDateTimeMemberTranslator.cs @@ -5,8 +5,10 @@ using System.Collections.Generic; using System.Diagnostics; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { @@ -27,13 +29,16 @@ private static readonly Dictionary _datePartMapping private readonly ISqlExpressionFactory _sqlExpressionFactory; - public SqliteDateTimeMemberTranslator(ISqlExpressionFactory sqlExpressionFactory) + public SqliteDateTimeMemberTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { + Check.NotNull(member, nameof(member)); + Check.NotNull(returnType, nameof(returnType)); + if (member.DeclaringType == typeof(DateTime)) { var memberName = member.Name; diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteExpression.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteExpression.cs index 28c2fda6d07..2b974227cfb 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteExpression.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteExpression.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; @@ -25,12 +26,12 @@ public static class SqliteExpression /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public static SqlFunctionExpression Strftime( - ISqlExpressionFactory sqlExpressionFactory, - Type returnType, - string format, - SqlExpression timestring, - IEnumerable modifiers = null, - RelationalTypeMapping typeMapping = null) + [NotNull] ISqlExpressionFactory sqlExpressionFactory, + [NotNull] Type returnType, + [NotNull] string format, + [NotNull] SqlExpression timestring, + [CanBeNull] IEnumerable modifiers = null, + [CanBeNull] RelationalTypeMapping typeMapping = null) { modifiers ??= Enumerable.Empty(); diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteMathTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteMathTranslator.cs index 34382f6a04c..11b40981c5a 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteMathTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteMathTranslator.cs @@ -4,9 +4,11 @@ using System; using System.Collections.Generic; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { @@ -44,13 +46,16 @@ public class SqliteMathTranslator : IMethodCallTranslator private readonly ISqlExpressionFactory _sqlExpressionFactory; - public SqliteMathTranslator(ISqlExpressionFactory sqlExpressionFactory) + public SqliteMathTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { + Check.NotNull(method, nameof(method)); + Check.NotNull(arguments, nameof(arguments)); + if (_supportedMethods.TryGetValue(method, out var sqlFunctionName)) { RelationalTypeMapping typeMapping; diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteMemberTranslatorProvider.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteMemberTranslatorProvider.cs index 9e734b45188..b73b352f31f 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteMemberTranslatorProvider.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteMemberTranslatorProvider.cs @@ -1,13 +1,14 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { public class SqliteMemberTranslatorProvider : RelationalMemberTranslatorProvider { - public SqliteMemberTranslatorProvider(RelationalMemberTranslatorProviderDependencies dependencies) + public SqliteMemberTranslatorProvider([NotNull] RelationalMemberTranslatorProviderDependencies dependencies) : base(dependencies) { var sqlExpressionFactory = dependencies.SqlExpressionFactory; diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteQuerySqlGenerator.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQuerySqlGenerator.cs index bdc49aa2533..cf1ce72e58d 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteQuerySqlGenerator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQuerySqlGenerator.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; @@ -10,16 +11,20 @@ namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { public class SqliteQuerySqlGenerator : QuerySqlGenerator { - public SqliteQuerySqlGenerator(QuerySqlGeneratorDependencies dependencies) + public SqliteQuerySqlGenerator([NotNull] QuerySqlGeneratorDependencies dependencies) : base(dependencies) { } protected override string GenerateOperator(SqlBinaryExpression binaryExpression) - => binaryExpression.OperatorType == ExpressionType.Add + { + Check.NotNull(binaryExpression, nameof(binaryExpression)); + + return binaryExpression.OperatorType == ExpressionType.Add && binaryExpression.Type == typeof(string) ? " || " : base.GenerateOperator(binaryExpression); + } protected override void GenerateLimitOffset(SelectExpression selectExpression) { @@ -46,6 +51,9 @@ protected override void GenerateLimitOffset(SelectExpression selectExpression) protected override void GenerateSetOperationOperand(SetOperationBase setOperation, SelectExpression operand) { + Check.NotNull(setOperation, nameof(setOperation)); + Check.NotNull(operand, nameof(operand)); + // Sqlite doesn't support parentheses around set operation operands Visit(operand); } diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteQuerySqlGeneratorFactory.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQuerySqlGeneratorFactory.cs index 65111844334..90fd840f52a 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteQuerySqlGeneratorFactory.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQuerySqlGeneratorFactory.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal @@ -9,7 +10,7 @@ public class SqliteQuerySqlGeneratorFactory : IQuerySqlGeneratorFactory { private readonly QuerySqlGeneratorDependencies _dependencies; - public SqliteQuerySqlGeneratorFactory(QuerySqlGeneratorDependencies dependencies) + public SqliteQuerySqlGeneratorFactory([NotNull] QuerySqlGeneratorDependencies dependencies) { _dependencies = dependencies; } diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryableMethodTranslatingExpressionVisitor.cs index 22a8ed43880..9149257723a 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryableMethodTranslatingExpressionVisitor.cs @@ -4,26 +4,28 @@ using System; using System.Linq; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Sqlite.Internal; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { public class SqliteQueryableMethodTranslatingExpressionVisitor : RelationalQueryableMethodTranslatingExpressionVisitor { public SqliteQueryableMethodTranslatingExpressionVisitor( - QueryableMethodTranslatingExpressionVisitorDependencies dependencies, - RelationalQueryableMethodTranslatingExpressionVisitorDependencies relationalDependencies, - IModel model) + [NotNull] QueryableMethodTranslatingExpressionVisitorDependencies dependencies, + [NotNull] RelationalQueryableMethodTranslatingExpressionVisitorDependencies relationalDependencies, + [NotNull] IModel model) : base(dependencies, relationalDependencies, model) { } protected SqliteQueryableMethodTranslatingExpressionVisitor( - SqliteQueryableMethodTranslatingExpressionVisitor parentVisitor) + [NotNull] SqliteQueryableMethodTranslatingExpressionVisitor parentVisitor) : base(parentVisitor) { } @@ -34,6 +36,9 @@ protected override QueryableMethodTranslatingExpressionVisitor CreateSubqueryVis protected override ShapedQueryExpression TranslateOrderBy( ShapedQueryExpression source, LambdaExpression keySelector, bool ascending) { + Check.NotNull(source, nameof(source)); + Check.NotNull(keySelector, nameof(keySelector)); + var translation = base.TranslateOrderBy(source, keySelector, ascending); if (translation == null) { @@ -56,6 +61,9 @@ protected override ShapedQueryExpression TranslateOrderBy( protected override ShapedQueryExpression TranslateThenBy(ShapedQueryExpression source, LambdaExpression keySelector, bool ascending) { + Check.NotNull(source, nameof(source)); + Check.NotNull(keySelector, nameof(keySelector)); + var translation = base.TranslateThenBy(source, keySelector, ascending); if (translation == null) { diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryableMethodTranslatingExpressionVisitorFactory.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryableMethodTranslatingExpressionVisitorFactory.cs index 8d15281039a..2a4e3071c0f 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryableMethodTranslatingExpressionVisitorFactory.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryableMethodTranslatingExpressionVisitorFactory.cs @@ -1,8 +1,10 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { @@ -12,14 +14,18 @@ public class SqliteQueryableMethodTranslatingExpressionVisitorFactory : IQueryab private readonly RelationalQueryableMethodTranslatingExpressionVisitorDependencies _relationalDependencies; public SqliteQueryableMethodTranslatingExpressionVisitorFactory( - QueryableMethodTranslatingExpressionVisitorDependencies dependencies, - RelationalQueryableMethodTranslatingExpressionVisitorDependencies relationalDependencies) + [NotNull] QueryableMethodTranslatingExpressionVisitorDependencies dependencies, + [NotNull] RelationalQueryableMethodTranslatingExpressionVisitorDependencies relationalDependencies) { _dependencies = dependencies; _relationalDependencies = relationalDependencies; } public virtual QueryableMethodTranslatingExpressionVisitor Create(IModel model) - => new SqliteQueryableMethodTranslatingExpressionVisitor(_dependencies, _relationalDependencies, model); + { + Check.NotNull(model, nameof(model)); + + return new SqliteQueryableMethodTranslatingExpressionVisitor(_dependencies, _relationalDependencies, model); + } } } diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlTranslatingExpressionVisitor.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlTranslatingExpressionVisitor.cs index 4fc93592dc6..fc26bb0a234 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlTranslatingExpressionVisitor.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlTranslatingExpressionVisitor.cs @@ -5,9 +5,11 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { @@ -74,15 +76,17 @@ private static readonly IReadOnlyDictionary arguments) { + Check.NotNull(method, nameof(method)); + Check.NotNull(arguments, nameof(arguments)); + if (_indexOfMethodInfo.Equals(method)) { var argument = arguments[0]; diff --git a/src/EFCore.Sqlite.Core/Storage/Internal/SqliteTypeMappingSource.cs b/src/EFCore.Sqlite.Core/Storage/Internal/SqliteTypeMappingSource.cs index c7d2458860b..a8f48d87d11 100644 --- a/src/EFCore.Sqlite.Core/Storage/Internal/SqliteTypeMappingSource.cs +++ b/src/EFCore.Sqlite.Core/Storage/Internal/SqliteTypeMappingSource.cs @@ -100,7 +100,7 @@ public SqliteTypeMappingSource( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public static bool IsSpatialiteType(string columnType) + public static bool IsSpatialiteType([NotNull] string columnType) => _spatialiteTypes.Contains(columnType); /// diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMemberTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMemberTranslator.cs index 118d816108b..3d41c8a98cc 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMemberTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMemberTranslator.cs @@ -3,8 +3,10 @@ using System; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal @@ -14,13 +16,16 @@ public class SqliteGeometryCollectionMemberTranslator : IMemberTranslator private static readonly MemberInfo _count = typeof(GeometryCollection).GetRuntimeProperty(nameof(GeometryCollection.Count)); private readonly ISqlExpressionFactory _sqlExpressionFactory; - public SqliteGeometryCollectionMemberTranslator(ISqlExpressionFactory sqlExpressionFactory) + public SqliteGeometryCollectionMemberTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { + Check.NotNull(member, nameof(member)); + Check.NotNull(returnType, nameof(returnType)); + return Equals(member, _count) ? _sqlExpressionFactory.Function("NumGeometries", new[] { instance }, returnType) : null; diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMethodTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMethodTranslator.cs index 48986038292..82297091c13 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMethodTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMethodTranslator.cs @@ -3,8 +3,10 @@ using System.Collections.Generic; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal @@ -14,13 +16,16 @@ public class SqliteGeometryCollectionMethodTranslator : IMethodCallTranslator private static readonly MethodInfo _item = typeof(GeometryCollection).GetRuntimeProperty("Item").GetMethod; private readonly ISqlExpressionFactory _sqlExpressionFactory; - public SqliteGeometryCollectionMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) + public SqliteGeometryCollectionMethodTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { + Check.NotNull(method, nameof(method)); + Check.NotNull(arguments, nameof(arguments)); + if (Equals(method, _item)) { return _sqlExpressionFactory.Function( diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMemberTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMemberTranslator.cs index bc30675a485..5a6fe2d179f 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMemberTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMemberTranslator.cs @@ -4,8 +4,10 @@ using System; using System.Collections.Generic; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal @@ -34,13 +36,16 @@ public class SqliteGeometryMemberTranslator : IMemberTranslator private static readonly MemberInfo _ogcGeometryType = typeof(Geometry).GetRuntimeProperty(nameof(Geometry.OgcGeometryType)); private readonly ISqlExpressionFactory _sqlExpressionFactory; - public SqliteGeometryMemberTranslator(ISqlExpressionFactory sqlExpressionFactory) + public SqliteGeometryMemberTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { + Check.NotNull(member, nameof(member)); + Check.NotNull(returnType, nameof(returnType)); + if (_memberToFunctionName.TryGetValue(member, out var functionName)) { SqlExpression translation = _sqlExpressionFactory.Function(functionName, new[] { instance }, returnType); diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMethodTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMethodTranslator.cs index f2116ec5550..b82f7f530b3 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMethodTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMethodTranslator.cs @@ -5,8 +5,10 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal @@ -50,13 +52,16 @@ public class SqliteGeometryMethodTranslator : IMethodCallTranslator private readonly ISqlExpressionFactory _sqlExpressionFactory; - public SqliteGeometryMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) + public SqliteGeometryMethodTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { + Check.NotNull(method, nameof(method)); + Check.NotNull(arguments, nameof(arguments)); + if (_methodToFunctionName.TryGetValue(method, out var functionName)) { SqlExpression translation = _sqlExpressionFactory.Function( diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMemberTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMemberTranslator.cs index 5b4075aec5c..401263fff13 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMemberTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMemberTranslator.cs @@ -4,8 +4,10 @@ using System; using System.Collections.Generic; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal @@ -24,13 +26,16 @@ private static readonly IDictionary _memberToFunctionName private readonly ISqlExpressionFactory _sqlExpressionFactory; - public SqliteLineStringMemberTranslator(ISqlExpressionFactory sqlExpressionFactory) + public SqliteLineStringMemberTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { + Check.NotNull(member, nameof(member)); + Check.NotNull(returnType, nameof(returnType)); + if (_memberToFunctionName.TryGetValue(member, out var functionName)) { SqlExpression translation = _sqlExpressionFactory.Function( diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMethodTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMethodTranslator.cs index 331d6fcc5da..1da9272b8de 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMethodTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMethodTranslator.cs @@ -3,8 +3,10 @@ using System.Collections.Generic; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal @@ -16,13 +18,16 @@ private static readonly MethodInfo _getPointN private readonly ISqlExpressionFactory _sqlExpressionFactory; - public SqliteLineStringMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) + public SqliteLineStringMethodTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { + Check.NotNull(method, nameof(method)); + Check.NotNull(arguments, nameof(arguments)); + if (Equals(method, _getPointN)) { return _sqlExpressionFactory.Function( diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteMultiLineStringMemberTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteMultiLineStringMemberTranslator.cs index cd956f5a69d..c24b3170763 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteMultiLineStringMemberTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteMultiLineStringMemberTranslator.cs @@ -3,8 +3,10 @@ using System; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal @@ -14,13 +16,16 @@ public class SqliteMultiLineStringMemberTranslator : IMemberTranslator private static readonly MemberInfo _isClosed = typeof(MultiLineString).GetRuntimeProperty(nameof(MultiLineString.IsClosed)); private readonly ISqlExpressionFactory _sqlExpressionFactory; - public SqliteMultiLineStringMemberTranslator(ISqlExpressionFactory sqlExpressionFactory) + public SqliteMultiLineStringMemberTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { + Check.NotNull(member, nameof(member)); + Check.NotNull(returnType, nameof(returnType)); + if (Equals(member, _isClosed)) { return _sqlExpressionFactory.Case( diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteMemberTranslatorPlugin.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteMemberTranslatorPlugin.cs index ddee3692b13..f7162401bb0 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteMemberTranslatorPlugin.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteMemberTranslatorPlugin.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.Extensions.DependencyInjection; @@ -23,7 +24,7 @@ namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal public class SqliteNetTopologySuiteMemberTranslatorPlugin : IMemberTranslatorPlugin { public SqliteNetTopologySuiteMemberTranslatorPlugin( - ISqlExpressionFactory sqlExpressionFactory) + [NotNull] ISqlExpressionFactory sqlExpressionFactory) { Translators = new IMemberTranslator[] { diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteMethodCallTranslatorPlugin.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteMethodCallTranslatorPlugin.cs index 5b6c35e94d8..c0029c0a4d0 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteMethodCallTranslatorPlugin.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteMethodCallTranslatorPlugin.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.Extensions.DependencyInjection; @@ -23,7 +24,7 @@ namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal /// public class SqliteNetTopologySuiteMethodCallTranslatorPlugin : IMethodCallTranslatorPlugin { - public SqliteNetTopologySuiteMethodCallTranslatorPlugin(ISqlExpressionFactory sqlExpressionFactory) + public SqliteNetTopologySuiteMethodCallTranslatorPlugin([NotNull] ISqlExpressionFactory sqlExpressionFactory) { Translators = new IMethodCallTranslator[] { diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePointMemberTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePointMemberTranslator.cs index b49023da1a6..b7f4655ef8e 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePointMemberTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePointMemberTranslator.cs @@ -4,8 +4,10 @@ using System; using System.Collections.Generic; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal @@ -22,13 +24,16 @@ public class SqlitePointMemberTranslator : IMemberTranslator private readonly ISqlExpressionFactory _sqlExpressionFactory; - public SqlitePointMemberTranslator(ISqlExpressionFactory sqlExpressionFactory) + public SqlitePointMemberTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { + Check.NotNull(member, nameof(member)); + Check.NotNull(returnType, nameof(returnType)); + return _memberToFunctionName.TryGetValue(member, out var functionName) ? _sqlExpressionFactory.Function(functionName, new[] { instance }, returnType) : null; diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMemberTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMemberTranslator.cs index 9246f3cb137..ac112d59118 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMemberTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMemberTranslator.cs @@ -4,8 +4,10 @@ using System; using System.Collections.Generic; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal @@ -21,13 +23,16 @@ private static readonly IDictionary _memberToFunctionName private readonly ISqlExpressionFactory _sqlExpressionFactory; - public SqlitePolygonMemberTranslator(ISqlExpressionFactory sqlExpressionFactory) + public SqlitePolygonMemberTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { + Check.NotNull(member, nameof(member)); + Check.NotNull(returnType, nameof(returnType)); + return _memberToFunctionName.TryGetValue(member, out var functionName) ? _sqlExpressionFactory.Function(functionName, new[] { instance }, returnType) : null; diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMethodTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMethodTranslator.cs index aa213dfdf0c..17c5dee6f39 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMethodTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMethodTranslator.cs @@ -3,8 +3,10 @@ using System.Collections.Generic; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal @@ -16,13 +18,16 @@ private static readonly MethodInfo _getInteriorRingN private readonly ISqlExpressionFactory _sqlExpressionFactory; - public SqlitePolygonMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) + public SqlitePolygonMethodTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) { _sqlExpressionFactory = sqlExpressionFactory; } public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { + Check.NotNull(method, nameof(method)); + Check.NotNull(arguments, nameof(arguments)); + if (Equals(method, _getInteriorRingN)) { return _sqlExpressionFactory.Function( diff --git a/src/EFCore.Sqlite.NTS/Storage/Internal/SqliteGeometryTypeMapping.cs b/src/EFCore.Sqlite.NTS/Storage/Internal/SqliteGeometryTypeMapping.cs index e53909f5908..4bf5499cc9f 100644 --- a/src/EFCore.Sqlite.NTS/Storage/Internal/SqliteGeometryTypeMapping.cs +++ b/src/EFCore.Sqlite.NTS/Storage/Internal/SqliteGeometryTypeMapping.cs @@ -35,7 +35,7 @@ private static readonly MethodInfo _getBytes /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [UsedImplicitly] - public SqliteGeometryTypeMapping(NtsGeometryServices geometryServices, string storeType) + public SqliteGeometryTypeMapping([NotNull] NtsGeometryServices geometryServices, [NotNull] string storeType) : base(new GeometryValueConverter(CreateReader(geometryServices), CreateWriter()), storeType) { } @@ -48,7 +48,7 @@ public SqliteGeometryTypeMapping(NtsGeometryServices geometryServices, string st /// protected SqliteGeometryTypeMapping( RelationalTypeMappingParameters parameters, - ValueConverter converter) + [CanBeNull] ValueConverter converter) : base(parameters, converter) { } diff --git a/src/EFCore.Sqlite.NTS/Storage/ValueConversion/Internal/GeometryValueConverter.cs b/src/EFCore.Sqlite.NTS/Storage/ValueConversion/Internal/GeometryValueConverter.cs index 6f7717a7c4e..5e797267937 100644 --- a/src/EFCore.Sqlite.NTS/Storage/ValueConversion/Internal/GeometryValueConverter.cs +++ b/src/EFCore.Sqlite.NTS/Storage/ValueConversion/Internal/GeometryValueConverter.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using NetTopologySuite.Geometries; using NetTopologySuite.IO; @@ -22,7 +23,7 @@ public class GeometryValueConverter : ValueConverter - public GeometryValueConverter(GaiaGeoReader reader, GaiaGeoWriter writer) + public GeometryValueConverter([NotNull] GaiaGeoReader reader, [NotNull] GaiaGeoWriter writer) : base( g => writer.Write(g), b => (TGeometry)reader.Read(b)) diff --git a/src/EFCore/ChangeTracking/Internal/IIdentityMap.cs b/src/EFCore/ChangeTracking/Internal/IIdentityMap.cs index 476f144b707..3da18511ef6 100644 --- a/src/EFCore/ChangeTracking/Internal/IIdentityMap.cs +++ b/src/EFCore/ChangeTracking/Internal/IIdentityMap.cs @@ -53,7 +53,7 @@ public interface IIdentityMap /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - InternalEntityEntry TryGetEntry(object[] keyValues, bool throwOnNullKey, out bool hasNullKey); + InternalEntityEntry TryGetEntry([NotNull] object[] keyValues, bool throwOnNullKey, out bool hasNullKey); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore/ChangeTracking/Internal/IPrincipalKeyValueFactory.cs b/src/EFCore/ChangeTracking/Internal/IPrincipalKeyValueFactory.cs index 6ad296de93a..a0f55ae1705 100644 --- a/src/EFCore/ChangeTracking/Internal/IPrincipalKeyValueFactory.cs +++ b/src/EFCore/ChangeTracking/Internal/IPrincipalKeyValueFactory.cs @@ -38,7 +38,7 @@ public interface IPrincipalKeyValueFactory /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - IProperty FindNullPropertyInKeyValues(object[] keyValues); + IProperty FindNullPropertyInKeyValues([NotNull] object[] keyValues); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore/ChangeTracking/Internal/IStateManager.cs b/src/EFCore/ChangeTracking/Internal/IStateManager.cs index 4f35f8b7c3c..82051de17a7 100644 --- a/src/EFCore/ChangeTracking/Internal/IStateManager.cs +++ b/src/EFCore/ChangeTracking/Internal/IStateManager.cs @@ -106,7 +106,7 @@ InternalEntityEntry StartTrackingFromQuery( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - InternalEntityEntry TryGetEntry([NotNull] IKey key, object[] keyValues, bool throwOnNullKey, out bool hasNullKey); + InternalEntityEntry TryGetEntry([NotNull] IKey key, [NotNull] object[] keyValues, bool throwOnNullKey, out bool hasNullKey); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -432,7 +432,7 @@ IEnumerable GetDependentsUsingRelationshipSnapshot( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - void CascadeDelete([NotNull] InternalEntityEntry entry, bool force, IEnumerable foreignKeys = null); + void CascadeDelete([NotNull] InternalEntityEntry entry, bool force, [CanBeNull] IEnumerable foreignKeys = null); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs b/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs index 9b3d6d3479a..55d59cd49e4 100644 --- a/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs +++ b/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs @@ -582,7 +582,7 @@ private CurrentValueType GetValueType( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual void SetTemporaryValue([NotNull] IProperty property, object value, bool setModified = true) + public virtual void SetTemporaryValue([NotNull] IProperty property, [CanBeNull] object value, bool setModified = true) { if (property.GetStoreGeneratedIndex() == -1) { @@ -1447,7 +1447,7 @@ public virtual bool IsStoreGenerated(IProperty property) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool HasDefaultValue(IProperty property) // Intentionally non-virtual + public bool HasDefaultValue([NotNull] IProperty property) // Intentionally non-virtual { if (!PropertyHasDefaultValue(property)) { diff --git a/src/EFCore/ChangeTracking/Internal/SnapshotFactoryFactory.cs b/src/EFCore/ChangeTracking/Internal/SnapshotFactoryFactory.cs index 00387607bce..5ea15cce951 100644 --- a/src/EFCore/ChangeTracking/Internal/SnapshotFactoryFactory.cs +++ b/src/EFCore/ChangeTracking/Internal/SnapshotFactoryFactory.cs @@ -99,10 +99,10 @@ protected virtual Expression CreateConstructorExpression( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// protected virtual Expression CreateSnapshotExpression( - Type entityType, - ParameterExpression parameter, - Type[] types, - IList propertyBases) + [CanBeNull] Type entityType, + [NotNull] ParameterExpression parameter, + [NotNull] Type[] types, + [NotNull] IList propertyBases) { var count = types.Length; diff --git a/src/EFCore/Extensions/Internal/EFPropertyExtensions.cs b/src/EFCore/Extensions/Internal/EFPropertyExtensions.cs index 733a5778699..1d241600ffa 100644 --- a/src/EFCore/Extensions/Internal/EFPropertyExtensions.cs +++ b/src/EFCore/Extensions/Internal/EFPropertyExtensions.cs @@ -32,8 +32,8 @@ public static class EFPropertyExtensions /// public static bool TryGetEFIndexerArguments( [NotNull] this MethodCallExpression methodCallExpression, - out Expression entityExpression, - out string propertyName) + [CanBeNull] out Expression entityExpression, + [CanBeNull] out string propertyName) { if (IsEFIndexer(methodCallExpression) && methodCallExpression.Arguments[0] is ConstantExpression propertyNameExpression) @@ -62,7 +62,7 @@ public static bool IsEFIndexer([NotNull] this MethodCallExpression methodCallExp /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public static bool IsEFIndexer(this MethodInfo methodInfo) + public static bool IsEFIndexer([NotNull] this MethodInfo methodInfo) => !methodInfo.IsStatic && "get_Item".Equals(methodInfo.Name, StringComparison.Ordinal) && typeof(object) == methodInfo.ReturnType diff --git a/src/EFCore/Extensions/Internal/ExpressionExtensions.cs b/src/EFCore/Extensions/Internal/ExpressionExtensions.cs index d9d2e4dcf8b..93e7d31bc95 100644 --- a/src/EFCore/Extensions/Internal/ExpressionExtensions.cs +++ b/src/EFCore/Extensions/Internal/ExpressionExtensions.cs @@ -148,7 +148,7 @@ public static bool IsEntityQueryable([NotNull] this ConstantExpression constantE /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public static LambdaExpression GetLambdaOrNull(this Expression expression) + public static LambdaExpression GetLambdaOrNull([NotNull] this Expression expression) => expression is LambdaExpression lambda ? lambda : expression is UnaryExpression unary && expression.NodeType == ExpressionType.Quote @@ -161,7 +161,7 @@ public static LambdaExpression GetLambdaOrNull(this Expression expression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public static bool IsLogicalNot(this UnaryExpression sqlUnaryExpression) + public static bool IsLogicalNot([NotNull] this UnaryExpression sqlUnaryExpression) => sqlUnaryExpression.NodeType == ExpressionType.Not && (sqlUnaryExpression.Type == typeof(bool) || sqlUnaryExpression.Type == typeof(bool?)); diff --git a/src/EFCore/Extensions/Internal/QueryableExtensions.cs b/src/EFCore/Extensions/Internal/QueryableExtensions.cs index 23a1d30dadc..99670405a2d 100644 --- a/src/EFCore/Extensions/Internal/QueryableExtensions.cs +++ b/src/EFCore/Extensions/Internal/QueryableExtensions.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Linq.Expressions; using System.Reflection; +using JetBrains.Annotations; // ReSharper disable CheckNamespace namespace Microsoft.EntityFrameworkCore.Internal @@ -28,11 +29,11 @@ public static class QueryableExtensions /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public static IQueryable LeftJoin( - this IQueryable outer, - IEnumerable inner, - Expression> outerKeySelector, - Expression> innerKeySelector, - Expression> resultSelector) + [NotNull] this IQueryable outer, + [NotNull] IEnumerable inner, + [NotNull] Expression> outerKeySelector, + [NotNull] Expression> innerKeySelector, + [NotNull] Expression> resultSelector) { throw new NotImplementedException(); } diff --git a/src/EFCore/Extensions/Internal/TypeExtensions.cs b/src/EFCore/Extensions/Internal/TypeExtensions.cs index 5d2a401a390..e3ccd12eb16 100644 --- a/src/EFCore/Extensions/Internal/TypeExtensions.cs +++ b/src/EFCore/Extensions/Internal/TypeExtensions.cs @@ -189,7 +189,7 @@ public static IEnumerable GetNamespaces([NotNull] this Type type) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public static string GenerateParameterName(this Type type) + public static string GenerateParameterName([NotNull] this Type type) { var sb = new StringBuilder(); var removeLowerCase = sb.Append(type.Name.Where(char.IsUpper).ToArray()).ToString(); @@ -203,7 +203,7 @@ public static string GenerateParameterName(this Type type) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public static bool IsQueryableType(this Type type) + public static bool IsQueryableType([NotNull] this Type type) { if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IQueryable<>)) diff --git a/src/EFCore/Infrastructure/DbContextOptionsExtensionInfo.cs b/src/EFCore/Infrastructure/DbContextOptionsExtensionInfo.cs index 4867dc5ba53..03fda996c1c 100644 --- a/src/EFCore/Infrastructure/DbContextOptionsExtensionInfo.cs +++ b/src/EFCore/Infrastructure/DbContextOptionsExtensionInfo.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Infrastructure { @@ -17,8 +18,10 @@ public abstract class DbContextOptionsExtensionInfo /// info/metadata for the given extension. /// /// The extension. - protected DbContextOptionsExtensionInfo(IDbContextOptionsExtension extension) + protected DbContextOptionsExtensionInfo([NotNull] IDbContextOptionsExtension extension) { + Check.NotNull(extension, nameof(extension)); + Extension = extension; } diff --git a/src/EFCore/Metadata/Builders/InvertibleRelationshipBuilderBase.cs b/src/EFCore/Metadata/Builders/InvertibleRelationshipBuilderBase.cs index 98f95f9f292..18ed5279273 100644 --- a/src/EFCore/Metadata/Builders/InvertibleRelationshipBuilderBase.cs +++ b/src/EFCore/Metadata/Builders/InvertibleRelationshipBuilderBase.cs @@ -50,8 +50,8 @@ protected InvertibleRelationshipBuilderBase( /// [EntityFrameworkInternal] protected InvertibleRelationshipBuilderBase( - InternalRelationshipBuilder builder, - InvertibleRelationshipBuilderBase oldBuilder, + [NotNull] InternalRelationshipBuilder builder, + [CanBeNull] InvertibleRelationshipBuilderBase oldBuilder, bool inverted = false, bool foreignKeySet = false, bool principalKeySet = false, diff --git a/src/EFCore/Metadata/Builders/OwnershipBuilder.cs b/src/EFCore/Metadata/Builders/OwnershipBuilder.cs index d5ec440f7a4..9591471a277 100644 --- a/src/EFCore/Metadata/Builders/OwnershipBuilder.cs +++ b/src/EFCore/Metadata/Builders/OwnershipBuilder.cs @@ -39,8 +39,8 @@ public OwnershipBuilder( /// [EntityFrameworkInternal] protected OwnershipBuilder( - InternalRelationshipBuilder builder, - OwnershipBuilder oldBuilder, + [NotNull] InternalRelationshipBuilder builder, + [CanBeNull] OwnershipBuilder oldBuilder, bool foreignKeySet = false, bool principalKeySet = false, bool requiredSet = false) diff --git a/src/EFCore/Metadata/Builders/OwnershipBuilder`.cs b/src/EFCore/Metadata/Builders/OwnershipBuilder`.cs index fe9adccfc57..90d10865fce 100644 --- a/src/EFCore/Metadata/Builders/OwnershipBuilder`.cs +++ b/src/EFCore/Metadata/Builders/OwnershipBuilder`.cs @@ -43,8 +43,8 @@ public OwnershipBuilder( /// [EntityFrameworkInternal] protected OwnershipBuilder( - InternalRelationshipBuilder builder, - OwnershipBuilder oldBuilder, + [NotNull] InternalRelationshipBuilder builder, + [CanBeNull] OwnershipBuilder oldBuilder, bool foreignKeySet = false, bool principalKeySet = false, bool requiredSet = false) diff --git a/src/EFCore/Metadata/Builders/ReferenceCollectionBuilder.cs b/src/EFCore/Metadata/Builders/ReferenceCollectionBuilder.cs index f58cede17c2..2cdab341ef6 100644 --- a/src/EFCore/Metadata/Builders/ReferenceCollectionBuilder.cs +++ b/src/EFCore/Metadata/Builders/ReferenceCollectionBuilder.cs @@ -45,8 +45,8 @@ public ReferenceCollectionBuilder( /// [EntityFrameworkInternal] protected ReferenceCollectionBuilder( - InternalRelationshipBuilder builder, - ReferenceCollectionBuilder oldBuilder, + [NotNull] InternalRelationshipBuilder builder, + [CanBeNull] ReferenceCollectionBuilder oldBuilder, bool foreignKeySet = false, bool principalKeySet = false, bool requiredSet = false) diff --git a/src/EFCore/Metadata/Builders/ReferenceCollectionBuilder`.cs b/src/EFCore/Metadata/Builders/ReferenceCollectionBuilder`.cs index f80d0dfbb0d..4fd6d44bc94 100644 --- a/src/EFCore/Metadata/Builders/ReferenceCollectionBuilder`.cs +++ b/src/EFCore/Metadata/Builders/ReferenceCollectionBuilder`.cs @@ -49,8 +49,8 @@ public ReferenceCollectionBuilder( /// [EntityFrameworkInternal] protected ReferenceCollectionBuilder( - InternalRelationshipBuilder builder, - ReferenceCollectionBuilder oldBuilder, + [NotNull] InternalRelationshipBuilder builder, + [CanBeNull] ReferenceCollectionBuilder oldBuilder, bool foreignKeySet = false, bool principalKeySet = false, bool requiredSet = false) diff --git a/src/EFCore/Metadata/Builders/ReferenceReferenceBuilder.cs b/src/EFCore/Metadata/Builders/ReferenceReferenceBuilder.cs index 58a57caf000..80207fe375f 100644 --- a/src/EFCore/Metadata/Builders/ReferenceReferenceBuilder.cs +++ b/src/EFCore/Metadata/Builders/ReferenceReferenceBuilder.cs @@ -44,8 +44,8 @@ public ReferenceReferenceBuilder( /// [EntityFrameworkInternal] protected ReferenceReferenceBuilder( - InternalRelationshipBuilder builder, - ReferenceReferenceBuilder oldBuilder, + [NotNull] InternalRelationshipBuilder builder, + [CanBeNull] ReferenceReferenceBuilder oldBuilder, bool inverted = false, bool foreignKeySet = false, bool principalKeySet = false, diff --git a/src/EFCore/Metadata/Builders/ReferenceReferenceBuilder`.cs b/src/EFCore/Metadata/Builders/ReferenceReferenceBuilder`.cs index d982ca0454b..f428782bc38 100644 --- a/src/EFCore/Metadata/Builders/ReferenceReferenceBuilder`.cs +++ b/src/EFCore/Metadata/Builders/ReferenceReferenceBuilder`.cs @@ -43,8 +43,8 @@ public ReferenceReferenceBuilder( /// [EntityFrameworkInternal] protected ReferenceReferenceBuilder( - InternalRelationshipBuilder builder, - ReferenceReferenceBuilder oldBuilder, + [NotNull] InternalRelationshipBuilder builder, + [CanBeNull] ReferenceReferenceBuilder oldBuilder, bool inverted = false, bool foreignKeySet = false, bool principalKeySet = false, diff --git a/src/EFCore/Metadata/Builders/RelationshipBuilderBase.cs b/src/EFCore/Metadata/Builders/RelationshipBuilderBase.cs index 492f5bc3ef3..1bf65c3af35 100644 --- a/src/EFCore/Metadata/Builders/RelationshipBuilderBase.cs +++ b/src/EFCore/Metadata/Builders/RelationshipBuilderBase.cs @@ -44,8 +44,8 @@ protected RelationshipBuilderBase( /// [EntityFrameworkInternal] protected RelationshipBuilderBase( - InternalRelationshipBuilder builder, - RelationshipBuilderBase oldBuilder, + [NotNull] InternalRelationshipBuilder builder, + [CanBeNull] RelationshipBuilderBase oldBuilder, bool foreignKeySet = false, bool principalKeySet = false, bool requiredSet = false) diff --git a/src/EFCore/Metadata/Conventions/Internal/ConventionContext.cs b/src/EFCore/Metadata/Conventions/Internal/ConventionContext.cs index 057186d5e74..d1bf8fa23c8 100644 --- a/src/EFCore/Metadata/Conventions/Internal/ConventionContext.cs +++ b/src/EFCore/Metadata/Conventions/Internal/ConventionContext.cs @@ -1,6 +1,8 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using JetBrains.Annotations; + namespace Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal { /// @@ -21,7 +23,7 @@ public class ConventionContext : IConventionContext, IRead /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public ConventionContext(ConventionDispatcher dispatcher) + public ConventionContext([NotNull] ConventionDispatcher dispatcher) { _dispatcher = dispatcher; } @@ -102,7 +104,7 @@ public virtual void StopProcessingIfChanged(TMetadata result) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual void ResetState(TMetadata input) + public virtual void ResetState([CanBeNull] TMetadata input) { _stopProcessing = false; _result = input; diff --git a/src/EFCore/Metadata/Conventions/Internal/ConventionDispatcher.cs b/src/EFCore/Metadata/Conventions/Internal/ConventionDispatcher.cs index a65eaf18c2f..5cc6f28b26e 100644 --- a/src/EFCore/Metadata/Conventions/Internal/ConventionDispatcher.cs +++ b/src/EFCore/Metadata/Conventions/Internal/ConventionDispatcher.cs @@ -459,7 +459,7 @@ public virtual IConventionAnnotation OnPropertyAnnotationChanged( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual T Run(Func func, ref ForeignKey foreignKey) + public virtual T Run([NotNull] Func func, [CanBeNull] ref ForeignKey foreignKey) { var batch = DelayConventions(); using var foreignKeyReference = Tracker.Track(foreignKey); diff --git a/src/EFCore/Metadata/Conventions/QueryFilterDefiningQueryRewritingConvention.cs b/src/EFCore/Metadata/Conventions/QueryFilterDefiningQueryRewritingConvention.cs index 2cb73365bcf..60a105644cc 100644 --- a/src/EFCore/Metadata/Conventions/QueryFilterDefiningQueryRewritingConvention.cs +++ b/src/EFCore/Metadata/Conventions/QueryFilterDefiningQueryRewritingConvention.cs @@ -7,6 +7,7 @@ using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure; using Microsoft.EntityFrameworkCore.Query.Internal; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { @@ -73,6 +74,8 @@ public DbSetAccessRewritingExpressionVisitor(Type contextType) protected override Expression VisitMember(MemberExpression memberExpression) { + Check.NotNull(memberExpression, nameof(memberExpression)); + if (memberExpression.Expression != null && (memberExpression.Expression.Type.IsAssignableFrom(_contextType) || _contextType.IsAssignableFrom(memberExpression.Expression.Type)) @@ -87,6 +90,8 @@ protected override Expression VisitMember(MemberExpression memberExpression) protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { + Check.NotNull(methodCallExpression, nameof(methodCallExpression)); + if (methodCallExpression.Method.Name == nameof(DbContext.Set) && methodCallExpression.Object != null && typeof(DbContext).IsAssignableFrom(methodCallExpression.Object.Type) diff --git a/src/EFCore/Metadata/Internal/ClrAccessorFactory.cs b/src/EFCore/Metadata/Internal/ClrAccessorFactory.cs index 99ce5e9aadb..6a10b835b07 100644 --- a/src/EFCore/Metadata/Internal/ClrAccessorFactory.cs +++ b/src/EFCore/Metadata/Internal/ClrAccessorFactory.cs @@ -43,7 +43,7 @@ public virtual TAccessor Create([NotNull] MemberInfo memberInfo) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected virtual TAccessor Create(MemberInfo memberInfo, IPropertyBase propertyBase) + protected virtual TAccessor Create([NotNull] MemberInfo memberInfo, [CanBeNull] IPropertyBase propertyBase) { var boundMethod = propertyBase != null ? _genericCreate.MakeGenericMethod( diff --git a/src/EFCore/Metadata/Internal/ConventionAnnotatable.cs b/src/EFCore/Metadata/Internal/ConventionAnnotatable.cs index 00be2fd0f79..403d46fc595 100644 --- a/src/EFCore/Metadata/Internal/ConventionAnnotatable.cs +++ b/src/EFCore/Metadata/Internal/ConventionAnnotatable.cs @@ -87,7 +87,7 @@ protected virtual IConventionAnnotation OnAnnotationSet( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public new virtual ConventionAnnotation FindAnnotation(string name) + public new virtual ConventionAnnotation FindAnnotation([NotNull] string name) => (ConventionAnnotation)base.FindAnnotation(name); /// @@ -96,7 +96,7 @@ protected virtual IConventionAnnotation OnAnnotationSet( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public new virtual ConventionAnnotation RemoveAnnotation(string name) + public new virtual ConventionAnnotation RemoveAnnotation([NotNull] string name) => (ConventionAnnotation)base.RemoveAnnotation(name); /// diff --git a/src/EFCore/Metadata/Internal/EntityType.cs b/src/EFCore/Metadata/Internal/EntityType.cs index f456123c58c..0e8b6834ef3 100644 --- a/src/EFCore/Metadata/Internal/EntityType.cs +++ b/src/EFCore/Metadata/Internal/EntityType.cs @@ -915,7 +915,7 @@ public virtual ForeignKey AddForeignKey( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual void OnForeignKeyUpdating(ForeignKey foreignKey) + public virtual void OnForeignKeyUpdating([NotNull] ForeignKey foreignKey) { var removed = _foreignKeys.Remove(foreignKey); Debug.Assert(removed); @@ -944,7 +944,7 @@ public virtual void OnForeignKeyUpdating(ForeignKey foreignKey) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual void OnForeignKeyUpdated(ForeignKey foreignKey) + public virtual void OnForeignKeyUpdated([NotNull] ForeignKey foreignKey) { var added = _foreignKeys.Add(foreignKey); Debug.Assert(added); @@ -1649,7 +1649,7 @@ public virtual Index RemoveIndex([NotNull] IReadOnlyList properties) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual Index RemoveIndex(Index index) + public virtual Index RemoveIndex([NotNull] Index index) { if (!_indexes.Remove(index.Properties)) { @@ -1753,9 +1753,9 @@ public virtual Property AddProperty( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual Property AddProperty( - string name, - Type propertyType, - MemberInfo memberInfo, + [NotNull] string name, + [NotNull] Type propertyType, + [CanBeNull] MemberInfo memberInfo, ConfigurationSource? typeConfigurationSource, ConfigurationSource configurationSource) { @@ -1949,7 +1949,7 @@ public virtual Property RemoveProperty([NotNull] string name) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual Property RemoveProperty(Property property) + public virtual Property RemoveProperty([NotNull] Property property) { if (property.DeclaringEntityType != this) { @@ -2497,7 +2497,7 @@ private void CheckDiscriminatorProperty(IProperty property) } } - public virtual void CheckDiscriminatorValue(IEntityType entityType, object value) + public virtual void CheckDiscriminatorValue([NotNull] IEntityType entityType, [CanBeNull] object value) { if (value != null && entityType.GetDiscriminatorProperty() == null) diff --git a/src/EFCore/Metadata/Internal/ForeignKey.cs b/src/EFCore/Metadata/Internal/ForeignKey.cs index a676be2ad01..18477957347 100644 --- a/src/EFCore/Metadata/Internal/ForeignKey.cs +++ b/src/EFCore/Metadata/Internal/ForeignKey.cs @@ -163,7 +163,9 @@ protected override IConventionAnnotation OnAnnotationSet( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual void SetProperties( - IReadOnlyList properties, Key principalKey, ConfigurationSource? configurationSource) + [NotNull] IReadOnlyList properties, + [NotNull] Key principalKey, + ConfigurationSource? configurationSource) { Validate(properties, principalKey, DeclaringEntityType, PrincipalEntityType); diff --git a/src/EFCore/Metadata/Internal/InternalAnnotatableBuilder.cs b/src/EFCore/Metadata/Internal/InternalAnnotatableBuilder.cs index 556a686f93a..4909757ef28 100644 --- a/src/EFCore/Metadata/Internal/InternalAnnotatableBuilder.cs +++ b/src/EFCore/Metadata/Internal/InternalAnnotatableBuilder.cs @@ -142,7 +142,7 @@ public virtual InternalAnnotatableBuilder RemoveAnnotation([NotNull] string name /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual bool CanRemoveAnnotation(string name, ConfigurationSource configurationSource) + public virtual bool CanRemoveAnnotation([NotNull] string name, ConfigurationSource configurationSource) { var existingAnnotation = Metadata.FindAnnotation(name); return existingAnnotation == null diff --git a/src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs b/src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs index 60255f44a21..fe7caf5dac0 100644 --- a/src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs +++ b/src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs @@ -135,7 +135,7 @@ public virtual InternalKeyBuilder PrimaryKey( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual bool CanSetPrimaryKey(IReadOnlyList properties, ConfigurationSource configurationSource) + public virtual bool CanSetPrimaryKey([CanBeNull] IReadOnlyList properties, ConfigurationSource configurationSource) { var previousPrimaryKey = Metadata.FindPrimaryKey(); if (properties == null) @@ -305,7 +305,7 @@ public virtual InternalEntityTypeBuilder HasNoKey([NotNull] Key key, Configurati /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public static List<(InternalKeyBuilder, ConfigurationSource?)> DetachKeys(IEnumerable keysToDetach) + public static List<(InternalKeyBuilder, ConfigurationSource?)> DetachKeys([NotNull] IEnumerable keysToDetach) { var keysToDetachList = (keysToDetach as List) ?? keysToDetach.ToList(); if (keysToDetachList.Count == 0) @@ -662,7 +662,7 @@ private bool CanRemoveProperty( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual bool CanAddProperty(Type propertyType, string name, ConfigurationSource? typeConfigurationSource) + public virtual bool CanAddProperty([NotNull] Type propertyType, [NotNull] string name, ConfigurationSource? typeConfigurationSource) { var conflictingMember = Metadata.FindPropertiesInHierarchy(name).FirstOrDefault(); if (conflictingMember != null @@ -969,7 +969,7 @@ public virtual InternalEntityTypeBuilder Ignore([NotNull] string name, Configura /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual bool CanIgnore(string name, ConfigurationSource configurationSource) + public virtual bool CanIgnore([NotNull] string name, ConfigurationSource configurationSource) => CanIgnore(name, configurationSource, shouldThrow: false); private bool CanIgnore(string name, ConfigurationSource configurationSource, bool shouldThrow) @@ -1119,7 +1119,7 @@ public virtual InternalEntityTypeBuilder HasDefiningQuery( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual bool CanSetDefiningQuery(LambdaExpression query, ConfigurationSource configurationSource) + public virtual bool CanSetDefiningQuery([CanBeNull] LambdaExpression query, ConfigurationSource configurationSource) => configurationSource.Overrides(Metadata.GetDefiningQueryConfigurationSource()) || Metadata.GetDefiningQuery() == query; @@ -1431,7 +1431,7 @@ public virtual InternalEntityTypeBuilder HasBaseType( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual bool CanSetBaseType(EntityType baseEntityType, ConfigurationSource configurationSource) + public virtual bool CanSetBaseType([NotNull] EntityType baseEntityType, ConfigurationSource configurationSource) => Metadata.BaseType == baseEntityType || configurationSource.Overrides(Metadata.GetBaseTypeConfigurationSource()); @@ -1894,7 +1894,7 @@ public virtual InternalEntityTypeBuilder HasNoIndex([NotNull] Index index, Confi /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public static List DetachIndexes(IEnumerable indexesToDetach) + public static List DetachIndexes([NotNull] IEnumerable indexesToDetach) { var indexesToDetachList = (indexesToDetach as List) ?? indexesToDetach.ToList(); if (indexesToDetachList.Count == 0) @@ -2678,7 +2678,7 @@ private InternalRelationshipBuilder HasOwnership( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual bool RemoveNonOwnershipRelationships(ForeignKey ownership, ConfigurationSource configurationSource) + public virtual bool RemoveNonOwnershipRelationships([NotNull] ForeignKey ownership, ConfigurationSource configurationSource) { var incompatibleRelationships = Metadata.GetDerivedTypesInclusive() .SelectMany(t => t.GetDeclaredForeignKeys()) @@ -2756,8 +2756,8 @@ public virtual InternalRelationshipBuilder HasRelationship( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual InternalEntityTypeBuilder GetTargetEntityTypeBuilder( - Type targetClrType, - MemberInfo navigationInfo, + [NotNull] Type targetClrType, + [NotNull] MemberInfo navigationInfo, ConfigurationSource? configurationSource) { var ownership = Metadata.FindOwnership(); @@ -3032,8 +3032,8 @@ public virtual bool ShouldReuniquifyTemporaryProperties([NotNull] ForeignKey for /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual Property CreateUniqueProperty( - string propertyName, - Type propertyType, + [NotNull] string propertyName, + [NotNull] Type propertyType, bool isRequired) => CreateUniqueProperties( new[] { propertyName }, @@ -3047,8 +3047,8 @@ public virtual Property CreateUniqueProperty( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual IReadOnlyList CreateUniqueProperties( - IReadOnlyList propertyNames, - IReadOnlyList propertyTypes, + [NotNull] IReadOnlyList propertyNames, + [NotNull] IReadOnlyList propertyTypes, bool isRequired) => TryCreateUniqueProperties( propertyNames.Count, @@ -3367,7 +3367,8 @@ public virtual bool CanSetPropertyAccessMode(PropertyAccessMode? propertyAccessM /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual InternalPropertyBuilder GetOrCreateDiscriminatorProperty(Type type, string name, bool fromDataAnnotation) + public virtual InternalPropertyBuilder GetOrCreateDiscriminatorProperty( + [CanBeNull] Type type, [CanBeNull] string name, bool fromDataAnnotation) { var discriminatorProperty = ((IEntityType)Metadata).GetDiscriminatorProperty(); if ((name != null && discriminatorProperty?.Name != name) @@ -3385,7 +3386,7 @@ public virtual InternalPropertyBuilder GetOrCreateDiscriminatorProperty(Type typ } public virtual DiscriminatorBuilder DiscriminatorBuilder( - InternalPropertyBuilder discriminatorPropertyBuilder, + [CanBeNull] InternalPropertyBuilder discriminatorPropertyBuilder, ConfigurationSource configurationSource) { if (discriminatorPropertyBuilder == null) diff --git a/src/EFCore/Metadata/Internal/InternalPropertyBuilder.cs b/src/EFCore/Metadata/Internal/InternalPropertyBuilder.cs index bc39cd3036a..9b63182b695 100644 --- a/src/EFCore/Metadata/Internal/InternalPropertyBuilder.cs +++ b/src/EFCore/Metadata/Internal/InternalPropertyBuilder.cs @@ -427,7 +427,7 @@ public virtual InternalPropertyBuilder HasValueGenerator( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual bool CanSetValueGenerator( - Func factory, ConfigurationSource? configurationSource) + [CanBeNull] Func factory, ConfigurationSource? configurationSource) => configurationSource.Overrides(Metadata.GetValueGeneratorFactoryConfigurationSource()) || Metadata.GetValueGeneratorFactory() == factory; diff --git a/src/EFCore/Metadata/Internal/InternalServicePropertyBuilder.cs b/src/EFCore/Metadata/Internal/InternalServicePropertyBuilder.cs index 89a82822aa9..370987dd969 100644 --- a/src/EFCore/Metadata/Internal/InternalServicePropertyBuilder.cs +++ b/src/EFCore/Metadata/Internal/InternalServicePropertyBuilder.cs @@ -118,7 +118,7 @@ public virtual InternalServicePropertyBuilder UsePropertyAccessMode( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual InternalServicePropertyBuilder HasParameterBinding( - ServiceParameterBinding parameterBinding, ConfigurationSource configurationSource) + [CanBeNull] ServiceParameterBinding parameterBinding, ConfigurationSource configurationSource) { if (CanSetParameterBinding(parameterBinding, configurationSource)) { @@ -135,7 +135,7 @@ public virtual InternalServicePropertyBuilder HasParameterBinding( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual bool CanSetParameterBinding(ServiceParameterBinding parameterBinding, ConfigurationSource configurationSource) + public virtual bool CanSetParameterBinding([CanBeNull] ServiceParameterBinding parameterBinding, ConfigurationSource configurationSource) => configurationSource.Overrides(Metadata.GetParameterBindingConfigurationSource()) || (Metadata.ParameterBinding == parameterBinding); diff --git a/src/EFCore/Metadata/Internal/Model.cs b/src/EFCore/Metadata/Internal/Model.cs index 86517f4466d..44c822a24b1 100644 --- a/src/EFCore/Metadata/Internal/Model.cs +++ b/src/EFCore/Metadata/Internal/Model.cs @@ -373,7 +373,7 @@ public virtual void AddDetachedEntityType( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [DebuggerStepThrough] - public virtual string GetDisplayName(Type type) + public virtual string GetDisplayName([NotNull] Type type) => _clrTypeNameMap.GetOrAdd(type, t => t.DisplayName()); /// diff --git a/src/EFCore/Metadata/Internal/Property.cs b/src/EFCore/Metadata/Internal/Property.cs index 0e3db23af26..9098201e9b4 100644 --- a/src/EFCore/Metadata/Internal/Property.cs +++ b/src/EFCore/Metadata/Internal/Property.cs @@ -511,7 +511,7 @@ public virtual void SetStructuralValueComparer([CanBeNull] ValueComparer compare /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual string CheckValueComparer(ValueComparer comparer) + public virtual string CheckValueComparer([CanBeNull] ValueComparer comparer) { if (comparer != null && comparer.Type != ClrType) diff --git a/src/EFCore/Metadata/Internal/ServiceProperty.cs b/src/EFCore/Metadata/Internal/ServiceProperty.cs index d6a7d39b564..92a4913f562 100644 --- a/src/EFCore/Metadata/Internal/ServiceProperty.cs +++ b/src/EFCore/Metadata/Internal/ServiceProperty.cs @@ -123,7 +123,7 @@ public virtual ServiceParameterBinding ParameterBinding /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual void SetParameterBinding(ServiceParameterBinding parameterBinding, ConfigurationSource configurationSource) + public virtual void SetParameterBinding([CanBeNull] ServiceParameterBinding parameterBinding, ConfigurationSource configurationSource) { _parameterBinding = parameterBinding; diff --git a/src/EFCore/Metadata/Internal/TypeBaseExtensions.cs b/src/EFCore/Metadata/Internal/TypeBaseExtensions.cs index 9f39ca39f12..f6846cca13e 100644 --- a/src/EFCore/Metadata/Internal/TypeBaseExtensions.cs +++ b/src/EFCore/Metadata/Internal/TypeBaseExtensions.cs @@ -33,7 +33,7 @@ public static bool HasClrType([NotNull] this ITypeBase type) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public static IReadOnlyDictionary GetRuntimeProperties(this ITypeBase type) + public static IReadOnlyDictionary GetRuntimeProperties([NotNull] this ITypeBase type) => (type as TypeBase).GetRuntimeProperties(); /// @@ -42,7 +42,7 @@ public static IReadOnlyDictionary GetRuntimeProperties(thi /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public static IReadOnlyDictionary GetRuntimeFields(this ITypeBase type) + public static IReadOnlyDictionary GetRuntimeFields([NotNull] this ITypeBase type) => (type as TypeBase).GetRuntimeFields(); /// @@ -51,7 +51,7 @@ public static IReadOnlyDictionary GetRuntimeFields(this IType /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public static MemberInfo FindClrMember(this TypeBase type, string name) + public static MemberInfo FindClrMember([NotNull] this TypeBase type, [NotNull] string name) { if (type.GetRuntimeProperties().TryGetValue(name, out var property)) { diff --git a/src/EFCore/Query/CollectionShaperExpression.cs b/src/EFCore/Query/CollectionShaperExpression.cs index a825efbb4ad..93922a1cf85 100644 --- a/src/EFCore/Query/CollectionShaperExpression.cs +++ b/src/EFCore/Query/CollectionShaperExpression.cs @@ -4,18 +4,23 @@ using System; using System.Collections.Generic; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query { public class CollectionShaperExpression : Expression, IPrintableExpression { public CollectionShaperExpression( - Expression projection, - Expression innerShaper, - INavigation navigation, - Type elementType) + [NotNull] Expression projection, + [NotNull] Expression innerShaper, + [CanBeNull] INavigation navigation, + [CanBeNull] Type elementType) { + Check.NotNull(projection, nameof(projection)); + Check.NotNull(innerShaper, nameof(innerShaper)); + Projection = projection; InnerShaper = innerShaper; Navigation = navigation; @@ -24,16 +29,25 @@ public CollectionShaperExpression( protected override Expression VisitChildren(ExpressionVisitor visitor) { + Check.NotNull(visitor, nameof(visitor)); + var projection = visitor.Visit(Projection); var innerShaper = visitor.Visit(InnerShaper); return Update(projection, innerShaper); } - public virtual CollectionShaperExpression Update(Expression projection, Expression innerShaper) - => projection != Projection || innerShaper != InnerShaper + public virtual CollectionShaperExpression Update( + [NotNull] Expression projection, + [NotNull] Expression innerShaper) + { + Check.NotNull(projection, nameof(projection)); + Check.NotNull(innerShaper, nameof(innerShaper)); + + return projection != Projection || innerShaper != InnerShaper ? new CollectionShaperExpression(projection, innerShaper, Navigation, ElementType) : this; + } public sealed override ExpressionType NodeType => ExpressionType.Extension; public override Type Type => Navigation?.ClrType ?? typeof(List<>).MakeGenericType(ElementType); @@ -45,6 +59,8 @@ public virtual CollectionShaperExpression Update(Expression projection, Expressi public virtual void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.AppendLine("CollectionShaper:"); using (expressionPrinter.Indent()) { diff --git a/src/EFCore/Query/EntityShaperExpression.cs b/src/EFCore/Query/EntityShaperExpression.cs index d9e95a082a9..c68aa5b45b6 100644 --- a/src/EFCore/Query/EntityShaperExpression.cs +++ b/src/EFCore/Query/EntityShaperExpression.cs @@ -3,14 +3,22 @@ using System; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query { public class EntityShaperExpression : Expression, IPrintableExpression { - public EntityShaperExpression(IEntityType entityType, Expression valueBufferExpression, bool nullable) + public EntityShaperExpression( + [NotNull] IEntityType entityType, + [NotNull] Expression valueBufferExpression, + bool nullable) { + Check.NotNull(entityType, nameof(entityType)); + Check.NotNull(valueBufferExpression, nameof(valueBufferExpression)); + EntityType = entityType; ValueBufferExpression = valueBufferExpression; IsNullable = nullable; @@ -22,31 +30,44 @@ public EntityShaperExpression(IEntityType entityType, Expression valueBufferExpr protected override Expression VisitChildren(ExpressionVisitor visitor) { + Check.NotNull(visitor, nameof(visitor)); + var valueBufferExpression = visitor.Visit(ValueBufferExpression); return Update(valueBufferExpression); } - public virtual EntityShaperExpression WithEntityType(IEntityType entityType) - => entityType != EntityType + public virtual EntityShaperExpression WithEntityType([NotNull] IEntityType entityType) + { + Check.NotNull(entityType, nameof(entityType)); + + return entityType != EntityType ? new EntityShaperExpression(entityType, ValueBufferExpression, IsNullable) : this; + } public virtual EntityShaperExpression MarkAsNullable() => !IsNullable ? new EntityShaperExpression(EntityType, ValueBufferExpression, true) : this; - public virtual EntityShaperExpression Update(Expression valueBufferExpression) - => valueBufferExpression != ValueBufferExpression + public virtual EntityShaperExpression Update([NotNull] Expression valueBufferExpression) + { + Check.NotNull(valueBufferExpression, nameof(valueBufferExpression)); + + return valueBufferExpression != ValueBufferExpression ? new EntityShaperExpression(EntityType, valueBufferExpression, IsNullable) : this; + } public override Type Type => EntityType.ClrType; + public sealed override ExpressionType NodeType => ExpressionType.Extension; public virtual void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.AppendLine(nameof(EntityShaperExpression) + ": "); using (expressionPrinter.Indent()) { diff --git a/src/EFCore/Query/EvaluatableExpressionFilter.cs b/src/EFCore/Query/EvaluatableExpressionFilter.cs index 194cb1452c6..395610dbdcb 100644 --- a/src/EFCore/Query/EvaluatableExpressionFilter.cs +++ b/src/EFCore/Query/EvaluatableExpressionFilter.cs @@ -84,6 +84,9 @@ public EvaluatableExpressionFilter( /// True if the expression can be evaluated; false otherwise. public virtual bool IsEvaluatableExpression(Expression expression, IModel model) { + Check.NotNull(expression, nameof(expression)); + Check.NotNull(model, nameof(model)); + switch (expression) { case MemberExpression memberExpression: diff --git a/src/EFCore/Query/ExpressionPrinter.cs b/src/EFCore/Query/ExpressionPrinter.cs index c3c093aa52b..ed0110f1aca 100644 --- a/src/EFCore/Query/ExpressionPrinter.cs +++ b/src/EFCore/Query/ExpressionPrinter.cs @@ -12,6 +12,7 @@ using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query { @@ -56,10 +57,12 @@ public ExpressionPrinter() private bool Verbose { get; set; } public virtual void VisitList( - IReadOnlyList items, - Action joinAction = null) + [NotNull] IReadOnlyList items, + [CanBeNull] Action joinAction = null) where T : Expression { + Check.NotNull(items, nameof(items)); + joinAction ??= (p => p.Append(", ")); for (var i = 0; i < items.Count; i++) @@ -99,29 +102,31 @@ public virtual ExpressionPrinter AppendLines([NotNull] object o, bool skipFinalN public virtual IDisposable Indent() => _stringBuilder.Indent(); - private void Append([NotNull] string message) => _stringBuilder.Append(message); + private void Append(string message) => _stringBuilder.Append(message); - private void AppendLine([NotNull] string message) + private void AppendLine(string message) { _stringBuilder.AppendLine(message); } public virtual string Print( - Expression expression, + [NotNull] Expression expression, int? characterLimit = null) => PrintCore(expression, characterLimit, verbose: false); public virtual string PrintDebug( - Expression expression, + [NotNull] Expression expression, int? characterLimit = null, bool verbose = true) => PrintCore(expression, characterLimit, verbose); protected virtual string PrintCore( - Expression expression, + [NotNull] Expression expression, int? characterLimit, bool verbose) { + Check.NotNull(expression, nameof(expression)); + _stringBuilder.Clear(); _parametersInScope.Clear(); _namelessParameters.Clear(); @@ -273,6 +278,8 @@ public override Expression Visit(Expression expression) protected override Expression VisitBinary(BinaryExpression binaryExpression) { + Check.NotNull(binaryExpression, nameof(binaryExpression)); + Visit(binaryExpression.Left); if (binaryExpression.NodeType == ExpressionType.ArrayIndex) @@ -302,6 +309,8 @@ protected override Expression VisitBinary(BinaryExpression binaryExpression) protected override Expression VisitBlock(BlockExpression blockExpression) { + Check.NotNull(blockExpression, nameof(blockExpression)); + AppendLine(); AppendLine("{"); @@ -344,6 +353,8 @@ protected override Expression VisitBlock(BlockExpression blockExpression) protected override Expression VisitConditional(ConditionalExpression conditionalExpression) { + Check.NotNull(conditionalExpression, nameof(conditionalExpression)); + Visit(conditionalExpression.Test); _stringBuilder.Append(" ? "); @@ -359,6 +370,8 @@ protected override Expression VisitConditional(ConditionalExpression conditional protected override Expression VisitConstant(ConstantExpression constantExpression) { + Check.NotNull(constantExpression, nameof(constantExpression)); + if (constantExpression.Value is IPrintableExpression printable) { printable.Print(this); @@ -408,6 +421,8 @@ private void Print(object value) protected override Expression VisitGoto(GotoExpression gotoExpression) { + Check.NotNull(gotoExpression, nameof(gotoExpression)); + AppendLine("return (" + gotoExpression.Target.Type.ShortDisplayName() + ")" + gotoExpression.Target + " {"); using (_stringBuilder.Indent()) { @@ -421,6 +436,8 @@ protected override Expression VisitGoto(GotoExpression gotoExpression) protected override Expression VisitLabel(LabelExpression labelExpression) { + Check.NotNull(labelExpression, nameof(labelExpression)); + _stringBuilder.Append(labelExpression.Target.ToString()); return labelExpression; @@ -428,6 +445,8 @@ protected override Expression VisitLabel(LabelExpression labelExpression) protected override Expression VisitLambda(Expression lambdaExpression) { + Check.NotNull(lambdaExpression, nameof(lambdaExpression)); + if (lambdaExpression.Parameters.Count != 1) { _stringBuilder.Append("("); @@ -470,6 +489,8 @@ protected override Expression VisitLambda(Expression lambdaExpression) protected override Expression VisitMember(MemberExpression memberExpression) { + Check.NotNull(memberExpression, nameof(memberExpression)); + if (memberExpression.Expression != null) { if (memberExpression.Expression.NodeType == ExpressionType.Convert @@ -497,6 +518,8 @@ protected override Expression VisitMember(MemberExpression memberExpression) protected override Expression VisitMemberInit(MemberInitExpression memberInitExpression) { + Check.NotNull(memberInitExpression, nameof(memberInitExpression)); + _stringBuilder.Append("new " + memberInitExpression.Type.ShortDisplayName()); var appendAction = memberInitExpression.Bindings.Count > 1 ? (Action)AppendLine : Append; @@ -532,6 +555,8 @@ protected override Expression VisitMemberInit(MemberInitExpression memberInitExp protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { + Check.NotNull(methodCallExpression, nameof(methodCallExpression)); + if (methodCallExpression.Object != null) { if (methodCallExpression.Object is BinaryExpression) @@ -661,6 +686,8 @@ static void PrintGenericArguments(MethodInfo method, IndentedStringBuilder strin protected override Expression VisitNew(NewExpression newExpression) { + Check.NotNull(newExpression, nameof(newExpression)); + _stringBuilder.Append("new "); var isComplex = newExpression.Arguments.Count > 1; @@ -713,6 +740,8 @@ protected override Expression VisitNew(NewExpression newExpression) protected override Expression VisitNewArray(NewArrayExpression newArrayExpression) { + Check.NotNull(newArrayExpression, nameof(newArrayExpression)); + var isComplex = newArrayExpression.Expressions.Count > 1; var appendAction = isComplex ? (Action)AppendLine : Append; @@ -739,6 +768,8 @@ protected override Expression VisitNewArray(NewArrayExpression newArrayExpressio protected override Expression VisitParameter(ParameterExpression parameterExpression) { + Check.NotNull(parameterExpression, nameof(parameterExpression)); + if (_parametersInScope.ContainsKey(parameterExpression)) { var parameterName = _parametersInScope[parameterExpression]; @@ -798,6 +829,8 @@ protected override Expression VisitParameter(ParameterExpression parameterExpres protected override Expression VisitUnary(UnaryExpression unaryExpression) { + Check.NotNull(unaryExpression, nameof(unaryExpression)); + // ReSharper disable once SwitchStatementMissingSomeCases switch (unaryExpression.NodeType) { @@ -848,6 +881,8 @@ protected override Expression VisitUnary(UnaryExpression unaryExpression) protected override Expression VisitDefault(DefaultExpression defaultExpression) { + Check.NotNull(defaultExpression, nameof(defaultExpression)); + _stringBuilder.Append("default(" + defaultExpression.Type.ShortDisplayName() + ")"); return defaultExpression; @@ -855,6 +890,8 @@ protected override Expression VisitDefault(DefaultExpression defaultExpression) protected override Expression VisitTry(TryExpression tryExpression) { + Check.NotNull(tryExpression, nameof(tryExpression)); + _stringBuilder.Append("try { "); Visit(tryExpression.Body); _stringBuilder.Append(" } "); @@ -869,6 +906,8 @@ protected override Expression VisitTry(TryExpression tryExpression) protected override Expression VisitIndex(IndexExpression indexExpression) { + Check.NotNull(indexExpression, nameof(indexExpression)); + Visit(indexExpression.Object); _stringBuilder.Append("["); VisitArguments(indexExpression.Arguments, s => _stringBuilder.Append(s)); @@ -879,6 +918,8 @@ protected override Expression VisitIndex(IndexExpression indexExpression) protected override Expression VisitTypeBinary(TypeBinaryExpression typeBinaryExpression) { + Check.NotNull(typeBinaryExpression, nameof(typeBinaryExpression)); + _stringBuilder.Append("("); Visit(typeBinaryExpression.Expression); _stringBuilder.Append(" is " + typeBinaryExpression.TypeOperand.ShortDisplayName() + ")"); @@ -888,6 +929,8 @@ protected override Expression VisitTypeBinary(TypeBinaryExpression typeBinaryExp protected override Expression VisitExtension(Expression extensionExpression) { + Check.NotNull(extensionExpression, nameof(extensionExpression)); + if (extensionExpression is IPrintableExpression printable) { _stringBuilder.Append("("); diff --git a/src/EFCore/Query/GroupByShaperExpression.cs b/src/EFCore/Query/GroupByShaperExpression.cs index 17f1e3529e1..6fabdce63bc 100644 --- a/src/EFCore/Query/GroupByShaperExpression.cs +++ b/src/EFCore/Query/GroupByShaperExpression.cs @@ -4,13 +4,20 @@ using System; using System.Linq; using System.Linq.Expressions; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query { public class GroupByShaperExpression : Expression, IPrintableExpression { - public GroupByShaperExpression(Expression keySelector, Expression elementSelector) + public GroupByShaperExpression( + [NotNull] Expression keySelector, + [NotNull] Expression elementSelector) { + Check.NotNull(keySelector, nameof(keySelector)); + Check.NotNull(elementSelector, nameof(elementSelector)); + KeySelector = keySelector; ElementSelector = elementSelector; } @@ -23,6 +30,8 @@ public GroupByShaperExpression(Expression keySelector, Expression elementSelecto public virtual void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.AppendLine($"{nameof(GroupByShaperExpression)}:"); expressionPrinter.Append("KeySelector: "); expressionPrinter.Visit(KeySelector); @@ -34,15 +43,22 @@ public virtual void Print(ExpressionPrinter expressionPrinter) protected override Expression VisitChildren(ExpressionVisitor visitor) { + Check.NotNull(visitor, nameof(visitor)); + var keySelector = visitor.Visit(KeySelector); var elementSelector = visitor.Visit(ElementSelector); return Update(keySelector, elementSelector); } - public virtual GroupByShaperExpression Update(Expression keySelector, Expression elementSelector) - => keySelector != KeySelector || elementSelector != ElementSelector + public virtual GroupByShaperExpression Update([NotNull] Expression keySelector, [NotNull] Expression elementSelector) + { + Check.NotNull(keySelector, nameof(keySelector)); + Check.NotNull(elementSelector, nameof(elementSelector)); + + return keySelector != KeySelector || elementSelector != ElementSelector ? new GroupByShaperExpression(keySelector, elementSelector) : this; + } } } diff --git a/src/EFCore/Query/IEvaluatableExpressionFilter.cs b/src/EFCore/Query/IEvaluatableExpressionFilter.cs index 8b8f62f9252..d461a93e17e 100644 --- a/src/EFCore/Query/IEvaluatableExpressionFilter.cs +++ b/src/EFCore/Query/IEvaluatableExpressionFilter.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.Extensions.DependencyInjection; @@ -25,6 +26,6 @@ public interface IEvaluatableExpressionFilter /// The expression. /// The model. /// True if the expression can be evaluated; false otherwise. - bool IsEvaluatableExpression(Expression expression, IModel model); + bool IsEvaluatableExpression([NotNull] Expression expression, [NotNull] IModel model); } } diff --git a/src/EFCore/Query/IQueryTranslationPostprocessorFactory.cs b/src/EFCore/Query/IQueryTranslationPostprocessorFactory.cs index 57720185037..4fe2bf04778 100644 --- a/src/EFCore/Query/IQueryTranslationPostprocessorFactory.cs +++ b/src/EFCore/Query/IQueryTranslationPostprocessorFactory.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; namespace Microsoft.EntityFrameworkCore.Query @@ -17,6 +18,6 @@ namespace Microsoft.EntityFrameworkCore.Query /// public interface IQueryTranslationPostprocessorFactory { - QueryTranslationPostprocessor Create(QueryCompilationContext queryCompilationContext); + QueryTranslationPostprocessor Create([NotNull] QueryCompilationContext queryCompilationContext); } } diff --git a/src/EFCore/Query/IQueryTranslationPreprocessorFactory.cs b/src/EFCore/Query/IQueryTranslationPreprocessorFactory.cs index c6601c07622..6067aeb65ed 100644 --- a/src/EFCore/Query/IQueryTranslationPreprocessorFactory.cs +++ b/src/EFCore/Query/IQueryTranslationPreprocessorFactory.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; namespace Microsoft.EntityFrameworkCore.Query @@ -17,6 +18,6 @@ namespace Microsoft.EntityFrameworkCore.Query /// public interface IQueryTranslationPreprocessorFactory { - QueryTranslationPreprocessor Create(QueryCompilationContext queryCompilationContext); + QueryTranslationPreprocessor Create([NotNull] QueryCompilationContext queryCompilationContext); } } diff --git a/src/EFCore/Query/IQueryableMethodTranslatingExpressionVisitorFactory.cs b/src/EFCore/Query/IQueryableMethodTranslatingExpressionVisitorFactory.cs index f6e3935df57..b45e36ed189 100644 --- a/src/EFCore/Query/IQueryableMethodTranslatingExpressionVisitorFactory.cs +++ b/src/EFCore/Query/IQueryableMethodTranslatingExpressionVisitorFactory.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.Extensions.DependencyInjection; @@ -18,6 +19,6 @@ namespace Microsoft.EntityFrameworkCore.Query /// public interface IQueryableMethodTranslatingExpressionVisitorFactory { - QueryableMethodTranslatingExpressionVisitor Create(IModel model); + QueryableMethodTranslatingExpressionVisitor Create([NotNull] IModel model); } } diff --git a/src/EFCore/Query/IShapedQueryCompilingExpressionVisitorFactory.cs b/src/EFCore/Query/IShapedQueryCompilingExpressionVisitorFactory.cs index 9f873e7b3a0..0db1452263a 100644 --- a/src/EFCore/Query/IShapedQueryCompilingExpressionVisitorFactory.cs +++ b/src/EFCore/Query/IShapedQueryCompilingExpressionVisitorFactory.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; namespace Microsoft.EntityFrameworkCore.Query @@ -17,6 +18,6 @@ namespace Microsoft.EntityFrameworkCore.Query /// public interface IShapedQueryCompilingExpressionVisitorFactory { - ShapedQueryCompilingExpressionVisitor Create(QueryCompilationContext queryCompilationContext); + ShapedQueryCompilingExpressionVisitor Create([NotNull] QueryCompilationContext queryCompilationContext); } } diff --git a/src/EFCore/Query/IncludeExpression.cs b/src/EFCore/Query/IncludeExpression.cs index 3c7feefd68c..79befb81b9b 100644 --- a/src/EFCore/Query/IncludeExpression.cs +++ b/src/EFCore/Query/IncludeExpression.cs @@ -3,42 +3,78 @@ using System; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query { public class IncludeExpression : Expression, IPrintableExpression { - public IncludeExpression(Expression entityExpression, Expression navigationExpression, INavigation navigation) + private Expression _entityExpression; + private Expression _navigationExpression; + private INavigation _navigation; + + public IncludeExpression( + [NotNull] Expression entityExpression, + [NotNull] Expression navigationExpression, + [NotNull] INavigation navigation) { + Check.NotNull(entityExpression, nameof(entityExpression)); + Check.NotNull(navigationExpression, nameof(navigationExpression)); + Check.NotNull(navigation, nameof(navigation)); + EntityExpression = entityExpression; NavigationExpression = navigationExpression; Navigation = navigation; Type = EntityExpression.Type; } - public virtual Expression EntityExpression { get; set; } - public virtual Expression NavigationExpression { get; set; } - public virtual INavigation Navigation { get; set; } + public virtual Expression EntityExpression + { + get => _entityExpression; + [param: NotNull] set => _entityExpression = Check.NotNull(value, nameof(value)); + } + + public virtual Expression NavigationExpression + { + get => _navigationExpression; + [param: NotNull] set => _navigationExpression = Check.NotNull(value, nameof(value)); + } + + public virtual INavigation Navigation + { + get => _navigation; + [param: NotNull] set => _navigation = Check.NotNull(value, nameof(value)); + } public sealed override ExpressionType NodeType => ExpressionType.Extension; public override Type Type { get; } protected override Expression VisitChildren(ExpressionVisitor visitor) { + Check.NotNull(visitor, nameof(visitor)); + var newEntityExpression = visitor.Visit(EntityExpression); var newNavigationExpression = visitor.Visit(NavigationExpression); return Update(newEntityExpression, newNavigationExpression); } - public virtual IncludeExpression Update(Expression entityExpression, Expression navigationExpression) - => entityExpression != EntityExpression || navigationExpression != NavigationExpression + public virtual IncludeExpression Update([NotNull] Expression entityExpression, [NotNull] Expression navigationExpression) + { + Check.NotNull(entityExpression, nameof(entityExpression)); + Check.NotNull(navigationExpression, nameof(navigationExpression)); + + return entityExpression != EntityExpression || navigationExpression != NavigationExpression ? new IncludeExpression(entityExpression, navigationExpression, Navigation) : this; + } public virtual void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.AppendLine("IncludeExpression("); using (expressionPrinter.Indent()) { diff --git a/src/EFCore/Query/Internal/AllAnyToContainsRewritingExpressionVisitor.cs b/src/EFCore/Query/Internal/AllAnyToContainsRewritingExpressionVisitor.cs index 173c25741ed..58425eaacc5 100644 --- a/src/EFCore/Query/Internal/AllAnyToContainsRewritingExpressionVisitor.cs +++ b/src/EFCore/Query/Internal/AllAnyToContainsRewritingExpressionVisitor.cs @@ -5,6 +5,7 @@ using System.Linq.Expressions; using System.Reflection; using Microsoft.EntityFrameworkCore.Internal; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.Internal { @@ -16,6 +17,8 @@ private static bool IsExpressionOfFunc(Type type, int funcGenericArgs = 2) protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { + Check.NotNull(methodCallExpression, nameof(methodCallExpression)); + if (methodCallExpression.Method.IsGenericMethod && methodCallExpression.Method.GetGenericMethodDefinition() is MethodInfo methodInfo && (methodInfo.Equals(EnumerableMethods.AnyWithPredicate) || methodInfo.Equals(EnumerableMethods.All)) diff --git a/src/EFCore/Query/Internal/CompiledQueryBase.cs b/src/EFCore/Query/Internal/CompiledQueryBase.cs index 9e8e610fad1..fdb72681a32 100644 --- a/src/EFCore/Query/Internal/CompiledQueryBase.cs +++ b/src/EFCore/Query/Internal/CompiledQueryBase.cs @@ -10,6 +10,7 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.Internal { @@ -111,6 +112,8 @@ public QueryExpressionRewriter( protected override Expression VisitParameter(ParameterExpression parameterExpression) { + Check.NotNull(parameterExpression, nameof(parameterExpression)); + if (typeof(TContext).IsAssignableFrom(parameterExpression.Type)) { return Expression.Constant(_context); diff --git a/src/EFCore/Query/Internal/EntityEqualityRewritingExpressionVisitor.cs b/src/EFCore/Query/Internal/EntityEqualityRewritingExpressionVisitor.cs index 6dac4719cf4..afa4f07cc81 100644 --- a/src/EFCore/Query/Internal/EntityEqualityRewritingExpressionVisitor.cs +++ b/src/EFCore/Query/Internal/EntityEqualityRewritingExpressionVisitor.cs @@ -14,6 +14,7 @@ using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.Internal { @@ -41,23 +42,30 @@ private static readonly MethodInfo _objectEqualsMethodInfo .GetDeclaredMethods(nameof(Enumerable.Contains)) .Single(mi => mi.GetParameters().Length == 2); - public EntityEqualityRewritingExpressionVisitor(QueryCompilationContext queryCompilationContext) + public EntityEqualityRewritingExpressionVisitor([NotNull] QueryCompilationContext queryCompilationContext) { _queryCompilationContext = queryCompilationContext; _logger = queryCompilationContext.Logger; } - public virtual Expression Rewrite(Expression expression) => Unwrap(Visit(expression)); + public virtual Expression Rewrite([NotNull] Expression expression) + => Unwrap(Visit(expression)); protected override Expression VisitConstant(ConstantExpression constantExpression) - => constantExpression.IsEntityQueryable() + { + Check.NotNull(constantExpression, nameof(constantExpression)); + + return constantExpression.IsEntityQueryable() ? new EntityReferenceExpression( constantExpression, _queryCompilationContext.Model.FindEntityType(((IQueryable)constantExpression.Value).ElementType)) : (Expression)constantExpression; + } protected override Expression VisitNew(NewExpression newExpression) { + Check.NotNull(newExpression, nameof(newExpression)); + var visitedArgs = Visit(newExpression.Arguments); var visitedExpression = newExpression.Update(visitedArgs.Select(Unwrap)); @@ -83,6 +91,8 @@ protected override Expression VisitNew(NewExpression newExpression) protected override Expression VisitMemberInit(MemberInitExpression memberInitExpression) { + Check.NotNull(memberInitExpression, nameof(memberInitExpression)); + var visitedNew = Visit(memberInitExpression.NewExpression); var (visitedBindings, entityReferenceInfo) = VisitMemberBindings(memberInitExpression.Bindings); var visitedMemberInit = memberInitExpression.Update((NewExpression)Unwrap(visitedNew), visitedBindings); @@ -130,20 +140,34 @@ protected override Expression VisitMemberInit(MemberInitExpression memberInitExp // Note that we could bubble up entity type information from the expressions initializing the array. However, EF Core doesn't // actually support doing much further with this array, so it's not worth the complexity (right now). So we simply unwrap. protected override Expression VisitNewArray(NewArrayExpression newArrayExpression) - => newArrayExpression.Update(Visit(newArrayExpression.Expressions).Select(Unwrap)); + { + Check.NotNull(newArrayExpression, nameof(newArrayExpression)); + + return newArrayExpression.Update(Visit(newArrayExpression.Expressions).Select(Unwrap)); + } // Note that we could bubble up entity type information from the expressions initializing the list. However, EF Core doesn't // actually support doing much further with this list, so it's not worth the complexity (right now). So we simply unwrap. protected override Expression VisitListInit(ListInitExpression listInitExpression) - => listInitExpression.Update( + { + Check.NotNull(listInitExpression, nameof(listInitExpression)); + + return listInitExpression.Update( (NewExpression)Unwrap(listInitExpression.NewExpression), listInitExpression.Initializers.Select(VisitElementInit)); + } protected override ElementInit VisitElementInit(ElementInit elementInit) - => Expression.ElementInit(elementInit.AddMethod, Visit(elementInit.Arguments).Select(Unwrap)); + { + Check.NotNull(elementInit, nameof(elementInit)); + + return Expression.ElementInit(elementInit.AddMethod, Visit(elementInit.Arguments).Select(Unwrap)); + } protected override Expression VisitMember(MemberExpression memberExpression) { + Check.NotNull(memberExpression, nameof(memberExpression)); + var visitedExpression = base.Visit(memberExpression.Expression); var visitedMemberExpression = memberExpression.Update(Unwrap(visitedExpression)); return visitedExpression is EntityReferenceExpression entityWrapper @@ -153,6 +177,8 @@ protected override Expression VisitMember(MemberExpression memberExpression) protected override Expression VisitBinary(BinaryExpression binaryExpression) { + Check.NotNull(binaryExpression, nameof(binaryExpression)); + var (newLeft, newRight) = (Visit(binaryExpression.Left), Visit(binaryExpression.Right)); if (binaryExpression.NodeType == ExpressionType.Equal || binaryExpression.NodeType == ExpressionType.NotEqual) @@ -168,6 +194,8 @@ protected override Expression VisitBinary(BinaryExpression binaryExpression) protected override Expression VisitUnary(UnaryExpression unaryExpression) { + Check.NotNull(unaryExpression, nameof(unaryExpression)); + var newOperand = Visit(unaryExpression.Operand); var newUnary = unaryExpression.Update(Unwrap(newOperand)); @@ -196,6 +224,8 @@ protected override Expression VisitUnary(UnaryExpression unaryExpression) protected override Expression VisitTypeBinary(TypeBinaryExpression typeBinaryExpression) { + Check.NotNull(typeBinaryExpression, nameof(typeBinaryExpression)); + // This is for "x is y" var visitedExpression = Visit(typeBinaryExpression.Expression); var visitedTypeBinary = typeBinaryExpression.Update(Unwrap(visitedExpression)); @@ -206,6 +236,8 @@ protected override Expression VisitTypeBinary(TypeBinaryExpression typeBinaryExp protected override Expression VisitConditional(ConditionalExpression conditionalExpression) { + Check.NotNull(conditionalExpression, nameof(conditionalExpression)); + var newTest = Visit(conditionalExpression.Test); var newIfTrue = Visit(conditionalExpression.IfTrue); var newIfFalse = Visit(conditionalExpression.IfFalse); @@ -221,6 +253,8 @@ protected override Expression VisitConditional(ConditionalExpression conditional protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { + Check.NotNull(methodCallExpression, nameof(methodCallExpression)); + var method = methodCallExpression.Method; var genericMethod = method.IsGenericMethod ? method.GetGenericMethodDefinition() : null; var arguments = methodCallExpression.Arguments; @@ -893,6 +927,8 @@ private Expression RewriteEntityEquality( protected override Expression VisitExtension(Expression extensionExpression) { + Check.NotNull(extensionExpression, nameof(extensionExpression)); + // If the expression is an EntityReferenceExpression, simply returns it as all rewriting has already occurred. // This is necessary when traversing wrapping expressions that have been injected into the lambda for parameters. return extensionExpression is EntityReferenceExpression @@ -1005,14 +1041,18 @@ private static readonly MethodInfo _parameterListValueExtractor .GetTypeInfo() .GetDeclaredMethod(nameof(ParameterListValueExtractor)); - protected static Expression UnwrapLastNavigation(Expression expression) - => (expression as MemberExpression)?.Expression + protected static Expression UnwrapLastNavigation([NotNull] Expression expression) + { + Check.NotNull(expression, nameof(expression)); + + return (expression as MemberExpression)?.Expression ?? (expression is MethodCallExpression methodCallExpression && methodCallExpression.Method.IsEFPropertyMethod() ? methodCallExpression.Arguments[0] : null); + } - protected static Expression Unwrap(Expression expression) + protected static Expression Unwrap([NotNull] Expression expression) => expression switch { EntityReferenceExpression wrapper => wrapper.Underlying, @@ -1143,10 +1183,16 @@ public EntityReferenceExpression Update(Expression newUnderlying) => new EntityReferenceExpression(newUnderlying, EntityType, null, DtoType, SubqueryTraversed); protected override Expression VisitChildren(ExpressionVisitor visitor) - => Update(visitor.Visit(Underlying)); + { + Check.NotNull(visitor, nameof(visitor)); + + return Update(visitor.Visit(Underlying)); + } public virtual void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.Visit(Underlying); if (IsEntityType) diff --git a/src/EFCore/Query/Internal/EnumerableToQueryableMethodConvertingExpressionVisitor.cs b/src/EFCore/Query/Internal/EnumerableToQueryableMethodConvertingExpressionVisitor.cs index 449595f748a..922b36a70b7 100644 --- a/src/EFCore/Query/Internal/EnumerableToQueryableMethodConvertingExpressionVisitor.cs +++ b/src/EFCore/Query/Internal/EnumerableToQueryableMethodConvertingExpressionVisitor.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Linq.Expressions; using System.Reflection; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.Internal { @@ -14,6 +15,8 @@ public class EnumerableToQueryableMethodConvertingExpressionVisitor : Expression { protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { + Check.NotNull(methodCallExpression, nameof(methodCallExpression)); + if (methodCallExpression.Method.DeclaringType == typeof(Enumerable)) { if (methodCallExpression.Method.Name == nameof(Enumerable.SequenceEqual)) diff --git a/src/EFCore/Query/Internal/FunctionPreprocessingExpressionVisitor.cs b/src/EFCore/Query/Internal/FunctionPreprocessingExpressionVisitor.cs index dabf281fcb7..62699b065a0 100644 --- a/src/EFCore/Query/Internal/FunctionPreprocessingExpressionVisitor.cs +++ b/src/EFCore/Query/Internal/FunctionPreprocessingExpressionVisitor.cs @@ -3,6 +3,7 @@ using System.Linq.Expressions; using System.Reflection; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.Internal { @@ -18,6 +19,8 @@ private static readonly MethodInfo _endsWithMethodInfo protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { + Check.NotNull(methodCallExpression, nameof(methodCallExpression)); + if (_startsWithMethodInfo.Equals(methodCallExpression.Method) || _endsWithMethodInfo.Equals(methodCallExpression.Method)) { @@ -51,6 +54,8 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp protected override Expression VisitUnary(UnaryExpression unaryExpression) { + Check.NotNull(unaryExpression, nameof(unaryExpression)); + if (unaryExpression.NodeType == ExpressionType.Not && unaryExpression.Operand is MethodCallExpression innerMethodCall && (_startsWithMethodInfo.Equals(innerMethodCall.Method) diff --git a/src/EFCore/Query/Internal/GroupJoinFlatteningExpressionVisitor.cs b/src/EFCore/Query/Internal/GroupJoinFlatteningExpressionVisitor.cs index 3f5361082d3..0f632ab3543 100644 --- a/src/EFCore/Query/Internal/GroupJoinFlatteningExpressionVisitor.cs +++ b/src/EFCore/Query/Internal/GroupJoinFlatteningExpressionVisitor.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Internal; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.Internal { @@ -19,6 +20,8 @@ private readonly SelectManyVerifyingExpressionVisitor _selectManyVerifyingExpres protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { + Check.NotNull(methodCallExpression, nameof(methodCallExpression)); + if (methodCallExpression.Method.DeclaringType == typeof(Queryable) && methodCallExpression.Method.IsGenericMethod) { @@ -291,6 +294,8 @@ public bool VerifyCollectionSelector(Expression body, ParameterExpression rootPa protected override Expression VisitLambda(Expression lambdaExpression) { + Check.NotNull(lambdaExpression, nameof(lambdaExpression)); + try { _allowedParameters.AddRange(lambdaExpression.Parameters); @@ -308,6 +313,8 @@ protected override Expression VisitLambda(Expression lambdaExpression) protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { + Check.NotNull(methodCallExpression, nameof(methodCallExpression)); + if (_correlated) { return methodCallExpression; @@ -337,6 +344,8 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp protected override Expression VisitParameter(ParameterExpression parameterExpression) { + Check.NotNull(parameterExpression, nameof(parameterExpression)); + if (_allowedParameters.Contains(parameterExpression)) { return parameterExpression; diff --git a/src/EFCore/Query/Internal/InvocationExpressionRemovingExpressionVisitor.cs b/src/EFCore/Query/Internal/InvocationExpressionRemovingExpressionVisitor.cs index 960cb76b114..7e32bd41d0d 100644 --- a/src/EFCore/Query/Internal/InvocationExpressionRemovingExpressionVisitor.cs +++ b/src/EFCore/Query/Internal/InvocationExpressionRemovingExpressionVisitor.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq.Expressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.Internal { @@ -11,6 +12,8 @@ public class InvocationExpressionRemovingExpressionVisitor : ExpressionVisitor { protected override Expression VisitInvocation(InvocationExpression invocationExpression) { + Check.NotNull(invocationExpression, nameof(invocationExpression)); + var invokedExpression = StripTrivialConversions(invocationExpression.Expression); return invokedExpression is LambdaExpression lambdaExpression diff --git a/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.ExpressionVisitors.cs b/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.ExpressionVisitors.cs index 01fd59e8da7..970dc1d1e68 100644 --- a/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.ExpressionVisitors.cs +++ b/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.ExpressionVisitors.cs @@ -9,6 +9,7 @@ using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.Internal { @@ -41,6 +42,8 @@ public Expression Expand(Expression expression, bool applyIncludes = false) protected override Expression VisitExtension(Expression expression) { + Check.NotNull(expression, nameof(expression)); + switch (expression) { case NavigationExpansionExpression _: @@ -54,6 +57,8 @@ protected override Expression VisitExtension(Expression expression) protected override Expression VisitMember(MemberExpression memberExpression) { + Check.NotNull(memberExpression, nameof(memberExpression)); + var innerExpression = Visit(memberExpression.Expression); return TryExpandNavigation(innerExpression, MemberIdentity.Create(memberExpression.Member)) ?? memberExpression.Update(innerExpression); @@ -61,6 +66,8 @@ protected override Expression VisitMember(MemberExpression memberExpression) protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { + Check.NotNull(methodCallExpression, nameof(methodCallExpression)); + if (methodCallExpression.TryGetEFPropertyArguments(out var source, out var navigationName)) { source = Visit(source); @@ -308,6 +315,8 @@ public IncludeExpandingExpressionVisitor( protected override Expression VisitExtension(Expression extensionExpression) { + Check.NotNull(extensionExpression, nameof(extensionExpression)); + switch (extensionExpression) { case NavigationTreeExpression navigationTreeExpression: @@ -338,6 +347,8 @@ protected override Expression VisitExtension(Expression extensionExpression) protected override Expression VisitMember(MemberExpression memberExpression) { + Check.NotNull(memberExpression, nameof(memberExpression)); + if (UnwrapEntityReference(memberExpression.Expression) is EntityReference entityReferece) { // If it is mapped property then, it would get converted to a column so we don't need to expand includes. @@ -353,6 +364,8 @@ protected override Expression VisitMember(MemberExpression memberExpression) protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { + Check.NotNull(methodCallExpression, nameof(methodCallExpression)); + if (methodCallExpression.TryGetEFPropertyArguments(out var _, out var __)) { // If it is EF.Property then, it would get converted to a column or throw @@ -365,6 +378,8 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp protected override Expression VisitNew(NewExpression newExpression) { + Check.NotNull(newExpression, nameof(newExpression)); + var arguments = new Expression[newExpression.Arguments.Count]; for (var i = 0; i < newExpression.Arguments.Count; i++) { @@ -611,6 +626,8 @@ public SelfReferenceEntityQueryableRewritingExpressionVisitor( protected override Expression VisitConstant(ConstantExpression constantExpression) { + Check.NotNull(constantExpression, nameof(constantExpression)); + if (constantExpression.IsEntityQueryable()) { var entityType = diff --git a/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.Expressions.cs b/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.Expressions.cs index 1a232e41e48..a4ab8d7ce48 100644 --- a/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.Expressions.cs +++ b/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.Expressions.cs @@ -9,6 +9,7 @@ using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.Internal { @@ -30,7 +31,13 @@ public EntityReference(IEntityType entityType) public virtual IncludeTreeNode LastIncludeTreeNode { get; private set; } public override ExpressionType NodeType => ExpressionType.Extension; public override Type Type => EntityType.ClrType; - protected override Expression VisitChildren(ExpressionVisitor visitor) => this; + + protected override Expression VisitChildren(ExpressionVisitor visitor) + { + Check.NotNull(visitor, nameof(visitor)); + + return this; + } public virtual void SetIncludePaths(IncludeTreeNode includePaths) { @@ -52,6 +59,8 @@ public virtual EntityReference Clone() public virtual void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.Append($"{nameof(EntityReference)}: {EntityType.DisplayName()}"); if (IsOptional) { @@ -213,10 +222,17 @@ public virtual void ConvertToSingleResult(MethodInfo genericMethod) public override Type Type => CardinalityReducingGenericMethodInfo == null ? typeof(IQueryable<>).MakeGenericType(PendingSelector.Type) : PendingSelector.Type; - protected override Expression VisitChildren(ExpressionVisitor visitor) => this; + protected override Expression VisitChildren(ExpressionVisitor visitor) + { + Check.NotNull(visitor, nameof(visitor)); + + return this; + } public virtual void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.AppendLine(nameof(NavigationExpansionExpression)); using (expressionPrinter.Indent()) { @@ -246,6 +262,8 @@ public NavigationTreeExpression(Expression value) protected override Expression VisitChildren(ExpressionVisitor visitor) { + Check.NotNull(visitor, nameof(visitor)); + Value = visitor.Visit(Value); return this; @@ -255,6 +273,8 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) public virtual void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.AppendLine(nameof(NavigationTreeExpression)); using (expressionPrinter.Indent()) { @@ -329,6 +349,8 @@ public OwnedNavigationReference(Expression parent, INavigation navigation, Entit protected override Expression VisitChildren(ExpressionVisitor visitor) { + Check.NotNull(visitor, nameof(visitor)); + Parent = visitor.Visit(Parent); return this; diff --git a/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.cs b/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.cs index c2e2cbbfd77..148af715ff0 100644 --- a/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.cs +++ b/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.cs @@ -6,11 +6,13 @@ using System.Linq; using System.Linq.Expressions; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.Internal { @@ -20,6 +22,7 @@ private static readonly PropertyInfo _queryContextContextPropertyInfo = typeof(QueryContext) .GetTypeInfo() .GetDeclaredProperty(nameof(QueryContext.Context)); + private static readonly IDictionary _predicateLessMethodInfo = new Dictionary { { QueryableMethods.FirstWithPredicate, QueryableMethods.FirstWithoutPredicate }, @@ -39,13 +42,15 @@ private static readonly PropertyInfo _queryContextContextPropertyInfo private readonly EnumerableToQueryableMethodConvertingExpressionVisitor _enumerableToQueryableMethodConvertingExpressionVisitor; private readonly EntityEqualityRewritingExpressionVisitor _entityEqualityRewritingExpressionVisitor; private readonly ParameterExtractingExpressionVisitor _parameterExtractingExpressionVisitor; + private readonly Dictionary _parameterizedQueryFilterPredicateCache = new Dictionary(); + private readonly Parameters _parameters = new Parameters(); public NavigationExpandingExpressionVisitor( - QueryCompilationContext queryCompilationContext, - IEvaluatableExpressionFilter evaluatableExpressionFilter) + [NotNull] QueryCompilationContext queryCompilationContext, + [NotNull] IEvaluatableExpressionFilter evaluatableExpressionFilter) { _queryCompilationContext = queryCompilationContext; _pendingSelectorExpandingExpressionVisitor = new PendingSelectorExpandingExpressionVisitor(this); @@ -64,7 +69,7 @@ public NavigationExpandingExpressionVisitor( generateContextAccessors: true); } - public virtual Expression Expand(Expression query) + public virtual Expression Expand([NotNull] Expression query) { var result = Visit(query); result = new PendingSelectorExpandingExpressionVisitor(this, applyIncludes: true).Visit(result); @@ -99,6 +104,8 @@ public virtual Expression Expand(Expression query) protected override Expression VisitConstant(ConstantExpression constantExpression) { + Check.NotNull(constantExpression, nameof(constantExpression)); + if (constantExpression.IsEntityQueryable()) { var entityType = _queryCompilationContext.Model.FindEntityType(((IQueryable)constantExpression.Value).ElementType); @@ -129,6 +136,8 @@ protected override Expression VisitConstant(ConstantExpression constantExpressio protected override Expression VisitExtension(Expression extensionExpression) { + Check.NotNull(extensionExpression, nameof(extensionExpression)); + return extensionExpression is NavigationExpansionExpression || extensionExpression is OwnedNavigationReference ? extensionExpression @@ -137,6 +146,8 @@ protected override Expression VisitExtension(Expression extensionExpression) protected override Expression VisitMember(MemberExpression memberExpression) { + Check.NotNull(memberExpression, nameof(memberExpression)); + var innerExpression = Visit(memberExpression.Expression); // Convert CollectionNavigation.Count to subquery.Count() @@ -177,6 +188,8 @@ protected override Expression VisitMember(MemberExpression memberExpression) protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { + Check.NotNull(methodCallExpression, nameof(methodCallExpression)); + var method = methodCallExpression.Method; if (method.DeclaringType == typeof(Queryable) || method.DeclaringType == typeof(QueryableExtensions) diff --git a/src/EFCore/Query/Internal/NegationOptimizingExpressionVisitor.cs b/src/EFCore/Query/Internal/NegationOptimizingExpressionVisitor.cs index 3aaf1eee74b..30dcd7f4c0b 100644 --- a/src/EFCore/Query/Internal/NegationOptimizingExpressionVisitor.cs +++ b/src/EFCore/Query/Internal/NegationOptimizingExpressionVisitor.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Internal; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.Internal { @@ -33,6 +34,8 @@ private static ExpressionType Negate(ExpressionType expressionType) protected override Expression VisitUnary(UnaryExpression unaryExpression) { + Check.NotNull(unaryExpression, nameof(unaryExpression)); + if (unaryExpression.NodeType == ExpressionType.Not && unaryExpression.IsLogicalNot()) { diff --git a/src/EFCore/Query/Internal/NullCheckRemovingExpressionVisitor.cs b/src/EFCore/Query/Internal/NullCheckRemovingExpressionVisitor.cs index e703906cedd..a08b8619e93 100644 --- a/src/EFCore/Query/Internal/NullCheckRemovingExpressionVisitor.cs +++ b/src/EFCore/Query/Internal/NullCheckRemovingExpressionVisitor.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq.Expressions; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.Internal { @@ -13,6 +14,8 @@ private readonly NullSafeAccessVerifyingExpressionVisitor _nullSafeAccessVerifyi protected override Expression VisitConditional(ConditionalExpression conditionalExpression) { + Check.NotNull(conditionalExpression, nameof(conditionalExpression)); + var test = Visit(conditionalExpression.Test); if (test is BinaryExpression binaryTest @@ -65,6 +68,8 @@ public override Expression Visit(Expression expression) protected override Expression VisitMember(MemberExpression memberExpression) { + Check.NotNull(memberExpression, nameof(memberExpression)); + var innerExpression = Visit(memberExpression.Expression); if (_nullSafeAccesses.Contains(innerExpression)) { @@ -76,6 +81,8 @@ protected override Expression VisitMember(MemberExpression memberExpression) protected override Expression VisitUnary(UnaryExpression unaryExpression) { + Check.NotNull(unaryExpression, nameof(unaryExpression)); + var operand = Visit(unaryExpression.Operand); if ((unaryExpression.NodeType == ExpressionType.Convert || unaryExpression.NodeType == ExpressionType.ConvertChecked) diff --git a/src/EFCore/Query/Internal/ParameterExtractingExpressionVisitor.cs b/src/EFCore/Query/Internal/ParameterExtractingExpressionVisitor.cs index bbfca3c5624..b767c0215f0 100644 --- a/src/EFCore/Query/Internal/ParameterExtractingExpressionVisitor.cs +++ b/src/EFCore/Query/Internal/ParameterExtractingExpressionVisitor.cs @@ -7,10 +7,12 @@ using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.Internal { @@ -44,20 +46,22 @@ private readonly Dictionary _evaluatedValues /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public ParameterExtractingExpressionVisitor( - IEvaluatableExpressionFilter evaluatableExpressionFilter, - IParameterValues parameterValues, - Type contextType, - IModel model, - IDiagnosticsLogger logger, + [NotNull] IEvaluatableExpressionFilter evaluatableExpressionFilter, + [NotNull] IParameterValues parameterValues, + [NotNull] Type contextType, + [NotNull] IModel model, + [NotNull] IDiagnosticsLogger logger, bool parameterize, bool generateContextAccessors) { _evaluatableExpressionFindingExpressionVisitor = new EvaluatableExpressionFindingExpressionVisitor(evaluatableExpressionFilter, model); + _parameterValues = parameterValues; _logger = logger; _parameterize = parameterize; _generateContextAccessors = generateContextAccessors; + if (_generateContextAccessors) { _contextParameterReplacingExpressionVisitor = new ContextParameterReplacingExpressionVisitor(contextType); @@ -70,7 +74,7 @@ public ParameterExtractingExpressionVisitor( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual Expression ExtractParameters(Expression expression) + public virtual Expression ExtractParameters([NotNull] Expression expression) { var oldEvaluatableExpressions = _evaluatableExpressions; _evaluatableExpressions = _evaluatableExpressionFindingExpressionVisitor.Find(expression); @@ -150,6 +154,8 @@ private bool PreserveConvertNode(Expression expression) /// protected override Expression VisitConditional(ConditionalExpression conditionalExpression) { + Check.NotNull(conditionalExpression, nameof(conditionalExpression)); + var newTestExpression = TryGetConstantValue(conditionalExpression.Test) ?? Visit(conditionalExpression.Test); if (newTestExpression is ConstantExpression constantTestExpression @@ -174,6 +180,8 @@ protected override Expression VisitConditional(ConditionalExpression conditional /// protected override Expression VisitBinary(BinaryExpression binaryExpression) { + Check.NotNull(binaryExpression, nameof(binaryExpression)); + switch (binaryExpression.NodeType) { case ExpressionType.Coalesce: @@ -244,6 +252,8 @@ private static bool ShortCircuitLogicalExpression(Expression expression, Express /// protected override Expression VisitConstant(ConstantExpression constantExpression) { + Check.NotNull(constantExpression, nameof(constantExpression)); + if (constantExpression.Value is IDetachableContext detachableContext) { var queryProvider = ((IQueryable)constantExpression.Value).Provider; @@ -513,6 +523,8 @@ public override Expression Visit(Expression expression) protected override Expression VisitLambda(Expression lambdaExpression) { + Check.NotNull(lambdaExpression, nameof(lambdaExpression)); + var oldInLambda = _inLambda; _inLambda = true; @@ -526,6 +538,8 @@ protected override Expression VisitLambda(Expression lambdaExpression) protected override Expression VisitMemberInit(MemberInitExpression memberInitExpression) { + Check.NotNull(memberInitExpression, nameof(memberInitExpression)); + Visit(memberInitExpression.Bindings, VisitMemberBinding); // Cannot make parameter for NewExpression if Bindings cannot be evaluated @@ -539,6 +553,8 @@ protected override Expression VisitMemberInit(MemberInitExpression memberInitExp protected override Expression VisitListInit(ListInitExpression listInitExpression) { + Check.NotNull(listInitExpression, nameof(listInitExpression)); + Visit(listInitExpression.Initializers, VisitElementInit); // Cannot make parameter for NewExpression if Initializers cannot be evaluated @@ -552,6 +568,8 @@ protected override Expression VisitListInit(ListInitExpression listInitExpressio protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { + Check.NotNull(methodCallExpression, nameof(methodCallExpression)); + Visit(methodCallExpression.Object); var parameterInfos = methodCallExpression.Method.GetParameters(); for (var i = 0; i < methodCallExpression.Arguments.Count; i++) @@ -591,13 +609,18 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp protected override Expression VisitMember(MemberExpression memberExpression) { + Check.NotNull(memberExpression, nameof(memberExpression)); + _containsClosure = memberExpression.Expression != null || !(memberExpression.Member is FieldInfo fieldInfo && fieldInfo.IsInitOnly); + return base.VisitMember(memberExpression); } protected override Expression VisitParameter(ParameterExpression parameterExpression) { + Check.NotNull(parameterExpression, nameof(parameterExpression)); + _evaluatable = _allowedParameters.Contains(parameterExpression); return base.VisitParameter(parameterExpression); @@ -605,6 +628,8 @@ protected override Expression VisitParameter(ParameterExpression parameterExpres protected override Expression VisitConstant(ConstantExpression constantExpression) { + Check.NotNull(constantExpression, nameof(constantExpression)); + _evaluatable = !(constantExpression.Value is IDetachableContext) && !(constantExpression.Value is IQueryable); diff --git a/src/EFCore/Query/Internal/QueryCompilationContextFactory.cs b/src/EFCore/Query/Internal/QueryCompilationContextFactory.cs index 7bb4fd837c3..71c805ccb62 100644 --- a/src/EFCore/Query/Internal/QueryCompilationContextFactory.cs +++ b/src/EFCore/Query/Internal/QueryCompilationContextFactory.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; namespace Microsoft.EntityFrameworkCore.Query.Internal @@ -20,7 +21,7 @@ public class QueryCompilationContextFactory : IQueryCompilationContextFactory { private readonly QueryCompilationContextDependencies _dependencies; - public QueryCompilationContextFactory(QueryCompilationContextDependencies dependencies) + public QueryCompilationContextFactory([NotNull] QueryCompilationContextDependencies dependencies) { _dependencies = dependencies; } diff --git a/src/EFCore/Query/Internal/QueryCompiler.cs b/src/EFCore/Query/Internal/QueryCompiler.cs index ba65196cfbe..258272cb165 100644 --- a/src/EFCore/Query/Internal/QueryCompiler.cs +++ b/src/EFCore/Query/Internal/QueryCompiler.cs @@ -98,10 +98,16 @@ var compiledQuery return compiledQuery(queryContext); } + /// + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// public virtual Func CompileQueryCore( - IDatabase database, - Expression query, - IModel model, + [NotNull] IDatabase database, + [NotNull] Expression query, + [NotNull] IModel model, bool async) => database.CompileQuery(query, async); @@ -120,6 +126,12 @@ public virtual Func CreateCompiledQuery(Expressi return CompileQueryCore(_database, query, _model, false); } + /// + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// public virtual TResult ExecuteAsync(Expression query, CancellationToken cancellationToken = default) { Check.NotNull(query, nameof(query)); diff --git a/src/EFCore/Query/Internal/QueryMetadataExtractingExpressionVisitor.cs b/src/EFCore/Query/Internal/QueryMetadataExtractingExpressionVisitor.cs index f2927a32975..d9d24ce01b5 100644 --- a/src/EFCore/Query/Internal/QueryMetadataExtractingExpressionVisitor.cs +++ b/src/EFCore/Query/Internal/QueryMetadataExtractingExpressionVisitor.cs @@ -2,6 +2,8 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Linq.Expressions; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.Internal { @@ -9,13 +11,15 @@ public class QueryMetadataExtractingExpressionVisitor : ExpressionVisitor { private readonly QueryCompilationContext _queryCompilationContext; - public QueryMetadataExtractingExpressionVisitor(QueryCompilationContext queryCompilationContext) + public QueryMetadataExtractingExpressionVisitor([NotNull] QueryCompilationContext queryCompilationContext) { _queryCompilationContext = queryCompilationContext; } protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { + Check.NotNull(methodCallExpression, nameof(methodCallExpression)); + var method = methodCallExpression.Method; if (method.DeclaringType == typeof(EntityFrameworkQueryableExtensions) && method.IsGenericMethod) diff --git a/src/EFCore/Query/Internal/QueryTranslationPostprocessorFactory.cs b/src/EFCore/Query/Internal/QueryTranslationPostprocessorFactory.cs index 2f8d23fadf9..9d137a897b9 100644 --- a/src/EFCore/Query/Internal/QueryTranslationPostprocessorFactory.cs +++ b/src/EFCore/Query/Internal/QueryTranslationPostprocessorFactory.cs @@ -1,6 +1,8 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; namespace Microsoft.EntityFrameworkCore.Query.Internal @@ -22,13 +24,15 @@ public class QueryTranslationPostprocessorFactory : IQueryTranslationPostprocess { private readonly QueryTranslationPostprocessorDependencies _dependencies; - public QueryTranslationPostprocessorFactory(QueryTranslationPostprocessorDependencies dependencies) + public QueryTranslationPostprocessorFactory([NotNull] QueryTranslationPostprocessorDependencies dependencies) { _dependencies = dependencies; } public virtual QueryTranslationPostprocessor Create(QueryCompilationContext queryCompilationContext) { + Check.NotNull(queryCompilationContext, nameof(queryCompilationContext)); + return new QueryTranslationPostprocessor(_dependencies); } } diff --git a/src/EFCore/Query/Internal/QueryTranslationPreprocessorFactory.cs b/src/EFCore/Query/Internal/QueryTranslationPreprocessorFactory.cs index d496b5f557b..0ec15437e55 100644 --- a/src/EFCore/Query/Internal/QueryTranslationPreprocessorFactory.cs +++ b/src/EFCore/Query/Internal/QueryTranslationPreprocessorFactory.cs @@ -1,6 +1,8 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; namespace Microsoft.EntityFrameworkCore.Query.Internal @@ -19,12 +21,16 @@ public class QueryTranslationPreprocessorFactory : IQueryTranslationPreprocessor { private readonly QueryTranslationPreprocessorDependencies _dependencies; - public QueryTranslationPreprocessorFactory(QueryTranslationPreprocessorDependencies dependencies) + public QueryTranslationPreprocessorFactory([NotNull] QueryTranslationPreprocessorDependencies dependencies) { _dependencies = dependencies; } public virtual QueryTranslationPreprocessor Create(QueryCompilationContext queryCompilationContext) - => new QueryTranslationPreprocessor(_dependencies, queryCompilationContext); + { + Check.NotNull(queryCompilationContext, nameof(queryCompilationContext)); + + return new QueryTranslationPreprocessor(_dependencies, queryCompilationContext); + } } } diff --git a/src/EFCore/Query/Internal/SubqueryMemberPushdownExpressionVisitor.cs b/src/EFCore/Query/Internal/SubqueryMemberPushdownExpressionVisitor.cs index 747b8990a54..4fa21505d5b 100644 --- a/src/EFCore/Query/Internal/SubqueryMemberPushdownExpressionVisitor.cs +++ b/src/EFCore/Query/Internal/SubqueryMemberPushdownExpressionVisitor.cs @@ -7,6 +7,7 @@ using System.Reflection; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query.Internal { @@ -42,6 +43,8 @@ public class SubqueryMemberPushdownExpressionVisitor : ExpressionVisitor protected override Expression VisitMember(MemberExpression memberExpression) { + Check.NotNull(memberExpression, nameof(memberExpression)); + var innerExpression = Visit(memberExpression.Expression); if (innerExpression is MethodCallExpression methodCallExpression && methodCallExpression.Method.IsGenericMethod @@ -65,6 +68,8 @@ protected override Expression VisitMember(MemberExpression memberExpression) protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { + Check.NotNull(methodCallExpression, nameof(methodCallExpression)); + if (methodCallExpression.TryGetEFPropertyArguments(out var source, out _)) { source = Visit(source); diff --git a/src/EFCore/Query/MaterializeCollectionNavigationExpression.cs b/src/EFCore/Query/MaterializeCollectionNavigationExpression.cs index 601ce9fe25a..7fc00d0d7a6 100644 --- a/src/EFCore/Query/MaterializeCollectionNavigationExpression.cs +++ b/src/EFCore/Query/MaterializeCollectionNavigationExpression.cs @@ -3,15 +3,20 @@ using System; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query { public class MaterializeCollectionNavigationExpression : Expression, IPrintableExpression { - public MaterializeCollectionNavigationExpression(Expression subquery, INavigation navigation) + public MaterializeCollectionNavigationExpression([NotNull] Expression subquery, [NotNull] INavigation navigation) { + Check.NotNull(subquery, nameof(subquery)); + Check.NotNull(navigation, nameof(navigation)); + Subquery = subquery; Navigation = navigation; } @@ -23,15 +28,25 @@ public MaterializeCollectionNavigationExpression(Expression subquery, INavigatio public override Type Type => Navigation.ClrType; protected override Expression VisitChildren(ExpressionVisitor visitor) - => Update(visitor.Visit(Subquery)); + { + Check.NotNull(visitor, nameof(visitor)); + + return Update(visitor.Visit(Subquery)); + } - public virtual MaterializeCollectionNavigationExpression Update(Expression subquery) - => subquery != Subquery + public virtual MaterializeCollectionNavigationExpression Update([NotNull] Expression subquery) + { + Check.NotNull(subquery, nameof(subquery)); + + return subquery != Subquery ? new MaterializeCollectionNavigationExpression(subquery, Navigation) : this; + } public virtual void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.AppendLine("MaterializeCollectionNavigation("); using (expressionPrinter.Indent()) { diff --git a/src/EFCore/Query/ProjectionBindingExpression.cs b/src/EFCore/Query/ProjectionBindingExpression.cs index 6892764e47a..5cd4fd741c2 100644 --- a/src/EFCore/Query/ProjectionBindingExpression.cs +++ b/src/EFCore/Query/ProjectionBindingExpression.cs @@ -4,29 +4,49 @@ using System; using System.Collections.Generic; using System.Linq.Expressions; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query { public class ProjectionBindingExpression : Expression, IPrintableExpression { - public ProjectionBindingExpression(Expression queryExpression, ProjectionMember projectionMember, Type type) + public ProjectionBindingExpression( + [NotNull] Expression queryExpression, + [NotNull] ProjectionMember projectionMember, + [NotNull] Type type) { + Check.NotNull(queryExpression, nameof(queryExpression)); + Check.NotNull(projectionMember, nameof(projectionMember)); + Check.NotNull(type, nameof(type)); + QueryExpression = queryExpression; ProjectionMember = projectionMember; Type = type; } - public ProjectionBindingExpression(Expression queryExpression, int index, Type type) + public ProjectionBindingExpression( + [NotNull] Expression queryExpression, + int index, + [NotNull] Type type) { + Check.NotNull(queryExpression, nameof(queryExpression)); + Check.NotNull(type, nameof(type)); + QueryExpression = queryExpression; Index = index; Type = type; } - public ProjectionBindingExpression(Expression queryExpression, IDictionary indexMap) + public ProjectionBindingExpression( + [NotNull] Expression queryExpression, + [NotNull] IDictionary indexMap) { + Check.NotNull(queryExpression, nameof(queryExpression)); + Check.NotNull(indexMap, nameof(indexMap)); + QueryExpression = queryExpression; IndexMap = indexMap; Type = typeof(ValueBuffer); @@ -39,10 +59,17 @@ public ProjectionBindingExpression(Expression queryExpression, IDictionary ExpressionType.Extension; - protected override Expression VisitChildren(ExpressionVisitor visitor) => this; + protected override Expression VisitChildren(ExpressionVisitor visitor) + { + Check.NotNull(visitor, nameof(visitor)); + + return this; + } public virtual void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.Append(nameof(ProjectionBindingExpression) + ": "); if (ProjectionMember != null) { diff --git a/src/EFCore/Query/ProjectionMember.cs b/src/EFCore/Query/ProjectionMember.cs index e26aeb8e421..b3bfe64ae3f 100644 --- a/src/EFCore/Query/ProjectionMember.cs +++ b/src/EFCore/Query/ProjectionMember.cs @@ -6,6 +6,8 @@ using System.Diagnostics; using System.Linq; using System.Reflection; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query { @@ -19,21 +21,27 @@ public ProjectionMember() _memberChain = new List(); } - private ProjectionMember(IList memberChain) + private ProjectionMember([NotNull] IList memberChain) { + Check.NotNull(memberChain, nameof(memberChain)); + _memberChain = memberChain; } - public virtual ProjectionMember Append(MemberInfo member) + public virtual ProjectionMember Append([NotNull] MemberInfo member) { + Check.NotNull(member, nameof(member)); + var existingChain = _memberChain.ToList(); existingChain.Add(member); return new ProjectionMember(existingChain); } - public virtual ProjectionMember Prepend(MemberInfo member) + public virtual ProjectionMember Prepend([NotNull] MemberInfo member) { + Check.NotNull(member, nameof(member)); + var existingChain = _memberChain.ToList(); existingChain.Insert(0, member); diff --git a/src/EFCore/Query/QueryCompilationContext.cs b/src/EFCore/Query/QueryCompilationContext.cs index 4746ff9995f..82618bebee6 100644 --- a/src/EFCore/Query/QueryCompilationContext.cs +++ b/src/EFCore/Query/QueryCompilationContext.cs @@ -6,9 +6,11 @@ using System.Linq; using System.Linq.Expressions; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query { @@ -29,9 +31,11 @@ public class QueryCompilationContext private Dictionary _runtimeParameters; public QueryCompilationContext( - QueryCompilationContextDependencies dependencies, + [NotNull] QueryCompilationContextDependencies dependencies, bool async) { + Check.NotNull(dependencies, nameof(dependencies)); + IsAsync = async; IsTracking = dependencies.IsTracking; IsBuffering = dependencies.IsRetryingExecutionStrategy; @@ -56,13 +60,17 @@ public QueryCompilationContext( public virtual IDiagnosticsLogger Logger { get; } public virtual Type ContextType { get; } - public virtual void AddTag(string tag) + public virtual void AddTag([NotNull] string tag) { + Check.NotEmpty(tag, nameof(tag)); + Tags.Add(tag); } - public virtual Func CreateQueryExecutor(Expression query) + public virtual Func CreateQueryExecutor([NotNull] Expression query) { + Check.NotNull(query, nameof(query)); + query = _queryTranslationPreprocessorFactory.Create(this).Process(query); // Convert EntityQueryable to ShapedQueryExpression query = _queryableMethodTranslatingExpressionVisitorFactory.Create(Model).Visit(query); @@ -95,8 +103,11 @@ public virtual Func CreateQueryExecutor(Expressi /// A lambda must be provided, which will extract the parameter's value from the QueryContext every time /// the query is executed. /// - public virtual ParameterExpression RegisterRuntimeParameter(string name, LambdaExpression valueExtractor) + public virtual ParameterExpression RegisterRuntimeParameter([NotNull] string name, [NotNull] LambdaExpression valueExtractor) { + Check.NotEmpty(name, nameof(name)); + Check.NotNull(valueExtractor, nameof(valueExtractor)); + if (valueExtractor.Parameters.Count != 1 || valueExtractor.Parameters[0] != QueryContextParameter) { diff --git a/src/EFCore/Query/QueryContext.cs b/src/EFCore/Query/QueryContext.cs index 5174391bf8f..420b92cdee6 100644 --- a/src/EFCore/Query/QueryContext.cs +++ b/src/EFCore/Query/QueryContext.cs @@ -65,7 +65,12 @@ public virtual IStateManager StateManager /// The entity instance. /// The navigation property. public virtual void SetNavigationIsLoaded([NotNull] object entity, [NotNull] INavigation navigation) - => Dependencies.StateManager.TryGetEntry(entity).SetIsLoaded(navigation); + { + Check.NotNull(entity, nameof(entity)); + Check.NotNull(navigation, nameof(navigation)); + + Dependencies.StateManager.TryGetEntry(entity).SetIsLoaded(navigation); + } /// /// The query provider. @@ -146,8 +151,8 @@ public virtual void AddParameter(string name, object value) /// [EntityFrameworkInternal] public virtual InternalEntityEntry StartTracking( - IEntityType entityType, - object entity, + [NotNull] IEntityType entityType, + [NotNull] object entity, ValueBuffer valueBuffer) => StateManager.StartTrackingFromQuery(entityType, entity, valueBuffer); } diff --git a/src/EFCore/Query/QueryTranslationPostprocessor.cs b/src/EFCore/Query/QueryTranslationPostprocessor.cs index bbf3b3d5bf3..d178108aa8f 100644 --- a/src/EFCore/Query/QueryTranslationPostprocessor.cs +++ b/src/EFCore/Query/QueryTranslationPostprocessor.cs @@ -2,20 +2,26 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Linq.Expressions; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query { public class QueryTranslationPostprocessor { - public QueryTranslationPostprocessor(QueryTranslationPostprocessorDependencies dependencies) + public QueryTranslationPostprocessor([NotNull] QueryTranslationPostprocessorDependencies dependencies) { + Check.NotNull(dependencies, nameof(dependencies)); + Dependencies = dependencies; } protected virtual QueryTranslationPostprocessorDependencies Dependencies { get; } - public virtual Expression Process(Expression query) + public virtual Expression Process([NotNull] Expression query) { + Check.NotNull(query, nameof(query)); + return query; } } diff --git a/src/EFCore/Query/QueryTranslationPreprocessor.cs b/src/EFCore/Query/QueryTranslationPreprocessor.cs index 0112f4a65fc..be5611d7106 100644 --- a/src/EFCore/Query/QueryTranslationPreprocessor.cs +++ b/src/EFCore/Query/QueryTranslationPreprocessor.cs @@ -1,10 +1,10 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System.Linq; using System.Linq.Expressions; -using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query.Internal; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query { @@ -13,17 +13,22 @@ public class QueryTranslationPreprocessor private readonly QueryCompilationContext _queryCompilationContext; public QueryTranslationPreprocessor( - QueryTranslationPreprocessorDependencies dependencies, - QueryCompilationContext queryCompilationContext) + [NotNull] QueryTranslationPreprocessorDependencies dependencies, + [NotNull] QueryCompilationContext queryCompilationContext) { + Check.NotNull(dependencies, nameof(dependencies)); + Check.NotNull(queryCompilationContext, nameof(queryCompilationContext)); + Dependencies = dependencies; _queryCompilationContext = queryCompilationContext; } protected virtual QueryTranslationPreprocessorDependencies Dependencies { get; } - public virtual Expression Process(Expression query) + public virtual Expression Process([NotNull] Expression query) { + Check.NotNull(query, nameof(query)); + query = new EnumerableToQueryableMethodConvertingExpressionVisitor().Visit(query); query = new QueryMetadataExtractingExpressionVisitor(_queryCompilationContext).Visit(query); query = new InvocationExpressionRemovingExpressionVisitor().Visit(query); @@ -35,27 +40,8 @@ public virtual Expression Process(Expression query) query = new NavigationExpandingExpressionVisitor(_queryCompilationContext, Dependencies.EvaluatableExpressionFilter).Expand( query); query = new FunctionPreprocessingExpressionVisitor().Visit(query); - new EnumerableVerifyingExpressionVisitor().Visit(query); return query; } - - // TODO: For debugging - private sealed class EnumerableVerifyingExpressionVisitor : ExpressionVisitor - { - protected override Expression VisitMethodCall(MethodCallExpression node) - { - if (node.Method.DeclaringType == typeof(Enumerable) - && node.Arguments[0].Type.IsGenericType - && node.Arguments[0].Type.GetGenericTypeDefinition() == typeof(IQueryable<>) - && !string.Equals(node.Method.Name, nameof(Enumerable.ToList)) - && !string.Equals(node.Method.Name, nameof(Enumerable.ToArray))) - { - throw new InvalidFilterCriteriaException(); - } - - return base.VisitMethodCall(node); - } - } } } diff --git a/src/EFCore/Query/QueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore/Query/QueryableMethodTranslatingExpressionVisitor.cs index 708c2e4ed6b..f53fbf7c457 100644 --- a/src/EFCore/Query/QueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore/Query/QueryableMethodTranslatingExpressionVisitor.cs @@ -6,9 +6,11 @@ using System.Linq; using System.Linq.Expressions; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query { @@ -18,9 +20,11 @@ public abstract class QueryableMethodTranslatingExpressionVisitor : ExpressionVi private readonly EntityShaperNullableMarkingExpressionVisitor _entityShaperNullableMarkingExpressionVisitor; protected QueryableMethodTranslatingExpressionVisitor( - QueryableMethodTranslatingExpressionVisitorDependencies dependencies, + [NotNull] QueryableMethodTranslatingExpressionVisitorDependencies dependencies, bool subquery) { + Check.NotNull(dependencies, nameof(dependencies)); + Dependencies = dependencies; _subquery = subquery; _entityShaperNullableMarkingExpressionVisitor = new EntityShaperNullableMarkingExpressionVisitor(); @@ -29,17 +33,27 @@ protected QueryableMethodTranslatingExpressionVisitor( protected virtual QueryableMethodTranslatingExpressionVisitorDependencies Dependencies { get; } protected override Expression VisitConstant(ConstantExpression constantExpression) - => constantExpression.IsEntityQueryable() + { + Check.NotNull(constantExpression, nameof(constantExpression)); + + return constantExpression.IsEntityQueryable() ? CreateShapedQueryExpression(((IQueryable)constantExpression.Value).ElementType) : base.VisitConstant(constantExpression); + } protected override Expression VisitExtension(Expression expression) - => expression is ShapedQueryExpression + { + Check.NotNull(expression, nameof(expression)); + + return expression is ShapedQueryExpression ? expression : base.VisitExtension(expression); + } protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { + Check.NotNull(methodCallExpression, nameof(methodCallExpression)); + ShapedQueryExpression CheckTranslated(ShapedQueryExpression translated) { if (translated == null) @@ -441,21 +455,31 @@ private sealed class EntityShaperNullableMarkingExpressionVisitor : ExpressionVi { protected override Expression VisitExtension(Expression extensionExpression) { + Check.NotNull(extensionExpression, nameof(extensionExpression)); + return extensionExpression is EntityShaperExpression entityShaper ? entityShaper.MarkAsNullable() : base.VisitExtension(extensionExpression); } } - protected virtual Expression MarkShaperNullable(Expression shaperExpression) - => _entityShaperNullableMarkingExpressionVisitor.Visit(shaperExpression); + protected virtual Expression MarkShaperNullable([NotNull] Expression shaperExpression) + { + Check.NotNull(shaperExpression, nameof(shaperExpression)); + + return _entityShaperNullableMarkingExpressionVisitor.Visit(shaperExpression); + } protected virtual ShapedQueryExpression TranslateResultSelectorForJoin( - ShapedQueryExpression outer, - LambdaExpression resultSelector, - Expression innerShaper, - Type transparentIdentifierType) + [NotNull] ShapedQueryExpression outer, + [NotNull] LambdaExpression resultSelector, + [NotNull] Expression innerShaper, + [CanBeNull] Type transparentIdentifierType) { + Check.NotNull(outer, nameof(outer)); + Check.NotNull(resultSelector, nameof(resultSelector)); + Check.NotNull(innerShaper, nameof(innerShaper)); + outer.ShaperExpression = CombineShapers( outer.QueryExpression, outer.ShaperExpression, @@ -506,6 +530,8 @@ public MemberAccessShiftingExpressionVisitor(Expression queryExpression, MemberI protected override Expression VisitExtension(Expression node) { + Check.NotNull(node, nameof(node)); + if (node is ProjectionBindingExpression projectionBindingExpression) { return new ProjectionBindingExpression( @@ -536,79 +562,127 @@ private static Expression AccessInnerTransparentField( return Expression.Field(targetExpression, fieldInfo); } - public virtual ShapedQueryExpression TranslateSubquery(Expression expression) - => (ShapedQueryExpression)CreateSubqueryVisitor().Visit(expression); + public virtual ShapedQueryExpression TranslateSubquery([NotNull] Expression expression) + { + Check.NotNull(expression, nameof(expression)); + + return (ShapedQueryExpression)CreateSubqueryVisitor().Visit(expression); + } protected abstract QueryableMethodTranslatingExpressionVisitor CreateSubqueryVisitor(); - protected abstract ShapedQueryExpression CreateShapedQueryExpression(Type elementType); - protected abstract ShapedQueryExpression TranslateAll(ShapedQueryExpression source, LambdaExpression predicate); - protected abstract ShapedQueryExpression TranslateAny(ShapedQueryExpression source, LambdaExpression predicate); - protected abstract ShapedQueryExpression TranslateAverage(ShapedQueryExpression source, LambdaExpression selector, Type resultType); - protected abstract ShapedQueryExpression TranslateCast(ShapedQueryExpression source, Type resultType); - protected abstract ShapedQueryExpression TranslateConcat(ShapedQueryExpression source1, ShapedQueryExpression source2); - protected abstract ShapedQueryExpression TranslateContains(ShapedQueryExpression source, Expression item); - protected abstract ShapedQueryExpression TranslateCount(ShapedQueryExpression source, LambdaExpression predicate); - protected abstract ShapedQueryExpression TranslateDefaultIfEmpty(ShapedQueryExpression source, Expression defaultValue); - protected abstract ShapedQueryExpression TranslateDistinct(ShapedQueryExpression source); + protected abstract ShapedQueryExpression CreateShapedQueryExpression([NotNull] Type elementType); + protected abstract ShapedQueryExpression TranslateAll([NotNull] ShapedQueryExpression source, [NotNull] LambdaExpression predicate); + protected abstract ShapedQueryExpression TranslateAny([NotNull] ShapedQueryExpression source, [NotNull] LambdaExpression predicate); + + protected abstract ShapedQueryExpression TranslateAverage( + [NotNull] ShapedQueryExpression source, [CanBeNull] LambdaExpression selector, [NotNull] Type resultType); + + protected abstract ShapedQueryExpression TranslateCast([NotNull] ShapedQueryExpression source, [NotNull] Type resultType); + + protected abstract ShapedQueryExpression TranslateConcat( + [NotNull] ShapedQueryExpression source1, [NotNull] ShapedQueryExpression source2); + protected abstract ShapedQueryExpression TranslateContains([NotNull] ShapedQueryExpression source, [NotNull] Expression item); + + protected abstract ShapedQueryExpression TranslateCount( + [NotNull] ShapedQueryExpression source, [CanBeNull] LambdaExpression predicate); + + protected abstract ShapedQueryExpression TranslateDefaultIfEmpty( + [NotNull] ShapedQueryExpression source, [CanBeNull] Expression defaultValue); + + protected abstract ShapedQueryExpression TranslateDistinct([NotNull] ShapedQueryExpression source); protected abstract ShapedQueryExpression TranslateElementAtOrDefault( - ShapedQueryExpression source, Expression index, bool returnDefault); + [NotNull] ShapedQueryExpression source, [NotNull] Expression index, bool returnDefault); - protected abstract ShapedQueryExpression TranslateExcept(ShapedQueryExpression source1, ShapedQueryExpression source2); + protected abstract ShapedQueryExpression TranslateExcept( + [NotNull] ShapedQueryExpression source1, [NotNull] ShapedQueryExpression source2); protected abstract ShapedQueryExpression TranslateFirstOrDefault( - ShapedQueryExpression source, LambdaExpression predicate, Type returnType, bool returnDefault); + [NotNull] ShapedQueryExpression source, [CanBeNull] LambdaExpression predicate, [NotNull] Type returnType, bool returnDefault); protected abstract ShapedQueryExpression TranslateGroupBy( - ShapedQueryExpression source, LambdaExpression keySelector, LambdaExpression elementSelector, LambdaExpression resultSelector); + [NotNull] ShapedQueryExpression source, + [NotNull] LambdaExpression keySelector, + [CanBeNull] LambdaExpression elementSelector, + [CanBeNull] LambdaExpression resultSelector); protected abstract ShapedQueryExpression TranslateGroupJoin( - ShapedQueryExpression outer, ShapedQueryExpression inner, LambdaExpression outerKeySelector, LambdaExpression innerKeySelector, - LambdaExpression resultSelector); + [NotNull] ShapedQueryExpression outer, + [NotNull] ShapedQueryExpression inner, + [NotNull] LambdaExpression outerKeySelector, + [NotNull] LambdaExpression innerKeySelector, + [NotNull] LambdaExpression resultSelector); - protected abstract ShapedQueryExpression TranslateIntersect(ShapedQueryExpression source1, ShapedQueryExpression source2); + protected abstract ShapedQueryExpression TranslateIntersect( + [NotNull] ShapedQueryExpression source1, [NotNull] ShapedQueryExpression source2); protected abstract ShapedQueryExpression TranslateJoin( - ShapedQueryExpression outer, ShapedQueryExpression inner, LambdaExpression outerKeySelector, LambdaExpression innerKeySelector, - LambdaExpression resultSelector); + [NotNull] ShapedQueryExpression outer, + [NotNull] ShapedQueryExpression inner, + [CanBeNull] LambdaExpression outerKeySelector, + [CanBeNull] LambdaExpression innerKeySelector, + [NotNull] LambdaExpression resultSelector); protected abstract ShapedQueryExpression TranslateLeftJoin( - ShapedQueryExpression outer, ShapedQueryExpression inner, LambdaExpression outerKeySelector, LambdaExpression innerKeySelector, - LambdaExpression resultSelector); + [NotNull] ShapedQueryExpression outer, + [NotNull] ShapedQueryExpression inner, + [CanBeNull] LambdaExpression outerKeySelector, + [CanBeNull] LambdaExpression innerKeySelector, + [NotNull] LambdaExpression resultSelector); protected abstract ShapedQueryExpression TranslateLastOrDefault( - ShapedQueryExpression source, LambdaExpression predicate, Type returnType, bool returnDefault); + [NotNull] ShapedQueryExpression source, [CanBeNull] LambdaExpression predicate, [NotNull] Type returnType, bool returnDefault); + + protected abstract ShapedQueryExpression TranslateLongCount( + [NotNull] ShapedQueryExpression source, [CanBeNull] LambdaExpression predicate); + + protected abstract ShapedQueryExpression TranslateMax( + [NotNull] ShapedQueryExpression source, [CanBeNull] LambdaExpression selector, [NotNull] Type resultType); - protected abstract ShapedQueryExpression TranslateLongCount(ShapedQueryExpression source, LambdaExpression predicate); - protected abstract ShapedQueryExpression TranslateMax(ShapedQueryExpression source, LambdaExpression selector, Type resultType); - protected abstract ShapedQueryExpression TranslateMin(ShapedQueryExpression source, LambdaExpression selector, Type resultType); - protected abstract ShapedQueryExpression TranslateOfType(ShapedQueryExpression source, Type resultType); + protected abstract ShapedQueryExpression TranslateMin( + [NotNull] ShapedQueryExpression source, [CanBeNull] LambdaExpression selector, [NotNull] Type resultType); + + protected abstract ShapedQueryExpression TranslateOfType([NotNull] ShapedQueryExpression source, [NotNull] Type resultType); protected abstract ShapedQueryExpression TranslateOrderBy( - ShapedQueryExpression source, LambdaExpression keySelector, bool ascending); + [NotNull] ShapedQueryExpression source, [NotNull] LambdaExpression keySelector, bool ascending); + + protected abstract ShapedQueryExpression TranslateReverse([NotNull] ShapedQueryExpression source); - protected abstract ShapedQueryExpression TranslateReverse(ShapedQueryExpression source); - protected abstract ShapedQueryExpression TranslateSelect(ShapedQueryExpression source, LambdaExpression selector); + protected abstract ShapedQueryExpression TranslateSelect( + [NotNull] ShapedQueryExpression source, [NotNull] LambdaExpression selector); protected abstract ShapedQueryExpression TranslateSelectMany( - ShapedQueryExpression source, LambdaExpression collectionSelector, LambdaExpression resultSelector); + [NotNull] ShapedQueryExpression source, [NotNull] LambdaExpression collectionSelector, [NotNull] LambdaExpression resultSelector); - protected abstract ShapedQueryExpression TranslateSelectMany(ShapedQueryExpression source, LambdaExpression selector); + protected abstract ShapedQueryExpression TranslateSelectMany( + [NotNull] ShapedQueryExpression source, [NotNull] LambdaExpression selector); protected abstract ShapedQueryExpression TranslateSingleOrDefault( - ShapedQueryExpression source, LambdaExpression predicate, Type returnType, bool returnDefault); + [NotNull] ShapedQueryExpression source, [CanBeNull] LambdaExpression predicate, [NotNull] Type returnType, bool returnDefault); + + protected abstract ShapedQueryExpression TranslateSkip( + [NotNull] ShapedQueryExpression source, [NotNull] Expression count); - protected abstract ShapedQueryExpression TranslateSkip(ShapedQueryExpression source, Expression count); - protected abstract ShapedQueryExpression TranslateSkipWhile(ShapedQueryExpression source, LambdaExpression predicate); - protected abstract ShapedQueryExpression TranslateSum(ShapedQueryExpression source, LambdaExpression selector, Type resultType); - protected abstract ShapedQueryExpression TranslateTake(ShapedQueryExpression source, Expression count); - protected abstract ShapedQueryExpression TranslateTakeWhile(ShapedQueryExpression source, LambdaExpression predicate); + protected abstract ShapedQueryExpression TranslateSkipWhile( + [NotNull] ShapedQueryExpression source, [NotNull] LambdaExpression predicate); + + protected abstract ShapedQueryExpression TranslateSum( + [NotNull] ShapedQueryExpression source, [CanBeNull] LambdaExpression selector, [NotNull] Type resultType); + + protected abstract ShapedQueryExpression TranslateTake([NotNull] ShapedQueryExpression source, [NotNull] Expression count); + + protected abstract ShapedQueryExpression TranslateTakeWhile( + [NotNull] ShapedQueryExpression source, [NotNull] LambdaExpression predicate); protected abstract ShapedQueryExpression TranslateThenBy( - ShapedQueryExpression source, LambdaExpression keySelector, bool ascending); + [NotNull] ShapedQueryExpression source, [NotNull] LambdaExpression keySelector, bool ascending); + + protected abstract ShapedQueryExpression TranslateUnion( + [NotNull] ShapedQueryExpression source1, [NotNull] ShapedQueryExpression source2); - protected abstract ShapedQueryExpression TranslateUnion(ShapedQueryExpression source1, ShapedQueryExpression source2); - protected abstract ShapedQueryExpression TranslateWhere(ShapedQueryExpression source, LambdaExpression predicate); + protected abstract ShapedQueryExpression TranslateWhere( + [NotNull] ShapedQueryExpression source, [NotNull] LambdaExpression predicate); } } diff --git a/src/EFCore/Query/QueryableMethods.cs b/src/EFCore/Query/QueryableMethods.cs index bf610199a30..54344159548 100644 --- a/src/EFCore/Query/QueryableMethods.cs +++ b/src/EFCore/Query/QueryableMethods.cs @@ -6,6 +6,8 @@ using System.Linq; using System.Linq.Expressions; using System.Reflection; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query { @@ -77,24 +79,63 @@ public static class QueryableMethods public static MethodInfo GroupByWithKeyElementResultSelector { get; } public static MethodInfo GroupByWithKeyResultSelector { get; } - public static bool IsSumWithoutSelector(MethodInfo methodInfo) - => SumWithoutSelectorMethods.Values.Contains(methodInfo); + public static bool IsSumWithoutSelector([NotNull] MethodInfo methodInfo) + { + Check.NotNull(methodInfo, nameof(methodInfo)); + + return SumWithoutSelectorMethods.Values.Contains(methodInfo); + } - public static bool IsSumWithSelector(MethodInfo methodInfo) - => methodInfo.IsGenericMethod + public static bool IsSumWithSelector([NotNull] MethodInfo methodInfo) + { + Check.NotNull(methodInfo, nameof(methodInfo)); + + return methodInfo.IsGenericMethod && SumWithSelectorMethods.Values.Contains(methodInfo.GetGenericMethodDefinition()); + } + + public static bool IsAverageWithoutSelector([NotNull] MethodInfo methodInfo) + { + Check.NotNull(methodInfo, nameof(methodInfo)); + + return AverageWithoutSelectorMethods.Values.Contains(methodInfo); + } - public static bool IsAverageWithoutSelector(MethodInfo methodInfo) - => AverageWithoutSelectorMethods.Values.Contains(methodInfo); + public static bool IsAverageWithSelector([NotNull] MethodInfo methodInfo) + { + Check.NotNull(methodInfo, nameof(methodInfo)); - public static bool IsAverageWithSelector(MethodInfo methodInfo) - => methodInfo.IsGenericMethod + return methodInfo.IsGenericMethod && AverageWithSelectorMethods.Values.Contains(methodInfo.GetGenericMethodDefinition()); + } + + public static MethodInfo GetSumWithoutSelector([NotNull] Type type) + { + Check.NotNull(type, nameof(type)); - public static MethodInfo GetSumWithoutSelector(Type type) => SumWithoutSelectorMethods[type]; - public static MethodInfo GetSumWithSelector(Type type) => SumWithSelectorMethods[type]; - public static MethodInfo GetAverageWithoutSelector(Type type) => AverageWithoutSelectorMethods[type]; - public static MethodInfo GetAverageWithSelector(Type type) => AverageWithSelectorMethods[type]; + return SumWithoutSelectorMethods[type]; + } + + public static MethodInfo GetSumWithSelector([NotNull] Type type) + { + Check.NotNull(type, nameof(type)); + + return SumWithSelectorMethods[type]; + } + + public static MethodInfo GetAverageWithoutSelector([NotNull] Type type) + { + Check.NotNull(type, nameof(type)); + + return AverageWithoutSelectorMethods[type]; + } + + public static MethodInfo GetAverageWithSelector([NotNull] Type type) + { + Check.NotNull(type, nameof(type)); + + return AverageWithSelectorMethods[type]; + } private static Dictionary SumWithoutSelectorMethods { get; } private static Dictionary SumWithSelectorMethods { get; } diff --git a/src/EFCore/Query/ReplacingExpressionVisitor.cs b/src/EFCore/Query/ReplacingExpressionVisitor.cs index f0f67b5acc2..870e7a8b61e 100644 --- a/src/EFCore/Query/ReplacingExpressionVisitor.cs +++ b/src/EFCore/Query/ReplacingExpressionVisitor.cs @@ -5,8 +5,10 @@ using System.Linq; using System.Linq.Expressions; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query { @@ -14,14 +16,20 @@ public class ReplacingExpressionVisitor : ExpressionVisitor { private readonly IDictionary _replacements; - public static Expression Replace(Expression original, Expression replacement, Expression tree) + public static Expression Replace([NotNull] Expression original, [NotNull] Expression replacement, [NotNull] Expression tree) { + Check.NotNull(original, nameof(original)); + Check.NotNull(replacement, nameof(replacement)); + Check.NotNull(tree, nameof(tree)); + return new ReplacingExpressionVisitor( new Dictionary { { original, replacement } }).Visit(tree); } - public ReplacingExpressionVisitor(IDictionary replacements) + public ReplacingExpressionVisitor([NotNull] IDictionary replacements) { + Check.NotNull(replacements, nameof(replacements)); + _replacements = replacements; } @@ -42,6 +50,8 @@ public override Expression Visit(Expression expression) protected override Expression VisitMember(MemberExpression memberExpression) { + Check.NotNull(memberExpression, nameof(memberExpression)); + var innerExpression = Visit(memberExpression.Expression); if (innerExpression is GroupByShaperExpression groupByShaperExpression @@ -71,6 +81,8 @@ protected override Expression VisitMember(MemberExpression memberExpression) protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { + Check.NotNull(methodCallExpression, nameof(methodCallExpression)); + if (methodCallExpression.TryGetEFPropertyArguments(out var entityExpression, out var propertyName)) { var newEntityExpression = Visit(entityExpression); diff --git a/src/EFCore/Query/ShapedQueryCompilingExpressionVisitor.cs b/src/EFCore/Query/ShapedQueryCompilingExpressionVisitor.cs index 93140db093c..df3d1bbe8d3 100644 --- a/src/EFCore/Query/ShapedQueryCompilingExpressionVisitor.cs +++ b/src/EFCore/Query/ShapedQueryCompilingExpressionVisitor.cs @@ -15,6 +15,7 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query { @@ -28,9 +29,12 @@ private static readonly PropertyInfo _cancellationTokenMemberInfo private readonly ConstantVerifyingExpressionVisitor _constantVerifyingExpressionVisitor; protected ShapedQueryCompilingExpressionVisitor( - ShapedQueryCompilingExpressionVisitorDependencies dependencies, - QueryCompilationContext queryCompilationContext) + [NotNull] ShapedQueryCompilingExpressionVisitorDependencies dependencies, + [NotNull] QueryCompilationContext queryCompilationContext) { + Check.NotNull(dependencies, nameof(dependencies)); + Check.NotNull(queryCompilationContext, nameof(queryCompilationContext)); + Dependencies = dependencies; IsTracking = queryCompilationContext.IsTracking; @@ -62,6 +66,8 @@ protected ShapedQueryCompilingExpressionVisitor( protected override Expression VisitExtension(Expression extensionExpression) { + Check.NotNull(extensionExpression, nameof(extensionExpression)); + if (extensionExpression is ShapedQueryExpression shapedQueryExpression) { var serverEnumerable = VisitShapedQueryExpression(shapedQueryExpression); @@ -146,10 +152,12 @@ private static async Task SingleOrDefaultAsync( return result; } - protected abstract Expression VisitShapedQueryExpression(ShapedQueryExpression shapedQueryExpression); + protected abstract Expression VisitShapedQueryExpression([NotNull] ShapedQueryExpression shapedQueryExpression); - protected virtual Expression InjectEntityMaterializers(Expression expression) + protected virtual Expression InjectEntityMaterializers([NotNull] Expression expression) { + Check.NotNull(expression, nameof(expression)); + _constantVerifyingExpressionVisitor.Visit(expression); return _entityMaterializerInjectingExpressionVisitor.Inject(expression); @@ -172,6 +180,8 @@ private bool ValidConstant(ConstantExpression constantExpression) protected override Expression VisitConstant(ConstantExpression constantExpression) { + Check.NotNull(constantExpression, nameof(constantExpression)); + if (!ValidConstant(constantExpression)) { throw new InvalidOperationException( @@ -183,6 +193,8 @@ protected override Expression VisitConstant(ConstantExpression constantExpressio protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { + Check.NotNull(methodCallExpression, nameof(methodCallExpression)); + if (RemoveConvert(methodCallExpression.Object) is ConstantExpression constantInstance && !ValidConstant(constantInstance)) { @@ -209,6 +221,8 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp protected override Expression VisitExtension(Expression extensionExpression) { + Check.NotNull(extensionExpression, nameof(extensionExpression)); + return extensionExpression is EntityShaperExpression || extensionExpression is ProjectionBindingExpression ? extensionExpression @@ -293,9 +307,13 @@ bool ContainsOwner(IEntityType owner) } protected override Expression VisitExtension(Expression extensionExpression) - => extensionExpression is EntityShaperExpression entityShaperExpression + { + Check.NotNull(extensionExpression, nameof(extensionExpression)); + + return extensionExpression is EntityShaperExpression entityShaperExpression ? ProcessEntityShaper(entityShaperExpression) : base.VisitExtension(extensionExpression); + } private Expression ProcessEntityShaper(EntityShaperExpression entityShaperExpression) { diff --git a/src/EFCore/Query/ShapedQueryExpression.cs b/src/EFCore/Query/ShapedQueryExpression.cs index 2d26d74f64e..bd2b86392b6 100644 --- a/src/EFCore/Query/ShapedQueryExpression.cs +++ b/src/EFCore/Query/ShapedQueryExpression.cs @@ -4,20 +4,38 @@ using System; using System.Linq; using System.Linq.Expressions; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query { public class ShapedQueryExpression : Expression, IPrintableExpression { - public ShapedQueryExpression(Expression queryExpression, Expression shaperExpression) + private Expression _queryExpression; + private Expression _shaperExpression; + + public ShapedQueryExpression([NotNull] Expression queryExpression, [NotNull] Expression shaperExpression) { + Check.NotNull(queryExpression, nameof(queryExpression)); + Check.NotNull(shaperExpression, nameof(shaperExpression)); + QueryExpression = queryExpression; ShaperExpression = shaperExpression; } - public virtual Expression QueryExpression { get; set; } + public virtual Expression QueryExpression + { + get => _queryExpression; + [param: NotNull] set => _queryExpression = Check.NotNull(value, nameof(value)); + } + public virtual ResultCardinality ResultCardinality { get; set; } - public virtual Expression ShaperExpression { get; set; } + + public virtual Expression ShaperExpression + { + get => _shaperExpression; + [param: NotNull] set => _shaperExpression = Check.NotNull(value, nameof(value)); + } public override Type Type => ResultCardinality == ResultCardinality.Enumerable ? typeof(IQueryable<>).MakeGenericType(ShaperExpression.Type) @@ -27,6 +45,8 @@ public ShapedQueryExpression(Expression queryExpression, Expression shaperExpres protected override Expression VisitChildren(ExpressionVisitor visitor) { + Check.NotNull(visitor, nameof(visitor)); + QueryExpression = visitor.Visit(QueryExpression); return this; @@ -34,6 +54,8 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) public virtual void Print(ExpressionPrinter expressionPrinter) { + Check.NotNull(expressionPrinter, nameof(expressionPrinter)); + expressionPrinter.AppendLine(nameof(ShapedQueryExpression) + ": "); using (expressionPrinter.Indent()) { diff --git a/src/EFCore/Query/TransparentIdentifierFactory.cs b/src/EFCore/Query/TransparentIdentifierFactory.cs index 74dc6465a83..1de6d78bd80 100644 --- a/src/EFCore/Query/TransparentIdentifierFactory.cs +++ b/src/EFCore/Query/TransparentIdentifierFactory.cs @@ -3,13 +3,19 @@ using System; using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query { public static class TransparentIdentifierFactory { - public static Type Create(Type outerType, Type innerType) - => typeof(TransparentIdentifier<,>).MakeGenericType(outerType, innerType); + public static Type Create([NotNull] Type outerType, [NotNull] Type innerType) + { + Check.NotNull(outerType, nameof(outerType)); + Check.NotNull(innerType, nameof(innerType)); + + return typeof(TransparentIdentifier<,>).MakeGenericType(outerType, innerType); + } private readonly struct TransparentIdentifier { diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs index 2494b5fa968..2947b06cf33 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs @@ -5547,7 +5547,7 @@ private interface IHasId17276 private interface IOwned { - public string OwnedValue { get; } + string OwnedValue { get; } } private class Specification17276 diff --git a/test/EFCore.Tests/ApiConsistencyTestBase.cs b/test/EFCore.Tests/ApiConsistencyTestBase.cs index 89d08ac1f40..5907fe60943 100644 --- a/test/EFCore.Tests/ApiConsistencyTestBase.cs +++ b/test/EFCore.Tests/ApiConsistencyTestBase.cs @@ -318,14 +318,13 @@ var parametersMissingAttribute = (from type in GetAllTypes(TargetAssembly.GetTypes()) where type.IsVisible && !typeof(Delegate).IsAssignableFrom(type) - && !type.Namespace.Contains("Internal", StringComparison.Ordinal) let interfaceMappings = type.GetInterfaces().Select(i => type.GetTypeInfo().GetRuntimeInterfaceMap(i)) let events = type.GetEvents() from method in type.GetMethods(AnyInstance | BindingFlags.Static | BindingFlags.DeclaredOnly) - .Concat(type.GetConstructors()) + .Concat(type.GetConstructors( + BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Static)) where (method.IsPublic || method.IsFamily || method.IsFamilyOrAssembly) && ShouldHaveNotNullAnnotation(method, type) - && !method.DeclaringType.Namespace.Contains("Query", StringComparison.Ordinal) where type.IsInterface || !interfaceMappings.Any(im => im.TargetMethods.Contains(method)) where !events.Any(e => e.AddMethod == method || e.RemoveMethod == method) from parameter in method.GetParameters()